diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..80dfc8da --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +**/vendor/** linguist-generated diff --git a/.github/workflows/docker-build-push.yaml b/.github/workflows/docker-build-push.yaml index a2277836..fa48b9ed 100644 --- a/.github/workflows/docker-build-push.yaml +++ b/.github/workflows/docker-build-push.yaml @@ -10,7 +10,7 @@ env: TASK_VERSION: '3.38.0' REGISTRY: ghcr.io REPO: runtime-radar - GO_VERSION: '1.24' + GO_VERSION: '1.25' jobs: build-and-push: diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 9829515c..d97c2228 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -16,7 +16,7 @@ on: - '.golangci.yml' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' TASK_VERSION: '3.38.0' jobs: diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml index 9bc567b0..38eb4a50 100644 --- a/.github/workflows/test-lib.yaml +++ b/.github/workflows/test-lib.yaml @@ -11,7 +11,7 @@ on: - main env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' TASK_VERSION: '3.38.0' jobs: diff --git a/Taskfile.yml b/Taskfile.yml index a6f5c558..369bda0a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -55,6 +55,7 @@ tasks: - event-processor - runtime-monitor - cs-manager + - public-api task: "{{.ITEM}}:proto" proto-clean: diff --git a/auth-center/Dockerfile b/auth-center/Dockerfile index 029a81d7..374d4c03 100644 --- a/auth-center/Dockerfile +++ b/auth-center/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.24.1 AS tools +FROM golang:1.25.0 AS tools RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0 -FROM golang:1.24.1 AS builder +FROM golang:1.25.0 AS builder ARG BUILD_RELEASE ARG BUILD_BRANCH diff --git a/auth-center/docker-compose.test.yml b/auth-center/docker-compose.test.yml index 3126a730..c59784f0 100644 --- a/auth-center/docker-compose.test.yml +++ b/auth-center/docker-compose.test.yml @@ -1,6 +1,6 @@ services: test: - image: golang:1.24 + image: golang:1.25 working_dir: /go/src/repo volumes: - .:/go/src/repo diff --git a/auth-center/go.mod b/auth-center/go.mod index d12fced4..192dd4b7 100644 --- a/auth-center/go.mod +++ b/auth-center/go.mod @@ -1,6 +1,6 @@ module github.com/runtime-radar/runtime-radar/auth-center -go 1.24.0 +go 1.25 require ( github.com/golang-jwt/jwt/v5 v5.0.0 diff --git a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go index fb4087d9..3604294e 100644 --- a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go +++ b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go @@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error { return nil } +func (jt JSONTime) String() string { + return time.Time(jt).String() +} + type Token struct { Username string `json:"username"` UserID string `json:"user_id"` @@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) { return nil, errors.New("unknown authorization format") } - token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) { + token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) { return key, nil }) if err != nil { diff --git a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go index 79432fec..24b0d6e3 100644 --- a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go +++ b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go @@ -27,7 +27,7 @@ func SetReady() { } // ReadyHandler handles ready probes. -func ReadyHandler(w http.ResponseWriter, r *http.Request) { +func ReadyHandler(w http.ResponseWriter, _ *http.Request) { if IsReady() { // Make it simple: do nothing and have 200 OK return @@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) { } // LiveHandler handles live probes. -func LiveHandler(w http.ResponseWriter, r *http.Request) { +func LiveHandler(http.ResponseWriter, *http.Request) { // Make it simple: do nothing and have 200 OK } diff --git a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go index cb9487d6..822eb440 100644 --- a/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go +++ b/auth-center/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go @@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, const CorrelationHeader = "correlation-id" -func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { +func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { var corrID string md, ok := metadata.FromIncomingContext(ctx) diff --git a/auth-center/vendor/modules.txt b/auth-center/vendor/modules.txt index b0fdcbaf..f770fe1e 100644 --- a/auth-center/vendor/modules.txt +++ b/auth-center/vendor/modules.txt @@ -775,7 +775,7 @@ github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log # github.com/runtime-radar/runtime-radar/lib v0.0.0-00010101000000-000000000000 => ../lib -## explicit; go 1.23 +## explicit; go 1.25 github.com/runtime-radar/runtime-radar/lib/config github.com/runtime-radar/runtime-radar/lib/errcommon github.com/runtime-radar/runtime-radar/lib/security diff --git a/cluster-manager/Dockerfile b/cluster-manager/Dockerfile index be5b27d4..6449da36 100644 --- a/cluster-manager/Dockerfile +++ b/cluster-manager/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.24.1 AS tools +FROM golang:1.25.0 AS tools RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0 -FROM golang:1.24.1 AS builder +FROM golang:1.25.0 AS builder ARG BUILD_RELEASE ARG BUILD_BRANCH diff --git a/cluster-manager/docker-compose.test.yml b/cluster-manager/docker-compose.test.yml index 4942cf10..2c01739b 100644 --- a/cluster-manager/docker-compose.test.yml +++ b/cluster-manager/docker-compose.test.yml @@ -9,7 +9,7 @@ services: - POSTGRES_DB=cs_test test: - image: golang:1.24 + image: golang:1.25 working_dir: /go/src/repo volumes: - .:/go/src/repo diff --git a/cluster-manager/go.mod b/cluster-manager/go.mod index a7c28db1..1b9ff6ad 100644 --- a/cluster-manager/go.mod +++ b/cluster-manager/go.mod @@ -1,6 +1,6 @@ module github.com/runtime-radar/runtime-radar/cluster-manager -go 1.24.0 +go 1.25 require ( github.com/golangci/golangci-lint v1.64.8 diff --git a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go index fb4087d9..3604294e 100644 --- a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go +++ b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go @@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error { return nil } +func (jt JSONTime) String() string { + return time.Time(jt).String() +} + type Token struct { Username string `json:"username"` UserID string `json:"user_id"` @@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) { return nil, errors.New("unknown authorization format") } - token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) { + token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) { return key, nil }) if err != nil { diff --git a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go index 79432fec..24b0d6e3 100644 --- a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go +++ b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go @@ -27,7 +27,7 @@ func SetReady() { } // ReadyHandler handles ready probes. -func ReadyHandler(w http.ResponseWriter, r *http.Request) { +func ReadyHandler(w http.ResponseWriter, _ *http.Request) { if IsReady() { // Make it simple: do nothing and have 200 OK return @@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) { } // LiveHandler handles live probes. -func LiveHandler(w http.ResponseWriter, r *http.Request) { +func LiveHandler(http.ResponseWriter, *http.Request) { // Make it simple: do nothing and have 200 OK } diff --git a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go index cb9487d6..822eb440 100644 --- a/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go +++ b/cluster-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go @@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, const CorrelationHeader = "correlation-id" -func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { +func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { var corrID string md, ok := metadata.FromIncomingContext(ctx) diff --git a/cluster-manager/vendor/modules.txt b/cluster-manager/vendor/modules.txt index 6f973aae..d663f0bc 100644 --- a/cluster-manager/vendor/modules.txt +++ b/cluster-manager/vendor/modules.txt @@ -738,7 +738,7 @@ github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log # github.com/runtime-radar/runtime-radar/lib v0.0.0-00010101000000-000000000000 => ../lib -## explicit; go 1.23 +## explicit; go 1.25 github.com/runtime-radar/runtime-radar/lib/config github.com/runtime-radar/runtime-radar/lib/errcommon github.com/runtime-radar/runtime-radar/lib/logger diff --git a/cs-manager/Dockerfile b/cs-manager/Dockerfile index 50f47535..9e525e3e 100644 --- a/cs-manager/Dockerfile +++ b/cs-manager/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.24.1 AS tools +FROM golang:1.25.0 AS tools RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0 -FROM golang:1.24.1 AS builder +FROM golang:1.25.0 AS builder ARG BUILD_RELEASE ARG BUILD_BRANCH diff --git a/cs-manager/docker-compose.test.yml b/cs-manager/docker-compose.test.yml index 3126a730..c59784f0 100644 --- a/cs-manager/docker-compose.test.yml +++ b/cs-manager/docker-compose.test.yml @@ -1,6 +1,6 @@ services: test: - image: golang:1.24 + image: golang:1.25 working_dir: /go/src/repo volumes: - .:/go/src/repo diff --git a/cs-manager/go.mod b/cs-manager/go.mod index d78e7a68..768c9874 100644 --- a/cs-manager/go.mod +++ b/cs-manager/go.mod @@ -1,8 +1,6 @@ module github.com/runtime-radar/runtime-radar/cs-manager -go 1.24.0 - -toolchain go1.24.4 +go 1.25 require ( github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.go index 5cc1f5f7..53644c62 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.go @@ -7,15 +7,16 @@ package api import ( + reflect "reflect" + sync "sync" + unsafe "unsafe" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" - unsafe "unsafe" ) const ( diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.gw.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.gw.go index 7ccc6a99..441ffcf5 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.gw.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster.pb.gw.go @@ -10,6 +10,7 @@ package api import ( "context" + "errors" "io" "net/http" @@ -25,568 +26,454 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_ClusterController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Cluster - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Cluster + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Cluster - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Cluster + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Create(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadClusterReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadClusterReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadClusterReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadClusterReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Read(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_Update_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Cluster - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Cluster + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Update_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Cluster - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Cluster + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Update(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteClusterReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteClusterReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteClusterReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteClusterReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Delete(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_ClusterController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0, "pageNum": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} -) +var filter_ClusterController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} func request_ClusterController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListClusterPageReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListClusterPageReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["page_num"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["page_num"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num") } - protoReq.PageNum, err = runtime.Uint32(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_ListPage_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.ListPage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListClusterPageReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListClusterPageReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["page_num"] + val, ok := pathParams["page_num"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num") } - protoReq.PageNum, err = runtime.Uint32(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_ListPage_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.ListPage(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_ClusterController_Register_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +var filter_ClusterController_Register_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_ClusterController_Register_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterClusterReq - var metadata runtime.ServerMetadata - + var ( + protoReq RegisterClusterReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_Register_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Register(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Register_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterClusterReq - var metadata runtime.ServerMetadata - + var ( + protoReq RegisterClusterReq + metadata runtime.ServerMetadata + ) if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_Register_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Register(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_ClusterController_Unregister_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +var filter_ClusterController_Unregister_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_ClusterController_Unregister_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnregisterClusterReq - var metadata runtime.ServerMetadata - + var ( + protoReq UnregisterClusterReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_Unregister_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Unregister(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_Unregister_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnregisterClusterReq - var metadata runtime.ServerMetadata - + var ( + protoReq UnregisterClusterReq + metadata runtime.ServerMetadata + ) if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_Unregister_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Unregister(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_GenerateUninstallCmd_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateUninstallCmdReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateUninstallCmdReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.GenerateUninstallCmd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_GenerateUninstallCmd_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateUninstallCmdReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateUninstallCmdReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.GenerateUninstallCmd(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_ClusterController_GenerateInstallCmd_0 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}} -) +var filter_ClusterController_GenerateInstallCmd_0 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} func request_ClusterController_GenerateInstallCmd_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateInstallCmdReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateInstallCmdReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_GenerateInstallCmd_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GenerateInstallCmd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_GenerateInstallCmd_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateInstallCmdReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateInstallCmdReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ClusterController_GenerateInstallCmd_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.GenerateInstallCmd(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_GenerateValuesYAML_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateValuesReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateValuesReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.GenerateValuesYAML(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_GenerateValuesYAML_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenerateValuesReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GenerateValuesReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.GenerateValuesYAML(ctx, &protoReq) return msg, metadata, err - } func request_ClusterController_ListRegistered_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - + var ( + protoReq emptypb.Empty + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } msg, err := client.ListRegistered(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ClusterController_ListRegistered_0(ctx context.Context, marshaler runtime.Marshaler, server ClusterControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - + var ( + protoReq emptypb.Empty + metadata runtime.ServerMetadata + ) msg, err := server.ListRegistered(ctx, &protoReq) return msg, metadata, err - } // RegisterClusterControllerHandlerServer registers the http handlers for service ClusterController to "mux". // UnaryRPC :call ClusterControllerServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterClusterControllerHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ClusterControllerServer) error { - - mux.Handle("POST", pattern_ClusterController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Create", runtime.WithHTTPPathPattern("/api/v1/cluster")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Create", runtime.WithHTTPPathPattern("/api/v1/cluster")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -598,20 +485,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Read", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Read", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -623,20 +505,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_ClusterController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_ClusterController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Update", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Update", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -648,20 +525,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_ClusterController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_ClusterController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Delete", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Delete", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -673,20 +545,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/ListPage", runtime.WithHTTPPathPattern("/api/v1/cluster/page/{page_num}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/ListPage", runtime.WithHTTPPathPattern("/api/v1/cluster/page/{page_num}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -698,20 +565,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ClusterController_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Register", runtime.WithHTTPPathPattern("/api/v1/cluster/register")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Register", runtime.WithHTTPPathPattern("/api/v1/cluster/register")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -723,20 +585,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Register_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ClusterController_Unregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Unregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Unregister", runtime.WithHTTPPathPattern("/api/v1/cluster/unregister")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/Unregister", runtime.WithHTTPPathPattern("/api/v1/cluster/unregister")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -748,20 +605,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Unregister_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateUninstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateUninstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateUninstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/uninstall")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateUninstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/uninstall")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -773,20 +625,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateUninstallCmd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateInstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateInstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateInstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/install")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateInstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/install")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -798,20 +645,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateInstallCmd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateValuesYAML_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateValuesYAML_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateValuesYAML", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/values")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/GenerateValuesYAML", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/values")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -823,20 +665,15 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateValuesYAML_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_ListRegistered_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_ListRegistered_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/ListRegistered", runtime.WithHTTPPathPattern("/api/v1/cluster/registered")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/cluster.ClusterController/ListRegistered", runtime.WithHTTPPathPattern("/api/v1/cluster/registered")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -848,9 +685,7 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_ListRegistered_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -859,25 +694,24 @@ func RegisterClusterControllerHandlerServer(ctx context.Context, mux *runtime.Se // RegisterClusterControllerHandlerFromEndpoint is same as RegisterClusterControllerHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterClusterControllerHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterClusterControllerHandler(ctx, mux, conn) } @@ -891,16 +725,13 @@ func RegisterClusterControllerHandler(ctx context.Context, mux *runtime.ServeMux // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ClusterControllerClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ClusterControllerClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "ClusterControllerClient" to call the correct interceptors. +// "ClusterControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ClusterControllerClient) error { - - mux.Handle("POST", pattern_ClusterController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Create", runtime.WithHTTPPathPattern("/api/v1/cluster")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Create", runtime.WithHTTPPathPattern("/api/v1/cluster")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -911,18 +742,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Read", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Read", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -933,18 +759,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_ClusterController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_ClusterController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Update", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Update", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -955,18 +776,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_ClusterController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_ClusterController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Delete", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Delete", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -977,18 +793,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/ListPage", runtime.WithHTTPPathPattern("/api/v1/cluster/page/{page_num}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/ListPage", runtime.WithHTTPPathPattern("/api/v1/cluster/page/{page_num}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -999,18 +810,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ClusterController_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Register", runtime.WithHTTPPathPattern("/api/v1/cluster/register")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Register", runtime.WithHTTPPathPattern("/api/v1/cluster/register")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1021,18 +827,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Register_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ClusterController_Unregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ClusterController_Unregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Unregister", runtime.WithHTTPPathPattern("/api/v1/cluster/unregister")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/Unregister", runtime.WithHTTPPathPattern("/api/v1/cluster/unregister")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1043,18 +844,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_Unregister_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateUninstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateUninstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateUninstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/uninstall")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateUninstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/uninstall")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1065,18 +861,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateUninstallCmd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateInstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateInstallCmd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateInstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/install")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateInstallCmd", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/install")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1087,18 +878,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateInstallCmd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_GenerateValuesYAML_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_GenerateValuesYAML_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateValuesYAML", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/values")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/GenerateValuesYAML", runtime.WithHTTPPathPattern("/api/v1/cluster/{id}/cmd/values")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1109,18 +895,13 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_GenerateValuesYAML_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ClusterController_ListRegistered_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ClusterController_ListRegistered_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/ListRegistered", runtime.WithHTTPPathPattern("/api/v1/cluster/registered")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/cluster.ClusterController/ListRegistered", runtime.WithHTTPPathPattern("/api/v1/cluster/registered")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1131,58 +912,35 @@ func RegisterClusterControllerHandlerClient(ctx context.Context, mux *runtime.Se runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ClusterController_ListRegistered_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_ClusterController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "cluster"}, "")) - - pattern_ClusterController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) - - pattern_ClusterController_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) - - pattern_ClusterController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) - - pattern_ClusterController_ListPage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "cluster", "page", "page_num"}, "")) - - pattern_ClusterController_Register_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "register"}, "")) - - pattern_ClusterController_Unregister_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "unregister"}, "")) - + pattern_ClusterController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "cluster"}, "")) + pattern_ClusterController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) + pattern_ClusterController_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) + pattern_ClusterController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "cluster", "id"}, "")) + pattern_ClusterController_ListPage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "cluster", "page", "page_num"}, "")) + pattern_ClusterController_Register_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "register"}, "")) + pattern_ClusterController_Unregister_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "unregister"}, "")) pattern_ClusterController_GenerateUninstallCmd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"api", "v1", "cluster", "id", "cmd", "uninstall"}, "")) - - pattern_ClusterController_GenerateInstallCmd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"api", "v1", "cluster", "id", "cmd", "install"}, "")) - - pattern_ClusterController_GenerateValuesYAML_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"api", "v1", "cluster", "id", "cmd", "values"}, "")) - - pattern_ClusterController_ListRegistered_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "registered"}, "")) + pattern_ClusterController_GenerateInstallCmd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"api", "v1", "cluster", "id", "cmd", "install"}, "")) + pattern_ClusterController_GenerateValuesYAML_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"api", "v1", "cluster", "id", "cmd", "values"}, "")) + pattern_ClusterController_ListRegistered_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "cluster", "registered"}, "")) ) var ( - forward_ClusterController_Create_0 = runtime.ForwardResponseMessage - - forward_ClusterController_Read_0 = runtime.ForwardResponseMessage - - forward_ClusterController_Update_0 = runtime.ForwardResponseMessage - - forward_ClusterController_Delete_0 = runtime.ForwardResponseMessage - - forward_ClusterController_ListPage_0 = runtime.ForwardResponseMessage - - forward_ClusterController_Register_0 = runtime.ForwardResponseMessage - - forward_ClusterController_Unregister_0 = runtime.ForwardResponseMessage - + forward_ClusterController_Create_0 = runtime.ForwardResponseMessage + forward_ClusterController_Read_0 = runtime.ForwardResponseMessage + forward_ClusterController_Update_0 = runtime.ForwardResponseMessage + forward_ClusterController_Delete_0 = runtime.ForwardResponseMessage + forward_ClusterController_ListPage_0 = runtime.ForwardResponseMessage + forward_ClusterController_Register_0 = runtime.ForwardResponseMessage + forward_ClusterController_Unregister_0 = runtime.ForwardResponseMessage forward_ClusterController_GenerateUninstallCmd_0 = runtime.ForwardResponseMessage - - forward_ClusterController_GenerateInstallCmd_0 = runtime.ForwardResponseMessage - - forward_ClusterController_GenerateValuesYAML_0 = runtime.ForwardResponseMessage - - forward_ClusterController_ListRegistered_0 = runtime.ForwardResponseMessage + forward_ClusterController_GenerateInstallCmd_0 = runtime.ForwardResponseMessage + forward_ClusterController_GenerateValuesYAML_0 = runtime.ForwardResponseMessage + forward_ClusterController_ListRegistered_0 = runtime.ForwardResponseMessage ) diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster_grpc.pb.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster_grpc.pb.go index 45c1c55b..66491fe8 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster_grpc.pb.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/cluster-manager/api/cluster_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.3.0 // - protoc v5.29.3 // source: cluster.proto @@ -16,8 +16,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 const ( ClusterController_Create_FullMethodName = "/cluster.ClusterController/Create" @@ -36,8 +36,6 @@ const ( // ClusterControllerClient is the client API for ClusterController service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -// -// The cluster service definition. type ClusterControllerClient interface { Create(ctx context.Context, in *Cluster, opts ...grpc.CallOption) (*CreateClusterResp, error) Read(ctx context.Context, in *ReadClusterReq, opts ...grpc.CallOption) (*ReadClusterResp, error) @@ -61,9 +59,8 @@ func NewClusterControllerClient(cc grpc.ClientConnInterface) ClusterControllerCl } func (c *clusterControllerClient) Create(ctx context.Context, in *Cluster, opts ...grpc.CallOption) (*CreateClusterResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateClusterResp) - err := c.cc.Invoke(ctx, ClusterController_Create_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Create_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -71,9 +68,8 @@ func (c *clusterControllerClient) Create(ctx context.Context, in *Cluster, opts } func (c *clusterControllerClient) Read(ctx context.Context, in *ReadClusterReq, opts ...grpc.CallOption) (*ReadClusterResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ReadClusterResp) - err := c.cc.Invoke(ctx, ClusterController_Read_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Read_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -81,9 +77,8 @@ func (c *clusterControllerClient) Read(ctx context.Context, in *ReadClusterReq, } func (c *clusterControllerClient) Update(ctx context.Context, in *Cluster, opts ...grpc.CallOption) (*emptypb.Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, ClusterController_Update_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Update_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -91,9 +86,8 @@ func (c *clusterControllerClient) Update(ctx context.Context, in *Cluster, opts } func (c *clusterControllerClient) Delete(ctx context.Context, in *DeleteClusterReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, ClusterController_Delete_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Delete_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -101,9 +95,8 @@ func (c *clusterControllerClient) Delete(ctx context.Context, in *DeleteClusterR } func (c *clusterControllerClient) ListPage(ctx context.Context, in *ListClusterPageReq, opts ...grpc.CallOption) (*ListClusterPageResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListClusterPageResp) - err := c.cc.Invoke(ctx, ClusterController_ListPage_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_ListPage_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -111,9 +104,8 @@ func (c *clusterControllerClient) ListPage(ctx context.Context, in *ListClusterP } func (c *clusterControllerClient) Register(ctx context.Context, in *RegisterClusterReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, ClusterController_Register_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Register_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -121,9 +113,8 @@ func (c *clusterControllerClient) Register(ctx context.Context, in *RegisterClus } func (c *clusterControllerClient) Unregister(ctx context.Context, in *UnregisterClusterReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, ClusterController_Unregister_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_Unregister_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -131,9 +122,8 @@ func (c *clusterControllerClient) Unregister(ctx context.Context, in *Unregister } func (c *clusterControllerClient) GenerateUninstallCmd(ctx context.Context, in *GenerateUninstallCmdReq, opts ...grpc.CallOption) (*GenerateUninstallCmdResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GenerateUninstallCmdResp) - err := c.cc.Invoke(ctx, ClusterController_GenerateUninstallCmd_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_GenerateUninstallCmd_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -141,9 +131,8 @@ func (c *clusterControllerClient) GenerateUninstallCmd(ctx context.Context, in * } func (c *clusterControllerClient) GenerateInstallCmd(ctx context.Context, in *GenerateInstallCmdReq, opts ...grpc.CallOption) (*GenerateInstallCmdResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GenerateInstallCmdResp) - err := c.cc.Invoke(ctx, ClusterController_GenerateInstallCmd_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_GenerateInstallCmd_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -151,9 +140,8 @@ func (c *clusterControllerClient) GenerateInstallCmd(ctx context.Context, in *Ge } func (c *clusterControllerClient) GenerateValuesYAML(ctx context.Context, in *GenerateValuesReq, opts ...grpc.CallOption) (*GenerateValuesResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GenerateValuesResp) - err := c.cc.Invoke(ctx, ClusterController_GenerateValuesYAML_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_GenerateValuesYAML_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -161,9 +149,8 @@ func (c *clusterControllerClient) GenerateValuesYAML(ctx context.Context, in *Ge } func (c *clusterControllerClient) ListRegistered(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListRegisteredResp, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListRegisteredResp) - err := c.cc.Invoke(ctx, ClusterController_ListRegistered_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ClusterController_ListRegistered_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -172,9 +159,7 @@ func (c *clusterControllerClient) ListRegistered(ctx context.Context, in *emptyp // ClusterControllerServer is the server API for ClusterController service. // All implementations must embed UnimplementedClusterControllerServer -// for forward compatibility. -// -// The cluster service definition. +// for forward compatibility type ClusterControllerServer interface { Create(context.Context, *Cluster) (*CreateClusterResp, error) Read(context.Context, *ReadClusterReq) (*ReadClusterResp, error) @@ -190,12 +175,9 @@ type ClusterControllerServer interface { mustEmbedUnimplementedClusterControllerServer() } -// UnimplementedClusterControllerServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedClusterControllerServer struct{} +// UnimplementedClusterControllerServer must be embedded to have forward compatible implementations. +type UnimplementedClusterControllerServer struct { +} func (UnimplementedClusterControllerServer) Create(context.Context, *Cluster) (*CreateClusterResp, error) { return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") @@ -231,7 +213,6 @@ func (UnimplementedClusterControllerServer) ListRegistered(context.Context, *emp return nil, status.Errorf(codes.Unimplemented, "method ListRegistered not implemented") } func (UnimplementedClusterControllerServer) mustEmbedUnimplementedClusterControllerServer() {} -func (UnimplementedClusterControllerServer) testEmbeddedByValue() {} // UnsafeClusterControllerServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ClusterControllerServer will @@ -241,13 +222,6 @@ type UnsafeClusterControllerServer interface { } func RegisterClusterControllerServer(s grpc.ServiceRegistrar, srv ClusterControllerServer) { - // If the following call pancis, it indicates UnimplementedClusterControllerServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } s.RegisterService(&ClusterController_ServiceDesc, srv) } diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go index fb4087d9..3604294e 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go @@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error { return nil } +func (jt JSONTime) String() string { + return time.Time(jt).String() +} + type Token struct { Username string `json:"username"` UserID string `json:"user_id"` @@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) { return nil, errors.New("unknown authorization format") } - token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) { + token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) { return key, nil }) if err != nil { diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go index 79432fec..24b0d6e3 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go @@ -27,7 +27,7 @@ func SetReady() { } // ReadyHandler handles ready probes. -func ReadyHandler(w http.ResponseWriter, r *http.Request) { +func ReadyHandler(w http.ResponseWriter, _ *http.Request) { if IsReady() { // Make it simple: do nothing and have 200 OK return @@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) { } // LiveHandler handles live probes. -func LiveHandler(w http.ResponseWriter, r *http.Request) { +func LiveHandler(http.ResponseWriter, *http.Request) { // Make it simple: do nothing and have 200 OK } diff --git a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go index cb9487d6..822eb440 100644 --- a/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go +++ b/cs-manager/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go @@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, const CorrelationHeader = "correlation-id" -func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { +func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { var corrID string md, ok := metadata.FromIncomingContext(ctx) diff --git a/cs-manager/vendor/modules.txt b/cs-manager/vendor/modules.txt index c5cacc1e..cd53e9b4 100644 --- a/cs-manager/vendor/modules.txt +++ b/cs-manager/vendor/modules.txt @@ -741,10 +741,10 @@ github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log # github.com/runtime-radar/runtime-radar/cluster-manager v0.0.0-00010101000000-000000000000 => ../cluster-manager -## explicit; go 1.24.0 +## explicit; go 1.25 github.com/runtime-radar/runtime-radar/cluster-manager/api # github.com/runtime-radar/runtime-radar/lib v0.0.0-00010101000000-000000000000 => ../lib -## explicit; go 1.23 +## explicit; go 1.25 github.com/runtime-radar/runtime-radar/lib/config github.com/runtime-radar/runtime-radar/lib/errcommon github.com/runtime-radar/runtime-radar/lib/logger diff --git a/docs/guides/detectors/guide.md b/docs/guides/detectors/guide.md index 591f453c..01c81305 100644 --- a/docs/guides/detectors/guide.md +++ b/docs/guides/detectors/guide.md @@ -14,7 +14,7 @@ task detectors ``` в директории `/event-processor` репозитория продукта. -Обратите внимание, что на текущий момент времени RuntimeRadar поддерживает только детекторы, собранные компилятором TinyGo версии v0.34.0. +Обратите внимание, что на текущий момент времени RuntimeRadar поддерживает только детекторы, собранные компилятором TinyGo версии v0.39.0. ## Настройка окружения @@ -23,8 +23,8 @@ task detectors Для работы с кодом детекторов рекомендуется открыть директорию `/event-processor/detector/wasm/` в отдельном инстансе VS Code. Настройки подключатся автоматически. Если это первый запуск VS Code в контексте Go, необходимо установить рекомендуемые расширения и перезапустить IDE. Также необходимо установить - - go1.23 - - TinyGo v0.34.0 + - go1.25 + - TinyGo v0.39.0 Проверить что в системе установлены правильные версии тулчейна Go и TinyGo можно командой ``` @@ -62,6 +62,33 @@ const ( После загрузки детектора в систему эти метаданные будут отображаться в интерфейсе. +Далее объявляется секция с критериями для запуска текущего детектора - это необходимо для оптимизации работы детекторов. Точечное описание критериев позволяет запускать конкретный детектор только для конкретных типов событий и для конкретных функций, тем самым существенно сокращая суммарное время обработки события. + +В критериях указываются типы событий, которые детектор должен обрабатывать, и названия функций (для тех типов, где это актуально). Подробнее с типами событий можно ознакомиться по [ссылке](https://tetragon.io/docs/reference/grpc-api/#eventtype). Детектор может работать одновременно как с разными типами событий, так и с разными функциями. Для корректной работы детектора необходимо указывать те функции, которые отслеживаются в соответствии с загруженными в систему TracingPolicy. + +Если требуется запускать детектор для всех событий, необходимо указать все типы событий, которые отслеживаются в соответствии с загруженными в систему TracingPolicy. Политики, [поставляемые](https://github.com/Runtime-Radar/runtime-radar/tree/main/runtime-monitor/pkg/model/tracingpolicy) вместе с Runtime Radar, на текущий момент работают только с `PROCESS_EXEC` и `PROCESS_KPROBE`. Если необходимо, чтобы детектор запускался для всех вызываемых функций, следует оставить список функций пустым или указать в качестве значения `*`. + +Нас интересует только одна функция ядра `inet_csk_listen_start` и мы не хотим, чтобы детектор срабатывал при вызове других функций или при возникновении событий других типов. +```go +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"inet_csk_listen_start"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) +``` + После этой секции в детекторе определяются некоторые переменные, например `sshdBin`, которая задает glob-паттерн для матчинга исполняемого файла `sshd` по имени, с учетом его полного пути. Заменим эту переменную на соответствующий шаблон для `nc`: ```go var ( @@ -191,6 +218,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"inet_csk_listen_start"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( nc = glob.MustCompile("*/nc") ) @@ -264,4 +309,16 @@ func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectRe return resp, nil } + +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} ``` diff --git a/event-processor/.task/checksum/detectors b/event-processor/.task/checksum/detectors index 15ae7e40..d29834b9 100644 --- a/event-processor/.task/checksum/detectors +++ b/event-processor/.task/checksum/detectors @@ -1 +1 @@ -e6b67040385930abdda8df7b36dfaea0 +51c209ed850e742bfbce722150503954 diff --git a/event-processor/Dockerfile b/event-processor/Dockerfile index 82bce1e4..c52915d6 100644 --- a/event-processor/Dockerfile +++ b/event-processor/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.24.1 AS tools +FROM golang:1.25.0 AS tools RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0 -FROM golang:1.24.1 AS builder +FROM golang:1.25.0 AS builder ARG BUILD_RELEASE ARG BUILD_BRANCH diff --git a/event-processor/Taskfile.yml b/event-processor/Taskfile.yml index 7b6c31a3..19d34496 100644 --- a/event-processor/Taskfile.yml +++ b/event-processor/Taskfile.yml @@ -95,7 +95,7 @@ tasks: vars: TINYGO_CURRENT_VERSION: sh: "tinygo version | cut -d' ' -f3" - TINYGO_REQUIRED_VERSION: "0.34.0" + TINYGO_REQUIRED_VERSION: "0.39.0" DETECTOR_DIR: detector/wasm DEPLOY_DIR: deploy cmds: @@ -106,7 +106,7 @@ tasks: - | detectors=`ls {{.DETECTOR_DIR}}` for detector in $detectors; do - tinygo build -o {{.DEPLOY_DIR}}/${detector}.wasm -scheduler=none -target=wasip1 --no-debug ./{{.DETECTOR_DIR}}/${detector} + tinygo build -o {{.DEPLOY_DIR}}/${detector}.wasm -scheduler=none -target=wasip1 -buildmode=wasi-legacy --no-debug ./{{.DETECTOR_DIR}}/${detector} done sources: - "go.mod" diff --git a/event-processor/cmd/event-processor/main.go b/event-processor/cmd/event-processor/main.go index a7268524..0783d2af 100644 --- a/event-processor/cmd/event-processor/main.go +++ b/event-processor/cmd/event-processor/main.go @@ -303,7 +303,7 @@ func ensureDetectors(db *gorm.DB, plugin *detector_api.DetectorPlugin, deployDir return fmt.Errorf("can't read wasm file '%s': %w", file, err) } - d, err := detector.ModelFromBinary(ctx, plugin, b) + d, err := detector.BinToModel(ctx, plugin, b) if err != nil { return fmt.Errorf("can't get detector info from wasm file '%s': %w", file, err) } diff --git a/event-processor/deploy/CS_RT_BASE64_DECODE_RUN.wasm b/event-processor/deploy/CS_RT_BASE64_DECODE_RUN.wasm index d43448f6..b9e8a3f6 100644 Binary files a/event-processor/deploy/CS_RT_BASE64_DECODE_RUN.wasm and b/event-processor/deploy/CS_RT_BASE64_DECODE_RUN.wasm differ diff --git a/event-processor/deploy/CS_RT_BIN_PERM_RAISE.wasm b/event-processor/deploy/CS_RT_BIN_PERM_RAISE.wasm index 1eb11af5..6f5fdd4d 100644 Binary files a/event-processor/deploy/CS_RT_BIN_PERM_RAISE.wasm and b/event-processor/deploy/CS_RT_BIN_PERM_RAISE.wasm differ diff --git a/event-processor/deploy/CS_RT_CORE_PATTERN_MODIFY.wasm b/event-processor/deploy/CS_RT_CORE_PATTERN_MODIFY.wasm index a8d6c583..ddaf565a 100644 Binary files a/event-processor/deploy/CS_RT_CORE_PATTERN_MODIFY.wasm and b/event-processor/deploy/CS_RT_CORE_PATTERN_MODIFY.wasm differ diff --git a/event-processor/deploy/CS_RT_CRYPTOMINER.wasm b/event-processor/deploy/CS_RT_CRYPTOMINER.wasm index 3b402db0..be7e9aae 100644 Binary files a/event-processor/deploy/CS_RT_CRYPTOMINER.wasm and b/event-processor/deploy/CS_RT_CRYPTOMINER.wasm differ diff --git a/event-processor/deploy/CS_RT_CVE_2022_0492.wasm b/event-processor/deploy/CS_RT_CVE_2022_0492.wasm index 12db9c2c..064366e9 100644 Binary files a/event-processor/deploy/CS_RT_CVE_2022_0492.wasm and b/event-processor/deploy/CS_RT_CVE_2022_0492.wasm differ diff --git a/event-processor/deploy/CS_RT_CVE_2025_1974.wasm b/event-processor/deploy/CS_RT_CVE_2025_1974.wasm index bcb4f47f..e9f6504e 100644 Binary files a/event-processor/deploy/CS_RT_CVE_2025_1974.wasm and b/event-processor/deploy/CS_RT_CVE_2025_1974.wasm differ diff --git a/event-processor/deploy/CS_RT_DOWNLOAD_TOOLS.wasm b/event-processor/deploy/CS_RT_DOWNLOAD_TOOLS.wasm index 1893b98d..98eaef5f 100644 Binary files a/event-processor/deploy/CS_RT_DOWNLOAD_TOOLS.wasm and b/event-processor/deploy/CS_RT_DOWNLOAD_TOOLS.wasm differ diff --git a/event-processor/deploy/CS_RT_FILELESS_EXEC.wasm b/event-processor/deploy/CS_RT_FILELESS_EXEC.wasm index 177331f0..7bdb7f63 100644 Binary files a/event-processor/deploy/CS_RT_FILELESS_EXEC.wasm and b/event-processor/deploy/CS_RT_FILELESS_EXEC.wasm differ diff --git a/event-processor/deploy/CS_RT_HACK_TOOLS.wasm b/event-processor/deploy/CS_RT_HACK_TOOLS.wasm index e9666ca9..5127c88e 100644 Binary files a/event-processor/deploy/CS_RT_HACK_TOOLS.wasm and b/event-processor/deploy/CS_RT_HACK_TOOLS.wasm differ diff --git a/event-processor/deploy/CS_RT_HACK_TOOLS_EXT.wasm b/event-processor/deploy/CS_RT_HACK_TOOLS_EXT.wasm index 2a929c2d..469c0a7e 100644 Binary files a/event-processor/deploy/CS_RT_HACK_TOOLS_EXT.wasm and b/event-processor/deploy/CS_RT_HACK_TOOLS_EXT.wasm differ diff --git a/event-processor/deploy/CS_RT_IO_URING_CREATE.wasm b/event-processor/deploy/CS_RT_IO_URING_CREATE.wasm index d409a6df..ff8696d2 100644 Binary files a/event-processor/deploy/CS_RT_IO_URING_CREATE.wasm and b/event-processor/deploy/CS_RT_IO_URING_CREATE.wasm differ diff --git a/event-processor/deploy/CS_RT_K8S_SA_TOKEN_READ.wasm b/event-processor/deploy/CS_RT_K8S_SA_TOKEN_READ.wasm index 968f70b3..cbbee171 100644 Binary files a/event-processor/deploy/CS_RT_K8S_SA_TOKEN_READ.wasm and b/event-processor/deploy/CS_RT_K8S_SA_TOKEN_READ.wasm differ diff --git a/event-processor/deploy/CS_RT_KERNEL_MODULE.wasm b/event-processor/deploy/CS_RT_KERNEL_MODULE.wasm index dedad298..6f3c2346 100644 Binary files a/event-processor/deploy/CS_RT_KERNEL_MODULE.wasm and b/event-processor/deploy/CS_RT_KERNEL_MODULE.wasm differ diff --git a/event-processor/deploy/CS_RT_LD_PRELOAD.wasm b/event-processor/deploy/CS_RT_LD_PRELOAD.wasm index 2e1b4166..f5912055 100644 Binary files a/event-processor/deploy/CS_RT_LD_PRELOAD.wasm and b/event-processor/deploy/CS_RT_LD_PRELOAD.wasm differ diff --git a/event-processor/deploy/CS_RT_MEMFD_RUN.wasm b/event-processor/deploy/CS_RT_MEMFD_RUN.wasm deleted file mode 100644 index d1969c90..00000000 Binary files a/event-processor/deploy/CS_RT_MEMFD_RUN.wasm and /dev/null differ diff --git a/event-processor/deploy/CS_RT_MOUNT_DEV.wasm b/event-processor/deploy/CS_RT_MOUNT_DEV.wasm index 53735564..3c996e8c 100644 Binary files a/event-processor/deploy/CS_RT_MOUNT_DEV.wasm and b/event-processor/deploy/CS_RT_MOUNT_DEV.wasm differ diff --git a/event-processor/deploy/CS_RT_OPENSSL_CUSTOM_LIB_LOAD.wasm b/event-processor/deploy/CS_RT_OPENSSL_CUSTOM_LIB_LOAD.wasm index 80f6c328..192fac01 100644 Binary files a/event-processor/deploy/CS_RT_OPENSSL_CUSTOM_LIB_LOAD.wasm and b/event-processor/deploy/CS_RT_OPENSSL_CUSTOM_LIB_LOAD.wasm differ diff --git a/event-processor/deploy/CS_RT_OPENSSL_FILE_ACCESS.wasm b/event-processor/deploy/CS_RT_OPENSSL_FILE_ACCESS.wasm index c6be0bd8..f6bee457 100644 Binary files a/event-processor/deploy/CS_RT_OPENSSL_FILE_ACCESS.wasm and b/event-processor/deploy/CS_RT_OPENSSL_FILE_ACCESS.wasm differ diff --git a/event-processor/deploy/CS_RT_OPENSSL_SERVER_RUN.wasm b/event-processor/deploy/CS_RT_OPENSSL_SERVER_RUN.wasm index 6bfd7b80..4030e463 100644 Binary files a/event-processor/deploy/CS_RT_OPENSSL_SERVER_RUN.wasm and b/event-processor/deploy/CS_RT_OPENSSL_SERVER_RUN.wasm differ diff --git a/event-processor/deploy/CS_RT_PRIV_ESC.wasm b/event-processor/deploy/CS_RT_PRIV_ESC.wasm index 1dd2c8c0..7d9617b9 100644 Binary files a/event-processor/deploy/CS_RT_PRIV_ESC.wasm and b/event-processor/deploy/CS_RT_PRIV_ESC.wasm differ diff --git a/event-processor/deploy/CS_RT_PROCESS_CAP_RAISE.wasm b/event-processor/deploy/CS_RT_PROCESS_CAP_RAISE.wasm index 1087fdf5..eb844632 100644 Binary files a/event-processor/deploy/CS_RT_PROCESS_CAP_RAISE.wasm and b/event-processor/deploy/CS_RT_PROCESS_CAP_RAISE.wasm differ diff --git a/event-processor/deploy/CS_RT_PTRACE_CODE_INJ.wasm b/event-processor/deploy/CS_RT_PTRACE_CODE_INJ.wasm index 56d6191f..648a47e3 100644 Binary files a/event-processor/deploy/CS_RT_PTRACE_CODE_INJ.wasm and b/event-processor/deploy/CS_RT_PTRACE_CODE_INJ.wasm differ diff --git a/event-processor/deploy/CS_RT_RAW_SOCKETS.wasm b/event-processor/deploy/CS_RT_RAW_SOCKETS.wasm index b3a7c221..3047a360 100644 Binary files a/event-processor/deploy/CS_RT_RAW_SOCKETS.wasm and b/event-processor/deploy/CS_RT_RAW_SOCKETS.wasm differ diff --git a/event-processor/deploy/CS_RT_RECON_TOOLS.wasm b/event-processor/deploy/CS_RT_RECON_TOOLS.wasm index 4f50faf3..706fd5cc 100644 Binary files a/event-processor/deploy/CS_RT_RECON_TOOLS.wasm and b/event-processor/deploy/CS_RT_RECON_TOOLS.wasm differ diff --git a/event-processor/deploy/CS_RT_REVERSE_SHELL_CREATE.wasm b/event-processor/deploy/CS_RT_REVERSE_SHELL_CREATE.wasm index 78b53763..18585e37 100644 Binary files a/event-processor/deploy/CS_RT_REVERSE_SHELL_CREATE.wasm and b/event-processor/deploy/CS_RT_REVERSE_SHELL_CREATE.wasm differ diff --git a/event-processor/deploy/CS_RT_REVERSE_SHELL_USE.wasm b/event-processor/deploy/CS_RT_REVERSE_SHELL_USE.wasm index ffa0057e..5c4c0c2b 100644 Binary files a/event-processor/deploy/CS_RT_REVERSE_SHELL_USE.wasm and b/event-processor/deploy/CS_RT_REVERSE_SHELL_USE.wasm differ diff --git a/event-processor/deploy/CS_RT_REV_ENG.wasm b/event-processor/deploy/CS_RT_REV_ENG.wasm index 8420c45e..f534a317 100644 Binary files a/event-processor/deploy/CS_RT_REV_ENG.wasm and b/event-processor/deploy/CS_RT_REV_ENG.wasm differ diff --git a/event-processor/deploy/CS_RT_SCHED_TASK_MOD.wasm b/event-processor/deploy/CS_RT_SCHED_TASK_MOD.wasm index 457da493..342e5f20 100644 Binary files a/event-processor/deploy/CS_RT_SCHED_TASK_MOD.wasm and b/event-processor/deploy/CS_RT_SCHED_TASK_MOD.wasm differ diff --git a/event-processor/deploy/CS_RT_SSH_KEY_MODIFY.wasm b/event-processor/deploy/CS_RT_SSH_KEY_MODIFY.wasm index 1bfa68e0..86ce6c53 100644 Binary files a/event-processor/deploy/CS_RT_SSH_KEY_MODIFY.wasm and b/event-processor/deploy/CS_RT_SSH_KEY_MODIFY.wasm differ diff --git a/event-processor/deploy/CS_RT_SSH_TUNNEL_CREATE.wasm b/event-processor/deploy/CS_RT_SSH_TUNNEL_CREATE.wasm index da2f867c..6334324f 100644 Binary files a/event-processor/deploy/CS_RT_SSH_TUNNEL_CREATE.wasm and b/event-processor/deploy/CS_RT_SSH_TUNNEL_CREATE.wasm differ diff --git a/event-processor/deploy/CS_RT_SSH_TUNNEL_USE.wasm b/event-processor/deploy/CS_RT_SSH_TUNNEL_USE.wasm index 01303309..b5b4c955 100644 Binary files a/event-processor/deploy/CS_RT_SSH_TUNNEL_USE.wasm and b/event-processor/deploy/CS_RT_SSH_TUNNEL_USE.wasm differ diff --git a/event-processor/deploy/CS_RT_SUSP_FILE_READ.wasm b/event-processor/deploy/CS_RT_SUSP_FILE_READ.wasm index d5b9a5c5..0d4c0948 100644 Binary files a/event-processor/deploy/CS_RT_SUSP_FILE_READ.wasm and b/event-processor/deploy/CS_RT_SUSP_FILE_READ.wasm differ diff --git a/event-processor/deploy/CS_RT_SUSP_FILE_WRITE.wasm b/event-processor/deploy/CS_RT_SUSP_FILE_WRITE.wasm index 28c98d64..4b03f0fc 100644 Binary files a/event-processor/deploy/CS_RT_SUSP_FILE_WRITE.wasm and b/event-processor/deploy/CS_RT_SUSP_FILE_WRITE.wasm differ diff --git a/event-processor/deploy/CS_RT_SUSP_SHELL.wasm b/event-processor/deploy/CS_RT_SUSP_SHELL.wasm index 13a395a9..8899d602 100644 Binary files a/event-processor/deploy/CS_RT_SUSP_SHELL.wasm and b/event-processor/deploy/CS_RT_SUSP_SHELL.wasm differ diff --git a/event-processor/detector/api/detector.pb.go b/event-processor/detector/api/detector.pb.go index 3a6aa9d7..4329a099 100644 --- a/event-processor/detector/api/detector.pb.go +++ b/event-processor/detector/api/detector.pb.go @@ -55,167 +55,168 @@ func (x DetectResp_Severity) Enum() *DetectResp_Severity { return p } -type DetectReq struct { +type InfoReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Event *tetragon.GetEventsResponse `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` } -func (x *DetectReq) ProtoReflect() protoreflect.Message { +func (x *InfoReq) ProtoReflect() protoreflect.Message { panic(`not implemented`) } -func (x *DetectReq) GetEvent() *tetragon.GetEventsResponse { - if x != nil { - return x.Event - } - return nil -} - -type DetectResp struct { +type InfoResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Version uint32 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` - Author string `protobuf:"bytes,5,opt,name=author,proto3" json:"author,omitempty"` - Contact string `protobuf:"bytes,6,opt,name=contact,proto3" json:"contact,omitempty"` - Severity DetectResp_Severity `protobuf:"varint,8,opt,name=severity,proto3,enum=detector.DetectResp_Severity" json:"severity,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Version uint32 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` + Author string `protobuf:"bytes,5,opt,name=author,proto3" json:"author,omitempty"` + Contact string `protobuf:"bytes,6,opt,name=contact,proto3" json:"contact,omitempty"` + License string `protobuf:"bytes,7,opt,name=license,proto3" json:"license,omitempty"` } -func (x *DetectResp) ProtoReflect() protoreflect.Message { +func (x *InfoResp) ProtoReflect() protoreflect.Message { panic(`not implemented`) } -func (x *DetectResp) GetId() string { +func (x *InfoResp) GetId() string { if x != nil { return x.Id } return "" } -func (x *DetectResp) GetName() string { +func (x *InfoResp) GetName() string { if x != nil { return x.Name } return "" } -func (x *DetectResp) GetDescription() string { +func (x *InfoResp) GetDescription() string { if x != nil { return x.Description } return "" } -func (x *DetectResp) GetVersion() uint32 { +func (x *InfoResp) GetVersion() uint32 { if x != nil { return x.Version } return 0 } -func (x *DetectResp) GetAuthor() string { +func (x *InfoResp) GetAuthor() string { if x != nil { return x.Author } return "" } -func (x *DetectResp) GetContact() string { +func (x *InfoResp) GetContact() string { if x != nil { return x.Contact } return "" } -func (x *DetectResp) GetSeverity() DetectResp_Severity { +func (x *InfoResp) GetLicense() string { if x != nil { - return x.Severity + return x.License } - return DetectResp_NONE + return "" } -type InfoReq struct { +type DetectReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Event *tetragon.GetEventsResponse `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` } -func (x *InfoReq) ProtoReflect() protoreflect.Message { +func (x *DetectReq) ProtoReflect() protoreflect.Message { panic(`not implemented`) } -type InfoResp struct { +func (x *DetectReq) GetEvent() *tetragon.GetEventsResponse { + if x != nil { + return x.Event + } + return nil +} + +type DetectResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Version uint32 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` - Author string `protobuf:"bytes,5,opt,name=author,proto3" json:"author,omitempty"` - Contact string `protobuf:"bytes,6,opt,name=contact,proto3" json:"contact,omitempty"` - License string `protobuf:"bytes,7,opt,name=license,proto3" json:"license,omitempty"` + Severity DetectResp_Severity `protobuf:"varint,8,opt,name=severity,proto3,enum=detector.DetectResp_Severity" json:"severity,omitempty"` } -func (x *InfoResp) ProtoReflect() protoreflect.Message { +func (x *DetectResp) ProtoReflect() protoreflect.Message { panic(`not implemented`) } -func (x *InfoResp) GetId() string { +func (x *DetectResp) GetSeverity() DetectResp_Severity { if x != nil { - return x.Id + return x.Severity } - return "" + return DetectResp_NONE } -func (x *InfoResp) GetName() string { - if x != nil { - return x.Name - } - return "" +type TriggerCriteriaReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields } -func (x *InfoResp) GetDescription() string { - if x != nil { - return x.Description - } - return "" +func (x *TriggerCriteriaReq) ProtoReflect() protoreflect.Message { + panic(`not implemented`) } -func (x *InfoResp) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 +type TriggerCriteriaResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Criteria links event types with function names. Supported event types are defined in history-api/pkg/model/RuntimeEventType* constants. + Criteria map[string]*TriggerCriteriaResp_FuncNames `protobuf:"bytes,1,rep,name=criteria,proto3" json:"criteria,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } -func (x *InfoResp) GetAuthor() string { - if x != nil { - return x.Author - } - return "" +func (x *TriggerCriteriaResp) ProtoReflect() protoreflect.Message { + panic(`not implemented`) } -func (x *InfoResp) GetContact() string { +func (x *TriggerCriteriaResp) GetCriteria() map[string]*TriggerCriteriaResp_FuncNames { if x != nil { - return x.Contact + return x.Criteria } - return "" + return nil } -func (x *InfoResp) GetLicense() string { +type TriggerCriteriaResp_FuncNames struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FuncNames []string `protobuf:"bytes,1,rep,name=func_names,json=funcNames,proto3" json:"func_names,omitempty"` +} + +func (x *TriggerCriteriaResp_FuncNames) ProtoReflect() protoreflect.Message { + panic(`not implemented`) +} + +func (x *TriggerCriteriaResp_FuncNames) GetFuncNames() []string { if x != nil { - return x.License + return x.FuncNames } - return "" + return nil } // Detector service definition. @@ -223,4 +224,5 @@ func (x *InfoResp) GetLicense() string { type Detector interface { Info(context.Context, *InfoReq) (*InfoResp, error) Detect(context.Context, *DetectReq) (*DetectResp, error) + TriggerCriteria(context.Context, *TriggerCriteriaReq) (*TriggerCriteriaResp, error) } diff --git a/event-processor/detector/api/detector.proto b/event-processor/detector/api/detector.proto index f133ccb5..9de5f141 100644 --- a/event-processor/detector/api/detector.proto +++ b/event-processor/detector/api/detector.proto @@ -11,25 +11,26 @@ option go_package = "./api"; service Detector { rpc Info(InfoReq) returns (InfoResp) {} rpc Detect(DetectReq) returns (DetectResp) {} + rpc TriggerCriteria(TriggerCriteriaReq) returns (TriggerCriteriaResp) {} } -message DetectReq { - tetragon.GetEventsResponse event = 1; -} +message InfoReq {} -message DetectResp { +message InfoResp { string id = 1; string name = 2; string description = 3; uint32 version = 4; string author = 5; string contact = 6; - // license is not added to detector response because it's supposed that - // it can include the whole text of the License Agreement, which may add - // significant overhead to communication flow. - // string license = 7; - reserved 7; + string license = 7; +} + +message DetectReq { + tetragon.GetEventsResponse event = 1; +} +message DetectResp { enum Severity { NONE = 0; LOW = 1; @@ -40,14 +41,12 @@ message DetectResp { Severity severity = 8; } -message InfoReq {} +message TriggerCriteriaReq {} -message InfoResp { - string id = 1; - string name = 2; - string description = 3; - uint32 version = 4; - string author = 5; - string contact = 6; - string license = 7; +message TriggerCriteriaResp { + message FuncNames { + repeated string func_names = 1; + } + // Criteria links event types with function names. Supported event types are defined in history-api/pkg/model/RuntimeEventType* constants. + map criteria = 1; } diff --git a/event-processor/detector/api/detector_host.pb.go b/event-processor/detector/api/detector_host.pb.go index b1dee166..e683058e 100644 --- a/event-processor/detector/api/detector_host.pb.go +++ b/event-processor/detector/api/detector_host.pb.go @@ -103,6 +103,10 @@ func (p *DetectorPlugin) LoadBinary(ctx context.Context, pluginBinary []byte) (d if detect == nil { return nil, errors.New("detector_detect is not exported") } + triggercriteria := module.ExportedFunction("detector_trigger_criteria") + if triggercriteria == nil { + return nil, errors.New("detector_trigger_criteria is not exported") + } malloc := module.ExportedFunction("malloc") if malloc == nil { @@ -114,12 +118,13 @@ func (p *DetectorPlugin) LoadBinary(ctx context.Context, pluginBinary []byte) (d return nil, errors.New("free is not exported") } return &detectorPlugin{ - runtime: r, - module: module, - malloc: malloc, - free: free, - info: info, - detect: detect, + runtime: r, + module: module, + malloc: malloc, + free: free, + info: info, + detect: detect, + triggercriteria: triggercriteria, }, nil } @@ -131,12 +136,13 @@ func (p *detectorPlugin) Close(ctx context.Context) (err error) { } type detectorPlugin struct { - runtime wazero.Runtime - module api.Module - malloc api.Function - free api.Function - info api.Function - detect api.Function + runtime wazero.Runtime + module api.Module + malloc api.Function + free api.Function + info api.Function + detect api.Function + triggercriteria api.Function } func (p *detectorPlugin) Info(ctx context.Context, request *InfoReq) (*InfoResp, error) { @@ -261,3 +267,64 @@ func (p *detectorPlugin) Detect(ctx context.Context, request *DetectReq) (*Detec return response, nil } +func (p *detectorPlugin) TriggerCriteria(ctx context.Context, request *TriggerCriteriaReq) (*TriggerCriteriaResp, error) { + data, err := request.MarshalVT() + if err != nil { + return nil, err + } + dataSize := uint64(len(data)) + + var dataPtr uint64 + // If the input data is not empty, we must allocate the in-Wasm memory to store it, and pass to the plugin. + if dataSize != 0 { + results, err := p.malloc.Call(ctx, dataSize) + if err != nil { + return nil, err + } + dataPtr = results[0] + // This pointer is managed by TinyGo, but TinyGo is unaware of external usage. + // So, we have to free it when finished + defer p.free.Call(ctx, dataPtr) + + // The pointer is a linear memory offset, which is where we write the name. + if !p.module.Memory().Write(uint32(dataPtr), data) { + return nil, fmt.Errorf("Memory.Write(%d, %d) out of range of memory size %d", dataPtr, dataSize, p.module.Memory().Size()) + } + } + + ptrSize, err := p.triggercriteria.Call(ctx, dataPtr, dataSize) + if err != nil { + return nil, err + } + + resPtr := uint32(ptrSize[0] >> 32) + resSize := uint32(ptrSize[0]) + var isErrResponse bool + if (resSize & (1 << 31)) > 0 { + isErrResponse = true + resSize &^= (1 << 31) + } + + // We don't need the memory after deserialization: make sure it is freed. + if resPtr != 0 { + defer p.free.Call(ctx, uint64(resPtr)) + } + + // The pointer is a linear memory offset, which is where we write the name. + bytes, ok := p.module.Memory().Read(resPtr, resSize) + if !ok { + return nil, fmt.Errorf("Memory.Read(%d, %d) out of range of memory size %d", + resPtr, resSize, p.module.Memory().Size()) + } + + if isErrResponse { + return nil, errors.New(string(bytes)) + } + + response := new(TriggerCriteriaResp) + if err = response.UnmarshalVT(bytes); err != nil { + return nil, err + } + + return response, nil +} diff --git a/event-processor/detector/api/detector_plugin.pb.go b/event-processor/detector/api/detector_plugin.pb.go index b37086a5..f41a1d11 100644 --- a/event-processor/detector/api/detector_plugin.pb.go +++ b/event-processor/detector/api/detector_plugin.pb.go @@ -73,3 +73,27 @@ func _detector_detect(ptr, size uint32) uint64 { ptr, size = wasm.ByteToPtr(b) return (uint64(ptr) << uint64(32)) | uint64(size) } + +//export detector_trigger_criteria +func _detector_trigger_criteria(ptr, size uint32) uint64 { + b := wasm.PtrToByte(ptr, size) + req := new(TriggerCriteriaReq) + if err := req.UnmarshalVT(b); err != nil { + return 0 + } + response, err := detector.TriggerCriteria(context.Background(), req) + if err != nil { + ptr, size = wasm.ByteToPtr([]byte(err.Error())) + return (uint64(ptr) << uint64(32)) | uint64(size) | + // Indicate that this is the error string by setting the 32-th bit, assuming that + // no data exceeds 31-bit size (2 GiB). + (1 << 31) + } + + b, err = response.MarshalVT() + if err != nil { + return 0 + } + ptr, size = wasm.ByteToPtr(b) + return (uint64(ptr) << uint64(32)) | uint64(size) +} diff --git a/event-processor/detector/api/detector_vtproto.pb.go b/event-processor/detector/api/detector_vtproto.pb.go index e5f8914c..5aa09bdc 100644 --- a/event-processor/detector/api/detector_vtproto.pb.go +++ b/event-processor/detector/api/detector_vtproto.pb.go @@ -8,11 +8,10 @@ package api import ( fmt "fmt" - io "io" - bits "math/bits" - tetragon "github.com/runtime-radar/runtime-radar/event-processor/detector/api/tetragon" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + bits "math/bits" ) const ( @@ -22,7 +21,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -func (m *DetectReq) MarshalVT() (dAtA []byte, err error) { +func (m *InfoReq) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -35,12 +34,12 @@ func (m *DetectReq) MarshalVT() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *DetectReq) MarshalToVT(dAtA []byte) (int, error) { +func (m *InfoReq) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *DetectReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { +func (m *InfoReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -52,20 +51,10 @@ func (m *DetectReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if m.Event != nil { - size, err := m.Event.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0xa - } return len(dAtA) - i, nil } -func (m *DetectResp) MarshalVT() (dAtA []byte, err error) { +func (m *InfoResp) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -78,12 +67,12 @@ func (m *DetectResp) MarshalVT() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *DetectResp) MarshalToVT(dAtA []byte) (int, error) { +func (m *InfoResp) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *DetectResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { +func (m *InfoResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -95,10 +84,12 @@ func (m *DetectResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if m.Severity != 0 { - i = encodeVarint(dAtA, i, uint64(m.Severity)) + if len(m.License) > 0 { + i -= len(m.License) + copy(dAtA[i:], m.License) + i = encodeVarint(dAtA, i, uint64(len(m.License))) i-- - dAtA[i] = 0x40 + dAtA[i] = 0x3a } if len(m.Contact) > 0 { i -= len(m.Contact) @@ -143,7 +134,7 @@ func (m *DetectResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *InfoReq) MarshalVT() (dAtA []byte, err error) { +func (m *DetectReq) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -156,12 +147,12 @@ func (m *InfoReq) MarshalVT() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *InfoReq) MarshalToVT(dAtA []byte) (int, error) { +func (m *DetectReq) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *InfoReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { +func (m *DetectReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -173,10 +164,20 @@ func (m *InfoReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Event != nil { + size, err := m.Event.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } -func (m *InfoResp) MarshalVT() (dAtA []byte, err error) { +func (m *DetectResp) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -189,12 +190,12 @@ func (m *InfoResp) MarshalVT() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *InfoResp) MarshalToVT(dAtA []byte) (int, error) { +func (m *DetectResp) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *InfoResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { +func (m *DetectResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -206,52 +207,140 @@ func (m *InfoResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.License) > 0 { - i -= len(m.License) - copy(dAtA[i:], m.License) - i = encodeVarint(dAtA, i, uint64(len(m.License))) + if m.Severity != 0 { + i = encodeVarint(dAtA, i, uint64(m.Severity)) i-- - dAtA[i] = 0x3a + dAtA[i] = 0x40 } - if len(m.Contact) > 0 { - i -= len(m.Contact) - copy(dAtA[i:], m.Contact) - i = encodeVarint(dAtA, i, uint64(len(m.Contact))) - i-- - dAtA[i] = 0x32 + return len(dAtA) - i, nil +} + +func (m *TriggerCriteriaReq) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil } - if len(m.Author) > 0 { - i -= len(m.Author) - copy(dAtA[i:], m.Author) - i = encodeVarint(dAtA, i, uint64(len(m.Author))) - i-- - dAtA[i] = 0x2a + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err } - if m.Version != 0 { - i = encodeVarint(dAtA, i, uint64(m.Version)) - i-- - dAtA[i] = 0x20 + return dAtA[:n], nil +} + +func (m *TriggerCriteriaReq) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TriggerCriteriaReq) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil } - if len(m.Description) > 0 { - i -= len(m.Description) - copy(dAtA[i:], m.Description) - i = encodeVarint(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x1a + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) } - if len(m.Name) > 0 { - i -= len(m.Name) - copy(dAtA[i:], m.Name) - i = encodeVarint(dAtA, i, uint64(len(m.Name))) - i-- - dAtA[i] = 0x12 + return len(dAtA) - i, nil +} + +func (m *TriggerCriteriaResp_FuncNames) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil } - if len(m.Id) > 0 { - i -= len(m.Id) - copy(dAtA[i:], m.Id) - i = encodeVarint(dAtA, i, uint64(len(m.Id))) - i-- - dAtA[i] = 0xa + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TriggerCriteriaResp_FuncNames) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TriggerCriteriaResp_FuncNames) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.FuncNames) > 0 { + for iNdEx := len(m.FuncNames) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.FuncNames[iNdEx]) + copy(dAtA[i:], m.FuncNames[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.FuncNames[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *TriggerCriteriaResp) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TriggerCriteriaResp) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TriggerCriteriaResp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Criteria) > 0 { + for k := range m.Criteria { + v := m.Criteria[k] + baseI := i + size, err := v.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } } return len(dAtA) - i, nil } @@ -267,21 +356,17 @@ func encodeVarint(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *DetectReq) SizeVT() (n int) { +func (m *InfoReq) SizeVT() (n int) { if m == nil { return 0 } var l int _ = l - if m.Event != nil { - l = m.Event.SizeVT() - n += 1 + l + sov(uint64(l)) - } n += len(m.unknownFields) return n } -func (m *DetectResp) SizeVT() (n int) { +func (m *InfoResp) SizeVT() (n int) { if m == nil { return 0 } @@ -310,67 +395,97 @@ func (m *DetectResp) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } - if m.Severity != 0 { - n += 1 + sov(uint64(m.Severity)) + l = len(m.License) + if l > 0 { + n += 1 + l + sov(uint64(l)) } n += len(m.unknownFields) return n } -func (m *InfoReq) SizeVT() (n int) { +func (m *DetectReq) SizeVT() (n int) { if m == nil { return 0 } var l int _ = l + if m.Event != nil { + l = m.Event.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } -func (m *InfoResp) SizeVT() (n int) { +func (m *DetectResp) SizeVT() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.Id) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Name) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - if m.Version != 0 { - n += 1 + sov(uint64(m.Version)) + if m.Severity != 0 { + n += 1 + sov(uint64(m.Severity)) } - l = len(m.Author) - if l > 0 { - n += 1 + l + sov(uint64(l)) + n += len(m.unknownFields) + return n +} + +func (m *TriggerCriteriaReq) SizeVT() (n int) { + if m == nil { + return 0 } - l = len(m.Contact) - if l > 0 { - n += 1 + l + sov(uint64(l)) + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *TriggerCriteriaResp_FuncNames) SizeVT() (n int) { + if m == nil { + return 0 } - l = len(m.License) - if l > 0 { - n += 1 + l + sov(uint64(l)) + var l int + _ = l + if len(m.FuncNames) > 0 { + for _, s := range m.FuncNames { + l = len(s) + n += 1 + l + sov(uint64(l)) + } } n += len(m.unknownFields) return n } -func sov(x uint64) (n int) { - return (bits.Len64(x|1) + 6) / 7 -} -func soz(x uint64) (n int) { - return sov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +func (m *TriggerCriteriaResp) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Criteria) > 0 { + for k, v := range m.Criteria { + _ = k + _ = v + l = 0 + if v != nil { + l = v.SizeVT() + } + l += 1 + sov(uint64(l)) + mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l + n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) + } + } + n += len(m.unknownFields) + return n } -func (m *DetectReq) UnmarshalVT(dAtA []byte) error { + +func sov(x uint64) (n int) { + return (bits.Len64(x|1) + 6) / 7 +} +func soz(x uint64) (n int) { + return sov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *InfoReq) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -393,48 +508,12 @@ func (m *DetectReq) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DetectReq: wiretype end group for non-group") + return fmt.Errorf("proto: InfoReq: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DetectReq: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InfoReq: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Event", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Event == nil { - m.Event = &tetragon.GetEventsResponse{} - } - if err := m.Event.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -457,7 +536,7 @@ func (m *DetectReq) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *DetectResp) UnmarshalVT(dAtA []byte) error { +func (m *InfoResp) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -480,10 +559,10 @@ func (m *DetectResp) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DetectResp: wiretype end group for non-group") + return fmt.Errorf("proto: InfoResp: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DetectResp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InfoResp: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -665,11 +744,11 @@ func (m *DetectResp) UnmarshalVT(dAtA []byte) error { } m.Contact = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Severity", wireType) + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field License", wireType) } - m.Severity = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -679,11 +758,24 @@ func (m *DetectResp) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Severity |= DetectResp_Severity(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.License = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -706,7 +798,7 @@ func (m *DetectResp) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *InfoReq) UnmarshalVT(dAtA []byte) error { +func (m *DetectReq) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -729,12 +821,48 @@ func (m *InfoReq) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: InfoReq: wiretype end group for non-group") + return fmt.Errorf("proto: DetectReq: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: InfoReq: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DetectReq: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Event", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Event == nil { + m.Event = &tetragon.GetEventsResponse{} + } + if err := m.Event.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -757,7 +885,7 @@ func (m *InfoReq) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *InfoResp) UnmarshalVT(dAtA []byte) error { +func (m *DetectResp) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -780,17 +908,17 @@ func (m *InfoResp) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: InfoResp: wiretype end group for non-group") + return fmt.Errorf("proto: DetectResp: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: InfoResp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DetectResp: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Severity", wireType) } - var stringLen uint64 + m.Severity = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -800,110 +928,116 @@ func (m *InfoResp) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.Severity |= DetectResp_Severity(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - postIndex := iNdEx + intStringLen - if postIndex < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.Id = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TriggerCriteriaReq) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow } - if postIndex > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TriggerCriteriaReq: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TriggerCriteriaReq: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - postIndex := iNdEx + intStringLen - if postIndex < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - if postIndex > l { + if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF } - m.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TriggerCriteriaResp_FuncNames) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow } - m.Version = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Version |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } + if iNdEx >= l { + return io.ErrUnexpectedEOF } - case 5: + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TriggerCriteriaResp_FuncNames: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TriggerCriteriaResp_FuncNames: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Author", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field FuncNames", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -931,45 +1065,64 @@ func (m *InfoResp) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Author = string(dAtA[iNdEx:postIndex]) + m.FuncNames = append(m.FuncNames, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Contact", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TriggerCriteriaResp) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.Contact = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TriggerCriteriaResp: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TriggerCriteriaResp: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field License", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Criteria", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -979,23 +1132,120 @@ func (m *InfoResp) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLength } if postIndex > l { return io.ErrUnexpectedEOF } - m.License = string(dAtA[iNdEx:postIndex]) + if m.Criteria == nil { + m.Criteria = make(map[string]*TriggerCriteriaResp_FuncNames) + } + var mapkey string + var mapvalue *TriggerCriteriaResp_FuncNames + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLength + } + postmsgIndex := iNdEx + mapmsglen + if postmsgIndex < 0 { + return ErrInvalidLength + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &TriggerCriteriaResp_FuncNames{} + if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Criteria[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex diff --git a/event-processor/detector/api/tetragon/bpf.proto b/event-processor/detector/api/tetragon/bpf.proto index e74c4f3b..486c4ed3 100644 --- a/event-processor/detector/api/tetragon/bpf.proto +++ b/event-processor/detector/api/tetragon/bpf.proto @@ -5,180 +5,182 @@ syntax = "proto3"; package tetragon; +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; + enum BpfCmd { - /* Create a map and return a file descriptor that refers to the - map. */ - BPF_MAP_CREATE = 0; + /* Create a map and return a file descriptor that refers to the + map. */ + BPF_MAP_CREATE = 0; - /* Look up an element with a given key in the map referred to - by the file descriptor map_fd. */ - BPF_MAP_LOOKUP_ELEM = 1; + /* Look up an element with a given key in the map referred to + by the file descriptor map_fd. */ + BPF_MAP_LOOKUP_ELEM = 1; - /* Create or update an element (key/value pair) in a specified map. */ - BPF_MAP_UPDATE_ELEM = 2; + /* Create or update an element (key/value pair) in a specified map. */ + BPF_MAP_UPDATE_ELEM = 2; - /* Look up and delete an element by key in a specified map. */ - BPF_MAP_DELETE_ELEM = 3; + /* Look up and delete an element by key in a specified map. */ + BPF_MAP_DELETE_ELEM = 3; - /* Look up an element by key in a specified map and return the key - of the next element. Can be used to iterate over all elements - in the map. */ - BPF_MAP_GET_NEXT_KEY = 4; + /* Look up an element by key in a specified map and return the key + of the next element. Can be used to iterate over all elements + in the map. */ + BPF_MAP_GET_NEXT_KEY = 4; - /* Verify and load an eBPF program, returning a new file descriptor - associated with the program. */ - BPF_PROG_LOAD = 5; + /* Verify and load an eBPF program, returning a new file descriptor + associated with the program. */ + BPF_PROG_LOAD = 5; - /* Pin an eBPF program or map referred by the specified bpf_fd - to the provided pathname on the filesystem. */ - BPF_OBJ_PIN = 6; + /* Pin an eBPF program or map referred by the specified bpf_fd + to the provided pathname on the filesystem. */ + BPF_OBJ_PIN = 6; - /* Open a file descriptor for the eBPF object pinned to the - specified pathname. */ - BPF_OBJ_GET = 7; + /* Open a file descriptor for the eBPF object pinned to the + specified pathname. */ + BPF_OBJ_GET = 7; - /* Attach an eBPF program to a target_fd at the specified - attach_type hook. */ - BPF_PROG_ATTACH = 8; + /* Attach an eBPF program to a target_fd at the specified + attach_type hook. */ + BPF_PROG_ATTACH = 8; - /* Detach the eBPF program associated with the target_fd at the - hook specified by attach_type. */ - BPF_PROG_DETACH = 9; + /* Detach the eBPF program associated with the target_fd at the + hook specified by attach_type. */ + BPF_PROG_DETACH = 9; - /* Run the eBPF program associated with the prog_fd a repeat - number of times against a provided program context ctx_in and - data data_in, and return the modified program context - ctx_out, data_out (for example, packet data), result of the - execution retval, and duration of the test run. */ - BPF_PROG_TEST_RUN = 10; + /* Run the eBPF program associated with the prog_fd a repeat + number of times against a provided program context ctx_in and + data data_in, and return the modified program context + ctx_out, data_out (for example, packet data), result of the + execution retval, and duration of the test run. */ + BPF_PROG_TEST_RUN = 10; - /* Fetch the next eBPF program currently loaded into the kernel. */ - BPF_PROG_GET_NEXT_ID = 11; + /* Fetch the next eBPF program currently loaded into the kernel. */ + BPF_PROG_GET_NEXT_ID = 11; - /* Fetch the next eBPF map currently loaded into the kernel. */ - BPF_MAP_GET_NEXT_ID = 12; + /* Fetch the next eBPF map currently loaded into the kernel. */ + BPF_MAP_GET_NEXT_ID = 12; - /* Open a file descriptor for the eBPF program corresponding to prog_id. */ - BPF_PROG_GET_FD_BY_ID = 13; + /* Open a file descriptor for the eBPF program corresponding to prog_id. */ + BPF_PROG_GET_FD_BY_ID = 13; - /* Open a file descriptor for the eBPF map corresponding to map_id. */ - BPF_MAP_GET_FD_BY_ID = 14; + /* Open a file descriptor for the eBPF map corresponding to map_id. */ + BPF_MAP_GET_FD_BY_ID = 14; - /* Obtain information about the eBPF object corresponding to bpf_fd. */ - BPF_OBJ_GET_INFO_BY_FD = 15; + /* Obtain information about the eBPF object corresponding to bpf_fd. */ + BPF_OBJ_GET_INFO_BY_FD = 15; - /* Obtain information about eBPF programs associated with the specified - attach_type hook. */ - BPF_PROG_QUERY = 16; + /* Obtain information about eBPF programs associated with the specified + attach_type hook. */ + BPF_PROG_QUERY = 16; - /* Attach an eBPF program to a tracepoint *name* to access kernel - internal arguments of the tracepoint in their raw form. */ - BPF_RAW_TRACEPOINT_OPEN = 17; + /* Attach an eBPF program to a tracepoint *name* to access kernel + internal arguments of the tracepoint in their raw form. */ + BPF_RAW_TRACEPOINT_OPEN = 17; - /* Verify and load BPF Type Format (BTF) metadata into the kernel, - returning a new file descriptor associated with the metadata. */ - BPF_BTF_LOAD = 18; + /* Verify and load BPF Type Format (BTF) metadata into the kernel, + returning a new file descriptor associated with the metadata. */ + BPF_BTF_LOAD = 18; - /* Open a file descriptor for the BPF Type Format (BTF) - corresponding to btf_id. */ - BPF_BTF_GET_FD_BY_ID = 19; + /* Open a file descriptor for the BPF Type Format (BTF) + corresponding to btf_id. */ + BPF_BTF_GET_FD_BY_ID = 19; - /* Obtain information about eBPF programs associated with the target - process identified by pid and fd. */ - BPF_TASK_FD_QUERY = 20; + /* Obtain information about eBPF programs associated with the target + process identified by pid and fd. */ + BPF_TASK_FD_QUERY = 20; - /* Look up an element with the given key in the map referred to - by the file descriptor fd, and if found, delete the element. */ - BPF_MAP_LOOKUP_AND_DELETE_ELEM = 21; + /* Look up an element with the given key in the map referred to + by the file descriptor fd, and if found, delete the element. */ + BPF_MAP_LOOKUP_AND_DELETE_ELEM = 21; - /* Freeze the permissions of the specified map. */ - BPF_MAP_FREEZE = 22; + /* Freeze the permissions of the specified map. */ + BPF_MAP_FREEZE = 22; - /* Fetch the next BPF Type Format (BTF) object currently loaded into - the kernel. */ - BPF_BTF_GET_NEXT_ID = 23; + /* Fetch the next BPF Type Format (BTF) object currently loaded into + the kernel. */ + BPF_BTF_GET_NEXT_ID = 23; - /* Iterate and fetch multiple elements in a map. */ - BPF_MAP_LOOKUP_BATCH = 24; + /* Iterate and fetch multiple elements in a map. */ + BPF_MAP_LOOKUP_BATCH = 24; - /* Iterate and delete all elements in a map. */ - BPF_MAP_LOOKUP_AND_DELETE_BATCH = 25; + /* Iterate and delete all elements in a map. */ + BPF_MAP_LOOKUP_AND_DELETE_BATCH = 25; - /* Update multiple elements in a map by key. */ - BPF_MAP_UPDATE_BATCH = 26; + /* Update multiple elements in a map by key. */ + BPF_MAP_UPDATE_BATCH = 26; - /* Delete multiple elements in a map by key. */ - BPF_MAP_DELETE_BATCH = 27; + /* Delete multiple elements in a map by key. */ + BPF_MAP_DELETE_BATCH = 27; - /* Attach an eBPF program to a target_fd at the specified - attach_type hook and return a file descriptor handle for - managing the link. */ - BPF_LINK_CREATE = 28; + /* Attach an eBPF program to a target_fd at the specified + attach_type hook and return a file descriptor handle for + managing the link. */ + BPF_LINK_CREATE = 28; - /* Update the eBPF program in the specified link_fd to - new_prog_fd. */ - BPF_LINK_UPDATE = 29; + /* Update the eBPF program in the specified link_fd to + new_prog_fd. */ + BPF_LINK_UPDATE = 29; - /* Open a file descriptor for the eBPF Link corresponding to - link_id. */ - BPF_LINK_GET_FD_BY_ID = 30; + /* Open a file descriptor for the eBPF Link corresponding to + link_id. */ + BPF_LINK_GET_FD_BY_ID = 30; - /* Fetch the next eBPF link currently loaded into the kernel. */ - BPF_LINK_GET_NEXT_ID = 31; + /* Fetch the next eBPF link currently loaded into the kernel. */ + BPF_LINK_GET_NEXT_ID = 31; - /* Enable eBPF runtime statistics gathering. */ - BPF_ENABLE_STATS = 32; + /* Enable eBPF runtime statistics gathering. */ + BPF_ENABLE_STATS = 32; - /* Create an iterator on top of the specified link_fd (as - previously created using BPF_LINK_CREATE) and return a - file descriptor that can be used to trigger the iteration. */ - BPF_ITER_CREATE = 33; + /* Create an iterator on top of the specified link_fd (as + previously created using BPF_LINK_CREATE) and return a + file descriptor that can be used to trigger the iteration. */ + BPF_ITER_CREATE = 33; - /* Forcefully detach the specified link_fd from its corresponding - attachment point. */ - BPF_LINK_DETACH = 34; + /* Forcefully detach the specified link_fd from its corresponding + attachment point. */ + BPF_LINK_DETACH = 34; - /* Bind a map to the lifetime of an eBPF program. */ - BPF_PROG_BIND_MAP = 35; + /* Bind a map to the lifetime of an eBPF program. */ + BPF_PROG_BIND_MAP = 35; - /* Create BPF token with embedded information about what can be - passed as an extra parameter to various bpf() syscall commands - to grant BPF subsystem functionality to unprivileged processes. */ - BPF_TOKEN_CREATE = 36; + /* Create BPF token with embedded information about what can be + passed as an extra parameter to various bpf() syscall commands + to grant BPF subsystem functionality to unprivileged processes. */ + BPF_TOKEN_CREATE = 36; } enum BpfProgramType { - BPF_PROG_TYPE_UNSPEC = 0; - BPF_PROG_TYPE_SOCKET_FILTER = 1; - BPF_PROG_TYPE_KPROBE = 2; - BPF_PROG_TYPE_SCHED_CLS = 3; - BPF_PROG_TYPE_SCHED_ACT = 4; - BPF_PROG_TYPE_TRACEPOINT = 5; - BPF_PROG_TYPE_XDP = 6; - BPF_PROG_TYPE_PERF_EVENT = 7; - BPF_PROG_TYPE_CGROUP_SKB = 8; - BPF_PROG_TYPE_CGROUP_SOCK = 9; - BPF_PROG_TYPE_LWT_IN = 10; - BPF_PROG_TYPE_LWT_OUT = 11; - BPF_PROG_TYPE_LWT_XMIT = 12; - BPF_PROG_TYPE_SOCK_OPS = 13; - BPF_PROG_TYPE_SK_SKB = 14; - BPF_PROG_TYPE_CGROUP_DEVICE = 15; - BPF_PROG_TYPE_SK_MSG = 16; - BPF_PROG_TYPE_RAW_TRACEPOINT = 17; - BPF_PROG_TYPE_CGROUP_SOCK_ADDR = 18; - BPF_PROG_TYPE_LWT_SEG6LOCAL = 19; - BPF_PROG_TYPE_LIRC_MODE2 = 20; - BPF_PROG_TYPE_SK_REUSEPORT = 21; - BPF_PROG_TYPE_FLOW_DISSECTOR = 22; - BPF_PROG_TYPE_CGROUP_SYSCTL = 23; - BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE = 24; - BPF_PROG_TYPE_CGROUP_SOCKOPT = 25; - BPF_PROG_TYPE_TRACING = 26; - BPF_PROG_TYPE_STRUCT_OPS = 27; - BPF_PROG_TYPE_EXT = 28; - BPF_PROG_TYPE_LSM = 29; - BPF_PROG_TYPE_SK_LOOKUP = 30; - BPF_PROG_TYPE_SYSCALL = 31; - BPF_PROG_TYPE_NETFILTER = 32; -}; + BPF_PROG_TYPE_UNSPEC = 0; + BPF_PROG_TYPE_SOCKET_FILTER = 1; + BPF_PROG_TYPE_KPROBE = 2; + BPF_PROG_TYPE_SCHED_CLS = 3; + BPF_PROG_TYPE_SCHED_ACT = 4; + BPF_PROG_TYPE_TRACEPOINT = 5; + BPF_PROG_TYPE_XDP = 6; + BPF_PROG_TYPE_PERF_EVENT = 7; + BPF_PROG_TYPE_CGROUP_SKB = 8; + BPF_PROG_TYPE_CGROUP_SOCK = 9; + BPF_PROG_TYPE_LWT_IN = 10; + BPF_PROG_TYPE_LWT_OUT = 11; + BPF_PROG_TYPE_LWT_XMIT = 12; + BPF_PROG_TYPE_SOCK_OPS = 13; + BPF_PROG_TYPE_SK_SKB = 14; + BPF_PROG_TYPE_CGROUP_DEVICE = 15; + BPF_PROG_TYPE_SK_MSG = 16; + BPF_PROG_TYPE_RAW_TRACEPOINT = 17; + BPF_PROG_TYPE_CGROUP_SOCK_ADDR = 18; + BPF_PROG_TYPE_LWT_SEG6LOCAL = 19; + BPF_PROG_TYPE_LIRC_MODE2 = 20; + BPF_PROG_TYPE_SK_REUSEPORT = 21; + BPF_PROG_TYPE_FLOW_DISSECTOR = 22; + BPF_PROG_TYPE_CGROUP_SYSCTL = 23; + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE = 24; + BPF_PROG_TYPE_CGROUP_SOCKOPT = 25; + BPF_PROG_TYPE_TRACING = 26; + BPF_PROG_TYPE_STRUCT_OPS = 27; + BPF_PROG_TYPE_EXT = 28; + BPF_PROG_TYPE_LSM = 29; + BPF_PROG_TYPE_SK_LOOKUP = 30; + BPF_PROG_TYPE_SYSCALL = 31; + BPF_PROG_TYPE_NETFILTER = 32; +} diff --git a/event-processor/detector/api/tetragon/capabilities.proto b/event-processor/detector/api/tetragon/capabilities.proto index c453a534..032e16c8 100644 --- a/event-processor/detector/api/tetragon/capabilities.proto +++ b/event-processor/detector/api/tetragon/capabilities.proto @@ -5,345 +5,347 @@ syntax = "proto3"; package tetragon; +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; + enum CapabilitiesType { - /* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this - overrides the restriction of changing file ownership and group - ownership. */ - CAP_CHOWN = 0; - /* Override all DAC access, including ACL execute access if - [_POSIX_ACL] is defined. Excluding DAC access covered by - CAP_LINUX_IMMUTABLE. */ - DAC_OVERRIDE = 1; - - /* Overrides all DAC restrictions regarding read and search on files - and directories, including ACL restrictions if [_POSIX_ACL] is - defined. Excluding DAC access covered by "$1"_LINUX_IMMUTABLE. */ - CAP_DAC_READ_SEARCH = 2; - - /* Overrides all restrictions about allowed operations on files, where - file owner ID must be equal to the user ID, except where CAP_FSETID - is applicable. It doesn't override MAC and DAC restrictions. */ - CAP_FOWNER = 3; - - /* Overrides the following restrictions that the effective user ID - shall match the file owner ID when setting the S_ISUID and S_ISGID - bits on that file; that the effective group ID (or one of the - supplementary group IDs) shall match the file owner ID when setting - the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are - cleared on successful return from chown(2) (not implemented). */ - CAP_FSETID = 4; - - /* Overrides the restriction that the real or effective user ID of a - process sending a signal must match the real or effective user ID - of the process receiving the signal. */ - CAP_KILL = 5; - - /* Allows setgid(2) manipulation */ - /* Allows setgroups(2) */ - /* Allows forged gids on socket credentials passing. */ - CAP_SETGID = 6; - - /* Allows set*uid(2) manipulation (including fsuid). */ - /* Allows forged pids on socket credentials passing. */ - CAP_SETUID = 7; - - /** - ** Linux-specific capabilities - **/ - - /* Without VFS support for capabilities: - * Transfer any capability in your permitted set to any pid, - * remove any capability in your permitted set from any pid - * With VFS support for capabilities (neither of above, but) - * Add any capability from current's capability bounding set - * to the current process' inheritable set - * Allow taking bits out of capability bounding set - * Allow modification of the securebits for a process - */ - CAP_SETPCAP = 8; - - /* Allow modification of S_IMMUTABLE and S_APPEND file attributes */ - CAP_LINUX_IMMUTABLE = 9; - - /* Allows binding to TCP/UDP sockets below 1024 */ - /* Allows binding to ATM VCIs below 32 */ - CAP_NET_BIND_SERVICE = 10; - - /* Allow broadcasting, listen to multicast */ - CAP_NET_BROADCAST = 11; - - /* Allow interface configuration */ - /* Allow administration of IP firewall, masquerading and accounting */ - /* Allow setting debug option on sockets */ - /* Allow modification of routing tables */ - /* Allow setting arbitrary process / process group ownership on - sockets */ - /* Allow binding to any address for transparent proxying (also via NET_RAW) */ - /* Allow setting TOS (type of service) */ - /* Allow setting promiscuous mode */ - /* Allow clearing driver statistics */ - /* Allow multicasting */ - /* Allow read/write of device-specific registers */ - /* Allow activation of ATM control sockets */ - CAP_NET_ADMIN = 12; - - /* Allow use of RAW sockets */ - /* Allow use of PACKET sockets */ - /* Allow binding to any address for transparent proxying (also via NET_ADMIN) */ - CAP_NET_RAW = 13; - - /* Allow locking of shared memory segments */ - /* Allow mlock and mlockall (which doesn't really have anything to do - with IPC) */ - CAP_IPC_LOCK = 14; - - /* Override IPC ownership checks */ - CAP_IPC_OWNER = 15; - - /* Insert and remove kernel modules - modify kernel without limit */ - CAP_SYS_MODULE = 16; - - /* Allow ioperm/iopl access */ - /* Allow sending USB messages to any device via /dev/bus/usb */ - CAP_SYS_RAWIO = 17; - - /* Allow use of chroot() */ - CAP_SYS_CHROOT = 18; - - /* Allow ptrace() of any process */ - CAP_SYS_PTRACE = 19; - /* Allow configuration of process accounting */ - CAP_SYS_PACCT = 20; - - /* Allow configuration of the secure attention key */ - /* Allow administration of the random device */ - /* Allow examination and configuration of disk quotas */ - /* Allow setting the domainname */ - /* Allow setting the hostname */ - /* Allow calling bdflush() */ - /* Allow mount() and umount(), setting up new smb connection */ - /* Allow some autofs root ioctls */ - /* Allow nfsservctl */ - /* Allow VM86_REQUEST_IRQ */ - /* Allow to read/write pci config on alpha */ - /* Allow irix_prctl on mips (setstacksize) */ - /* Allow flushing all cache on m68k (sys_cacheflush) */ - /* Allow removing semaphores */ - /* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores and shared memory */ - /* Allow locking/unlocking of shared memory segment */ - /* Allow turning swap on/off */ - /* Allow forged pids on socket credentials passing */ - /* Allow setting readahead and flushing buffers on block devices */ - /* Allow setting geometry in floppy driver */ - /* Allow turning DMA on/off in xd driver */ - /* Allow administration of md devices (mostly the above, but some extra ioctls) */ - /* Allow tuning the ide driver */ - /* Allow access to the nvram device */ - /* Allow administration of apm_bios, serial and bttv (TV) device */ - /* Allow manufacturer commands in isdn CAPI support driver */ - /* Allow reading non-standardized portions of pci configuration space */ - /* Allow DDI debug ioctl on sbpcd driver */ - /* Allow setting up serial ports */ - /* Allow sending raw qic-117 commands */ - /* Allow enabling/disabling tagged queuing on SCSI controllers and sending - arbitrary SCSI commands */ - /* Allow setting encryption key on loopback filesystem */ - /* Allow setting zone reclaim policy */ - /* Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility */ - CAP_SYS_ADMIN = 21; - - /* Allow use of reboot() */ - CAP_SYS_BOOT = 22; - - /* Allow raising priority and setting priority on other (different - UID) processes */ - /* Allow use of FIFO and round-robin (realtime) scheduling on own - processes and setting the scheduling algorithm used by another - process. */ - /* Allow setting cpu affinity on other processes */ - CAP_SYS_NICE = 23; - - /* Override resource limits. Set resource limits. */ - /* Override quota limits. */ - /* Override reserved space on ext2 filesystem */ - /* Modify data journaling mode on ext3 filesystem (uses journaling - resources) */ - /* ext2 honors fsuid when checking for resource overrides, so - you can override using fsuid too */ - /* Override size restrictions on IPC message queues */ - /* Allow more than 64hz interrupts from the real-time clock */ - /* Override max number of consoles on console allocation */ - /* Override max number of keymaps */ - /* Control memory reclaim behavior */ - CAP_SYS_RESOURCE = 24; - - /* Allow manipulation of system clock */ - /* Allow irix_stime on mips */ - /* Allow setting the real-time clock */ - CAP_SYS_TIME = 25; - - /* Allow configuration of tty devices */ - /* Allow vhangup() of tty */ - CAP_SYS_TTY_CONFIG = 26; - - /* Allow the privileged aspects of mknod() */ - CAP_MKNOD = 27; - - /* Allow taking of leases on files */ - CAP_LEASE = 28; - - /* Allow writing the audit log via unicast netlink socket */ - CAP_AUDIT_WRITE = 29; - - /* Allow configuration of audit via unicast netlink socket */ - CAP_AUDIT_CONTROL = 30; - - /* Set or remove capabilities on files */ - CAP_SETFCAP = 31; - - /* Override MAC access. - The base kernel enforces no MAC policy. - An LSM may enforce a MAC policy, and if it does and it chooses - to implement capability based overrides of that policy, this is - the capability it should use to do so. */ - CAP_MAC_OVERRIDE = 32; - - /* Allow MAC configuration or state changes. - The base kernel requires no MAC configuration. - An LSM may enforce a MAC policy, and if it does and it chooses - to implement capability based checks on modifications to that - policy or the data required to maintain it, this is the - capability it should use to do so. */ - CAP_MAC_ADMIN = 33; - - /* Allow configuring the kernel's syslog (printk behaviour) */ - CAP_SYSLOG = 34; - - /* Allow triggering something that will wake the system */ - CAP_WAKE_ALARM = 35; - - /* Allow preventing system suspends */ - CAP_BLOCK_SUSPEND = 36; - - /* Allow reading the audit log via multicast netlink socket */ - CAP_AUDIT_READ = 37; - - /* - * Allow system performance and observability privileged operations - * using perf_events, i915_perf and other kernel subsystems - */ - CAP_PERFMON = 38; - - /* - * CAP_BPF allows the following BPF operations: - * - Creating all types of BPF maps - * - Advanced verifier features - * - Indirect variable access - * - Bounded loops - * - BPF to BPF function calls - * - Scalar precision tracking - * - Larger complexity limits - * - Dead code elimination - * - And potentially other features - * - Loading BPF Type Format (BTF) data - * - Retrieve xlated and JITed code of BPF programs - * - Use bpf_spin_lock() helper - * CAP_PERFMON relaxes the verifier checks further: - * - BPF progs can use of pointer-to-integer conversions - * - speculation attack hardening measures are bypassed - * - bpf_probe_read to read arbitrary kernel memory is allowed - * - bpf_trace_printk to print kernel memory is allowed - * CAP_SYS_ADMIN is required to use bpf_probe_write_user. - * CAP_SYS_ADMIN is required to iterate system wide loaded - * programs, maps, links, BTFs and convert their IDs to file descriptors. - * CAP_PERFMON and CAP_BPF are required to load tracing programs. - * CAP_NET_ADMIN and CAP_BPF are required to load networking programs. - */ - CAP_BPF = 39; - - /* Allow checkpoint/restore related operations */ - /* Allow PID selection during clone3() */ - /* Allow writing to ns_last_pid */ - CAP_CHECKPOINT_RESTORE = 40; + /* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this + overrides the restriction of changing file ownership and group + ownership. */ + CAP_CHOWN = 0; + /* Override all DAC access, including ACL execute access if + [_POSIX_ACL] is defined. Excluding DAC access covered by + CAP_LINUX_IMMUTABLE. */ + DAC_OVERRIDE = 1; + + /* Overrides all DAC restrictions regarding read and search on files + and directories, including ACL restrictions if [_POSIX_ACL] is + defined. Excluding DAC access covered by "$1"_LINUX_IMMUTABLE. */ + CAP_DAC_READ_SEARCH = 2; + + /* Overrides all restrictions about allowed operations on files, where + file owner ID must be equal to the user ID, except where CAP_FSETID + is applicable. It doesn't override MAC and DAC restrictions. */ + CAP_FOWNER = 3; + + /* Overrides the following restrictions that the effective user ID + shall match the file owner ID when setting the S_ISUID and S_ISGID + bits on that file; that the effective group ID (or one of the + supplementary group IDs) shall match the file owner ID when setting + the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are + cleared on successful return from chown(2) (not implemented). */ + CAP_FSETID = 4; + + /* Overrides the restriction that the real or effective user ID of a + process sending a signal must match the real or effective user ID + of the process receiving the signal. */ + CAP_KILL = 5; + + /* Allows setgid(2) manipulation */ + /* Allows setgroups(2) */ + /* Allows forged gids on socket credentials passing. */ + CAP_SETGID = 6; + + /* Allows set*uid(2) manipulation (including fsuid). */ + /* Allows forged pids on socket credentials passing. */ + CAP_SETUID = 7; + + /** + ** Linux-specific capabilities + **/ + + /* Without VFS support for capabilities: + * Transfer any capability in your permitted set to any pid, + * remove any capability in your permitted set from any pid + * With VFS support for capabilities (neither of above, but) + * Add any capability from current's capability bounding set + * to the current process' inheritable set + * Allow taking bits out of capability bounding set + * Allow modification of the securebits for a process + */ + CAP_SETPCAP = 8; + + /* Allow modification of S_IMMUTABLE and S_APPEND file attributes */ + CAP_LINUX_IMMUTABLE = 9; + + /* Allows binding to TCP/UDP sockets below 1024 */ + /* Allows binding to ATM VCIs below 32 */ + CAP_NET_BIND_SERVICE = 10; + + /* Allow broadcasting, listen to multicast */ + CAP_NET_BROADCAST = 11; + + /* Allow interface configuration */ + /* Allow administration of IP firewall, masquerading and accounting */ + /* Allow setting debug option on sockets */ + /* Allow modification of routing tables */ + /* Allow setting arbitrary process / process group ownership on + sockets */ + /* Allow binding to any address for transparent proxying (also via NET_RAW) */ + /* Allow setting TOS (type of service) */ + /* Allow setting promiscuous mode */ + /* Allow clearing driver statistics */ + /* Allow multicasting */ + /* Allow read/write of device-specific registers */ + /* Allow activation of ATM control sockets */ + CAP_NET_ADMIN = 12; + + /* Allow use of RAW sockets */ + /* Allow use of PACKET sockets */ + /* Allow binding to any address for transparent proxying (also via NET_ADMIN) */ + CAP_NET_RAW = 13; + + /* Allow locking of shared memory segments */ + /* Allow mlock and mlockall (which doesn't really have anything to do + with IPC) */ + CAP_IPC_LOCK = 14; + + /* Override IPC ownership checks */ + CAP_IPC_OWNER = 15; + + /* Insert and remove kernel modules - modify kernel without limit */ + CAP_SYS_MODULE = 16; + + /* Allow ioperm/iopl access */ + /* Allow sending USB messages to any device via /dev/bus/usb */ + CAP_SYS_RAWIO = 17; + + /* Allow use of chroot() */ + CAP_SYS_CHROOT = 18; + + /* Allow ptrace() of any process */ + CAP_SYS_PTRACE = 19; + /* Allow configuration of process accounting */ + CAP_SYS_PACCT = 20; + + /* Allow configuration of the secure attention key */ + /* Allow administration of the random device */ + /* Allow examination and configuration of disk quotas */ + /* Allow setting the domainname */ + /* Allow setting the hostname */ + /* Allow calling bdflush() */ + /* Allow mount() and umount(), setting up new smb connection */ + /* Allow some autofs root ioctls */ + /* Allow nfsservctl */ + /* Allow VM86_REQUEST_IRQ */ + /* Allow to read/write pci config on alpha */ + /* Allow irix_prctl on mips (setstacksize) */ + /* Allow flushing all cache on m68k (sys_cacheflush) */ + /* Allow removing semaphores */ + /* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores and shared memory */ + /* Allow locking/unlocking of shared memory segment */ + /* Allow turning swap on/off */ + /* Allow forged pids on socket credentials passing */ + /* Allow setting readahead and flushing buffers on block devices */ + /* Allow setting geometry in floppy driver */ + /* Allow turning DMA on/off in xd driver */ + /* Allow administration of md devices (mostly the above, but some extra ioctls) */ + /* Allow tuning the ide driver */ + /* Allow access to the nvram device */ + /* Allow administration of apm_bios, serial and bttv (TV) device */ + /* Allow manufacturer commands in isdn CAPI support driver */ + /* Allow reading non-standardized portions of pci configuration space */ + /* Allow DDI debug ioctl on sbpcd driver */ + /* Allow setting up serial ports */ + /* Allow sending raw qic-117 commands */ + /* Allow enabling/disabling tagged queuing on SCSI controllers and sending + arbitrary SCSI commands */ + /* Allow setting encryption key on loopback filesystem */ + /* Allow setting zone reclaim policy */ + /* Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility */ + CAP_SYS_ADMIN = 21; + + /* Allow use of reboot() */ + CAP_SYS_BOOT = 22; + + /* Allow raising priority and setting priority on other (different + UID) processes */ + /* Allow use of FIFO and round-robin (realtime) scheduling on own + processes and setting the scheduling algorithm used by another + process. */ + /* Allow setting cpu affinity on other processes */ + CAP_SYS_NICE = 23; + + /* Override resource limits. Set resource limits. */ + /* Override quota limits. */ + /* Override reserved space on ext2 filesystem */ + /* Modify data journaling mode on ext3 filesystem (uses journaling + resources) */ + /* ext2 honors fsuid when checking for resource overrides, so + you can override using fsuid too */ + /* Override size restrictions on IPC message queues */ + /* Allow more than 64hz interrupts from the real-time clock */ + /* Override max number of consoles on console allocation */ + /* Override max number of keymaps */ + /* Control memory reclaim behavior */ + CAP_SYS_RESOURCE = 24; + + /* Allow manipulation of system clock */ + /* Allow irix_stime on mips */ + /* Allow setting the real-time clock */ + CAP_SYS_TIME = 25; + + /* Allow configuration of tty devices */ + /* Allow vhangup() of tty */ + CAP_SYS_TTY_CONFIG = 26; + + /* Allow the privileged aspects of mknod() */ + CAP_MKNOD = 27; + + /* Allow taking of leases on files */ + CAP_LEASE = 28; + + /* Allow writing the audit log via unicast netlink socket */ + CAP_AUDIT_WRITE = 29; + + /* Allow configuration of audit via unicast netlink socket */ + CAP_AUDIT_CONTROL = 30; + + /* Set or remove capabilities on files */ + CAP_SETFCAP = 31; + + /* Override MAC access. + The base kernel enforces no MAC policy. + An LSM may enforce a MAC policy, and if it does and it chooses + to implement capability based overrides of that policy, this is + the capability it should use to do so. */ + CAP_MAC_OVERRIDE = 32; + + /* Allow MAC configuration or state changes. + The base kernel requires no MAC configuration. + An LSM may enforce a MAC policy, and if it does and it chooses + to implement capability based checks on modifications to that + policy or the data required to maintain it, this is the + capability it should use to do so. */ + CAP_MAC_ADMIN = 33; + + /* Allow configuring the kernel's syslog (printk behaviour) */ + CAP_SYSLOG = 34; + + /* Allow triggering something that will wake the system */ + CAP_WAKE_ALARM = 35; + + /* Allow preventing system suspends */ + CAP_BLOCK_SUSPEND = 36; + + /* Allow reading the audit log via multicast netlink socket */ + CAP_AUDIT_READ = 37; + + /* + * Allow system performance and observability privileged operations + * using perf_events, i915_perf and other kernel subsystems + */ + CAP_PERFMON = 38; + + /* + * CAP_BPF allows the following BPF operations: + * - Creating all types of BPF maps + * - Advanced verifier features + * - Indirect variable access + * - Bounded loops + * - BPF to BPF function calls + * - Scalar precision tracking + * - Larger complexity limits + * - Dead code elimination + * - And potentially other features + * - Loading BPF Type Format (BTF) data + * - Retrieve xlated and JITed code of BPF programs + * - Use bpf_spin_lock() helper + * CAP_PERFMON relaxes the verifier checks further: + * - BPF progs can use of pointer-to-integer conversions + * - speculation attack hardening measures are bypassed + * - bpf_probe_read to read arbitrary kernel memory is allowed + * - bpf_trace_printk to print kernel memory is allowed + * CAP_SYS_ADMIN is required to use bpf_probe_write_user. + * CAP_SYS_ADMIN is required to iterate system wide loaded + * programs, maps, links, BTFs and convert their IDs to file descriptors. + * CAP_PERFMON and CAP_BPF are required to load tracing programs. + * CAP_NET_ADMIN and CAP_BPF are required to load networking programs. + */ + CAP_BPF = 39; + + /* Allow checkpoint/restore related operations */ + /* Allow PID selection during clone3() */ + /* Allow writing to ns_last_pid */ + CAP_CHECKPOINT_RESTORE = 40; } enum SecureBitsType { - SecBitNotSet = 0; - - /* When set UID 0 has no special privileges. When unset, inheritance - of root-permissions and suid-root executable under compatibility mode - is supported. If the effective uid of the new process is 0 then - the effective and inheritable bitmasks of the executable file is raised. - If the real uid is 0, the effective (legacy) bit of the executable file - is raised. */ - SecBitNoRoot = 1; - - /* Make bit-0 SecBitNoRoot immutable */ - SecBitNoRootLocked = 2; - - /* When set, setuid to/from uid 0 does not trigger capability-"fixup". - When unset, to provide compatiblility with old programs relying on - set*uid to gain/lose privilege, transitions to/from uid 0 cause - capabilities to be gained/lost. */ - SecBitNoSetUidFixup = 4; - - /* Make bit-2 SecBitNoSetUidFixup immutable */ - SecBitNoSetUidFixupLocked = 8; - - /* When set, a process can retain its capabilities even after - transitioning to a non-root user (the set-uid fixup suppressed by - bit 2). Bit-4 is cleared when a process calls exec(); setting both - bit 4 and 5 will create a barrier through exec that no exec()'d - child can use this feature again. */ - SecBitKeepCaps = 16; - - /* Make bit-4 SecBitKeepCaps immutable */ - SecBitKeepCapsLocked = 32; - - /* When set, a process cannot add new capabilities to its ambient set. */ - SecBitNoCapAmbientRaise = 64; - - /* Make bit-6 SecBitNoCapAmbientRaise immutable */ - SecBitNoCapAmbientRaiseLocked = 128; + SecBitNotSet = 0; + + /* When set UID 0 has no special privileges. When unset, inheritance + of root-permissions and suid-root executable under compatibility mode + is supported. If the effective uid of the new process is 0 then + the effective and inheritable bitmasks of the executable file is raised. + If the real uid is 0, the effective (legacy) bit of the executable file + is raised. */ + SecBitNoRoot = 1; + + /* Make bit-0 SecBitNoRoot immutable */ + SecBitNoRootLocked = 2; + + /* When set, setuid to/from uid 0 does not trigger capability-"fixup". + When unset, to provide compatiblility with old programs relying on + set*uid to gain/lose privilege, transitions to/from uid 0 cause + capabilities to be gained/lost. */ + SecBitNoSetUidFixup = 4; + + /* Make bit-2 SecBitNoSetUidFixup immutable */ + SecBitNoSetUidFixupLocked = 8; + + /* When set, a process can retain its capabilities even after + transitioning to a non-root user (the set-uid fixup suppressed by + bit 2). Bit-4 is cleared when a process calls exec(); setting both + bit 4 and 5 will create a barrier through exec that no exec()'d + child can use this feature again. */ + SecBitKeepCaps = 16; + + /* Make bit-4 SecBitKeepCaps immutable */ + SecBitKeepCapsLocked = 32; + + /* When set, a process cannot add new capabilities to its ambient set. */ + SecBitNoCapAmbientRaise = 64; + + /* Make bit-6 SecBitNoCapAmbientRaise immutable */ + SecBitNoCapAmbientRaiseLocked = 128; } // Reasons of why the process privileges changed. enum ProcessPrivilegesChanged { - PRIVILEGES_CHANGED_UNSET = 0; - - // A privilege elevation happened due to the execution of a binary with file capability sets. - // The kernel supports associating capability sets with an executable file using `setcap` command. - // The file capability sets are stored in an extended attribute (see https://man7.org/linux/man-pages/man7/xattr.7.html) - // named `security.capability`. The file capability sets, in conjunction with the capability sets - // of the process, determine the process capabilities and privileges after the `execve` system call. - // For further reference, please check sections `File capability extended attribute versioning` and - // `Namespaced file capabilities` of the capabilities man pages: https://man7.org/linux/man-pages/man7/capabilities.7.html. - // The new granted capabilities can be listed inside the `process` object. - PRIVILEGES_RAISED_EXEC_FILE_CAP = 1; - - // A privilege elevation happened due to the execution of a binary with set-user-ID to root. - // When a process with nonzero UIDs executes a binary with a set-user-ID to root also - // known as suid-root executable, then the kernel switches the effective user ID to 0 (root) which - // is a privilege elevation operation since it grants access to resources owned by the root user. - // The effective user ID is listed inside the `process_credentials` part of the `process` object. - // For further reading, section `Capabilities and execution of programs by root` of https://man7.org/linux/man-pages/man7/capabilities.7.html. - // Afterward the kernel recalculates the capability sets of the process and grants all capabilities - // in the permitted and effective capability sets, except those masked out by the capability bounding set. - // If the binary also have file capability sets then these bits are honored and the process gains just - // the capabilities granted by the file capability sets (i.e., not all capabilities, as it would occur - // when executing a set-user-ID to root binary that does not have any associated file capabilities). This - // is described in section `Set-user-ID-root programs that have file capabilities` of https://man7.org/linux/man-pages/man7/capabilities.7.html. - // The new granted capabilities can be listed inside the `process` object. - // There is one exception for the special treatments of set-user-ID to root execution receiving all - // capabilities, if the `SecBitNoRoot` bit of the Secure bits is set, then the kernel does not grant - // any capability. Please check section: `The securebits flags: establishing a capabilities-only environment` - // of the capabilities man pages: https://man7.org/linux/man-pages/man7/capabilities.7.html - PRIVILEGES_RAISED_EXEC_FILE_SETUID = 2; - - // A privilege elevation happened due to the execution of a binary with set-group-ID to root. - // When a process with nonzero GIDs executes a binary with a set-group-ID to root, the kernel switches - // the effective group ID to 0 (root) which is a privilege elevation operation since it grants access to - // resources owned by the root group. - // The effective group ID is listed inside the `process_credentials` part of the `process` object. - PRIVILEGES_RAISED_EXEC_FILE_SETGID = 3; + PRIVILEGES_CHANGED_UNSET = 0; + + // A privilege elevation happened due to the execution of a binary with file capability sets. + // The kernel supports associating capability sets with an executable file using `setcap` command. + // The file capability sets are stored in an extended attribute (see https://man7.org/linux/man-pages/man7/xattr.7.html) + // named `security.capability`. The file capability sets, in conjunction with the capability sets + // of the process, determine the process capabilities and privileges after the `execve` system call. + // For further reference, please check sections `File capability extended attribute versioning` and + // `Namespaced file capabilities` of the capabilities man pages: https://man7.org/linux/man-pages/man7/capabilities.7.html. + // The new granted capabilities can be listed inside the `process` object. + PRIVILEGES_RAISED_EXEC_FILE_CAP = 1; + + // A privilege elevation happened due to the execution of a binary with set-user-ID to root. + // When a process with nonzero UIDs executes a binary with a set-user-ID to root also + // known as suid-root executable, then the kernel switches the effective user ID to 0 (root) which + // is a privilege elevation operation since it grants access to resources owned by the root user. + // The effective user ID is listed inside the `process_credentials` part of the `process` object. + // For further reading, section `Capabilities and execution of programs by root` of https://man7.org/linux/man-pages/man7/capabilities.7.html. + // Afterward the kernel recalculates the capability sets of the process and grants all capabilities + // in the permitted and effective capability sets, except those masked out by the capability bounding set. + // If the binary also have file capability sets then these bits are honored and the process gains just + // the capabilities granted by the file capability sets (i.e., not all capabilities, as it would occur + // when executing a set-user-ID to root binary that does not have any associated file capabilities). This + // is described in section `Set-user-ID-root programs that have file capabilities` of https://man7.org/linux/man-pages/man7/capabilities.7.html. + // The new granted capabilities can be listed inside the `process` object. + // There is one exception for the special treatments of set-user-ID to root execution receiving all + // capabilities, if the `SecBitNoRoot` bit of the Secure bits is set, then the kernel does not grant + // any capability. Please check section: `The securebits flags: establishing a capabilities-only environment` + // of the capabilities man pages: https://man7.org/linux/man-pages/man7/capabilities.7.html + PRIVILEGES_RAISED_EXEC_FILE_SETUID = 2; + + // A privilege elevation happened due to the execution of a binary with set-group-ID to root. + // When a process with nonzero GIDs executes a binary with a set-group-ID to root, the kernel switches + // the effective group ID to 0 (root) which is a privilege elevation operation since it grants access to + // resources owned by the root group. + // The effective group ID is listed inside the `process_credentials` part of the `process` object. + PRIVILEGES_RAISED_EXEC_FILE_SETGID = 3; } diff --git a/event-processor/detector/api/tetragon/events.pb.go b/event-processor/detector/api/tetragon/events.pb.go index c00799f7..9b0349dd 100644 --- a/event-processor/detector/api/tetragon/events.pb.go +++ b/event-processor/detector/api/tetragon/events.pb.go @@ -180,6 +180,8 @@ type Filter struct { // for processes injected into a container via docker exec, kubectl exec, or // similar mechanisms. InInitTree *wrapperspb.BoolValue `protobuf:"bytes,16,opt,name=in_init_tree,json=inInitTree,proto3" json:"in_init_tree,omitempty"` + // Filter ancestor processes' binaries using RE2 regular expression syntax. + AncestorBinaryRegex []string `protobuf:"bytes,17,rep,name=ancestor_binary_regex,json=ancestorBinaryRegex,proto3" json:"ancestor_binary_regex,omitempty"` } func (x *Filter) ProtoReflect() protoreflect.Message { @@ -298,6 +300,13 @@ func (x *Filter) GetInInitTree() *wrapperspb.BoolValue { return nil } +func (x *Filter) GetAncestorBinaryRegex() []string { + if x != nil { + return x.AncestorBinaryRegex + } + return nil +} + // Filter over a set of Linux process capabilities. See `message Capabilities` // for more info. WARNING: Multiple sets are ANDed. For example, if the // permitted filter matches, but the effective filter does not, the filter will @@ -563,6 +572,8 @@ type GetEventsResponse struct { AggregationInfo *AggregationInfo `protobuf:"bytes,1002,opt,name=aggregation_info,json=aggregationInfo,proto3" json:"aggregation_info,omitempty"` // Name of the cluster where this event was observed. ClusterName string `protobuf:"bytes,1003,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` + // Labels associated with the node where this event was observed. + NodeLabels map[string]string `protobuf:"bytes,1004,rep,name=node_labels,json=nodeLabels,proto3" json:"node_labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { @@ -674,6 +685,13 @@ func (x *GetEventsResponse) GetClusterName() string { return "" } +func (x *GetEventsResponse) GetNodeLabels() map[string]string { + if x != nil { + return x.NodeLabels + } + return nil +} + type isGetEventsResponse_Event interface { isGetEventsResponse_Event() } diff --git a/event-processor/detector/api/tetragon/events.proto b/event-processor/detector/api/tetragon/events.proto index 1e9d2f70..da495e36 100644 --- a/event-processor/detector/api/tetragon/events.proto +++ b/event-processor/detector/api/tetragon/events.proto @@ -5,76 +5,80 @@ syntax = "proto3"; package tetragon; -import "tetragon/tetragon.proto"; -import "tetragon/capabilities.proto"; import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "google/protobuf/timestamp.proto"; import "google/protobuf/field_mask.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "tetragon/capabilities.proto"; +import "tetragon/tetragon.proto"; + +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; // Represents the type of a Tetragon event. // // NOTE: EventType constants must be in sync with the numbers used in the // GetEventsResponse event oneof. enum EventType { - reserved 2 to 4, 6 to 8, 13 to 26; - UNDEF = 0; - - PROCESS_EXEC = 1; - PROCESS_EXIT = 5; - PROCESS_KPROBE = 9; - PROCESS_TRACEPOINT = 10; - PROCESS_LOADER = 11; - PROCESS_UPROBE = 12; - PROCESS_THROTTLE = 27; - PROCESS_LSM = 28; - - TEST = 40000; - RATE_LIMIT_INFO = 40001; + reserved 2 to 4, 6 to 8, 13 to 26; + UNDEF = 0; + + PROCESS_EXEC = 1; + PROCESS_EXIT = 5; + PROCESS_KPROBE = 9; + PROCESS_TRACEPOINT = 10; + PROCESS_LOADER = 11; + PROCESS_UPROBE = 12; + PROCESS_THROTTLE = 27; + PROCESS_LSM = 28; + + TEST = 40000; + RATE_LIMIT_INFO = 40001; } message Filter { - repeated string binary_regex = 1; - repeated string namespace = 2; - google.protobuf.BoolValue health_check = 3; - repeated uint32 pid = 4; - // Filter by the PID of a process and any of its descendants. Note that this filter is - // intended for testing and development purposes only and should not be used in - // production. In particular, PID cycling in the OS over longer periods of time may - // cause unexpected events to pass this filter. - repeated uint32 pid_set = 5; - repeated EventType event_set = 6; - // Filter by process.pod.name field using RE2 regular expression syntax: - // https://github.com/google/re2/wiki/Syntax - repeated string pod_regex = 7; - // Filter by process.arguments field using RE2 regular expression syntax: - // https://github.com/google/re2/wiki/Syntax - repeated string arguments_regex = 8; - // Filter events by pod labels using Kubernetes label selector syntax: - // https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // Note that this filter never matches events without the pod field (i.e. - // host process events). - repeated string labels = 9; - // Filter events by tracing policy names - repeated string policy_names = 10; - // Filter events by Linux process capability - CapFilter capabilities = 11; - // Filter parent process' binary using RE2 regular expression syntax. - repeated string parent_binary_regex = 12; - // Filter using CEL expressions. CEL filters support IP and CIDR notiation extensions from the k8s project. - // See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#IP and https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#CIDR for details. - repeated string cel_expression = 13; - // Filter by process.parent.arguments field using RE2 regular expression syntax: - // https://github.com/google/re2/wiki/Syntax - repeated string parent_arguments_regex = 14; - // Filter by the container ID in the process.docker field using RE2 regular expression syntax: - // https://github.com/google/re2/wiki/Syntax - repeated string container_id = 15; - // Filter containerized processes based on whether they are descendants of - // the container's init process. This can be used, for example, to watch - // for processes injected into a container via docker exec, kubectl exec, or - // similar mechanisms. - google.protobuf.BoolValue in_init_tree = 16; + repeated string binary_regex = 1; + repeated string namespace = 2; + google.protobuf.BoolValue health_check = 3; + repeated uint32 pid = 4; + // Filter by the PID of a process and any of its descendants. Note that this filter is + // intended for testing and development purposes only and should not be used in + // production. In particular, PID cycling in the OS over longer periods of time may + // cause unexpected events to pass this filter. + repeated uint32 pid_set = 5; + repeated EventType event_set = 6; + // Filter by process.pod.name field using RE2 regular expression syntax: + // https://github.com/google/re2/wiki/Syntax + repeated string pod_regex = 7; + // Filter by process.arguments field using RE2 regular expression syntax: + // https://github.com/google/re2/wiki/Syntax + repeated string arguments_regex = 8; + // Filter events by pod labels using Kubernetes label selector syntax: + // https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + // Note that this filter never matches events without the pod field (i.e. + // host process events). + repeated string labels = 9; + // Filter events by tracing policy names + repeated string policy_names = 10; + // Filter events by Linux process capability + CapFilter capabilities = 11; + // Filter parent process' binary using RE2 regular expression syntax. + repeated string parent_binary_regex = 12; + // Filter using CEL expressions. CEL filters support IP and CIDR notiation extensions from the k8s project. + // See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#IP and https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#CIDR for details. + repeated string cel_expression = 13; + // Filter by process.parent.arguments field using RE2 regular expression syntax: + // https://github.com/google/re2/wiki/Syntax + repeated string parent_arguments_regex = 14; + // Filter by the container ID in the process.docker field using RE2 regular expression syntax: + // https://github.com/google/re2/wiki/Syntax + repeated string container_id = 15; + // Filter containerized processes based on whether they are descendants of + // the container's init process. This can be used, for example, to watch + // for processes injected into a container via docker exec, kubectl exec, or + // similar mechanisms. + google.protobuf.BoolValue in_init_tree = 16; + // Filter ancestor processes' binaries using RE2 regular expression syntax. + repeated string ancestor_binary_regex = 17; } // Filter over a set of Linux process capabilities. See `message Capabilities` @@ -82,142 +86,144 @@ message Filter { // permitted filter matches, but the effective filter does not, the filter will // NOT match. message CapFilter { - // Filter over the set of permitted capabilities. - CapFilterSet permitted = 1; - // Filter over the set of effective capabilities. - CapFilterSet effective = 2; - // Filter over the set of inheritable capabilities. - CapFilterSet inheritable = 3; + // Filter over the set of permitted capabilities. + CapFilterSet permitted = 1; + // Filter over the set of effective capabilities. + CapFilterSet effective = 2; + // Filter over the set of inheritable capabilities. + CapFilterSet inheritable = 3; } // Capability set to filter over. NOTE: you may specify only ONE set here. message CapFilterSet { - // Match if the capability set contains any of the capabilities defined in this filter. - repeated CapabilitiesType any = 1; - // Match if the capability set contains all of the capabilities defined in this filter. - repeated CapabilitiesType all = 2; - // Match if the capability set exactly matches all of the capabilities defined in this filter. - repeated CapabilitiesType exactly = 3; - // Match if the capability set contains none of the capabilities defined in this filter. - repeated CapabilitiesType none = 4; + // Match if the capability set contains any of the capabilities defined in this filter. + repeated CapabilitiesType any = 1; + // Match if the capability set contains all of the capabilities defined in this filter. + repeated CapabilitiesType all = 2; + // Match if the capability set exactly matches all of the capabilities defined in this filter. + repeated CapabilitiesType exactly = 3; + // Match if the capability set contains none of the capabilities defined in this filter. + repeated CapabilitiesType none = 4; } message RedactionFilter { - // Deprecated, do not use. - repeated Filter match = 1 [deprecated=true]; - // RE2 regular expressions to use for redaction. Strings inside capture groups are redacted. - repeated string redact = 2; - // RE2 regular expression to match binary name. If supplied, redactions will only be applied to matching processes. - repeated string binary_regex = 3; + // Deprecated, do not use. + repeated Filter match = 1 [deprecated = true]; + // RE2 regular expressions to use for redaction. Strings inside capture groups are redacted. + repeated string redact = 2; + // RE2 regular expression to match binary name. If supplied, redactions will only be applied to matching processes. + repeated string binary_regex = 3; } // Determines the behavior of a field filter enum FieldFilterAction { - INCLUDE = 0; - EXCLUDE = 1; + INCLUDE = 0; + EXCLUDE = 1; } // message FieldFilter { -// // Event types to filter or undefined to filter over all event types. -// repeated EventType event_set = 1; -// // Fields to include or exclude. -// google.protobuf.FieldMask fields = 2; -// // Whether to include or exclude fields. -// FieldFilterAction action = 3; -// // Whether or not the event set filter should be inverted. -// google.protobuf.BoolValue invert_event_set = 4; +// // Event types to filter or undefined to filter over all event types. +// repeated EventType event_set = 1; +// // Fields to include or exclude. +// google.protobuf.FieldMask fields = 2; +// // Whether to include or exclude fields. +// FieldFilterAction action = 3; +// // Whether or not the event set filter should be inverted. +// google.protobuf.BoolValue invert_event_set = 4; // } // message GetEventsRequest { -// // allow_list specifies a list of filters to apply to only return certain -// // events. If multiple filters are specified, at least one of them has to -// // match for an event to be included in the results. -// repeated Filter allow_list = 1; -// // deny_list specifies a list of filters to apply to exclude certain events -// // from the results. If multiple filters are specified, at least one of -// // them has to match for an event to be excluded. -// // If both allow_list and deny_list are specified, the results contain the -// // set difference allow_list - deny_list. -// repeated Filter deny_list = 2; -// // aggregation_options configures aggregation options for this request. -// // If this field is not set, responses will not be aggregated. -// // Note that currently only process_accept and process_connect events are -// // aggregated. Other events remain unaggregated. -// AggregationOptions aggregation_options = 3; -// // Fields to include or exclude for events in the GetEventsResponse. Omitting this -// // field implies that all fields will be included. Exclusion always takes precedence -// // over inclusion in the case of conflicts. -// repeated FieldFilter field_filters = 4; +// // allow_list specifies a list of filters to apply to only return certain +// // events. If multiple filters are specified, at least one of them has to +// // match for an event to be included in the results. +// repeated Filter allow_list = 1; +// // deny_list specifies a list of filters to apply to exclude certain events +// // from the results. If multiple filters are specified, at least one of +// // them has to match for an event to be excluded. +// // If both allow_list and deny_list are specified, the results contain the +// // set difference allow_list - deny_list. +// repeated Filter deny_list = 2; +// // aggregation_options configures aggregation options for this request. +// // If this field is not set, responses will not be aggregated. +// // Note that currently only process_accept and process_connect events are +// // aggregated. Other events remain unaggregated. +// AggregationOptions aggregation_options = 3; +// // Fields to include or exclude for events in the GetEventsResponse. Omitting this +// // field implies that all fields will be included. Exclusion always takes precedence +// // over inclusion in the case of conflicts. +// repeated FieldFilter field_filters = 4; // } // AggregationOptions defines configuration options for aggregating events. message AggregationOptions { - // Aggregation window size. Defaults to 15 seconds if this field is not set. - google.protobuf.Duration window_size = 1; - // Size of the buffer for the aggregator to receive incoming events. If the - // buffer becomes full, the aggregator will log a warning and start dropping - // incoming events. - uint64 channel_buffer_size = 2; + // Aggregation window size. Defaults to 15 seconds if this field is not set. + google.protobuf.Duration window_size = 1; + // Size of the buffer for the aggregator to receive incoming events. If the + // buffer becomes full, the aggregator will log a warning and start dropping + // incoming events. + uint64 channel_buffer_size = 2; } // AggregationInfo contains information about aggregation results. message AggregationInfo { - // Total count of events in this aggregation time window. - uint64 count = 1; + // Total count of events in this aggregation time window. + uint64 count = 1; } message RateLimitInfo { - uint64 number_of_dropped_process_events = 1; + uint64 number_of_dropped_process_events = 1; } enum ThrottleType { - THROTTLE_UNKNOWN = 0; - THROTTLE_START = 1; - THROTTLE_STOP = 2; + THROTTLE_UNKNOWN = 0; + THROTTLE_START = 1; + THROTTLE_STOP = 2; } message ProcessThrottle { - // Throttle type - ThrottleType type = 1; - // Cgroup name - string cgroup = 2; + // Throttle type + ThrottleType type = 1; + // Cgroup name + string cgroup = 2; } message GetEventsResponse { - reserved 2 to 4, 6 to 8, 13 to 26; - // The type-specific fields of an event. - // - // NOTE: Numbers must stay in sync with enum EventType. - oneof event { - // ProcessExec event includes information about the execution of - // binaries and other related process metadata. - ProcessExec process_exec = 1; - // ProcessExit event indicates how and when a process terminates. - ProcessExit process_exit = 5; - // ProcessKprobe event contains information about the pre-defined - // functions and the process that invoked them. - ProcessKprobe process_kprobe = 9; - // ProcessTracepoint contains information about the pre-defined - // tracepoint and the process that invoked them. - ProcessTracepoint process_tracepoint = 10; - ProcessLoader process_loader = 11; - ProcessUprobe process_uprobe = 12; - ProcessThrottle process_throttle = 27; - ProcessLsm process_lsm = 28; - - Test test = 40000; - RateLimitInfo rate_limit_info = 40001; - } - // Name of the node where this event was observed. - string node_name = 1000; - // Timestamp at which this event was observed. - // For an aggregated response, this field to set to the timestamp at which - // the event was observed for the first time in a given aggregation time window. - google.protobuf.Timestamp time = 1001; - - // aggregation_info contains information about aggregation results. This field - // is set only for aggregated responses. - AggregationInfo aggregation_info = 1002; - // Name of the cluster where this event was observed. - string cluster_name = 1003; + reserved 2 to 4, 6 to 8, 13 to 26; + // The type-specific fields of an event. + // + // NOTE: Numbers must stay in sync with enum EventType. + oneof event { + // ProcessExec event includes information about the execution of + // binaries and other related process metadata. + ProcessExec process_exec = 1; + // ProcessExit event indicates how and when a process terminates. + ProcessExit process_exit = 5; + // ProcessKprobe event contains information about the pre-defined + // functions and the process that invoked them. + ProcessKprobe process_kprobe = 9; + // ProcessTracepoint contains information about the pre-defined + // tracepoint and the process that invoked them. + ProcessTracepoint process_tracepoint = 10; + ProcessLoader process_loader = 11; + ProcessUprobe process_uprobe = 12; + ProcessThrottle process_throttle = 27; + ProcessLsm process_lsm = 28; + + Test test = 40000; + RateLimitInfo rate_limit_info = 40001; + } + // Name of the node where this event was observed. + string node_name = 1000; + // Timestamp at which this event was observed. + // For an aggregated response, this field to set to the timestamp at which + // the event was observed for the first time in a given aggregation time window. + google.protobuf.Timestamp time = 1001; + + // aggregation_info contains information about aggregation results. This field + // is set only for aggregated responses. + AggregationInfo aggregation_info = 1002; + // Name of the cluster where this event was observed. + string cluster_name = 1003; + // Labels associated with the node where this event was observed. + map node_labels = 1004; } diff --git a/event-processor/detector/api/tetragon/events_vtproto.pb.go b/event-processor/detector/api/tetragon/events_vtproto.pb.go index 1cad0506..ea1e61b5 100644 --- a/event-processor/detector/api/tetragon/events_vtproto.pb.go +++ b/event-processor/detector/api/tetragon/events_vtproto.pb.go @@ -56,6 +56,17 @@ func (m *Filter) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.AncestorBinaryRegex) > 0 { + for iNdEx := len(m.AncestorBinaryRegex) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AncestorBinaryRegex[iNdEx]) + copy(dAtA[i:], m.AncestorBinaryRegex[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.AncestorBinaryRegex[iNdEx]))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + } if m.InInitTree != nil { if vtmsg, ok := interface{}(m.InInitTree).(interface { MarshalToSizedBufferVT([]byte) (int, error) @@ -729,6 +740,27 @@ func (m *GetEventsResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { } i -= size } + if len(m.NodeLabels) > 0 { + for k := range m.NodeLabels { + v := m.NodeLabels[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarint(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x3e + i-- + dAtA[i] = 0xe2 + } + } if len(m.ClusterName) > 0 { i -= len(m.ClusterName) copy(dAtA[i:], m.ClusterName) @@ -1099,6 +1131,12 @@ func (m *Filter) SizeVT() (n int) { } n += 2 + l + sov(uint64(l)) } + if len(m.AncestorBinaryRegex) > 0 { + for _, s := range m.AncestorBinaryRegex { + l = len(s) + n += 2 + l + sov(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -1288,6 +1326,14 @@ func (m *GetEventsResponse) SizeVT() (n int) { if l > 0 { n += 2 + l + sov(uint64(l)) } + if len(m.NodeLabels) > 0 { + for k, v := range m.NodeLabels { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + 1 + len(v) + sov(uint64(len(v))) + n += mapEntrySize + 2 + sov(uint64(mapEntrySize)) + } + } n += len(m.unknownFields) return n } @@ -2106,6 +2152,38 @@ func (m *Filter) UnmarshalVT(dAtA []byte) error { } } iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AncestorBinaryRegex", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AncestorBinaryRegex = append(m.AncestorBinaryRegex, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -3620,6 +3698,133 @@ func (m *GetEventsResponse) UnmarshalVT(dAtA []byte) error { } m.ClusterName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 1004: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NodeLabels", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NodeLabels == nil { + m.NodeLabels = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLength + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLength + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.NodeLabels[mapkey] = mapvalue + iNdEx = postIndex case 40000: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Test", wireType) diff --git a/event-processor/detector/api/tetragon/sensors.pb.go b/event-processor/detector/api/tetragon/sensors.pb.go index e23b327b..e2d6fb70 100644 --- a/event-processor/detector/api/tetragon/sensors.pb.go +++ b/event-processor/detector/api/tetragon/sensors.pb.go @@ -69,6 +69,34 @@ func (x TracingPolicyState) Enum() *TracingPolicyState { return p } +type TracingPolicyMode int32 + +const ( + TracingPolicyMode_TP_MODE_UNKNOWN TracingPolicyMode = 0 + TracingPolicyMode_TP_MODE_ENFORCE TracingPolicyMode = 1 + TracingPolicyMode_TP_MODE_MONITOR TracingPolicyMode = 2 +) + +// Enum value maps for TracingPolicyMode. +var ( + TracingPolicyMode_name = map[int32]string{ + 0: "TP_MODE_UNKNOWN", + 1: "TP_MODE_ENFORCE", + 2: "TP_MODE_MONITOR", + } + TracingPolicyMode_value = map[string]int32{ + "TP_MODE_UNKNOWN": 0, + "TP_MODE_ENFORCE": 1, + "TP_MODE_MONITOR": 2, + } +) + +func (x TracingPolicyMode) Enum() *TracingPolicyMode { + p := new(TracingPolicyMode) + *p = x + return p +} + // For now, we only want to support debug-related config flags to be configurable. type ConfigFlag int32 @@ -239,6 +267,8 @@ type TracingPolicyStatus struct { State TracingPolicyState `protobuf:"varint,9,opt,name=state,proto3,enum=tetragon.TracingPolicyState" json:"state,omitempty"` // the amount of kernel memory in bytes used by policy's sensors non-shared BPF maps (memlock) KernelMemoryBytes uint64 `protobuf:"varint,10,opt,name=kernel_memory_bytes,json=kernelMemoryBytes,proto3" json:"kernel_memory_bytes,omitempty"` + // current mode of the tracing policy + Mode TracingPolicyMode `protobuf:"varint,11,opt,name=mode,proto3,enum=tetragon.TracingPolicyMode" json:"mode,omitempty"` } func (x *TracingPolicyStatus) ProtoReflect() protoreflect.Message { @@ -316,6 +346,13 @@ func (x *TracingPolicyStatus) GetKernelMemoryBytes() uint64 { return 0 } +func (x *TracingPolicyStatus) GetMode() TracingPolicyMode { + if x != nil { + return x.Mode + } + return TracingPolicyMode_TP_MODE_UNKNOWN +} + type ListTracingPoliciesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -475,6 +512,59 @@ func (x *DisableTracingPolicyResponse) ProtoReflect() protoreflect.Message { panic(`not implemented`) } +type ConfigureTracingPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Enable *bool `protobuf:"varint,3,opt,name=enable,proto3,oneof" json:"enable,omitempty"` + Mode *TracingPolicyMode `protobuf:"varint,4,opt,name=mode,proto3,enum=tetragon.TracingPolicyMode,oneof" json:"mode,omitempty"` +} + +func (x *ConfigureTracingPolicyRequest) ProtoReflect() protoreflect.Message { + panic(`not implemented`) +} + +func (x *ConfigureTracingPolicyRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ConfigureTracingPolicyRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ConfigureTracingPolicyRequest) GetEnable() bool { + if x != nil && x.Enable != nil { + return *x.Enable + } + return false +} + +func (x *ConfigureTracingPolicyRequest) GetMode() TracingPolicyMode { + if x != nil && x.Mode != nil { + return *x.Mode + } + return TracingPolicyMode_TP_MODE_UNKNOWN +} + +type ConfigureTracingPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ConfigureTracingPolicyResponse) ProtoReflect() protoreflect.Message { + panic(`not implemented`) +} + type RemoveSensorRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -670,6 +760,8 @@ type ProcessInternal struct { // - "process--": process decreased refcnt (i.e. this process exits) // - "parent++": parent increased refcnt (i.e. a process starts that has this process as a parent) // - "parent--": parent decreased refcnt (i.e. a process exits that has this process as a parent) + // - "ancestor++": ancestor increased refcnt (i.e. a process starts that has this process as an ancestor) + // - "ancestor--": ancestor decreased refcnt (i.e. a process exits that has this process as an ancestor) RefcntOps map[string]int32 `protobuf:"bytes,4,rep,name=refcnt_ops,json=refcntOps,proto3" json:"refcnt_ops,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` } diff --git a/event-processor/detector/api/tetragon/sensors.proto b/event-processor/detector/api/tetragon/sensors.proto index a58f0aef..8de65886 100644 --- a/event-processor/detector/api/tetragon/sensors.proto +++ b/event-processor/detector/api/tetragon/sensors.proto @@ -3,226 +3,260 @@ syntax = "proto3"; -import "google/protobuf/wrappers.proto"; - package tetragon; -import "tetragon/tetragon.proto"; -import "tetragon/stack.proto"; +import "google/protobuf/wrappers.proto"; import "tetragon/events.proto"; +import "tetragon/stack.proto"; +import "tetragon/tetragon.proto"; + +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; /** * Sensors */ -message ListSensorsRequest { } +message ListSensorsRequest {} message SensorStatus { - // name is the name of the sensor - string name = 1; - // enabled marks whether the sensor is enabled - bool enabled = 2; - // collection is the collection the sensor belongs to (typically a tracing policy) - string collection = 3; + // name is the name of the sensor + string name = 1; + // enabled marks whether the sensor is enabled + bool enabled = 2; + // collection is the collection the sensor belongs to (typically a tracing policy) + string collection = 3; } message ListSensorsResponse { - repeated SensorStatus sensors = 1; + repeated SensorStatus sensors = 1; } -message ListTracingPoliciesRequest { } +message ListTracingPoliciesRequest {} enum TracingPolicyState { - // unknown state - TP_STATE_UNKNOWN = 0; - // loaded and enabled - TP_STATE_ENABLED = 1; - // loaded but disabled - TP_STATE_DISABLED = 2; - // failed to load - TP_STATE_LOAD_ERROR = 3; - // failed during lifetime - TP_STATE_ERROR = 4; - // in the process of loading - TP_STATE_LOADING = 5; - // in the process of unloading - TP_STATE_UNLOADING = 6; + // unknown state + TP_STATE_UNKNOWN = 0; + // loaded and enabled + TP_STATE_ENABLED = 1; + // loaded but disabled + TP_STATE_DISABLED = 2; + // failed to load + TP_STATE_LOAD_ERROR = 3; + // failed during lifetime + TP_STATE_ERROR = 4; + // in the process of loading + TP_STATE_LOADING = 5; + // in the process of unloading + TP_STATE_UNLOADING = 6; +} + +enum TracingPolicyMode { + TP_MODE_UNKNOWN = 0; + TP_MODE_ENFORCE = 1; + TP_MODE_MONITOR = 2; } message TracingPolicyStatus { - // id is the id of the policy - uint64 id = 1; - // name is the name of the policy - string name = 2; - // namespace is the namespace of the policy (or empty of the policy is global) - string namespace = 3; - // info is additional information about the policy - string info = 4; - // sensors loaded in the scope of this policy - repeated string sensors = 5; - // indicating if the policy is enabled. Deprecated: use 'state' instead. - bool enabled = 6 [deprecated = true]; - // filter ID of the policy used for k8s filtering - uint64 filter_id = 7; - // potential error of the policy - string error = 8; - // current state of the tracing policy - TracingPolicyState state = 9; - // the amount of kernel memory in bytes used by policy's sensors non-shared BPF maps (memlock) - uint64 kernel_memory_bytes = 10; + // id is the id of the policy + uint64 id = 1; + // name is the name of the policy + string name = 2; + // namespace is the namespace of the policy (or empty of the policy is global) + string namespace = 3; + // info is additional information about the policy + string info = 4; + // sensors loaded in the scope of this policy + repeated string sensors = 5; + // indicating if the policy is enabled. Deprecated: use 'state' instead. + bool enabled = 6 [deprecated = true]; + // filter ID of the policy used for k8s filtering + uint64 filter_id = 7; + // potential error of the policy + string error = 8; + // current state of the tracing policy + TracingPolicyState state = 9; + // the amount of kernel memory in bytes used by policy's sensors non-shared BPF maps (memlock) + uint64 kernel_memory_bytes = 10; + // current mode of the tracing policy + TracingPolicyMode mode = 11; } message ListTracingPoliciesResponse { - repeated TracingPolicyStatus policies = 1; + repeated TracingPolicyStatus policies = 1; } message AddTracingPolicyRequest { - string yaml = 1; + string yaml = 1; } message AddTracingPolicyResponse {} message DeleteTracingPolicyRequest { - string name = 1; - string namespace = 2; + string name = 1; + string namespace = 2; } message DeleteTracingPolicyResponse {} message EnableTracingPolicyRequest { - string name = 1; - string namespace = 2; + string name = 1; + string namespace = 2; } message EnableTracingPolicyResponse {} message DisableTracingPolicyRequest { - string name = 1; - string namespace = 2; + string name = 1; + string namespace = 2; } message DisableTracingPolicyResponse {} +message ConfigureTracingPolicyRequest { + string name = 1; + string namespace = 2; + + optional bool enable = 3; + optional TracingPolicyMode mode = 4; +} + +message ConfigureTracingPolicyResponse {} + message RemoveSensorRequest { - string name = 1; + string name = 1; } message RemoveSensorResponse {} - message EnableSensorRequest { - string name = 1; + string name = 1; } message EnableSensorResponse {} message DisableSensorRequest { - string name = 1; + string name = 1; } -message DisableSensorResponse { } +message DisableSensorResponse {} message GetStackTraceTreeRequest { - string name = 1; + string name = 1; } message GetStackTraceTreeResponse { - StackTraceNode root = 1; + StackTraceNode root = 1; } -message GetVersionRequest{} -message GetVersionResponse{ - string version = 1; +message GetVersionRequest {} +message GetVersionResponse { + string version = 1; } // For now, we only want to support debug-related config flags to be configurable. enum ConfigFlag { - CONFIG_FLAG_LOG_LEVEL = 0; - CONFIG_FLAG_DUMP_PROCESS_CACHE = 1; + CONFIG_FLAG_LOG_LEVEL = 0; + CONFIG_FLAG_DUMP_PROCESS_CACHE = 1; } enum LogLevel { - LOG_LEVEL_PANIC = 0; - LOG_LEVEL_FATAL = 1; - LOG_LEVEL_ERROR = 2; - LOG_LEVEL_WARN = 3; - LOG_LEVEL_INFO = 4; - LOG_LEVEL_DEBUG = 5; - LOG_LEVEL_TRACE = 6; + LOG_LEVEL_PANIC = 0; + LOG_LEVEL_FATAL = 1; + LOG_LEVEL_ERROR = 2; + LOG_LEVEL_WARN = 3; + LOG_LEVEL_INFO = 4; + LOG_LEVEL_DEBUG = 5; + LOG_LEVEL_TRACE = 6; } message DumpProcessCacheReqArgs { - bool skip_zero_refcnt = 1; - bool exclude_execve_map_processes = 2; + bool skip_zero_refcnt = 1; + bool exclude_execve_map_processes = 2; } message ProcessInternal { - Process process = 1; - string color = 2; - google.protobuf.UInt32Value refcnt = 3; - // refcnt_ops is a map of operations to refcnt change - // keys can be: - // - "process++": process increased refcnt (i.e. this process starts) - // - "process--": process decreased refcnt (i.e. this process exits) - // - "parent++": parent increased refcnt (i.e. a process starts that has this process as a parent) - // - "parent--": parent decreased refcnt (i.e. a process exits that has this process as a parent) - map refcnt_ops = 4; + Process process = 1; + string color = 2; + google.protobuf.UInt32Value refcnt = 3; + // refcnt_ops is a map of operations to refcnt change + // keys can be: + // - "process++": process increased refcnt (i.e. this process starts) + // - "process--": process decreased refcnt (i.e. this process exits) + // - "parent++": parent increased refcnt (i.e. a process starts that has this process as a parent) + // - "parent--": parent decreased refcnt (i.e. a process exits that has this process as a parent) + // - "ancestor++": ancestor increased refcnt (i.e. a process starts that has this process as an ancestor) + // - "ancestor--": ancestor decreased refcnt (i.e. a process exits that has this process as an ancestor) + map refcnt_ops = 4; } message DumpProcessCacheResArgs { - repeated ProcessInternal processes = 1; + repeated ProcessInternal processes = 1; } -message GetDebugRequest{ - ConfigFlag flag = 1; - oneof arg { - DumpProcessCacheReqArgs dump = 2; - } +message GetDebugRequest { + ConfigFlag flag = 1; + oneof arg { + DumpProcessCacheReqArgs dump = 2; + } } -message GetDebugResponse{ - ConfigFlag flag = 1; - oneof arg { - LogLevel level = 2; - DumpProcessCacheResArgs processes = 3; - } +message GetDebugResponse { + ConfigFlag flag = 1; + oneof arg { + LogLevel level = 2; + DumpProcessCacheResArgs processes = 3; + } } -message SetDebugRequest{ - ConfigFlag flag = 1; - oneof arg { - LogLevel level = 2; - } +message SetDebugRequest { + ConfigFlag flag = 1; + oneof arg { + LogLevel level = 2; + } } -message SetDebugResponse{ - ConfigFlag flag = 1; - oneof arg { - LogLevel level = 2; - } +message SetDebugResponse { + ConfigFlag flag = 1; + oneof arg { + LogLevel level = 2; + } } service FineGuidanceSensors { - // rpc GetEvents(GetEventsRequest) returns (stream GetEventsResponse) {} - rpc GetHealth(GetHealthStatusRequest) returns (GetHealthStatusResponse) {} - - rpc AddTracingPolicy(AddTracingPolicyRequest) returns (AddTracingPolicyResponse) {} - rpc DeleteTracingPolicy(DeleteTracingPolicyRequest) returns (DeleteTracingPolicyResponse) {} - rpc ListTracingPolicies(ListTracingPoliciesRequest) returns (ListTracingPoliciesResponse) {} - rpc EnableTracingPolicy(EnableTracingPolicyRequest) returns (EnableTracingPolicyResponse) {} - rpc DisableTracingPolicy(DisableTracingPolicyRequest) returns (DisableTracingPolicyResponse) {} - - rpc ListSensors(ListSensorsRequest) returns (ListSensorsResponse) { - option deprecated = true; - } - rpc EnableSensor(EnableSensorRequest) returns (EnableSensorResponse) { - option deprecated = true; - } - rpc DisableSensor(DisableSensorRequest) returns (DisableSensorResponse) { - option deprecated = true; - } - rpc RemoveSensor(RemoveSensorRequest) returns (RemoveSensorResponse) { - option deprecated = true; - } - - rpc GetStackTraceTree(GetStackTraceTreeRequest) returns (GetStackTraceTreeResponse) {} - - rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {} - - rpc RuntimeHook(RuntimeHookRequest) returns (RuntimeHookResponse) {} - - rpc GetDebug(GetDebugRequest) returns (GetDebugResponse) {} - rpc SetDebug(SetDebugRequest) returns (SetDebugResponse) {} + // rpc GetEvents(GetEventsRequest) returns (stream GetEventsResponse) {} + rpc GetHealth(GetHealthStatusRequest) returns (GetHealthStatusResponse) {} + + rpc AddTracingPolicy(AddTracingPolicyRequest) returns (AddTracingPolicyResponse) {} + rpc DeleteTracingPolicy(DeleteTracingPolicyRequest) returns (DeleteTracingPolicyResponse) {} + rpc ListTracingPolicies(ListTracingPoliciesRequest) returns (ListTracingPoliciesResponse) {} + // ConfigureTracingPolicy can be used to configure a loaded tracing policy. + // It can be used to: + // - enable/disable it + // - change its mode (enforcement vs monitoring) + // If multiple changes are requested and an error is encountered, the resulting state might have + // partial updates applied. In other words, the configuring a tracing policy is not atomic. + rpc ConfigureTracingPolicy(ConfigureTracingPolicyRequest) returns (ConfigureTracingPolicyResponse) {} + + rpc EnableTracingPolicy(EnableTracingPolicyRequest) returns (EnableTracingPolicyResponse) { + // use ConfigureTracingPolicy instead + option deprecated = true; + } + rpc DisableTracingPolicy(DisableTracingPolicyRequest) returns (DisableTracingPolicyResponse) { + // use ConfigureTracingPolicy instead + option deprecated = true; + } + + rpc ListSensors(ListSensorsRequest) returns (ListSensorsResponse) { + option deprecated = true; + } + rpc EnableSensor(EnableSensorRequest) returns (EnableSensorResponse) { + option deprecated = true; + } + rpc DisableSensor(DisableSensorRequest) returns (DisableSensorResponse) { + option deprecated = true; + } + rpc RemoveSensor(RemoveSensorRequest) returns (RemoveSensorResponse) { + option deprecated = true; + } + + rpc GetStackTraceTree(GetStackTraceTreeRequest) returns (GetStackTraceTreeResponse) {} + + rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {} + + rpc RuntimeHook(RuntimeHookRequest) returns (RuntimeHookResponse) {} + + rpc GetDebug(GetDebugRequest) returns (GetDebugResponse) {} + rpc SetDebug(SetDebugRequest) returns (SetDebugResponse) {} } diff --git a/event-processor/detector/api/tetragon/sensors_vtproto.pb.go b/event-processor/detector/api/tetragon/sensors_vtproto.pb.go index db6fec95..7c425b76 100644 --- a/event-processor/detector/api/tetragon/sensors_vtproto.pb.go +++ b/event-processor/detector/api/tetragon/sensors_vtproto.pb.go @@ -222,6 +222,11 @@ func (m *TracingPolicyStatus) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Mode != 0 { + i = encodeVarint(dAtA, i, uint64(m.Mode)) + i-- + dAtA[i] = 0x58 + } if m.KernelMemoryBytes != 0 { i = encodeVarint(dAtA, i, uint64(m.KernelMemoryBytes)) i-- @@ -650,6 +655,101 @@ func (m *DisableTracingPolicyResponse) MarshalToSizedBufferVT(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *ConfigureTracingPolicyRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConfigureTracingPolicyRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ConfigureTracingPolicyRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Mode != nil { + i = encodeVarint(dAtA, i, uint64(*m.Mode)) + i-- + dAtA[i] = 0x20 + } + if m.Enable != nil { + i-- + if *m.Enable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Namespace) > 0 { + i -= len(m.Namespace) + copy(dAtA[i:], m.Namespace) + i = encodeVarint(dAtA, i, uint64(len(m.Namespace))) + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ConfigureTracingPolicyResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConfigureTracingPolicyResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ConfigureTracingPolicyResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + func (m *RemoveSensorRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -1574,6 +1674,9 @@ func (m *TracingPolicyStatus) SizeVT() (n int) { if m.KernelMemoryBytes != 0 { n += 1 + sov(uint64(m.KernelMemoryBytes)) } + if m.Mode != 0 { + n += 1 + sov(uint64(m.Mode)) + } n += len(m.unknownFields) return n } @@ -1702,6 +1805,40 @@ func (m *DisableTracingPolicyResponse) SizeVT() (n int) { return n } +func (m *ConfigureTracingPolicyRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Namespace) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Enable != nil { + n += 2 + } + if m.Mode != nil { + n += 1 + sov(uint64(*m.Mode)) + } + n += len(m.unknownFields) + return n +} + +func (m *ConfigureTracingPolicyResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + func (m *RemoveSensorRequest) SizeVT() (n int) { if m == nil { return 0 @@ -2616,6 +2753,25 @@ func (m *TracingPolicyStatus) UnmarshalVT(dAtA []byte) error { break } } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Mode |= TracingPolicyMode(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -3355,6 +3511,213 @@ func (m *DisableTracingPolicyResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *ConfigureTracingPolicyRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConfigureTracingPolicyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConfigureTracingPolicyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Enable", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Enable = &b + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + var v TracingPolicyMode + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= TracingPolicyMode(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Mode = &v + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConfigureTracingPolicyResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConfigureTracingPolicyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConfigureTracingPolicyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RemoveSensorRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/event-processor/detector/api/tetragon/stack.proto b/event-processor/detector/api/tetragon/stack.proto index e73a7d6e..f0f90bef 100644 --- a/event-processor/detector/api/tetragon/stack.proto +++ b/event-processor/detector/api/tetragon/stack.proto @@ -5,27 +5,29 @@ syntax = "proto3"; package tetragon; +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; + /** * Stack traces */ message StackAddress { - uint64 address = 1; - string symbol = 2; + uint64 address = 1; + string symbol = 2; } message StackTrace { - repeated StackAddress addresses = 1; + repeated StackAddress addresses = 1; } message StackTraceLabel { - string key = 1; - uint64 count = 2; + string key = 1; + uint64 count = 2; } message StackTraceNode { - StackAddress address = 1; - uint64 count = 2; - repeated StackTraceLabel labels = 3; - repeated StackTraceNode children = 4; + StackAddress address = 1; + uint64 count = 2; + repeated StackTraceLabel labels = 3; + repeated StackTraceNode children = 4; } diff --git a/event-processor/detector/api/tetragon/tetragon.pb.go b/event-processor/detector/api/tetragon/tetragon.pb.go index 85ff3162..f0e3c0de 100644 --- a/event-processor/detector/api/tetragon/tetragon.pb.go +++ b/event-processor/detector/api/tetragon/tetragon.pb.go @@ -244,6 +244,26 @@ func (x *Image) GetName() string { return "" } +type SecurityContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // True if this container is priviledged. + Privileged bool `protobuf:"varint,1,opt,name=privileged,proto3" json:"privileged,omitempty"` +} + +func (x *SecurityContext) ProtoReflect() protoreflect.Message { + panic(`not implemented`) +} + +func (x *SecurityContext) GetPrivileged() bool { + if x != nil { + return x.Privileged + } + return false +} + type Container struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -266,6 +286,8 @@ type Container struct { // and "ls" are considered a match. // 2. The arguments field exactly matches the rest of the exec command list. MaybeExecProbe bool `protobuf:"varint,13,opt,name=maybe_exec_probe,json=maybeExecProbe,proto3" json:"maybe_exec_probe,omitempty"` + // The security context of the container + SecurityContext *SecurityContext `protobuf:"bytes,14,opt,name=security_context,json=securityContext,proto3" json:"security_context,omitempty"` } func (x *Container) ProtoReflect() protoreflect.Message { @@ -314,6 +336,13 @@ func (x *Container) GetMaybeExecProbe() bool { return false } +func (x *Container) GetSecurityContext() *SecurityContext { + if x != nil { + return x.SecurityContext + } + return nil +} + type Pod struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -332,6 +361,8 @@ type Pod struct { Workload string `protobuf:"bytes,6,opt,name=workload,proto3" json:"workload,omitempty"` // Kubernetes workload kind (e.g. "Deployment", "DaemonSet") of the Pod. WorkloadKind string `protobuf:"bytes,7,opt,name=workload_kind,json=workloadKind,proto3" json:"workload_kind,omitempty"` + // Contains all the annotations of the pod. + PodAnnotations map[string]string `protobuf:"bytes,8,rep,name=pod_annotations,json=podAnnotations,proto3" json:"pod_annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Pod) ProtoReflect() protoreflect.Message { @@ -380,6 +411,13 @@ func (x *Pod) GetWorkloadKind() string { return "" } +func (x *Pod) GetPodAnnotations() map[string]string { + if x != nil { + return x.PodAnnotations + } + return nil +} + type Capabilities struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -917,6 +955,8 @@ type Process struct { // current process with a new process by doing an exec* without a clone. In // this case the flag will be omitted and the same PID will be used by the // kernel for both the old process and the newly exec'd process. + // - `unknown` Indicates the process was not found in the process cache + // and contains just pid and start time. Flags string `protobuf:"bytes,7,opt,name=flags,proto3" json:"flags,omitempty"` // Start time of the execution. StartTime *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` @@ -1160,6 +1200,8 @@ type ProcessExit struct { Status uint32 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"` // Date and time of the event. Time *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=time,proto3" json:"time,omitempty"` + // Ancestors of the process beyond the immediate parent. + Ancestors []*Process `protobuf:"bytes,6,rep,name=ancestors,proto3" json:"ancestors,omitempty"` } func (x *ProcessExit) ProtoReflect() protoreflect.Message { @@ -1201,6 +1243,13 @@ func (x *ProcessExit) GetTime() *timestamppb.Timestamp { return nil } +func (x *ProcessExit) GetAncestors() []*Process { + if x != nil { + return x.Ancestors + } + return nil +} + type KprobeSock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1415,6 +1464,41 @@ func (x *KprobeSkb) GetFamily() string { return "" } +type KprobeSockaddr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family string `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"` + Port uint32 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *KprobeSockaddr) ProtoReflect() protoreflect.Message { + panic(`not implemented`) +} + +func (x *KprobeSockaddr) GetFamily() string { + if x != nil { + return x.Family + } + return "" +} + +func (x *KprobeSockaddr) GetAddr() string { + if x != nil { + return x.Addr + } + return "" +} + +func (x *KprobeSockaddr) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + type KprobeNetDev struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1878,6 +1962,7 @@ type KprobeArgument struct { // *KprobeArgument_NetDevArg // *KprobeArgument_BpfCmdArg // *KprobeArgument_SyscallId + // *KprobeArgument_SockaddrArg Arg isKprobeArgument_Arg `protobuf_oneof:"arg"` Label string `protobuf:"bytes,18,opt,name=label,proto3" json:"label,omitempty"` } @@ -2090,6 +2175,13 @@ func (x *KprobeArgument) GetSyscallId() *SyscallId { return nil } +func (x *KprobeArgument) GetSockaddrArg() *KprobeSockaddr { + if x, ok := x.GetArg().(*KprobeArgument_SockaddrArg); ok { + return x.SockaddrArg + } + return nil +} + func (x *KprobeArgument) GetLabel() string { if x != nil { return x.Label @@ -2214,6 +2306,10 @@ type KprobeArgument_SyscallId struct { SyscallId *SyscallId `protobuf:"bytes,29,opt,name=syscall_id,json=syscallId,proto3,oneof"` } +type KprobeArgument_SockaddrArg struct { + SockaddrArg *KprobeSockaddr `protobuf:"bytes,30,opt,name=sockaddr_arg,json=sockaddrArg,proto3,oneof"` +} + func (*KprobeArgument_StringArg) isKprobeArgument_Arg() {} func (*KprobeArgument_IntArg) isKprobeArgument_Arg() {} @@ -2270,6 +2366,8 @@ func (*KprobeArgument_BpfCmdArg) isKprobeArgument_Arg() {} func (*KprobeArgument_SyscallId) isKprobeArgument_Arg() {} +func (*KprobeArgument_SockaddrArg) isKprobeArgument_Arg() {} + type ProcessKprobe struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2299,6 +2397,8 @@ type ProcessKprobe struct { Tags []string `protobuf:"bytes,11,rep,name=tags,proto3" json:"tags,omitempty"` // User-mode stack trace to the call. UserStackTrace []*StackTraceEntry `protobuf:"bytes,12,rep,name=user_stack_trace,json=userStackTrace,proto3" json:"user_stack_trace,omitempty"` + // Ancestors of the process beyond the immediate parent. + Ancestors []*Process `protobuf:"bytes,13,rep,name=ancestors,proto3" json:"ancestors,omitempty"` } func (x *ProcessKprobe) ProtoReflect() protoreflect.Message { @@ -2389,6 +2489,13 @@ func (x *ProcessKprobe) GetUserStackTrace() []*StackTraceEntry { return nil } +func (x *ProcessKprobe) GetAncestors() []*Process { + if x != nil { + return x.Ancestors + } + return nil +} + type ProcessTracepoint struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2413,6 +2520,8 @@ type ProcessTracepoint struct { Message string `protobuf:"bytes,9,opt,name=message,proto3" json:"message,omitempty"` // Tags of the Tracing Policy to categorize the event. Tags []string `protobuf:"bytes,10,rep,name=tags,proto3" json:"tags,omitempty"` + // Ancestors of the process beyond the immediate parent. + Ancestors []*Process `protobuf:"bytes,11,rep,name=ancestors,proto3" json:"ancestors,omitempty"` } func (x *ProcessTracepoint) ProtoReflect() protoreflect.Message { @@ -2482,6 +2591,13 @@ func (x *ProcessTracepoint) GetTags() []string { return nil } +func (x *ProcessTracepoint) GetAncestors() []*Process { + if x != nil { + return x.Ancestors + } + return nil +} + type ProcessUprobe struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2499,6 +2615,12 @@ type ProcessUprobe struct { Args []*KprobeArgument `protobuf:"bytes,7,rep,name=args,proto3" json:"args,omitempty"` // Tags of the Tracing Policy to categorize the event. Tags []string `protobuf:"bytes,8,rep,name=tags,proto3" json:"tags,omitempty"` + // Ancestors of the process beyond the immediate parent. + Ancestors []*Process `protobuf:"bytes,9,rep,name=ancestors,proto3" json:"ancestors,omitempty"` + // uprobe offset (mutualy exclusive with symbol) + Offset uint64 `protobuf:"varint,10,opt,name=offset,proto3" json:"offset,omitempty"` + // uprobe ref_ctr_offset + RefCtrOffset uint64 `protobuf:"varint,11,opt,name=ref_ctr_offset,json=refCtrOffset,proto3" json:"ref_ctr_offset,omitempty"` } func (x *ProcessUprobe) ProtoReflect() protoreflect.Message { @@ -2561,6 +2683,27 @@ func (x *ProcessUprobe) GetTags() []string { return nil } +func (x *ProcessUprobe) GetAncestors() []*Process { + if x != nil { + return x.Ancestors + } + return nil +} + +func (x *ProcessUprobe) GetOffset() uint64 { + if x != nil { + return x.Offset + } + return 0 +} + +func (x *ProcessUprobe) GetRefCtrOffset() uint64 { + if x != nil { + return x.RefCtrOffset + } + return 0 +} + type ProcessLsm struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2580,6 +2723,8 @@ type ProcessLsm struct { Action KprobeAction `protobuf:"varint,8,opt,name=action,proto3,enum=tetragon.KprobeAction" json:"action,omitempty"` // Tags of the Tracing Policy to categorize the event. Tags []string `protobuf:"bytes,9,rep,name=tags,proto3" json:"tags,omitempty"` + // Ancestors of the process beyond the immediate parent. + Ancestors []*Process `protobuf:"bytes,10,rep,name=ancestors,proto3" json:"ancestors,omitempty"` // IMA file hash. Format algorithm:value. ImaHash string `protobuf:"bytes,11,opt,name=ima_hash,json=imaHash,proto3" json:"ima_hash,omitempty"` } @@ -2644,6 +2789,13 @@ func (x *ProcessLsm) GetTags() []string { return nil } +func (x *ProcessLsm) GetAncestors() []*Process { + if x != nil { + return x.Ancestors + } + return nil +} + func (x *ProcessLsm) GetImaHash() string { if x != nil { return x.ImaHash @@ -2924,6 +3076,8 @@ type CreateContainer struct { PodUID string `protobuf:"bytes,7,opt,name=podUID,proto3" json:"podUID,omitempty"` // podNamespace is the namespace of the pod PodNamespace string `protobuf:"bytes,8,opt,name=podNamespace,proto3" json:"podNamespace,omitempty"` + // containerImage is the full image location (repo + image) + ContainerImage string `protobuf:"bytes,9,opt,name=containerImage,proto3" json:"containerImage,omitempty"` } func (x *CreateContainer) ProtoReflect() protoreflect.Message { @@ -2986,6 +3140,13 @@ func (x *CreateContainer) GetPodNamespace() string { return "" } +func (x *CreateContainer) GetContainerImage() string { + if x != nil { + return x.ContainerImage + } + return "" +} + type StackTraceEntry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/event-processor/detector/api/tetragon/tetragon.proto b/event-processor/detector/api/tetragon/tetragon.proto index 0ce9e5ae..dc5ad629 100644 --- a/event-processor/detector/api/tetragon/tetragon.proto +++ b/event-processor/detector/api/tetragon/tetragon.proto @@ -3,652 +3,685 @@ syntax = "proto3"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/wrappers.proto"; - package tetragon; -import "tetragon/capabilities.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; import "tetragon/bpf.proto"; +import "tetragon/capabilities.proto"; + +option go_package = "github.com/cilium/tetragon/api/v1/tetragon"; message Image { - // Identifier of the container image composed of the registry path and the - // sha256. - string id = 1; - // Name of the container image composed of the registry path and the tag. - string name = 2; + // Identifier of the container image composed of the registry path and the + // sha256. + string id = 1; + // Name of the container image composed of the registry path and the tag. + string name = 2; +} + +message SecurityContext { + // True if this container is priviledged. + bool privileged = 1; } message Container { - // Identifier of the container. - string id = 1; - // Name of the container. - string name = 2; - // Image of the container. - Image image = 3; - // Start time of the container. - google.protobuf.Timestamp start_time = 4; - // Process identifier in the container namespace. - google.protobuf.UInt32Value pid = 5; - // If this is set true, it means that the process might have been originated from - // a Kubernetes exec probe. For this field to be true, the following must be true: - // 1. The binary field matches the first element of the exec command list for either - // liveness or readiness probe excluding the basename. For example, "/bin/ls" - // and "ls" are considered a match. - // 2. The arguments field exactly matches the rest of the exec command list. - bool maybe_exec_probe = 13; + // Identifier of the container. + string id = 1; + // Name of the container. + string name = 2; + // Image of the container. + Image image = 3; + // Start time of the container. + google.protobuf.Timestamp start_time = 4; + // Process identifier in the container namespace. + google.protobuf.UInt32Value pid = 5; + // If this is set true, it means that the process might have been originated from + // a Kubernetes exec probe. For this field to be true, the following must be true: + // 1. The binary field matches the first element of the exec command list for either + // liveness or readiness probe excluding the basename. For example, "/bin/ls" + // and "ls" are considered a match. + // 2. The arguments field exactly matches the rest of the exec command list. + bool maybe_exec_probe = 13; + // The security context of the container + SecurityContext security_context = 14; } message Pod { - // Kubernetes namespace of the Pod. - string namespace = 1; - // Name of the Pod. - string name = 2; - // Container of the Pod from which the process that triggered the event - // originates. - Container container = 4; - // Contains all the labels of the pod. - map pod_labels = 5; - // Kubernetes workload of the Pod. - string workload = 6; - // Kubernetes workload kind (e.g. "Deployment", "DaemonSet") of the Pod. - string workload_kind = 7; + // Kubernetes namespace of the Pod. + string namespace = 1; + // Name of the Pod. + string name = 2; + // Container of the Pod from which the process that triggered the event + // originates. + Container container = 4; + // Contains all the labels of the pod. + map pod_labels = 5; + // Kubernetes workload of the Pod. + string workload = 6; + // Kubernetes workload kind (e.g. "Deployment", "DaemonSet") of the Pod. + string workload_kind = 7; + // Contains all the annotations of the pod. + map pod_annotations = 8; } message Capabilities { - // Permitted set indicates what capabilities the process can use. This is a - // limiting superset for the effective capabilities that the thread may - // assume. It is also a limiting superset for the capabilities that may be - // added to the inheritable set by a thread without the CAP_SETPCAP in its - // effective set. - repeated CapabilitiesType permitted = 1; - // Effective set indicates what capabilities are active in a process. This - // is the set used by the kernel to perform permission checks for the - // thread. - repeated CapabilitiesType effective = 2; - // Inheritable set indicates which capabilities will be inherited by the - // current process when running as a root user. - repeated CapabilitiesType inheritable = 3; + // Permitted set indicates what capabilities the process can use. This is a + // limiting superset for the effective capabilities that the thread may + // assume. It is also a limiting superset for the capabilities that may be + // added to the inheritable set by a thread without the CAP_SETPCAP in its + // effective set. + repeated CapabilitiesType permitted = 1; + // Effective set indicates what capabilities are active in a process. This + // is the set used by the kernel to perform permission checks for the + // thread. + repeated CapabilitiesType effective = 2; + // Inheritable set indicates which capabilities will be inherited by the + // current process when running as a root user. + repeated CapabilitiesType inheritable = 3; } message Namespace { - // Inode number of the namespace. - uint32 inum = 1; - // Indicates if namespace belongs to host. - bool is_host = 2; + // Inode number of the namespace. + uint32 inum = 1; + // Indicates if namespace belongs to host. + bool is_host = 2; } message Namespaces { - // Hostname and NIS domain name. - Namespace uts = 1; - // System V IPC, POSIX message queues. - Namespace ipc = 2; - // Mount points. - Namespace mnt = 3; - // Process IDs. - Namespace pid = 4; - // Process IDs for children processes. - Namespace pid_for_children = 5; - // Network devices, stacks, ports, etc. - Namespace net = 6; - // Boot and monotonic clocks. - Namespace time = 7; - // Boot and monotonic clocks for children processes. - Namespace time_for_children = 8; - // Cgroup root directory. - Namespace cgroup = 9; - // User and group IDs. - Namespace user = 10; + // Hostname and NIS domain name. + Namespace uts = 1; + // System V IPC, POSIX message queues. + Namespace ipc = 2; + // Mount points. + Namespace mnt = 3; + // Process IDs. + Namespace pid = 4; + // Process IDs for children processes. + Namespace pid_for_children = 5; + // Network devices, stacks, ports, etc. + Namespace net = 6; + // Boot and monotonic clocks. + Namespace time = 7; + // Boot and monotonic clocks for children processes. + Namespace time_for_children = 8; + // Cgroup root directory. + Namespace cgroup = 9; + // User and group IDs. + Namespace user = 10; } message UserNamespace { - // Nested level of the user namespace. Init or host user namespace is at level 0. - google.protobuf.Int32Value level = 1; - // The owner user ID of the namespace - google.protobuf.UInt32Value uid = 2; - // The owner group ID of the namepace. - google.protobuf.UInt32Value gid = 3; - // The user namespace details that include the inode number of the namespace. - Namespace ns = 4; + // Nested level of the user namespace. Init or host user namespace is at level 0. + google.protobuf.Int32Value level = 1; + // The owner user ID of the namespace + google.protobuf.UInt32Value uid = 2; + // The owner group ID of the namepace. + google.protobuf.UInt32Value gid = 3; + // The user namespace details that include the inode number of the namespace. + Namespace ns = 4; } message ProcessCredentials { - // The real user ID of the process' owner. - google.protobuf.UInt32Value uid = 1; - // The real group ID of the process' owner. - google.protobuf.UInt32Value gid = 2; - // The effective user ID used for permission checks. - google.protobuf.UInt32Value euid = 3; - // The effective group ID used for permission checks. - google.protobuf.UInt32Value egid = 4; - // The saved user ID. - google.protobuf.UInt32Value suid = 5; - // The saved group ID. - google.protobuf.UInt32Value sgid = 6; - // the filesystem user ID used for filesystem access checks. Usually equals the euid. - google.protobuf.UInt32Value fsuid = 7; - // The filesystem group ID used for filesystem access checks. Usually equals the egid. - google.protobuf.UInt32Value fsgid = 8; - // Secure management flags - repeated SecureBitsType securebits = 9; - // Set of capabilities that define the permissions the process can execute with. - Capabilities caps = 10; - // User namespace where the UIDs, GIDs and capabilities are relative to. - UserNamespace user_ns = 11; + // The real user ID of the process' owner. + google.protobuf.UInt32Value uid = 1; + // The real group ID of the process' owner. + google.protobuf.UInt32Value gid = 2; + // The effective user ID used for permission checks. + google.protobuf.UInt32Value euid = 3; + // The effective group ID used for permission checks. + google.protobuf.UInt32Value egid = 4; + // The saved user ID. + google.protobuf.UInt32Value suid = 5; + // The saved group ID. + google.protobuf.UInt32Value sgid = 6; + // the filesystem user ID used for filesystem access checks. Usually equals the euid. + google.protobuf.UInt32Value fsuid = 7; + // The filesystem group ID used for filesystem access checks. Usually equals the egid. + google.protobuf.UInt32Value fsgid = 8; + // Secure management flags + repeated SecureBitsType securebits = 9; + // Set of capabilities that define the permissions the process can execute with. + Capabilities caps = 10; + // User namespace where the UIDs, GIDs and capabilities are relative to. + UserNamespace user_ns = 11; } message InodeProperties { - // The inode number - uint64 number = 1; - // The inode links on the file system. If zero means the file is only in memory - google.protobuf.UInt32Value links = 2; + // The inode number + uint64 number = 1; + // The inode links on the file system. If zero means the file is only in memory + google.protobuf.UInt32Value links = 2; } message FileProperties { - // Inode of the file - InodeProperties inode = 1; - // Path of the file - string path = 2; + // Inode of the file + InodeProperties inode = 1; + // Path of the file + string path = 2; } message BinaryProperties { - // If set then this is the set user ID used for execution - google.protobuf.UInt32Value setuid = 1; - // If set then this is the set group ID used for execution - google.protobuf.UInt32Value setgid = 2; - // The reasons why this binary execution changed privileges. Usually this happens when the process executes - // a binary with the set-user-ID to root or file capability sets. - // The final granted privileges can be listed inside the `process_credentials` or capabilities fields part of of the `process` object. - repeated ProcessPrivilegesChanged privileges_changed = 3; - // File properties in case the executed binary is: - // 1. An anonymous shared memory file https://man7.org/linux/man-pages/man7/shm_overview.7.html. - // 2. An anonymous file obtained with memfd API https://man7.org/linux/man-pages/man2/memfd_create.2.html. - // 3. Or it was deleted from the file system. - FileProperties file = 4; + // If set then this is the set user ID used for execution + google.protobuf.UInt32Value setuid = 1; + // If set then this is the set group ID used for execution + google.protobuf.UInt32Value setgid = 2; + // The reasons why this binary execution changed privileges. Usually this happens when the process executes + // a binary with the set-user-ID to root or file capability sets. + // The final granted privileges can be listed inside the `process_credentials` or capabilities fields part of of the `process` object. + repeated ProcessPrivilegesChanged privileges_changed = 3; + // File properties in case the executed binary is: + // 1. An anonymous shared memory file https://man7.org/linux/man-pages/man7/shm_overview.7.html. + // 2. An anonymous file obtained with memfd API https://man7.org/linux/man-pages/man2/memfd_create.2.html. + // 3. Or it was deleted from the file system. + FileProperties file = 4; } // User records message UserRecord { - // The UNIX username for this record. Corresponds to `pw_name` field of [struct passwd](https://man7.org/linux/man-pages/man3/getpwnam.3.html) - // and the `sp_namp` field of [struct spwd](https://man7.org/linux/man-pages/man3/getspnam.3.html). - string name = 1; + // The UNIX username for this record. Corresponds to `pw_name` field of [struct passwd](https://man7.org/linux/man-pages/man3/getpwnam.3.html) + // and the `sp_namp` field of [struct spwd](https://man7.org/linux/man-pages/man3/getspnam.3.html). + string name = 1; } message Process { - // Exec ID uniquely identifies the process over time across all the nodes in the cluster. - string exec_id = 1; - // Process identifier from host PID namespace. - google.protobuf.UInt32Value pid = 2; - // The effective User identifier used for permission checks. This field maps to the - // 'ProcessCredentials.euid' field. Run with the `--enable-process-cred` flag to - // enable 'ProcessCredentials' and get all the User and Group identifiers. - google.protobuf.UInt32Value uid = 3; - // Current working directory of the process. - string cwd = 4; - // Absolute path of the executed binary. - string binary = 5; - // Arguments passed to the binary at execution. - string arguments = 6; - // Flags are for debugging purposes only and should not be considered a - // reliable source of information. They hold various information about - // which syscalls generated events, use of internal Tetragon buffers, - // errors and more. - // - `execve` This event is generated by an execve syscall for a new - // process. See procFs for the other option. A correctly formatted event - // should either set execve or procFS (described next). - // - `procFS` This event is generated from a proc interface. This happens - // at Tetragon init when existing processes are being loaded into Tetragon - // event buffer. All events should have either execve or procFS set. - // - `truncFilename` Indicates a truncated processes filename because the - // buffer size is too small to contain the process filename. Consider - // increasing buffer size to avoid this. - // - `truncArgs` Indicates truncated the processes arguments because the - // buffer size was too small to contain all exec args. Consider increasing - // buffer size to avoid this. - // - `taskWalk` Primarily useful for debugging. Indicates a walked process - // hierarchy to find a parent process in the Tetragon buffer. This may - // happen when we did not receive an exec event for the immediate parent of - // a process. Typically means we are looking at a fork that in turn did - // another fork we don't currently track fork events exactly and instead - // push an event with the original parent exec data. This flag can provide - // this insight into the event if needed. - // - `miss` An error flag indicating we could not find parent info in the - // Tetragon event buffer. If this is set it should be reported to Tetragon - // developers for debugging. Tetragon will do its best to recover - // information about the process from available kernel data structures - // instead of using cached info in this case. However, args will not be - // available. - // - `needsAUID` An internal flag for Tetragon to indicate the audit has - // not yet been resolved. The BPF hooks look at this flag to determine if - // probing the audit system is necessary. - // - `errorFilename` An error flag indicating an error happened while - // reading the filename. If this is set it should be reported to Tetragon - // developers for debugging. - // - `errorArgs` An error flag indicating an error happened while reading - // the process args. If this is set it should be reported to Tetragon - // developers for debugging - // - `needsCWD` An internal flag for Tetragon to indicate the current - // working directory has not yet been resolved. The Tetragon hooks look at - // this flag to determine if probing the CWD is necessary. - // - `noCWDSupport` Indicates that CWD is removed from the event because - // the buffer size is too small. Consider increasing buffer size to avoid - // this. - // - `rootCWD` Indicates that CWD is the root directory. This is necessary - // to inform readers the CWD is not in the event buffer and is '/' instead. - // - `errorCWD` An error flag indicating an error occurred while reading - // the CWD of a process. If this is set it should be reported to Tetragon - // developers for debugging. - // - `clone` Indicates the process issued a clone before exec*. This is the - // general flow to exec* a new process, however its possible to replace the - // current process with a new process by doing an exec* without a clone. In - // this case the flag will be omitted and the same PID will be used by the - // kernel for both the old process and the newly exec'd process. - string flags = 7; - // Start time of the execution. - google.protobuf.Timestamp start_time = 8; - // Audit user ID, this ID is assigned to a user upon login and is inherited - // by every process even when the user's identity changes. For example, by - // switching user accounts with su - john. - google.protobuf.UInt32Value auid = 9; - // Information about the the Kubernetes Pod where the event originated. - Pod pod = 10; - // The 15 first digits of the container ID. - string docker = 11; - // Exec ID of the parent process. - string parent_exec_id = 12; - // Reference counter from the Tetragon process cache. - uint32 refcnt = 13; - // Set of capabilities that define the permissions the process can execute with. - Capabilities cap = 14; - // Linux namespaces of the process, disabled by default, can be enabled by - // the `--enable-process-ns` flag. - Namespaces ns = 15; - // Thread ID, note that for the thread group leader, tid is equal to pid. - google.protobuf.UInt32Value tid = 16; - // Process credentials, disabled by default, can be enabled by the - // `--enable-process-cred` flag. - ProcessCredentials process_credentials = 17; - // Executed binary properties. This field is only available on ProcessExec events. - BinaryProperties binary_properties = 18; - // UserRecord contains user information about the event. - // It is only supported when i) Tetragon is running as a systemd service or directly on the host, and - // ii) when the flag `--username-metadata` is set to "unix". In this case, the information is retrieved from - // the traditional user database `/etc/passwd` and no name services lookups are performed. - // The resolution will only be attempted for processes in the host namespace. - // Note that this resolution happens in user-space, which means that mapping might have changed - // between the in-kernel BPF hook being executed and the username resolution. - UserRecord user = 19; - // If set to true, this process is containerized and is a member of the - // process tree rooted at pid=1 in its PID namespace. This is useful if, - // for example, you wish to discern whether a process was spawned using a - // tool like nsenter or kubectl exec. - google.protobuf.BoolValue in_init_tree = 20; + // Exec ID uniquely identifies the process over time across all the nodes in the cluster. + string exec_id = 1; + // Process identifier from host PID namespace. + google.protobuf.UInt32Value pid = 2; + // The effective User identifier used for permission checks. This field maps to the + // 'ProcessCredentials.euid' field. Run with the `--enable-process-cred` flag to + // enable 'ProcessCredentials' and get all the User and Group identifiers. + google.protobuf.UInt32Value uid = 3; + // Current working directory of the process. + string cwd = 4; + // Absolute path of the executed binary. + string binary = 5; + // Arguments passed to the binary at execution. + string arguments = 6; + // Flags are for debugging purposes only and should not be considered a + // reliable source of information. They hold various information about + // which syscalls generated events, use of internal Tetragon buffers, + // errors and more. + // - `execve` This event is generated by an execve syscall for a new + // process. See procFs for the other option. A correctly formatted event + // should either set execve or procFS (described next). + // - `procFS` This event is generated from a proc interface. This happens + // at Tetragon init when existing processes are being loaded into Tetragon + // event buffer. All events should have either execve or procFS set. + // - `truncFilename` Indicates a truncated processes filename because the + // buffer size is too small to contain the process filename. Consider + // increasing buffer size to avoid this. + // - `truncArgs` Indicates truncated the processes arguments because the + // buffer size was too small to contain all exec args. Consider increasing + // buffer size to avoid this. + // - `taskWalk` Primarily useful for debugging. Indicates a walked process + // hierarchy to find a parent process in the Tetragon buffer. This may + // happen when we did not receive an exec event for the immediate parent of + // a process. Typically means we are looking at a fork that in turn did + // another fork we don't currently track fork events exactly and instead + // push an event with the original parent exec data. This flag can provide + // this insight into the event if needed. + // - `miss` An error flag indicating we could not find parent info in the + // Tetragon event buffer. If this is set it should be reported to Tetragon + // developers for debugging. Tetragon will do its best to recover + // information about the process from available kernel data structures + // instead of using cached info in this case. However, args will not be + // available. + // - `needsAUID` An internal flag for Tetragon to indicate the audit has + // not yet been resolved. The BPF hooks look at this flag to determine if + // probing the audit system is necessary. + // - `errorFilename` An error flag indicating an error happened while + // reading the filename. If this is set it should be reported to Tetragon + // developers for debugging. + // - `errorArgs` An error flag indicating an error happened while reading + // the process args. If this is set it should be reported to Tetragon + // developers for debugging + // - `needsCWD` An internal flag for Tetragon to indicate the current + // working directory has not yet been resolved. The Tetragon hooks look at + // this flag to determine if probing the CWD is necessary. + // - `noCWDSupport` Indicates that CWD is removed from the event because + // the buffer size is too small. Consider increasing buffer size to avoid + // this. + // - `rootCWD` Indicates that CWD is the root directory. This is necessary + // to inform readers the CWD is not in the event buffer and is '/' instead. + // - `errorCWD` An error flag indicating an error occurred while reading + // the CWD of a process. If this is set it should be reported to Tetragon + // developers for debugging. + // - `clone` Indicates the process issued a clone before exec*. This is the + // general flow to exec* a new process, however its possible to replace the + // current process with a new process by doing an exec* without a clone. In + // this case the flag will be omitted and the same PID will be used by the + // kernel for both the old process and the newly exec'd process. + // - `unknown` Indicates the process was not found in the process cache + // and contains just pid and start time. + string flags = 7; + // Start time of the execution. + google.protobuf.Timestamp start_time = 8; + // Audit user ID, this ID is assigned to a user upon login and is inherited + // by every process even when the user's identity changes. For example, by + // switching user accounts with su - john. + google.protobuf.UInt32Value auid = 9; + // Information about the the Kubernetes Pod where the event originated. + Pod pod = 10; + // The 15 first digits of the container ID. + string docker = 11; + // Exec ID of the parent process. + string parent_exec_id = 12; + // Reference counter from the Tetragon process cache. + uint32 refcnt = 13; + // Set of capabilities that define the permissions the process can execute with. + Capabilities cap = 14; + // Linux namespaces of the process, disabled by default, can be enabled by + // the `--enable-process-ns` flag. + Namespaces ns = 15; + // Thread ID, note that for the thread group leader, tid is equal to pid. + google.protobuf.UInt32Value tid = 16; + // Process credentials, disabled by default, can be enabled by the + // `--enable-process-cred` flag. + ProcessCredentials process_credentials = 17; + // Executed binary properties. This field is only available on ProcessExec events. + BinaryProperties binary_properties = 18; + // UserRecord contains user information about the event. + // It is only supported when i) Tetragon is running as a systemd service or directly on the host, and + // ii) when the flag `--username-metadata` is set to "unix". In this case, the information is retrieved from + // the traditional user database `/etc/passwd` and no name services lookups are performed. + // The resolution will only be attempted for processes in the host namespace. + // Note that this resolution happens in user-space, which means that mapping might have changed + // between the in-kernel BPF hook being executed and the username resolution. + UserRecord user = 19; + // If set to true, this process is containerized and is a member of the + // process tree rooted at pid=1 in its PID namespace. This is useful if, + // for example, you wish to discern whether a process was spawned using a + // tool like nsenter or kubectl exec. + google.protobuf.BoolValue in_init_tree = 20; } message ProcessExec { - // Process that triggered the exec. - Process process = 1; - // Immediate parent of the process. - Process parent = 2; - // Ancestors of the process beyond the immediate parent. - repeated Process ancestors = 3; + // Process that triggered the exec. + Process process = 1; + // Immediate parent of the process. + Process parent = 2; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 3; } message ProcessExit { - // Process that triggered the exit. - Process process = 1; - // Immediate parent of the process. - Process parent = 2; - // Signal that the process received when it exited, for example SIGKILL or - // SIGTERM (list all signal names with `kill -l`). If there is no signal - // handler implemented for a specific process, we report the exit status - // code that can be found in the status field. - string signal = 3; - // Status code on process exit. For example, the status code can indicate - // if an error was encountered or the program exited successfully. - uint32 status = 4; - // Date and time of the event. - google.protobuf.Timestamp time = 5; + // Process that triggered the exit. + Process process = 1; + // Immediate parent of the process. + Process parent = 2; + // Signal that the process received when it exited, for example SIGKILL or + // SIGTERM (list all signal names with `kill -l`). If there is no signal + // handler implemented for a specific process, we report the exit status + // code that can be found in the status field. + string signal = 3; + // Status code on process exit. For example, the status code can indicate + // if an error was encountered or the program exited successfully. + uint32 status = 4; + // Date and time of the event. + google.protobuf.Timestamp time = 5; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 6; } message KprobeSock { - string family = 1; - string type = 2; - string protocol = 3; - uint32 mark = 4; - uint32 priority = 5; - string saddr = 6; - string daddr = 7; - uint32 sport = 8; - uint32 dport = 9; - uint64 cookie = 10; - string state = 11; + string family = 1; + string type = 2; + string protocol = 3; + uint32 mark = 4; + uint32 priority = 5; + string saddr = 6; + string daddr = 7; + uint32 sport = 8; + uint32 dport = 9; + uint64 cookie = 10; + string state = 11; } message KprobeSkb { - uint32 hash = 1; - uint32 len = 2; - uint32 priority = 3; - uint32 mark = 4; - string saddr = 5; - string daddr = 6; - uint32 sport = 7; - uint32 dport = 8; - uint32 proto = 9; - uint32 sec_path_len = 10; - uint32 sec_path_olen = 11; - string protocol = 12; - string family = 13; + uint32 hash = 1; + uint32 len = 2; + uint32 priority = 3; + uint32 mark = 4; + string saddr = 5; + string daddr = 6; + uint32 sport = 7; + uint32 dport = 8; + uint32 proto = 9; + uint32 sec_path_len = 10; + uint32 sec_path_olen = 11; + string protocol = 12; + string family = 13; +} + +message KprobeSockaddr { + string family = 1; + string addr = 2; + uint32 port = 3; } message KprobeNetDev { - string name = 1; + string name = 1; } message KprobePath { - string mount = 1; - string path = 2; - string flags = 3; - string permission = 4; + string mount = 1; + string path = 2; + string flags = 3; + string permission = 4; } message KprobeFile { - string mount = 1; - string path = 2; - string flags = 3; - string permission = 4; + string mount = 1; + string path = 2; + string flags = 3; + string permission = 4; } message KprobeTruncatedBytes { - bytes bytes_arg = 1; - uint64 orig_size = 2; + bytes bytes_arg = 1; + uint64 orig_size = 2; } message KprobeCred { - repeated CapabilitiesType permitted = 1; - repeated CapabilitiesType effective = 2; - repeated CapabilitiesType inheritable = 3; + repeated CapabilitiesType permitted = 1; + repeated CapabilitiesType effective = 2; + repeated CapabilitiesType inheritable = 3; } message KprobeLinuxBinprm { - string path = 1; - string flags = 2; - string permission = 3; + string path = 1; + string flags = 2; + string permission = 3; } message KprobeCapability { - google.protobuf.Int32Value value = 1; - string name = 2; + google.protobuf.Int32Value value = 1; + string name = 2; } message KprobeUserNamespace { - google.protobuf.Int32Value level = 1; - google.protobuf.UInt32Value owner = 2; - google.protobuf.UInt32Value group = 3; - Namespace ns = 4; + google.protobuf.Int32Value level = 1; + google.protobuf.UInt32Value owner = 2; + google.protobuf.UInt32Value group = 3; + Namespace ns = 4; } message KprobeBpfAttr { - string ProgType = 1; - uint32 InsnCnt = 2; - string ProgName = 3; + string ProgType = 1; + uint32 InsnCnt = 2; + string ProgName = 3; } message KprobePerfEvent { - string KprobeFunc = 1; - string Type = 2; - uint64 Config = 3; - uint64 ProbeOffset = 4; + string KprobeFunc = 1; + string Type = 2; + uint64 Config = 3; + uint64 ProbeOffset = 4; } message KprobeBpfMap { - string MapType = 1; - uint32 KeySize = 2; - uint32 ValueSize = 3; - uint32 MaxEntries = 4; - string MapName = 5; + string MapType = 1; + uint32 KeySize = 2; + uint32 ValueSize = 3; + uint32 MaxEntries = 4; + string MapName = 5; } message SyscallId { - uint32 id = 1; - string abi = 2; + uint32 id = 1; + string abi = 2; } message KprobeArgument { - oneof arg { - string string_arg = 1; - int32 int_arg = 2; - KprobeSkb skb_arg = 3; - uint64 size_arg = 4; - bytes bytes_arg = 5; - KprobePath path_arg = 6; - KprobeFile file_arg = 7; - KprobeTruncatedBytes truncated_bytes_arg = 8; - KprobeSock sock_arg = 9; - KprobeCred cred_arg = 10; - int64 long_arg = 11; - KprobeBpfAttr bpf_attr_arg = 12; - KprobePerfEvent perf_event_arg = 13; - KprobeBpfMap bpf_map_arg = 14; - uint32 uint_arg = 15; - KprobeUserNamespace user_namespace_arg = 16 [deprecated = true]; - KprobeCapability capability_arg = 17; - ProcessCredentials process_credentials_arg = 19; - UserNamespace user_ns_arg = 20; - KernelModule module_arg = 21; - string kernel_cap_t_arg = 22; // Capabilities in hexadecimal format. - string cap_inheritable_arg = 23; // Capabilities inherited by a forked process in hexadecimal format. - string cap_permitted_arg = 24; // Capabilities that are currently permitted in hexadecimal format. - string cap_effective_arg = 25; // Capabilities that are actually used in hexadecimal format. - KprobeLinuxBinprm linux_binprm_arg = 26; - KprobeNetDev net_dev_arg = 27; - BpfCmd bpf_cmd_arg = 28; - SyscallId syscall_id = 29; - } - string label = 18; + oneof arg { + string string_arg = 1; + int32 int_arg = 2; + KprobeSkb skb_arg = 3; + uint64 size_arg = 4; + bytes bytes_arg = 5; + KprobePath path_arg = 6; + KprobeFile file_arg = 7; + KprobeTruncatedBytes truncated_bytes_arg = 8; + KprobeSock sock_arg = 9; + KprobeCred cred_arg = 10; + int64 long_arg = 11; + KprobeBpfAttr bpf_attr_arg = 12; + KprobePerfEvent perf_event_arg = 13; + KprobeBpfMap bpf_map_arg = 14; + uint32 uint_arg = 15; + KprobeUserNamespace user_namespace_arg = 16 [deprecated = true]; + KprobeCapability capability_arg = 17; + ProcessCredentials process_credentials_arg = 19; + UserNamespace user_ns_arg = 20; + KernelModule module_arg = 21; + string kernel_cap_t_arg = 22; // Capabilities in hexadecimal format. + string cap_inheritable_arg = 23; // Capabilities inherited by a forked process in hexadecimal format. + string cap_permitted_arg = 24; // Capabilities that are currently permitted in hexadecimal format. + string cap_effective_arg = 25; // Capabilities that are actually used in hexadecimal format. + KprobeLinuxBinprm linux_binprm_arg = 26; + KprobeNetDev net_dev_arg = 27; + BpfCmd bpf_cmd_arg = 28; + SyscallId syscall_id = 29; + KprobeSockaddr sockaddr_arg = 30; + } + string label = 18; } enum KprobeAction { - // Unknown action - KPROBE_ACTION_UNKNOWN = 0; - // Post action creates an event (default action). - KPROBE_ACTION_POST = 1; - // Post action creates a mapping between file descriptors and file names. - KPROBE_ACTION_FOLLOWFD = 2; - // Sigkill action synchronously terminates the process. - KPROBE_ACTION_SIGKILL = 3; - // Post action removes a mapping between file descriptors and file names. - KPROBE_ACTION_UNFOLLOWFD = 4; - // Override action modifies the return value of the call. - KPROBE_ACTION_OVERRIDE = 5; - // Post action dupplicates a mapping between file descriptors and file - // names. - KPROBE_ACTION_COPYFD = 6; - // GetURL action issue an HTTP Get request against an URL from userspace. - KPROBE_ACTION_GETURL = 7; - // GetURL action issue a DNS lookup against an URL from userspace. - KPROBE_ACTION_DNSLOOKUP = 8; - // NoPost action suppresses the transmission of the event to userspace. - KPROBE_ACTION_NOPOST = 9; - // Signal action sends specified signal to the process. - KPROBE_ACTION_SIGNAL = 10; - // TrackSock action tracks socket. - KPROBE_ACTION_TRACKSOCK = 11; - // UntrackSock action un-tracks socket. - KPROBE_ACTION_UNTRACKSOCK = 12; - // NotifyEnforcer action notifies enforcer sensor. - KPROBE_ACTION_NOTIFYENFORCER = 13; - // CleanupEnforcerNotification action cleanups any state left by NotifyEnforcer - KPROBE_ACTION_CLEANUPENFORCERNOTIFICATION = 14; + // Unknown action + KPROBE_ACTION_UNKNOWN = 0; + // Post action creates an event (default action). + KPROBE_ACTION_POST = 1; + // Post action creates a mapping between file descriptors and file names. + KPROBE_ACTION_FOLLOWFD = 2; + // Sigkill action synchronously terminates the process. + KPROBE_ACTION_SIGKILL = 3; + // Post action removes a mapping between file descriptors and file names. + KPROBE_ACTION_UNFOLLOWFD = 4; + // Override action modifies the return value of the call. + KPROBE_ACTION_OVERRIDE = 5; + // Post action dupplicates a mapping between file descriptors and file + // names. + KPROBE_ACTION_COPYFD = 6; + // GetURL action issue an HTTP Get request against an URL from userspace. + KPROBE_ACTION_GETURL = 7; + // GetURL action issue a DNS lookup against an URL from userspace. + KPROBE_ACTION_DNSLOOKUP = 8; + // NoPost action suppresses the transmission of the event to userspace. + KPROBE_ACTION_NOPOST = 9; + // Signal action sends specified signal to the process. + KPROBE_ACTION_SIGNAL = 10; + // TrackSock action tracks socket. + KPROBE_ACTION_TRACKSOCK = 11; + // UntrackSock action un-tracks socket. + KPROBE_ACTION_UNTRACKSOCK = 12; + // NotifyEnforcer action notifies enforcer sensor. + KPROBE_ACTION_NOTIFYENFORCER = 13; + // CleanupEnforcerNotification action cleanups any state left by NotifyEnforcer + KPROBE_ACTION_CLEANUPENFORCERNOTIFICATION = 14; } message ProcessKprobe { - // Process that triggered the kprobe. - Process process = 1; - // Immediate parent of the process. - Process parent = 2; - // Symbol on which the kprobe was attached. - string function_name = 3; - // Arguments definition of the observed kprobe. - repeated KprobeArgument args = 4; - // Return value definition of the observed kprobe. - KprobeArgument return = 5; - // Action performed when the kprobe matched. - KprobeAction action = 6; - // Kernel stack trace to the call. - repeated StackTraceEntry kernel_stack_trace = 7; - // Name of the Tracing Policy that created that kprobe. - string policy_name = 8; - // Action performed when the return kprobe executed. - KprobeAction return_action = 9; - // Short message of the Tracing Policy to inform users what is going on. - string message = 10; - // Tags of the Tracing Policy to categorize the event. - repeated string tags = 11; - // User-mode stack trace to the call. - repeated StackTraceEntry user_stack_trace = 12; + // Process that triggered the kprobe. + Process process = 1; + // Immediate parent of the process. + Process parent = 2; + // Symbol on which the kprobe was attached. + string function_name = 3; + // Arguments definition of the observed kprobe. + repeated KprobeArgument args = 4; + // Return value definition of the observed kprobe. + KprobeArgument return = 5; + // Action performed when the kprobe matched. + KprobeAction action = 6; + // Kernel stack trace to the call. + repeated StackTraceEntry kernel_stack_trace = 7; + // Name of the Tracing Policy that created that kprobe. + string policy_name = 8; + // Action performed when the return kprobe executed. + KprobeAction return_action = 9; + // Short message of the Tracing Policy to inform users what is going on. + string message = 10; + // Tags of the Tracing Policy to categorize the event. + repeated string tags = 11; + // User-mode stack trace to the call. + repeated StackTraceEntry user_stack_trace = 12; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 13; } message ProcessTracepoint { - // Process that triggered the tracepoint. - Process process = 1; - // Immediate parent of the process. - Process parent = 2; - // Subsystem of the tracepoint. - string subsys = 4; - // Event of the subsystem. - string event = 5; - // Arguments definition of the observed tracepoint. - // TODO: once we implement all we want, rename KprobeArgument to GenericArgument - repeated KprobeArgument args = 6; - // Name of the policy that created that tracepoint. - string policy_name = 7; - // Action performed when the tracepoint matched. - KprobeAction action = 8; - // Short message of the Tracing Policy to inform users what is going on. - string message = 9; - // Tags of the Tracing Policy to categorize the event. - repeated string tags = 10; + // Process that triggered the tracepoint. + Process process = 1; + // Immediate parent of the process. + Process parent = 2; + // Subsystem of the tracepoint. + string subsys = 4; + // Event of the subsystem. + string event = 5; + // Arguments definition of the observed tracepoint. + // TODO: once we implement all we want, rename KprobeArgument to GenericArgument + repeated KprobeArgument args = 6; + // Name of the policy that created that tracepoint. + string policy_name = 7; + // Action performed when the tracepoint matched. + KprobeAction action = 8; + // Short message of the Tracing Policy to inform users what is going on. + string message = 9; + // Tags of the Tracing Policy to categorize the event. + repeated string tags = 10; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 11; } message ProcessUprobe { - Process process = 1; - Process parent = 2; - string path = 3; - string symbol = 4; - // Name of the policy that created that uprobe. - string policy_name = 5; - // Short message of the Tracing Policy to inform users what is going on. - string message = 6; - // Arguments definition of the observed uprobe. - repeated KprobeArgument args = 7; - // Tags of the Tracing Policy to categorize the event. - repeated string tags = 8; + Process process = 1; + Process parent = 2; + string path = 3; + string symbol = 4; + // Name of the policy that created that uprobe. + string policy_name = 5; + // Short message of the Tracing Policy to inform users what is going on. + string message = 6; + // Arguments definition of the observed uprobe. + repeated KprobeArgument args = 7; + // Tags of the Tracing Policy to categorize the event. + repeated string tags = 8; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 9; + // uprobe offset (mutualy exclusive with symbol) + uint64 offset = 10; + // uprobe ref_ctr_offset + uint64 ref_ctr_offset = 11; } message ProcessLsm { - Process process = 1; - Process parent = 2; - // LSM hook name. - string function_name = 3; - // Name of the policy that created that LSM hook. - string policy_name = 5; - // Short message of the Tracing Policy to inform users what is going on. - string message = 6; - // Arguments definition of the observed LSM hook. - repeated KprobeArgument args = 7; - // Action performed when the LSM hook matched. - KprobeAction action = 8; - // Tags of the Tracing Policy to categorize the event. - repeated string tags = 9; - // IMA file hash. Format algorithm:value. - string ima_hash = 11; + Process process = 1; + Process parent = 2; + // LSM hook name. + string function_name = 3; + // Name of the policy that created that LSM hook. + string policy_name = 5; + // Short message of the Tracing Policy to inform users what is going on. + string message = 6; + // Arguments definition of the observed LSM hook. + repeated KprobeArgument args = 7; + // Action performed when the LSM hook matched. + KprobeAction action = 8; + // Tags of the Tracing Policy to categorize the event. + repeated string tags = 9; + // Ancestors of the process beyond the immediate parent. + repeated Process ancestors = 10; + // IMA file hash. Format algorithm:value. + string ima_hash = 11; } message KernelModule { - // Kernel module name - string name = 1; - // If true the module signature was verified successfully. Depends on kernels compiled with - // CONFIG_MODULE_SIG option, for details please read: https://www.kernel.org/doc/Documentation/admin-guide/module-signing.rst - google.protobuf.BoolValue signature_ok = 2; - // The module tainted flags that will be applied on the kernel. For further details please read: https://docs.kernel.org/admin-guide/tainted-kernels.html - repeated TaintedBitsType tainted = 3; + // Kernel module name + string name = 1; + // If true the module signature was verified successfully. Depends on kernels compiled with + // CONFIG_MODULE_SIG option, for details please read: https://www.kernel.org/doc/Documentation/admin-guide/module-signing.rst + google.protobuf.BoolValue signature_ok = 2; + // The module tainted flags that will be applied on the kernel. For further details please read: https://docs.kernel.org/admin-guide/tainted-kernels.html + repeated TaintedBitsType tainted = 3; } message Test { - uint64 arg0 = 1; - uint64 arg1 = 2; - uint64 arg2 = 3; - uint64 arg3 = 4; + uint64 arg0 = 1; + uint64 arg1 = 2; + uint64 arg2 = 3; + uint64 arg3 = 4; } enum HealthStatusType { - HEALTH_STATUS_TYPE_UNDEF = 0; - HEALTH_STATUS_TYPE_STATUS = 1; + HEALTH_STATUS_TYPE_UNDEF = 0; + HEALTH_STATUS_TYPE_STATUS = 1; } enum HealthStatusResult { - HEALTH_STATUS_UNDEF = 0; - HEALTH_STATUS_RUNNING = 1; - HEALTH_STATUS_STOPPED = 2; - HEALTH_STATUS_ERROR = 3; + HEALTH_STATUS_UNDEF = 0; + HEALTH_STATUS_RUNNING = 1; + HEALTH_STATUS_STOPPED = 2; + HEALTH_STATUS_ERROR = 3; } message GetHealthStatusRequest { - repeated HealthStatusType event_set = 1; + repeated HealthStatusType event_set = 1; } // Tainted bits to indicate if the kernel was tainted. For further details: https://docs.kernel.org/admin-guide/tainted-kernels.html enum TaintedBitsType { - TAINT_UNSET = 0; + TAINT_UNSET = 0; - /* A proprietary module was loaded. */ - TAINT_PROPRIETARY_MODULE = 1; + /* A proprietary module was loaded. */ + TAINT_PROPRIETARY_MODULE = 1; - /* A module was force loaded. */ - TAINT_FORCED_MODULE = 2; + /* A module was force loaded. */ + TAINT_FORCED_MODULE = 2; - /* A module was force unloaded. */ - TAINT_FORCED_UNLOAD_MODULE = 4; + /* A module was force unloaded. */ + TAINT_FORCED_UNLOAD_MODULE = 4; - /* A staging driver was loaded. */ - TAINT_STAGED_MODULE = 1024; + /* A staging driver was loaded. */ + TAINT_STAGED_MODULE = 1024; - /* An out of tree module was loaded. */ - TAINT_OUT_OF_TREE_MODULE = 4096; + /* An out of tree module was loaded. */ + TAINT_OUT_OF_TREE_MODULE = 4096; - /* An unsigned module was loaded. Supported only on kernels built with CONFIG_MODULE_SIG option. */ - TAINT_UNSIGNED_MODULE = 8192; + /* An unsigned module was loaded. Supported only on kernels built with CONFIG_MODULE_SIG option. */ + TAINT_UNSIGNED_MODULE = 8192; - /* The kernel has been live patched. */ - TAINT_KERNEL_LIVE_PATCH_MODULE = 32768; + /* The kernel has been live patched. */ + TAINT_KERNEL_LIVE_PATCH_MODULE = 32768; - /* Loading a test module. */ - TAINT_TEST_MODULE = 262144; + /* Loading a test module. */ + TAINT_TEST_MODULE = 262144; } message HealthStatus { - HealthStatusType event = 1; - HealthStatusResult status = 2; - string details = 3; + HealthStatusType event = 1; + HealthStatusResult status = 2; + string details = 3; } message GetHealthStatusResponse { - repeated HealthStatus health_status = 1; + repeated HealthStatus health_status = 1; } // loader sensor event triggered for loaded binary/library message ProcessLoader { - Process process = 1; - string path = 2; - bytes buildid = 3; + Process process = 1; + string path = 2; + bytes buildid = 3; } // RuntimeHookRequest synchronously propagates information to the agent about run-time state. message RuntimeHookRequest { - oneof event { - CreateContainer createContainer = 1; - } + oneof event { + CreateContainer createContainer = 1; + } } message RuntimeHookResponse {} @@ -662,34 +695,36 @@ message RuntimeHookResponse {} // annotations as a convenience, and may be left empty if the corresponding annotations are not // found. message CreateContainer { - // cgroupsPath is the cgroups path for the container. The path is expected to be relative to the - // cgroups mountpoint. See: https://github.com/opencontainers/runtime-spec/blob/58ec43f9fc39e0db229b653ae98295bfde74aeab/specs-go/config.go#L174 - string cgroupsPath = 1; - // rootDir is the absolute path of the root directory of the container. - // See: https://github.com/opencontainers/runtime-spec/blob/main/specs-go/config.go#L174 - string rootDir = 2; - // annotations are the run-time annotations for the container - // see https://github.com/opencontainers/runtime-spec/blob/main/config.md#annotations - map annotations = 3; - // containerName is the name of the container - string containerName = 4; - // containerID is the id of the container - string containerID = 5; - // podName is the pod name - string podName = 6; - // podUID is the pod uid - string podUID = 7; - // podNamespace is the namespace of the pod - string podNamespace = 8; + // cgroupsPath is the cgroups path for the container. The path is expected to be relative to the + // cgroups mountpoint. See: https://github.com/opencontainers/runtime-spec/blob/58ec43f9fc39e0db229b653ae98295bfde74aeab/specs-go/config.go#L174 + string cgroupsPath = 1; + // rootDir is the absolute path of the root directory of the container. + // See: https://github.com/opencontainers/runtime-spec/blob/main/specs-go/config.go#L174 + string rootDir = 2; + // annotations are the run-time annotations for the container + // see https://github.com/opencontainers/runtime-spec/blob/main/config.md#annotations + map annotations = 3; + // containerName is the name of the container + string containerName = 4; + // containerID is the id of the container + string containerID = 5; + // podName is the pod name + string podName = 6; + // podUID is the pod uid + string podUID = 7; + // podNamespace is the namespace of the pod + string podNamespace = 8; + // containerImage is the full image location (repo + image) + string containerImage = 9; } message StackTraceEntry { - // linear address of the function in kernel or user space. - uint64 address = 1; - // offset is the offset into the native instructions for the function. - uint64 offset = 2; - // symbol is the symbol name of the function. - string symbol = 3; - // module path for user space addresses. - string module = 4; + // linear address of the function in kernel or user space. + uint64 address = 1; + // offset is the offset into the native instructions for the function. + uint64 offset = 2; + // symbol is the symbol name of the function. + string symbol = 3; + // module path for user space addresses. + string module = 4; } diff --git a/event-processor/detector/api/tetragon/tetragon_vtproto.pb.go b/event-processor/detector/api/tetragon/tetragon_vtproto.pb.go index c840ace2..dcc44474 100644 --- a/event-processor/detector/api/tetragon/tetragon_vtproto.pb.go +++ b/event-processor/detector/api/tetragon/tetragon_vtproto.pb.go @@ -73,6 +73,49 @@ func (m *Image) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *SecurityContext) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SecurityContext) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *SecurityContext) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Privileged { + i-- + if m.Privileged { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *Container) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -103,6 +146,16 @@ func (m *Container) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.SecurityContext != nil { + size, err := m.SecurityContext.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x72 + } if m.MaybeExecProbe { i-- if m.MaybeExecProbe { @@ -214,6 +267,25 @@ func (m *Pod) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.PodAnnotations) > 0 { + for k := range m.PodAnnotations { + v := m.PodAnnotations[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarint(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarint(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarint(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x42 + } + } if len(m.WorkloadKind) > 0 { i -= len(m.WorkloadKind) copy(dAtA[i:], m.WorkloadKind) @@ -1552,6 +1624,18 @@ func (m *ProcessExit) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Ancestors) > 0 { + for iNdEx := len(m.Ancestors) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Ancestors[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + } if m.Time != nil { if vtmsg, ok := interface{}(m.Time).(interface { MarshalToSizedBufferVT([]byte) (int, error) @@ -1815,6 +1899,58 @@ func (m *KprobeSkb) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *KprobeSockaddr) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KprobeSockaddr) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *KprobeSockaddr) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Port != 0 { + i = encodeVarint(dAtA, i, uint64(m.Port)) + i-- + dAtA[i] = 0x18 + } + if len(m.Addr) > 0 { + i -= len(m.Addr) + copy(dAtA[i:], m.Addr) + i = encodeVarint(dAtA, i, uint64(len(m.Addr))) + i-- + dAtA[i] = 0x12 + } + if len(m.Family) > 0 { + i -= len(m.Family) + copy(dAtA[i:], m.Family) + i = encodeVarint(dAtA, i, uint64(len(m.Family))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *KprobeNetDev) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -3103,6 +3239,27 @@ func (m *KprobeArgument_SyscallId) MarshalToSizedBufferVT(dAtA []byte) (int, err } return len(dAtA) - i, nil } +func (m *KprobeArgument_SockaddrArg) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *KprobeArgument_SockaddrArg) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SockaddrArg != nil { + size, err := m.SockaddrArg.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xf2 + } + return len(dAtA) - i, nil +} func (m *ProcessKprobe) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -3133,6 +3290,18 @@ func (m *ProcessKprobe) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Ancestors) > 0 { + for iNdEx := len(m.Ancestors) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Ancestors[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x6a + } + } if len(m.UserStackTrace) > 0 { for iNdEx := len(m.UserStackTrace) - 1; iNdEx >= 0; iNdEx-- { size, err := m.UserStackTrace[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) @@ -3272,6 +3441,18 @@ func (m *ProcessTracepoint) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Ancestors) > 0 { + for iNdEx := len(m.Ancestors) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Ancestors[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x5a + } + } if len(m.Tags) > 0 { for iNdEx := len(m.Tags) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Tags[iNdEx]) @@ -3379,6 +3560,28 @@ func (m *ProcessUprobe) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.RefCtrOffset != 0 { + i = encodeVarint(dAtA, i, uint64(m.RefCtrOffset)) + i-- + dAtA[i] = 0x58 + } + if m.Offset != 0 { + i = encodeVarint(dAtA, i, uint64(m.Offset)) + i-- + dAtA[i] = 0x50 + } + if len(m.Ancestors) > 0 { + for iNdEx := len(m.Ancestors) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Ancestors[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x4a + } + } if len(m.Tags) > 0 { for iNdEx := len(m.Tags) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Tags[iNdEx]) @@ -3488,6 +3691,18 @@ func (m *ProcessLsm) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i-- dAtA[i] = 0x5a } + if len(m.Ancestors) > 0 { + for iNdEx := len(m.Ancestors) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Ancestors[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x52 + } + } if len(m.Tags) > 0 { for iNdEx := len(m.Tags) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Tags[iNdEx]) @@ -4024,6 +4239,13 @@ func (m *CreateContainer) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.ContainerImage) > 0 { + i -= len(m.ContainerImage) + copy(dAtA[i:], m.ContainerImage) + i = encodeVarint(dAtA, i, uint64(len(m.ContainerImage))) + i-- + dAtA[i] = 0x4a + } if len(m.PodNamespace) > 0 { i -= len(m.PodNamespace) copy(dAtA[i:], m.PodNamespace) @@ -4181,6 +4403,19 @@ func (m *Image) SizeVT() (n int) { return n } +func (m *SecurityContext) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Privileged { + n += 2 + } + n += len(m.unknownFields) + return n +} + func (m *Container) SizeVT() (n int) { if m == nil { return 0 @@ -4222,6 +4457,10 @@ func (m *Container) SizeVT() (n int) { if m.MaybeExecProbe { n += 2 } + if m.SecurityContext != nil { + l = m.SecurityContext.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -4260,6 +4499,14 @@ func (m *Pod) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + if len(m.PodAnnotations) > 0 { + for k, v := range m.PodAnnotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + 1 + len(v) + sov(uint64(len(v))) + n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) + } + } n += len(m.unknownFields) return n } @@ -4786,6 +5033,12 @@ func (m *ProcessExit) SizeVT() (n int) { } n += 1 + l + sov(uint64(l)) } + if len(m.Ancestors) > 0 { + for _, e := range m.Ancestors { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -4892,6 +5145,27 @@ func (m *KprobeSkb) SizeVT() (n int) { return n } +func (m *KprobeSockaddr) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Family) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Addr) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Port != 0 { + n += 1 + sov(uint64(m.Port)) + } + n += len(m.unknownFields) + return n +} + func (m *KprobeNetDev) SizeVT() (n int) { if m == nil { return 0 @@ -5511,6 +5785,18 @@ func (m *KprobeArgument_SyscallId) SizeVT() (n int) { } return n } +func (m *KprobeArgument_SockaddrArg) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SockaddrArg != nil { + l = m.SockaddrArg.SizeVT() + n += 2 + l + sov(uint64(l)) + } + return n +} func (m *ProcessKprobe) SizeVT() (n int) { if m == nil { return 0 @@ -5571,6 +5857,12 @@ func (m *ProcessKprobe) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } + if len(m.Ancestors) > 0 { + for _, e := range m.Ancestors { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -5620,6 +5912,12 @@ func (m *ProcessTracepoint) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } + if len(m.Ancestors) > 0 { + for _, e := range m.Ancestors { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } n += len(m.unknownFields) return n } @@ -5666,8 +5964,20 @@ func (m *ProcessUprobe) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } - n += len(m.unknownFields) - return n + if len(m.Ancestors) > 0 { + for _, e := range m.Ancestors { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if m.Offset != 0 { + n += 1 + sov(uint64(m.Offset)) + } + if m.RefCtrOffset != 0 { + n += 1 + sov(uint64(m.RefCtrOffset)) + } + n += len(m.unknownFields) + return n } func (m *ProcessLsm) SizeVT() (n int) { @@ -5711,6 +6021,12 @@ func (m *ProcessLsm) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } + if len(m.Ancestors) > 0 { + for _, e := range m.Ancestors { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } l = len(m.ImaHash) if l > 0 { n += 1 + l + sov(uint64(l)) @@ -5924,6 +6240,10 @@ func (m *CreateContainer) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + l = len(m.ContainerImage) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -6073,6 +6393,77 @@ func (m *Image) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *SecurityContext) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SecurityContext: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SecurityContext: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Privileged", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Privileged = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Container) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -6310,6 +6701,42 @@ func (m *Container) UnmarshalVT(dAtA []byte) error { } } m.MaybeExecProbe = bool(v != 0) + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecurityContext", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SecurityContext == nil { + m.SecurityContext = &SecurityContext{} + } + if err := m.SecurityContext.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -6652,6 +7079,133 @@ func (m *Pod) UnmarshalVT(dAtA []byte) error { } m.WorkloadKind = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PodAnnotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PodAnnotations == nil { + m.PodAnnotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLength + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLength + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLength + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLength + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.PodAnnotations[mapkey] = mapvalue + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -9883,6 +10437,40 @@ func (m *ProcessExit) UnmarshalVT(dAtA []byte) error { } } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ancestors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ancestors = append(m.Ancestors, &Process{}) + if err := m.Ancestors[len(m.Ancestors)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -10539,9 +11127,124 @@ func (m *KprobeSkb) UnmarshalVT(dAtA []byte) error { } m.Protocol = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 13: + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Family", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Family = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KprobeSockaddr) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KprobeSockaddr: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KprobeSockaddr: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Family", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Family = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Family", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Addr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -10569,8 +11272,27 @@ func (m *KprobeSkb) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Family = string(dAtA[iNdEx:postIndex]) + m.Addr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Port", wireType) + } + m.Port = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Port |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -13501,6 +14223,47 @@ func (m *KprobeArgument) UnmarshalVT(dAtA []byte) error { m.Arg = &KprobeArgument_SyscallId{SyscallId: v} } iNdEx = postIndex + case 30: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SockaddrArg", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Arg.(*KprobeArgument_SockaddrArg); ok { + if err := oneof.SockaddrArg.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := &KprobeSockaddr{} + if err := v.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Arg = &KprobeArgument_SockaddrArg{SockaddrArg: v} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -13928,6 +14691,40 @@ func (m *ProcessKprobe) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ancestors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ancestors = append(m.Ancestors, &Process{}) + if err := m.Ancestors[len(m.Ancestors)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -14264,6 +15061,40 @@ func (m *ProcessTracepoint) UnmarshalVT(dAtA []byte) error { } m.Tags = append(m.Tags, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ancestors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ancestors = append(m.Ancestors, &Process{}) + if err := m.Ancestors[len(m.Ancestors)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -14581,6 +15412,78 @@ func (m *ProcessUprobe) UnmarshalVT(dAtA []byte) error { } m.Tags = append(m.Tags, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ancestors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ancestors = append(m.Ancestors, &Process{}) + if err := m.Ancestors[len(m.Ancestors)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Offset", wireType) + } + m.Offset = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Offset |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RefCtrOffset", wireType) + } + m.RefCtrOffset = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RefCtrOffset |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -14885,6 +15788,40 @@ func (m *ProcessLsm) UnmarshalVT(dAtA []byte) error { } m.Tags = append(m.Tags, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ancestors", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ancestors = append(m.Ancestors, &Process{}) + if err := m.Ancestors[len(m.Ancestors)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 11: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ImaHash", wireType) @@ -16264,6 +17201,38 @@ func (m *CreateContainer) UnmarshalVT(dAtA []byte) error { } m.PodNamespace = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContainerImage", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ContainerImage = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/event-processor/detector/wasm/CS_RT_BASE64_DECODE_RUN/main.go b/event-processor/detector/wasm/CS_RT_BASE64_DECODE_RUN/main.go index 08adc9a8..5ca7eb17 100644 --- a/event-processor/detector/wasm/CS_RT_BASE64_DECODE_RUN/main.go +++ b/event-processor/detector/wasm/CS_RT_BASE64_DECODE_RUN/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( base64Utils = []glob.Glob{ glob.MustCompile("*/base64"), @@ -52,16 +70,22 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_BIN_PERM_RAISE/main.go b/event-processor/detector/wasm/CS_RT_BIN_PERM_RAISE/main.go index e2e7a676..90f1f348 100644 --- a/event-processor/detector/wasm/CS_RT_BIN_PERM_RAISE/main.go +++ b/event-processor/detector/wasm/CS_RT_BIN_PERM_RAISE/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( chmod = glob.MustCompile(`*/chmod`) execPerm = regexp.MustCompile(`^(?:[\-Rcfv\s]+)?(?:(?:[0-7]?[0-7][1357][0-7]\s|[0-7]?[1357][0-7][0-7]\s|[0-7]?[0-7][0-7][1357]\s)|(?:[ugoa]*[+=]x\s))`) @@ -54,22 +72,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, @@ -393,7 +415,7 @@ func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectRe }, "ancestors": [] }, - "node_name": "cs-master-node", + "node_name": "ptcs-master-node", "time": "2024-11-13T10:15:07.462452981Z", "aggregation_info": null } diff --git a/event-processor/detector/wasm/CS_RT_CORE_PATTERN_MODIFY/main.go b/event-processor/detector/wasm/CS_RT_CORE_PATTERN_MODIFY/main.go index 04a25aae..75824d8f 100644 --- a/event-processor/detector/wasm/CS_RT_CORE_PATTERN_MODIFY/main.go +++ b/event-processor/detector/wasm/CS_RT_CORE_PATTERN_MODIFY/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + const ( // File access permissions // https://elixir.bootlin.com/linux/v6.10-rc6/source/include/linux/fs.h#L100 @@ -48,22 +66,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_CRYPTOMINER/main.go b/event-processor/detector/wasm/CS_RT_CRYPTOMINER/main.go index 64d6f8a8..65f5736e 100644 --- a/event-processor/detector/wasm/CS_RT_CRYPTOMINER/main.go +++ b/event-processor/detector/wasm/CS_RT_CRYPTOMINER/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( minerTools = []*regexp.Regexp{ regexp.MustCompile(`/[^/]*stratum[^/]*$`), @@ -86,22 +104,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_CVE_2022_0492/main.go b/event-processor/detector/wasm/CS_RT_CVE_2022_0492/main.go index 30f33611..1ca1d4d9 100644 --- a/event-processor/detector/wasm/CS_RT_CVE_2022_0492/main.go +++ b/event-processor/detector/wasm/CS_RT_CVE_2022_0492/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( fileRegex = regexp.MustCompile(`(?:release_agent|notify_on_release)$`) ) @@ -38,22 +56,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_CVE_2025_1974/main.go b/event-processor/detector/wasm/CS_RT_CVE_2025_1974/main.go index bd5be19d..66786805 100644 --- a/event-processor/detector/wasm/CS_RT_CVE_2025_1974/main.go +++ b/event-processor/detector/wasm/CS_RT_CVE_2025_1974/main.go @@ -26,6 +26,24 @@ const ( PROT_READ = 1 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_mmap_file"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( // NGINX binary. nginxBinary = glob.MustCompile("*/nginx") @@ -48,22 +66,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_DOWNLOAD_TOOLS/main.go b/event-processor/detector/wasm/CS_RT_DOWNLOAD_TOOLS/main.go index 3a128f0a..4660b196 100644 --- a/event-processor/detector/wasm/CS_RT_DOWNLOAD_TOOLS/main.go +++ b/event-processor/detector/wasm/CS_RT_DOWNLOAD_TOOLS/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"tcp_connect"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // downloadTool represents a combination of binary's and its arguments' patterns. type downloadTool struct { binaryPattern glob.Glob @@ -65,22 +83,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_FILELESS_EXEC/main.go b/event-processor/detector/wasm/CS_RT_FILELESS_EXEC/main.go index f13bc405..c2e12680 100644 --- a/event-processor/detector/wasm/CS_RT_FILELESS_EXEC/main.go +++ b/event-processor/detector/wasm/CS_RT_FILELESS_EXEC/main.go @@ -18,6 +18,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -32,22 +50,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_HACK_TOOLS/main.go b/event-processor/detector/wasm/CS_RT_HACK_TOOLS/main.go index 4363aa5c..74fde3ee 100644 --- a/event-processor/detector/wasm/CS_RT_HACK_TOOLS/main.go +++ b/event-processor/detector/wasm/CS_RT_HACK_TOOLS/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( hackTools = []glob.Glob{ // sudo and su a rarely used in runtime, containers are either rooted or rootless with no need to escalate privileges for a normal user. @@ -92,22 +110,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_HACK_TOOLS_EXT/main.go b/event-processor/detector/wasm/CS_RT_HACK_TOOLS_EXT/main.go index 01f77d5c..80fd8ea1 100644 --- a/event-processor/detector/wasm/CS_RT_HACK_TOOLS_EXT/main.go +++ b/event-processor/detector/wasm/CS_RT_HACK_TOOLS_EXT/main.go @@ -28,6 +28,24 @@ const ( rootGID = 0 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( hackTools = []*regexp.Regexp{ // sudo and su are rarely used in runtime, containers are either rooted or rootless with no need to escalate privileges for a normal user. @@ -214,22 +232,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_IO_URING_CREATE/main.go b/event-processor/detector/wasm/CS_RT_IO_URING_CREATE/main.go index 1a4da3c9..8c5e5891 100644 --- a/event-processor/detector/wasm/CS_RT_IO_URING_CREATE/main.go +++ b/event-processor/detector/wasm/CS_RT_IO_URING_CREATE/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"sys_io_uring_setup"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -34,22 +52,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_K8S_SA_TOKEN_READ/main.go b/event-processor/detector/wasm/CS_RT_K8S_SA_TOKEN_READ/main.go index f9dc88bd..cacfaa2d 100644 --- a/event-processor/detector/wasm/CS_RT_K8S_SA_TOKEN_READ/main.go +++ b/event-processor/detector/wasm/CS_RT_K8S_SA_TOKEN_READ/main.go @@ -21,6 +21,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( // Following code is commented and will probably be removed later on, because listed tools run on host itself, out of container context, // and will be filtered out by monitoring agent most of the time because of runtime filters. @@ -56,22 +74,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_KERNEL_MODULE/main.go b/event-processor/detector/wasm/CS_RT_KERNEL_MODULE/main.go index 7009b0f3..521820fc 100644 --- a/event-processor/detector/wasm/CS_RT_KERNEL_MODULE/main.go +++ b/event-processor/detector/wasm/CS_RT_KERNEL_MODULE/main.go @@ -19,6 +19,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"do_init_module"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -33,22 +51,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_LD_PRELOAD/main.go b/event-processor/detector/wasm/CS_RT_LD_PRELOAD/main.go index 150210a7..7b145572 100644 --- a/event-processor/detector/wasm/CS_RT_LD_PRELOAD/main.go +++ b/event-processor/detector/wasm/CS_RT_LD_PRELOAD/main.go @@ -30,6 +30,24 @@ const ( PROT_WRITE = 2 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + const ( ldPreloadPath = "/etc/ld.so.preload" ) @@ -48,22 +66,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_MOUNT_DEV/main.go b/event-processor/detector/wasm/CS_RT_MOUNT_DEV/main.go index 5f9b4029..118e69cf 100644 --- a/event-processor/detector/wasm/CS_RT_MOUNT_DEV/main.go +++ b/event-processor/detector/wasm/CS_RT_MOUNT_DEV/main.go @@ -22,6 +22,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"sys_mount"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( devPattern = glob.MustCompile("/dev/*") ) @@ -40,22 +58,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_OPENSSL_CUSTOM_LIB_LOAD/main.go b/event-processor/detector/wasm/CS_RT_OPENSSL_CUSTOM_LIB_LOAD/main.go index 5f3ec8ae..b0413793 100644 --- a/event-processor/detector/wasm/CS_RT_OPENSSL_CUSTOM_LIB_LOAD/main.go +++ b/event-processor/detector/wasm/CS_RT_OPENSSL_CUSTOM_LIB_LOAD/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( // Command for loading custom user library as crypto engine. libraryLoadCmd = regexp.MustCompile(`^engine\s(?:dynamic\s)?.*-pre SO_PATH:.*-pre LOAD`) @@ -41,22 +59,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_OPENSSL_FILE_ACCESS/main.go b/event-processor/detector/wasm/CS_RT_OPENSSL_FILE_ACCESS/main.go index 42362452..ab42c549 100644 --- a/event-processor/detector/wasm/CS_RT_OPENSSL_FILE_ACCESS/main.go +++ b/event-processor/detector/wasm/CS_RT_OPENSSL_FILE_ACCESS/main.go @@ -16,8 +16,25 @@ const ( Description = "The detector detects if the OpenSSL utility was used to read and write arbitrary files, which may indicate an attacker's attempt to gain access to sensitive data and change the system behavior." Version = 1 Author = "Runtime Radar Team" + License = "Apache License 2.0" +) + +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, - License = "Apache License 2.0" + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } ) var ( @@ -38,22 +55,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_OPENSSL_SERVER_RUN/main.go b/event-processor/detector/wasm/CS_RT_OPENSSL_SERVER_RUN/main.go index d43fc5cc..dbc310e7 100644 --- a/event-processor/detector/wasm/CS_RT_OPENSSL_SERVER_RUN/main.go +++ b/event-processor/detector/wasm/CS_RT_OPENSSL_SERVER_RUN/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( s_serverInArgs = glob.MustCompile("s_server*") ) @@ -38,22 +56,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_PRIV_ESC/main.go b/event-processor/detector/wasm/CS_RT_PRIV_ESC/main.go index 3049f0dc..0400a852 100644 --- a/event-processor/detector/wasm/CS_RT_PRIV_ESC/main.go +++ b/event-processor/detector/wasm/CS_RT_PRIV_ESC/main.go @@ -26,6 +26,24 @@ const ( rootGID = 0 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"commit_creds"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -40,22 +58,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_PROCESS_CAP_RAISE/main.go b/event-processor/detector/wasm/CS_RT_PROCESS_CAP_RAISE/main.go index e8c6df7f..e2821973 100644 --- a/event-processor/detector/wasm/CS_RT_PROCESS_CAP_RAISE/main.go +++ b/event-processor/detector/wasm/CS_RT_PROCESS_CAP_RAISE/main.go @@ -17,8 +17,25 @@ const ( Description = "This detector detects processes running with excessive capabilities, which may indicate an attacker's attempt to escalate their privileges in the system." Version = 1 Author = "Runtime Radar Team" + License = "Apache License 2.0" +) + +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"commit_creds"}, - License = "Apache License 2.0" + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } ) var ( @@ -50,22 +67,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_PTRACE_CODE_INJ/main.go b/event-processor/detector/wasm/CS_RT_PTRACE_CODE_INJ/main.go index 24228b38..1f4c3a71 100644 --- a/event-processor/detector/wasm/CS_RT_PTRACE_CODE_INJ/main.go +++ b/event-processor/detector/wasm/CS_RT_PTRACE_CODE_INJ/main.go @@ -21,6 +21,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"sys_ptrace"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( // Taken from here (link from ESC): https://github.com/torvalds/linux/blob/master/include/uapi/linux/ptrace.h ptraceMaliciousRequests = []int32{ @@ -53,22 +71,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_RAW_SOCKETS/main.go b/event-processor/detector/wasm/CS_RT_RAW_SOCKETS/main.go index 323908dd..1df0e5e8 100644 --- a/event-processor/detector/wasm/CS_RT_RAW_SOCKETS/main.go +++ b/event-processor/detector/wasm/CS_RT_RAW_SOCKETS/main.go @@ -31,6 +31,24 @@ const ( SOCK_PACKET = 10 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_socket_create"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( binaryWhitelist = []*regexp.Regexp{ regexp.MustCompile(`/NetworkManager$`), @@ -55,22 +73,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_RECON_TOOLS/main.go b/event-processor/detector/wasm/CS_RT_RECON_TOOLS/main.go index 9bc9cdff..381e533d 100644 --- a/event-processor/detector/wasm/CS_RT_RECON_TOOLS/main.go +++ b/event-processor/detector/wasm/CS_RT_RECON_TOOLS/main.go @@ -31,6 +31,24 @@ const ( PROT_READ = 1 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( libPath = glob.MustCompile("*/libpcap.so*") ) @@ -49,22 +67,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_CREATE/main.go b/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_CREATE/main.go index e5d6f7e1..25d7a2d1 100644 --- a/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_CREATE/main.go +++ b/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_CREATE/main.go @@ -19,6 +19,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"do_dup2"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -33,22 +51,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_USE/main.go b/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_USE/main.go index bf9c9f39..d3ac521e 100644 --- a/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_USE/main.go +++ b/event-processor/detector/wasm/CS_RT_REVERSE_SHELL_USE/main.go @@ -19,6 +19,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"tcp_sendmsg"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( commonLinuxTools = []glob.Glob{ glob.MustCompile("*/ls"), @@ -69,22 +87,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_REV_ENG/main.go b/event-processor/detector/wasm/CS_RT_REV_ENG/main.go index 192fa70c..a29d566b 100644 --- a/event-processor/detector/wasm/CS_RT_REV_ENG/main.go +++ b/event-processor/detector/wasm/CS_RT_REV_ENG/main.go @@ -19,6 +19,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"sys_ptrace"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + // main is required for TinyGo to compile to Wasm. func main() { api.RegisterDetector(Detector{}) @@ -33,22 +51,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SCHED_TASK_MOD/main.go b/event-processor/detector/wasm/CS_RT_SCHED_TASK_MOD/main.go index c987e30f..79f7003f 100644 --- a/event-processor/detector/wasm/CS_RT_SCHED_TASK_MOD/main.go +++ b/event-processor/detector/wasm/CS_RT_SCHED_TASK_MOD/main.go @@ -30,6 +30,24 @@ const ( PROT_WRITE = 2 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( schedulerFiles = []glob.Glob{ glob.MustCompile("/etc/crontab"), // system task scheduler @@ -67,22 +85,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SSH_KEY_MODIFY/main.go b/event-processor/detector/wasm/CS_RT_SSH_KEY_MODIFY/main.go index e94eb72f..c2d70658 100644 --- a/event-processor/detector/wasm/CS_RT_SSH_KEY_MODIFY/main.go +++ b/event-processor/detector/wasm/CS_RT_SSH_KEY_MODIFY/main.go @@ -30,6 +30,24 @@ const ( PROT_WRITE = 2 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( sshKeysPath = regexp.MustCompile(`^(/root/|/home/.*/)\.ssh/`) filesToExclude = regexp.MustCompile(`\.ssh2?/(config|known_hosts)$`) @@ -49,22 +67,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_CREATE/main.go b/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_CREATE/main.go index c6d8ae07..e36ff0ae 100644 --- a/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_CREATE/main.go +++ b/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_CREATE/main.go @@ -20,6 +20,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( sshBin = glob.MustCompile("*/ssh") @@ -42,22 +60,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_USE/main.go b/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_USE/main.go index 551554c8..04855692 100644 --- a/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_USE/main.go +++ b/event-processor/detector/wasm/CS_RT_SSH_TUNNEL_USE/main.go @@ -24,6 +24,23 @@ const ( sshdPort = 22 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"tcp_connect", "inet_csk_listen_start"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) var ( sshdBin = glob.MustCompile("*/sshd") ) @@ -42,22 +59,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SUSP_FILE_READ/main.go b/event-processor/detector/wasm/CS_RT_SUSP_FILE_READ/main.go index deac93f3..1111b8cf 100644 --- a/event-processor/detector/wasm/CS_RT_SUSP_FILE_READ/main.go +++ b/event-processor/detector/wasm/CS_RT_SUSP_FILE_READ/main.go @@ -30,6 +30,24 @@ const ( PROT_READ = 1 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( sensitiveFiles = []glob.Glob{ glob.MustCompile("/etc/shadow"), // users shadow info @@ -102,22 +120,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SUSP_FILE_WRITE/main.go b/event-processor/detector/wasm/CS_RT_SUSP_FILE_WRITE/main.go index 70dd8380..95c6741e 100644 --- a/event-processor/detector/wasm/CS_RT_SUSP_FILE_WRITE/main.go +++ b/event-processor/detector/wasm/CS_RT_SUSP_FILE_WRITE/main.go @@ -30,6 +30,24 @@ const ( PROT_WRITE = 2 ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( sensitiveFiles = []glob.Glob{ glob.MustCompile("/etc/passwd"), // users info @@ -107,22 +125,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/detector/wasm/CS_RT_SUSP_SHELL/main.go b/event-processor/detector/wasm/CS_RT_SUSP_SHELL/main.go index 3890d651..0564eaf0 100644 --- a/event-processor/detector/wasm/CS_RT_SUSP_SHELL/main.go +++ b/event-processor/detector/wasm/CS_RT_SUSP_SHELL/main.go @@ -19,6 +19,24 @@ const ( License = "Apache License 2.0" ) +var ( + // triggerCriteria sets Trigger Criteria as map of events types to corresponding functions + // which will be used by Detector. If function names are not applicable for + // a particular event type, such as "PROCESS_EXEC", leave slice empty or use + // wildcard "*". + triggerCriteria = map[string][]string{ + "PROCESS_EXEC": {}, + + // Examples: + // + // "PROCESS_KPROBE": {"security_file_permission", "security_mmap_file", "security_path_truncate"}, + // In order to process all possible functions leave right-hand part empty or use wildcard "*": + // "PROCESS_EXEC": {}, + // same as: + // "PROCESS_EXEC": {"*"}, + } +) + var ( shells = []glob.Glob{ glob.MustCompile("*/ash"), @@ -181,22 +199,26 @@ func (d Detector) Info(ctx context.Context, req *api.InfoReq) (*api.InfoResp, er Description: Description, Version: Version, Author: Author, - Contact: Contact, License: License, }, nil } +func (d Detector) TriggerCriteria(ctx context.Context, req *api.TriggerCriteriaReq) (*api.TriggerCriteriaResp, error) { + resp := &api.TriggerCriteriaResp{ + Criteria: make(map[string]*api.TriggerCriteriaResp_FuncNames, len(triggerCriteria)), + } + + for k, v := range triggerCriteria { + resp.Criteria[k] = &api.TriggerCriteriaResp_FuncNames{FuncNames: v} + } + + return resp, nil +} + func (d Detector) Detect(ctx context.Context, req *api.DetectReq) (*api.DetectResp, error) { // Detector info added to DetectResp because detector info is always correlated to response, thus // to avoid +1 Wasm call on detect. resp := &api.DetectResp{ - Id: ID, - Name: Name, - Description: Description, - Version: Version, - Author: Author, - Contact: Contact, - // Default response indicates that nothing detected (this is redundant and put here just for reference, // as Severity == api.DetectResp_NONE == 0 when omitted (default zero value)). Severity: api.DetectResp_NONE, diff --git a/event-processor/docker-compose.test.yml b/event-processor/docker-compose.test.yml index 3126a730..c59784f0 100644 --- a/event-processor/docker-compose.test.yml +++ b/event-processor/docker-compose.test.yml @@ -1,6 +1,6 @@ services: test: - image: golang:1.24 + image: golang:1.25 working_dir: /go/src/repo volumes: - .:/go/src/repo diff --git a/event-processor/go.mod b/event-processor/go.mod index be8be9ba..4e879bb4 100644 --- a/event-processor/go.mod +++ b/event-processor/go.mod @@ -1,32 +1,33 @@ module github.com/runtime-radar/runtime-radar/event-processor -go 1.23.0 +go 1.25 require ( + github.com/cilium/tetragon v1.3.0 github.com/cilium/tetragon/api v1.3.0 github.com/gobwas/glob v0.2.3 github.com/golangci/golangci-lint v1.64.8 github.com/google/go-cmp v0.7.0 github.com/google/gops v0.3.28 github.com/google/uuid v1.6.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 github.com/justinas/alice v1.2.0 - github.com/knqyf263/go-plugin v0.8.1-0.20241107183803-4626258850e7 - github.com/rs/cors v1.11.0 - github.com/rs/zerolog v1.33.0 + github.com/knqyf263/go-plugin v0.9.0 + github.com/rs/cors v1.11.1 + github.com/rs/zerolog v1.34.0 github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000 github.com/runtime-radar/runtime-radar/lib v0.0.24 github.com/runtime-radar/runtime-radar/notifier v0.0.0-00010101000000-000000000000 github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8 github.com/tetratelabs/wazero v1.9.0 go.uber.org/automaxprocs v1.6.0 - golang.org/x/vuln v0.2.0 - google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 - google.golang.org/grpc v1.73.0 + golang.org/x/vuln v1.1.4 + google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f + google.golang.org/grpc v1.75.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 - google.golang.org/protobuf v1.36.6 + google.golang.org/protobuf v1.36.10 gorm.io/driver/postgres v1.6.0 - gorm.io/gorm v1.30.0 + gorm.io/gorm v1.31.0 ) require ( @@ -74,7 +75,7 @@ require ( github.com/fatih/structtag v1.2.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/firefart/nonamedreturns v1.0.5 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/ghostiam/protogetter v0.3.9 // indirect github.com/go-critic/go-critic v0.12.0 // indirect @@ -86,7 +87,7 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -105,12 +106,11 @@ require ( github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.7.1 // indirect + github.com/jackc/pgx/v5 v5.7.6 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jgautheron/goconst v1.7.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect @@ -132,7 +132,6 @@ require ( github.com/leonklingele/grouper v1.1.2 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/macabu/inamedparam v0.1.3 // indirect - github.com/magiconair/properties v1.8.7 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect @@ -141,7 +140,6 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mgechev/revive v1.7.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nakabonne/nestif v0.3.1 // indirect @@ -158,7 +156,7 @@ require ( github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/procfs v0.17.0 // indirect github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect @@ -170,8 +168,7 @@ require ( github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/ryancurrah/gomodguard v1.3.5 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect - github.com/sagikazarmark/locafero v0.3.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect @@ -186,10 +183,10 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.12.0 // indirect - github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/spf13/viper v1.17.0 // indirect + github.com/spf13/pflag v1.0.7 // indirect + github.com/spf13/viper v1.20.1 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -218,17 +215,19 @@ require ( go-simpler.org/sloglint v0.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.25.0 // indirect - golang.org/x/net v0.40.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.26.0 // indirect - golang.org/x/tools v0.33.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools/go/expect v0.1.1-deprecated // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.6.1 // indirect diff --git a/event-processor/go.sum b/event-processor/go.sum index 9786de36..9c69ba23 100644 --- a/event-processor/go.sum +++ b/event-processor/go.sum @@ -68,6 +68,8 @@ github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iy github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/cilium/tetragon v1.3.0 h1:GDeDHyt9xqp+k/hMRtgrkn4alU0VEQwDSVdC2X3A91E= +github.com/cilium/tetragon v1.3.0/go.mod h1:S71rSd3XAXptk1s1e76sNGxvyfGFHmseSopyhPOCLgQ= github.com/cilium/tetragon/api v1.3.0 h1:DSc9arjOot/2/ay+yqy2/P2sxLT1BmJiOC3OoINFlUY= github.com/cilium/tetragon/api v1.3.0/go.mod h1:yFA8H1EFJoCgx0QHgnFAilKvyreWE5SG2so1galbulI= github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= @@ -98,18 +100,18 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -137,8 +139,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -202,8 +204,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= @@ -213,8 +215,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -223,8 +223,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= -github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= +github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= @@ -247,8 +247,8 @@ github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3 github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= -github.com/knqyf263/go-plugin v0.8.1-0.20241107183803-4626258850e7 h1:hGS7VnW4ur7zJ5PP2PczafwPw4DLb0/Hby6X5D09zcs= -github.com/knqyf263/go-plugin v0.8.1-0.20241107183803-4626258850e7/go.mod h1:ORAg7LxEKEkAt8oldLuNTfWpellPv/QXIGwqDFWWt50= +github.com/knqyf263/go-plugin v0.9.0 h1:CQs2+lOPIlkZVtcb835ZYDEoyyWJWLbSTWeCs0EwTwI= +github.com/knqyf263/go-plugin v0.9.0/go.mod h1:2z5lCO1/pez6qGo8CvCxSlBFSEat4MEp1DrnA+f7w8Q= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -275,8 +275,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= @@ -299,8 +297,6 @@ github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -348,8 +344,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= +github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= @@ -369,20 +365,18 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= @@ -415,15 +409,16 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -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/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= @@ -503,16 +498,16 @@ go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -521,16 +516,18 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= 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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= @@ -546,8 +543,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= 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= @@ -563,8 +560,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= 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-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -574,8 +571,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -594,7 +591,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -603,8 +599,10 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE= +golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -623,8 +621,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= 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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= @@ -643,31 +641,35 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= -golang.org/x/vuln v0.2.0 h1:Dlz47lW0pvPHU7tnb10S8vbMn9GnV2B6eyT7Tem5XBI= -golang.org/x/vuln v0.2.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= +golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s= 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/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f h1:OiFuztEyBivVKDvguQJYWq1yDcfAHIID/FVrPR4oiI0= +google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f/go.mod h1:kprOiu9Tr0JYyD6DORrc4Hfyk3RFXqkQ3ctHEum3ZbM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= 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.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -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.2/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= @@ -676,8 +678,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= -gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= -gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= diff --git a/event-processor/pkg/processor/detector/chain.go b/event-processor/pkg/processor/detector/chain.go new file mode 100644 index 00000000..42ef04e3 --- /dev/null +++ b/event-processor/pkg/processor/detector/chain.go @@ -0,0 +1,108 @@ +package detector + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + tetragon_api "github.com/cilium/tetragon/api/v1/tetragon" + "github.com/rs/zerolog/log" + "github.com/runtime-radar/runtime-radar/event-processor/api" + detector_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api" + enf_model "github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model" +) + +// Chain is a chain of detectors wrapped with corresponding info. +type Chain map[Key]Wrapper + +// Key is used to identify particular detector. We do not allow same combination of ID and version, but we do allow same ID with different versions. +// This is in line with model.Detector, where primary key is also set to ID and version. +type Key struct { + ID string + Version uint +} + +// Wrapper represents a detector itself with info about it alongside, so that it can be used without calling Detector.Info. +type Wrapper struct { + detector_api.Detector + Info *api.Detector +} + +// ChainResult represents a result of execution of detectors' chain. +// If at least one of detectors returned an error, it's appended to Errors +// and it doesn't prevent remaining chain from being executed. +type ChainResult struct { + Threats []*api.Threat + Errors []*api.DetectError +} + +// Detect executes chain of detectors and returns a result, which can contain found threats or detect errors. +// Error in particular detector won't prevent other detectors in chain from being executed. +// Detect will stop with error if it occurs anywhere else. If len(c) == 0, it will return nil, nil. +func (c Chain) Detect(ctx context.Context, event *tetragon_api.GetEventsResponse) (*ChainResult, error) { + if len(c) == 0 { + return nil, nil + } + + res := &ChainResult{} + + dEvent, err := convertEvent(event) + if err != nil { + return nil, fmt.Errorf("can't convert event: %w", err) + } + + for _, d := range c { + t0 := time.Now() + resp, err := d.Detect(ctx, &detector_api.DetectReq{Event: dEvent}) + if err != nil { + res.Errors = append(res.Errors, &api.DetectError{ + Detector: d.Info, + Error: err.Error(), + }) + + continue + } + delta := time.Since(t0) + + log.Debug().Str("delay", delta.String()).Interface("detector_event", dEvent).Interface("detector_resp", resp).Msgf("Detector[%s] is done", d.Info.GetId()) + + if resp.GetSeverity() > detector_api.DetectResp_NONE { + s := enf_model.Severity(resp.GetSeverity()) + + res.Threats = append(res.Threats, &api.Threat{ + Detector: &api.Detector{ + Id: d.Info.GetId(), + Name: d.Info.GetName(), + Description: d.Info.GetDescription(), + Version: d.Info.GetVersion(), + Author: d.Info.GetAuthor(), + Contact: d.Info.GetContact(), + }, + Severity: s.String(), + }) + } + } + + return res, nil +} + +// String implements fmt.Stringer for logging purposes. +func (c Chain) String() string { + wb := &strings.Builder{} + + i := 0 + for k := range c { + wb.WriteString("[") + wb.WriteString(k.ID + ";") + wb.WriteString(strconv.Itoa(int(k.Version))) + wb.WriteString("]") + if i < len(c)-1 { + wb.WriteString(", ") + } + i++ + } + + return wb.String() +} diff --git a/event-processor/pkg/processor/detector/detector.go b/event-processor/pkg/processor/detector/detector.go index 20e410b3..0557c956 100644 --- a/event-processor/pkg/processor/detector/detector.go +++ b/event-processor/pkg/processor/detector/detector.go @@ -5,43 +5,16 @@ package detector import ( "context" "fmt" - "time" tetragon_api "github.com/cilium/tetragon/api/v1/tetragon" - "github.com/rs/zerolog/log" - "github.com/runtime-radar/runtime-radar/event-processor/api" detector_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api" detector_tetragon_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api/tetragon" "github.com/runtime-radar/runtime-radar/event-processor/pkg/model" "github.com/runtime-radar/runtime-radar/lib/security" - enf_model "github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model" "github.com/tetratelabs/wazero" "google.golang.org/protobuf/proto" ) -// Key is used to identify particular detector. We do not allow same combination of ID and version, but we do allow same ID with different versions. -// This is in line with model.Detector, where primary key is also set to ID and version. -type Key struct { - ID string - Version uint -} - -// Wrapper represents a detector itself with info about it alongside, so that it can be used without calling Detector.Info. -type Wrapper struct { - detector_api.Detector - Info *api.Detector -} - -type Chain map[Key]Wrapper - -// ChainResult represents a result of execution of detectors' chain. -// If at least one of detectors returned an error, it's appended to Errors -// and it doesn't prevent remaining chain from being executed. -type ChainResult struct { - Threats []*api.Threat - Errors []*api.DetectError -} - func NewPlugin(ctx context.Context) (*detector_api.DetectorPlugin, error) { mc := wazero.NewModuleConfig() @@ -53,88 +26,21 @@ func NewPlugin(ctx context.Context) (*detector_api.DetectorPlugin, error) { return p, nil } -func NewChain(ctx context.Context, plugin *detector_api.DetectorPlugin, binaries [][]byte) (Chain, error) { - c := make(Chain, len(binaries)) +func BinsToDetectors(ctx context.Context, plugin *detector_api.DetectorPlugin, bins [][]byte) ([]detector_api.Detector, error) { + ds := make([]detector_api.Detector, 0, len(bins)) - for _, binary := range binaries { - d, err := plugin.LoadBinary(ctx, binary) + for _, bin := range bins { + d, err := plugin.LoadBinary(ctx, bin) if err != nil { return nil, fmt.Errorf("can't load binary: %w", err) } - - resp, err := d.Info(ctx, &detector_api.InfoReq{}) - if err != nil { - return nil, fmt.Errorf("can't get detector info: %w", err) - } - - k := Key{resp.GetId(), uint(resp.GetVersion())} - if _, ok := c[k]; ok { - return nil, fmt.Errorf("duplicate detector key: %+v", k) - } - - info := &api.Detector{ - Id: resp.GetId(), - Name: resp.GetName(), - Description: resp.GetDescription(), - Version: resp.GetVersion(), - Author: resp.GetAuthor(), - Contact: resp.GetContact(), - License: resp.GetLicense(), - } - - c[k] = Wrapper{d, info} - } - - return c, nil -} - -// Detect returns a result of executing chain of detectors. -// If detector resulted in error, an error is appended to result and remaining chain continues to execute. -// If an error occurred outside a detector, it's returned. -func (c Chain) Detect(ctx context.Context, event *tetragon_api.GetEventsResponse) (*ChainResult, error) { - res := &ChainResult{} - - dEvent, err := convertEvent(event) - if err != nil { - return nil, fmt.Errorf("can't convert event: %w", err) - } - - for _, d := range c { - t0 := time.Now() - - resp, err := d.Detect(ctx, &detector_api.DetectReq{Event: dEvent}) - if err != nil { - res.Errors = append(res.Errors, &api.DetectError{ - Detector: d.Info, - Error: err.Error(), - }) - - continue - } - - log.Debug().Str("delay", time.Since(t0).String()).Interface("detector_event", dEvent).Interface("detector_resp", resp).Msgf("Detector[%s] is done", resp.GetId()) - - if resp.GetSeverity() > detector_api.DetectResp_NONE { - s := enf_model.Severity(resp.GetSeverity()) - - res.Threats = append(res.Threats, &api.Threat{ - Detector: &api.Detector{ - Id: resp.GetId(), - Name: resp.GetName(), - Description: resp.GetDescription(), - Version: resp.GetVersion(), - Author: resp.GetAuthor(), - Contact: resp.GetContact(), - }, - Severity: s.String(), - }) - } + ds = append(ds, d) } - return res, nil + return ds, nil } -func ModelFromBinary(ctx context.Context, plugin *detector_api.DetectorPlugin, bin []byte) (*model.Detector, error) { +func BinToModel(ctx context.Context, plugin *detector_api.DetectorPlugin, bin []byte) (*model.Detector, error) { detector, err := plugin.LoadBinary(ctx, bin) if err != nil { return nil, fmt.Errorf("can't load wasm module: %w", err) diff --git a/event-processor/pkg/processor/detector/matcher.go b/event-processor/pkg/processor/detector/matcher.go new file mode 100644 index 00000000..e6bc1e2a --- /dev/null +++ b/event-processor/pkg/processor/detector/matcher.go @@ -0,0 +1,99 @@ +package detector + +import ( + "context" + "fmt" + "maps" + + "github.com/cilium/tetragon/pkg/arch" + "github.com/runtime-radar/runtime-radar/event-processor/api" + detector_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api" +) + +// Matcher is a matrix which links events and detectors (event type -> function -> chain). It makes it possible to dynamically construct a [Chain] via [Matcher.MatchChain] method. +type Matcher map[string]map[string]Chain + +func NewMatcher(ctx context.Context, ds ...detector_api.Detector) (Matcher, error) { + m := Matcher{} + + for _, d := range ds { + infoResp, err := d.Info(ctx, &detector_api.InfoReq{}) + if err != nil { + return nil, fmt.Errorf("can't get detector info: %w", err) + } + + key := Key{infoResp.GetId(), uint(infoResp.GetVersion())} + + info := &api.Detector{ + Id: infoResp.GetId(), + Name: infoResp.GetName(), + Description: infoResp.GetDescription(), + Version: infoResp.GetVersion(), + Author: infoResp.GetAuthor(), + Contact: infoResp.GetContact(), + License: infoResp.GetLicense(), + } + + w := Wrapper{ + Detector: d, + Info: info, + } + + tcResp, err := d.TriggerCriteria(ctx, &detector_api.TriggerCriteriaReq{}) + if err != nil { + return nil, fmt.Errorf("can't get detector trigger criteria: %w", err) + } + + if len(tcResp.GetCriteria()) == 0 { + return nil, fmt.Errorf("empty trigger criteria for detector: %+v", key) + } + + for k, v := range tcResp.GetCriteria() { + eventType := k + funcNames := v.GetFuncNames() + + if m[eventType] == nil { + m[eventType] = map[string]Chain{} + } + + if len(funcNames) == 0 { + t := m[eventType]["*"] + if t == nil { + m[eventType]["*"] = Chain{key: w} + } else { + maps.Copy(t, Chain{key: w}) + } + } else { + for _, fn := range funcNames { + _, fn = arch.CutSyscallPrefix(fn) + t := m[eventType][fn] + if t == nil { + m[eventType][fn] = Chain{key: w} + } else { + maps.Copy(t, Chain{key: w}) + } + } + } + } + } + + return m, nil +} + +func (m Matcher) MatchChain(eventType string, funcNames ...string) Chain { + // Always match "*" pattern + funcNames = append(funcNames, "*") + + var chain Chain + + for _, fn := range funcNames { + matched, ok := m[eventType][fn] + if ok && chain == nil { + chain = maps.Clone(matched) + } else if ok { + maps.Copy(chain, matched) + } + } + + return chain +} diff --git a/event-processor/pkg/processor/detector/matcher_test.go b/event-processor/pkg/processor/detector/matcher_test.go new file mode 100644 index 00000000..3c52bcbc --- /dev/null +++ b/event-processor/pkg/processor/detector/matcher_test.go @@ -0,0 +1,205 @@ +package detector + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + detector_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api" +) + +func TestMatcher(t *testing.T) { + t.Parallel() + + allDetectors := []detector_api.Detector{ + &TestExecAll{}, + &TestKprobeTCP{}, + &TestKprobeFile1{}, + &TestKprobeFile2{}, + &TestKprobeAll{}, + } + + testcases := []struct { + Name string + Detectors []detector_api.Detector + EventType string + FuncNames []string + MatchedIDs []string + }{ + { + "Test exec all detector", + allDetectors, + "PROCESS_EXEC", + []string{}, + []string{"TEST_EXEC_ALL"}, + }, + { + "Test kprobe tcp_connect detector", + allDetectors, + "PROCESS_KPROBE", + []string{"tcp_connect"}, + []string{"TEST_KPROBE_ALL", "TEST_KPROBE_TCP"}, + }, + { + "Test kprobe security_file_permission detector", + allDetectors, + "PROCESS_KPROBE", + []string{"security_file_permission"}, + []string{"TEST_KPROBE_ALL", "TEST_KPROBE_FILE_1", "TEST_KPROBE_FILE_2"}, + }, + } + + for _, tc := range testcases { + t.Run(tc.Name, func(t *testing.T) { + t.Parallel() + + matcher, err := NewMatcher(context.Background(), tc.Detectors...) + if err != nil { + t.Fatalf("Can't create matcher: %v", err) + } + + chain := matcher.MatchChain(tc.EventType, tc.FuncNames...) + ids := getIDs(chain) + + if diff := cmp.Diff(ids, tc.MatchedIDs, + cmpopts.SortSlices(func(a, b string) bool { + return a < b // particular way of sorting does not matter + }), + ); diff != "" { + t.Fatalf("Expected detectors != actual: %s", diff) + } + }) + } +} + +func getIDs(chain Chain) (ids []string) { + for k := range chain { + ids = append(ids, k.ID) + } + + return +} + +type TestExecAll struct { + detector_api.Detector +} + +func (d *TestExecAll) Info(_ context.Context, _ *detector_api.InfoReq) (*detector_api.InfoResp, error) { + resp := &detector_api.InfoResp{ + Id: "TEST_EXEC_ALL", + Version: 1, + } + + return resp, nil +} + +func (d *TestExecAll) TriggerCriteria(_ context.Context, _ *detector_api.TriggerCriteriaReq) (*detector_api.TriggerCriteriaResp, error) { + resp := &detector_api.TriggerCriteriaResp{ + Criteria: map[string]*detector_api.TriggerCriteriaResp_FuncNames{ + "PROCESS_EXEC": { + FuncNames: []string{"*"}, + }, + }, + } + + return resp, nil +} + +type TestKprobeTCP struct { + detector_api.Detector +} + +func (d *TestKprobeTCP) Info(_ context.Context, _ *detector_api.InfoReq) (*detector_api.InfoResp, error) { + resp := &detector_api.InfoResp{ + Id: "TEST_KPROBE_TCP", + Version: 1, + } + + return resp, nil +} + +func (d *TestKprobeTCP) TriggerCriteria(_ context.Context, _ *detector_api.TriggerCriteriaReq) (*detector_api.TriggerCriteriaResp, error) { + resp := &detector_api.TriggerCriteriaResp{ + Criteria: map[string]*detector_api.TriggerCriteriaResp_FuncNames{ + "PROCESS_KPROBE": { + FuncNames: []string{"tcp_connect", "tcp_close", "tcp_sendmsg"}, + }, + }, + } + + return resp, nil +} + +type TestKprobeFile1 struct { + detector_api.Detector +} + +func (d *TestKprobeFile1) Info(_ context.Context, _ *detector_api.InfoReq) (*detector_api.InfoResp, error) { + resp := &detector_api.InfoResp{ + Id: "TEST_KPROBE_FILE_1", + Version: 1, + } + + return resp, nil +} + +func (d *TestKprobeFile1) TriggerCriteria(_ context.Context, _ *detector_api.TriggerCriteriaReq) (*detector_api.TriggerCriteriaResp, error) { + resp := &detector_api.TriggerCriteriaResp{ + Criteria: map[string]*detector_api.TriggerCriteriaResp_FuncNames{ + "PROCESS_KPROBE": { + FuncNames: []string{"security_file_permission", "security_mmap_file", "security_path_truncate"}, + }, + }, + } + + return resp, nil +} + +type TestKprobeFile2 struct { + detector_api.Detector +} + +func (d *TestKprobeFile2) Info(_ context.Context, _ *detector_api.InfoReq) (*detector_api.InfoResp, error) { + resp := &detector_api.InfoResp{ + Id: "TEST_KPROBE_FILE_2", + Version: 1, + } + + return resp, nil +} + +func (d *TestKprobeFile2) TriggerCriteria(_ context.Context, _ *detector_api.TriggerCriteriaReq) (*detector_api.TriggerCriteriaResp, error) { + resp := &detector_api.TriggerCriteriaResp{ + Criteria: map[string]*detector_api.TriggerCriteriaResp_FuncNames{ + "PROCESS_KPROBE": { + FuncNames: []string{"security_file_permission", "sys_write"}, + }, + }, + } + + return resp, nil +} + +type TestKprobeAll struct { + detector_api.Detector +} + +func (d *TestKprobeAll) Info(_ context.Context, _ *detector_api.InfoReq) (*detector_api.InfoResp, error) { + resp := &detector_api.InfoResp{ + Id: "TEST_KPROBE_ALL", + Version: 1, + } + + return resp, nil +} + +func (d *TestKprobeAll) TriggerCriteria(_ context.Context, _ *detector_api.TriggerCriteriaReq) (*detector_api.TriggerCriteriaResp, error) { + resp := &detector_api.TriggerCriteriaResp{ + Criteria: map[string]*detector_api.TriggerCriteriaResp_FuncNames{ + "PROCESS_KPROBE": {}, + }, + } + + return resp, nil +} diff --git a/event-processor/pkg/processor/event_data.go b/event-processor/pkg/processor/event_data.go index d4efafff..11ff4bc6 100644 --- a/event-processor/pkg/processor/event_data.go +++ b/event-processor/pkg/processor/event_data.go @@ -6,6 +6,7 @@ import ( "time" "github.com/cilium/tetragon/api/v1/tetragon" + "github.com/cilium/tetragon/pkg/arch" history_model "github.com/runtime-radar/runtime-radar/history-api/pkg/model" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/wrapperspb" @@ -111,6 +112,29 @@ func getEventData(e *tetragon.GetEventsResponse) (*eventData, error) { return ed, nil } +// getEventAndFunc parses event and returns corresponding event type and function. +func getEventAndFunc(ev *tetragon.GetEventsResponse) (string, string) { + switch e := ev.GetEvent().(type) { + case *tetragon.GetEventsResponse_ProcessExec: + return history_model.RuntimeEventTypeProcessExec, "" + case *tetragon.GetEventsResponse_ProcessExit: + return history_model.RuntimeEventTypeProcessExit, "" + case *tetragon.GetEventsResponse_ProcessKprobe: + funcName := e.ProcessKprobe.GetFunctionName() + _, funcName = arch.CutSyscallPrefix(funcName) + return history_model.RuntimeEventTypeProcessKprobe, funcName + case *tetragon.GetEventsResponse_ProcessTracepoint: + return history_model.RuntimeEventTypeProcessTracepoint, "" + case *tetragon.GetEventsResponse_ProcessLoader: + return history_model.RuntimeEventTypeProcessLoader, "" + case *tetragon.GetEventsResponse_ProcessUprobe: + sym := e.ProcessUprobe.GetSymbol() + return history_model.RuntimeEventTypeProcessUprobe, sym + default: + return history_model.RuntimeEventTypeUndef, "" + } +} + // setCommonAttributes sets process' and parent's (if not nil) attributes, // that are common for different types of events. func setCommonAttributes(process, parent *tetragon.Process, ed *eventData) { @@ -177,13 +201,13 @@ func uint32WrapperToPtr(v *wrapperspb.UInt32Value) *uint32 { } func capsToStrings(caps []tetragon.CapabilitiesType) []string { - strs := make([]string, 0, len(caps)) + ss := make([]string, 0, len(caps)) for _, cap := range caps { - strs = append(strs, cap.String()) + ss = append(ss, cap.String()) } - return strs + return ss } func marshalOptions() protojson.MarshalOptions { diff --git a/event-processor/pkg/processor/processor.go b/event-processor/pkg/processor/processor.go index 990bafdb..52237032 100644 --- a/event-processor/pkg/processor/processor.go +++ b/event-processor/pkg/processor/processor.go @@ -187,6 +187,13 @@ func (wp *WorkersPool) SetBins(bins [][]byte) { wp.bins = bins } +func (wp *WorkersPool) registerUpdate(upd chan bool) { + wp.binsMu.Lock() + defer wp.binsMu.Unlock() + + wp.updates = append(wp.updates, upd) +} + func BinsRootHashAsHex(bins [][]byte) string { hashes := make([][]byte, 0, len(bins)) for _, b := range bins { diff --git a/event-processor/pkg/processor/worker.go b/event-processor/pkg/processor/worker.go index 261504b5..fac27740 100644 --- a/event-processor/pkg/processor/worker.go +++ b/event-processor/pkg/processor/worker.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/rs/zerolog/log" "github.com/runtime-radar/runtime-radar/event-processor/api" + detector_api "github.com/runtime-radar/runtime-radar/event-processor/detector/api" "github.com/runtime-radar/runtime-radar/event-processor/pkg/processor/detector" enforcer_api "github.com/runtime-radar/runtime-radar/policy-enforcer/api" enforcer_model "github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model" @@ -34,32 +35,33 @@ func (wp *WorkersPool) worker(id int) { bins, rootHash := wp.Bins() t0 := time.Now() - chain, err := detector.NewChain(ctx, wp.plugin, bins) + + matcher, err := getMatcher(ctx, wp.plugin, bins) if err != nil { // If very first initialization failed, there are not too many options - panic(fmt.Errorf("can't init detector chain when starting worker[%d]: %w", id, err)) + panic(fmt.Errorf("can't init matcher when starting worker[%d]: %w", id, err)) } - log.Info().Str("delay", time.Since(t0).String()).Int("len", len(chain)).Str("root_hash", rootHash).Msgf("Detector chain initialized for worker[%d]", id) + log.Info().Str("delay", time.Since(t0).String()).Str("root_hash", rootHash).Msgf("Matcher initialized for worker[%d]", id) upd := make(chan bool, 1) - wp.updates = append(wp.updates, upd) + wp.registerUpdate(upd) for { select { case <-upd: bins, rootHash := wp.Bins() t0 := time.Now() - chain, err = detector.NewChain(ctx, wp.plugin, bins) + matcher, err = getMatcher(ctx, wp.plugin, bins) if err != nil { - log.Error().Err(err).Msgf("Can't init detector chain for worker[%d]", id) + log.Error().Err(err).Msgf("Can't init matcher chain for worker[%d]", id) } else { - log.Info().Str("delay", time.Since(t0).String()).Int("len", len(chain)).Str("root_hash", rootHash).Msgf("Detector chain initialized for worker[%d]", id) + log.Info().Str("delay", time.Since(t0).String()).Str("root_hash", rootHash).Msgf("Matcher initialized for worker[%d]", id) } case j := <-wp.jobs: log.Debug().Interface("job", j).Int("id", id).Msgf("Worker[%d] got job", id) t0 := time.Now() - result, err := wp.doJob(ctx, j, chain) // <-- do the job + result, err := wp.doJob(ctx, j, matcher) // <-- do the job delta := time.Since(t0) if wp.withReports { @@ -88,15 +90,20 @@ func (wp *WorkersPool) worker(id int) { } } -func (wp *WorkersPool) doJob(ctx context.Context, event *tetragon.GetEventsResponse, chain detector.Chain) (*detector.ChainResult, error) { - t0 := time.Now() +func (wp *WorkersPool) doJob(ctx context.Context, event *tetragon.GetEventsResponse, matcher detector.Matcher) (*detector.ChainResult, error) { + eventType, funcName := getEventAndFunc(event) + chain := matcher.MatchChain(eventType, funcName) + log.Debug().Str("event_type", eventType).Str("func_name", funcName).Str("chain", chain.String()).Msgf("Got detectors chain") + + t0 := time.Now() result, err := chain.Detect(ctx, event) if err != nil { return nil, fmt.Errorf("can't detect event: %w", err) } delta := time.Since(t0) - log.Debug().Str("delay", delta.String()).Interface("event", event).Interface("result", result).Msgf("Detector chain is done") + + log.Debug().Str("delay", delta.String()).Interface("event", event).Interface("result", result).Msgf("Detectors chain is done") eventData, err := getEventData(event) if err != nil { @@ -106,12 +113,20 @@ func (wp *WorkersPool) doJob(ctx context.Context, event *tetragon.GetEventsRespo blockRules, notifyRules := []*enforcer_api.Rule{}, []*enforcer_api.Rule{} incidentSeverity := enforcer_model.NoneSeverity // incident's severity to be passed to history API. Depends on policy enforce's response - if len(result.Threats) > 0 { + var threats []*api.Threat + var detectErrors []*api.DetectError + + if result != nil { + threats = result.Threats + detectErrors = result.Errors + } + + if len(threats) > 0 { // TODO: temporarily enabled logging of threats to INFO level, need to take a look if it adds any valuable overhead in production, and in case it does, // it will be a subject for removal (there is already a lot of DEBUG messages at the moment, no need to add another one) - log.Info().Str("delay", delta.String()).Interface("event_data", eventData).Interface("result", result).Msg("Threats detected") + log.Info().Str("delay", delta.String()).Interface("event_data", eventData).Int("chain_length", len(chain)).Interface("result", result).Msg("Threats detected") - enforcerResp, err := wp.evaluatePolicy(ctx, eventData, result.Threats) + enforcerResp, err := wp.evaluatePolicy(ctx, eventData, threats) if err != nil { return nil, fmt.Errorf("can't evaluate policy: %w", err) } @@ -137,19 +152,19 @@ func (wp *WorkersPool) doJob(ctx context.Context, event *tetragon.GetEventsRespo notifyRules = append(notifyRules, r) } } - } else if len(result.Errors) > 0 { + } else if len(detectErrors) > 0 { log.Info().Str("delay", delta.String()).Interface("event_data", eventData).Interface("result", result).Msg("Detect errors found") } var eventID string - if cfg := wp.Config(); shouldSaveEvent(cfg.Config.HistoryControl, result.Threats) { + if cfg := wp.Config(); shouldSaveEvent(cfg.Config.HistoryControl, threats) { eventID = uuid.NewString() re := &api.RuntimeEvent{ Id: eventID, TetragonVersion: tetragonVersion, Event: event, - Threats: result.Threats, - DetectErrors: result.Errors, + Threats: threats, + DetectErrors: detectErrors, IsIncident: len(blockRules) > 0 || len(notifyRules) > 0, IncidentSeverity: incidentSeverity.String(), BlockBy: uniqueRuleIDs(blockRules), @@ -176,6 +191,20 @@ func (wp *WorkersPool) doJob(ctx context.Context, event *tetragon.GetEventsRespo return result, nil } +func getMatcher(ctx context.Context, plugin *detector_api.DetectorPlugin, bins [][]byte) (detector.Matcher, error) { + ds, err := detector.BinsToDetectors(ctx, plugin, bins) + if err != nil { + return nil, fmt.Errorf("can't get detectors from bins: %w", err) + } + + m, err := detector.NewMatcher(ctx, ds...) + if err != nil { + return nil, fmt.Errorf("can't init matcher: %w", err) + } + + return m, nil +} + func uniqueRules(rs []*enforcer_api.Rule) []*enforcer_api.Rule { m := make(map[string]*enforcer_api.Rule, len(rs)) diff --git a/event-processor/pkg/server/server.go b/event-processor/pkg/server/server.go index 245956e7..6486cf94 100644 --- a/event-processor/pkg/server/server.go +++ b/event-processor/pkg/server/server.go @@ -19,8 +19,8 @@ import ( ) const ( - readTimeout = 5 * time.Second - writeTimeout = 5 * time.Second + readTimeout = 30 * time.Second + writeTimeout = 30 * time.Second // Maximum message size for grpc request MaxRecvMsgSize = 10 * 1024 * 1024 // 10MB ) diff --git a/event-processor/pkg/service/detector_generic.go b/event-processor/pkg/service/detector_generic.go index f0fc3927..2a74cbbc 100644 --- a/event-processor/pkg/service/detector_generic.go +++ b/event-processor/pkg/service/detector_generic.go @@ -37,7 +37,7 @@ func (dg *DetectorGeneric) Create(ctx context.Context, req *api.CreateDetectorRe return nil, status.Errorf(codes.InvalidArgument, "can't parse base64 binary: %v", err) } - d, err := detector.ModelFromBinary(ctx, dg.DetectorPlugin, wasmBinary) + d, err := detector.BinToModel(ctx, dg.DetectorPlugin, wasmBinary) if err != nil { return nil, status.Errorf(codes.Internal, "can't get detector info from binary: %v", err) } diff --git a/event-processor/vendor/github.com/cilium/tetragon/LICENSE b/event-processor/vendor/github.com/cilium/tetragon/LICENSE new file mode 100644 index 00000000..a2e486a8 --- /dev/null +++ b/event-processor/vendor/github.com/cilium/tetragon/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} Authors of Cilium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/event-processor/vendor/github.com/cilium/tetragon/pkg/arch/arch.go b/event-processor/vendor/github.com/cilium/tetragon/pkg/arch/arch.go new file mode 100644 index 00000000..e1bddf19 --- /dev/null +++ b/event-processor/vendor/github.com/cilium/tetragon/pkg/arch/arch.go @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Tetragon + +package arch + +import ( + "fmt" + "runtime" + "strings" + "testing" +) + +var supportedArchPrefix = map[string]string{"amd64": "__x64_", "arm64": "__arm64_", "i386": "__ia32_"} + +func addSyscallPrefix(symbol string, arch string) (string, error) { + for prefix_arch, prefix := range supportedArchPrefix { + if strings.HasPrefix(symbol, prefix) { + // check that the prefix found is the correct one + if prefix_arch != arch { + return "", fmt.Errorf("expecting %s and got %s", supportedArchPrefix[arch], prefix) + } + return symbol, nil + } + } + if prefix, found := supportedArchPrefix[arch]; found { + return prefix + symbol, nil + } + return "", fmt.Errorf("unsupported architecture %s", arch) +} + +// AddSyscallPrefix detects if the symbol is already prefixed with arch specific +// prefix in the form of "__x64_" or "__arm64_", and if not, adds it based on +// provided arch. +// +// Note that cilium/ebpf, retries to attach to an arch specific version of the +// symbol after a failure thus making possible to attach to "sys_listen" which +// will fail and retry with the corrected "__arm64_sys_listen" if you are +// running on arm64. See https://github.com/cilium/ebpf/pull/304. However, this +// causes Tetragon users to believe that two symbols exist (following the same +// example) "__arm64_sys_listen" and "sys_listen", which results in differents +// events. Because we actually know if a call is a syscall, we can pre-format +// the symbol directly here to allow the user to specify the "sys_listen" +// version while only registering the real symbol "__arm64_sys_listen". +func AddSyscallPrefix(symbol string) (string, error) { + return addSyscallPrefix(symbol, runtime.GOARCH) +} + +// AddSyscallPrefixTestHelper is like AddSyscallPrefix but calls t.Fatal if the +// arch is unsupported or if the symbol has already a prefix that doesn't +// correspond to the running arch. +// +// It's a helper supposed to be used only in testing code. +func AddSyscallPrefixTestHelper(t *testing.T, symbol string) string { + syscallName, err := AddSyscallPrefix(symbol) + if err != nil { + t.Fatal(err) + } + return syscallName +} + +// CutSyscallPrefix removes a potential arch specific prefix from the symbol. +// If a prefix was removed, it returns the corresponding arch as a first argument. +func CutSyscallPrefix(symbol string) (arch string, name string) { + for a, p := range supportedArchPrefix { + if rest, ok := strings.CutPrefix(symbol, p); ok { + arch = a + name = rest + return + } + } + + name = symbol + return +} + +func HasSyscallPrefix(symbol string) bool { + for _, prefix := range supportedArchPrefix { + if strings.HasPrefix(symbol, prefix) { + return true + } + } + return false +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/event-processor/vendor/github.com/fsnotify/fsnotify/.cirrus.yml new file mode 100644 index 00000000..f4e7dbf3 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/.cirrus.yml @@ -0,0 +1,14 @@ +freebsd_task: + name: 'FreeBSD' + freebsd_instance: + image_family: freebsd-14-1 + install_script: + - pkg update -f + - pkg install -y go + test_script: + # run tests as user "cirrus" instead of root + - pw useradd cirrus -m + - chown -R cirrus:cirrus . + - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./... diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/.editorconfig b/event-processor/vendor/github.com/fsnotify/fsnotify/.editorconfig deleted file mode 100644 index fad89585..00000000 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -root = true - -[*.go] -indent_style = tab -indent_size = 4 -insert_final_newline = true - -[*.{yml,yaml}] -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/.gitattributes b/event-processor/vendor/github.com/fsnotify/fsnotify/.gitattributes deleted file mode 100644 index 32f1001b..00000000 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -go.sum linguist-generated diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/.gitignore b/event-processor/vendor/github.com/fsnotify/fsnotify/.gitignore index 1d89d85c..daea9dd6 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -4,3 +4,7 @@ # Output of go build ./cmd/fsnotify /fsnotify +/fsnotify.exe + +/test/kqueue +/test/a.out diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/event-processor/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index 77f9593b..fa854785 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,16 +1,115 @@ # Changelog -All notable changes to this project will be documented in this file. +1.8.0 2023-10-31 +---------------- -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### Additions + +- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619]) + +### Changes and fixes + +- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610]) + +- kqueue: ignore events with Ident=0 ([#590]) + +- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617]) + +- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625]) + +- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620]) + +- inotify: fix panic when calling Remove() in a goroutine ([#650]) + +- fen: allow watching subdirectories of watched directories ([#621]) + +[#590]: https://github.com/fsnotify/fsnotify/pull/590 +[#610]: https://github.com/fsnotify/fsnotify/pull/610 +[#617]: https://github.com/fsnotify/fsnotify/pull/617 +[#619]: https://github.com/fsnotify/fsnotify/pull/619 +[#620]: https://github.com/fsnotify/fsnotify/pull/620 +[#621]: https://github.com/fsnotify/fsnotify/pull/621 +[#625]: https://github.com/fsnotify/fsnotify/pull/625 +[#650]: https://github.com/fsnotify/fsnotify/pull/650 + +1.7.0 - 2023-10-22 +------------------ +This version of fsnotify needs Go 1.17. + +### Additions + +- illumos: add FEN backend to support illumos and Solaris. ([#371]) + +- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful + in cases where you can't control the kernel buffer and receive a large number + of events in bursts. ([#550], [#572]) + +- all: add `AddWith()`, which is identical to `Add()` but allows passing + options. ([#521]) + +- windows: allow setting the ReadDirectoryChangesW() buffer size with + `fsnotify.WithBufferSize()`; the default of 64K is the highest value that + works on all platforms and is enough for most purposes, but in some cases a + highest buffer is needed. ([#521]) + +### Changes and fixes + +- inotify: remove watcher if a watched path is renamed ([#518]) + + After a rename the reported name wasn't updated, or even an empty string. + Inotify doesn't provide any good facilities to update it, so just remove the + watcher. This is already how it worked on kqueue and FEN. + + On Windows this does work, and remains working. + +- windows: don't listen for file attribute changes ([#520]) + + File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API, + with no way to see if they're a file write or attribute change, so would show + up as a fsnotify.Write event. This is never useful, and could result in many + spurious Write events. + +- windows: return `ErrEventOverflow` if the buffer is full ([#525]) + + Before it would merely return "short read", making it hard to detect this + error. + +- kqueue: make sure events for all files are delivered properly when removing a + watched directory ([#526]) + + Previously they would get sent with `""` (empty string) or `"."` as the path + name. + +- kqueue: don't emit spurious Create events for symbolic links ([#524]) + + The link would get resolved but kqueue would "forget" it already saw the link + itself, resulting on a Create for every Write event for the directory. + +- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516]) -## [Unreleased] +- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in + `backend_other.go`, making it easier to use on unsupported platforms such as + WASM, AIX, etc. ([#528]) -Nothing yet. +- other: use the `backend_other.go` no-op if the `appengine` build tag is set; + Google AppEngine forbids usage of the unsafe package so the inotify backend + won't compile there. -## [1.6.0] - 2022-10-13 +[#371]: https://github.com/fsnotify/fsnotify/pull/371 +[#516]: https://github.com/fsnotify/fsnotify/pull/516 +[#518]: https://github.com/fsnotify/fsnotify/pull/518 +[#520]: https://github.com/fsnotify/fsnotify/pull/520 +[#521]: https://github.com/fsnotify/fsnotify/pull/521 +[#524]: https://github.com/fsnotify/fsnotify/pull/524 +[#525]: https://github.com/fsnotify/fsnotify/pull/525 +[#526]: https://github.com/fsnotify/fsnotify/pull/526 +[#528]: https://github.com/fsnotify/fsnotify/pull/528 +[#537]: https://github.com/fsnotify/fsnotify/pull/537 +[#550]: https://github.com/fsnotify/fsnotify/pull/550 +[#572]: https://github.com/fsnotify/fsnotify/pull/572 +1.6.0 - 2022-10-13 +------------------ This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1, but not documented). It also increases the minimum Linux version to 2.6.32. diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/event-processor/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md index ea379759..e4ac2a2f 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -1,7 +1,7 @@ Thank you for your interest in contributing to fsnotify! We try to review and merge PRs in a reasonable timeframe, but please be aware that: -- To avoid "wasted" work, please discus changes on the issue tracker first. You +- To avoid "wasted" work, please discuss changes on the issue tracker first. You can just send PRs, but they may end up being rejected for one reason or the other. @@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like Use the `-short` flag to make the "stress test" run faster. +Writing new tests +----------------- +Scripts in the testdata directory allow creating test cases in a "shell-like" +syntax. The basic format is: + + script + + Output: + desired output + +For example: + + # Create a new empty file with some data. + watch / + echo data >/file + + Output: + create /file + write /file + +Just create a new file to add a new test; select which tests to run with +`-run TestScript/[path]`. + +script +------ +The script is a "shell-like" script: + + cmd arg arg + +Comments are supported with `#`: + + # Comment + cmd arg arg # Comment + +All operations are done in a temp directory; a path like "/foo" is rewritten to +"/tmp/TestFoo/foo". + +Arguments can be quoted with `"` or `'`; there are no escapes and they're +functionally identical right now, but this may change in the future, so best to +assume shell-like rules. + + touch "/file with spaces" + +End-of-line escapes with `\` are not supported. + +### Supported commands + + watch path [ops] # Watch the path, reporting events for it. Nothing is + # watched by default. Optionally a list of ops can be + # given, as with AddWith(path, WithOps(...)). + unwatch path # Stop watching the path. + watchlist n # Assert watchlist length. + + stop # Stop running the script; for debugging. + debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in + parallel by default, so -parallel=1 is probably a good + idea). + + touch path + mkdir [-p] dir + ln -s target link # Only ln -s supported. + mkfifo path + mknod dev path + mv src dst + rm [-r] path + chmod mode path # Octal only + sleep time-in-ms + + cat path # Read path (does nothing with the data; just reads it). + echo str >>path # Append "str" to "path". + echo str >path # Truncate "path" and write "str". + + require reason # Skip the test if "reason" is true; "skip" and + skip reason # "require" behave identical; it supports both for + # readability. Possible reasons are: + # + # always Always skip this test. + # symlink Symlinks are supported (requires admin + # permissions on Windows). + # mkfifo Platform doesn't support FIFO named sockets. + # mknod Platform doesn't support device nodes. + + +output +------ +After `Output:` the desired output is given; this is indented by convention, but +that's not required. + +The format of that is: + + # Comment + event path # Comment + + system: + event path + system2: + event path + +Every event is one line, and any whitespace between the event and path are +ignored. The path can optionally be surrounded in ". Anything after a "#" is +ignored. + +Platform-specific tests can be added after GOOS; for example: + + watch / + touch /file + + Output: + # Tested if nothing else matches + create /file + + # Windows-specific test. + windows: + write /file + +You can specify multiple platforms with a comma (e.g. "windows, linux:"). +"kqueue" is a shortcut for all kqueue systems (BSD, macOS). + [goon]: https://github.com/arp242/goon [Vagrant]: https://www.vagrantup.com/ diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/README.md b/event-processor/vendor/github.com/fsnotify/fsnotify/README.md index d4e6080f..e480733d 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/README.md +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/README.md @@ -1,29 +1,31 @@ fsnotify is a Go library to provide cross-platform filesystem notifications on -Windows, Linux, macOS, and BSD systems. +Windows, Linux, macOS, BSD, and illumos. -Go 1.16 or newer is required; the full documentation is at +Go 1.17 or newer is required; the full documentation is at https://pkg.go.dev/github.com/fsnotify/fsnotify -**It's best to read the documentation at pkg.go.dev, as it's pinned to the last -released version, whereas this README is for the last development version which -may include additions/changes.** - --- Platform support: -| Adapter | OS | Status | -| --------------------- | ---------------| -------------------------------------------------------------| -| inotify | Linux 2.6.32+ | Supported | -| kqueue | BSD, macOS | Supported | -| ReadDirectoryChangesW | Windows | Supported | -| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | -| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | -| fanotify | Linux 5.9+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | -| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | -| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | - -Linux and macOS should include Android and iOS, but these are currently untested. +| Backend | OS | Status | +| :-------------------- | :--------- | :------------------------------------------------------------------------ | +| inotify | Linux | Supported | +| kqueue | BSD, macOS | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FEN | illumos | Supported | +| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) | +| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment | +| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] | +| USN Journals | Windows | [Needs support in x/sys/windows][usn] | +| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) | + +Linux and illumos should include Android and Solaris, but these are currently +untested. + +[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120 +[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847 +[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129 Usage ----- @@ -83,20 +85,23 @@ run with: % go run ./cmd/fsnotify +Further detailed documentation can be found in godoc: +https://pkg.go.dev/github.com/fsnotify/fsnotify + FAQ --- ### Will a file still be watched when it's moved to another directory? No, not unless you are watching the location it was moved to. -### Are subdirectories watched too? +### Are subdirectories watched? No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap: [#18]). [#18]: https://github.com/fsnotify/fsnotify/issues/18 ### Do I have to watch the Error and Event channels in a goroutine? -As of now, yes (you can read both channels in the same goroutine using `select`, -you don't need a separate goroutine for both channels; see the example). +Yes. You can read both channels in the same goroutine using `select` (you don't +need a separate goroutine for both channels; see the example). ### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys? fsnotify requires support from underlying OS to work. The current NFS and SMB @@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented. [#9]: https://github.com/fsnotify/fsnotify/issues/9 +### Why do I get many Chmod events? +Some programs may generate a lot of attribute changes; for example Spotlight on +macOS, anti-virus programs, backup applications, and some others are known to do +this. As a rule, it's typically best to ignore Chmod events. They're often not +useful, and tend to cause problems. + +Spotlight indexing on macOS can result in multiple events (see [#15]). A +temporary workaround is to add your folder(s) to the *Spotlight Privacy +settings* until we have a native FSEvents implementation (see [#11]). + +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#15]: https://github.com/fsnotify/fsnotify/issues/15 + +### Watching a file doesn't work well +Watching individual files (rather than directories) is generally not recommended +as many programs (especially editors) update files atomically: it will write to +a temporary file which is then moved to to destination, overwriting the original +(or some variant thereof). The watcher on the original file is now lost, as that +no longer exists. + +The upshot of this is that a power failure or crash won't leave a half-written +file. + +Watch the parent directory and use `Event.Name` to filter out files you're not +interested in. There is an example of this in `cmd/fsnotify/file.go`. + Platform-specific notes ----------------------- ### Linux @@ -151,11 +182,3 @@ these platforms. The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to control the maximum number of open files. - -### macOS -Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary -workaround is to add your folder(s) to the *Spotlight Privacy settings* until we -have a native FSEvents implementation (see [#11]). - -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#15]: https://github.com/fsnotify/fsnotify/issues/15 diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_fen.go index 1a95ad8e..c349c326 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_fen.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_fen.go @@ -1,162 +1,484 @@ //go:build solaris -// +build solaris + +// FEN backend for illumos (supported) and Solaris (untested, but should work). +// +// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create package fsnotify import ( "errors" + "fmt" + "os" + "path/filepath" + "sync" + "time" + + "github.com/fsnotify/fsnotify/internal" + "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # macOS notes -// -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). -// -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. +type fen struct { Events chan Event - - // Errors sends any errors. Errors chan error + + mu sync.Mutex + port *unix.EventPort + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + dirs map[string]Op // Explicitly watched directories + watches map[string]Op // Explicitly watched non-directories } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) } -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + w := &fen{ + Events: ev, + Errors: errs, + dirs: make(map[string]Op), + watches: make(map[string]Op), + done: make(chan struct{}), + } + + var err error + w.port, err = unix.NewEventPort() + if err != nil { + return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err) + } + + go w.readEvents() + return w, nil +} + +// sendEvent attempts to send an event to the user, returning true if the event +// was put in the channel successfully and false if the watcher has been closed. +func (w *fen) sendEvent(name string, op Op) (sent bool) { + select { + case <-w.done: + return false + case w.Events <- Event{Name: name, Op: op}: + return true + } +} + +// sendError attempts to send an error to the user, returning true if the error +// was put in the channel successfully and false if the watcher has been closed. +func (w *fen) sendError(err error) (sent bool) { + if err == nil { + return true + } + select { + case <-w.done: + return false + case w.Errors <- err: + return true + } +} + +func (w *fen) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +func (w *fen) Close() error { + // Take the lock used by associateFile to prevent lingering events from + // being processed after the close + w.mu.Lock() + defer w.mu.Unlock() + if w.isClosed() { + return nil + } + close(w.done) + return w.port.Close() +} + +func (w *fen) Add(name string) error { return w.AddWith(name) } + +func (w *fen) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + + // Currently we resolve symlinks that were explicitly requested to be + // watched. Otherwise we would use LStat here. + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Associate all files in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, true, w.associateFile) + if err != nil { + return err + } + + w.mu.Lock() + w.dirs[name] = with.op + w.mu.Unlock() + return nil + } + + err = w.associateFile(name, stat, true) + if err != nil { + return err + } + + w.mu.Lock() + w.watches[name] = with.op + w.mu.Unlock() return nil } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. -// -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { +func (w *fen) Remove(name string) error { + if w.isClosed() { + return nil + } + if !w.port.PathIsWatched(name) { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + // The user has expressed an intent. Immediately remove this name from + // whichever watch list it might be in. If it's not in there the delete + // doesn't cause harm. + w.mu.Lock() + delete(w.watches, name) + delete(w.dirs, name) + w.mu.Unlock() + + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Remove associations for every file in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, false, w.dissociateFile) + if err != nil { + return err + } + return nil + } + + err = w.port.DissociatePath(name) + if err != nil { + return err + } + return nil } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { +// readEvents contains the main loop that runs in a goroutine watching for events. +func (w *fen) readEvents() { + // If this function returns, the watcher has been closed and we can close + // these channels + defer func() { + close(w.Errors) + close(w.Events) + }() + + pevents := make([]unix.PortEvent, 8) + for { + count, err := w.port.Get(pevents, 1, nil) + if err != nil && err != unix.ETIME { + // Interrupted system call (count should be 0) ignore and continue + if errors.Is(err, unix.EINTR) && count == 0 { + continue + } + // Get failed because we called w.Close() + if errors.Is(err, unix.EBADF) && w.isClosed() { + return + } + // There was an error not caused by calling w.Close() + if !w.sendError(err) { + return + } + } + + p := pevents[:count] + for _, pevent := range p { + if pevent.Source != unix.PORT_SOURCE_FILE { + // Event from unexpected source received; should never happen. + if !w.sendError(errors.New("Event from unexpected source received")) { + return + } + continue + } + + if debug { + internal.Debug(pevent.Path, pevent.Events) + } + + err = w.handleEvent(&pevent) + if !w.sendError(err) { + return + } + } + } +} + +func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error { + files, err := os.ReadDir(path) + if err != nil { + return err + } + + // Handle all children of the directory. + for _, entry := range files { + finfo, err := entry.Info() + if err != nil { + return err + } + err = handler(filepath.Join(path, finfo.Name()), finfo, false) + if err != nil { + return err + } + } + + // And finally handle the directory itself. + return handler(path, stat, follow) +} + +// handleEvent might need to emit more than one fsnotify event if the events +// bitmap matches more than one event type (e.g. the file was both modified and +// had the attributes changed between when the association was created and the +// when event was returned) +func (w *fen) handleEvent(event *unix.PortEvent) error { + var ( + events = event.Events + path = event.Path + fmode = event.Cookie.(os.FileMode) + reRegister = true + ) + + w.mu.Lock() + _, watchedDir := w.dirs[path] + _, watchedPath := w.watches[path] + w.mu.Unlock() + isWatched := watchedDir || watchedPath + + if events&unix.FILE_DELETE != 0 { + if !w.sendEvent(path, Remove) { + return nil + } + reRegister = false + } + if events&unix.FILE_RENAME_FROM != 0 { + if !w.sendEvent(path, Rename) { + return nil + } + // Don't keep watching the new file name + reRegister = false + } + if events&unix.FILE_RENAME_TO != 0 { + // We don't report a Rename event for this case, because Rename events + // are interpreted as referring to the _old_ name of the file, and in + // this case the event would refer to the new name of the file. This + // type of rename event is not supported by fsnotify. + + // inotify reports a Remove event in this case, so we simulate this + // here. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't keep watching the file that was removed + reRegister = false + } + + // The file is gone, nothing left to do. + if !reRegister { + if watchedDir { + w.mu.Lock() + delete(w.dirs, path) + w.mu.Unlock() + } + if watchedPath { + w.mu.Lock() + delete(w.watches, path) + w.mu.Unlock() + } + return nil + } + + // If we didn't get a deletion the file still exists and we're going to have + // to watch it again. Let's Stat it now so that we can compare permissions + // and have what we need to continue watching the file + + stat, err := os.Lstat(path) + if err != nil { + // This is unexpected, but we should still emit an event. This happens + // most often on "rm -r" of a subdirectory inside a watched directory We + // get a modify event of something happening inside, but by the time we + // get here, the sudirectory is already gone. Clearly we were watching + // this path but now it is gone. Let's tell the user that it was + // removed. + if !w.sendEvent(path, Remove) { + return nil + } + // Suppress extra write events on removed directories; they are not + // informative and can be confusing. + return nil + } + + // resolve symlinks that were explicitly watched as we would have at Add() + // time. this helps suppress spurious Chmod events on watched symlinks + if isWatched { + stat, err = os.Stat(path) + if err != nil { + // The symlink still exists, but the target is gone. Report the + // Remove similar to above. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't return the error + } + } + + if events&unix.FILE_MODIFIED != 0 { + if fmode.IsDir() && watchedDir { + if err := w.updateDirectory(path); err != nil { + return err + } + } else { + if !w.sendEvent(path, Write) { + return nil + } + } + } + if events&unix.FILE_ATTRIB != 0 && stat != nil { + // Only send Chmod if perms changed + if stat.Mode().Perm() != fmode.Perm() { + if !w.sendEvent(path, Chmod) { + return nil + } + } + } + + if stat != nil { + // If we get here, it means we've hit an event above that requires us to + // continue watching the file or directory + return w.associateFile(path, stat, isWatched) + } + return nil +} + +func (w *fen) updateDirectory(path string) error { + // The directory was modified, so we must find unwatched entities and watch + // them. If something was removed from the directory, nothing will happen, + // as everything else should still be watched. + files, err := os.ReadDir(path) + if err != nil { + return err + } + + for _, entry := range files { + path := filepath.Join(path, entry.Name()) + if w.port.PathIsWatched(path) { + continue + } + + finfo, err := entry.Info() + if err != nil { + return err + } + err = w.associateFile(path, finfo, false) + if !w.sendError(err) { + return nil + } + if !w.sendEvent(path, Create) { + return nil + } + } return nil } + +func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error { + if w.isClosed() { + return ErrClosed + } + // This is primarily protecting the call to AssociatePath but it is + // important and intentional that the call to PathIsWatched is also + // protected by this mutex. Without this mutex, AssociatePath has been seen + // to error out that the path is already associated. + w.mu.Lock() + defer w.mu.Unlock() + + if w.port.PathIsWatched(path) { + // Remove the old association in favor of this one If we get ENOENT, + // then while the x/sys/unix wrapper still thought that this path was + // associated, the underlying event port did not. This call will have + // cleared up that discrepancy. The most likely cause is that the event + // has fired but we haven't processed it yet. + err := w.port.DissociatePath(path) + if err != nil && !errors.Is(err, unix.ENOENT) { + return err + } + } + + var events int + if !follow { + // Watch symlinks themselves rather than their targets unless this entry + // is explicitly watched. + events |= unix.FILE_NOFOLLOW + } + if true { // TODO: implement withOps() + events |= unix.FILE_MODIFIED + } + if true { + events |= unix.FILE_ATTRIB + } + return w.port.AssociatePath(path, stat, events, stat.Mode()) +} + +func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error { + if !w.port.PathIsWatched(path) { + return nil + } + return w.port.DissociatePath(path) +} + +func (w *fen) WatchList() []string { + if w.isClosed() { + return nil + } + + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)+len(w.dirs)) + for pathname := range w.dirs { + entries = append(entries, pathname) + } + for pathname := range w.watches { + entries = append(entries, pathname) + } + + return entries +} + +func (w *fen) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_inotify.go index 54c77fbb..36c31169 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_inotify.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -1,5 +1,4 @@ -//go:build linux -// +build linux +//go:build linux && !appengine package fsnotify @@ -7,142 +6,188 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "strings" "sync" + "time" "unsafe" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # macOS notes -// -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). -// -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. +type inotify struct { Events chan Event - - // Errors sends any errors. Errors chan error // Store fd here as os.File.Read() will no longer return on close after // calling Fd(). See: https://github.com/golang/go/issues/26439 fd int - mu sync.Mutex // Map access inotifyFile *os.File - watches map[string]*watch // Map of inotify watches (key: path) - paths map[int]string // Map of watched paths (key: watch descriptor) - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - doneResp chan struct{} // Channel to respond to Close + watches *watches + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneMu sync.Mutex + doneResp chan struct{} // Channel to respond to Close + + // Store rename cookies in an array, with the index wrapping to 0. Almost + // all of the time what we get is a MOVED_FROM to set the cookie and the + // next event inotify sends will be MOVED_TO to read it. However, this is + // not guaranteed – as described in inotify(7) – and we may get other events + // between the two MOVED_* events (including other MOVED_* ones). + // + // A second issue is that moving a file outside the watched directory will + // trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to + // read and delete it. So just storing it in a map would slowly leak memory. + // + // Doing it like this gives us a simple fast LRU-cache that won't allocate. + // Ten items should be more than enough for our purpose, and a loop over + // such a short array is faster than a map access anyway (not that it hugely + // matters since we're talking about hundreds of ns at the most, but still). + cookies [10]koekje + cookieIndex uint8 + cookiesMu sync.Mutex } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - // Create inotify fd - // Need to set the FD to nonblocking mode in order for SetDeadline methods to work - // Otherwise, blocking i/o operations won't terminate on close +type ( + watches struct { + mu sync.RWMutex + wd map[uint32]*watch // wd → watch + path map[string]uint32 // pathname → wd + } + watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) + path string // Watch path. + recurse bool // Recursion with ./...? + } + koekje struct { + cookie uint32 + path string + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[uint32]*watch), + path: make(map[string]uint32), + } +} + +func (w *watches) len() int { + w.mu.RLock() + defer w.mu.RUnlock() + return len(w.wd) +} + +func (w *watches) add(ww *watch) { + w.mu.Lock() + defer w.mu.Unlock() + w.wd[ww.wd] = ww + w.path[ww.path] = ww.wd +} + +func (w *watches) remove(wd uint32) { + w.mu.Lock() + defer w.mu.Unlock() + watch := w.wd[wd] // Could have had Remove() called. See #616. + if watch == nil { + return + } + delete(w.path, watch.path) + delete(w.wd, wd) +} + +func (w *watches) removePath(path string) ([]uint32, error) { + w.mu.Lock() + defer w.mu.Unlock() + + path, recurse := recursivePath(path) + wd, ok := w.path[path] + if !ok { + return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path) + } + + watch := w.wd[wd] + if recurse && !watch.recurse { + return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path) + } + + delete(w.path, path) + delete(w.wd, wd) + if !watch.recurse { + return []uint32{wd}, nil + } + + wds := make([]uint32, 0, 8) + wds = append(wds, wd) + for p, rwd := range w.path { + if filepath.HasPrefix(p, path) { + delete(w.path, p) + delete(w.wd, rwd) + wds = append(wds, rwd) + } + } + return wds, nil +} + +func (w *watches) byPath(path string) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[w.path[path]] +} + +func (w *watches) byWd(wd uint32) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[wd] +} + +func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error { + w.mu.Lock() + defer w.mu.Unlock() + + var existing *watch + wd, ok := w.path[path] + if ok { + existing = w.wd[wd] + } + + upd, err := f(existing) + if err != nil { + return err + } + if upd != nil { + w.wd[upd.wd] = upd + w.path[upd.path] = upd.wd + + if upd.wd != wd { + delete(w.wd, wd) + } + } + + return nil +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + // Need to set nonblocking mode for SetDeadline to work, otherwise blocking + // I/O operations won't terminate on close. fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) if fd == -1 { return nil, errno } - w := &Watcher{ + w := &inotify{ + Events: ev, + Errors: errs, fd: fd, inotifyFile: os.NewFile(uintptr(fd), ""), - watches: make(map[string]*watch), - paths: make(map[int]string), - Events: make(chan Event), - Errors: make(chan error), + watches: newWatches(), done: make(chan struct{}), doneResp: make(chan struct{}), } @@ -152,26 +197,29 @@ func NewWatcher() (*Watcher, error) { } // Returns true if the event was sent, or false if watcher is closed. -func (w *Watcher) sendEvent(e Event) bool { +func (w *inotify) sendEvent(e Event) bool { select { + case <-w.done: + return false case w.Events <- e: return true - case <-w.done: } - return false } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { - select { - case w.Errors <- err: +func (w *inotify) sendError(err error) bool { + if err == nil { return true + } + select { case <-w.done: return false + case w.Errors <- err: + return true } } -func (w *Watcher) isClosed() bool { +func (w *inotify) isClosed() bool { select { case <-w.done: return true @@ -180,17 +228,14 @@ func (w *Watcher) isClosed() bool { } } -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() +func (w *inotify) Close() error { + w.doneMu.Lock() if w.isClosed() { - w.mu.Unlock() + w.doneMu.Unlock() return nil } - - // Send 'close' signal to goroutine, and set the Watcher to closed. close(w.done) - w.mu.Unlock() + w.doneMu.Unlock() // Causes any blocking reads to return with an error, provided the file // still supports deadline operations. @@ -205,138 +250,168 @@ func (w *Watcher) Close() error { return nil } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. -// -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - name = filepath.Clean(name) +func (w *inotify) Add(name string) error { return w.AddWith(name) } + +func (w *inotify) AddWith(path string, opts ...addOpt) error { if w.isClosed() { - return errors.New("inotify instance already closed") + return ErrClosed } - - var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | - unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | - unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF - - w.mu.Lock() - defer w.mu.Unlock() - watchEntry := w.watches[name] - if watchEntry != nil { - flags |= watchEntry.flags | unix.IN_MASK_ADD + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), path) } - wd, errno := unix.InotifyAddWatch(w.fd, name, flags) - if wd == -1 { - return errno + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) } - if watchEntry == nil { - w.watches[name] = &watch{wd: uint32(wd), flags: flags} - w.paths[wd] = name - } else { - watchEntry.wd = uint32(wd) - watchEntry.flags = flags + path, recurse := recursivePath(path) + if recurse { + return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + if root == path { + return fmt.Errorf("fsnotify: not a directory: %q", path) + } + return nil + } + + // Send a Create event when adding new directory from a recursive + // watch; this is for "mkdir -p one/two/three". Usually all those + // directories will be created before we can set up watchers on the + // subdirectories, so only "one" would be sent as a Create event and + // not "one/two" and "one/two/three" (inotifywait -r has the same + // problem). + if with.sendCreate && root != path { + w.sendEvent(Event{Name: root, Op: Create}) + } + + return w.add(root, with, true) + }) } - return nil + return w.add(path, with, false) } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) +func (w *inotify) add(path string, with withOpts, recurse bool) error { + var flags uint32 + if with.noFollow { + flags |= unix.IN_DONT_FOLLOW + } + if with.op.Has(Create) { + flags |= unix.IN_CREATE + } + if with.op.Has(Write) { + flags |= unix.IN_MODIFY + } + if with.op.Has(Remove) { + flags |= unix.IN_DELETE | unix.IN_DELETE_SELF + } + if with.op.Has(Rename) { + flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF + } + if with.op.Has(Chmod) { + flags |= unix.IN_ATTRIB + } + if with.op.Has(xUnportableOpen) { + flags |= unix.IN_OPEN + } + if with.op.Has(xUnportableRead) { + flags |= unix.IN_ACCESS + } + if with.op.Has(xUnportableCloseWrite) { + flags |= unix.IN_CLOSE_WRITE + } + if with.op.Has(xUnportableCloseRead) { + flags |= unix.IN_CLOSE_NOWRITE + } + return w.register(path, flags, recurse) +} - // Fetch the watch. - w.mu.Lock() - defer w.mu.Unlock() - watch, ok := w.watches[name] +func (w *inotify) register(path string, flags uint32, recurse bool) error { + return w.watches.updatePath(path, func(existing *watch) (*watch, error) { + if existing != nil { + flags |= existing.flags | unix.IN_MASK_ADD + } - // Remove it from inotify. - if !ok { - return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) - } - - // We successfully removed the watch if InotifyRmWatch doesn't return an - // error, we need to clean up our internal state to ensure it matches - // inotify's kernel state. - delete(w.paths, int(watch.wd)) - delete(w.watches, name) - - // inotify_rm_watch will return EINVAL if the file has been deleted; - // the inotify will already have been removed. - // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously - // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE - // so that EINVAL means that the wd is being rm_watch()ed or its file removed - // by another thread and we have not received IN_IGNORE event. - success, errno := unix.InotifyRmWatch(w.fd, watch.wd) - if success == -1 { - // TODO: Perhaps it's not helpful to return an error here in every case; - // The only two possible errors are: - // - // - EBADF, which happens when w.fd is not a valid file descriptor - // of any kind. - // - EINVAL, which is when fd is not an inotify descriptor or wd - // is not a valid watch descriptor. Watch descriptors are - // invalidated when they are removed explicitly or implicitly; - // explicitly by inotify_rm_watch, implicitly when the file they - // are watching is deleted. - return errno + wd, err := unix.InotifyAddWatch(w.fd, path, flags) + if wd == -1 { + return nil, err + } + + if existing == nil { + return &watch{ + wd: uint32(wd), + path: path, + flags: flags, + recurse: recurse, + }, nil + } + + existing.wd = uint32(wd) + existing.flags = flags + return existing, nil + }) +} + +func (w *inotify) Remove(name string) error { + if w.isClosed() { + return nil + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + return w.remove(filepath.Clean(name)) +} + +func (w *inotify) remove(name string) error { + wds, err := w.watches.removePath(name) + if err != nil { + return err } + for _, wd := range wds { + _, err := unix.InotifyRmWatch(w.fd, wd) + if err != nil { + // TODO: Perhaps it's not helpful to return an error here in every + // case; the only two possible errors are: + // + // EBADF, which happens when w.fd is not a valid file descriptor of + // any kind. + // + // EINVAL, which is when fd is not an inotify descriptor or wd is + // not a valid watch descriptor. Watch descriptors are invalidated + // when they are removed explicitly or implicitly; explicitly by + // inotify_rm_watch, implicitly when the file they are watching is + // deleted. + return err + } + } return nil } -// WatchList returns all paths added with [Add] (and are not yet removed). -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() +func (w *inotify) WatchList() []string { + if w.isClosed() { + return nil + } - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { + entries := make([]string, 0, w.watches.len()) + w.watches.mu.RLock() + for pathname := range w.watches.path { entries = append(entries, pathname) } + w.watches.mu.RUnlock() return entries } -type watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) -} - // readEvents reads from the inotify file descriptor, converts the // received events into Event objects and sends them via the Events channel -func (w *Watcher) readEvents() { +func (w *inotify) readEvents() { defer func() { close(w.doneResp) close(w.Errors) @@ -367,14 +442,11 @@ func (w *Watcher) readEvents() { if n < unix.SizeofInotifyEvent { var err error if n == 0 { - // If EOF is received. This should really never happen. - err = io.EOF + err = io.EOF // If EOF is received. This should really never happen. } else if n < 0 { - // If an error occurred while reading. - err = errno + err = errno // If an error occurred while reading. } else { - // Read was too short. - err = errors.New("notify: short read in readEvents()") + err = errors.New("notify: short read in readEvents()") // Read was too short. } if !w.sendError(err) { return @@ -382,15 +454,17 @@ func (w *Watcher) readEvents() { continue } - var offset uint32 // We don't know how many events we just read into the buffer // While the offset points to at least one whole event... + var offset uint32 for offset <= uint32(n-unix.SizeofInotifyEvent) { var ( // Point "raw" to the event in the buffer raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) mask = uint32(raw.Mask) nameLen = uint32(raw.Len) + // Move to the next event in the buffer + next = func() { offset += unix.SizeofInotifyEvent + nameLen } ) if mask&unix.IN_Q_OVERFLOW != 0 { @@ -399,46 +473,124 @@ func (w *Watcher) readEvents() { } } - // If the event happened to the watched directory or the watched file, the kernel - // doesn't append the filename to the event, but we would like to always fill the - // the "Name" field with a valid filename. We retrieve the path of the watch from - // the "paths" map. - w.mu.Lock() - name, ok := w.paths[int(raw.Wd)] - // IN_DELETE_SELF occurs when the file/directory being watched is removed. - // This is a sign to clean up the maps, otherwise we are no longer in sync - // with the inotify kernel state which has already deleted the watch - // automatically. - if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { - delete(w.paths, int(raw.Wd)) - delete(w.watches, name) + /// If the event happened to the watched directory or the watched + /// file, the kernel doesn't append the filename to the event, but + /// we would like to always fill the the "Name" field with a valid + /// filename. We retrieve the path of the watch from the "paths" + /// map. + watch := w.watches.byWd(uint32(raw.Wd)) + /// Can be nil if Remove() was called in another goroutine for this + /// path inbetween reading the events from the kernel and reading + /// the internal state. Not much we can do about it, so just skip. + /// See #616. + if watch == nil { + next() + continue } - w.mu.Unlock() + name := watch.path if nameLen > 0 { - // Point "bytes" at the first byte of the filename + /// Point "bytes" at the first byte of the filename bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] - // The filename is padded with NULL bytes. TrimRight() gets rid of those. + /// The filename is padded with NULL bytes. TrimRight() gets rid of those. name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") } - event := w.newEvent(name, mask) + if debug { + internal.Debug(name, raw.Mask, raw.Cookie) + } - // Send the events that are not ignored on the events channel - if mask&unix.IN_IGNORED == 0 { - if !w.sendEvent(event) { - return + if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0 + next() + continue + } + + // inotify will automatically remove the watch on deletes; just need + // to clean our state here. + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + w.watches.remove(watch.wd) + } + + // We can't really update the state when a watched path is moved; + // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove + // the watch. + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF { + if watch.recurse { + next() // Do nothing + continue + } + + err := w.remove(watch.path) + if err != nil && !errors.Is(err, ErrNonExistentWatch) { + if !w.sendError(err) { + return + } + } + } + + /// Skip if we're watching both this path and the parent; the parent + /// will already send a delete so no need to do it twice. + if mask&unix.IN_DELETE_SELF != 0 { + if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok { + next() + continue + } + } + + ev := w.newEvent(name, mask, raw.Cookie) + // Need to update watch path for recurse. + if watch.recurse { + isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR + /// New directory created: set up watch on it. + if isDir && ev.Has(Create) { + err := w.register(ev.Name, watch.flags, true) + if !w.sendError(err) { + return + } + + // This was a directory rename, so we need to update all + // the children. + // + // TODO: this is of course pretty slow; we should use a + // better data structure for storing all of this, e.g. store + // children in the watch. I have some code for this in my + // kqueue refactor we can use in the future. For now I'm + // okay with this as it's not publicly available. + // Correctness first, performance second. + if ev.renamedFrom != "" { + w.watches.mu.Lock() + for k, ww := range w.watches.wd { + if k == watch.wd || ww.path == ev.Name { + continue + } + if strings.HasPrefix(ww.path, ev.renamedFrom) { + ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1) + w.watches.wd[k] = ww + } + } + w.watches.mu.Unlock() + } } } - // Move to the next event in the buffer - offset += unix.SizeofInotifyEvent + nameLen + /// Send the events that are not ignored on the events channel + if !w.sendEvent(ev) { + return + } + next() } } } -// newEvent returns an platform-independent Event based on an inotify mask. -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *inotify) isRecursive(path string) bool { + ww := w.watches.byPath(path) + if ww == nil { // path could be a file, so also check the Dir. + ww = w.watches.byPath(filepath.Dir(path)) + } + return ww != nil && ww.recurse +} + +func (w *inotify) newEvent(name string, mask, cookie uint32) Event { e := Event{Name: name} if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { e.Op |= Create @@ -449,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&unix.IN_MODIFY == unix.IN_MODIFY { e.Op |= Write } + if mask&unix.IN_OPEN == unix.IN_OPEN { + e.Op |= xUnportableOpen + } + if mask&unix.IN_ACCESS == unix.IN_ACCESS { + e.Op |= xUnportableRead + } + if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE { + e.Op |= xUnportableCloseWrite + } + if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE { + e.Op |= xUnportableCloseRead + } if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { e.Op |= Rename } if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { e.Op |= Chmod } + + if cookie != 0 { + if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + w.cookiesMu.Lock() + w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name} + w.cookieIndex++ + if w.cookieIndex > 9 { + w.cookieIndex = 0 + } + w.cookiesMu.Unlock() + } else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + w.cookiesMu.Lock() + var prev string + for _, c := range w.cookies { + if c.cookie == cookie { + prev = c.path + break + } + } + w.cookiesMu.Unlock() + e.renamedFrom = prev + } + } return e } + +func (w *inotify) xSupports(op Op) bool { + return true // Supports everything. +} + +func (w *inotify) state() { + w.watches.mu.Lock() + defer w.watches.mu.Unlock() + for wd, ww := range w.watches.wd { + fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path) + } +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go index 29087469..d8de5ab7 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go @@ -1,155 +1,201 @@ //go:build freebsd || openbsd || netbsd || dragonfly || darwin -// +build freebsd openbsd netbsd dragonfly darwin package fsnotify import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" + "runtime" "sync" + "time" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/unix" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # macOS notes -// -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). -// -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. +type kqueue struct { Events chan Event - - // Errors sends any errors. Errors chan error - done chan struct{} - kq int // File descriptor (as returned by the kqueue() syscall). - closepipe [2]int // Pipe used for closing. - mu sync.Mutex // Protects access to watcher data - watches map[string]int // Watched file descriptors (key: path). - watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)). - userWatches map[string]struct{} // Watches added with Watcher.Add() - dirFlags map[string]uint32 // Watched directories to fflags used in kqueue. - paths map[int]pathInfo // File descriptors to path names for processing kqueue events. - fileExists map[string]struct{} // Keep track of if we know this file exists (to stop duplicate create events). - isClosed bool // Set to true when Close() is first called + kq int // File descriptor (as returned by the kqueue() syscall). + closepipe [2]int // Pipe used for closing kq. + watches *watches + done chan struct{} + doneMu sync.Mutex } -type pathInfo struct { - name string - isDir bool +type ( + watches struct { + mu sync.RWMutex + wd map[int]watch // wd → watch + path map[string]int // pathname → wd + byDir map[string]map[int]struct{} // dirname(path) → wd + seen map[string]struct{} // Keep track of if we know this file exists. + byUser map[string]struct{} // Watches added with Watcher.Add() + } + watch struct { + wd int + name string + linkName string // In case of links; name is the target, and this is the link. + isDir bool + dirFlags uint32 + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[int]watch), + path: make(map[string]int), + byDir: make(map[string]map[int]struct{}), + seen: make(map[string]struct{}), + byUser: make(map[string]struct{}), + } } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { +func (w *watches) listPaths(userOnly bool) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + if userOnly { + l := make([]string, 0, len(w.byUser)) + for p := range w.byUser { + l = append(l, p) + } + return l + } + + l := make([]string, 0, len(w.path)) + for p := range w.path { + l = append(l, p) + } + return l +} + +func (w *watches) watchesInDir(path string) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + l := make([]string, 0, 4) + for fd := range w.byDir[path] { + info := w.wd[fd] + if _, ok := w.byUser[info.name]; !ok { + l = append(l, info.name) + } + } + return l +} + +// Mark path as added by the user. +func (w *watches) addUserWatch(path string) { + w.mu.Lock() + defer w.mu.Unlock() + w.byUser[path] = struct{}{} +} + +func (w *watches) addLink(path string, fd int) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.seen[path] = struct{}{} +} + +func (w *watches) add(path, linkPath string, fd int, isDir bool) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir} + + parent := filepath.Dir(path) + byDir, ok := w.byDir[parent] + if !ok { + byDir = make(map[int]struct{}, 1) + w.byDir[parent] = byDir + } + byDir[fd] = struct{}{} +} + +func (w *watches) byWd(fd int) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[fd] + return info, ok +} + +func (w *watches) byPath(path string) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[w.path[path]] + return info, ok +} + +func (w *watches) updateDirFlags(path string, flags uint32) { + w.mu.Lock() + defer w.mu.Unlock() + + fd := w.path[path] + info := w.wd[fd] + info.dirFlags = flags + w.wd[fd] = info +} + +func (w *watches) remove(fd int, path string) bool { + w.mu.Lock() + defer w.mu.Unlock() + + isDir := w.wd[fd].isDir + delete(w.path, path) + delete(w.byUser, path) + + parent := filepath.Dir(path) + delete(w.byDir[parent], fd) + + if len(w.byDir[parent]) == 0 { + delete(w.byDir, parent) + } + + delete(w.wd, fd) + delete(w.seen, path) + return isDir +} + +func (w *watches) markSeen(path string, exists bool) { + w.mu.Lock() + defer w.mu.Unlock() + if exists { + w.seen[path] = struct{}{} + } else { + delete(w.seen, path) + } +} + +func (w *watches) seenBefore(path string) bool { + w.mu.RLock() + defer w.mu.RUnlock() + _, ok := w.seen[path] + return ok +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { kq, closepipe, err := newKqueue() if err != nil { return nil, err } - w := &Watcher{ - kq: kq, - closepipe: closepipe, - watches: make(map[string]int), - watchesByDir: make(map[string]map[int]struct{}), - dirFlags: make(map[string]uint32), - paths: make(map[int]pathInfo), - fileExists: make(map[string]struct{}), - userWatches: make(map[string]struct{}), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), + w := &kqueue{ + Events: ev, + Errors: errs, + kq: kq, + closepipe: closepipe, + done: make(chan struct{}), + watches: newWatches(), } go w.readEvents() @@ -174,6 +220,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) { unix.Close(kq) return kq, closepipe, err } + unix.CloseOnExec(closepipe[0]) + unix.CloseOnExec(closepipe[1]) // Register changes to listen on the closepipe. changes := make([]unix.Kevent_t, 1) @@ -192,218 +240,172 @@ func newKqueue() (kq int, closepipe [2]int, err error) { } // Returns true if the event was sent, or false if watcher is closed. -func (w *Watcher) sendEvent(e Event) bool { +func (w *kqueue) sendEvent(e Event) bool { select { + case <-w.done: + return false case w.Events <- e: return true - case <-w.done: } - return false } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { +func (w *kqueue) sendError(err error) bool { + if err == nil { + return true + } select { + case <-w.done: + return false case w.Errors <- err: return true + } +} + +func (w *kqueue) isClosed() bool { + select { case <-w.done: + return true + default: + return false } - return false } -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() +func (w *kqueue) Close() error { + w.doneMu.Lock() + if w.isClosed() { + w.doneMu.Unlock() return nil } - w.isClosed = true + close(w.done) + w.doneMu.Unlock() - // copy paths to remove while locked - pathsToRemove := make([]string, 0, len(w.watches)) - for name := range w.watches { - pathsToRemove = append(pathsToRemove, name) - } - w.mu.Unlock() // Unlock before calling Remove, which also locks + pathsToRemove := w.watches.listPaths(false) for _, name := range pathsToRemove { w.Remove(name) } // Send "quit" message to the reader goroutine. unix.Close(w.closepipe[1]) - close(w.done) - return nil } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. -// -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - w.mu.Lock() - w.userWatches[name] = struct{}{} - w.mu.Unlock() +func (w *kqueue) Add(name string) error { return w.AddWith(name) } + +func (w *kqueue) AddWith(name string, opts ...addOpt) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + _, err := w.addWatch(name, noteAllEvents) - return err + if err != nil { + return err + } + w.watches.addUserWatch(name) + return nil } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { +func (w *kqueue) Remove(name string) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + return w.remove(name, true) +} + +func (w *kqueue) remove(name string, unwatchFiles bool) error { + if w.isClosed() { + return nil + } + name = filepath.Clean(name) - w.mu.Lock() - watchfd, ok := w.watches[name] - w.mu.Unlock() + info, ok := w.watches.byPath(name) if !ok { return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) } - err := w.register([]int{watchfd}, unix.EV_DELETE, 0) + err := w.register([]int{info.wd}, unix.EV_DELETE, 0) if err != nil { return err } - unix.Close(watchfd) - - w.mu.Lock() - isDir := w.paths[watchfd].isDir - delete(w.watches, name) - delete(w.userWatches, name) - - parentName := filepath.Dir(name) - delete(w.watchesByDir[parentName], watchfd) - - if len(w.watchesByDir[parentName]) == 0 { - delete(w.watchesByDir, parentName) - } + unix.Close(info.wd) - delete(w.paths, watchfd) - delete(w.dirFlags, name) - delete(w.fileExists, name) - w.mu.Unlock() + isDir := w.watches.remove(info.wd, name) // Find all watched paths that are in this directory that are not external. - if isDir { - var pathsToRemove []string - w.mu.Lock() - for fd := range w.watchesByDir[name] { - path := w.paths[fd] - if _, ok := w.userWatches[path.name]; !ok { - pathsToRemove = append(pathsToRemove, path.name) - } - } - w.mu.Unlock() + if unwatchFiles && isDir { + pathsToRemove := w.watches.watchesInDir(name) for _, name := range pathsToRemove { - // Since these are internal, not much sense in propagating error - // to the user, as that will just confuse them with an error about - // a path they did not explicitly watch themselves. + // Since these are internal, not much sense in propagating error to + // the user, as that will just confuse them with an error about a + // path they did not explicitly watch themselves. w.Remove(name) } } - return nil } -// WatchList returns all paths added with [Add] (and are not yet removed). -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.userWatches)) - for pathname := range w.userWatches { - entries = append(entries, pathname) +func (w *kqueue) WatchList() []string { + if w.isClosed() { + return nil } - - return entries + return w.watches.listPaths(true) } // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME -// addWatch adds name to the watched file set. -// The flags are interpreted as described in kevent(2). -// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. -func (w *Watcher) addWatch(name string, flags uint32) (string, error) { - var isDir bool - // Make ./name and name equivalent - name = filepath.Clean(name) - - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return "", errors.New("kevent instance already closed") - } - watchfd, alreadyWatching := w.watches[name] - // We already have a watch, but we can still override flags. - if alreadyWatching { - isDir = w.paths[watchfd].isDir +// addWatch adds name to the watched file set; the flags are interpreted as +// described in kevent(2). +// +// Returns the real path to the file which was added, with symlinks resolved. +func (w *kqueue) addWatch(name string, flags uint32) (string, error) { + if w.isClosed() { + return "", ErrClosed } - w.mu.Unlock() + name = filepath.Clean(name) + + info, alreadyWatching := w.watches.byPath(name) if !alreadyWatching { fi, err := os.Lstat(name) if err != nil { return "", err } - // Don't watch sockets or named pipes + // Don't watch sockets or named pipes. if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) { return "", nil } - // Follow Symlinks - // - // Linux can add unresolvable symlinks to the watch list without issue, - // and Windows can't do symlinks period. To maintain consistency, we - // will act like everything is fine if the link can't be resolved. - // There will simply be no file events for broken symlinks. Hence the - // returns of nil on errors. + // Follow symlinks. if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - name, err = filepath.EvalSymlinks(name) + link, err := os.Readlink(name) if err != nil { + // Return nil because Linux can add unresolvable symlinks to the + // watch list without problems, so maintain consistency with + // that. There will be no file events for broken symlinks. + // TODO: more specific check; returns os.PathError; ENOENT? return "", nil } - w.mu.Lock() - _, alreadyWatching = w.watches[name] - w.mu.Unlock() - + _, alreadyWatching = w.watches.byPath(link) if alreadyWatching { - return name, nil + // Add to watches so we don't get spurious Create events later + // on when we diff the directories. + w.watches.addLink(name, 0) + return link, nil } + info.linkName = name + name = link fi, err = os.Lstat(name) if err != nil { return "", nil @@ -411,9 +413,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { } // Retry on EINTR; open() can return EINTR in practice on macOS. - // See #354, and go issues 11180 and 39237. + // See #354, and Go issues 11180 and 39237. for { - watchfd, err = unix.Open(name, openMode, 0) + info.wd, err = unix.Open(name, openMode, 0) if err == nil { break } @@ -424,41 +426,25 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { return "", err } - isDir = fi.IsDir() + info.isDir = fi.IsDir() } - err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) + err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) if err != nil { - unix.Close(watchfd) + unix.Close(info.wd) return "", err } if !alreadyWatching { - w.mu.Lock() - parentName := filepath.Dir(name) - w.watches[name] = watchfd - - watchesByDir, ok := w.watchesByDir[parentName] - if !ok { - watchesByDir = make(map[int]struct{}, 1) - w.watchesByDir[parentName] = watchesByDir - } - watchesByDir[watchfd] = struct{}{} - - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} - w.mu.Unlock() + w.watches.add(name, info.linkName, info.wd, info.isDir) } - if isDir { - // Watch the directory if it has not been watched before, - // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) - w.mu.Lock() - + // Watch the directory if it has not been watched before, or if it was + // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + if info.isDir { watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && - (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) - // Store flags so this watch can be updated later - w.dirFlags[name] = flags - w.mu.Unlock() + (!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE) + w.watches.updateDirFlags(name, flags) if watchDir { if err := w.watchDirectoryFiles(name); err != nil { @@ -471,95 +457,110 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { // readEvents reads from kqueue and converts the received kevents into // Event values that it sends down the Events channel. -func (w *Watcher) readEvents() { +func (w *kqueue) readEvents() { defer func() { - err := unix.Close(w.kq) - if err != nil { - w.Errors <- err - } - unix.Close(w.closepipe[0]) close(w.Events) close(w.Errors) + _ = unix.Close(w.kq) + unix.Close(w.closepipe[0]) }() eventBuffer := make([]unix.Kevent_t, 10) - for closed := false; !closed; { + for { kevents, err := w.read(eventBuffer) // EINTR is okay, the syscall was interrupted before timeout expired. if err != nil && err != unix.EINTR { if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) { - closed = true + return } - continue } - // Flush the events we received to the Events channel for _, kevent := range kevents { var ( - watchfd = int(kevent.Ident) - mask = uint32(kevent.Fflags) + wd = int(kevent.Ident) + mask = uint32(kevent.Fflags) ) // Shut down the loop when the pipe is closed, but only after all // other events have been processed. - if watchfd == w.closepipe[0] { - closed = true - continue + if wd == w.closepipe[0] { + return } - w.mu.Lock() - path := w.paths[watchfd] - w.mu.Unlock() - - event := w.newEvent(path.name, mask) + path, ok := w.watches.byWd(wd) + if debug { + internal.Debug(path.name, &kevent) + } - if path.isDir && !event.Has(Remove) { - // Double check to make sure the directory exists. This can - // happen when we do a rm -fr on a recursively watched folders - // and we receive a modification event first but the folder has - // been deleted and later receive the delete event. - if _, err := os.Lstat(event.Name); os.IsNotExist(err) { - event.Op |= Remove - } + // On macOS it seems that sometimes an event with Ident=0 is + // delivered, and no other flags/information beyond that, even + // though we never saw such a file descriptor. For example in + // TestWatchSymlink/277 (usually at the end, but sometimes sooner): + // + // fmt.Printf("READ: %2d %#v\n", kevent.Ident, kevent) + // unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // unix.Kevent_t{Ident:0x0, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // + // The first is a normal event, the second with Ident 0. No error + // flag, no data, no ... nothing. + // + // I read a bit through bsd/kern_event.c from the xnu source, but I + // don't really see an obvious location where this is triggered – + // this doesn't seem intentional, but idk... + // + // Technically fd 0 is a valid descriptor, so only skip it if + // there's no path, and if we're on macOS. + if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" { + continue } + event := w.newEvent(path.name, path.linkName, mask) + if event.Has(Rename) || event.Has(Remove) { - w.Remove(event.Name) - w.mu.Lock() - delete(w.fileExists, event.Name) - w.mu.Unlock() + w.remove(event.Name, false) + w.watches.markSeen(event.Name, false) } if path.isDir && event.Has(Write) && !event.Has(Remove) { - w.sendDirectoryChangeEvents(event.Name) - } else { - if !w.sendEvent(event) { - closed = true - continue - } + w.dirChange(event.Name) + } else if !w.sendEvent(event) { + return } if event.Has(Remove) { - // Look for a file that may have overwritten this. - // For example, mv f1 f2 will delete f2, then create f2. + // Look for a file that may have overwritten this; for example, + // mv f1 f2 will delete f2, then create f2. if path.isDir { fileDir := filepath.Clean(event.Name) - w.mu.Lock() - _, found := w.watches[fileDir] - w.mu.Unlock() + _, found := w.watches.byPath(fileDir) if found { - // make sure the directory exists before we watch for changes. When we - // do a recursive watch and perform rm -fr, the parent directory might - // have gone missing, ignore the missing directory and let the - // upcoming delete event remove the watch from the parent directory. - if _, err := os.Lstat(fileDir); err == nil { - w.sendDirectoryChangeEvents(fileDir) + // TODO: this branch is never triggered in any test. + // Added in d6220df (2012). + // isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111 + // + // I don't really get how this can be triggered either. + // And it wasn't triggered in the patch that added it, + // either. + // + // Original also had a comment: + // make sure the directory exists before we watch for + // changes. When we do a recursive watch and perform + // rm -rf, the parent directory might have gone + // missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the + // parent directory. + err := w.dirChange(fileDir) + if !w.sendError(err) { + return } } } else { - filePath := filepath.Clean(event.Name) - if fileInfo, err := os.Lstat(filePath); err == nil { - w.sendFileCreatedEventIfNew(filePath, fileInfo) + path := filepath.Clean(event.Name) + if fi, err := os.Lstat(path); err == nil { + err := w.sendCreateIfNew(path, fi) + if !w.sendError(err) { + return + } } } } @@ -568,8 +569,14 @@ func (w *Watcher) readEvents() { } // newEvent returns an platform-independent Event based on kqueue Fflags. -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *kqueue) newEvent(name, linkName string, mask uint32) Event { e := Event{Name: name} + if linkName != "" { + // If the user watched "/path/link" then emit events as "/path/link" + // rather than "/path/target". + e.Name = linkName + } + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { e.Op |= Remove } @@ -582,21 +589,30 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { e.Op |= Chmod } + // No point sending a write and delete event at the same time: if it's gone, + // then it's gone. + if e.Op.Has(Write) && e.Op.Has(Remove) { + e.Op &^= Write + } return e } // watchDirectoryFiles to mimic inotify when adding a watch on a directory -func (w *Watcher) watchDirectoryFiles(dirPath string) error { - // Get all files - files, err := ioutil.ReadDir(dirPath) +func (w *kqueue) watchDirectoryFiles(dirPath string) error { + files, err := os.ReadDir(dirPath) if err != nil { return err } - for _, fileInfo := range files { - path := filepath.Join(dirPath, fileInfo.Name()) + for _, f := range files { + path := filepath.Join(dirPath, f.Name()) - cleanPath, err := w.internalWatch(path, fileInfo) + fi, err := f.Info() + if err != nil { + return fmt.Errorf("%q: %w", path, err) + } + + cleanPath, err := w.internalWatch(path, fi) if err != nil { // No permission to read the file; that's not a problem: just skip. // But do add it to w.fileExists to prevent it from being picked up @@ -606,13 +622,11 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM): cleanPath = filepath.Clean(path) default: - return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err) + return fmt.Errorf("%q: %w", path, err) } } - w.mu.Lock() - w.fileExists[cleanPath] = struct{}{} - w.mu.Unlock() + w.watches.markSeen(cleanPath, true) } return nil @@ -622,58 +636,59 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { // // This functionality is to have the BSD watcher match the inotify, which sends // a create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dir string) { - // Get all files - files, err := ioutil.ReadDir(dir) +func (w *kqueue) dirChange(dir string) error { + files, err := os.ReadDir(dir) if err != nil { - if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) { - return + // Directory no longer exists: we can ignore this safely. kqueue will + // still give us the correct events. + if errors.Is(err, os.ErrNotExist) { + return nil } + return fmt.Errorf("fsnotify.dirChange: %w", err) } - // Search for new files - for _, fi := range files { - err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi) + for _, f := range files { + fi, err := f.Info() + if err != nil { + return fmt.Errorf("fsnotify.dirChange: %w", err) + } + + err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi) if err != nil { - return + // Don't need to send an error if this file isn't readable. + if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) { + return nil + } + return fmt.Errorf("fsnotify.dirChange: %w", err) } } + return nil } -// sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { - w.mu.Lock() - _, doesExist := w.fileExists[filePath] - w.mu.Unlock() - if !doesExist { - if !w.sendEvent(Event{Name: filePath, Op: Create}) { - return +// Send a create event if the file isn't already being tracked, and start +// watching this file. +func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error { + if !w.watches.seenBefore(path) { + if !w.sendEvent(Event{Name: path, Op: Create}) { + return nil } } - // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fileInfo) + // Like watchDirectoryFiles, but without doing another ReadDir. + path, err := w.internalWatch(path, fi) if err != nil { return err } - - w.mu.Lock() - w.fileExists[filePath] = struct{}{} - w.mu.Unlock() - + w.watches.markSeen(path, true) return nil } -func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { - if fileInfo.IsDir() { - // mimic Linux providing delete events for subdirectories - // but preserve the flags used if currently watching subdirectory - w.mu.Lock() - flags := w.dirFlags[name] - w.mu.Unlock() - - flags |= unix.NOTE_DELETE | unix.NOTE_RENAME - return w.addWatch(name, flags) +func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) { + if fi.IsDir() { + // mimic Linux providing delete events for subdirectories, but preserve + // the flags used if currently watching subdirectory + info, _ := w.watches.byPath(name) + return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME) } // watch file to mimic Linux inotify @@ -681,7 +696,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro } // Register events with the queue. -func (w *Watcher) register(fds []int, flags int, fflags uint32) error { +func (w *kqueue) register(fds []int, flags int, fflags uint32) error { changes := make([]unix.Kevent_t, len(fds)) for i, fd := range fds { // SetKevent converts int to the platform-specific types. @@ -698,10 +713,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error { } // read retrieves pending events, or waits until an event occurs. -func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { +func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { n, err := unix.Kevent(w.kq, nil, events, nil) if err != nil { return nil, err } return events[0:n], nil } + +func (w *kqueue) xSupports(op Op) bool { + if runtime.GOOS == "freebsd" { + //return true // Supports everything. + } + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_other.go b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_other.go index a9bb1c3c..5eb5dbc6 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_other.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_other.go @@ -1,66 +1,23 @@ -//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows +//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) package fsnotify -import ( - "fmt" - "runtime" -) +import "errors" -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct{} - -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { - return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil +type other struct { + Events chan Event + Errors chan error } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. -// -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - return nil +func newBackend(ev chan Event, errs chan error) (backend, error) { + return nil, errors.New("fsnotify not supported on the current platform") } - -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { - return nil +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + return newBackend(ev, errs) } +func (w *other) Close() error { return nil } +func (w *other) WatchList() []string { return nil } +func (w *other) Add(name string) error { return nil } +func (w *other) AddWith(name string, opts ...addOpt) error { return nil } +func (w *other) Remove(name string) error { return nil } +func (w *other) xSupports(op Op) bool { return false } diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_windows.go index ae392867..c54a6308 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/backend_windows.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -1,5 +1,8 @@ //go:build windows -// +build windows + +// Windows backend based on ReadDirectoryChangesW() +// +// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw package fsnotify @@ -12,143 +15,60 @@ import ( "runtime" "strings" "sync" + "time" "unsafe" + "github.com/fsnotify/fsnotify/internal" "golang.org/x/sys/windows" ) -// Watcher watches a set of paths, delivering events on a channel. -// -// A watcher should not be copied (e.g. pass it by pointer, rather than by -// value). -// -// # Linux notes -// -// When a file is removed a Remove event won't be emitted until all file -// descriptors are closed, and deletes will always emit a Chmod. For example: -// -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove -// -// This is the event that inotify sends, so not much can be changed about this. -// -// The fs.inotify.max_user_watches sysctl variable specifies the upper limit -// for the number of watches per user, and fs.inotify.max_user_instances -// specifies the maximum number of inotify instances per user. Every Watcher you -// create is an "instance", and every path you add is a "watch". -// -// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and -// /proc/sys/fs/inotify/max_user_instances -// -// To increase them you can use sysctl or write the value to the /proc file: -// -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 -// -// To make the changes persist on reboot edit /etc/sysctl.conf or -// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check -// your distro's documentation): -// -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 -// -// Reaching the limit will result in a "no space left on device" or "too many open -// files" error. -// -// # kqueue notes (macOS, BSD) -// -// kqueue requires opening a file descriptor for every file that's being watched; -// so if you're watching a directory with five files then that's six file -// descriptors. You will run in to your system's "max open files" limit faster on -// these platforms. -// -// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to -// control the maximum number of open files, as well as /etc/login.conf on BSD -// systems. -// -// # macOS notes -// -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). -// -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 -type Watcher struct { - // Events sends the filesystem change events. - // - // fsnotify can send the following events; a "path" here can refer to a - // file, directory, symbolic link, or special file like a FIFO. - // - // fsnotify.Create A new path was created; this may be followed by one - // or more Write events if data also gets written to a - // file. - // - // fsnotify.Remove A path was removed. - // - // fsnotify.Rename A path was renamed. A rename is always sent with the - // old path as Event.Name, and a Create event will be - // sent with the new name. Renames are only sent for - // paths that are currently watched; e.g. moving an - // unmonitored file into a monitored directory will - // show up as just a Create. Similarly, renaming a file - // to outside a monitored directory will show up as - // only a Rename. - // - // fsnotify.Write A file or named pipe was written to. A Truncate will - // also trigger a Write. A single "write action" - // initiated by the user may show up as one or multiple - // writes, depending on when the system syncs things to - // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). - // - // fsnotify.Chmod Attributes were changed. On Linux this is also sent - // when a file is removed (or more accurately, when a - // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. +type readDirChangesW struct { Events chan Event - - // Errors sends any errors. Errors chan error port windows.Handle // Handle to completion port input chan *input // Inputs to the reader are sent on this channel quit chan chan<- error - mu sync.Mutex // Protects access to watches, isClosed - watches watchMap // Map of watches (key: i-number) - isClosed bool // Set to true when Close() is first called + mu sync.Mutex // Protects access to watches, closed + watches watchMap // Map of watches (key: i-number) + closed bool // Set to true when Close() is first called } -// NewWatcher creates a new Watcher. -func NewWatcher() (*Watcher, error) { +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(50, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) if err != nil { return nil, os.NewSyscallError("CreateIoCompletionPort", err) } - w := &Watcher{ + w := &readDirChangesW{ + Events: ev, + Errors: errs, port: port, watches: make(watchMap), input: make(chan *input, 1), - Events: make(chan Event, 50), - Errors: make(chan error), quit: make(chan chan<- error, 1), } go w.readEvents() return w, nil } -func (w *Watcher) sendEvent(name string, mask uint64) bool { +func (w *readDirChangesW) isClosed() bool { + w.mu.Lock() + defer w.mu.Unlock() + return w.closed +} + +func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool { if mask == 0 { return false } event := w.newEvent(name, uint32(mask)) + event.renamedFrom = renamedFrom select { case ch := <-w.quit: w.quit <- ch @@ -158,23 +78,25 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool { } // Returns true if the error was sent, or false if watcher is closed. -func (w *Watcher) sendError(err error) bool { +func (w *readDirChangesW) sendError(err error) bool { + if err == nil { + return true + } select { case w.Errors <- err: return true case <-w.quit: + return false } - return false } -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() +func (w *readDirChangesW) Close() error { + if w.isClosed() { return nil } - w.isClosed = true + + w.mu.Lock() + w.closed = true w.mu.Unlock() // Send "quit" message to the reader goroutine @@ -186,49 +108,31 @@ func (w *Watcher) Close() error { return <-ch } -// Add starts monitoring the path for changes. -// -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. -// -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. -// -// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special -// filesystems (/proc, /sys, etc.) generally don't work. -// -// # Watching directories -// -// All files in a directory are monitored, including new files that are created -// after the watcher is started. Subdirectories are not watched (i.e. it's -// non-recursive). -// -// # Watching files -// -// Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return errors.New("watcher already closed") +func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) } + +func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + if with.bufsize < 4096 { + return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes") } - w.mu.Unlock() in := &input{ - op: opAddWatch, - path: filepath.Clean(name), - flags: sysFSALLEVENTS, - reply: make(chan error), + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + bufsize: with.bufsize, } w.input <- in if err := w.wakeupReader(); err != nil { @@ -237,13 +141,15 @@ func (w *Watcher) Add(name string) error { return <-in.reply } -// Remove stops monitoring the path for changes. -// -// Directories are always removed non-recursively. For example, if you added -// /tmp/dir and /tmp/dir/subdir then you will need to remove both. -// -// Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { +func (w *readDirChangesW) Remove(name string) error { + if w.isClosed() { + return nil + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } + in := &input{ op: opRemoveWatch, path: filepath.Clean(name), @@ -256,15 +162,24 @@ func (w *Watcher) Remove(name string) error { return <-in.reply } -// WatchList returns all paths added with [Add] (and are not yet removed). -func (w *Watcher) WatchList() []string { +func (w *readDirChangesW) WatchList() []string { + if w.isClosed() { + return nil + } + w.mu.Lock() defer w.mu.Unlock() entries := make([]string, 0, len(w.watches)) for _, entry := range w.watches { for _, watchEntry := range entry { - entries = append(entries, watchEntry.path) + for name := range watchEntry.names { + entries = append(entries, filepath.Join(watchEntry.path, name)) + } + // the directory itself is being watched + if watchEntry.mask != 0 { + entries = append(entries, watchEntry.path) + } } } @@ -279,7 +194,6 @@ func (w *Watcher) WatchList() []string { // This should all be removed at some point, and just use windows.FILE_NOTIFY_* const ( sysFSALLEVENTS = 0xfff - sysFSATTRIB = 0x4 sysFSCREATE = 0x100 sysFSDELETE = 0x200 sysFSDELETESELF = 0x400 @@ -291,7 +205,7 @@ const ( sysFSIGNORED = 0x8000 ) -func (w *Watcher) newEvent(name string, mask uint32) Event { +func (w *readDirChangesW) newEvent(name string, mask uint32) Event { e := Event{Name: name} if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { e.Op |= Create @@ -305,9 +219,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { e.Op |= Rename } - if mask&sysFSATTRIB == sysFSATTRIB { - e.Op |= Chmod - } return e } @@ -321,10 +232,11 @@ const ( ) type input struct { - op int - path string - flags uint32 - reply chan error + op int + path string + flags uint32 + bufsize int + reply chan error } type inode struct { @@ -334,13 +246,14 @@ type inode struct { } type watch struct { - ov windows.Overlapped - ino *inode // i-number - path string // Directory path - mask uint64 // Directory itself is being watched with these notify flags - names map[string]uint64 // Map of names being watched and their notify flags - rename string // Remembers the old name while renaming a file - buf [65536]byte // 64K buffer + ov windows.Overlapped + ino *inode // i-number + recurse bool // Recursive watch? + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf []byte // buffer, allocated later } type ( @@ -348,7 +261,7 @@ type ( watchMap map[uint32]indexMap ) -func (w *Watcher) wakeupReader() error { +func (w *readDirChangesW) wakeupReader() error { err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil) if err != nil { return os.NewSyscallError("PostQueuedCompletionStatus", err) @@ -356,7 +269,7 @@ func (w *Watcher) wakeupReader() error { return nil } -func (w *Watcher) getDir(pathname string) (dir string, err error) { +func (w *readDirChangesW) getDir(pathname string) (dir string, err error) { attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname)) if err != nil { return "", os.NewSyscallError("GetFileAttributes", err) @@ -370,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) { return } -func (w *Watcher) getIno(path string) (ino *inode, err error) { +func (w *readDirChangesW) getIno(path string) (ino *inode, err error) { h, err := windows.CreateFile(windows.StringToUTF16Ptr(path), windows.FILE_LIST_DIRECTORY, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, @@ -413,7 +326,9 @@ func (m watchMap) set(ino *inode, watch *watch) { } // Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64) error { +func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error { + pathname, recurse := recursivePath(pathname) + dir, err := w.getDir(pathname) if err != nil { return err @@ -433,9 +348,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error { return os.NewSyscallError("CreateIoCompletionPort", err) } watchEntry = &watch{ - ino: ino, - path: dir, - names: make(map[string]uint64), + ino: ino, + path: dir, + names: make(map[string]uint64), + recurse: recurse, + buf: make([]byte, bufsize), } w.mu.Lock() w.watches.set(ino, watchEntry) @@ -464,7 +381,9 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error { } // Must run within the I/O thread. -func (w *Watcher) remWatch(pathname string) error { +func (w *readDirChangesW) remWatch(pathname string) error { + pathname, recurse := recursivePath(pathname) + dir, err := w.getDir(pathname) if err != nil { return err @@ -478,6 +397,10 @@ func (w *Watcher) remWatch(pathname string) error { watch := w.watches.get(ino) w.mu.Unlock() + if recurse && !watch.recurse { + return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname) + } + err = windows.CloseHandle(ino.handle) if err != nil { w.sendError(os.NewSyscallError("CloseHandle", err)) @@ -486,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error { return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname) } if pathname == dir { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) watch.mask = 0 } else { name := filepath.Base(pathname) - w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) + w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED) delete(watch.names, name) } @@ -498,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error { } // Must run within the I/O thread. -func (w *Watcher) deleteWatch(watch *watch) { +func (w *readDirChangesW) deleteWatch(watch *watch) { for name, mask := range watch.names { if mask&provisional == 0 { - w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) + w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED) } delete(watch.names, name) } if watch.mask != 0 { if watch.mask&provisional == 0 { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) } watch.mask = 0 } } // Must run within the I/O thread. -func (w *Watcher) startRead(watch *watch) error { +func (w *readDirChangesW) startRead(watch *watch) error { err := windows.CancelIo(watch.ino.handle) if err != nil { w.sendError(os.NewSyscallError("CancelIo", err)) @@ -535,13 +458,16 @@ func (w *Watcher) startRead(watch *watch) error { return nil } - rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], - uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + // We need to pass the array, rather than the slice. + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf)) + rdErr := windows.ReadDirectoryChanges(watch.ino.handle, + (*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len), + watch.recurse, mask, nil, &watch.ov, 0) if rdErr != nil { err := os.NewSyscallError("ReadDirectoryChanges", rdErr) if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) err = nil } w.deleteWatch(watch) @@ -554,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error { // readEvents reads from the I/O completion port, converts the // received events into Event objects and sends them via the Events channel. // Entry point to the I/O thread. -func (w *Watcher) readEvents() { +func (w *readDirChangesW) readEvents() { var ( n uint32 key uintptr @@ -563,9 +489,8 @@ func (w *Watcher) readEvents() { runtime.LockOSThread() for { + // This error is handled after the watch == nil check below. qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE) - // This error is handled after the watch == nil check below. NOTE: this - // seems odd, note sure if it's correct. watch := (*watch)(unsafe.Pointer(ov)) if watch == nil { @@ -595,7 +520,7 @@ func (w *Watcher) readEvents() { case in := <-w.input: switch in.op { case opAddWatch: - in.reply <- w.addWatch(in.path, uint64(in.flags)) + in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize) case opRemoveWatch: in.reply <- w.remWatch(in.path) } @@ -605,6 +530,8 @@ func (w *Watcher) readEvents() { } switch qErr { + case nil: + // No error case windows.ERROR_MORE_DATA: if watch == nil { w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer")) @@ -616,7 +543,7 @@ func (w *Watcher) readEvents() { } case windows.ERROR_ACCESS_DENIED: // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) w.deleteWatch(watch) w.startRead(watch) continue @@ -626,13 +553,12 @@ func (w *Watcher) readEvents() { default: w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr)) continue - case nil: } var offset uint32 for { if n == 0 { - w.sendError(errors.New("short read in readEvents()")) + w.sendError(ErrEventOverflow) break } @@ -650,6 +576,10 @@ func (w *Watcher) readEvents() { name := windows.UTF16ToString(buf) fullname := filepath.Join(watch.path, name) + if debug { + internal.Debug(fullname, raw.Action) + } + var mask uint64 switch raw.Action { case windows.FILE_ACTION_REMOVED: @@ -678,21 +608,22 @@ func (w *Watcher) readEvents() { } } - sendNameEvent := func() { - w.sendEvent(fullname, watch.names[name]&mask) - } if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME { - sendNameEvent() + w.sendEvent(fullname, "", watch.names[name]&mask) } if raw.Action == windows.FILE_ACTION_REMOVED { - w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) + w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED) delete(watch.names, name) } - w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action)) + if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { + w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action)) + } else { + w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action)) + } + if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { - fullname = filepath.Join(watch.path, watch.rename) - sendNameEvent() + w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask) } // Move to the next event in the buffer @@ -703,8 +634,8 @@ func (w *Watcher) readEvents() { // Error! if offset >= n { - w.sendError(errors.New( - "Windows system assumed buffer larger than it is, events have likely been missed.")) + //lint:ignore ST1005 Windows should be capitalized + w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed")) break } } @@ -715,21 +646,18 @@ func (w *Watcher) readEvents() { } } -func (w *Watcher) toWindowsFlags(mask uint64) uint32 { +func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 { var m uint32 if mask&sysFSMODIFY != 0 { m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE } - if mask&sysFSATTRIB != 0 { - m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES - } if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME } return m } -func (w *Watcher) toFSnotifyFlags(action uint32) uint64 { +func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 { switch action { case windows.FILE_ACTION_ADDED: return sysFSCREATE @@ -744,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 { } return 0 } + +func (w *readDirChangesW) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/event-processor/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 30a5bf0f..0760efe9 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -1,16 +1,148 @@ -//go:build !plan9 -// +build !plan9 - // Package fsnotify provides a cross-platform interface for file system // notifications. +// +// Currently supported systems: +// +// - Linux via inotify +// - BSD, macOS via kqueue +// - Windows via ReadDirectoryChangesW +// - illumos via FEN +// +// # FSNOTIFY_DEBUG +// +// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to +// stderr. This can be useful to track down some problems, especially in cases +// where fsnotify is used as an indirect dependency. +// +// Every event will be printed as soon as there's something useful to print, +// with as little processing from fsnotify. +// +// Example output: +// +// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1" package fsnotify import ( "errors" "fmt" + "os" + "path/filepath" "strings" ) +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # Windows notes +// +// Paths can be added as "C:\\path\\to\\dir", but forward slashes +// ("C:/path/to/dir") will also work. +// +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all files, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. +type Watcher struct { + b backend + + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // when a file is truncated. On Windows it's never + // sent. + Events chan Event + + // Errors sends any errors. + Errors chan error +} + // Event represents a file system notification. type Event struct { // Path to the file or directory. @@ -25,6 +157,16 @@ type Event struct { // This is a bitmask and some systems may send multiple operations at once. // Use the Event.Has() method instead of comparing with ==. Op Op + + // Create events will have this set to the old path if it's a rename. This + // only works when both the source and destination are watched. It's not + // reliable when watching individual files, only directories. + // + // For example "mv /tmp/file /tmp/rename" will emit: + // + // Event{Op: Rename, Name: "/tmp/file"} + // Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"} + renamedFrom string } // Op describes a set of file operations. @@ -33,34 +175,204 @@ type Op uint32 // The operations fsnotify can trigger; see the documentation on [Watcher] for a // full description, and check them with [Event.Has]. const ( + // A new pathname was created. Create Op = 1 << iota + + // The pathname was written to; this does *not* mean the write has finished, + // and a write can be followed by more writes. Write + + // The path was removed; any watches on it will be removed. Some "remove" + // operations may trigger a Rename if the file is actually moved (for + // example "remove to trash" is often a rename). Remove + + // The path was renamed to something else; any watches on it will be + // removed. Rename + + // File attributes were changed. + // + // It's generally not recommended to take action on this event, as it may + // get triggered very frequently by some software. For example, Spotlight + // indexing on macOS, anti-virus software, backup software, etc. Chmod + + // File descriptor was opened. + // + // Only works on Linux and FreeBSD. + xUnportableOpen + + // File was read from. + // + // Only works on Linux and FreeBSD. + xUnportableRead + + // File opened for writing was closed. + // + // Only works on Linux and FreeBSD. + // + // The advantage of using this over Write is that it's more reliable than + // waiting for Write events to stop. It's also faster (if you're not + // listening to Write events): copying a file of a few GB can easily + // generate tens of thousands of Write events in a short span of time. + xUnportableCloseWrite + + // File opened for reading was closed. + // + // Only works on Linux and FreeBSD. + xUnportableCloseRead ) -// Common errors that can be reported by a watcher var ( - ErrNonExistentWatch = errors.New("can't remove non-existent watcher") - ErrEventOverflow = errors.New("fsnotify queue overflow") + // ErrNonExistentWatch is used when Remove() is called on a path that's not + // added. + ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch") + + // ErrClosed is used when trying to operate on a closed Watcher. + ErrClosed = errors.New("fsnotify: watcher already closed") + + // ErrEventOverflow is reported from the Errors channel when there are too + // many events: + // + // - inotify: inotify returns IN_Q_OVERFLOW – because there are too + // many queued events (the fs.inotify.max_queued_events + // sysctl can be used to increase this). + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. + ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") + + // ErrUnsupported is returned by AddWith() when WithOps() specified an + // Unportable event that's not supported on this platform. + xErrUnsupported = errors.New("fsnotify: not supported with this backend") ) -func (op Op) String() string { +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBackend(ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBufferedBackend(sz, ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. +// +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(path string) error { return w.b.Add(path) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) } + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) Remove(path string) error { return w.b.Remove(path) } + +// Close removes all watches and closes the Events channel. +func (w *Watcher) Close() error { return w.b.Close() } + +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { return w.b.WatchList() } + +// Supports reports if all the listed operations are supported by this platform. +// +// Create, Write, Remove, Rename, and Chmod are always supported. It can only +// return false for an Op starting with Unportable. +func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) } + +func (o Op) String() string { var b strings.Builder - if op.Has(Create) { + if o.Has(Create) { b.WriteString("|CREATE") } - if op.Has(Remove) { + if o.Has(Remove) { b.WriteString("|REMOVE") } - if op.Has(Write) { + if o.Has(Write) { b.WriteString("|WRITE") } - if op.Has(Rename) { + if o.Has(xUnportableOpen) { + b.WriteString("|OPEN") + } + if o.Has(xUnportableRead) { + b.WriteString("|READ") + } + if o.Has(xUnportableCloseWrite) { + b.WriteString("|CLOSE_WRITE") + } + if o.Has(xUnportableCloseRead) { + b.WriteString("|CLOSE_READ") + } + if o.Has(Rename) { b.WriteString("|RENAME") } - if op.Has(Chmod) { + if o.Has(Chmod) { b.WriteString("|CHMOD") } if b.Len() == 0 { @@ -70,12 +382,113 @@ func (op Op) String() string { } // Has reports if this operation has the given operation. -func (o Op) Has(h Op) bool { return o&h == h } +func (o Op) Has(h Op) bool { return o&h != 0 } // Has reports if this event has the given operation. func (e Event) Has(op Op) bool { return e.Op.Has(op) } // String returns a string representation of the event with their path. func (e Event) String() string { + if e.renamedFrom != "" { + return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom) + } return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } + +type ( + backend interface { + Add(string) error + AddWith(string, ...addOpt) error + Remove(string) error + WatchList() []string + Close() error + xSupports(Op) bool + } + addOpt func(opt *withOpts) + withOpts struct { + bufsize int + op Op + noFollow bool + sendCreate bool + } +) + +var debug = func() bool { + // Check for exactly "1" (rather than mere existence) so we can add + // options/flags in the future. I don't know if we ever want that, but it's + // nice to leave the option open. + return os.Getenv("FSNOTIFY_DEBUG") == "1" +}() + +var defaultOpts = withOpts{ + bufsize: 65536, // 64K + op: Create | Write | Remove | Rename | Chmod, +} + +func getOptions(opts ...addOpt) withOpts { + with := defaultOpts + for _, o := range opts { + if o != nil { + o(&with) + } + } + return with +} + +// WithBufferSize sets the [ReadDirectoryChangesW] buffer size. +// +// This only has effect on Windows systems, and is a no-op for other backends. +// +// The default value is 64K (65536 bytes) which is the highest value that works +// on all filesystems and should be enough for most applications, but if you +// have a large burst of events it may not be enough. You can increase it if +// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]). +// +// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw +func WithBufferSize(bytes int) addOpt { + return func(opt *withOpts) { opt.bufsize = bytes } +} + +// WithOps sets which operations to listen for. The default is [Create], +// [Write], [Remove], [Rename], and [Chmod]. +// +// Excluding operations you're not interested in can save quite a bit of CPU +// time; in some use cases there may be hundreds of thousands of useless Write +// or Chmod operations per second. +// +// This can also be used to add unportable operations not supported by all +// platforms; unportable operations all start with "Unportable": +// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and +// [UnportableCloseRead]. +// +// AddWith returns an error when using an unportable operation that's not +// supported. Use [Watcher.Support] to check for support. +func withOps(op Op) addOpt { + return func(opt *withOpts) { opt.op = op } +} + +// WithNoFollow disables following symlinks, so the symlinks themselves are +// watched. +func withNoFollow() addOpt { + return func(opt *withOpts) { opt.noFollow = true } +} + +// "Internal" option for recursive watches on inotify. +func withCreate() addOpt { + return func(opt *withOpts) { opt.sendCreate = true } +} + +var enableRecurse = false + +// Check if this path is recursive (ends with "/..." or "\..."), and return the +// path with the /... stripped. +func recursivePath(path string) (string, bool) { + path = filepath.Clean(path) + if !enableRecurse { // Only enabled in tests for now. + return path, false + } + if filepath.Base(path) == "..." { + return filepath.Dir(path), true + } + return path, false +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/darwin.go new file mode 100644 index 00000000..b0eab100 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/darwin.go @@ -0,0 +1,39 @@ +//go:build darwin + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ +func SetRlimit() { + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = l.Cur + + if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } + + if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go new file mode 100644 index 00000000..928319fb --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go @@ -0,0 +1,57 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_BACKGROUND", unix.NOTE_BACKGROUND}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CRITICAL", unix.NOTE_CRITICAL}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS}, + {"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR}, + {"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL}, + {"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL}, + {"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK}, + {"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY}, + {"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_FUNLOCK", unix.NOTE_FUNLOCK}, + {"NOTE_LEEWAY", unix.NOTE_LEEWAY}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MACHTIME", unix.NOTE_MACHTIME}, + {"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME}, + {"NOTE_NONE", unix.NOTE_NONE}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OOB", unix.NOTE_OOB}, + //{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!) + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_REAP", unix.NOTE_REAP}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_SIGNAL", unix.NOTE_SIGNAL}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_VM_ERROR", unix.NOTE_VM_ERROR}, + {"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE}, + {"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE}, + {"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go new file mode 100644 index 00000000..3186b0c3 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go @@ -0,0 +1,33 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_OOB", unix.NOTE_OOB}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go new file mode 100644 index 00000000..f69fdb93 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go @@ -0,0 +1,42 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSTIME", unix.NOTE_ABSTIME}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CLOSE", unix.NOTE_CLOSE}, + {"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FILE_POLL", unix.NOTE_FILE_POLL}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MSECONDS", unix.NOTE_MSECONDS}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OPEN", unix.NOTE_OPEN}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_READ", unix.NOTE_READ}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go new file mode 100644 index 00000000..607e683b --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go @@ -0,0 +1,32 @@ +//go:build freebsd || openbsd || netbsd || dragonfly || darwin + +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, kevent *unix.Kevent_t) { + mask := uint32(kevent.Fflags) + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-60s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go new file mode 100644 index 00000000..35c734be --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go @@ -0,0 +1,56 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask, cookie uint32) { + names := []struct { + n string + m uint32 + }{ + {"IN_ACCESS", unix.IN_ACCESS}, + {"IN_ATTRIB", unix.IN_ATTRIB}, + {"IN_CLOSE", unix.IN_CLOSE}, + {"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE}, + {"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE}, + {"IN_CREATE", unix.IN_CREATE}, + {"IN_DELETE", unix.IN_DELETE}, + {"IN_DELETE_SELF", unix.IN_DELETE_SELF}, + {"IN_IGNORED", unix.IN_IGNORED}, + {"IN_ISDIR", unix.IN_ISDIR}, + {"IN_MODIFY", unix.IN_MODIFY}, + {"IN_MOVE", unix.IN_MOVE}, + {"IN_MOVED_FROM", unix.IN_MOVED_FROM}, + {"IN_MOVED_TO", unix.IN_MOVED_TO}, + {"IN_MOVE_SELF", unix.IN_MOVE_SELF}, + {"IN_OPEN", unix.IN_OPEN}, + {"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW}, + {"IN_UNMOUNT", unix.IN_UNMOUNT}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + var c string + if cookie > 0 { + c = fmt.Sprintf("(cookie: %d) ", cookie) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-30s → %s%q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name) +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go new file mode 100644 index 00000000..e5b3b6f6 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go @@ -0,0 +1,25 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go new file mode 100644 index 00000000..1dd455bc --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go @@ -0,0 +1,28 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + // {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386? + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EOF", unix.NOTE_EOF}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRUNCATE", unix.NOTE_TRUNCATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go new file mode 100644 index 00000000..f1b2e73b --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go @@ -0,0 +1,45 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask int32) { + names := []struct { + n string + m int32 + }{ + {"FILE_ACCESS", unix.FILE_ACCESS}, + {"FILE_MODIFIED", unix.FILE_MODIFIED}, + {"FILE_ATTRIB", unix.FILE_ATTRIB}, + {"FILE_TRUNC", unix.FILE_TRUNC}, + {"FILE_NOFOLLOW", unix.FILE_NOFOLLOW}, + {"FILE_DELETE", unix.FILE_DELETE}, + {"FILE_RENAME_TO", unix.FILE_RENAME_TO}, + {"FILE_RENAME_FROM", unix.FILE_RENAME_FROM}, + {"UNMOUNTED", unix.UNMOUNTED}, + {"MOUNTEDOVER", unix.MOUNTEDOVER}, + {"FILE_EXCEPTION", unix.FILE_EXCEPTION}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-30s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go new file mode 100644 index 00000000..52bf4ce5 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go @@ -0,0 +1,40 @@ +package internal + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/sys/windows" +) + +func Debug(name string, mask uint32) { + names := []struct { + n string + m uint32 + }{ + {"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED}, + {"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED}, + {"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED}, + {"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME}, + {"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-65s → %q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name)) +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go new file mode 100644 index 00000000..547df1df --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go @@ -0,0 +1,31 @@ +//go:build freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) } diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/internal.go new file mode 100644 index 00000000..7daa45e1 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/internal.go @@ -0,0 +1,2 @@ +// Package internal contains some helpers. +package internal diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix.go new file mode 100644 index 00000000..30976ce9 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix.go @@ -0,0 +1,31 @@ +//go:build !windows && !darwin && !freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix2.go new file mode 100644 index 00000000..37dfeddc --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/unix2.go @@ -0,0 +1,7 @@ +//go:build !windows + +package internal + +func HasPrivilegesForSymlink() bool { + return true +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/windows.go new file mode 100644 index 00000000..a72c6495 --- /dev/null +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/internal/windows.go @@ -0,0 +1,41 @@ +//go:build windows + +package internal + +import ( + "errors" + + "golang.org/x/sys/windows" +) + +// Just a dummy. +var ( + SyscallEACCES = errors.New("dummy") + UnixEACCES = errors.New("dummy") +) + +func SetRlimit() {} +func Maxfiles() uint64 { return 1<<64 - 1 } +func Mkfifo(path string, mode uint32) error { return errors.New("no FIFOs on Windows") } +func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") } + +func HasPrivilegesForSymlink() bool { + var sid *windows.SID + err := windows.AllocateAndInitializeSid( + &windows.SECURITY_NT_AUTHORITY, + 2, + windows.SECURITY_BUILTIN_DOMAIN_RID, + windows.DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid) + if err != nil { + return false + } + defer windows.FreeSid(sid) + token := windows.Token(0) + member, err := token.IsMember(sid) + if err != nil { + return false + } + return member || token.IsElevated() +} diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/event-processor/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh deleted file mode 100644 index b09ef768..00000000 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env zsh -[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 -setopt err_exit no_unset pipefail extended_glob - -# Simple script to update the godoc comments on all watchers. Probably took me -# more time to write this than doing it manually, but ah well 🙃 - -watcher=$(</tmp/x - print -r -- $cmt >>/tmp/x - tail -n+$(( end + 1 )) $file >>/tmp/x - mv /tmp/x $file - done -} - -set-cmt '^type Watcher struct ' $watcher -set-cmt '^func NewWatcher(' $new -set-cmt '^func (w \*Watcher) Add(' $add -set-cmt '^func (w \*Watcher) Remove(' $remove -set-cmt '^func (w \*Watcher) Close(' $close -set-cmt '^func (w \*Watcher) WatchList(' $watchlist -set-cmt '^[[:space:]]*Events *chan Event$' $events -set-cmt '^[[:space:]]*Errors *chan error$' $errors diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/event-processor/vendor/github.com/fsnotify/fsnotify/system_bsd.go index 4322b0b8..f65e8fe3 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/system_bsd.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/system_bsd.go @@ -1,5 +1,4 @@ //go:build freebsd || openbsd || netbsd || dragonfly -// +build freebsd openbsd netbsd dragonfly package fsnotify diff --git a/event-processor/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/event-processor/vendor/github.com/fsnotify/fsnotify/system_darwin.go index 5da5ffa7..a29fc7aa 100644 --- a/event-processor/vendor/github.com/fsnotify/fsnotify/system_darwin.go +++ b/event-processor/vendor/github.com/fsnotify/fsnotify/system_darwin.go @@ -1,5 +1,4 @@ //go:build darwin -// +build darwin package fsnotify diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/event-processor/vendor/github.com/go-viper/mapstructure/v2/.editorconfig index 1f664d13..faef0c91 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/.editorconfig +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/.editorconfig @@ -16,3 +16,6 @@ indent_style = tab [*.nix] indent_size = 2 + +[.golangci.yaml] +indent_size = 2 diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/event-processor/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml index 763143aa..bda96256 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -1,23 +1,48 @@ -run: - timeout: 5m +version: "2" -linters-settings: - gci: - sections: - - standard - - default - - prefix(github.com/go-viper/mapstructure) - golint: - min-confidence: 0 - goimports: - local-prefixes: github.com/go-viper/maptstructure +run: + timeout: 10m linters: - disable-all: true + enable: + - govet + - ineffassign + # - misspell + - nolintlint + # - revive + + disable: + - errcheck + - staticcheck + - unused + + settings: + misspell: + locale: US + nolintlint: + allow-unused: false # report any unused nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + +formatters: enable: - gci - gofmt - gofumpt - goimports - - staticcheck - # - stylecheck + # - golines + + settings: + gci: + sections: + - standard + - default + - localmodule + gofmt: + simplify: true + rewrite-rules: + - pattern: interface{} + replacement: any + + exclusions: + paths: + - internal/ diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/README.md b/event-processor/vendor/github.com/go-viper/mapstructure/v2/README.md index dd5ec69d..45db7197 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/README.md +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -1,8 +1,9 @@ # mapstructure -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml) [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2) mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. @@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else. Here is a script that can help you with the migration: ```shell -sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go') ``` If you need more time to migrate your code, that is absolutely fine. diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/event-processor/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go index 1f3c69d4..a852a0a0 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -13,7 +13,7 @@ import ( "time" ) -// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into the proper DecodeHookFunc type, such as DecodeHookFuncType. func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Create variables here so we can reference them with the reflect pkg @@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Fill in the variables into this interface and the rest is done // automatically using the reflect package. - potential := []interface{}{f1, f2, f3} + potential := []any{f1, f2, f3} v := reflect.ValueOf(h) vt := v.Type() @@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { return nil } -// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns // it into a closure to be used directly // if the type fails to convert we return a closure always erroring to keep the previous behaviour -func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) { +func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Type(), to.Type(), from.Interface()) } case DecodeHookFuncKind: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from.Kind(), to.Kind(), from.Interface()) } case DecodeHookFuncValue: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return f(from, to) } default: - return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return func(from reflect.Value, to reflect.Value) (any, error) { return nil, errors.New("invalid decode hook signature") } } @@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va func DecodeHookExec( raw DecodeHookFunc, from reflect.Value, to reflect.Value, -) (interface{}, error) { +) (any, error) { switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: return f(from.Type(), to.Type(), from.Interface()) @@ -86,11 +86,11 @@ func DecodeHookExec( // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs)) for _, f := range fs { cached = append(cached, cachedDecodeHook(f)) } - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { var err error data := f.Interface() @@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { if err != nil { return nil, err } - newFrom = reflect.ValueOf(data) + if v, ok := data.(reflect.Value); ok { + newFrom = v + } else { + newFrom = reflect.ValueOf(data) + } } return data, nil @@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { - cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff)) + cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff)) for _, f := range ff { cached = append(cached, cachedDecodeHook(f)) } - return func(a, b reflect.Value) (interface{}, error) { + return func(a, b reflect.Value) (any, error) { var allErrs string - var out interface{} + var out any var err error for _, c := range cached { @@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc { } } +// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc]. +// +// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice. +// This function removes that check. +func StringToWeakSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts // strings to time.Duration. func StringToTimeDurationHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc { } // Convert it by parsing - return time.ParseDuration(data.(string)) + d, err := time.ParseDuration(data.(string)) + + return d, wrapTimeParseDurationError(err) + } +} + +// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts +// strings to *time.Location. +func StringToTimeLocationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Local) { + return data, nil + } + d, err := time.LoadLocation(data.(string)) + + return d, wrapTimeParseLocationError(err) } } @@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc { } // Convert it by parsing - return url.Parse(data.(string)) + u, err := url.Parse(data.(string)) + + return u, wrapUrlError(err) } } @@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc { // Convert it by parsing ip := net.ParseIP(data.(string)) if ip == nil { - return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + return net.IP{}, fmt.Errorf("failed parsing ip") } return ip, nil @@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc { // Convert it by parsing _, net, err := net.ParseCIDR(data.(string)) - return net, err + return net, wrapNetParseError(err) } } @@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { } // Convert it by parsing - return time.Parse(layout, data.(string)) + ti, err := time.Parse(layout, data.(string)) + + return ti, wrapTimeParseError(err) } } @@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc { func WeaklyTypedHook( f reflect.Kind, t reflect.Kind, - data interface{}, -) (interface{}, error) { + data any, +) (any, error) { dataVal := reflect.ValueOf(data) switch t { case reflect.String: @@ -301,17 +354,17 @@ func WeaklyTypedHook( } func RecursiveStructToMapHookFunc() DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (any, error) { if f.Kind() != reflect.Struct { return f.Interface(), nil } - var i interface{} = struct{}{} + var i any = struct{}{} if t.Type() != reflect.TypeOf(&i).Elem() { return f.Interface(), nil } - m := make(map[string]interface{}) + m := make(map[string]any) t.Set(reflect.ValueOf(m)) return f.Interface(), nil @@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddr(data.(string)) + addr, err := netip.ParseAddr(data.(string)) + + return addr, wrapNetIPParseAddrError(err) } } @@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { return func( f reflect.Type, t reflect.Type, - data interface{}, - ) (interface{}, error) { + data any, + ) (any, error) { if f.Kind() != reflect.String { return data, nil } @@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc { } // Convert it by parsing - return netip.ParseAddrPort(data.(string)) + addrPort, err := netip.ParseAddrPort(data.(string)) + + return addrPort, wrapNetIPParseAddrPortError(err) + } +} + +// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts +// strings to netip.Prefix. +func StringToNetIPPrefixHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data any, + ) (any, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.Prefix{}) { + return data, nil + } + + // Convert it by parsing + prefix, err := netip.ParsePrefix(data.(string)) + + return prefix, wrapNetIPParsePrefixError(err) } } @@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc { // StringToInt8HookFunc returns a DecodeHookFunc that converts // strings to int8. func StringToInt8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int8 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 8) - return int8(i64), err + return int8(i64), wrapStrconvNumError(err) } } // StringToUint8HookFunc returns a DecodeHookFunc that converts // strings to uint8. func StringToUint8HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 8) - return uint8(u64), err + return uint8(u64), wrapStrconvNumError(err) } } // StringToInt16HookFunc returns a DecodeHookFunc that converts // strings to int16. func StringToInt16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int16 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 16) - return int16(i64), err + return int16(i64), wrapStrconvNumError(err) } } // StringToUint16HookFunc returns a DecodeHookFunc that converts // strings to uint16. func StringToUint16HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 16) - return uint16(u64), err + return uint16(u64), wrapStrconvNumError(err) } } // StringToInt32HookFunc returns a DecodeHookFunc that converts // strings to int32. func StringToInt32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int32 { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 32) - return int32(i64), err + return int32(i64), wrapStrconvNumError(err) } } // StringToUint32HookFunc returns a DecodeHookFunc that converts // strings to uint32. func StringToUint32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 32) - return uint32(u64), err + return uint32(u64), wrapStrconvNumError(err) } } // StringToInt64HookFunc returns a DecodeHookFunc that converts // strings to int64. func StringToInt64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int64 { return data, nil } // Convert it by parsing - return strconv.ParseInt(data.(string), 0, 64) + i64, err := strconv.ParseInt(data.(string), 0, 64) + return int64(i64), wrapStrconvNumError(err) } } // StringToUint64HookFunc returns a DecodeHookFunc that converts // strings to uint64. func StringToUint64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 { return data, nil } // Convert it by parsing - return strconv.ParseUint(data.(string), 0, 64) + u64, err := strconv.ParseUint(data.(string), 0, 64) + return uint64(u64), wrapStrconvNumError(err) } } // StringToIntHookFunc returns a DecodeHookFunc that converts // strings to int. func StringToIntHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Int { return data, nil } // Convert it by parsing i64, err := strconv.ParseInt(data.(string), 0, 0) - return int(i64), err + return int(i64), wrapStrconvNumError(err) } } // StringToUintHookFunc returns a DecodeHookFunc that converts // strings to uint. func StringToUintHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Uint { return data, nil } // Convert it by parsing u64, err := strconv.ParseUint(data.(string), 0, 0) - return uint(u64), err + return uint(u64), wrapStrconvNumError(err) } } // StringToFloat32HookFunc returns a DecodeHookFunc that converts // strings to float32. func StringToFloat32HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float32 { return data, nil } // Convert it by parsing f64, err := strconv.ParseFloat(data.(string), 32) - return float32(f64), err + return float32(f64), wrapStrconvNumError(err) } } // StringToFloat64HookFunc returns a DecodeHookFunc that converts // strings to float64. func StringToFloat64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Float64 { return data, nil } // Convert it by parsing - return strconv.ParseFloat(data.(string), 64) + f64, err := strconv.ParseFloat(data.(string), 64) + return f64, wrapStrconvNumError(err) } } // StringToBoolHookFunc returns a DecodeHookFunc that converts // strings to bool. func StringToBoolHookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Bool { return data, nil } // Convert it by parsing - return strconv.ParseBool(data.(string)) + b, err := strconv.ParseBool(data.(string)) + return b, wrapStrconvNumError(err) } } @@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc { // StringToComplex64HookFunc returns a DecodeHookFunc that converts // strings to complex64. func StringToComplex64HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 { return data, nil } // Convert it by parsing c128, err := strconv.ParseComplex(data.(string), 64) - return complex64(c128), err + return complex64(c128), wrapStrconvNumError(err) } } // StringToComplex128HookFunc returns a DecodeHookFunc that converts // strings to complex128. func StringToComplex128HookFunc() DecodeHookFunc { - return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + return func(f reflect.Type, t reflect.Type, data any) (any, error) { if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 { return data, nil } // Convert it by parsing - return strconv.ParseComplex(data.(string), 128) + c128, err := strconv.ParseComplex(data.(string), 128) + return c128, wrapStrconvNumError(err) } } diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/errors.go b/event-processor/vendor/github.com/go-viper/mapstructure/v2/errors.go new file mode 100644 index 00000000..07d31c22 --- /dev/null +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/errors.go @@ -0,0 +1,244 @@ +package mapstructure + +import ( + "errors" + "fmt" + "net" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +// Error interface is implemented by all errors emitted by mapstructure. +// +// Use [errors.As] to check if an error implements this interface. +type Error interface { + error + + mapstructure() +} + +// DecodeError is a generic error type that holds information about +// a decoding error together with the name of the field that caused the error. +type DecodeError struct { + name string + err error +} + +func newDecodeError(name string, err error) *DecodeError { + return &DecodeError{ + name: name, + err: err, + } +} + +func (e *DecodeError) Name() string { + return e.name +} + +func (e *DecodeError) Unwrap() error { + return e.err +} + +func (e *DecodeError) Error() string { + return fmt.Sprintf("'%s' %s", e.name, e.err) +} + +func (*DecodeError) mapstructure() {} + +// ParseError is an error type that indicates a value could not be parsed +// into the expected type. +type ParseError struct { + Expected reflect.Value + Value any + Err error +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err) +} + +func (*ParseError) mapstructure() {} + +// UnconvertibleTypeError is an error type that indicates a value could not be +// converted to the expected type. +type UnconvertibleTypeError struct { + Expected reflect.Value + Value any +} + +func (e *UnconvertibleTypeError) Error() string { + return fmt.Sprintf( + "expected type '%s', got unconvertible type '%s'", + e.Expected.Type(), + reflect.TypeOf(e.Value), + ) +} + +func (*UnconvertibleTypeError) mapstructure() {} + +func wrapStrconvNumError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*strconv.NumError); ok { + return &strconvNumError{Err: err} + } + + return err +} + +type strconvNumError struct { + Err *strconv.NumError +} + +func (e *strconvNumError) Error() string { + return "strconv." + e.Err.Func + ": " + e.Err.Err.Error() +} + +func (e *strconvNumError) Unwrap() error { return e.Err } + +func wrapUrlError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*url.Error); ok { + return &urlError{Err: err} + } + + return err +} + +type urlError struct { + Err *url.Error +} + +func (e *urlError) Error() string { + return fmt.Sprintf("%s", e.Err.Err) +} + +func (e *urlError) Unwrap() error { return e.Err } + +func wrapNetParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*net.ParseError); ok { + return &netParseError{Err: err} + } + + return err +} + +type netParseError struct { + Err *net.ParseError +} + +func (e *netParseError) Error() string { + return "invalid " + e.Err.Type +} + +func (e *netParseError) Unwrap() error { return e.Err } + +func wrapTimeParseError(err error) error { + if err == nil { + return nil + } + + if err, ok := err.(*time.ParseError); ok { + return &timeParseError{Err: err} + } + + return err +} + +type timeParseError struct { + Err *time.ParseError +} + +func (e *timeParseError) Error() string { + if e.Err.Message == "" { + return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem) + } + + return "parsing time " + e.Err.Message +} + +func (e *timeParseError) Unwrap() error { return e.Err } + +func wrapNetIPParseAddrError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapNetIPParseAddrPortError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "invalid port ") { + return errors.New("invalid port") + } else if strings.HasPrefix(errMsg, "invalid ip:port ") { + return errors.New("invalid ip:port") + } + + return err +} + +func wrapNetIPParsePrefixError(err error) error { + if err == nil { + return nil + } + + if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") { + errPieces := strings.Split(errMsg, ": ") + + return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1]) + } + + return err +} + +func wrapTimeParseDurationError(err error) error { + if err == nil { + return nil + } + + errMsg := err.Error() + if strings.HasPrefix(errMsg, "time: unknown unit ") { + return errors.New("time: unknown unit") + } else if strings.HasPrefix(errMsg, "time: ") { + idx := strings.LastIndex(errMsg, " ") + + return errors.New(errMsg[:idx]) + } + + return err +} + +func wrapTimeParseLocationError(err error) error { + if err == nil { + return nil + } + errMsg := err.Error() + if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") { + return fmt.Errorf("invalid time zone format: %w", err) + } + + return err +} diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.lock index 4bea8154..5e67bdd6 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.lock +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.lock @@ -2,30 +2,28 @@ "nodes": { "cachix": { "inputs": { - "devenv": "devenv_2", + "devenv": [ + "devenv" + ], "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "git-hooks": [ + "devenv" ], - "pre-commit-hooks": [ - "devenv", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1712055811, - "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "lastModified": 1742042642, + "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=", "owner": "cachix", "repo": "cachix", - "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203", "type": "github" }, "original": { "owner": "cachix", + "ref": "latest", "repo": "cachix", "type": "github" } @@ -33,52 +31,21 @@ "devenv": { "inputs": { "cachix": "cachix", - "flake-compat": "flake-compat_2", - "nix": "nix_2", - "nixpkgs": "nixpkgs_2", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1717245169, - "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", - "owner": "cachix", - "repo": "devenv", - "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "devenv_2": { - "inputs": { - "flake-compat": [ - "devenv", - "cachix", - "flake-compat" - ], + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", "nix": "nix", - "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix", - "pre-commit-hooks": [ - "devenv", - "cachix", - "pre-commit-hooks" - ] + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1708704632, - "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "lastModified": 1744876578, + "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=", "owner": "cachix", "repo": "devenv", - "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1", "type": "github" }, "original": { "owner": "cachix", - "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -86,27 +53,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -117,14 +68,18 @@ }, "flake-parts": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] }, "locked": { - "lastModified": 1717285511, - "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "type": "github" }, "original": { @@ -133,39 +88,46 @@ "type": "github" } }, - "flake-utils": { + "flake-parts_2": { "inputs": { - "systems": "systems" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "flake-utils_2": { + "git-hooks": { "inputs": { - "systems": "systems_2" + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "cachix", + "repo": "git-hooks.nix", "type": "github" } }, @@ -173,7 +135,7 @@ "inputs": { "nixpkgs": [ "devenv", - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -191,166 +153,109 @@ "type": "github" } }, - "nix": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", - "owner": "domenkozar", - "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "devenv-2.21", - "repo": "nix", - "type": "github" - } - }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "poetry2nix", - "nixpkgs" - ] - }, + "libgit2": { + "flake": false, "locked": { - "lastModified": 1688870561, - "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nix-github-actions", + "owner": "libgit2", + "repo": "libgit2", "type": "github" } }, - "nix_2": { + "nix": { "inputs": { "flake-compat": [ - "devenv", - "flake-compat" + "devenv" ], - "nixpkgs": [ - "devenv", - "nixpkgs" + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" ], - "nixpkgs-regression": "nixpkgs-regression_2" + "pre-commit-hooks": [ + "devenv" + ] }, "locked": { - "lastModified": 1712911606, - "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "lastModified": 1741798497, + "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=", "owner": "domenkozar", "repo": "nix", - "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "devenv-2.21", + "ref": "devenv-2.24", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1692808169, - "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-lib": { "locked": { - "lastModified": 1717284937, - "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-regression_2": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", "type": "github" }, "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "owner": "nix-community", + "repo": "nixpkgs.lib", "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs_2": { "locked": { - "lastModified": 1710695816, - "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "release-24.05", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs_2": { + "nixpkgs_3": { "locked": { - "lastModified": 1713361204, - "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "lastModified": 1733477122, + "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=", "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", "type": "github" }, "original": { @@ -360,13 +265,13 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { - "lastModified": 1717112898, - "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", "type": "github" }, "original": { @@ -376,94 +281,11 @@ "type": "github" } }, - "poetry2nix": { - "inputs": { - "flake-utils": "flake-utils", - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "devenv", - "cachix", - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1692876271, - "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils_2", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1713775815, - "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_3" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4" } } }, diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.nix index 4ed0f533..3b116f42 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.nix +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/flake.nix @@ -5,35 +5,42 @@ devenv.url = "github:cachix/devenv"; }; - outputs = inputs@{ flake-parts, ... }: + outputs = + inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { imports = [ inputs.devenv.flakeModule ]; - systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; + systems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; - perSystem = { config, self', inputs', pkgs, system, ... }: rec { - devenv.shells = { - default = { - languages = { - go.enable = true; - }; + perSystem = + { pkgs, ... }: + rec { + devenv.shells = { + default = { + languages = { + go.enable = true; + }; - pre-commit.hooks = { - nixpkgs-fmt.enable = true; - }; + pre-commit.hooks = { + nixpkgs-fmt.enable = true; + }; - packages = with pkgs; [ - golangci-lint - ]; + packages = with pkgs; [ + golangci-lint + ]; - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; + # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 + containers = pkgs.lib.mkForce { }; + }; - ci = devenv.shells.default; + ci = devenv.shells.default; + }; }; - }; }; } diff --git a/event-processor/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/event-processor/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go index e77e63ba..7c35bce0 100644 --- a/event-processor/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go +++ b/event-processor/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -1,5 +1,5 @@ // Package mapstructure exposes functionality to convert one arbitrary -// Go type into another, typically to convert a map[string]interface{} +// Go type into another, typically to convert a map[string]any // into a native Go structure. // // The Go structure can be arbitrarily complex, containing slices, @@ -54,8 +54,8 @@ // // This would require an input that looks like below: // -// map[string]interface{}{ -// "person": map[string]interface{}{"name": "alice"}, +// map[string]any{ +// "person": map[string]any{"name": "alice"}, // } // // If your "person" value is NOT nested, then you can append ",squash" to @@ -68,7 +68,7 @@ // // Now the following input would be accepted: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -79,7 +79,7 @@ // // Will be decoded into a map: // -// map[string]interface{}{ +// map[string]any{ // "name": "alice", // } // @@ -95,18 +95,18 @@ // // You can also use the ",remain" suffix on your tag to collect all unused // values in a map. The field with this tag MUST be a map type and should -// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// probably be a "map[string]any" or "map[any]any". // See example below: // // type Friend struct { // Name string -// Other map[string]interface{} `mapstructure:",remain"` +// Other map[string]any `mapstructure:",remain"` // } // // Given the input below, Other would be populated with the other // values that weren't used (everything but "name"): // -// map[string]interface{}{ +// map[string]any{ // "name": "bob", // "address": "123 Maple St.", // } @@ -115,15 +115,36 @@ // // When decoding from a struct to any other value, you may use the // ",omitempty" suffix on your tag to omit that value if it equates to -// the zero value. The zero value of all types is specified in the Go -// specification. +// the zero value, or a zero-length element. The zero value of all types is +// specified in the Go specification. // // For example, the zero type of a numeric type is zero ("0"). If the struct // field value is zero and a numeric type, the field is empty, and it won't -// be encoded into the destination type. +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil or empty, it won't be encoded into the destination type. // // type Source struct { -// Age int `mapstructure:",omitempty"` +// Age int `mapstructure:",omitempty"` +// URLs []string `mapstructure:",omitempty"` +// } +// +// # Omit Zero Values +// +// When decoding from a struct to any other value, you may use the +// ",omitzero" suffix on your tag to omit that value if it equates to the zero +// value. The zero value of all types is specified in the Go specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. And likewise for the URLs field, if the +// slice is nil, it won't be encoded into the destination type. +// +// Note that if the field is a slice, and it is empty but not nil, it will +// still be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitzero"` +// URLs []string `mapstructure:",omitzero"` // } // // # Unexported fields @@ -140,7 +161,7 @@ // // Using this map as input: // -// map[string]interface{}{ +// map[string]any{ // "private": "I will be ignored", // "Public": "I made it through!", // } @@ -183,19 +204,19 @@ import ( // we started with Kinds and then realized Types were the better solution, // but have a promise to not break backwards compat so we now support // both. -type DecodeHookFunc interface{} +type DecodeHookFunc any // DecodeHookFuncType is a DecodeHookFunc which has complete information about // the source and target types. -type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) +type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error) // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the // source and target types. -type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error) // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target // values. -type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error) // DecoderConfig is the configuration that is used to create a new decoder // and allows customization of various aspects of decoding. @@ -222,6 +243,12 @@ type DecoderConfig struct { // will affect all nested structs as well. ErrorUnset bool + // AllowUnsetPointer, if set to true, will prevent fields with pointer types + // from being reported as unset, even if ErrorUnset is true and the field was + // not present in the input data. This allows pointer fields to be optional + // without triggering an error when they are missing. + AllowUnsetPointer bool + // ZeroFields, if set to true, will zero fields before writing them. // For example, a map will be emptied before decoded values are put in // it. If this is false, a map will be merged. @@ -260,7 +287,7 @@ type DecoderConfig struct { // Result is a pointer to the struct that will contain the decoded // value. - Result interface{} + Result any // The tag name that mapstructure reads for field names. This // defaults to "mapstructure" @@ -292,7 +319,7 @@ type DecoderConfig struct { // up the most basic Decoder. type Decoder struct { config *DecoderConfig - cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error) + cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error) } // Metadata contains information about decoding a structure that @@ -313,7 +340,7 @@ type Metadata struct { // Decode takes an input structure and uses reflection to translate it to // the output structure. output must be a pointer to a map or struct. -func Decode(input interface{}, output interface{}) error { +func Decode(input any, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error { // WeakDecode is the same as Decode but is shorthand to enable // WeaklyTypedInput. See DecoderConfig for more info. -func WeakDecode(input, output interface{}) error { +func WeakDecode(input, output any) error { config := &DecoderConfig{ Metadata: nil, Result: output, @@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error { // DecodeMetadata is the same as Decode, but is shorthand to // enable metadata collection. See DecoderConfig for more info. -func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func DecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e // WeakDecodeMetadata is the same as Decode, but is shorthand to // enable both WeaklyTypedInput and metadata collection. See // DecoderConfig for more info. -func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { +func WeakDecodeMetadata(input any, output any, metadata *Metadata) error { config := &DecoderConfig{ Metadata: metadata, Result: output, @@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { // Decode decodes the given raw interface to the target pointer specified // by the configuration. -func (d *Decoder) Decode(input interface{}) error { +func (d *Decoder) Decode(input any) error { err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) // Retain some of the original behavior when multiple errors ocurr @@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error { } // isNil returns true if the input is nil or a typed nil pointer. -func isNil(input interface{}) bool { +func isNil(input any) bool { if input == nil { return true } @@ -452,7 +479,7 @@ func isNil(input interface{}) bool { } // Decodes an unknown data type into a specific reflection value. -func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { +func (d *Decoder) decode(name string, input any, outVal reflect.Value) error { var ( inputVal = reflect.ValueOf(input) outputKind = getKind(outVal) @@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // Hooks need a valid inputVal, so reset it to zero value of outVal type. switch outputKind { case reflect.Struct, reflect.Map: - var mapVal map[string]interface{} + var mapVal map[string]any inputVal = reflect.ValueOf(mapVal) // create nil map pointer case reflect.Slice, reflect.Array: - var sliceVal []interface{} + var sliceVal []any inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer default: inputVal = reflect.Zero(outVal.Type()) @@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e var err error input, err = d.cachedDecodeHook(inputVal, outVal) if err != nil { - return fmt.Errorf("error decoding '%s': %w", name, err) + return newDecodeError(name, err) } } if isNil(input) { @@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e err = d.decodeFunc(name, input, outVal) default: // If we reached this point then we weren't able to decode it - return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind)) } // If we reached here, then we successfully decoded SOMETHING, so @@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e // This decodes a basic type (bool, int, string, etc.) and sets the // value to "data" of that type. -func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error { if val.IsValid() && val.Elem().IsValid() { elem := val.Elem() @@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) dataValType := dataVal.Type() if !dataValType.AssignableTo(val.Type()) { - return fmt.Errorf( - "'%s' expected type '%s', got '%s'", - name, val.Type(), dataValType) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) return nil } -func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeString(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) } if !converted { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er if err == nil { val.SetInt(i) } else { - return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Int64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetInt(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Int: i := dataVal.Int() if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%d overflows uint", i), + }) } val.SetUint(uint64(i)) case dataKind == reflect.Uint: @@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e case dataKind == reflect.Float32: f := dataVal.Float() if f < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %f overflows uint", - name, f) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: fmt.Errorf("%f overflows uint", f), + }) } val.SetUint(uint64(f)) case dataKind == reflect.Bool && d.config.WeaklyTypedInput: @@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e if err == nil { val.SetUint(i) } else { - return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } val.SetUint(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } else if dataVal.String() == "" { val.SetBool(false) } else { - return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'", - name, val, dataVal, data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) dataType := dataVal.Type() @@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) if err == nil { val.SetFloat(f) } else { - return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: wrapStrconvNumError(err), + }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) i, err := jn.Float64() if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) + return newDecodeError(name, &ParseError{ + Expected: val, + Value: data, + Err: err, + }) } val.SetFloat(i) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataKind := getKind(dataVal) @@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value case dataKind == reflect.Complex64: val.SetComplex(dataVal.Complex()) default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } return nil } -func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error { valType := val.Type() valKeyType := valType.Key() valElemType := valType.Elem() @@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er fallthrough default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } } @@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // to the map value. v := dataVal.Field(i) if !v.Type().AssignableTo(valMap.Type().Elem()) { - return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()), + ) } tagValue := f.Tag.Get(d.config.TagName) @@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re continue } + // If "omitzero" is specified in the tag, it ignores zero values. + if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() { + continue + } + // If "squash" is specified in the tag, we squash the field down. squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption) if squash { @@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // The final type must be a struct if v.Kind() != reflect.Struct { - return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("cannot squash non-struct type %q", v.Type()), + ) } } else { if strings.Index(tagValue[index+1:], "remain") != -1 { if v.Kind() != reflect.Map { - return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type()) + return newDecodeError( + name+"."+f.Name, + fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()), + ) } ptr := v.MapRange() @@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re return nil } -func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { +func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) { // If the input data is nil, then we want to just set the output // pointer to be nil as well. isNil := data == nil @@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b return false, nil } -func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error { // Create an element of the concrete (non pointer) type and decode // into that. Then set the value of the pointer to this type. dataVal := reflect.Indirect(reflect.ValueOf(data)) if val.Type() != dataVal.Type() { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) + return newDecodeError(name, &UnconvertibleTypeError{ + Expected: val, + Value: data, + }) } val.Set(dataVal) return nil } -func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return nil } // Create slice of maps of other sizes - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: return d.decodeSlice(name, []byte(dataVal.String()), val) @@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string slice. default: // Just re-try this function with data as a slice. - return d.decodeSlice(name, []interface{}{data}, val) + return d.decodeSlice(name, []any{data}, val) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } // If the input value is nil, then don't allocate since empty != nil @@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) dataValKind := dataVal.Kind() valType := val.Type() @@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) // and "lift" it into it. i.e. a string becomes a string array. default: // Just re-try this function with data as a slice. - return d.decodeArray(name, []interface{}{data}, val) + return d.decodeArray(name, []any{data}, val) } } - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) + return newDecodeError(name, + fmt.Errorf("source data must be an array or slice, got %s", dataValKind)) } if dataVal.Len() > arrayType.Len() { - return fmt.Errorf( - "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + return newDecodeError(name, + fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len())) } // Make a new array to hold our result, same size as the original data. @@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) return errors.Join(errs...) } -func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) // If the type of the value to write to and the data match directly, @@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) // as an intermediary. // Make a new map to hold our result - mapType := reflect.TypeOf((map[string]interface{})(nil)) + mapType := reflect.TypeOf((map[string]any)(nil)) mval := reflect.MakeMap(mapType) // Creating a pointer to a map so that other methods can completely @@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) return result default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + return newDecodeError(name, + fmt.Errorf("expected a map or struct, got %q", dataValKind)) } } func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { dataValType := dataVal.Type() if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { - return fmt.Errorf( - "'%s' needs a map with string keys, has '%s' keys", - name, dataValType.Key().Kind()) + return newDecodeError(name, + fmt.Errorf("needs a map with string keys, has %q keys", kind)) } dataValKeys := make(map[reflect.Value]struct{}) - dataValKeysUnused := make(map[interface{}]struct{}) + dataValKeysUnused := make(map[any]struct{}) for _, dataValKey := range dataVal.MapKeys() { dataValKeys[dataValKey] = struct{}{} dataValKeysUnused[dataValKey.Interface()] = struct{}{} } - targetValKeysUnused := make(map[interface{}]struct{}) + targetValKeysUnused := make(map[any]struct{}) var errs []error @@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e structs = append(structs, fieldVal.Elem().Elem()) } default: - errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + errs = append(errs, newDecodeError( + name+"."+fieldType.Name, + fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()), + )) } continue } @@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e if !rawMapVal.IsValid() { // There was no matching key in the map for the value in // the struct. Remember it for potential errors and metadata. - targetValKeysUnused[fieldName] = struct{}{} + if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) { + targetValKeysUnused[fieldName] = struct{}{} + } continue } } @@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // we put the unused keys directly into the remain field. if remainField != nil && len(dataValKeysUnused) > 0 { // Build a map of only the unused values - remain := map[interface{}]interface{}{} + remain := map[any]any{} for key := range dataValKeysUnused { remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() } @@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")), + )) } if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { @@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } sort.Strings(keys) - err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) - errs = append(errs, err) + errs = append(errs, newDecodeError( + name, + fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")), + )) } if err := errors.Join(errs...); err != nil { diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel index 8766d38f..475699b5 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel @@ -13,6 +13,7 @@ go_library( deps = [ "@org_golang_google_protobuf//compiler/protogen", "@org_golang_google_protobuf//proto", + "@org_golang_google_protobuf//types/descriptorpb", "@org_golang_google_protobuf//types/pluginpb", ], ) diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go index 18c6cf07..dd476abf 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go @@ -2,18 +2,25 @@ package codegenerator import ( "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/pluginpb" ) func supportedCodeGeneratorFeatures() uint64 { - // Enable support for optional keyword in proto3. - return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) + // Enable support for Protobuf Editions + return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS) +} + +func supportedEditions() (descriptorpb.Edition, descriptorpb.Edition) { + // Declare support for edition 2023 only + return descriptorpb.Edition_EDITION_2023, descriptorpb.Edition_EDITION_2023 } // SetSupportedFeaturesOnPluginGen sets supported proto3 features // on protogen.Plugin. func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) { gen.SupportedFeatures = supportedCodeGeneratorFeatures() + gen.SupportedEditionsMinimum, gen.SupportedEditionsMaximum = supportedEditions() } // SetSupportedFeaturesOnCodeGeneratorResponse sets supported proto3 features @@ -21,4 +28,7 @@ func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) { func SetSupportedFeaturesOnCodeGeneratorResponse(resp *pluginpb.CodeGeneratorResponse) { sf := supportedCodeGeneratorFeatures() resp.SupportedFeatures = &sf + minE, maxE := supportedEditions() + minEN, maxEN := int32(minE.Number()), int32(maxE.Number()) + resp.MinimumEdition, resp.MaximumEdition = &minEN, &maxEN } diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel index 28b6e258..84b73d08 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel @@ -19,7 +19,7 @@ go_library( "//internal/descriptor/openapiconfig", "//internal/httprule", "//protoc-gen-openapiv2/options", - "@in_gopkg_yaml_v3//:yaml_v3", + "@in_yaml_go_yaml_v3//:yaml", "@org_golang_google_genproto_googleapis_api//annotations", "@org_golang_google_grpc//grpclog", "@org_golang_google_protobuf//compiler/protogen", diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go index 4f4a31c1..dea0605c 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/apiconfig" + "go.yaml.in/yaml/v3" "google.golang.org/protobuf/encoding/protojson" - "gopkg.in/yaml.v3" ) func loadGrpcAPIServiceFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*apiconfig.GrpcAPIService, error) { diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go index d48a7c81..8b540165 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go @@ -6,8 +6,8 @@ import ( "os" "github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapiconfig" + "go.yaml.in/yaml/v3" "google.golang.org/protobuf/encoding/protojson" - "gopkg.in/yaml.v3" ) func loadOpenAPIConfigFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*openapiconfig.OpenAPIConfig, error) { diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel index 06537035..e6e48130 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel @@ -34,3 +34,20 @@ go_proto_compiler( "@org_golang_google_grpc//metadata:go_default_library", ], ) + +go_proto_compiler( + name = "go_gen_grpc_gateway_opaque", + options = [ + "paths=source_relative", + "use_opaque_api=true", + ], + plugin = ":protoc-gen-grpc-gateway", + suffix = ".pb.gw.go", + visibility = ["//visibility:public"], + deps = [ + "//runtime:go_default_library", + "//utilities:go_default_library", + "@org_golang_google_grpc//grpclog:go_default_library", + "@org_golang_google_grpc//metadata:go_default_library", + ], +) diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go index 819cbf55..5a58625c 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go @@ -22,11 +22,12 @@ type generator struct { registerFuncSuffix string allowPatchFeature bool standalone bool + useOpaqueAPI bool } // New returns a new generator which generates grpc gateway files. func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix string, - allowPatchFeature, standalone bool) gen.Generator { + allowPatchFeature, standalone bool, useOpaqueAPI bool) gen.Generator { var imports []descriptor.GoPackage for _, pkgpath := range []string{ "context", @@ -66,6 +67,7 @@ func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix st registerFuncSuffix: registerFuncSuffix, allowPatchFeature: allowPatchFeature, standalone: standalone, + useOpaqueAPI: useOpaqueAPI, } } @@ -132,6 +134,7 @@ func (g *generator) generate(file *descriptor.File) (string, error) { UseRequestContext: g.useRequestContext, RegisterFuncSuffix: g.registerFuncSuffix, AllowPatchFeature: g.allowPatchFeature, + UseOpaqueAPI: g.useOpaqueAPI, } if g.reg != nil { params.OmitPackageDoc = g.reg.GetOmitPackageDoc() diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go index 80df6a0b..b647e1df 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go @@ -21,12 +21,14 @@ type param struct { RegisterFuncSuffix string AllowPatchFeature bool OmitPackageDoc bool + UseOpaqueAPI bool } type binding struct { *descriptor.Binding Registry *descriptor.Registry AllowPatchFeature bool + UseOpaqueAPI bool } // GetBodyFieldPath returns the binding body's field path. @@ -147,6 +149,7 @@ type trailerParams struct { Services []*descriptor.Service UseRequestContext bool RegisterFuncSuffix string + UseOpaqueAPI bool } func applyTemplate(p param, reg *descriptor.Registry) (string, error) { @@ -182,6 +185,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) { Binding: b, Registry: reg, AllowPatchFeature: p.AllowPatchFeature, + UseOpaqueAPI: p.UseOpaqueAPI, }); err != nil { return "", err } @@ -191,6 +195,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) { Binding: b, Registry: reg, AllowPatchFeature: p.AllowPatchFeature, + UseOpaqueAPI: p.UseOpaqueAPI, }); err != nil { return "", err } @@ -208,6 +213,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) { Services: targetServices, UseRequestContext: p.UseRequestContext, RegisterFuncSuffix: p.RegisterFuncSuffix, + UseOpaqueAPI: p.UseOpaqueAPI, } // Local if err := localTrailerTemplate.Execute(w, tp); err != nil { @@ -335,6 +341,7 @@ func request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }}(ct _ = template.Must(handlerTemplate.New("client-rpc-request-func").Funcs(funcMap).Parse(` {{ $AllowPatchFeature := .AllowPatchFeature }} +{{ $UseOpaqueAPI := .UseOpaqueAPI }} {{ if .HasQueryParam }} var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ .QueryParamFilter }} {{ end }} @@ -365,20 +372,53 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ {{printf "%s" $protoReq }} {{- end }} {{- if not $isFieldMask }} + {{- if $UseOpaqueAPI }} + var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}} + if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + {{- if eq "*" .GetBodyFieldPath }} + protoReq = bodyData + {{- else }} + protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}()) + {{- end }} + {{- else }} if err := marshaler.NewDecoder(req.Body).Decode(&{{.Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path}}); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } + {{- end }} if req.Body != nil { _, _ = io.Copy(io.Discard, req.Body) } {{- end }} {{- if $isFieldMask }} + {{- if $UseOpaqueAPI }} + var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}} + if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + {{- if eq "*" .GetBodyFieldPath }} + protoReq = bodyData + {{- else }} + protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}()) + {{- end }} + {{- else }} if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } + {{- end }} if req.Body != nil { _, _ = io.Copy(io.Discard, req.Body) } + {{- if $UseOpaqueAPI }} + if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.Set{{ .FieldMaskField }}(fieldMask) + } + } + {{- else }} if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 { if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) @@ -387,6 +427,7 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ } } {{- end }} + {{- end }} {{- else }} if req.Body != nil { _, _ = io.Copy(io.Discard, req.Body) @@ -421,19 +462,35 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ {{- if ne "" $protoReq }} {{ printf "%s" $protoReq }} {{- end}} + {{- if $UseOpaqueAPI }} + converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }}) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err) + } + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }}) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }}) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err) } + {{- end }} {{- end}} {{- if and $enum $param.IsRepeated }} s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es)) for i, v := range es { s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path}}(v) } + {{- if $UseOpaqueAPI }} + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s + {{- end }} {{- else if $enum}} + {{- if $UseOpaqueAPI }} + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e) + {{- end }} {{- end}} {{- end }} {{- end }} @@ -524,6 +581,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index _ = template.Must(localHandlerTemplate.New("local-client-rpc-request-func").Funcs(funcMap).Parse(` {{ $AllowPatchFeature := .AllowPatchFeature }} +{{ $UseOpaqueAPI := .UseOpaqueAPI }} {{ template "local-request-func-signature" . }} { var ( protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}} @@ -551,14 +609,47 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index {{ printf "%s" $protoReq }} {{- end }} {{- if not $isFieldMask }} + {{- if $UseOpaqueAPI }} + var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}} + if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + {{- if eq "*" .GetBodyFieldPath }} + protoReq = bodyData + {{- else }} + protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}()) + {{- end }} + {{- else }} if err := marshaler.NewDecoder(req.Body).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } {{- end }} + {{- end }} {{- if $isFieldMask }} + {{- if $UseOpaqueAPI }} + var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}} + if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + {{- if eq "*" .GetBodyFieldPath }} + protoReq = bodyData + {{- else }} + protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}()) + {{- end }} + {{- else }} if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } + {{- end }} + {{- if $UseOpaqueAPI }} + if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 { + if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } else { + protoReq.Set{{ .FieldMaskField }}(fieldMask) + } + } + {{- else }} if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 { if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) @@ -567,6 +658,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index } } {{- end }} + {{- end }} {{- end }} {{- if .PathParams}} {{- $binding := .}} @@ -596,20 +688,36 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index {{- $protoReq := $param.AssignableExprPrep "protoReq" $binding.Method.Service.File.GoPkg.Path -}} {{- if ne "" $protoReq }} {{ printf "%s" $protoReq }} - {{- end }} + {{- end}} + {{- if $UseOpaqueAPI }} + converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }}) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err) + } + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }}) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }}) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q" }}, err) } + {{- end }} {{- end}} {{- if and $enum $param.IsRepeated }} s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es)) for i, v := range es { s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}(v) } + {{- if $UseOpaqueAPI }} + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s + {{- end }} {{- else if $enum }} + {{- if $UseOpaqueAPI }} + protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)) + {{- else }} {{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e) + {{- end }} {{- end }} {{- end }} {{- end }} @@ -689,6 +797,7 @@ func Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}Server(ctx context.Cont trailerTemplate = template.Must(template.New("trailer").Funcs(funcMap).Parse(` {{ $UseRequestContext := .UseRequestContext }} +{{ $UseOpaqueAPI := .UseOpaqueAPI }} {{range $svc := .Services}} // Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}FromEndpoint is same as Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }} but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. @@ -782,7 +891,15 @@ type response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }} struct { func (m response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }}) XXX_ResponseBody() interface{} { response := m.{{ $m.ResponseType.GetName }} + {{- if $UseOpaqueAPI }} + {{- if eq "*" $b.ResponseBody.FieldPath.String }} + return response + {{- else }} + return response.Get{{ $b.ResponseBody.FieldPath.String | camelIdentifier }}() + {{- end }} + {{- else }} return {{ $b.ResponseBody.AssignableExpr "response" $m.Service.File.GoPkg.Path }} + {{- end }} } {{ end }} {{ end }} diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go index 086a4624..862a8fc0 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go @@ -36,6 +36,7 @@ var ( versionFlag = flag.Bool("version", false, "print the current version") warnOnUnboundMethods = flag.Bool("warn_on_unbound_methods", false, "emit a warning message if an RPC method has no HttpRule annotation") generateUnboundMethods = flag.Bool("generate_unbound_methods", false, "generate proxy methods even for RPC methods that have no HttpRule annotation") + useOpaqueAPI = flag.Bool("use_opaque_api", false, "generate code compatible with the new Opaque API instead of the older Open Struct API") _ = flag.Bool("logtostderr", false, "Legacy glog compatibility. This flag is a no-op, you can safely remove it") ) @@ -80,7 +81,7 @@ func main() { codegenerator.SetSupportedFeaturesOnPluginGen(gen) - generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone) + generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone, *useOpaqueAPI) if grpclog.V(1) { grpclog.Infof("Parsing code generator request") diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel index 7be6a90e..cef5f808 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel @@ -20,7 +20,7 @@ go_library( "//internal/descriptor", "//internal/generator", "//protoc-gen-openapiv2/options", - "@in_gopkg_yaml_v3//:yaml_v3", + "@in_yaml_go_yaml_v3//:yaml", "@org_golang_google_genproto_googleapis_api//annotations", "@org_golang_google_genproto_googleapis_api//visibility", "@org_golang_google_genproto_googleapis_rpc//status", @@ -59,7 +59,7 @@ go_test( "//protoc-gen-openapiv2/options", "//runtime", "@com_github_google_go_cmp//cmp", - "@in_gopkg_yaml_v3//:yaml_v3", + "@in_yaml_go_yaml_v3//:yaml", "@org_golang_google_genproto_googleapis_api//annotations", "@org_golang_google_genproto_googleapis_api//visibility", "@org_golang_google_protobuf//encoding/protojson", diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go index 6f0faa8e..30cf7dac 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go @@ -5,7 +5,7 @@ import ( "errors" "io" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) type Format string diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go index 6795cf71..69f69b9a 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go @@ -13,6 +13,7 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor" gen "github.com/grpc-ecosystem/grpc-gateway/v2/internal/generator" openapioptions "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" + "go.yaml.in/yaml/v3" statuspb "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/grpclog" "google.golang.org/protobuf/proto" @@ -20,7 +21,6 @@ import ( "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/pluginpb" - "gopkg.in/yaml.v3" ) var errNoTargetService = errors.New("no target service defined in the file") diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go index 84831c28..6265da8f 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go @@ -771,8 +771,8 @@ func filterOutExcludedFields(fields []string, excluded []descriptor.Parameter) [ return filtered } -// schemaOfField returns a OpenAPI Schema Object for a protobuf field. -func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject { +// schemaOfFieldBase returns a base Schema Object for a protobuf field. +func schemaOfFieldBase(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject { const ( singular = 0 array = 1 @@ -828,7 +828,7 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o } } - ret := openapiSchemaObject{} + var ret openapiSchemaObject switch aggregate { case array: @@ -854,6 +854,12 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o Properties: props, } } + return ret +} + +// schemaOfField returns a OpenAPI Schema Object for a protobuf field. +func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject { + ret := schemaOfFieldBase(f, reg, refs) if j, err := getFieldOpenAPIOption(reg, f); err == nil { updateswaggerObjectFromJSONSchema(&ret, j, reg, f) @@ -1037,7 +1043,7 @@ func resolveFullyQualifiedNameToOpenAPINames(messages []string, namingStrategy s return strategyFn(messages) } -var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.]*)([^}]*)}") +var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.-]*)([^}]*)}") // templateToParts splits a URL template into path segments for use by `partsToOpenAPIPath` and `partsToRegexpMap`. // @@ -1534,10 +1540,17 @@ func renderServices(services []*descriptor.Service, paths *openapiPathsObject, r } // Align pathParams with body field path. pathParams := subPathParams(bodyField.Name, b.PathParams) - var err error - schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams) - if err != nil { - return err + + if len(pathParams) == 0 { + // When there are no path parameters, we only need the base schema of the field. + // https://github.com/grpc-ecosystem/grpc-gateway/issues/3058 + schema = schemaOfFieldBase(bodyField.Target, reg, customRefs) + } else { + var err error + schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams) + if err != nil { + return err + } } if schema.Title != "" { desc = mergeDescription(schema) diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go index 02c85784..db9be4de 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) type param struct { diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel index a65d88eb..04b4bebf 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel @@ -27,6 +27,7 @@ go_library( "//internal/httprule", "//utilities", "@org_golang_google_genproto_googleapis_api//httpbody", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//grpclog", "@org_golang_google_grpc//health/grpc_health_v1", diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go index 2f2b3424..00b2228a 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go @@ -201,13 +201,13 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM if timeout != 0 { ctx, _ = context.WithTimeout(ctx, timeout) } - if len(pairs) == 0 { - return ctx, nil, nil - } md := metadata.Pairs(pairs...) for _, mda := range mux.metadataAnnotators { md = metadata.Join(md, mda(ctx, req)) } + if len(md) == 0 { + return ctx, nil, nil + } return ctx, md, nil } diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go index 8376d1e0..3d070630 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go @@ -66,7 +66,7 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error { var ( // protoMessageType is stored to prevent constant lookup of the same type at runtime. - protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() + protoMessageType = reflect.TypeFor[proto.Message]() ) // marshalNonProto marshals a non-message field of a protobuf message. @@ -325,9 +325,9 @@ type protoEnum interface { EnumDescriptor() ([]byte, []int) } -var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem() +var typeProtoEnum = reflect.TypeFor[protoEnum]() -var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() +var typeProtoMessage = reflect.TypeFor[proto.Message]() // Delimiter for newline encoded JSON streams. func (j *JSONPb) Delimiter() []byte { diff --git a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go index 19255ec4..3eb16167 100644 --- a/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go +++ b/event-processor/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule" + "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/health/grpc_health_v1" @@ -281,12 +282,19 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin http.MethodGet, endpointPath, func(w http.ResponseWriter, r *http.Request, _ map[string]string, ) { _, outboundMarshaler := MarshalerForRequest(s, r) + annotatedContext, err := AnnotateContext(r.Context(), s, r, grpc_health_v1.Health_Check_FullMethodName, WithHTTPPathPattern(endpointPath)) + if err != nil { + s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err) + return + } - resp, err := healthCheckClient.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{ + var md ServerMetadata + resp, err := healthCheckClient.Check(annotatedContext, &grpc_health_v1.HealthCheckRequest{ Service: r.URL.Query().Get("service"), - }) + }, grpc.Header(&md.HeaderMD), grpc.Trailer(&md.TrailerMD)) + annotatedContext = NewServerMetadataContext(annotatedContext, md) if err != nil { - s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err) + s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err) return } @@ -300,7 +308,7 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin err = status.Error(codes.NotFound, resp.String()) } - s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err) + s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err) return } diff --git a/event-processor/vendor/github.com/hashicorp/hcl/.gitignore b/event-processor/vendor/github.com/hashicorp/hcl/.gitignore deleted file mode 100644 index 15586a2b..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -y.output - -# ignore intellij files -.idea -*.iml -*.ipr -*.iws - -*.test diff --git a/event-processor/vendor/github.com/hashicorp/hcl/.travis.yml b/event-processor/vendor/github.com/hashicorp/hcl/.travis.yml deleted file mode 100644 index cb63a321..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -sudo: false - -language: go - -go: - - 1.x - - tip - -branches: - only: - - master - -script: make test diff --git a/event-processor/vendor/github.com/hashicorp/hcl/LICENSE b/event-processor/vendor/github.com/hashicorp/hcl/LICENSE deleted file mode 100644 index c33dcc7c..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/event-processor/vendor/github.com/hashicorp/hcl/Makefile b/event-processor/vendor/github.com/hashicorp/hcl/Makefile deleted file mode 100644 index 84fd743f..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -TEST?=./... - -default: test - -fmt: generate - go fmt ./... - -test: generate - go get -t ./... - go test $(TEST) $(TESTARGS) - -generate: - go generate ./... - -updatedeps: - go get -u golang.org/x/tools/cmd/stringer - -.PHONY: default generate test updatedeps diff --git a/event-processor/vendor/github.com/hashicorp/hcl/README.md b/event-processor/vendor/github.com/hashicorp/hcl/README.md deleted file mode 100644 index c8223326..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# HCL - -[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl) - -HCL (HashiCorp Configuration Language) is a configuration language built -by HashiCorp. The goal of HCL is to build a structured configuration language -that is both human and machine friendly for use with command-line tools, but -specifically targeted towards DevOps tools, servers, etc. - -HCL is also fully JSON compatible. That is, JSON can be used as completely -valid input to a system expecting HCL. This helps makes systems -interoperable with other systems. - -HCL is heavily inspired by -[libucl](https://github.com/vstakhov/libucl), -nginx configuration, and others similar. - -## Why? - -A common question when viewing HCL is to ask the question: why not -JSON, YAML, etc.? - -Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com) -used a variety of configuration languages from full programming languages -such as Ruby to complete data structure languages such as JSON. What we -learned is that some people wanted human-friendly configuration languages -and some people wanted machine-friendly languages. - -JSON fits a nice balance in this, but is fairly verbose and most -importantly doesn't support comments. With YAML, we found that beginners -had a really hard time determining what the actual structure was, and -ended up guessing more often than not whether to use a hyphen, colon, etc. -in order to represent some configuration key. - -Full programming languages such as Ruby enable complex behavior -a configuration language shouldn't usually allow, and also forces -people to learn some set of Ruby. - -Because of this, we decided to create our own configuration language -that is JSON-compatible. Our configuration language (HCL) is designed -to be written and modified by humans. The API for HCL allows JSON -as an input so that it is also machine-friendly (machines can generate -JSON instead of trying to generate HCL). - -Our goal with HCL is not to alienate other configuration languages. -It is instead to provide HCL as a specialized language for our tools, -and JSON as the interoperability layer. - -## Syntax - -For a complete grammar, please see the parser itself. A high-level overview -of the syntax and grammar is listed here. - - * Single line comments start with `#` or `//` - - * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments - are not allowed. A multi-line comment (also known as a block comment) - terminates at the first `*/` found. - - * Values are assigned with the syntax `key = value` (whitespace doesn't - matter). The value can be any primitive: a string, number, boolean, - object, or list. - - * Strings are double-quoted and can contain any UTF-8 characters. - Example: `"Hello, World"` - - * Multi-line strings start with `<- - echo %Path% - - go version - - go env - - go get -t ./... - -build_script: -- cmd: go test -v ./... diff --git a/event-processor/vendor/github.com/hashicorp/hcl/decoder.go b/event-processor/vendor/github.com/hashicorp/hcl/decoder.go deleted file mode 100644 index bed9ebbe..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/decoder.go +++ /dev/null @@ -1,729 +0,0 @@ -package hcl - -import ( - "errors" - "fmt" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" - "github.com/hashicorp/hcl/hcl/token" -) - -// This is the tag to use with structures to have settings for HCL -const tagName = "hcl" - -var ( - // nodeType holds a reference to the type of ast.Node - nodeType reflect.Type = findNodeType() -) - -// Unmarshal accepts a byte slice as input and writes the -// data to the value pointed to by v. -func Unmarshal(bs []byte, v interface{}) error { - root, err := parse(bs) - if err != nil { - return err - } - - return DecodeObject(v, root) -} - -// Decode reads the given input and decodes it into the structure -// given by `out`. -func Decode(out interface{}, in string) error { - obj, err := Parse(in) - if err != nil { - return err - } - - return DecodeObject(out, obj) -} - -// DecodeObject is a lower-level version of Decode. It decodes a -// raw Object into the given output. -func DecodeObject(out interface{}, n ast.Node) error { - val := reflect.ValueOf(out) - if val.Kind() != reflect.Ptr { - return errors.New("result must be a pointer") - } - - // If we have the file, we really decode the root node - if f, ok := n.(*ast.File); ok { - n = f.Node - } - - var d decoder - return d.decode("root", n, val.Elem()) -} - -type decoder struct { - stack []reflect.Kind -} - -func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error { - k := result - - // If we have an interface with a valid value, we use that - // for the check. - if result.Kind() == reflect.Interface { - elem := result.Elem() - if elem.IsValid() { - k = elem - } - } - - // Push current onto stack unless it is an interface. - if k.Kind() != reflect.Interface { - d.stack = append(d.stack, k.Kind()) - - // Schedule a pop - defer func() { - d.stack = d.stack[:len(d.stack)-1] - }() - } - - switch k.Kind() { - case reflect.Bool: - return d.decodeBool(name, node, result) - case reflect.Float32, reflect.Float64: - return d.decodeFloat(name, node, result) - case reflect.Int, reflect.Int32, reflect.Int64: - return d.decodeInt(name, node, result) - case reflect.Interface: - // When we see an interface, we make our own thing - return d.decodeInterface(name, node, result) - case reflect.Map: - return d.decodeMap(name, node, result) - case reflect.Ptr: - return d.decodePtr(name, node, result) - case reflect.Slice: - return d.decodeSlice(name, node, result) - case reflect.String: - return d.decodeString(name, node, result) - case reflect.Struct: - return d.decodeStruct(name, node, result) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()), - } - } -} - -func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.BOOL { - v, err := strconv.ParseBool(n.Token.Text) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v)) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { - v, err := strconv.ParseFloat(n.Token.Text, 64) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - v, err := strconv.ParseInt(n.Token.Text, 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - case token.STRING: - v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error { - // When we see an ast.Node, we retain the value to enable deferred decoding. - // Very useful in situations where we want to preserve ast.Node information - // like Pos - if result.Type() == nodeType && result.CanSet() { - result.Set(reflect.ValueOf(node)) - return nil - } - - var set reflect.Value - redecode := true - - // For testing types, ObjectType should just be treated as a list. We - // set this to a temporary var because we want to pass in the real node. - testNode := node - if ot, ok := node.(*ast.ObjectType); ok { - testNode = ot.List - } - - switch n := testNode.(type) { - case *ast.ObjectList: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items)) - set = result - } - case *ast.ObjectType: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 1) - set = result - } - case *ast.ListType: - var temp []interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 0) - set = result - case *ast.LiteralType: - switch n.Token.Type { - case token.BOOL: - var result bool - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.FLOAT: - var result float64 - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.NUMBER: - var result int - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.STRING, token.HEREDOC: - set = reflect.Indirect(reflect.New(reflect.TypeOf(""))) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node), - } - } - default: - return fmt.Errorf( - "%s: cannot decode into interface: %T", - name, node) - } - - // Set the result to what its supposed to be, then reset - // result so we don't reflect into this method anymore. - result.Set(set) - - if redecode { - // Revisit the node so that we can use the newly instantiated - // thing and populate it. - if err := d.decode(name, node, result); err != nil { - return err - } - } - - return nil -} - -func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error { - if item, ok := node.(*ast.ObjectItem); ok { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - n, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for map (%T)", name, node), - } - } - - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - - resultType := result.Type() - resultElemType := resultType.Elem() - resultKeyType := resultType.Key() - if resultKeyType.Kind() != reflect.String { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Make a map if it is nil - resultMap := result - if result.IsNil() { - resultMap = reflect.MakeMap( - reflect.MapOf(resultKeyType, resultElemType)) - } - - // Go through each element and decode it. - done := make(map[string]struct{}) - for _, item := range n.Items { - if item.Val == nil { - continue - } - - // github.com/hashicorp/terraform/issue/5740 - if len(item.Keys) == 0 { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Get the key we're dealing with, which is the first item - keyStr := item.Keys[0].Token.Value().(string) - - // If we've already processed this key, then ignore it - if _, ok := done[keyStr]; ok { - continue - } - - // Determine the value. If we have more than one key, then we - // get the objectlist of only these keys. - itemVal := item.Val - if len(item.Keys) > 1 { - itemVal = n.Filter(keyStr) - done[keyStr] = struct{}{} - } - - // Make the field name - fieldName := fmt.Sprintf("%s.%s", name, keyStr) - - // Get the key/value as reflection values - key := reflect.ValueOf(keyStr) - val := reflect.Indirect(reflect.New(resultElemType)) - - // If we have a pre-existing value in the map, use that - oldVal := resultMap.MapIndex(key) - if oldVal.IsValid() { - val.Set(oldVal) - } - - // Decode! - if err := d.decode(fieldName, itemVal, val); err != nil { - return err - } - - // Set the value on the map - resultMap.SetMapIndex(key, val) - } - - // Set the final map if we can - set.Set(resultMap) - return nil -} - -func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error { - // Create an element of the concrete (non pointer) type and decode - // into that. Then set the value of the pointer to this type. - resultType := result.Type() - resultElemType := resultType.Elem() - val := reflect.New(resultElemType) - if err := d.decode(name, node, reflect.Indirect(val)); err != nil { - return err - } - - result.Set(val) - return nil -} - -func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error { - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - // Create the slice if it isn't nil - resultType := result.Type() - resultElemType := resultType.Elem() - if result.IsNil() { - resultSliceType := reflect.SliceOf(resultElemType) - result = reflect.MakeSlice( - resultSliceType, 0, 0) - } - - // Figure out the items we'll be copying into the slice - var items []ast.Node - switch n := node.(type) { - case *ast.ObjectList: - items = make([]ast.Node, len(n.Items)) - for i, item := range n.Items { - items[i] = item - } - case *ast.ObjectType: - items = []ast.Node{n} - case *ast.ListType: - items = n.List - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("unknown slice type: %T", node), - } - } - - for i, item := range items { - fieldName := fmt.Sprintf("%s[%d]", name, i) - - // Decode - val := reflect.Indirect(reflect.New(resultElemType)) - - // if item is an object that was decoded from ambiguous JSON and - // flattened, make sure it's expanded if it needs to decode into a - // defined structure. - item := expandObject(item, val) - - if err := d.decode(fieldName, item, val); err != nil { - return err - } - - // Append it onto the slice - result = reflect.Append(result, val) - } - - set.Set(result) - return nil -} - -// expandObject detects if an ambiguous JSON object was flattened to a List which -// should be decoded into a struct, and expands the ast to properly deocode. -func expandObject(node ast.Node, result reflect.Value) ast.Node { - item, ok := node.(*ast.ObjectItem) - if !ok { - return node - } - - elemType := result.Type() - - // our target type must be a struct - switch elemType.Kind() { - case reflect.Ptr: - switch elemType.Elem().Kind() { - case reflect.Struct: - //OK - default: - return node - } - case reflect.Struct: - //OK - default: - return node - } - - // A list value will have a key and field name. If it had more fields, - // it wouldn't have been flattened. - if len(item.Keys) != 2 { - return node - } - - keyToken := item.Keys[0].Token - item.Keys = item.Keys[1:] - - // we need to un-flatten the ast enough to decode - newNode := &ast.ObjectItem{ - Keys: []*ast.ObjectKey{ - &ast.ObjectKey{ - Token: keyToken, - }, - }, - Val: &ast.ObjectType{ - List: &ast.ObjectList{ - Items: []*ast.ObjectItem{item}, - }, - }, - } - - return newNode -} - -func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type())) - return nil - case token.STRING, token.HEREDOC: - result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type for string %T", name, node), - } -} - -func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error { - var item *ast.ObjectItem - if it, ok := node.(*ast.ObjectItem); ok { - item = it - node = it.Val - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - // Handle the special case where the object itself is a literal. Previously - // the yacc parser would always ensure top-level elements were arrays. The new - // parser does not make the same guarantees, thus we need to convert any - // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok && item != nil { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - list, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node), - } - } - - // This slice will keep track of all the structs we'll be decoding. - // There can be more than one struct if there are embedded structs - // that are squashed. - structs := make([]reflect.Value, 1, 5) - structs[0] = result - - // Compile the list of all the fields that we're going to be decoding - // from all the structs. - type field struct { - field reflect.StructField - val reflect.Value - } - fields := []field{} - for len(structs) > 0 { - structVal := structs[0] - structs = structs[1:] - - structType := structVal.Type() - for i := 0; i < structType.NumField(); i++ { - fieldType := structType.Field(i) - tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") - - // Ignore fields with tag name "-" - if tagParts[0] == "-" { - continue - } - - if fieldType.Anonymous { - fieldKind := fieldType.Type.Kind() - if fieldKind != reflect.Struct { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unsupported type to struct: %s", - fieldType.Name, fieldKind), - } - } - - // We have an embedded field. We "squash" the fields down - // if specified in the tag. - squash := false - for _, tag := range tagParts[1:] { - if tag == "squash" { - squash = true - break - } - } - - if squash { - structs = append( - structs, result.FieldByName(fieldType.Name)) - continue - } - } - - // Normal struct field, store it away - fields = append(fields, field{fieldType, structVal.Field(i)}) - } - } - - usedKeys := make(map[string]struct{}) - decodedFields := make([]string, 0, len(fields)) - decodedFieldsVal := make([]reflect.Value, 0) - unusedKeysVal := make([]reflect.Value, 0) - for _, f := range fields { - field, fieldValue := f.field, f.val - if !fieldValue.IsValid() { - // This should never happen - panic("field is not valid") - } - - // If we can't set the field, then it is unexported or something, - // and we just continue onwards. - if !fieldValue.CanSet() { - continue - } - - fieldName := field.Name - - tagValue := field.Tag.Get(tagName) - tagParts := strings.SplitN(tagValue, ",", 2) - if len(tagParts) >= 2 { - switch tagParts[1] { - case "decodedFields": - decodedFieldsVal = append(decodedFieldsVal, fieldValue) - continue - case "key": - if item == nil { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: %s asked for 'key', impossible", - name, fieldName), - } - } - - fieldValue.SetString(item.Keys[0].Token.Value().(string)) - continue - case "unusedKeys": - unusedKeysVal = append(unusedKeysVal, fieldValue) - continue - } - } - - if tagParts[0] != "" { - fieldName = tagParts[0] - } - - // Determine the element we'll use to decode. If it is a single - // match (only object with the field), then we decode it exactly. - // If it is a prefix match, then we decode the matches. - filter := list.Filter(fieldName) - - prefixMatches := filter.Children() - matches := filter.Elem() - if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { - continue - } - - // Track the used key - usedKeys[fieldName] = struct{}{} - - // Create the field name and decode. We range over the elements - // because we actually want the value. - fieldName = fmt.Sprintf("%s.%s", name, fieldName) - if len(prefixMatches.Items) > 0 { - if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { - return err - } - } - for _, match := range matches.Items { - var decodeNode ast.Node = match.Val - if ot, ok := decodeNode.(*ast.ObjectType); ok { - decodeNode = &ast.ObjectList{Items: ot.List.Items} - } - - if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { - return err - } - } - - decodedFields = append(decodedFields, field.Name) - } - - if len(decodedFieldsVal) > 0 { - // Sort it so that it is deterministic - sort.Strings(decodedFields) - - for _, v := range decodedFieldsVal { - v.Set(reflect.ValueOf(decodedFields)) - } - } - - return nil -} - -// findNodeType returns the type of ast.Node -func findNodeType() reflect.Type { - var nodeContainer struct { - Node ast.Node - } - value := reflect.ValueOf(nodeContainer).FieldByName("Node") - return value.Type() -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl.go deleted file mode 100644 index 575a20b5..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl.go +++ /dev/null @@ -1,11 +0,0 @@ -// Package hcl decodes HCL into usable Go structures. -// -// hcl input can come in either pure HCL format or JSON format. -// It can be parsed into an AST, and then decoded into a structure, -// or it can be decoded directly from a string into a structure. -// -// If you choose to parse HCL into a raw AST, the benefit is that you -// can write custom visitor implementations to implement custom -// semantic checks. By default, HCL does not perform any semantic -// checks. -package hcl diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go deleted file mode 100644 index 6e5ef654..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package ast declares the types used to represent syntax trees for HCL -// (HashiCorp Configuration Language) -package ast - -import ( - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/token" -) - -// Node is an element in the abstract syntax tree. -type Node interface { - node() - Pos() token.Pos -} - -func (File) node() {} -func (ObjectList) node() {} -func (ObjectKey) node() {} -func (ObjectItem) node() {} -func (Comment) node() {} -func (CommentGroup) node() {} -func (ObjectType) node() {} -func (LiteralType) node() {} -func (ListType) node() {} - -// File represents a single HCL file -type File struct { - Node Node // usually a *ObjectList - Comments []*CommentGroup // list of all comments in the source -} - -func (f *File) Pos() token.Pos { - return f.Node.Pos() -} - -// ObjectList represents a list of ObjectItems. An HCL file itself is an -// ObjectList. -type ObjectList struct { - Items []*ObjectItem -} - -func (o *ObjectList) Add(item *ObjectItem) { - o.Items = append(o.Items, item) -} - -// Filter filters out the objects with the given key list as a prefix. -// -// The returned list of objects contain ObjectItems where the keys have -// this prefix already stripped off. This might result in objects with -// zero-length key lists if they have no children. -// -// If no matches are found, an empty ObjectList (non-nil) is returned. -func (o *ObjectList) Filter(keys ...string) *ObjectList { - var result ObjectList - for _, item := range o.Items { - // If there aren't enough keys, then ignore this - if len(item.Keys) < len(keys) { - continue - } - - match := true - for i, key := range item.Keys[:len(keys)] { - key := key.Token.Value().(string) - if key != keys[i] && !strings.EqualFold(key, keys[i]) { - match = false - break - } - } - if !match { - continue - } - - // Strip off the prefix from the children - newItem := *item - newItem.Keys = newItem.Keys[len(keys):] - result.Add(&newItem) - } - - return &result -} - -// Children returns further nested objects (key length > 0) within this -// ObjectList. This should be used with Filter to get at child items. -func (o *ObjectList) Children() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) > 0 { - result.Add(item) - } - } - - return &result -} - -// Elem returns items in the list that are direct element assignments -// (key length == 0). This should be used with Filter to get at elements. -func (o *ObjectList) Elem() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) == 0 { - result.Add(item) - } - } - - return &result -} - -func (o *ObjectList) Pos() token.Pos { - // always returns the uninitiliazed position - return o.Items[0].Pos() -} - -// ObjectItem represents a HCL Object Item. An item is represented with a key -// (or keys). It can be an assignment or an object (both normal and nested) -type ObjectItem struct { - // keys is only one length long if it's of type assignment. If it's a - // nested object it can be larger than one. In that case "assign" is - // invalid as there is no assignments for a nested object. - Keys []*ObjectKey - - // assign contains the position of "=", if any - Assign token.Pos - - // val is the item itself. It can be an object,list, number, bool or a - // string. If key length is larger than one, val can be only of type - // Object. - Val Node - - LeadComment *CommentGroup // associated lead comment - LineComment *CommentGroup // associated line comment -} - -func (o *ObjectItem) Pos() token.Pos { - // I'm not entirely sure what causes this, but removing this causes - // a test failure. We should investigate at some point. - if len(o.Keys) == 0 { - return token.Pos{} - } - - return o.Keys[0].Pos() -} - -// ObjectKeys are either an identifier or of type string. -type ObjectKey struct { - Token token.Token -} - -func (o *ObjectKey) Pos() token.Pos { - return o.Token.Pos -} - -// LiteralType represents a literal of basic type. Valid types are: -// token.NUMBER, token.FLOAT, token.BOOL and token.STRING -type LiteralType struct { - Token token.Token - - // comment types, only used when in a list - LeadComment *CommentGroup - LineComment *CommentGroup -} - -func (l *LiteralType) Pos() token.Pos { - return l.Token.Pos -} - -// ListStatement represents a HCL List type -type ListType struct { - Lbrack token.Pos // position of "[" - Rbrack token.Pos // position of "]" - List []Node // the elements in lexical order -} - -func (l *ListType) Pos() token.Pos { - return l.Lbrack -} - -func (l *ListType) Add(node Node) { - l.List = append(l.List, node) -} - -// ObjectType represents a HCL Object Type -type ObjectType struct { - Lbrace token.Pos // position of "{" - Rbrace token.Pos // position of "}" - List *ObjectList // the nodes in lexical order -} - -func (o *ObjectType) Pos() token.Pos { - return o.Lbrace -} - -// Comment node represents a single //, # style or /*- style commment -type Comment struct { - Start token.Pos // position of / or # - Text string -} - -func (c *Comment) Pos() token.Pos { - return c.Start -} - -// CommentGroup node represents a sequence of comments with no other tokens and -// no empty lines between. -type CommentGroup struct { - List []*Comment // len(List) > 0 -} - -func (c *CommentGroup) Pos() token.Pos { - return c.List[0].Pos() -} - -//------------------------------------------------------------------- -// GoStringer -//------------------------------------------------------------------- - -func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } -func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go deleted file mode 100644 index ba07ad42..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go +++ /dev/null @@ -1,52 +0,0 @@ -package ast - -import "fmt" - -// WalkFunc describes a function to be called for each node during a Walk. The -// returned node can be used to rewrite the AST. Walking stops the returned -// bool is false. -type WalkFunc func(Node) (Node, bool) - -// Walk traverses an AST in depth-first order: It starts by calling fn(node); -// node must not be nil. If fn returns true, Walk invokes fn recursively for -// each of the non-nil children of node, followed by a call of fn(nil). The -// returned node of fn can be used to rewrite the passed node to fn. -func Walk(node Node, fn WalkFunc) Node { - rewritten, ok := fn(node) - if !ok { - return rewritten - } - - switch n := node.(type) { - case *File: - n.Node = Walk(n.Node, fn) - case *ObjectList: - for i, item := range n.Items { - n.Items[i] = Walk(item, fn).(*ObjectItem) - } - case *ObjectKey: - // nothing to do - case *ObjectItem: - for i, k := range n.Keys { - n.Keys[i] = Walk(k, fn).(*ObjectKey) - } - - if n.Val != nil { - n.Val = Walk(n.Val, fn) - } - case *LiteralType: - // nothing to do - case *ListType: - for i, l := range n.List { - n.List[i] = Walk(l, fn) - } - case *ObjectType: - n.List = Walk(n.List, fn).(*ObjectList) - default: - // should we panic here? - fmt.Printf("unknown type: %T\n", n) - } - - fn(nil) - return rewritten -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/error.go deleted file mode 100644 index 5c99381d..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/error.go +++ /dev/null @@ -1,17 +0,0 @@ -package parser - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/token" -) - -// PosError is a parse error that contains a position. -type PosError struct { - Pos token.Pos - Err error -} - -func (e *PosError) Error() string { - return fmt.Sprintf("At %s: %s", e.Pos, e.Err) -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go deleted file mode 100644 index 64c83bcf..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go +++ /dev/null @@ -1,532 +0,0 @@ -// Package parser implements a parser for HCL (HashiCorp Configuration -// Language) -package parser - -import ( - "bytes" - "errors" - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/scanner" - "github.com/hashicorp/hcl/hcl/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - comments []*ast.CommentGroup - leadComment *ast.CommentGroup // last lead comment - lineComment *ast.CommentGroup // last line comment - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - // normalize all line endings - // since the scanner and output only work with "\n" line endings, we may - // end up with dangling "\r" characters in the parsed data. - src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) - - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = &PosError{Pos: pos, Err: errors.New(msg)} - } - - f.Node, err = p.objectList(false) - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - f.Comments = p.comments - return f, nil -} - -// objectList parses a list of items within an object (generally k/v pairs). -// The parameter" obj" tells this whether to we are within an object (braces: -// '{', '}') or just at the top level. If we're within an object, we end -// at an RBRACE. -func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - if obj { - tok := p.scan() - p.unscan() - if tok.Type == token.RBRACE { - break - } - } - - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // object lists can be optionally comma-delimited e.g. when a list of maps - // is being expressed, so a comma is allowed here - it's simply consumed - tok := p.scan() - if tok.Type != token.COMMA { - p.unscan() - } - } - return node, nil -} - -func (p *Parser) consumeComment() (comment *ast.Comment, endline int) { - endline = p.tok.Pos.Line - - // count the endline if it's multiline comment, ie starting with /* - if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' { - // don't use range here - no need to decode Unicode code points - for i := 0; i < len(p.tok.Text); i++ { - if p.tok.Text[i] == '\n' { - endline++ - } - } - } - - comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text} - p.tok = p.sc.Scan() - return -} - -func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) { - var list []*ast.Comment - endline = p.tok.Pos.Line - - for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n { - var comment *ast.Comment - comment, endline = p.consumeComment() - list = append(list, comment) - } - - // add comment group to the comments list - comments = &ast.CommentGroup{List: list} - p.comments = append(p.comments, comments) - - return -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if len(keys) > 0 && err == errEofToken { - // We ignore eof token here since it is an error if we didn't - // receive a value (but we did receive a key) for the item. - err = nil - } - if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE { - // This is a strange boolean statement, but what it means is: - // We have keys with no value, and we're likely in an object - // (since RBrace ends an object). For this, we set err to nil so - // we continue and get the error below of having the wrong value - // type. - err = nil - - // Reset the token type so we don't think it completed fine. See - // objectType which uses p.tok.Type to check if we're done with - // the object. - p.tok.Type = token.EOF - } - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - if p.leadComment != nil { - o.LeadComment = p.leadComment - p.leadComment = nil - } - - switch p.tok.Type { - case token.ASSIGN: - o.Assign = p.tok.Pos - o.Val, err = p.object() - if err != nil { - return nil, err - } - case token.LBRACE: - o.Val, err = p.objectType() - if err != nil { - return nil, err - } - default: - keyStr := make([]string, 0, len(keys)) - for _, k := range keys { - keyStr = append(keyStr, k.Token.Text) - } - - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf( - "key '%s' expected start of object ('{') or assignment ('=')", - strings.Join(keyStr, " ")), - } - } - - // key=#comment - // val - if p.lineComment != nil { - o.LineComment, p.lineComment = p.lineComment, nil - } - - // do a look-ahead for line comment - p.scan() - if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil { - o.LineComment = p.lineComment - p.lineComment = nil - } - p.unscan() - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - // It is very important to also return the keys here as well as - // the error. This is because we need to be able to tell if we - // did parse keys prior to finding the EOF, or if we just found - // a bare EOF. - return keys, errEofToken - case token.ASSIGN: - // assignment or object only, but not nested objects. this is not - // allowed: `foo bar = {}` - if keyCount > 1 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type), - } - } - - if keyCount == 0 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: errors.New("no object keys found!"), - } - } - - return keys, nil - case token.LBRACE: - var err error - - // If we have no keys, then it is a syntax error. i.e. {{}} is not - // allowed. - if len(keys) == 0 { - err = &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), - } - } - - // object - return keys, err - case token.IDENT, token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{Token: p.tok}) - case token.ILLEGAL: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("illegal character"), - } - default: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type), - } - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (ast.Node, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.COMMENT: - // implement comment - case token.EOF: - return nil, errEofToken - } - - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("Unknown token: %+v", tok), - } -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{ - Lbrace: p.tok.Pos, - } - - l, err := p.objectList(true) - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - // No error, scan and expect the ending to be a brace - if tok := p.scan(); tok.Type != token.RBRACE { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), - } - } - - o.List = l - o.Rbrace = p.tok.Pos // advanced via parseObjectList - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{ - Lbrack: p.tok.Pos, - } - - needComma := false - for { - tok := p.scan() - if needComma { - switch tok.Type { - case token.COMMA, token.RBRACK: - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error parsing list, expected comma or list end, got: %s", - tok.Type), - } - } - } - switch tok.Type { - case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: - node, err := p.literalType() - if err != nil { - return nil, err - } - - // If there is a lead comment, apply it - if p.leadComment != nil { - node.LeadComment = p.leadComment - p.leadComment = nil - } - - l.Add(node) - needComma = true - case token.COMMA: - // get next list item or we are at the end - // do a look-ahead for line comment - p.scan() - if p.lineComment != nil && len(l.List) > 0 { - lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) - if ok { - lit.LineComment = p.lineComment - l.List[len(l.List)-1] = lit - p.lineComment = nil - } - } - p.unscan() - - needComma = false - continue - case token.LBRACE: - // Looks like a nested object, so parse it out - node, err := p.objectType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse object within list: %s", err), - } - } - l.Add(node) - needComma = true - case token.LBRACK: - node, err := p.listType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse list within list: %s", err), - } - } - l.Add(node) - case token.RBRACK: - // finished - l.Rbrack = p.tok.Pos - return l, nil - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type), - } - } - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok, - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. In the process, it collects any -// comment groups encountered, and remembers the last lead and line comments. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - // Otherwise read the next token from the scanner and Save it to the buffer - // in case we unscan later. - prev := p.tok - p.tok = p.sc.Scan() - - if p.tok.Type == token.COMMENT { - var comment *ast.CommentGroup - var endline int - - // fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n", - // p.tok.Pos.Line, prev.Pos.Line, endline) - if p.tok.Pos.Line == prev.Pos.Line { - // The comment is on same line as the previous token; it - // cannot be a lead comment but may be a line comment. - comment, endline = p.consumeCommentGroup(0) - if p.tok.Pos.Line != endline { - // The next token is on a different line, thus - // the last comment group is a line comment. - p.lineComment = comment - } - } - - // consume successor comments, if any - endline = -1 - for p.tok.Type == token.COMMENT { - comment, endline = p.consumeCommentGroup(1) - } - - if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE { - switch p.tok.Type { - case token.RBRACE, token.RBRACK: - // Do not count for these cases - default: - // The next token is following on the line immediately after the - // comment group, thus the last comment group is a lead comment. - p.leadComment = comment - } - } - - } - - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go deleted file mode 100644 index 7c038d12..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go +++ /dev/null @@ -1,789 +0,0 @@ -package printer - -import ( - "bytes" - "fmt" - "sort" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/token" -) - -const ( - blank = byte(' ') - newline = byte('\n') - tab = byte('\t') - infinity = 1 << 30 // offset or line -) - -var ( - unindent = []byte("\uE123") // in the private use space -) - -type printer struct { - cfg Config - prev token.Pos - - comments []*ast.CommentGroup // may be nil, contains all comments - standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) - - enableTrace bool - indentTrace int -} - -type ByPosition []*ast.CommentGroup - -func (b ByPosition) Len() int { return len(b) } -func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) } - -// collectComments comments all standalone comments which are not lead or line -// comment -func (p *printer) collectComments(node ast.Node) { - // first collect all comments. This is already stored in - // ast.File.(comments) - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.File: - p.comments = t.Comments - return nn, false - } - return nn, true - }) - - standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0) - for _, c := range p.comments { - standaloneComments[c.Pos()] = c - } - - // next remove all lead and line comments from the overall comment map. - // This will give us comments which are standalone, comments which are not - // assigned to any kind of node. - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.LiteralType: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - case *ast.ObjectItem: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - } - - return nn, true - }) - - for _, c := range standaloneComments { - p.standaloneComments = append(p.standaloneComments, c) - } - - sort.Sort(ByPosition(p.standaloneComments)) -} - -// output prints creates b printable HCL output and returns it. -func (p *printer) output(n interface{}) []byte { - var buf bytes.Buffer - - switch t := n.(type) { - case *ast.File: - // File doesn't trace so we add the tracing here - defer un(trace(p, "File")) - return p.output(t.Node) - case *ast.ObjectList: - defer un(trace(p, "ObjectList")) - - var index int - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is at "infinity" - var nextItem token.Pos - if index != len(t.Items) { - nextItem = t.Items[index].Pos() - } else { - nextItem = token.Pos{Offset: infinity, Line: infinity} - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - // Go through all the comments in the group. The group - // should be printed together, not separated by double newlines. - printed := false - newlinePrinted := false - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // if we hit the end add newlines so we can print the comment - // we don't do this if prev is invalid which means the - // beginning of the file since the first comment should - // be at the first line. - if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) { - buf.Write([]byte{newline, newline}) - newlinePrinted = true - } - - // Write the actual comment. - buf.WriteString(comment.Text) - buf.WriteByte(newline) - - // Set printed to true to note that we printed something - printed = true - } - } - - // If we're not at the last item, write a new line so - // that there is a newline separating this comment from - // the next object. - if printed && index != len(t.Items) { - buf.WriteByte(newline) - } - } - - if index == len(t.Items) { - break - } - - buf.Write(p.output(t.Items[index])) - if index != len(t.Items)-1 { - // Always write a newline to separate us from the next item - buf.WriteByte(newline) - - // Need to determine if we're going to separate the next item - // with a blank line. The logic here is simple, though there - // are a few conditions: - // - // 1. The next object is more than one line away anyways, - // so we need an empty line. - // - // 2. The next object is not a "single line" object, so - // we need an empty line. - // - // 3. This current object is not a single line object, - // so we need an empty line. - current := t.Items[index] - next := t.Items[index+1] - if next.Pos().Line != t.Items[index].Pos().Line+1 || - !p.isSingleLineObject(next) || - !p.isSingleLineObject(current) { - buf.WriteByte(newline) - } - } - index++ - } - case *ast.ObjectKey: - buf.WriteString(t.Token.Text) - case *ast.ObjectItem: - p.prev = t.Pos() - buf.Write(p.objectItem(t)) - case *ast.LiteralType: - buf.Write(p.literalType(t)) - case *ast.ListType: - buf.Write(p.list(t)) - case *ast.ObjectType: - buf.Write(p.objectType(t)) - default: - fmt.Printf(" unknown type: %T\n", n) - } - - return buf.Bytes() -} - -func (p *printer) literalType(lit *ast.LiteralType) []byte { - result := []byte(lit.Token.Text) - switch lit.Token.Type { - case token.HEREDOC: - // Clear the trailing newline from heredocs - if result[len(result)-1] == '\n' { - result = result[:len(result)-1] - } - - // Poison lines 2+ so that we don't indent them - result = p.heredocIndent(result) - case token.STRING: - // If this is a multiline string, poison lines 2+ so we don't - // indent them. - if bytes.IndexRune(result, '\n') >= 0 { - result = p.heredocIndent(result) - } - } - - return result -} - -// objectItem returns the printable HCL form of an object item. An object type -// starts with one/multiple keys and has a value. The value might be of any -// type. -func (p *printer) objectItem(o *ast.ObjectItem) []byte { - defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text))) - var buf bytes.Buffer - - if o.LeadComment != nil { - for _, comment := range o.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - // If key and val are on different lines, treat line comments like lead comments. - if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line { - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range o.Keys { - buf.WriteString(k.Token.Text) - buf.WriteByte(blank) - - // reach end of key - if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - buf.Write(p.output(o.Val)) - - if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line { - buf.WriteByte(blank) - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - } - } - - return buf.Bytes() -} - -// objectType returns the printable HCL form of an object type. An object type -// begins with a brace and ends with a brace. -func (p *printer) objectType(o *ast.ObjectType) []byte { - defer un(trace(p, "ObjectType")) - var buf bytes.Buffer - buf.WriteString("{") - - var index int - var nextItem token.Pos - var commented, newlinePrinted bool - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is the closing brace - if index != len(o.List.Items) { - nextItem = o.List.Items[index].Pos() - } else { - nextItem = o.Rbrace - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - printed := false - var lastCommentPos token.Pos - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // If there are standalone comments and the initial newline has not - // been printed yet, do it now. - if !newlinePrinted { - newlinePrinted = true - buf.WriteByte(newline) - } - - // add newline if it's between other printed nodes - if index > 0 { - commented = true - buf.WriteByte(newline) - } - - // Store this position - lastCommentPos = comment.Pos() - - // output the comment itself - buf.Write(p.indent(p.heredocIndent([]byte(comment.Text)))) - - // Set printed to true to note that we printed something - printed = true - - /* - if index != len(o.List.Items) { - buf.WriteByte(newline) // do not print on the end - } - */ - } - } - - // Stuff to do if we had comments - if printed { - // Always write a newline - buf.WriteByte(newline) - - // If there is another item in the object and our comment - // didn't hug it directly, then make sure there is a blank - // line separating them. - if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 { - buf.WriteByte(newline) - } - } - } - - if index == len(o.List.Items) { - p.prev = o.Rbrace - break - } - - // At this point we are sure that it's not a totally empty block: print - // the initial newline if it hasn't been printed yet by the previous - // block about standalone comments. - if !newlinePrinted { - buf.WriteByte(newline) - newlinePrinted = true - } - - // check if we have adjacent one liner items. If yes we'll going to align - // the comments. - var aligned []*ast.ObjectItem - for _, item := range o.List.Items[index:] { - // we don't group one line lists - if len(o.List.Items) == 1 { - break - } - - // one means a oneliner with out any lead comment - // two means a oneliner with lead comment - // anything else might be something else - cur := lines(string(p.objectItem(item))) - if cur > 2 { - break - } - - curPos := item.Pos() - - nextPos := token.Pos{} - if index != len(o.List.Items)-1 { - nextPos = o.List.Items[index+1].Pos() - } - - prevPos := token.Pos{} - if index != 0 { - prevPos = o.List.Items[index-1].Pos() - } - - // fmt.Println("DEBUG ----------------") - // fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos) - // fmt.Printf("cur = %+v curPos: %s\n", cur, curPos) - // fmt.Printf("next = %+v nextPos: %s\n", next, nextPos) - - if curPos.Line+1 == nextPos.Line { - aligned = append(aligned, item) - index++ - continue - } - - if curPos.Line-1 == prevPos.Line { - aligned = append(aligned, item) - index++ - - // finish if we have a new line or comment next. This happens - // if the next item is not adjacent - if curPos.Line+1 != nextPos.Line { - break - } - continue - } - - break - } - - // put newlines if the items are between other non aligned items. - // newlines are also added if there is a standalone comment already, so - // check it too - if !commented && index != len(aligned) { - buf.WriteByte(newline) - } - - if len(aligned) >= 1 { - p.prev = aligned[len(aligned)-1].Pos() - - items := p.alignedItems(aligned) - buf.Write(p.indent(items)) - } else { - p.prev = o.List.Items[index].Pos() - - buf.Write(p.indent(p.objectItem(o.List.Items[index]))) - index++ - } - - buf.WriteByte(newline) - } - - buf.WriteString("}") - return buf.Bytes() -} - -func (p *printer) alignedItems(items []*ast.ObjectItem) []byte { - var buf bytes.Buffer - - // find the longest key and value length, needed for alignment - var longestKeyLen int // longest key length - var longestValLen int // longest value length - for _, item := range items { - key := len(item.Keys[0].Token.Text) - val := len(p.output(item.Val)) - - if key > longestKeyLen { - longestKeyLen = key - } - - if val > longestValLen { - longestValLen = val - } - } - - for i, item := range items { - if item.LeadComment != nil { - for _, comment := range item.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range item.Keys { - keyLen := len(k.Token.Text) - buf.WriteString(k.Token.Text) - for i := 0; i < longestKeyLen-keyLen+1; i++ { - buf.WriteByte(blank) - } - - // reach end of key - if i == len(item.Keys)-1 && len(item.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - val := p.output(item.Val) - valLen := len(val) - buf.Write(val) - - if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil { - for i := 0; i < longestValLen-valLen+1; i++ { - buf.WriteByte(blank) - } - - for _, comment := range item.LineComment.List { - buf.WriteString(comment.Text) - } - } - - // do not print for the last item - if i != len(items)-1 { - buf.WriteByte(newline) - } - } - - return buf.Bytes() -} - -// list returns the printable HCL form of an list type. -func (p *printer) list(l *ast.ListType) []byte { - if p.isSingleLineList(l) { - return p.singleLineList(l) - } - - var buf bytes.Buffer - buf.WriteString("[") - buf.WriteByte(newline) - - var longestLine int - for _, item := range l.List { - // for now we assume that the list only contains literal types - if lit, ok := item.(*ast.LiteralType); ok { - lineLen := len(lit.Token.Text) - if lineLen > longestLine { - longestLine = lineLen - } - } - } - - haveEmptyLine := false - for i, item := range l.List { - // If we have a lead comment, then we want to write that first - leadComment := false - if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil { - leadComment = true - - // Ensure an empty line before every element with a - // lead comment (except the first item in a list). - if !haveEmptyLine && i != 0 { - buf.WriteByte(newline) - } - - for _, comment := range lit.LeadComment.List { - buf.Write(p.indent([]byte(comment.Text))) - buf.WriteByte(newline) - } - } - - // also indent each line - val := p.output(item) - curLen := len(val) - buf.Write(p.indent(val)) - - // if this item is a heredoc, then we output the comma on - // the next line. This is the only case this happens. - comma := []byte{','} - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - comma = p.indent(comma) - } - - buf.Write(comma) - - if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil { - // if the next item doesn't have any comments, do not align - buf.WriteByte(blank) // align one space - for i := 0; i < longestLine-curLen; i++ { - buf.WriteByte(blank) - } - - for _, comment := range lit.LineComment.List { - buf.WriteString(comment.Text) - } - } - - buf.WriteByte(newline) - - // Ensure an empty line after every element with a - // lead comment (except the first item in a list). - haveEmptyLine = leadComment && i != len(l.List)-1 - if haveEmptyLine { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// isSingleLineList returns true if: -// * they were previously formatted entirely on one line -// * they consist entirely of literals -// * there are either no heredoc strings or the list has exactly one element -// * there are no line comments -func (printer) isSingleLineList(l *ast.ListType) bool { - for _, item := range l.List { - if item.Pos().Line != l.Lbrack.Line { - return false - } - - lit, ok := item.(*ast.LiteralType) - if !ok { - return false - } - - if lit.Token.Type == token.HEREDOC && len(l.List) != 1 { - return false - } - - if lit.LineComment != nil { - return false - } - } - - return true -} - -// singleLineList prints a simple single line list. -// For a definition of "simple", see isSingleLineList above. -func (p *printer) singleLineList(l *ast.ListType) []byte { - buf := &bytes.Buffer{} - - buf.WriteString("[") - for i, item := range l.List { - if i != 0 { - buf.WriteString(", ") - } - - // Output the item itself - buf.Write(p.output(item)) - - // The heredoc marker needs to be at the end of line. - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// indent indents the lines of the given buffer for each non-empty line -func (p *printer) indent(buf []byte) []byte { - var prefix []byte - if p.cfg.SpacesWidth != 0 { - for i := 0; i < p.cfg.SpacesWidth; i++ { - prefix = append(prefix, blank) - } - } else { - prefix = []byte{tab} - } - - var res []byte - bol := true - for _, c := range buf { - if bol && c != '\n' { - res = append(res, prefix...) - } - - res = append(res, c) - bol = c == '\n' - } - return res -} - -// unindent removes all the indentation from the tombstoned lines -func (p *printer) unindent(buf []byte) []byte { - var res []byte - for i := 0; i < len(buf); i++ { - skip := len(buf)-i <= len(unindent) - if !skip { - skip = !bytes.Equal(unindent, buf[i:i+len(unindent)]) - } - if skip { - res = append(res, buf[i]) - continue - } - - // We have a marker. we have to backtrace here and clean out - // any whitespace ahead of our tombstone up to a \n - for j := len(res) - 1; j >= 0; j-- { - if res[j] == '\n' { - break - } - - res = res[:j] - } - - // Skip the entire unindent marker - i += len(unindent) - 1 - } - - return res -} - -// heredocIndent marks all the 2nd and further lines as unindentable -func (p *printer) heredocIndent(buf []byte) []byte { - var res []byte - bol := false - for _, c := range buf { - if bol && c != '\n' { - res = append(res, unindent...) - } - res = append(res, c) - bol = c == '\n' - } - return res -} - -// isSingleLineObject tells whether the given object item is a single -// line object such as "obj {}". -// -// A single line object: -// -// * has no lead comments (hence multi-line) -// * has no assignment -// * has no values in the stanza (within {}) -// -func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool { - // If there is a lead comment, can't be one line - if val.LeadComment != nil { - return false - } - - // If there is assignment, we always break by line - if val.Assign.IsValid() { - return false - } - - // If it isn't an object type, then its not a single line object - ot, ok := val.Val.(*ast.ObjectType) - if !ok { - return false - } - - // If the object has no items, it is single line! - return len(ot.List.Items) == 0 -} - -func lines(txt string) int { - endline := 1 - for i := 0; i < len(txt); i++ { - if txt[i] == '\n' { - endline++ - } - } - return endline -} - -// ---------------------------------------------------------------------------- -// Tracing support - -func (p *printer) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - i := 2 * p.indentTrace - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *printer, msg string) *printer { - p.printTrace(msg, "(") - p.indentTrace++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *printer) { - p.indentTrace-- - p.printTrace(")") -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go deleted file mode 100644 index 6617ab8e..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package printer implements printing of AST nodes to HCL format. -package printer - -import ( - "bytes" - "io" - "text/tabwriter" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" -) - -var DefaultConfig = Config{ - SpacesWidth: 2, -} - -// A Config node controls the output of Fprint. -type Config struct { - SpacesWidth int // if set, it will use spaces instead of tabs for alignment -} - -func (c *Config) Fprint(output io.Writer, node ast.Node) error { - p := &printer{ - cfg: *c, - comments: make([]*ast.CommentGroup, 0), - standaloneComments: make([]*ast.CommentGroup, 0), - // enableTrace: true, - } - - p.collectComments(node) - - if _, err := output.Write(p.unindent(p.output(node))); err != nil { - return err - } - - // flush tabwriter, if any - var err error - if tw, _ := output.(*tabwriter.Writer); tw != nil { - err = tw.Flush() - } - - return err -} - -// Fprint "pretty-prints" an HCL node to output -// It calls Config.Fprint with default settings. -func Fprint(output io.Writer, node ast.Node) error { - return DefaultConfig.Fprint(output, node) -} - -// Format formats src HCL and returns the result. -func Format(src []byte) ([]byte, error) { - node, err := parser.Parse(src) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - if err := DefaultConfig.Fprint(&buf, node); err != nil { - return nil, err - } - - // Add trailing newline to result - buf.WriteString("\n") - return buf.Bytes(), nil -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go deleted file mode 100644 index 624a18fe..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go +++ /dev/null @@ -1,652 +0,0 @@ -// Package scanner implements a scanner for HCL (HashiCorp Configuration -// Language) source text. -package scanner - -import ( - "bytes" - "fmt" - "os" - "regexp" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/hcl/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == utf8.RuneError && size == 1 { - s.err("illegal UTF-8 encoding") - return ch - } - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - if ch == '\x00' { - s.err("unexpected null character (0x00)") - return eof - } - - if ch == '\uE123' { - s.err("unicode code point U+E123 reserved for internal use") - return utf8.RuneError - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - tok = token.IDENT - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '#', '/': - tok = token.COMMENT - s.scanComment(ch) - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '<': - tok = token.HEREDOC - s.scanHeredoc() - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case '=': - tok = token.ASSIGN - case '+': - tok = token.ADD - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - tok = token.SUB - } - default: - s.err("illegal char") - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -func (s *Scanner) scanComment(ch rune) { - // single line comments - if ch == '#' || (ch == '/' && s.peek() != '*') { - if ch == '/' && s.peek() != '/' { - s.err("expected '/' for comment") - return - } - - ch = s.next() - for ch != '\n' && ch >= 0 && ch != eof { - ch = s.next() - } - if ch != eof && ch >= 0 { - s.unread() - } - return - } - - // be sure we get the character after /* This allows us to find comment's - // that are not erminated - if ch == '/' { - s.next() - ch = s.next() // read character after "/*" - } - - // look for /* - style comments - for { - if ch < 0 || ch == eof { - s.err("comment not terminated") - break - } - - ch0 := ch - ch = s.next() - if ch0 == '*' && ch == '/' { - break - } - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - if ch == '0' { - // check for hexadecimal, octal or float - ch = s.next() - if ch == 'x' || ch == 'X' { - // hexadecimal - ch = s.next() - found := false - for isHexadecimal(ch) { - ch = s.next() - found = true - } - - if !found { - s.err("illegal hexadecimal number") - } - - if ch != eof { - s.unread() - } - - return token.NUMBER - } - - // now it's either something like: 0421(octal) or 0.1231(float) - illegalOctal := false - for isDecimal(ch) { - ch = s.next() - if ch == '8' || ch == '9' { - // this is just a possibility. For example 0159 is illegal, but - // 0159.23 is valid. So we mark a possible illegal octal. If - // the next character is not a period, we'll print the error. - illegalOctal = true - } - } - - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if illegalOctal { - s.err("illegal octal number") - } - - if ch != eof { - s.unread() - } - return token.NUMBER - } - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanHeredoc scans a heredoc string -func (s *Scanner) scanHeredoc() { - // Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) { - break - } - - // Not an anchor match, record the start of a new line - lineStart = s.srcPos.Offset - } - - if ch == eof { - s.err("heredoc not terminated") - return - } - } - - return -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' && braces == 0 { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - start := n - for n > 0 && digitVal(ch) < base { - ch = s.next() - if ch == eof { - // If we see an EOF, we halt any more scanning of digits - // immediately. - break - } - - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - if n != start && ch != eof { - // we scanned all digits, put the last non digit char back, - // only if we read anything at all - s.unread() - } - - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isDigit returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isDecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go deleted file mode 100644 index 5f981eaa..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go +++ /dev/null @@ -1,241 +0,0 @@ -package strconv - -import ( - "errors" - "unicode/utf8" -) - -// ErrSyntax indicates that a value does not have the right syntax for the target type. -var ErrSyntax = errors.New("invalid syntax") - -// Unquote interprets s as a single-quoted, double-quoted, -// or backquoted Go string literal, returning the string value -// that s quotes. (If s is single-quoted, it would be a Go -// character literal; Unquote returns the corresponding -// one-character string.) -func Unquote(s string) (t string, err error) { - n := len(s) - if n < 2 { - return "", ErrSyntax - } - quote := s[0] - if quote != s[n-1] { - return "", ErrSyntax - } - s = s[1 : n-1] - - if quote != '"' { - return "", ErrSyntax - } - if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { - return "", ErrSyntax - } - - // Is it trivial? Avoid allocation. - if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') { - switch quote { - case '"': - return s, nil - case '\'': - r, size := utf8.DecodeRuneInString(s) - if size == len(s) && (r != utf8.RuneError || size != 1) { - return s, nil - } - } - } - - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. - for len(s) > 0 { - // If we're starting a '${}' then let it through un-unquoted. - // Specifically: we don't unquote any characters within the `${}` - // section. - if s[0] == '$' && len(s) > 1 && s[1] == '{' { - buf = append(buf, '$', '{') - s = s[2:] - - // Continue reading until we find the closing brace, copying as-is - braces := 1 - for len(s) > 0 && braces > 0 { - r, size := utf8.DecodeRuneInString(s) - if r == utf8.RuneError { - return "", ErrSyntax - } - - s = s[size:] - - n := utf8.EncodeRune(runeTmp[:], r) - buf = append(buf, runeTmp[:n]...) - - switch r { - case '{': - braces++ - case '}': - braces-- - } - } - if braces != 0 { - return "", ErrSyntax - } - if len(s) == 0 { - // If there's no string left, we're done! - break - } else { - // If there's more left, we need to pop back up to the top of the loop - // in case there's another interpolation in this string. - continue - } - } - - if s[0] == '\n' { - return "", ErrSyntax - } - - c, multibyte, ss, err := unquoteChar(s, quote) - if err != nil { - return "", err - } - s = ss - if c < utf8.RuneSelf || !multibyte { - buf = append(buf, byte(c)) - } else { - n := utf8.EncodeRune(runeTmp[:], c) - buf = append(buf, runeTmp[:n]...) - } - if quote == '\'' && len(s) != 0 { - // single-quoted must be single character - return "", ErrSyntax - } - } - return string(buf), nil -} - -// contains reports whether the string contains the byte c. -func contains(s string, c byte) bool { - for i := 0; i < len(s); i++ { - if s[i] == c { - return true - } - } - return false -} - -func unhex(b byte) (v rune, ok bool) { - c := rune(b) - switch { - case '0' <= c && c <= '9': - return c - '0', true - case 'a' <= c && c <= 'f': - return c - 'a' + 10, true - case 'A' <= c && c <= 'F': - return c - 'A' + 10, true - } - return -} - -func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) { - // easy cases - switch c := s[0]; { - case c == quote && (quote == '\'' || quote == '"'): - err = ErrSyntax - return - case c >= utf8.RuneSelf: - r, size := utf8.DecodeRuneInString(s) - return r, true, s[size:], nil - case c != '\\': - return rune(s[0]), false, s[1:], nil - } - - // hard case: c is backslash - if len(s) <= 1 { - err = ErrSyntax - return - } - c := s[1] - s = s[2:] - - switch c { - case 'a': - value = '\a' - case 'b': - value = '\b' - case 'f': - value = '\f' - case 'n': - value = '\n' - case 'r': - value = '\r' - case 't': - value = '\t' - case 'v': - value = '\v' - case 'x', 'u', 'U': - n := 0 - switch c { - case 'x': - n = 2 - case 'u': - n = 4 - case 'U': - n = 8 - } - var v rune - if len(s) < n { - err = ErrSyntax - return - } - for j := 0; j < n; j++ { - x, ok := unhex(s[j]) - if !ok { - err = ErrSyntax - return - } - v = v<<4 | x - } - s = s[n:] - if c == 'x' { - // single-byte string, possibly not UTF-8 - value = v - break - } - if v > utf8.MaxRune { - err = ErrSyntax - return - } - value = v - multibyte = true - case '0', '1', '2', '3', '4', '5', '6', '7': - v := rune(c) - '0' - if len(s) < 2 { - err = ErrSyntax - return - } - for j := 0; j < 2; j++ { // one digit already; two more - x := rune(s[j]) - '0' - if x < 0 || x > 7 { - err = ErrSyntax - return - } - v = (v << 3) | x - } - s = s[2:] - if v > 255 { - err = ErrSyntax - return - } - value = v - case '\\': - value = '\\' - case '\'', '"': - if c != quote { - err = ErrSyntax - return - } - value = rune(c) - default: - err = ErrSyntax - return - } - tail = s - return -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/position.go deleted file mode 100644 index 59c1bb72..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/token.go deleted file mode 100644 index e37c0664..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/hcl/token/token.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package token defines constants representing the lexical tokens for HCL -// (HashiCorp Configuration Language) -package token - -import ( - "fmt" - "strconv" - "strings" - - hclstrconv "github.com/hashicorp/hcl/hcl/strconv" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string - JSON bool -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - COMMENT - - identifier_beg - IDENT // literals - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - HEREDOC // < 0 { - // Pop the current item - n := len(frontier) - item := frontier[n-1] - frontier = frontier[:n-1] - - switch v := item.Val.(type) { - case *ast.ObjectType: - items, frontier = flattenObjectType(v, item, items, frontier) - case *ast.ListType: - items, frontier = flattenListType(v, item, items, frontier) - default: - items = append(items, item) - } - } - - // Reverse the list since the frontier model runs things backwards - for i := len(items)/2 - 1; i >= 0; i-- { - opp := len(items) - 1 - i - items[i], items[opp] = items[opp], items[i] - } - - // Done! Set the original items - list.Items = items - return n, true - }) -} - -func flattenListType( - ot *ast.ListType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list is empty, keep the original list - if len(ot.List) == 0 { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List { - if _, ok := subitem.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, elem := range ot.List { - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: item.Keys, - Assign: item.Assign, - Val: elem, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} - -func flattenObjectType( - ot *ast.ObjectType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list has no items we do not have to flatten anything - if ot.List.Items == nil { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List.Items { - if _, ok := subitem.Val.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, subitem := range ot.List.Items { - // Copy the new key - keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys)) - copy(keys, item.Keys) - copy(keys[len(item.Keys):], subitem.Keys) - - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: keys, - Assign: item.Assign, - Val: subitem.Val, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/event-processor/vendor/github.com/hashicorp/hcl/json/parser/parser.go deleted file mode 100644 index 125a5f07..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/json/parser/parser.go +++ /dev/null @@ -1,313 +0,0 @@ -package parser - -import ( - "errors" - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hcltoken "github.com/hashicorp/hcl/hcl/token" - "github.com/hashicorp/hcl/json/scanner" - "github.com/hashicorp/hcl/json/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = fmt.Errorf("%s: %s", pos, msg) - } - - // The root must be an object in JSON - object, err := p.object() - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - // We make our final node an object list so it is more HCL compatible - f.Node = object.List - - // Flatten it, which finds patterns and turns them into more HCL-like - // AST trees. - flattenObjects(f.Node) - - return f, nil -} - -func (p *Parser) objectList() (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // Check for a followup comma. If it isn't a comma, then we're done - if tok := p.scan(); tok.Type != token.COMMA { - break - } - } - - return node, nil -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - switch p.tok.Type { - case token.COLON: - pos := p.tok.Pos - o.Assign = hcltoken.Pos{ - Filename: pos.Filename, - Offset: pos.Offset, - Line: pos.Line, - Column: pos.Column, - } - - o.Val, err = p.objectValue() - if err != nil { - return nil, err - } - } - - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - return nil, errEofToken - case token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{ - Token: p.tok.HCLToken(), - }) - case token.COLON: - // If we have a zero keycount it means that we never got - // an object key, i.e. `{ :`. This is a syntax error. - if keyCount == 0 { - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - - // Done - return keys, nil - case token.ILLEGAL: - return nil, errors.New("illegal") - default: - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) objectValue() (ast.Node, error) { - defer un(trace(p, "ParseObjectValue")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok) -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (*ast.ObjectType, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.LBRACE: - return p.objectType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok) -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{} - - l, err := p.objectList() - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - o.List = l - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{} - - for { - tok := p.scan() - switch tok.Type { - case token.NUMBER, token.FLOAT, token.STRING: - node, err := p.literalType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.COMMA: - continue - case token.LBRACE: - node, err := p.objectType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.BOOL: - // TODO(arslan) should we support? not supported by HCL yet - case token.LBRACK: - // TODO(arslan) should we support nested lists? Even though it's - // written in README of HCL, it's not a part of the grammar - // (not defined in parse.y) - case token.RBRACK: - // finished - return l, nil - default: - return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type) - } - - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok.HCLToken(), - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - p.tok = p.sc.Scan() - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/event-processor/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go deleted file mode 100644 index fe3f0f09..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go +++ /dev/null @@ -1,451 +0,0 @@ -package scanner - -import ( - "bytes" - "fmt" - "os" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/json/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - if ch == utf8.RuneError && size == 1 { - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - s.err("illegal UTF-8 encoding") - return ch - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } else if lit == "null" { - tok = token.NULL - } else { - s.err("illegal char") - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case ':': - tok = token.COLON - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - s.err("illegal char") - } - default: - s.err("illegal char: " + string(ch)) - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - zero := ch == '0' - pos := s.srcPos - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - - // If we have a larger number and this is zero, error - if zero && pos != s.srcPos { - s.err("numbers cannot start with 0") - } - - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if ch == '\n' || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - for n > 0 && digitVal(ch) < base { - ch = s.next() - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - // we scanned all digits, put the last non digit char back - s.unread() - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isHexadecimal returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isHexadecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/json/token/position.go b/event-processor/vendor/github.com/hashicorp/hcl/json/token/position.go deleted file mode 100644 index 59c1bb72..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/json/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/json/token/token.go b/event-processor/vendor/github.com/hashicorp/hcl/json/token/token.go deleted file mode 100644 index 95a0c3ee..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/json/token/token.go +++ /dev/null @@ -1,118 +0,0 @@ -package token - -import ( - "fmt" - "strconv" - - hcltoken "github.com/hashicorp/hcl/hcl/token" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - - identifier_beg - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - NULL // null - literal_end - identifier_end - - operator_beg - LBRACK // [ - LBRACE // { - COMMA // , - PERIOD // . - COLON // : - - RBRACK // ] - RBRACE // } - - operator_end -) - -var tokens = [...]string{ - ILLEGAL: "ILLEGAL", - - EOF: "EOF", - - NUMBER: "NUMBER", - FLOAT: "FLOAT", - BOOL: "BOOL", - STRING: "STRING", - NULL: "NULL", - - LBRACK: "LBRACK", - LBRACE: "LBRACE", - COMMA: "COMMA", - PERIOD: "PERIOD", - COLON: "COLON", - - RBRACK: "RBRACK", - RBRACE: "RBRACE", -} - -// String returns the string corresponding to the token tok. -func (t Type) String() string { - s := "" - if 0 <= t && t < Type(len(tokens)) { - s = tokens[t] - } - if s == "" { - s = "token(" + strconv.Itoa(int(t)) + ")" - } - return s -} - -// IsIdentifier returns true for tokens corresponding to identifiers and basic -// type literals; it returns false otherwise. -func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end } - -// IsLiteral returns true for tokens corresponding to basic type literals; it -// returns false otherwise. -func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end } - -// IsOperator returns true for tokens corresponding to operators and -// delimiters; it returns false otherwise. -func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end } - -// String returns the token's literal text. Note that this is only -// applicable for certain token types, such as token.IDENT, -// token.STRING, etc.. -func (t Token) String() string { - return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text) -} - -// HCLToken converts this token to an HCL token. -// -// The token type must be a literal type or this will panic. -func (t Token) HCLToken() hcltoken.Token { - switch t.Type { - case BOOL: - return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text} - case FLOAT: - return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text} - case NULL: - return hcltoken.Token{Type: hcltoken.STRING, Text: ""} - case NUMBER: - return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text} - case STRING: - return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true} - default: - panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type)) - } -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/lex.go b/event-processor/vendor/github.com/hashicorp/hcl/lex.go deleted file mode 100644 index d9993c29..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/lex.go +++ /dev/null @@ -1,38 +0,0 @@ -package hcl - -import ( - "unicode" - "unicode/utf8" -) - -type lexModeValue byte - -const ( - lexModeUnknown lexModeValue = iota - lexModeHcl - lexModeJson -) - -// lexMode returns whether we're going to be parsing in JSON -// mode or HCL mode. -func lexMode(v []byte) lexModeValue { - var ( - r rune - w int - offset int - ) - - for { - r, w = utf8.DecodeRune(v[offset:]) - offset += w - if unicode.IsSpace(r) { - continue - } - if r == '{' { - return lexModeJson - } - break - } - - return lexModeHcl -} diff --git a/event-processor/vendor/github.com/hashicorp/hcl/parse.go b/event-processor/vendor/github.com/hashicorp/hcl/parse.go deleted file mode 100644 index 1fca53c4..00000000 --- a/event-processor/vendor/github.com/hashicorp/hcl/parse.go +++ /dev/null @@ -1,39 +0,0 @@ -package hcl - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hclParser "github.com/hashicorp/hcl/hcl/parser" - jsonParser "github.com/hashicorp/hcl/json/parser" -) - -// ParseBytes accepts as input byte slice and returns ast tree. -// -// Input can be either JSON or HCL -func ParseBytes(in []byte) (*ast.File, error) { - return parse(in) -} - -// ParseString accepts input as a string and returns ast tree. -func ParseString(input string) (*ast.File, error) { - return parse([]byte(input)) -} - -func parse(in []byte) (*ast.File, error) { - switch lexMode(in) { - case lexModeHcl: - return hclParser.Parse(in) - case lexModeJson: - return jsonParser.Parse(in) - } - - return nil, fmt.Errorf("unknown config format") -} - -// Parse parses the given input and returns the root object. -// -// The input format can be either HCL or JSON. -func Parse(input string) (*ast.File, error) { - return parse([]byte(input)) -} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/.golangci.yml b/event-processor/vendor/github.com/jackc/pgx/v5/.golangci.yml new file mode 100644 index 00000000..ca74c703 --- /dev/null +++ b/event-processor/vendor/github.com/jackc/pgx/v5/.golangci.yml @@ -0,0 +1,21 @@ +# See for configurations: https://golangci-lint.run/usage/configuration/ +version: 2 + +# See: https://golangci-lint.run/usage/formatters/ +formatters: + default: none + enable: + - gofmt # https://pkg.go.dev/cmd/gofmt + - gofumpt # https://github.com/mvdan/gofumpt + + settings: + gofmt: + simplify: true # Simplify code: gofmt with `-s` option. + + gofumpt: + # Module path which contains the source code being formatted. + # Default: "" + module-path: github.com/jackc/pgx/v5 # Should match with module in go.mod + # Choose whether to use the extra rules. + # Default: false + extra-rules: true diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/CHANGELOG.md b/event-processor/vendor/github.com/jackc/pgx/v5/CHANGELOG.md index a0ff9ba3..6c9c99b5 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/CHANGELOG.md +++ b/event-processor/vendor/github.com/jackc/pgx/v5/CHANGELOG.md @@ -1,3 +1,54 @@ +# 5.7.6 (September 8, 2025) + +* Use ParseConfigError in pgx.ParseConfig and pgxpool.ParseConfig (Yurasov Ilia) +* Add PrepareConn hook to pgxpool (Jonathan Hall) +* Reduce allocations in QueryContext (Dominique Lefevre) +* Add MarshalJSON and UnmarshalJSON for pgtype.Uint32 (Panos Koutsovasilis) +* Configure ping behavior on pgxpool with ShouldPing (Christian Kiely) +* zeronull int types implement Int64Valuer and Int64Scanner (Li Zeghong) +* Fix panic when receiving terminate connection message during CopyFrom (Michal Drausowski) +* Fix statement cache not being invalidated on error during batch (Muhammadali Nazarov) + +# 5.7.5 (May 17, 2025) + +* Support sslnegotiation connection option (divyam234) +* Update golang.org/x/crypto to v0.37.0. This placates security scanners that were unable to see that pgx did not use the behavior affected by https://pkg.go.dev/vuln/GO-2025-3487. +* TraceLog now logs Acquire and Release at the debug level (dave sinclair) +* Add support for PGTZ environment variable +* Add support for PGOPTIONS environment variable +* Unpin memory used by Rows quicker +* Remove PlanScan memoization. This resolves a rare issue where scanning could be broken for one type by first scanning another. The problem was in the memoization system and benchmarking revealed that memoization was not providing any meaningful benefit. + +# 5.7.4 (March 24, 2025) + +* Fix / revert change to scanning JSON `null` (Felix Röhrich) + +# 5.7.3 (March 21, 2025) + +* Expose EmptyAcquireWaitTime in pgxpool.Stat (vamshiaruru32) +* Improve SQL sanitizer performance (ninedraft) +* Fix Scan confusion with json(b), sql.Scanner, and automatic dereferencing (moukoublen, felix-roehrich) +* Fix Values() for xml type always returning nil instead of []byte +* Add ability to send Flush message in pipeline mode (zenkovev) +* Fix pgtype.Timestamp's JSON behavior to match PostgreSQL (pconstantinou) +* Better error messages when scanning structs (logicbomb) +* Fix handling of error on batch write (bonnefoa) +* Match libpq's connection fallback behavior more closely (felix-roehrich) +* Add MinIdleConns to pgxpool (djahandarie) + +# 5.7.2 (December 21, 2024) + +* Fix prepared statement already exists on batch prepare failure +* Add commit query to tx options (Lucas Hild) +* Fix pgtype.Timestamp json unmarshal (Shean de Montigny-Desautels) +* Add message body size limits in frontend and backend (zene) +* Add xid8 type +* Ensure planning encodes and scans cannot infinitely recurse +* Implement pgtype.UUID.String() (Konstantin Grachev) +* Switch from ExecParams to Exec in ValidateConnectTargetSessionAttrs functions (Alexander Rumyantsev) +* Update golang.org/x/crypto +* Fix json(b) columns prefer sql.Scanner interface like database/sql (Ludovico Russo) + # 5.7.1 (September 10, 2024) * Fix data race in tracelog.TraceLog diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/README.md b/event-processor/vendor/github.com/jackc/pgx/v5/README.md index 0cf2c291..cb709e21 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/README.md +++ b/event-processor/vendor/github.com/jackc/pgx/v5/README.md @@ -84,7 +84,7 @@ It is also possible to use the `database/sql` interface and convert a connection ## Testing -See CONTRIBUTING.md for setup instructions. +See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions. ## Architecture @@ -92,7 +92,7 @@ See the presentation at Golang Estonia, [PGX Top to Bottom](https://www.youtube. ## Supported Go and PostgreSQL Versions -pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.21 and higher and PostgreSQL 12 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/). +pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.23 and higher and PostgreSQL 13 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/). ## Version Policy @@ -126,7 +126,8 @@ pgerrcode contains constants for the PostgreSQL error codes. ## Adapters for 3rd Party Tracers -* [https://github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer) +* [github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer) +* [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx) ## Adapters for 3rd Party Loggers @@ -156,7 +157,7 @@ Library for scanning data from a database into Go structs and more. A carefully designed SQL client for making using SQL easier, more productive, and less error-prone on Golang. -### [https://github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5) +### [github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5) Adds GSSAPI / Kerberos authentication support. @@ -169,6 +170,22 @@ Explicit data mapping and scanning library for Go structs and slices. Type safe and flexible package for scanning database data into Go types. Supports, structs, maps, slices and custom mapping functions. -### [https://github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx) +### [github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx) Code first migration library for native pgx (no database/sql abstraction). + +### [github.com/amirsalarsafaei/sqlc-pgx-monitoring](https://github.com/amirsalarsafaei/sqlc-pgx-monitoring) + +A database monitoring/metrics library for pgx and sqlc. Trace, log and monitor your sqlc query performance using OpenTelemetry. + +### [https://github.com/nikolayk812/pgx-outbox](https://github.com/nikolayk812/pgx-outbox) + +Simple Golang implementation for transactional outbox pattern for PostgreSQL using jackc/pgx driver. + +### [https://github.com/Arlandaren/pgxWrappy](https://github.com/Arlandaren/pgxWrappy) + +Simplifies working with the pgx library, providing convenient scanning of nested structures. + +## [https://github.com/KoNekoD/pgx-colon-query-rewriter](https://github.com/KoNekoD/pgx-colon-query-rewriter) + +Implementation of the pgx query rewriter to use ':' instead of '@' in named query parameters. diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/Rakefile b/event-processor/vendor/github.com/jackc/pgx/v5/Rakefile index d957573e..3e3aa503 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/Rakefile +++ b/event-processor/vendor/github.com/jackc/pgx/v5/Rakefile @@ -2,7 +2,7 @@ require "erb" rule '.go' => '.go.erb' do |task| erb = ERB.new(File.read(task.source)) - File.write(task.name, "// Do not edit. Generated from #{task.source}\n" + erb.result(binding)) + File.write(task.name, "// Code generated from #{task.source}. DO NOT EDIT.\n\n" + erb.result(binding)) sh "goimports", "-w", task.name end diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/batch.go b/event-processor/vendor/github.com/jackc/pgx/v5/batch.go index c3c2834f..1b1cbd84 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/batch.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/batch.go @@ -43,6 +43,10 @@ func (qq *QueuedQuery) QueryRow(fn func(row Row) error) { } // Exec sets fn to be called when the response to qq is received. +// +// Note: for simple batch insert uses where it is not required to handle +// each potential error individually, it's sufficient to not set any callbacks, +// and just handle the return value of BatchResults.Close. func (qq *QueuedQuery) Exec(fn func(ct pgconn.CommandTag) error) { qq.Fn = func(br BatchResults) error { ct, err := br.Exec() @@ -83,7 +87,7 @@ func (b *Batch) Len() int { type BatchResults interface { // Exec reads the results from the next query in the batch as if the query has been sent with Conn.Exec. Prefer - // calling Exec on the QueuedQuery. + // calling Exec on the QueuedQuery, or just calling Close. Exec() (pgconn.CommandTag, error) // Query reads the results from the next query in the batch as if the query has been sent with Conn.Query. Prefer @@ -98,6 +102,9 @@ type BatchResults interface { // QueuedQuery.Query, QueuedQuery.QueryRow, or QueuedQuery.Exec will be called. If a callback function returns an // error or the batch encounters an error subsequent callback functions will not be called. // + // For simple batch inserts inside a transaction or similar queries, it's sufficient to not set any callbacks, + // and just handle the return value of Close. + // // Close must be called before the underlying connection can be used again. Any error that occurred during a batch // operation may have made it impossible to resyncronize the connection with the server. In this case the underlying // connection will have been closed. @@ -207,7 +214,6 @@ func (br *batchResults) Query() (Rows, error) { func (br *batchResults) QueryRow() Row { rows, _ := br.Query() return (*connRow)(rows.(*baseRows)) - } // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to @@ -220,6 +226,8 @@ func (br *batchResults) Close() error { } br.endTraced = true } + + invalidateCachesOnBatchResultsError(br.conn, br.b, br.err) }() if br.err != nil { @@ -378,7 +386,6 @@ func (br *pipelineBatchResults) Query() (Rows, error) { func (br *pipelineBatchResults) QueryRow() Row { rows, _ := br.Query() return (*connRow)(rows.(*baseRows)) - } // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to @@ -391,6 +398,8 @@ func (br *pipelineBatchResults) Close() error { } br.endTraced = true } + + invalidateCachesOnBatchResultsError(br.conn, br.b, br.err) }() if br.err == nil && br.lastRows != nil && br.lastRows.err != nil { @@ -441,3 +450,20 @@ func (br *pipelineBatchResults) nextQueryAndArgs() (query string, args []any, er br.qqIdx++ return bi.SQL, bi.Arguments, nil } + +// invalidates statement and description caches on batch results error +func invalidateCachesOnBatchResultsError(conn *Conn, b *Batch, err error) { + if err != nil && conn != nil && b != nil { + if sc := conn.statementCache; sc != nil { + for _, bi := range b.QueuedQueries { + sc.Invalidate(bi.SQL) + } + } + + if sc := conn.descriptionCache; sc != nil { + for _, bi := range b.QueuedQueries { + sc.Invalidate(bi.SQL) + } + } + } +} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/conn.go b/event-processor/vendor/github.com/jackc/pgx/v5/conn.go index 187b3dd5..67b22529 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/conn.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/conn.go @@ -172,7 +172,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con delete(config.RuntimeParams, "statement_cache_capacity") n, err := strconv.ParseInt(s, 10, 32) if err != nil { - return nil, fmt.Errorf("cannot parse statement_cache_capacity: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse statement_cache_capacity", err) } statementCacheCapacity = int(n) } @@ -182,7 +182,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con delete(config.RuntimeParams, "description_cache_capacity") n, err := strconv.ParseInt(s, 10, 32) if err != nil { - return nil, fmt.Errorf("cannot parse description_cache_capacity: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse description_cache_capacity", err) } descriptionCacheCapacity = int(n) } @@ -202,7 +202,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con case "simple_protocol": defaultQueryExecMode = QueryExecModeSimpleProtocol default: - return nil, fmt.Errorf("invalid default_query_exec_mode: %s", s) + return nil, pgconn.NewParseConfigError(connString, "invalid default_query_exec_mode", err) } } @@ -420,7 +420,7 @@ func (c *Conn) IsClosed() bool { return c.pgConn.IsClosed() } -func (c *Conn) die(err error) { +func (c *Conn) die() { if c.IsClosed() { return } @@ -588,14 +588,6 @@ func (c *Conn) execPrepared(ctx context.Context, sd *pgconn.StatementDescription return result.CommandTag, result.Err } -type unknownArgumentTypeQueryExecModeExecError struct { - arg any -} - -func (e *unknownArgumentTypeQueryExecModeExecError) Error() string { - return fmt.Sprintf("cannot use unregistered type %T as query argument in QueryExecModeExec", e.arg) -} - func (c *Conn) execSQLParams(ctx context.Context, sql string, args []any) (pgconn.CommandTag, error) { err := c.eqb.Build(c.typeMap, nil, args) if err != nil { @@ -650,21 +642,33 @@ const ( // registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are // unregistered or ambiguous. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know // the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot. + // + // On rare occasions user defined types may behave differently when encoded in the text format instead of the binary + // format. For example, this could happen if a "type RomanNumeral int32" implements fmt.Stringer to format integers as + // Roman numerals (e.g. 7 is VII). The binary format would properly encode the integer 7 as the binary value for 7. + // But the text format would encode the integer 7 as the string "VII". As QueryExecModeExec uses the text format, it + // is possible that changing query mode from another mode to QueryExecModeExec could change the behavior of the query. + // This should not occur with types pgx supports directly and can be avoided by registering the types with + // pgtype.Map.RegisterDefaultPgType and implementing the appropriate type interfaces. In the cas of RomanNumeral, it + // should implement pgtype.Int64Valuer. QueryExecModeExec - // Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments. - // Queries are executed in a single round trip. Type mappings can be registered with + // Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments. This is + // especially significant for []byte values. []byte values are encoded as PostgreSQL bytea. string must be used + // instead for text type values including json and jsonb. Type mappings can be registered with // pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambiguous. - // e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use - // a map[string]string directly as an argument. This mode cannot. + // e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use a + // map[string]string directly as an argument. This mode cannot. Queries are executed in a single round trip. // - // QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec with minor - // exceptions such as behavior when multiple result returning queries are erroneously sent in a single string. + // QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec. This includes + // the warning regarding differences in text format and binary format encoding with user defined types. There may be + // other minor exceptions such as behavior when multiple result returning queries are erroneously sent in a single + // string. // // QueryExecModeSimpleProtocol uses client side parameter interpolation. All values are quoted and escaped. Prefer - // QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol - // should only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does - // not support the extended protocol. + // QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol should + // only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does not + // support the extended protocol. QueryExecModeSimpleProtocol ) @@ -904,6 +908,9 @@ func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) Row { // SendBatch sends all queued queries to the server at once. All queries are run in an implicit transaction unless // explicit transaction control statements are executed. The returned BatchResults must be closed before the connection // is used again. +// +// Depending on the QueryExecMode, all queries may be prepared before any are executed. This means that creating a table +// and using it in a subsequent query in the same batch can fail. func (c *Conn) SendBatch(ctx context.Context, b *Batch) (br BatchResults) { if c.batchTracer != nil { ctx = c.batchTracer.TraceBatchStart(ctx, c, TraceBatchStartData{Batch: b}) @@ -1126,47 +1133,64 @@ func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, d // Prepare any needed queries if len(distinctNewQueries) > 0 { - for _, sd := range distinctNewQueries { - pipeline.SendPrepare(sd.Name, sd.SQL, nil) - } + err := func() (err error) { + for _, sd := range distinctNewQueries { + pipeline.SendPrepare(sd.Name, sd.SQL, nil) + } - err := pipeline.Sync() - if err != nil { - return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true} - } + // Store all statements we are preparing into the cache. It's fine if it overflows because HandleInvalidated will + // clean them up later. + if sdCache != nil { + for _, sd := range distinctNewQueries { + sdCache.Put(sd) + } + } + + // If something goes wrong preparing the statements, we need to invalidate the cache entries we just added. + defer func() { + if err != nil && sdCache != nil { + for _, sd := range distinctNewQueries { + sdCache.Invalidate(sd.SQL) + } + } + }() + + err = pipeline.Sync() + if err != nil { + return err + } + + for _, sd := range distinctNewQueries { + results, err := pipeline.GetResults() + if err != nil { + return err + } + + resultSD, ok := results.(*pgconn.StatementDescription) + if !ok { + return fmt.Errorf("expected statement description, got %T", results) + } + + // Fill in the previously empty / pending statement descriptions. + sd.ParamOIDs = resultSD.ParamOIDs + sd.Fields = resultSD.Fields + } - for _, sd := range distinctNewQueries { results, err := pipeline.GetResults() if err != nil { - return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true} + return err } - resultSD, ok := results.(*pgconn.StatementDescription) + _, ok := results.(*pgconn.PipelineSync) if !ok { - return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected statement description, got %T", results), closed: true} + return fmt.Errorf("expected sync, got %T", results) } - // Fill in the previously empty / pending statement descriptions. - sd.ParamOIDs = resultSD.ParamOIDs - sd.Fields = resultSD.Fields - } - - results, err := pipeline.GetResults() + return nil + }() if err != nil { return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true} } - - _, ok := results.(*pgconn.PipelineSync) - if !ok { - return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected sync, got %T", results), closed: true} - } - } - - // Put all statements into the cache. It's fine if it overflows because HandleInvalidated will clean them up later. - if sdCache != nil { - for _, sd := range distinctNewQueries { - sdCache.Put(sd) - } } // Queue the queries. diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/derived_types.go b/event-processor/vendor/github.com/jackc/pgx/v5/derived_types.go index 22ab069c..72c0a242 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/derived_types.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/derived_types.go @@ -161,7 +161,7 @@ type derivedTypeInfo struct { // The result of this call can be passed into RegisterTypes to complete the process. func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Type, error) { m := c.TypeMap() - if typeNames == nil || len(typeNames) == 0 { + if len(typeNames) == 0 { return nil, fmt.Errorf("No type names were supplied.") } @@ -169,13 +169,7 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ // the SQL not support recent structures such as multirange serverVersion, _ := serverVersion(c) sql := buildLoadDerivedTypesSQL(serverVersion, typeNames) - var rows Rows - var err error - if typeNames == nil { - rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol) - } else { - rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames) - } + rows, err := c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames) if err != nil { return nil, fmt.Errorf("While generating load types query: %w", err) } @@ -232,15 +226,15 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ default: return nil, fmt.Errorf("Unknown typtype %q was found while registering %q", ti.Typtype, ti.TypeName) } - if type_ != nil { - m.RegisterType(type_) - if ti.NspName != "" { - nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec} - m.RegisterType(nspType) - result = append(result, nspType) - } - result = append(result, type_) + + // the type_ is imposible to be null + m.RegisterType(type_) + if ti.NspName != "" { + nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec} + m.RegisterType(nspType) + result = append(result, nspType) } + result = append(result, type_) } return result, nil } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/doc.go b/event-processor/vendor/github.com/jackc/pgx/v5/doc.go index 0e91d64e..5d2ae388 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/doc.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/doc.go @@ -183,7 +183,7 @@ For debug tracing of the actual PostgreSQL wire protocol messages see github.com Lower Level PostgreSQL Functionality -github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn in +github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn is implemented on top of pgconn. The Conn.PgConn() method can be used to access this lower layer. PgBouncer diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh b/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh new file mode 100644 index 00000000..ec0f7b03 --- /dev/null +++ b/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +current_branch=$(git rev-parse --abbrev-ref HEAD) +if [ "$current_branch" == "HEAD" ]; then + current_branch=$(git rev-parse HEAD) +fi + +restore_branch() { + echo "Restoring original branch/commit: $current_branch" + git checkout "$current_branch" +} +trap restore_branch EXIT + +# Check if there are uncommitted changes +if ! git diff --quiet || ! git diff --cached --quiet; then + echo "There are uncommitted changes. Please commit or stash them before running this script." + exit 1 +fi + +# Ensure that at least one commit argument is passed +if [ "$#" -lt 1 ]; then + echo "Usage: $0 ... " + exit 1 +fi + +commits=("$@") +benchmarks_dir=benchmarks + +if ! mkdir -p "${benchmarks_dir}"; then + echo "Unable to create dir for benchmarks data" + exit 1 +fi + +# Benchmark results +bench_files=() + +# Run benchmark for each listed commit +for i in "${!commits[@]}"; do + commit="${commits[i]}" + git checkout "$commit" || { + echo "Failed to checkout $commit" + exit 1 + } + + # Sanitized commmit message + commit_message=$(git log -1 --pretty=format:"%s" | tr -c '[:alnum:]-_' '_') + + # Benchmark data will go there + bench_file="${benchmarks_dir}/${i}_${commit_message}.bench" + + if ! go test -bench=. -count=10 >"$bench_file"; then + echo "Benchmarking failed for commit $commit" + exit 1 + fi + + bench_files+=("$bench_file") +done + +# go install golang.org/x/perf/cmd/benchstat[@latest] +benchstat "${bench_files[@]}" diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go index df58c448..b516817c 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go @@ -4,8 +4,10 @@ import ( "bytes" "encoding/hex" "fmt" + "slices" "strconv" "strings" + "sync" "time" "unicode/utf8" ) @@ -24,18 +26,33 @@ type Query struct { // https://github.com/jackc/pgx/issues/1380 const replacementcharacterwidth = 3 +const maxBufSize = 16384 // 16 Ki + +var bufPool = &pool[*bytes.Buffer]{ + new: func() *bytes.Buffer { + return &bytes.Buffer{} + }, + reset: func(b *bytes.Buffer) bool { + n := b.Len() + b.Reset() + return n < maxBufSize + }, +} + +var null = []byte("null") + func (q *Query) Sanitize(args ...any) (string, error) { argUse := make([]bool, len(args)) - buf := &bytes.Buffer{} + buf := bufPool.get() + defer bufPool.put(buf) for _, part := range q.Parts { - var str string switch part := part.(type) { case string: - str = part + buf.WriteString(part) case int: argIdx := part - 1 - + var p []byte if argIdx < 0 { return "", fmt.Errorf("first sql argument must be > 0") } @@ -43,34 +60,41 @@ func (q *Query) Sanitize(args ...any) (string, error) { if argIdx >= len(args) { return "", fmt.Errorf("insufficient arguments") } + + // Prevent SQL injection via Line Comment Creation + // https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p + buf.WriteByte(' ') + arg := args[argIdx] switch arg := arg.(type) { case nil: - str = "null" + p = null case int64: - str = strconv.FormatInt(arg, 10) + p = strconv.AppendInt(buf.AvailableBuffer(), arg, 10) case float64: - str = strconv.FormatFloat(arg, 'f', -1, 64) + p = strconv.AppendFloat(buf.AvailableBuffer(), arg, 'f', -1, 64) case bool: - str = strconv.FormatBool(arg) + p = strconv.AppendBool(buf.AvailableBuffer(), arg) case []byte: - str = QuoteBytes(arg) + p = QuoteBytes(buf.AvailableBuffer(), arg) case string: - str = QuoteString(arg) + p = QuoteString(buf.AvailableBuffer(), arg) case time.Time: - str = arg.Truncate(time.Microsecond).Format("'2006-01-02 15:04:05.999999999Z07:00:00'") + p = arg.Truncate(time.Microsecond). + AppendFormat(buf.AvailableBuffer(), "'2006-01-02 15:04:05.999999999Z07:00:00'") default: return "", fmt.Errorf("invalid arg type: %T", arg) } argUse[argIdx] = true + buf.Write(p) + // Prevent SQL injection via Line Comment Creation // https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p - str = " " + str + " " + buf.WriteByte(' ') default: return "", fmt.Errorf("invalid Part type: %T", part) } - buf.WriteString(str) } for i, used := range argUse { @@ -82,26 +106,99 @@ func (q *Query) Sanitize(args ...any) (string, error) { } func NewQuery(sql string) (*Query, error) { - l := &sqlLexer{ - src: sql, - stateFn: rawState, + query := &Query{} + query.init(sql) + + return query, nil +} + +var sqlLexerPool = &pool[*sqlLexer]{ + new: func() *sqlLexer { + return &sqlLexer{} + }, + reset: func(sl *sqlLexer) bool { + *sl = sqlLexer{} + return true + }, +} + +func (q *Query) init(sql string) { + parts := q.Parts[:0] + if parts == nil { + // dirty, but fast heuristic to preallocate for ~90% usecases + n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1 + parts = make([]Part, 0, n) } + l := sqlLexerPool.get() + defer sqlLexerPool.put(l) + + l.src = sql + l.stateFn = rawState + l.parts = parts + for l.stateFn != nil { l.stateFn = l.stateFn(l) } - query := &Query{Parts: l.parts} - - return query, nil + q.Parts = l.parts } -func QuoteString(str string) string { - return "'" + strings.ReplaceAll(str, "'", "''") + "'" +func QuoteString(dst []byte, str string) []byte { + const quote = '\'' + + // Preallocate space for the worst case scenario + dst = slices.Grow(dst, len(str)*2+2) + + // Add opening quote + dst = append(dst, quote) + + // Iterate through the string without allocating + for i := 0; i < len(str); i++ { + if str[i] == quote { + dst = append(dst, quote, quote) + } else { + dst = append(dst, str[i]) + } + } + + // Add closing quote + dst = append(dst, quote) + + return dst } -func QuoteBytes(buf []byte) string { - return `'\x` + hex.EncodeToString(buf) + "'" +func QuoteBytes(dst, buf []byte) []byte { + if len(buf) == 0 { + return append(dst, `'\x'`...) + } + + // Calculate required length + requiredLen := 3 + hex.EncodedLen(len(buf)) + 1 + + // Ensure dst has enough capacity + if cap(dst)-len(dst) < requiredLen { + newDst := make([]byte, len(dst), len(dst)+requiredLen) + copy(newDst, dst) + dst = newDst + } + + // Record original length and extend slice + origLen := len(dst) + dst = dst[:origLen+requiredLen] + + // Add prefix + dst[origLen] = '\'' + dst[origLen+1] = '\\' + dst[origLen+2] = 'x' + + // Encode bytes directly into dst + hex.Encode(dst[origLen+3:len(dst)-1], buf) + + // Add suffix + dst[len(dst)-1] = '\'' + + return dst } type sqlLexer struct { @@ -319,13 +416,45 @@ func multilineCommentState(l *sqlLexer) stateFn { } } +var queryPool = &pool[*Query]{ + new: func() *Query { + return &Query{} + }, + reset: func(q *Query) bool { + n := len(q.Parts) + q.Parts = q.Parts[:0] + return n < 64 // drop too large queries + }, +} + // SanitizeSQL replaces placeholder values with args. It quotes and escapes args // as necessary. This function is only safe when standard_conforming_strings is // on. func SanitizeSQL(sql string, args ...any) (string, error) { - query, err := NewQuery(sql) - if err != nil { - return "", err - } + query := queryPool.get() + query.init(sql) + defer queryPool.put(query) + return query.Sanitize(args...) } + +type pool[E any] struct { + p sync.Pool + new func() E + reset func(E) bool +} + +func (pool *pool[E]) get() E { + v, ok := pool.p.Get().(E) + if !ok { + v = pool.new() + } + + return v +} + +func (p *pool[E]) put(v E) { + if p.reset(v) { + p.p.Put(v) + } +} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go b/event-processor/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go index dec83f47..17fec937 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go @@ -31,7 +31,6 @@ func (c *LRUCache) Get(key string) *pgconn.StatementDescription { } return nil - } // Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache or diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go index 06498361..f846ba81 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go @@ -263,7 +263,7 @@ func computeClientProof(saltedPassword, authMessage []byte) []byte { return buf } -func computeServerSignature(saltedPassword []byte, authMessage []byte) []byte { +func computeServerSignature(saltedPassword, authMessage []byte) []byte { serverKey := computeHMAC(saltedPassword, []byte("Server Key")) serverSignature := computeHMAC(serverKey, authMessage) buf := make([]byte, base64.StdEncoding.EncodedLen(len(serverSignature))) diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/config.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/config.go index 6a198e67..3937dc40 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/config.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/config.go @@ -23,9 +23,11 @@ import ( "github.com/jackc/pgx/v5/pgproto3" ) -type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error -type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error -type GetSSLPasswordFunc func(ctx context.Context) string +type ( + AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error + ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error + GetSSLPasswordFunc func(ctx context.Context) string +) // Config is the settings used to establish a connection to a PostgreSQL server. It must be created by [ParseConfig]. A // manually initialized Config will cause ConnectConfig to panic. @@ -51,6 +53,8 @@ type Config struct { KerberosSpn string Fallbacks []*FallbackConfig + SSLNegotiation string // sslnegotiation=postgres or sslnegotiation=direct + // ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server. // It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next // fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs. @@ -177,7 +181,7 @@ func NetworkAddress(host string, port uint16) (network, address string) { // // ParseConfig supports specifying multiple hosts in similar manner to libpq. Host and port may include comma separated // values that will be tried in order. This can be used as part of a high availability system. See -// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information. +// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information. // // # Example URL // postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb @@ -198,13 +202,15 @@ func NetworkAddress(host string, port uint16) (network, address string) { // PGSSLKEY // PGSSLROOTCERT // PGSSLPASSWORD +// PGOPTIONS // PGAPPNAME // PGCONNECT_TIMEOUT // PGTARGETSESSIONATTRS +// PGTZ // -// See http://www.postgresql.org/docs/11/static/libpq-envars.html for details on the meaning of environment variables. +// See http://www.postgresql.org/docs/current/static/libpq-envars.html for details on the meaning of environment variables. // -// See https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are +// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are // usually but not always the environment variable name downcased and without the "PG" prefix. // // Important Security Notes: @@ -212,7 +218,7 @@ func NetworkAddress(host string, port uint16) (network, address string) { // ParseConfig tries to match libpq behavior with regard to PGSSLMODE. This includes defaulting to "prefer" behavior if // not set. // -// See http://www.postgresql.org/docs/11/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of +// See http://www.postgresql.org/docs/current/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of // security each sslmode provides. // // The sslmode "prefer" (the default), sslmode "allow", and multiple hosts are implemented via the Fallbacks field of @@ -318,6 +324,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con "sslkey": {}, "sslcert": {}, "sslrootcert": {}, + "sslnegotiation": {}, "sslpassword": {}, "sslsni": {}, "krbspn": {}, @@ -386,6 +393,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con config.Port = fallbacks[0].Port config.TLSConfig = fallbacks[0].TLSConfig config.Fallbacks = fallbacks[1:] + config.SSLNegotiation = settings["sslnegotiation"] passfile, err := pgpassfile.ReadPassfile(settings["passfile"]) if err == nil { @@ -449,9 +457,12 @@ func parseEnvSettings() map[string]string { "PGSSLSNI": "sslsni", "PGSSLROOTCERT": "sslrootcert", "PGSSLPASSWORD": "sslpassword", + "PGSSLNEGOTIATION": "sslnegotiation", "PGTARGETSESSIONATTRS": "target_session_attrs", "PGSERVICE": "service", "PGSERVICEFILE": "servicefile", + "PGTZ": "timezone", + "PGOPTIONS": "options", } for envname, realname := range nameMap { @@ -646,6 +657,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P sslkey := settings["sslkey"] sslpassword := settings["sslpassword"] sslsni := settings["sslsni"] + sslnegotiation := settings["sslnegotiation"] // Match libpq default behavior if sslmode == "" { @@ -657,6 +669,13 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P tlsConfig := &tls.Config{} + if sslnegotiation == "direct" { + tlsConfig.NextProtos = []string{"postgresql"} + if sslmode == "prefer" { + sslmode = "require" + } + } + if sslrootcert != "" { var caCertPool *x509.CertPool @@ -696,7 +715,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P // According to PostgreSQL documentation, if a root CA file exists, // the behavior of sslmode=require should be the same as that of verify-ca // - // See https://www.postgresql.org/docs/12/libpq-ssl.html + // See https://www.postgresql.org/docs/current/libpq-ssl.html if sslrootcert != "" { goto nextCase } @@ -767,8 +786,8 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P if sslpassword != "" { decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword)) } - //if sslpassword not provided or has decryption error when use it - //try to find sslpassword with callback function + // if sslpassword not provided or has decryption error when use it + // try to find sslpassword with callback function if sslpassword == "" || decryptedError != nil { if parseConfigOptions.GetSSLPassword != nil { sslpassword = parseConfigOptions.GetSSLPassword(context.Background()) @@ -861,12 +880,12 @@ func makeConnectTimeoutDialFunc(timeout time.Duration) DialFunc { // ValidateConnectTargetSessionAttrsReadWrite is a ValidateConnectFunc that implements libpq compatible // target_session_attrs=read-write. func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error { - result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read() - if result.Err != nil { - return result.Err + result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll() + if err != nil { + return err } - if string(result.Rows[0][0]) == "on" { + if string(result[0].Rows[0][0]) == "on" { return errors.New("read only connection") } @@ -876,12 +895,12 @@ func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgC // ValidateConnectTargetSessionAttrsReadOnly is a ValidateConnectFunc that implements libpq compatible // target_session_attrs=read-only. func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error { - result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read() - if result.Err != nil { - return result.Err + result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll() + if err != nil { + return err } - if string(result.Rows[0][0]) != "on" { + if string(result[0].Rows[0][0]) != "on" { return errors.New("connection is not read only") } @@ -891,12 +910,12 @@ func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgCo // ValidateConnectTargetSessionAttrsStandby is a ValidateConnectFunc that implements libpq compatible // target_session_attrs=standby. func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error { - result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read() - if result.Err != nil { - return result.Err + result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll() + if err != nil { + return err } - if string(result.Rows[0][0]) != "t" { + if string(result[0].Rows[0][0]) != "t" { return errors.New("server is not in hot standby mode") } @@ -906,12 +925,12 @@ func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgCon // ValidateConnectTargetSessionAttrsPrimary is a ValidateConnectFunc that implements libpq compatible // target_session_attrs=primary. func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error { - result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read() - if result.Err != nil { - return result.Err + result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll() + if err != nil { + return err } - if string(result.Rows[0][0]) == "t" { + if string(result[0].Rows[0][0]) == "t" { return errors.New("server is in standby mode") } @@ -921,12 +940,12 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon // ValidateConnectTargetSessionAttrsPreferStandby is a ValidateConnectFunc that implements libpq compatible // target_session_attrs=prefer-standby. func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error { - result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read() - if result.Err != nil { - return result.Err + result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll() + if err != nil { + return err } - if string(result.Rows[0][0]) != "t" { + if string(result[0].Rows[0][0]) != "t" { return &NotPreferredError{err: errors.New("server is not in hot standby mode")} } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/errors.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/errors.go index ec4a6d47..d968d3f0 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/errors.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/errors.go @@ -27,7 +27,7 @@ func Timeout(err error) bool { } // PgError represents an error reported by the PostgreSQL server. See -// http://www.postgresql.org/docs/11/static/protocol-error-fields.html for +// http://www.postgresql.org/docs/current/static/protocol-error-fields.html for // detailed field description. type PgError struct { Severity string @@ -112,6 +112,14 @@ type ParseConfigError struct { err error } +func NewParseConfigError(conn, msg string, err error) error { + return &ParseConfigError{ + ConnString: conn, + msg: msg, + err: err, + } +} + func (e *ParseConfigError) Error() string { // Now that ParseConfigError is public and ConnString is available to the developer, perhaps it would be better only // return a static string. That would ensure that the error message cannot leak a password. The ConnString field would diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go index 3c1af347..efb0d61b 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go @@ -28,7 +28,7 @@ func RegisterGSSProvider(newGSSArg NewGSSFunc) { // GSS provides GSSAPI authentication (e.g., Kerberos). type GSS interface { - GetInitToken(host string, service string) ([]byte, error) + GetInitToken(host, service string) ([]byte, error) GetInitTokenFromSPN(spn string) ([]byte, error) Continue(inToken []byte) (done bool, outToken []byte, err error) } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go index 7efb522a..97141c64 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go @@ -1,6 +1,7 @@ package pgconn import ( + "container/list" "context" "crypto/md5" "crypto/tls" @@ -134,7 +135,7 @@ func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptio // // If config.Fallbacks are present they will sequentially be tried in case of error establishing network connection. An // authentication error will terminate the chain of attempts (like libpq: -// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error. +// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error. func ConnectConfig(ctx context.Context, config *Config) (*PgConn, error) { // Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from // zero values. @@ -267,12 +268,15 @@ func connectPreferred(ctx context.Context, config *Config, connectOneConfigs []* var pgErr *PgError if errors.As(err, &pgErr) { - const ERRCODE_INVALID_PASSWORD = "28P01" // wrong password - const ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION = "28000" // wrong password or bad pg_hba.conf settings - const ERRCODE_INVALID_CATALOG_NAME = "3D000" // db does not exist - const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501" // missing connect privilege + // pgx will try next host even if libpq does not in certain cases (see #2246) + // consider change for the next major version + + const ERRCODE_INVALID_PASSWORD = "28P01" + const ERRCODE_INVALID_CATALOG_NAME = "3D000" // db does not exist + const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501" // missing connect privilege + + // auth failed due to invalid password, db does not exist or user has no permission if pgErr.Code == ERRCODE_INVALID_PASSWORD || - pgErr.Code == ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION && c.tlsConfig != nil || pgErr.Code == ERRCODE_INVALID_CATALOG_NAME || pgErr.Code == ERRCODE_INSUFFICIENT_PRIVILEGE { return nil, allErrors @@ -321,7 +325,15 @@ func connectOne(ctx context.Context, config *Config, connectConfig *connectOneCo if connectConfig.tlsConfig != nil { pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn}) pgConn.contextWatcher.Watch(ctx) - tlsConn, err := startTLS(pgConn.conn, connectConfig.tlsConfig) + var ( + tlsConn net.Conn + err error + ) + if config.SSLNegotiation == "direct" { + tlsConn = tls.Client(pgConn.conn, connectConfig.tlsConfig) + } else { + tlsConn, err = startTLS(pgConn.conn, connectConfig.tlsConfig) + } pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS. if err != nil { pgConn.conn.Close() @@ -979,7 +991,8 @@ func noticeResponseToNotice(msg *pgproto3.NoticeResponse) *Notice { // CancelRequest sends a cancel request to the PostgreSQL server. It returns an error if unable to deliver the cancel // request, but lack of an error does not ensure that the query was canceled. As specified in the documentation, there -// is no way to be sure a query was canceled. See https://www.postgresql.org/docs/11/protocol-flow.html#id-1.10.5.7.9 +// is no way to be sure a query was canceled. +// See https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-CANCELING-REQUESTS func (pgConn *PgConn) CancelRequest(ctx context.Context) error { // Open a cancellation request to the same server. The address is taken from the net.Conn directly instead of reusing // the connection config. This is important in high availability configurations where fallback connections may be @@ -1128,7 +1141,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader { // binary format. If resultFormats is nil all results will be in text format. // // ResultReader must be closed before PgConn can be used again. -func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader { +func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { return result @@ -1154,7 +1167,7 @@ func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [] // binary format. If resultFormats is nil all results will be in text format. // // ResultReader must be closed before PgConn can be used again. -func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) *ResultReader { +func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { return result @@ -1361,7 +1374,14 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co close(pgConn.cleanupDone) return CommandTag{}, normalizeTimeoutError(ctx, err) } - msg, _ := pgConn.receiveMessage() + // peekMessage never returns err in the bufferingReceive mode - it only forwards the bufferingReceive variables. + // Therefore, the only case for receiveMessage to return err is during handling of the ErrorResponse message type + // and using pgOnError handler to determine the connection is no longer valid (and thus closing the conn). + msg, serverError := pgConn.receiveMessage() + if serverError != nil { + close(abortCopyChan) + return CommandTag{}, serverError + } switch msg := msg.(type) { case *pgproto3.ErrorResponse: @@ -1408,9 +1428,8 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co // MultiResultReader is a reader for a command that could return multiple results such as Exec or ExecBatch. type MultiResultReader struct { - pgConn *PgConn - ctx context.Context - pipeline *Pipeline + pgConn *PgConn + ctx context.Context rr *ResultReader @@ -1443,12 +1462,8 @@ func (mrr *MultiResultReader) receiveMessage() (pgproto3.BackendMessage, error) switch msg := msg.(type) { case *pgproto3.ReadyForQuery: mrr.closed = true - if mrr.pipeline != nil { - mrr.pipeline.expectedReadyForQueryCount-- - } else { - mrr.pgConn.contextWatcher.Unwatch() - mrr.pgConn.unlock() - } + mrr.pgConn.contextWatcher.Unwatch() + mrr.pgConn.unlock() case *pgproto3.ErrorResponse: mrr.err = ErrorResponseToPgError(msg) } @@ -1672,7 +1687,11 @@ func (rr *ResultReader) receiveMessage() (msg pgproto3.BackendMessage, err error case *pgproto3.EmptyQueryResponse: rr.concludeCommand(CommandTag{}, nil) case *pgproto3.ErrorResponse: - rr.concludeCommand(CommandTag{}, ErrorResponseToPgError(msg)) + pgErr := ErrorResponseToPgError(msg) + if rr.pipeline != nil { + rr.pipeline.state.HandleError(pgErr) + } + rr.concludeCommand(CommandTag{}, pgErr) } return msg, nil @@ -1701,7 +1720,7 @@ type Batch struct { } // ExecParams appends an ExecParams command to the batch. See PgConn.ExecParams for parameter descriptions. -func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) { +func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) { if batch.err != nil { return } @@ -1714,7 +1733,7 @@ func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uin } // ExecPrepared appends an ExecPrepared e command to the batch. See PgConn.ExecPrepared for parameter descriptions. -func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) { +func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) { if batch.err != nil { return } @@ -1773,9 +1792,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR batch.buf, batch.err = (&pgproto3.Sync{}).Encode(batch.buf) if batch.err != nil { + pgConn.contextWatcher.Unwatch() + multiResult.err = normalizeTimeoutError(multiResult.ctx, batch.err) multiResult.closed = true - multiResult.err = batch.err - pgConn.unlock() + pgConn.asyncClose() return multiResult } @@ -1783,9 +1803,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR defer pgConn.exitPotentialWriteReadDeadlock() _, err := pgConn.conn.Write(batch.buf) if err != nil { + pgConn.contextWatcher.Unwatch() + multiResult.err = normalizeTimeoutError(multiResult.ctx, err) multiResult.closed = true - multiResult.err = err - pgConn.unlock() + pgConn.asyncClose() return multiResult } @@ -1999,9 +2020,7 @@ type Pipeline struct { conn *PgConn ctx context.Context - expectedReadyForQueryCount int - pendingSync bool - + state pipelineState err error closed bool } @@ -2012,6 +2031,122 @@ type PipelineSync struct{} // CloseComplete is returned by GetResults when a CloseComplete message is received. type CloseComplete struct{} +type pipelineRequestType int + +const ( + pipelineNil pipelineRequestType = iota + pipelinePrepare + pipelineQueryParams + pipelineQueryPrepared + pipelineDeallocate + pipelineSyncRequest + pipelineFlushRequest +) + +type pipelineRequestEvent struct { + RequestType pipelineRequestType + WasSentToServer bool + BeforeFlushOrSync bool +} + +type pipelineState struct { + requestEventQueue list.List + lastRequestType pipelineRequestType + pgErr *PgError + expectedReadyForQueryCount int +} + +func (s *pipelineState) Init() { + s.requestEventQueue.Init() + s.lastRequestType = pipelineNil +} + +func (s *pipelineState) RegisterSendingToServer() { + for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() { + val := elem.Value.(pipelineRequestEvent) + if val.WasSentToServer { + return + } + val.WasSentToServer = true + elem.Value = val + } +} + +func (s *pipelineState) registerFlushingBufferOnServer() { + for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() { + val := elem.Value.(pipelineRequestEvent) + if val.BeforeFlushOrSync { + return + } + val.BeforeFlushOrSync = true + elem.Value = val + } +} + +func (s *pipelineState) PushBackRequestType(req pipelineRequestType) { + if req == pipelineNil { + return + } + + if req != pipelineFlushRequest { + s.requestEventQueue.PushBack(pipelineRequestEvent{RequestType: req}) + } + if req == pipelineFlushRequest || req == pipelineSyncRequest { + s.registerFlushingBufferOnServer() + } + s.lastRequestType = req + + if req == pipelineSyncRequest { + s.expectedReadyForQueryCount++ + } +} + +func (s *pipelineState) ExtractFrontRequestType() pipelineRequestType { + for { + elem := s.requestEventQueue.Front() + if elem == nil { + return pipelineNil + } + val := elem.Value.(pipelineRequestEvent) + if !(val.WasSentToServer && val.BeforeFlushOrSync) { + return pipelineNil + } + + s.requestEventQueue.Remove(elem) + if val.RequestType == pipelineSyncRequest { + s.pgErr = nil + } + if s.pgErr == nil { + return val.RequestType + } + } +} + +func (s *pipelineState) HandleError(err *PgError) { + s.pgErr = err +} + +func (s *pipelineState) HandleReadyForQuery() { + s.expectedReadyForQueryCount-- +} + +func (s *pipelineState) PendingSync() bool { + var notPendingSync bool + + if elem := s.requestEventQueue.Back(); elem != nil { + val := elem.Value.(pipelineRequestEvent) + notPendingSync = (val.RequestType == pipelineSyncRequest) && val.WasSentToServer + } else { + notPendingSync = (s.lastRequestType == pipelineSyncRequest) || (s.lastRequestType == pipelineNil) + } + + return !notPendingSync +} + +func (s *pipelineState) ExpectedReadyForQuery() int { + return s.expectedReadyForQueryCount +} + // StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent // to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection // to normal mode. While in pipeline mode, no methods that communicate with the server may be called except @@ -2020,16 +2155,21 @@ type CloseComplete struct{} // Prefer ExecBatch when only sending one group of queries at once. func (pgConn *PgConn) StartPipeline(ctx context.Context) *Pipeline { if err := pgConn.lock(); err != nil { - return &Pipeline{ + pipeline := &Pipeline{ closed: true, err: err, } + pipeline.state.Init() + + return pipeline } pgConn.pipeline = Pipeline{ conn: pgConn, ctx: ctx, } + pgConn.pipeline.state.Init() + pipeline := &pgConn.pipeline if ctx != context.Background() { @@ -2052,10 +2192,10 @@ func (p *Pipeline) SendPrepare(name, sql string, paramOIDs []uint32) { if p.closed { return } - p.pendingSync = true p.conn.frontend.SendParse(&pgproto3.Parse{Name: name, Query: sql, ParameterOIDs: paramOIDs}) p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name}) + p.state.PushBackRequestType(pipelinePrepare) } // SendDeallocate deallocates a prepared statement. @@ -2063,34 +2203,65 @@ func (p *Pipeline) SendDeallocate(name string) { if p.closed { return } - p.pendingSync = true p.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: name}) + p.state.PushBackRequestType(pipelineDeallocate) } // SendQueryParams is the pipeline version of *PgConn.QueryParams. -func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) { +func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) { if p.closed { return } - p.pendingSync = true p.conn.frontend.SendParse(&pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs}) p.conn.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats}) p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'}) p.conn.frontend.SendExecute(&pgproto3.Execute{}) + p.state.PushBackRequestType(pipelineQueryParams) } // SendQueryPrepared is the pipeline version of *PgConn.QueryPrepared. -func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) { +func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) { if p.closed { return } - p.pendingSync = true p.conn.frontend.SendBind(&pgproto3.Bind{PreparedStatement: stmtName, ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats}) p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'}) p.conn.frontend.SendExecute(&pgproto3.Execute{}) + p.state.PushBackRequestType(pipelineQueryPrepared) +} + +// SendFlushRequest sends a request for the server to flush its output buffer. +// +// The server flushes its output buffer automatically as a result of Sync being called, +// or on any request when not in pipeline mode; this function is useful to cause the server +// to flush its output buffer in pipeline mode without establishing a synchronization point. +// Note that the request is not itself flushed to the server automatically; use Flush if +// necessary. This copies the behavior of libpq PQsendFlushRequest. +func (p *Pipeline) SendFlushRequest() { + if p.closed { + return + } + + p.conn.frontend.Send(&pgproto3.Flush{}) + p.state.PushBackRequestType(pipelineFlushRequest) +} + +// SendPipelineSync marks a synchronization point in a pipeline by sending a sync message +// without flushing the send buffer. This serves as the delimiter of an implicit +// transaction and an error recovery point. +// +// Note that the request is not itself flushed to the server automatically; use Flush if +// necessary. This copies the behavior of libpq PQsendPipelineSync. +func (p *Pipeline) SendPipelineSync() { + if p.closed { + return + } + + p.conn.frontend.SendSync(&pgproto3.Sync{}) + p.state.PushBackRequestType(pipelineSyncRequest) } // Flush flushes the queued requests without establishing a synchronization point. @@ -2115,28 +2286,14 @@ func (p *Pipeline) Flush() error { return err } + p.state.RegisterSendingToServer() return nil } // Sync establishes a synchronization point and flushes the queued requests. func (p *Pipeline) Sync() error { - if p.closed { - if p.err != nil { - return p.err - } - return errors.New("pipeline closed") - } - - p.conn.frontend.SendSync(&pgproto3.Sync{}) - err := p.Flush() - if err != nil { - return err - } - - p.pendingSync = false - p.expectedReadyForQueryCount++ - - return nil + p.SendPipelineSync() + return p.Flush() } // GetResults gets the next results. If results are present, results may be a *ResultReader, *StatementDescription, or @@ -2150,7 +2307,7 @@ func (p *Pipeline) GetResults() (results any, err error) { return nil, errors.New("pipeline closed") } - if p.expectedReadyForQueryCount == 0 { + if p.state.ExtractFrontRequestType() == pipelineNil { return nil, nil } @@ -2195,13 +2352,13 @@ func (p *Pipeline) getResults() (results any, err error) { case *pgproto3.CloseComplete: return &CloseComplete{}, nil case *pgproto3.ReadyForQuery: - p.expectedReadyForQueryCount-- + p.state.HandleReadyForQuery() return &PipelineSync{}, nil case *pgproto3.ErrorResponse: pgErr := ErrorResponseToPgError(msg) + p.state.HandleError(pgErr) return nil, pgErr } - } } @@ -2231,6 +2388,7 @@ func (p *Pipeline) getResultsPrepare() (*StatementDescription, error) { // These should never happen here. But don't take chances that could lead to a deadlock. case *pgproto3.ErrorResponse: pgErr := ErrorResponseToPgError(msg) + p.state.HandleError(pgErr) return nil, pgErr case *pgproto3.CommandComplete: p.conn.asyncClose() @@ -2250,7 +2408,7 @@ func (p *Pipeline) Close() error { p.closed = true - if p.pendingSync { + if p.state.PendingSync() { p.conn.asyncClose() p.err = errors.New("pipeline has unsynced requests") p.conn.contextWatcher.Unwatch() @@ -2259,7 +2417,7 @@ func (p *Pipeline) Close() error { return p.err } - for p.expectedReadyForQueryCount > 0 { + for p.state.ExpectedReadyForQuery() > 0 { _, err := p.getResults() if err != nil { p.err = err diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go index ac2962e9..415e1a24 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go @@ -9,8 +9,7 @@ import ( ) // AuthenticationCleartextPassword is a message sent from the backend indicating that a clear-text password is required. -type AuthenticationCleartextPassword struct { -} +type AuthenticationCleartextPassword struct{} // Backend identifies this message as sendable by the PostgreSQL backend. func (*AuthenticationCleartextPassword) Backend() {} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go index ec11d39f..98c0b2d6 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go @@ -9,8 +9,7 @@ import ( ) // AuthenticationOk is a message sent from the backend indicating that authentication was successful. -type AuthenticationOk struct { -} +type AuthenticationOk struct{} // Backend identifies this message as sendable by the PostgreSQL backend. func (*AuthenticationOk) Backend() {} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go index d146c338..28cff049 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go @@ -175,7 +175,13 @@ func (b *Backend) Receive() (FrontendMessage, error) { } b.msgType = header[0] - b.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4 + + msgLength := int(binary.BigEndian.Uint32(header[1:])) + if msgLength < 4 { + return nil, fmt.Errorf("invalid message length: %d", msgLength) + } + + b.bodyLen = msgLength - 4 if b.maxBodyLen > 0 && b.bodyLen > b.maxBodyLen { return nil, &ExceededMaxBodyLenErr{b.maxBodyLen, b.bodyLen} } @@ -282,9 +288,10 @@ func (b *Backend) SetAuthType(authType uint32) error { return nil } -// SetMaxBodyLen sets the maximum length of a message body in octets. If a message body exceeds this length, Receive will return -// an error. This is useful for protecting against malicious clients that send large messages with the intent of -// causing memory exhaustion. +// SetMaxBodyLen sets the maximum length of a message body in octets. +// If a message body exceeds this length, Receive will return an error. +// This is useful for protecting against malicious clients that send +// large messages with the intent of causing memory exhaustion. // The default value is 0. // If maxBodyLen is 0, then no maximum is enforced. func (b *Backend) SetMaxBodyLen(maxBodyLen int) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go index 040814db..c3421a9b 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go @@ -4,8 +4,7 @@ import ( "encoding/json" ) -type CopyDone struct { -} +type CopyDone struct{} // Backend identifies this message as sendable by the PostgreSQL backend. func (*CopyDone) Backend() {} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go index b41abbe1..056e547c 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go @@ -54,6 +54,7 @@ type Frontend struct { portalSuspended PortalSuspended bodyLen int + maxBodyLen int // maxBodyLen is the maximum length of a message body in octets. If a message body exceeds this length, Receive will return an error. msgType byte partialMsg bool authType uint32 @@ -317,6 +318,9 @@ func (f *Frontend) Receive() (BackendMessage, error) { } f.bodyLen = msgLength - 4 + if f.maxBodyLen > 0 && f.bodyLen > f.maxBodyLen { + return nil, &ExceededMaxBodyLenErr{f.maxBodyLen, f.bodyLen} + } f.partialMsg = true } @@ -452,3 +456,13 @@ func (f *Frontend) GetAuthType() uint32 { func (f *Frontend) ReadBufferLen() int { return f.cr.wp - f.cr.rp } + +// SetMaxBodyLen sets the maximum length of a message body in octets. +// If a message body exceeds this length, Receive will return an error. +// This is useful for protecting against a corrupted server that sends +// messages with incorrect length, which can cause memory exhaustion. +// The default value is 0. +// If maxBodyLen is 0, then no maximum is enforced. +func (f *Frontend) SetMaxBodyLen(maxBodyLen int) { + f.maxBodyLen = maxBodyLen +} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go index 70cb20cd..122d1341 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go @@ -10,8 +10,7 @@ import ( const gssEncReqNumber = 80877104 -type GSSEncRequest struct { -} +type GSSEncRequest struct{} // Frontend identifies this message as sendable by a PostgreSQL frontend. func (*GSSEncRequest) Frontend() {} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go index d820d327..67b78515 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go @@ -12,7 +12,7 @@ type PasswordMessage struct { // Frontend identifies this message as sendable by a PostgreSQL frontend. func (*PasswordMessage) Frontend() {} -// Frontend identifies this message as an authentication response. +// InitialResponse identifies this message as an authentication response. func (*PasswordMessage) InitialResponse() {} // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go index dc2a4ddf..c40a2261 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go @@ -56,7 +56,6 @@ func (*RowDescription) Backend() {} // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message // type identifier and 4 byte message length. func (dst *RowDescription) Decode(src []byte) error { - if len(src) < 2 { return &invalidMessageFormatErr{messageType: "RowDescription"} } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go index b0fc2847..bdfc7c42 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go @@ -10,8 +10,7 @@ import ( const sslRequestNumber = 80877103 -type SSLRequest struct { -} +type SSLRequest struct{} // Frontend identifies this message as sendable by a PostgreSQL frontend. func (*SSLRequest) Frontend() {} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/array.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/array.go index 06b824ad..872a0889 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/array.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/array.go @@ -374,8 +374,8 @@ func quoteArrayElementIfNeeded(src string) string { return src } -// Array represents a PostgreSQL array for T. It implements the ArrayGetter and ArraySetter interfaces. It preserves -// PostgreSQL dimensions and custom lower bounds. Use FlatArray if these are not needed. +// Array represents a PostgreSQL array for T. It implements the [ArrayGetter] and [ArraySetter] interfaces. It preserves +// PostgreSQL dimensions and custom lower bounds. Use [FlatArray] if these are not needed. type Array[T any] struct { Elements []T Dims []ArrayDimension @@ -419,8 +419,8 @@ func (a Array[T]) ScanIndexType() any { return new(T) } -// FlatArray implements the ArrayGetter and ArraySetter interfaces for any slice of T. It ignores PostgreSQL dimensions -// and custom lower bounds. Use Array to preserve these. +// FlatArray implements the [ArrayGetter] and [ArraySetter] interfaces for any slice of T. It ignores PostgreSQL dimensions +// and custom lower bounds. Use [Array] to preserve these. type FlatArray[T any] []T func (a FlatArray[T]) Dimensions() []ArrayDimension { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bits.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bits.go index e7a1d016..2a48e354 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bits.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bits.go @@ -23,16 +23,18 @@ type Bits struct { Valid bool } +// ScanBits implements the [BitsScanner] interface. func (b *Bits) ScanBits(v Bits) error { *b = v return nil } +// BitsValue implements the [BitsValuer] interface. func (b Bits) BitsValue() (Bits, error) { return b, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Bits) Scan(src any) error { if src == nil { *dst = Bits{} @@ -47,7 +49,7 @@ func (dst *Bits) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Bits) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -127,7 +129,6 @@ func (encodePlanBitsCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (BitsCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bool.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bool.go index 71caffa7..955f01fe 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bool.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bool.go @@ -22,16 +22,18 @@ type Bool struct { Valid bool } +// ScanBool implements the [BoolScanner] interface. func (b *Bool) ScanBool(v Bool) error { *b = v return nil } +// BoolValue implements the [BoolValuer] interface. func (b Bool) BoolValue() (Bool, error) { return b, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Bool) Scan(src any) error { if src == nil { *dst = Bool{} @@ -61,7 +63,7 @@ func (dst *Bool) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Bool) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -70,6 +72,7 @@ func (src Bool) Value() (driver.Value, error) { return src.Bool, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Bool) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -82,6 +85,7 @@ func (src Bool) MarshalJSON() ([]byte, error) { } } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Bool) UnmarshalJSON(b []byte) error { var v *bool err := json.Unmarshal(b, &v) @@ -200,7 +204,6 @@ func (encodePlanBoolCodecTextBool) Encode(value any, buf []byte) (newBuf []byte, } func (BoolCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { @@ -328,7 +331,7 @@ func (scanPlanTextAnyToBoolScanner) Scan(src []byte, dst any) error { return s.ScanBool(Bool{Bool: v, Valid: true}) } -// https://www.postgresql.org/docs/11/datatype-boolean.html +// https://www.postgresql.org/docs/current/datatype-boolean.html func planTextToBool(src []byte) (bool, error) { s := string(bytes.ToLower(bytes.TrimSpace(src))) diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/box.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/box.go index 887d268b..d243f58e 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/box.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/box.go @@ -24,16 +24,18 @@ type Box struct { Valid bool } +// ScanBox implements the [BoxScanner] interface. func (b *Box) ScanBox(v Box) error { *b = v return nil } +// BoxValue implements the [BoxValuer] interface. func (b Box) BoxValue() (Box, error) { return b, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Box) Scan(src any) error { if src == nil { *dst = Box{} @@ -48,7 +50,7 @@ func (dst *Box) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Box) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -127,7 +129,6 @@ func (encodePlanBoxCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (BoxCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go index b39d3fa1..84964425 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go @@ -527,6 +527,7 @@ func (w *netIPNetWrapper) ScanNetipPrefix(v netip.Prefix) error { return nil } + func (w netIPNetWrapper) NetipPrefixValue() (netip.Prefix, error) { ip, ok := netip.AddrFromSlice(w.IP) if !ok { @@ -881,7 +882,6 @@ func (a *anyMultiDimSliceArray) SetDimensions(dimensions []ArrayDimension) error return nil } - } func (a *anyMultiDimSliceArray) makeMultidimensionalSlice(sliceType reflect.Type, dimensions []ArrayDimension, flatSlice reflect.Value, flatSliceIdx int) reflect.Value { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go index a247705e..6c4f0c5e 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go @@ -148,7 +148,6 @@ func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf } func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/circle.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/circle.go index e8f118cc..fb9b4c11 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/circle.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/circle.go @@ -25,16 +25,18 @@ type Circle struct { Valid bool } +// ScanCircle implements the [CircleScanner] interface. func (c *Circle) ScanCircle(v Circle) error { *c = v return nil } +// CircleValue implements the [CircleValuer] interface. func (c Circle) CircleValue() (Circle, error) { return c, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Circle) Scan(src any) error { if src == nil { *dst = Circle{} @@ -49,7 +51,7 @@ func (dst *Circle) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Circle) Value() (driver.Value, error) { if !src.Valid { return nil, nil diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/composite.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/composite.go index fb372325..598cf7af 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/composite.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/composite.go @@ -276,7 +276,6 @@ func (c *CompositeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byt default: return nil, fmt.Errorf("unknown format code %d", format) } - } type CompositeBinaryScanner struct { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/date.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/date.go index 784b16de..44705686 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/date.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/date.go @@ -26,11 +26,13 @@ type Date struct { Valid bool } +// ScanDate implements the [DateScanner] interface. func (d *Date) ScanDate(v Date) error { *d = v return nil } +// DateValue implements the [DateValuer] interface. func (d Date) DateValue() (Date, error) { return d, nil } @@ -40,7 +42,7 @@ const ( infinityDayOffset = 2147483647 ) -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Date) Scan(src any) error { if src == nil { *dst = Date{} @@ -58,7 +60,7 @@ func (dst *Date) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Date) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -70,6 +72,7 @@ func (src Date) Value() (driver.Value, error) { return src.Time, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Date) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -89,6 +92,7 @@ func (src Date) MarshalJSON() ([]byte, error) { return json.Marshal(s) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Date) UnmarshalJSON(b []byte) error { var s *string err := json.Unmarshal(b, &s) @@ -223,7 +227,6 @@ func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/doc.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/doc.go index 7687ea8f..83dfc5de 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/doc.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/doc.go @@ -53,8 +53,8 @@ similar fashion to database/sql. The second is to use a pointer to a pointer. return err } -When using nullable pgtype types as parameters for queries, one has to remember -to explicitly set their Valid field to true, otherwise the parameter's value will be NULL. +When using nullable pgtype types as parameters for queries, one has to remember to explicitly set their Valid field to +true, otherwise the parameter's value will be NULL. JSON Support @@ -159,11 +159,16 @@ example_child_records_test.go for an example. Overview of Scanning Implementation -The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID -from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for -scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are -interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner and -PointValuer interfaces. +The first step is to use the OID to lookup the correct Codec. The Map will call the Codec's PlanScan method to get a +plan for scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types +are interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner +and PointValuer interfaces. + +If a Go value is not supported directly by a Codec then Map will try see if it is a sql.Scanner. If is then that +interface will be used to scan the value. Most sql.Scanners require the input to be in the text format (e.g. UUIDs and +numeric). However, pgx will typically have received the value in the binary format. In this case the binary value will be +parsed, reencoded as text, and then passed to the sql.Scanner. This may incur additional overhead for query results with +a large number of affected values. If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again. For example, Int8Codec does not support scanning into a renamed type (e.g. type myInt64 int64). But Map will detect that diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float4.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float4.go index 8646d9d2..241a25ad 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float4.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float4.go @@ -16,26 +16,29 @@ type Float4 struct { Valid bool } -// ScanFloat64 implements the Float64Scanner interface. +// ScanFloat64 implements the [Float64Scanner] interface. func (f *Float4) ScanFloat64(n Float8) error { *f = Float4{Float32: float32(n.Float64), Valid: n.Valid} return nil } +// Float64Value implements the [Float64Valuer] interface. func (f Float4) Float64Value() (Float8, error) { return Float8{Float64: float64(f.Float32), Valid: f.Valid}, nil } +// ScanInt64 implements the [Int64Scanner] interface. func (f *Float4) ScanInt64(n Int8) error { *f = Float4{Float32: float32(n.Int64), Valid: n.Valid} return nil } +// Int64Value implements the [Int64Valuer] interface. func (f Float4) Int64Value() (Int8, error) { return Int8{Int64: int64(f.Float32), Valid: f.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (f *Float4) Scan(src any) error { if src == nil { *f = Float4{} @@ -58,7 +61,7 @@ func (f *Float4) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (f Float4) Value() (driver.Value, error) { if !f.Valid { return nil, nil @@ -66,6 +69,7 @@ func (f Float4) Value() (driver.Value, error) { return float64(f.Float32), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (f Float4) MarshalJSON() ([]byte, error) { if !f.Valid { return []byte("null"), nil @@ -73,6 +77,7 @@ func (f Float4) MarshalJSON() ([]byte, error) { return json.Marshal(f.Float32) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (f *Float4) UnmarshalJSON(b []byte) error { var n *float32 err := json.Unmarshal(b, &n) @@ -170,7 +175,6 @@ func (encodePlanFloat4CodecBinaryInt64Valuer) Encode(value any, buf []byte) (new } func (Float4Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float8.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float8.go index 9c923c9a..54d6781e 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float8.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/float8.go @@ -24,26 +24,29 @@ type Float8 struct { Valid bool } -// ScanFloat64 implements the Float64Scanner interface. +// ScanFloat64 implements the [Float64Scanner] interface. func (f *Float8) ScanFloat64(n Float8) error { *f = n return nil } +// Float64Value implements the [Float64Valuer] interface. func (f Float8) Float64Value() (Float8, error) { return f, nil } +// ScanInt64 implements the [Int64Scanner] interface. func (f *Float8) ScanInt64(n Int8) error { *f = Float8{Float64: float64(n.Int64), Valid: n.Valid} return nil } +// Int64Value implements the [Int64Valuer] interface. func (f Float8) Int64Value() (Int8, error) { return Int8{Int64: int64(f.Float64), Valid: f.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (f *Float8) Scan(src any) error { if src == nil { *f = Float8{} @@ -66,7 +69,7 @@ func (f *Float8) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (f Float8) Value() (driver.Value, error) { if !f.Valid { return nil, nil @@ -74,6 +77,7 @@ func (f Float8) Value() (driver.Value, error) { return f.Float64, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (f Float8) MarshalJSON() ([]byte, error) { if !f.Valid { return []byte("null"), nil @@ -81,6 +85,7 @@ func (f Float8) MarshalJSON() ([]byte, error) { return json.Marshal(f.Float64) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (f *Float8) UnmarshalJSON(b []byte) error { var n *float64 err := json.Unmarshal(b, &n) @@ -208,7 +213,6 @@ func (encodePlanTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, e } func (Float8Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go index 2f34f4c9..ef864928 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go @@ -22,16 +22,18 @@ type HstoreValuer interface { // associated with its keys. type Hstore map[string]*string +// ScanHstore implements the [HstoreScanner] interface. func (h *Hstore) ScanHstore(v Hstore) error { *h = v return nil } +// HstoreValue implements the [HstoreValuer] interface. func (h Hstore) HstoreValue() (Hstore, error) { return h, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (h *Hstore) Scan(src any) error { if src == nil { *h = nil @@ -46,7 +48,7 @@ func (h *Hstore) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (h Hstore) Value() (driver.Value, error) { if h == nil { return nil, nil @@ -162,7 +164,6 @@ func (encodePlanHstoreCodecText) Encode(value any, buf []byte) (newBuf []byte, e } func (HstoreCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { @@ -298,7 +299,7 @@ func (p *hstoreParser) consume() (b byte, end bool) { return b, false } -func unexpectedByteErr(actualB byte, expectedB byte) error { +func unexpectedByteErr(actualB, expectedB byte) error { return fmt.Errorf("expected '%c' ('%#v'); found '%c' ('%#v')", expectedB, expectedB, actualB, actualB) } @@ -316,7 +317,7 @@ func (p *hstoreParser) consumeExpectedByte(expectedB byte) error { // consumeExpected2 consumes two expected bytes or returns an error. // This was a bit faster than using a string argument (better inlining? Not sure). -func (p *hstoreParser) consumeExpected2(one byte, two byte) error { +func (p *hstoreParser) consumeExpected2(one, two byte) error { if p.pos+2 > len(p.str) { return errors.New("unexpected end of string") } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/inet.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/inet.go index 6ca10ea0..b92edb23 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/inet.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/inet.go @@ -24,7 +24,7 @@ type NetipPrefixValuer interface { NetipPrefixValue() (netip.Prefix, error) } -// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are netip.Prefix and netip.Addr. If +// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are [netip.Prefix] and [netip.Addr]. If // IsValid() is false then they are treated as SQL NULL. type InetCodec struct{} @@ -107,7 +107,6 @@ func (encodePlanInetCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (InetCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go index 90a20a26..d1b8eb61 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go @@ -1,4 +1,5 @@ -// Do not edit. Generated from pgtype/int.go.erb +// Code generated from pgtype/int.go.erb. DO NOT EDIT. + package pgtype import ( @@ -25,7 +26,7 @@ type Int2 struct { Valid bool } -// ScanInt64 implements the Int64Scanner interface. +// ScanInt64 implements the [Int64Scanner] interface. func (dst *Int2) ScanInt64(n Int8) error { if !n.Valid { *dst = Int2{} @@ -43,11 +44,12 @@ func (dst *Int2) ScanInt64(n Int8) error { return nil } +// Int64Value implements the [Int64Valuer] interface. func (n Int2) Int64Value() (Int8, error) { return Int8{Int64: int64(n.Int16), Valid: n.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Int2) Scan(src any) error { if src == nil { *dst = Int2{} @@ -86,7 +88,7 @@ func (dst *Int2) Scan(src any) error { return nil } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Int2) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -94,6 +96,7 @@ func (src Int2) Value() (driver.Value, error) { return int64(src.Int16), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Int2) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -101,6 +104,7 @@ func (src Int2) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(src.Int16), 10)), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Int2) UnmarshalJSON(b []byte) error { var n *int16 err := json.Unmarshal(b, &n) @@ -585,7 +589,7 @@ type Int4 struct { Valid bool } -// ScanInt64 implements the Int64Scanner interface. +// ScanInt64 implements the [Int64Scanner] interface. func (dst *Int4) ScanInt64(n Int8) error { if !n.Valid { *dst = Int4{} @@ -603,11 +607,12 @@ func (dst *Int4) ScanInt64(n Int8) error { return nil } +// Int64Value implements the [Int64Valuer] interface. func (n Int4) Int64Value() (Int8, error) { return Int8{Int64: int64(n.Int32), Valid: n.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Int4) Scan(src any) error { if src == nil { *dst = Int4{} @@ -646,7 +651,7 @@ func (dst *Int4) Scan(src any) error { return nil } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Int4) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -654,6 +659,7 @@ func (src Int4) Value() (driver.Value, error) { return int64(src.Int32), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Int4) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -661,6 +667,7 @@ func (src Int4) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(src.Int32), 10)), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Int4) UnmarshalJSON(b []byte) error { var n *int32 err := json.Unmarshal(b, &n) @@ -1156,7 +1163,7 @@ type Int8 struct { Valid bool } -// ScanInt64 implements the Int64Scanner interface. +// ScanInt64 implements the [Int64Scanner] interface. func (dst *Int8) ScanInt64(n Int8) error { if !n.Valid { *dst = Int8{} @@ -1174,11 +1181,12 @@ func (dst *Int8) ScanInt64(n Int8) error { return nil } +// Int64Value implements the [Int64Valuer] interface. func (n Int8) Int64Value() (Int8, error) { return Int8{Int64: int64(n.Int64), Valid: n.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Int8) Scan(src any) error { if src == nil { *dst = Int8{} @@ -1217,7 +1225,7 @@ func (dst *Int8) Scan(src any) error { return nil } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Int8) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -1225,6 +1233,7 @@ func (src Int8) Value() (driver.Value, error) { return int64(src.Int64), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Int8) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -1232,6 +1241,7 @@ func (src Int8) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(src.Int64), 10)), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Int8) UnmarshalJSON(b []byte) error { var n *int64 err := json.Unmarshal(b, &n) diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb index e0c8b7a3..c2d40f60 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb @@ -27,7 +27,7 @@ type Int<%= pg_byte_size %> struct { Valid bool } -// ScanInt64 implements the Int64Scanner interface. +// ScanInt64 implements the [Int64Scanner] interface. func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error { if !n.Valid { *dst = Int<%= pg_byte_size %>{} @@ -45,11 +45,12 @@ func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error { return nil } +// Int64Value implements the [Int64Valuer] interface. func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) { return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Int<%= pg_byte_size %>) Scan(src any) error { if src == nil { *dst = Int<%= pg_byte_size %>{} @@ -88,7 +89,7 @@ func (dst *Int<%= pg_byte_size %>) Scan(src any) error { return nil } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -96,6 +97,7 @@ func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) { return int64(src.Int<%= pg_bit_size %>), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -103,6 +105,7 @@ func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error { var n *int<%= pg_bit_size %> err := json.Unmarshal(b, &n) diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb index 0175700a..6f401153 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb @@ -25,7 +25,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go rows, _ := conn.Query( ctx, `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`, - []any{pgx.QueryResultFormats{<%= format_code %>}}, + pgx.QueryResultFormats{<%= format_code %>}, ) _, err := pgx.ForEachRow(rows, []any{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>}, func() error { return nil }) if err != nil { @@ -49,7 +49,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array rows, _ := conn.Query( ctx, `select array_agg(n) from generate_series(1, <%= array_size %>) n`, - []any{pgx.QueryResultFormats{<%= format_code %>}}, + pgx.QueryResultFormats{<%= format_code %>}, ) _, err := pgx.ForEachRow(rows, []any{&v}, func() error { return nil }) if err != nil { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/interval.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/interval.go index 4b511629..ba5e818f 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/interval.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/interval.go @@ -33,16 +33,18 @@ type Interval struct { Valid bool } +// ScanInterval implements the [IntervalScanner] interface. func (interval *Interval) ScanInterval(v Interval) error { *interval = v return nil } +// IntervalValue implements the [IntervalValuer] interface. func (interval Interval) IntervalValue() (Interval, error) { return interval, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (interval *Interval) Scan(src any) error { if src == nil { *interval = Interval{} @@ -57,7 +59,7 @@ func (interval *Interval) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (interval Interval) Value() (driver.Value, error) { if !interval.Valid { return nil, nil @@ -157,7 +159,6 @@ func (encodePlanIntervalCodecText) Encode(value any, buf []byte) (newBuf []byte, } func (IntervalCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/json.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/json.go index c2aa0d3b..60aa2b71 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/json.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/json.go @@ -71,6 +71,27 @@ func (c *JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Enco } } +// JSON needs its on scan plan for pointers to handle 'null'::json(b). +// Consider making pointerPointerScanPlan more flexible in the future. +type jsonPointerScanPlan struct { + next ScanPlan +} + +func (p jsonPointerScanPlan) Scan(src []byte, dst any) error { + el := reflect.ValueOf(dst).Elem() + if src == nil || string(src) == "null" { + el.SetZero() + return nil + } + + el.Set(reflect.New(el.Type().Elem())) + if p.next != nil { + return p.next.Scan(src, el.Interface()) + } + + return nil +} + type encodePlanJSONCodecEitherFormatString struct{} func (encodePlanJSONCodecEitherFormatString) Encode(value any, buf []byte) (newBuf []byte, err error) { @@ -117,41 +138,35 @@ func (e *encodePlanJSONCodecEitherFormatMarshal) Encode(value any, buf []byte) ( return buf, nil } -func (c *JSONCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { +func (c *JSONCodec) PlanScan(m *Map, oid uint32, formatCode int16, target any) ScanPlan { + return c.planScan(m, oid, formatCode, target, 0) +} + +// JSON cannot fallback to pointerPointerScanPlan because of 'null'::json(b), +// so we need to duplicate the logic here. +func (c *JSONCodec) planScan(m *Map, oid uint32, formatCode int16, target any, depth int) ScanPlan { + if depth > 8 { + return &scanPlanFail{m: m, oid: oid, formatCode: formatCode} + } + switch target.(type) { case *string: - return scanPlanAnyToString{} - - case **string: - // This is to fix **string scanning. It seems wrong to special case **string, but it's not clear what a better - // solution would be. - // - // https://github.com/jackc/pgx/issues/1470 -- **string - // https://github.com/jackc/pgx/issues/1691 -- ** anything else - - if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok { - if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil { - if _, failed := nextPlan.(*scanPlanFail); !failed { - wrapperPlan.SetNext(nextPlan) - return wrapperPlan - } - } - } - + return &scanPlanAnyToString{} case *[]byte: - return scanPlanJSONToByteSlice{} + return &scanPlanJSONToByteSlice{} case BytesScanner: - return scanPlanBinaryBytesToBytesScanner{} - - // Cannot rely on sql.Scanner being handled later because scanPlanJSONToJSONUnmarshal will take precedence. - // - // https://github.com/jackc/pgx/issues/1418 + return &scanPlanBinaryBytesToBytesScanner{} case sql.Scanner: - return &scanPlanSQLScanner{formatCode: format} + return &scanPlanSQLScanner{formatCode: formatCode} } - return &scanPlanJSONToJSONUnmarshal{ - unmarshal: c.Unmarshal, + rv := reflect.ValueOf(target) + if rv.Kind() == reflect.Pointer && rv.Elem().Kind() == reflect.Pointer { + var plan jsonPointerScanPlan + plan.next = c.planScan(m, oid, formatCode, rv.Elem().Interface(), depth+1) + return plan + } else { + return &scanPlanJSONToJSONUnmarshal{unmarshal: c.Unmarshal} } } @@ -196,7 +211,12 @@ func (s *scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error { return fmt.Errorf("cannot scan NULL into %T", dst) } - elem := reflect.ValueOf(dst).Elem() + v := reflect.ValueOf(dst) + if v.Kind() != reflect.Pointer || v.IsNil() { + return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", dst) + } + + elem := v.Elem() elem.Set(reflect.Zero(elem.Type())) return s.unmarshal(src, dst) diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/line.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/line.go index 4ae8003e..10efc8ce 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/line.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/line.go @@ -24,11 +24,13 @@ type Line struct { Valid bool } +// ScanLine implements the [LineScanner] interface. func (line *Line) ScanLine(v Line) error { *line = v return nil } +// LineValue implements the [LineValuer] interface. func (line Line) LineValue() (Line, error) { return line, nil } @@ -37,7 +39,7 @@ func (line *Line) Set(src any) error { return fmt.Errorf("cannot convert %v to Line", src) } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (line *Line) Scan(src any) error { if src == nil { *line = Line{} @@ -52,7 +54,7 @@ func (line *Line) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (line Line) Value() (driver.Value, error) { if !line.Valid { return nil, nil @@ -129,7 +131,6 @@ func (encodePlanLineCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (LineCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go index 05a86e1c..ed0d40d2 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go @@ -24,16 +24,18 @@ type Lseg struct { Valid bool } +// ScanLseg implements the [LsegScanner] interface. func (lseg *Lseg) ScanLseg(v Lseg) error { *lseg = v return nil } +// LsegValue implements the [LsegValuer] interface. func (lseg Lseg) LsegValue() (Lseg, error) { return lseg, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (lseg *Lseg) Scan(src any) error { if src == nil { *lseg = Lseg{} @@ -48,7 +50,7 @@ func (lseg *Lseg) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (lseg Lseg) Value() (driver.Value, error) { if !lseg.Valid { return nil, nil @@ -127,7 +129,6 @@ func (encodePlanLsegCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (LsegCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go index e5763788..4fe6dd40 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go @@ -374,7 +374,6 @@ parseValueLoop: } return elements, nil - } func parseRange(buf *bytes.Buffer) (string, error) { @@ -403,8 +402,8 @@ func parseRange(buf *bytes.Buffer) (string, error) { // Multirange is a generic multirange type. // -// T should implement RangeValuer and *T should implement RangeScanner. However, there does not appear to be a way to -// enforce the RangeScanner constraint. +// T should implement [RangeValuer] and *T should implement [RangeScanner]. However, there does not appear to be a way to +// enforce the [RangeScanner] constraint. type Multirange[T RangeValuer] []T func (r Multirange[T]) IsNull() bool { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go index 4dbec786..7d236902 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go @@ -27,16 +27,20 @@ const ( pgNumericNegInfSign = 0xf000 ) -var big0 *big.Int = big.NewInt(0) -var big1 *big.Int = big.NewInt(1) -var big10 *big.Int = big.NewInt(10) -var big100 *big.Int = big.NewInt(100) -var big1000 *big.Int = big.NewInt(1000) +var ( + big0 *big.Int = big.NewInt(0) + big1 *big.Int = big.NewInt(1) + big10 *big.Int = big.NewInt(10) + big100 *big.Int = big.NewInt(100) + big1000 *big.Int = big.NewInt(1000) +) -var bigNBase *big.Int = big.NewInt(nbase) -var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase) -var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase) -var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase) +var ( + bigNBase *big.Int = big.NewInt(nbase) + bigNBaseX2 *big.Int = big.NewInt(nbase * nbase) + bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase) + bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase) +) type NumericScanner interface { ScanNumeric(v Numeric) error @@ -54,15 +58,18 @@ type Numeric struct { Valid bool } +// ScanNumeric implements the [NumericScanner] interface. func (n *Numeric) ScanNumeric(v Numeric) error { *n = v return nil } +// NumericValue implements the [NumericValuer] interface. func (n Numeric) NumericValue() (Numeric, error) { return n, nil } +// Float64Value implements the [Float64Valuer] interface. func (n Numeric) Float64Value() (Float8, error) { if !n.Valid { return Float8{}, nil @@ -92,6 +99,7 @@ func (n Numeric) Float64Value() (Float8, error) { return Float8{Float64: f, Valid: true}, nil } +// ScanInt64 implements the [Int64Scanner] interface. func (n *Numeric) ScanInt64(v Int8) error { if !v.Valid { *n = Numeric{} @@ -102,6 +110,7 @@ func (n *Numeric) ScanInt64(v Int8) error { return nil } +// Int64Value implements the [Int64Valuer] interface. func (n Numeric) Int64Value() (Int8, error) { if !n.Valid { return Int8{}, nil @@ -203,7 +212,7 @@ func nbaseDigitsToInt64(src []byte) (accum int64, bytesRead, digitsRead int) { return accum, rp, digits } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (n *Numeric) Scan(src any) error { if src == nil { *n = Numeric{} @@ -218,7 +227,7 @@ func (n *Numeric) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (n Numeric) Value() (driver.Value, error) { if !n.Valid { return nil, nil @@ -231,6 +240,7 @@ func (n Numeric) Value() (driver.Value, error) { return string(buf), err } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (n Numeric) MarshalJSON() ([]byte, error) { if !n.Valid { return []byte("null"), nil @@ -243,6 +253,7 @@ func (n Numeric) MarshalJSON() ([]byte, error) { return n.numberTextBytes(), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (n *Numeric) UnmarshalJSON(src []byte) error { if bytes.Equal(src, []byte(`null`)) { *n = Numeric{} @@ -553,7 +564,6 @@ func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) { } func (NumericCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/path.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/path.go index 73e0ec52..81dc1e5b 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/path.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/path.go @@ -25,16 +25,18 @@ type Path struct { Valid bool } +// ScanPath implements the [PathScanner] interface. func (path *Path) ScanPath(v Path) error { *path = v return nil } +// PathValue implements the [PathValuer] interface. func (path Path) PathValue() (Path, error) { return path, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (path *Path) Scan(src any) error { if src == nil { *path = Path{} @@ -49,7 +51,7 @@ func (path *Path) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (path Path) Value() (driver.Value, error) { if !path.Valid { return nil, nil @@ -154,7 +156,6 @@ func (encodePlanPathCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (PathCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go index bdd9f05c..b3ef3207 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go @@ -29,6 +29,7 @@ const ( XMLOID = 142 XMLArrayOID = 143 JSONArrayOID = 199 + XID8ArrayOID = 271 PointOID = 600 LsegOID = 601 PathOID = 602 @@ -117,6 +118,7 @@ const ( TstzmultirangeOID = 4534 DatemultirangeOID = 4535 Int8multirangeOID = 4536 + XID8OID = 5069 Int4multirangeArrayOID = 6150 NummultirangeArrayOID = 6151 TsmultirangeArrayOID = 6152 @@ -200,7 +202,6 @@ type Map struct { reflectTypeToType map[reflect.Type]*Type - memoizedScanPlans map[uint32]map[reflect.Type][2]ScanPlan memoizedEncodePlans map[uint32]map[reflect.Type][2]EncodePlan // TryWrapEncodePlanFuncs is a slice of functions that will wrap a value that cannot be encoded by the Codec. Every @@ -234,7 +235,6 @@ func NewMap() *Map { reflectTypeToName: make(map[reflect.Type]string), oidToFormatCode: make(map[uint32]int16), - memoizedScanPlans: make(map[uint32]map[reflect.Type][2]ScanPlan), memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan), TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{ @@ -274,9 +274,6 @@ func (m *Map) RegisterType(t *Type) { // Invalidated by type registration m.reflectTypeToType = nil - for k := range m.memoizedScanPlans { - delete(m.memoizedScanPlans, k) - } for k := range m.memoizedEncodePlans { delete(m.memoizedEncodePlans, k) } @@ -290,9 +287,6 @@ func (m *Map) RegisterDefaultPgType(value any, name string) { // Invalidated by type registration m.reflectTypeToType = nil - for k := range m.memoizedScanPlans { - delete(m.memoizedScanPlans, k) - } for k := range m.memoizedEncodePlans { delete(m.memoizedEncodePlans, k) } @@ -395,6 +389,7 @@ type scanPlanSQLScanner struct { func (plan *scanPlanSQLScanner) Scan(src []byte, dst any) error { scanner := dst.(sql.Scanner) + if src == nil { // This is necessary because interface value []byte:nil does not equal nil:nil for the binary format path and the // text format path would be converted to empty string. @@ -449,14 +444,14 @@ func (plan *scanPlanFail) Scan(src []byte, dst any) error { // As a horrible hack try all types to find anything that can scan into dst. for oid := range plan.m.oidToType { // using planScan instead of Scan or PlanScan to avoid polluting the planned scan cache. - plan := plan.m.planScan(oid, plan.formatCode, dst) + plan := plan.m.planScan(oid, plan.formatCode, dst, 0) if _, ok := plan.(*scanPlanFail); !ok { return plan.Scan(src, dst) } } for oid := range defaultMap.oidToType { if _, ok := plan.m.oidToType[oid]; !ok { - plan := plan.m.planScan(oid, plan.formatCode, dst) + plan := plan.m.planScan(oid, plan.formatCode, dst, 0) if _, ok := plan.(*scanPlanFail); !ok { return plan.Scan(src, dst) } @@ -1064,24 +1059,14 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error { // PlanScan prepares a plan to scan a value into target. func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan { - oidMemo := m.memoizedScanPlans[oid] - if oidMemo == nil { - oidMemo = make(map[reflect.Type][2]ScanPlan) - m.memoizedScanPlans[oid] = oidMemo - } - targetReflectType := reflect.TypeOf(target) - typeMemo := oidMemo[targetReflectType] - plan := typeMemo[formatCode] - if plan == nil { - plan = m.planScan(oid, formatCode, target) - typeMemo[formatCode] = plan - oidMemo[targetReflectType] = typeMemo - } - - return plan + return m.planScan(oid, formatCode, target, 0) } -func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan { +func (m *Map) planScan(oid uint32, formatCode int16, target any, depth int) ScanPlan { + if depth > 8 { + return &scanPlanFail{m: m, oid: oid, formatCode: formatCode} + } + if target == nil { return &scanPlanFail{m: m, oid: oid, formatCode: formatCode} } @@ -1141,7 +1126,7 @@ func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan { for _, f := range m.TryWrapScanPlanFuncs { if wrapperPlan, nextDst, ok := f(target); ok { - if nextPlan := m.planScan(oid, formatCode, nextDst); nextPlan != nil { + if nextPlan := m.planScan(oid, formatCode, nextDst, depth+1); nextPlan != nil { if _, failed := nextPlan.(*scanPlanFail); !failed { wrapperPlan.SetNext(nextPlan) return wrapperPlan @@ -1198,9 +1183,18 @@ func codecDecodeToTextFormat(codec Codec, m *Map, oid uint32, format int16, src } } -// PlanEncode returns an Encode plan for encoding value into PostgreSQL format for oid and format. If no plan can be +// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be // found then nil is returned. func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan { + return m.planEncodeDepth(oid, format, value, 0) +} + +func (m *Map) planEncodeDepth(oid uint32, format int16, value any, depth int) EncodePlan { + // Guard against infinite recursion. + if depth > 8 { + return nil + } + oidMemo := m.memoizedEncodePlans[oid] if oidMemo == nil { oidMemo = make(map[reflect.Type][2]EncodePlan) @@ -1210,7 +1204,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan { typeMemo := oidMemo[targetReflectType] plan := typeMemo[format] if plan == nil { - plan = m.planEncode(oid, format, value) + plan = m.planEncode(oid, format, value, depth) typeMemo[format] = plan oidMemo[targetReflectType] = typeMemo } @@ -1218,7 +1212,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan { return plan } -func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan { +func (m *Map) planEncode(oid uint32, format int16, value any, depth int) EncodePlan { if format == TextFormatCode { switch value.(type) { case string: @@ -1249,7 +1243,7 @@ func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan { for _, f := range m.TryWrapEncodePlanFuncs { if wrapperPlan, nextValue, ok := f(value); ok { - if nextPlan := m.PlanEncode(oid, format, nextValue); nextPlan != nil { + if nextPlan := m.planEncodeDepth(oid, format, nextValue, depth+1); nextPlan != nil { wrapperPlan.SetNext(nextPlan) return wrapperPlan } @@ -2012,30 +2006,11 @@ func (w *sqlScannerWrapper) Scan(src any) error { return w.m.Scan(t.OID, TextFormatCode, bufSrc, w.v) } -// canBeNil returns true if value can be nil. -func canBeNil(value any) bool { - refVal := reflect.ValueOf(value) - kind := refVal.Kind() - switch kind { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: - return true - default: - return false - } -} - -// valuerReflectType is a reflect.Type for driver.Valuer. It has confusing syntax because reflect.TypeOf returns nil -// when it's argument is a nil interface value. So we use a pointer to the interface and call Elem to get the actual -// type. Yuck. -// -// This can be simplified in Go 1.22 with reflect.TypeFor. -// -// var valuerReflectType = reflect.TypeFor[driver.Valuer]() -var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() +var valuerReflectType = reflect.TypeFor[driver.Valuer]() // isNilDriverValuer returns true if value is any type of nil unless it implements driver.Valuer. *T is not considered to implement // driver.Valuer if it is only implemented by T. -func isNilDriverValuer(value any) (isNil bool, callNilDriverValuer bool) { +func isNilDriverValuer(value any) (isNil, callNilDriverValuer bool) { if value == nil { return true, false } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go index c8125731..5648d89b 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go @@ -23,7 +23,6 @@ func initDefaultMap() { reflectTypeToName: make(map[reflect.Type]string), oidToFormatCode: make(map[uint32]int16), - memoizedScanPlans: make(map[uint32]map[reflect.Type][2]ScanPlan), memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan), TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{ @@ -90,7 +89,26 @@ func initDefaultMap() { defaultMap.RegisterType(&Type{Name: "varbit", OID: VarbitOID, Codec: BitsCodec{}}) defaultMap.RegisterType(&Type{Name: "varchar", OID: VarcharOID, Codec: TextCodec{}}) defaultMap.RegisterType(&Type{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}}) - defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{Marshal: xml.Marshal, Unmarshal: xml.Unmarshal}}) + defaultMap.RegisterType(&Type{Name: "xid8", OID: XID8OID, Codec: Uint64Codec{}}) + defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{ + Marshal: xml.Marshal, + // xml.Unmarshal does not support unmarshalling into *any. However, XMLCodec.DecodeValue calls Unmarshal with a + // *any. Wrap xml.Marshal with a function that copies the data into a new byte slice in this case. Not implementing + // directly in XMLCodec.DecodeValue to allow for the unlikely possibility that someone uses an alternative XML + // unmarshaler that does support unmarshalling into *any. + // + // https://github.com/jackc/pgx/issues/2227 + // https://github.com/jackc/pgx/pull/2228 + Unmarshal: func(data []byte, v any) error { + if v, ok := v.(*any); ok { + dstBuf := make([]byte, len(data)) + copy(dstBuf, data) + *v = dstBuf + return nil + } + return xml.Unmarshal(data, v) + }, + }}) // Range types defaultMap.RegisterType(&Type{Name: "daterange", OID: DaterangeOID, Codec: &RangeCodec{ElementType: defaultMap.oidToType[DateOID]}}) @@ -155,6 +173,7 @@ func initDefaultMap() { defaultMap.RegisterType(&Type{Name: "_varbit", OID: VarbitArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarbitOID]}}) defaultMap.RegisterType(&Type{Name: "_varchar", OID: VarcharArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarcharOID]}}) defaultMap.RegisterType(&Type{Name: "_xid", OID: XIDArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XIDOID]}}) + defaultMap.RegisterType(&Type{Name: "_xid8", OID: XID8ArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XID8OID]}}) defaultMap.RegisterType(&Type{Name: "_xml", OID: XMLArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XMLOID]}}) // Integer types that directly map to a PostgreSQL type diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/point.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/point.go index 09b19bb5..b701513d 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/point.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/point.go @@ -30,11 +30,13 @@ type Point struct { Valid bool } +// ScanPoint implements the [PointScanner] interface. func (p *Point) ScanPoint(v Point) error { *p = v return nil } +// PointValue implements the [PointValuer] interface. func (p Point) PointValue() (Point, error) { return p, nil } @@ -68,7 +70,7 @@ func parsePoint(src []byte) (*Point, error) { return &Point{P: Vec2{x, y}, Valid: true}, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Point) Scan(src any) error { if src == nil { *dst = Point{} @@ -83,7 +85,7 @@ func (dst *Point) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Point) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -96,6 +98,7 @@ func (src Point) Value() (driver.Value, error) { return string(buf), err } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Point) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -108,6 +111,7 @@ func (src Point) MarshalJSON() ([]byte, error) { return buff.Bytes(), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Point) UnmarshalJSON(point []byte) error { p, err := parsePoint(point) if err != nil { @@ -178,7 +182,6 @@ func (encodePlanPointCodecText) Encode(value any, buf []byte) (newBuf []byte, er } func (PointCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go index 04b0ba6b..a84b25fe 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go @@ -24,16 +24,18 @@ type Polygon struct { Valid bool } +// ScanPolygon implements the [PolygonScanner] interface. func (p *Polygon) ScanPolygon(v Polygon) error { *p = v return nil } +// PolygonValue implements the [PolygonValuer] interface. func (p Polygon) PolygonValue() (Polygon, error) { return p, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (p *Polygon) Scan(src any) error { if src == nil { *p = Polygon{} @@ -48,7 +50,7 @@ func (p *Polygon) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (p Polygon) Value() (driver.Value, error) { if !p.Valid { return nil, nil @@ -139,7 +141,6 @@ func (encodePlanPolygonCodecText) Encode(value any, buf []byte) (newBuf []byte, } func (PolygonCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/range.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/range.go index 16427ccc..62d69990 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/range.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/range.go @@ -191,11 +191,13 @@ type untypedBinaryRange struct { // 18 = [ = 10010 // 24 = = 11000 -const emptyMask = 1 -const lowerInclusiveMask = 2 -const upperInclusiveMask = 4 -const lowerUnboundedMask = 8 -const upperUnboundedMask = 16 +const ( + emptyMask = 1 + lowerInclusiveMask = 2 + upperInclusiveMask = 4 + lowerUnboundedMask = 8 + upperUnboundedMask = 16 +) func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) { ubr := &untypedBinaryRange{} @@ -273,7 +275,6 @@ func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) { } return ubr, nil - } // Range is a generic range type. diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go index b3b16604..90b9bd4b 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go @@ -121,5 +121,4 @@ func (RecordCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (an default: return nil, fmt.Errorf("unknown format code %d", format) } - } diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/text.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/text.go index 021ee331..e08b1254 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/text.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/text.go @@ -19,16 +19,18 @@ type Text struct { Valid bool } +// ScanText implements the [TextScanner] interface. func (t *Text) ScanText(v Text) error { *t = v return nil } +// TextValue implements the [TextValuer] interface. func (t Text) TextValue() (Text, error) { return t, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Text) Scan(src any) error { if src == nil { *dst = Text{} @@ -47,7 +49,7 @@ func (dst *Text) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Text) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -55,6 +57,7 @@ func (src Text) Value() (driver.Value, error) { return src.String, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src Text) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -63,6 +66,7 @@ func (src Text) MarshalJSON() ([]byte, error) { return json.Marshal(src.String) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *Text) UnmarshalJSON(b []byte) error { var s *string err := json.Unmarshal(b, &s) @@ -146,7 +150,6 @@ func (encodePlanTextCodecTextValuer) Encode(value any, buf []byte) (newBuf []byt } func (TextCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case TextFormatCode, BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/tid.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/tid.go index 9bc2c2a1..05c9e6d9 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/tid.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/tid.go @@ -35,16 +35,18 @@ type TID struct { Valid bool } +// ScanTID implements the [TIDScanner] interface. func (b *TID) ScanTID(v TID) error { *b = v return nil } +// TIDValue implements the [TIDValuer] interface. func (b TID) TIDValue() (TID, error) { return b, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *TID) Scan(src any) error { if src == nil { *dst = TID{} @@ -59,7 +61,7 @@ func (dst *TID) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src TID) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -131,7 +133,6 @@ func (encodePlanTIDCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (TIDCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/time.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/time.go index f8fd9489..4b8f6908 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/time.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/time.go @@ -29,16 +29,18 @@ type Time struct { Valid bool } +// ScanTime implements the [TimeScanner] interface. func (t *Time) ScanTime(v Time) error { *t = v return nil } +// TimeValue implements the [TimeValuer] interface. func (t Time) TimeValue() (Time, error) { return t, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (t *Time) Scan(src any) error { if src == nil { *t = Time{} @@ -58,7 +60,7 @@ func (t *Time) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (t Time) Value() (driver.Value, error) { if !t.Valid { return nil, nil @@ -137,7 +139,6 @@ func (encodePlanTimeCodecText) Encode(value any, buf []byte) (newBuf []byte, err } func (TimeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go index 677a2c6e..861fa883 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go @@ -11,7 +11,10 @@ import ( "github.com/jackc/pgx/v5/internal/pgio" ) -const pgTimestampFormat = "2006-01-02 15:04:05.999999999" +const ( + pgTimestampFormat = "2006-01-02 15:04:05.999999999" + jsonISO8601 = "2006-01-02T15:04:05.999999999" +) type TimestampScanner interface { ScanTimestamp(v Timestamp) error @@ -28,16 +31,18 @@ type Timestamp struct { Valid bool } +// ScanTimestamp implements the [TimestampScanner] interface. func (ts *Timestamp) ScanTimestamp(v Timestamp) error { *ts = v return nil } +// TimestampValue implements the [TimestampValuer] interface. func (ts Timestamp) TimestampValue() (Timestamp, error) { return ts, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (ts *Timestamp) Scan(src any) error { if src == nil { *ts = Timestamp{} @@ -55,7 +60,7 @@ func (ts *Timestamp) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (ts Timestamp) Value() (driver.Value, error) { if !ts.Valid { return nil, nil @@ -67,6 +72,7 @@ func (ts Timestamp) Value() (driver.Value, error) { return ts.Time, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (ts Timestamp) MarshalJSON() ([]byte, error) { if !ts.Valid { return []byte("null"), nil @@ -76,7 +82,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) { switch ts.InfinityModifier { case Finite: - s = ts.Time.Format(time.RFC3339Nano) + s = ts.Time.Format(jsonISO8601) case Infinity: s = "infinity" case NegativeInfinity: @@ -86,6 +92,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) { return json.Marshal(s) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (ts *Timestamp) UnmarshalJSON(b []byte) error { var s *string err := json.Unmarshal(b, &s) @@ -104,15 +111,23 @@ func (ts *Timestamp) UnmarshalJSON(b []byte) error { case "-infinity": *ts = Timestamp{Valid: true, InfinityModifier: -Infinity} default: - // PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz - tim, err := time.Parse(time.RFC3339Nano, *s) - if err != nil { - return err + // Parse time with or without timezonr + tss := *s + // PostgreSQL uses ISO 8601 without timezone for to_json function and casting from a string to timestampt + tim, err := time.Parse(time.RFC3339Nano, tss) + if err == nil { + *ts = Timestamp{Time: tim, Valid: true} + return nil } - - *ts = Timestamp{Time: tim, Valid: true} + tim, err = time.ParseInLocation(jsonISO8601, tss, time.UTC) + if err == nil { + *ts = Timestamp{Time: tim, Valid: true} + return nil + } + ts.Valid = false + return fmt.Errorf("cannot unmarshal %s to timestamp with layout %s or %s (%w)", + *s, time.RFC3339Nano, jsonISO8601, err) } - return nil } @@ -225,7 +240,6 @@ func discardTimeZone(t time.Time) time.Time { } func (c *TimestampCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go index 7efbcffd..5d67e47f 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go @@ -11,10 +11,12 @@ import ( "github.com/jackc/pgx/v5/internal/pgio" ) -const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07" -const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00" -const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00" -const microsecFromUnixEpochToY2K = 946684800 * 1000000 +const ( + pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07" + pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00" + pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00" + microsecFromUnixEpochToY2K = 946684800 * 1000000 +) const ( negativeInfinityMicrosecondOffset = -9223372036854775808 @@ -36,16 +38,18 @@ type Timestamptz struct { Valid bool } +// ScanTimestamptz implements the [TimestamptzScanner] interface. func (tstz *Timestamptz) ScanTimestamptz(v Timestamptz) error { *tstz = v return nil } +// TimestamptzValue implements the [TimestamptzValuer] interface. func (tstz Timestamptz) TimestamptzValue() (Timestamptz, error) { return tstz, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (tstz *Timestamptz) Scan(src any) error { if src == nil { *tstz = Timestamptz{} @@ -63,7 +67,7 @@ func (tstz *Timestamptz) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (tstz Timestamptz) Value() (driver.Value, error) { if !tstz.Valid { return nil, nil @@ -75,6 +79,7 @@ func (tstz Timestamptz) Value() (driver.Value, error) { return tstz.Time, nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (tstz Timestamptz) MarshalJSON() ([]byte, error) { if !tstz.Valid { return []byte("null"), nil @@ -94,6 +99,7 @@ func (tstz Timestamptz) MarshalJSON() ([]byte, error) { return json.Marshal(s) } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (tstz *Timestamptz) UnmarshalJSON(b []byte) error { var s *string err := json.Unmarshal(b, &s) @@ -225,7 +231,6 @@ func (encodePlanTimestamptzCodecText) Encode(value any, buf []byte) (newBuf []by } func (c *TimestamptzCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go index f2b2fa6d..e6d4b1cf 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go @@ -3,6 +3,7 @@ package pgtype import ( "database/sql/driver" "encoding/binary" + "encoding/json" "fmt" "math" "strconv" @@ -24,16 +25,18 @@ type Uint32 struct { Valid bool } +// ScanUint32 implements the [Uint32Scanner] interface. func (n *Uint32) ScanUint32(v Uint32) error { *n = v return nil } +// Uint32Value implements the [Uint32Valuer] interface. func (n Uint32) Uint32Value() (Uint32, error) { return n, nil } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *Uint32) Scan(src any) error { if src == nil { *dst = Uint32{} @@ -67,7 +70,7 @@ func (dst *Uint32) Scan(src any) error { return nil } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src Uint32) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -75,6 +78,31 @@ func (src Uint32) Value() (driver.Value, error) { return int64(src.Uint32), nil } +// MarshalJSON implements the [encoding/json.Marshaler] interface. +func (src Uint32) MarshalJSON() ([]byte, error) { + if !src.Valid { + return []byte("null"), nil + } + return json.Marshal(src.Uint32) +} + +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. +func (dst *Uint32) UnmarshalJSON(b []byte) error { + var n *uint32 + err := json.Unmarshal(b, &n) + if err != nil { + return err + } + + if n == nil { + *dst = Uint32{} + } else { + *dst = Uint32{Uint32: *n, Valid: true} + } + + return nil +} + type Uint32Codec struct{} func (Uint32Codec) FormatSupported(format int16) bool { @@ -197,7 +225,6 @@ func (encodePlanUint32CodecTextInt64Valuer) Encode(value any, buf []byte) (newBu } func (Uint32Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { - switch format { case BinaryFormatCode: switch target.(type) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go new file mode 100644 index 00000000..68fd1661 --- /dev/null +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go @@ -0,0 +1,323 @@ +package pgtype + +import ( + "database/sql/driver" + "encoding/binary" + "fmt" + "math" + "strconv" + + "github.com/jackc/pgx/v5/internal/pgio" +) + +type Uint64Scanner interface { + ScanUint64(v Uint64) error +} + +type Uint64Valuer interface { + Uint64Value() (Uint64, error) +} + +// Uint64 is the core type that is used to represent PostgreSQL types such as XID8. +type Uint64 struct { + Uint64 uint64 + Valid bool +} + +// ScanUint64 implements the [Uint64Scanner] interface. +func (n *Uint64) ScanUint64(v Uint64) error { + *n = v + return nil +} + +// Uint64Value implements the [Uint64Valuer] interface. +func (n Uint64) Uint64Value() (Uint64, error) { + return n, nil +} + +// Scan implements the [database/sql.Scanner] interface. +func (dst *Uint64) Scan(src any) error { + if src == nil { + *dst = Uint64{} + return nil + } + + var n uint64 + + switch src := src.(type) { + case int64: + if src < 0 { + return fmt.Errorf("%d is less than the minimum value for Uint64", src) + } + n = uint64(src) + case string: + un, err := strconv.ParseUint(src, 10, 64) + if err != nil { + return err + } + n = un + default: + return fmt.Errorf("cannot scan %T", src) + } + + *dst = Uint64{Uint64: n, Valid: true} + + return nil +} + +// Value implements the [database/sql/driver.Valuer] interface. +func (src Uint64) Value() (driver.Value, error) { + if !src.Valid { + return nil, nil + } + + // If the value is greater than the maximum value for int64, return it as a string instead of losing data or returning + // an error. + if src.Uint64 > math.MaxInt64 { + return strconv.FormatUint(src.Uint64, 10), nil + } + + return int64(src.Uint64), nil +} + +type Uint64Codec struct{} + +func (Uint64Codec) FormatSupported(format int16) bool { + return format == TextFormatCode || format == BinaryFormatCode +} + +func (Uint64Codec) PreferredFormat() int16 { + return BinaryFormatCode +} + +func (Uint64Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan { + switch format { + case BinaryFormatCode: + switch value.(type) { + case uint64: + return encodePlanUint64CodecBinaryUint64{} + case Uint64Valuer: + return encodePlanUint64CodecBinaryUint64Valuer{} + case Int64Valuer: + return encodePlanUint64CodecBinaryInt64Valuer{} + } + case TextFormatCode: + switch value.(type) { + case uint64: + return encodePlanUint64CodecTextUint64{} + case Int64Valuer: + return encodePlanUint64CodecTextInt64Valuer{} + } + } + + return nil +} + +type encodePlanUint64CodecBinaryUint64 struct{} + +func (encodePlanUint64CodecBinaryUint64) Encode(value any, buf []byte) (newBuf []byte, err error) { + v := value.(uint64) + return pgio.AppendUint64(buf, v), nil +} + +type encodePlanUint64CodecBinaryUint64Valuer struct{} + +func (encodePlanUint64CodecBinaryUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { + v, err := value.(Uint64Valuer).Uint64Value() + if err != nil { + return nil, err + } + + if !v.Valid { + return nil, nil + } + + return pgio.AppendUint64(buf, v.Uint64), nil +} + +type encodePlanUint64CodecBinaryInt64Valuer struct{} + +func (encodePlanUint64CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { + v, err := value.(Int64Valuer).Int64Value() + if err != nil { + return nil, err + } + + if !v.Valid { + return nil, nil + } + + if v.Int64 < 0 { + return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64) + } + + return pgio.AppendUint64(buf, uint64(v.Int64)), nil +} + +type encodePlanUint64CodecTextUint64 struct{} + +func (encodePlanUint64CodecTextUint64) Encode(value any, buf []byte) (newBuf []byte, err error) { + v := value.(uint64) + return append(buf, strconv.FormatUint(uint64(v), 10)...), nil +} + +type encodePlanUint64CodecTextUint64Valuer struct{} + +func (encodePlanUint64CodecTextUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { + v, err := value.(Uint64Valuer).Uint64Value() + if err != nil { + return nil, err + } + + if !v.Valid { + return nil, nil + } + + return append(buf, strconv.FormatUint(v.Uint64, 10)...), nil +} + +type encodePlanUint64CodecTextInt64Valuer struct{} + +func (encodePlanUint64CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) { + v, err := value.(Int64Valuer).Int64Value() + if err != nil { + return nil, err + } + + if !v.Valid { + return nil, nil + } + + if v.Int64 < 0 { + return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64) + } + + return append(buf, strconv.FormatInt(v.Int64, 10)...), nil +} + +func (Uint64Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { + switch format { + case BinaryFormatCode: + switch target.(type) { + case *uint64: + return scanPlanBinaryUint64ToUint64{} + case Uint64Scanner: + return scanPlanBinaryUint64ToUint64Scanner{} + case TextScanner: + return scanPlanBinaryUint64ToTextScanner{} + } + case TextFormatCode: + switch target.(type) { + case *uint64: + return scanPlanTextAnyToUint64{} + case Uint64Scanner: + return scanPlanTextAnyToUint64Scanner{} + } + } + + return nil +} + +func (c Uint64Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) { + if src == nil { + return nil, nil + } + + var n uint64 + err := codecScan(c, m, oid, format, src, &n) + if err != nil { + return nil, err + } + return int64(n), nil +} + +func (c Uint64Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) { + if src == nil { + return nil, nil + } + + var n uint64 + err := codecScan(c, m, oid, format, src, &n) + if err != nil { + return nil, err + } + return n, nil +} + +type scanPlanBinaryUint64ToUint64 struct{} + +func (scanPlanBinaryUint64ToUint64) Scan(src []byte, dst any) error { + if src == nil { + return fmt.Errorf("cannot scan NULL into %T", dst) + } + + if len(src) != 8 { + return fmt.Errorf("invalid length for uint64: %v", len(src)) + } + + p := (dst).(*uint64) + *p = binary.BigEndian.Uint64(src) + + return nil +} + +type scanPlanBinaryUint64ToUint64Scanner struct{} + +func (scanPlanBinaryUint64ToUint64Scanner) Scan(src []byte, dst any) error { + s, ok := (dst).(Uint64Scanner) + if !ok { + return ErrScanTargetTypeChanged + } + + if src == nil { + return s.ScanUint64(Uint64{}) + } + + if len(src) != 8 { + return fmt.Errorf("invalid length for uint64: %v", len(src)) + } + + n := binary.BigEndian.Uint64(src) + + return s.ScanUint64(Uint64{Uint64: n, Valid: true}) +} + +type scanPlanBinaryUint64ToTextScanner struct{} + +func (scanPlanBinaryUint64ToTextScanner) Scan(src []byte, dst any) error { + s, ok := (dst).(TextScanner) + if !ok { + return ErrScanTargetTypeChanged + } + + if src == nil { + return s.ScanText(Text{}) + } + + if len(src) != 8 { + return fmt.Errorf("invalid length for uint64: %v", len(src)) + } + + n := uint64(binary.BigEndian.Uint64(src)) + return s.ScanText(Text{String: strconv.FormatUint(n, 10), Valid: true}) +} + +type scanPlanTextAnyToUint64Scanner struct{} + +func (scanPlanTextAnyToUint64Scanner) Scan(src []byte, dst any) error { + s, ok := (dst).(Uint64Scanner) + if !ok { + return ErrScanTargetTypeChanged + } + + if src == nil { + return s.ScanUint64(Uint64{}) + } + + n, err := strconv.ParseUint(string(src), 10, 64) + if err != nil { + return err + } + + return s.ScanUint64(Uint64{Uint64: n, Valid: true}) +} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go index d57c0f2f..83d0c412 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go @@ -20,11 +20,13 @@ type UUID struct { Valid bool } +// ScanUUID implements the [UUIDScanner] interface. func (b *UUID) ScanUUID(v UUID) error { *b = v return nil } +// UUIDValue implements the [UUIDValuer] interface. func (b UUID) UUIDValue() (UUID, error) { return b, nil } @@ -67,7 +69,7 @@ func encodeUUID(src [16]byte) string { return string(buf[:]) } -// Scan implements the database/sql Scanner interface. +// Scan implements the [database/sql.Scanner] interface. func (dst *UUID) Scan(src any) error { if src == nil { *dst = UUID{} @@ -87,7 +89,7 @@ func (dst *UUID) Scan(src any) error { return fmt.Errorf("cannot scan %T", src) } -// Value implements the database/sql/driver Valuer interface. +// Value implements the [database/sql/driver.Valuer] interface. func (src UUID) Value() (driver.Value, error) { if !src.Valid { return nil, nil @@ -96,6 +98,15 @@ func (src UUID) Value() (driver.Value, error) { return encodeUUID(src.Bytes), nil } +func (src UUID) String() string { + if !src.Valid { + return "" + } + + return encodeUUID(src.Bytes) +} + +// MarshalJSON implements the [encoding/json.Marshaler] interface. func (src UUID) MarshalJSON() ([]byte, error) { if !src.Valid { return []byte("null"), nil @@ -108,6 +119,7 @@ func (src UUID) MarshalJSON() ([]byte, error) { return buff.Bytes(), nil } +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. func (dst *UUID) UnmarshalJSON(src []byte) error { if bytes.Equal(src, []byte("null")) { *dst = UUID{} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/xml.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/xml.go index fb4c49ad..79e3698a 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/xml.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgtype/xml.go @@ -113,7 +113,7 @@ func (c *XMLCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPl // https://github.com/jackc/pgx/issues/1691 -- ** anything else if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok { - if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil { + if nextPlan := m.planScan(oid, format, nextDst, 0); nextPlan != nil { if _, failed := nextPlan.(*scanPlanFail); !failed { wrapperPlan.SetNext(nextPlan) return wrapperPlan diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go index fdcba724..addfb412 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go @@ -2,7 +2,7 @@ package pgxpool import ( "context" - "fmt" + "errors" "math/rand" "runtime" "strconv" @@ -15,11 +15,14 @@ import ( "github.com/jackc/puddle/v2" ) -var defaultMaxConns = int32(4) -var defaultMinConns = int32(0) -var defaultMaxConnLifetime = time.Hour -var defaultMaxConnIdleTime = time.Minute * 30 -var defaultHealthCheckPeriod = time.Minute +var ( + defaultMaxConns = int32(4) + defaultMinConns = int32(0) + defaultMinIdleConns = int32(0) + defaultMaxConnLifetime = time.Hour + defaultMaxConnIdleTime = time.Minute * 30 + defaultHealthCheckPeriod = time.Minute +) type connResource struct { conn *pgx.Conn @@ -83,10 +86,12 @@ type Pool struct { config *Config beforeConnect func(context.Context, *pgx.ConnConfig) error afterConnect func(context.Context, *pgx.Conn) error - beforeAcquire func(context.Context, *pgx.Conn) bool + prepareConn func(context.Context, *pgx.Conn) (bool, error) afterRelease func(*pgx.Conn) bool beforeClose func(*pgx.Conn) + shouldPing func(context.Context, ShouldPingParams) bool minConns int32 + minIdleConns int32 maxConns int32 maxConnLifetime time.Duration maxConnLifetimeJitter time.Duration @@ -102,6 +107,12 @@ type Pool struct { closeChan chan struct{} } +// ShouldPingParams are the parameters passed to ShouldPing. +type ShouldPingParams struct { + Conn *pgx.Conn + IdleDuration time.Duration +} + // Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be // modified. type Config struct { @@ -117,8 +128,23 @@ type Config struct { // BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the // acquisition or false to indicate that the connection should be destroyed and a different connection should be // acquired. + // + // Deprecated: Use PrepareConn instead. If both PrepareConn and BeforeAcquire are set, PrepareConn will take + // precedence, ignoring BeforeAcquire. BeforeAcquire func(context.Context, *pgx.Conn) bool + // PrepareConn is called before a connection is acquired from the pool. If this function returns true, the connection + // is considered valid, otherwise the connection is destroyed. If the function returns a non-nil error, the instigating + // query will fail with the returned error. + // + // Specifically, this means that: + // + // - If it returns true and a nil error, the query proceeds as normal. + // - If it returns true and an error, the connection will be returned to the pool, and the instigating query will fail with the returned error. + // - If it returns false, and an error, the connection will be destroyed, and the query will fail with the returned error. + // - If it returns false and a nil error, the connection will be destroyed, and the instigating query will be retried on a new connection. + PrepareConn func(context.Context, *pgx.Conn) (bool, error) + // AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to // return the connection to the pool or false to destroy the connection. AfterRelease func(*pgx.Conn) bool @@ -126,6 +152,10 @@ type Config struct { // BeforeClose is called right before a connection is closed and removed from the pool. BeforeClose func(*pgx.Conn) + // ShouldPing is called after a connection is acquired from the pool. If it returns true, the connection is pinged to check for liveness. + // If this func is not set, the default behavior is to ping connections that have been idle for at least 1 second. + ShouldPing func(context.Context, ShouldPingParams) bool + // MaxConnLifetime is the duration since creation after which a connection will be automatically closed. MaxConnLifetime time.Duration @@ -144,6 +174,13 @@ type Config struct { // to create new connections. MinConns int32 + // MinIdleConns is the minimum number of idle connections in the pool. You can increase this to ensure that + // there are always idle connections available. This can help reduce tail latencies during request processing, + // as you can avoid the latency of establishing a new connection while handling requests. It is superior + // to MinConns for this purpose. + // Similar to MinConns, the pool might temporarily dip below MinIdleConns after connection closes. + MinIdleConns int32 + // HealthCheckPeriod is the duration between checks of the health of idle connections. HealthCheckPeriod time.Duration @@ -181,14 +218,22 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) { panic("config must be created by ParseConfig") } + prepareConn := config.PrepareConn + if prepareConn == nil && config.BeforeAcquire != nil { + prepareConn = func(ctx context.Context, conn *pgx.Conn) (bool, error) { + return config.BeforeAcquire(ctx, conn), nil + } + } + p := &Pool{ config: config, beforeConnect: config.BeforeConnect, afterConnect: config.AfterConnect, - beforeAcquire: config.BeforeAcquire, + prepareConn: prepareConn, afterRelease: config.AfterRelease, beforeClose: config.BeforeClose, minConns: config.MinConns, + minIdleConns: config.MinIdleConns, maxConns: config.MaxConns, maxConnLifetime: config.MaxConnLifetime, maxConnLifetimeJitter: config.MaxConnLifetimeJitter, @@ -206,6 +251,14 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) { p.releaseTracer = t } + if config.ShouldPing != nil { + p.shouldPing = config.ShouldPing + } else { + p.shouldPing = func(ctx context.Context, params ShouldPingParams) bool { + return params.IdleDuration > time.Second + } + } + var err error p.p, err = puddle.NewPool( &puddle.Config[*connResource]{ @@ -271,7 +324,8 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) { } go func() { - p.createIdleResources(ctx, int(p.minConns)) + targetIdleResources := max(int(p.minConns), int(p.minIdleConns)) + p.createIdleResources(ctx, targetIdleResources) p.backgroundHealthCheck() }() @@ -281,20 +335,20 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) { // ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the // addition of the following variables: // -// - pool_max_conns: integer greater than 0 -// - pool_min_conns: integer 0 or greater -// - pool_max_conn_lifetime: duration string -// - pool_max_conn_idle_time: duration string -// - pool_health_check_period: duration string -// - pool_max_conn_lifetime_jitter: duration string +// - pool_max_conns: integer greater than 0 (default 4) +// - pool_min_conns: integer 0 or greater (default 0) +// - pool_max_conn_lifetime: duration string (default 1 hour) +// - pool_max_conn_idle_time: duration string (default 30 minutes) +// - pool_health_check_period: duration string (default 1 minute) +// - pool_max_conn_lifetime_jitter: duration string (default 0) // // See Config for definitions of these arguments. // // # Example Keyword/Value -// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 +// user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 pool_max_conn_lifetime=1h30m // // # Example URL -// postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10 +// postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10&pool_max_conn_lifetime=1h30m func ParseConfig(connString string) (*Config, error) { connConfig, err := pgx.ParseConfig(connString) if err != nil { @@ -310,10 +364,10 @@ func ParseConfig(connString string) (*Config, error) { delete(connConfig.Config.RuntimeParams, "pool_max_conns") n, err := strconv.ParseInt(s, 10, 32) if err != nil { - return nil, fmt.Errorf("cannot parse pool_max_conns: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conns", err) } if n < 1 { - return nil, fmt.Errorf("pool_max_conns too small: %d", n) + return nil, pgconn.NewParseConfigError(connString, "pool_max_conns too small", err) } config.MaxConns = int32(n) } else { @@ -327,18 +381,29 @@ func ParseConfig(connString string) (*Config, error) { delete(connConfig.Config.RuntimeParams, "pool_min_conns") n, err := strconv.ParseInt(s, 10, 32) if err != nil { - return nil, fmt.Errorf("cannot parse pool_min_conns: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_conns", err) } config.MinConns = int32(n) } else { config.MinConns = defaultMinConns } + if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_idle_conns"]; ok { + delete(connConfig.Config.RuntimeParams, "pool_min_idle_conns") + n, err := strconv.ParseInt(s, 10, 32) + if err != nil { + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_idle_conns", err) + } + config.MinIdleConns = int32(n) + } else { + config.MinIdleConns = defaultMinIdleConns + } + if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok { delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime") d, err := time.ParseDuration(s) if err != nil { - return nil, fmt.Errorf("invalid pool_max_conn_lifetime: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime", err) } config.MaxConnLifetime = d } else { @@ -349,7 +414,7 @@ func ParseConfig(connString string) (*Config, error) { delete(connConfig.Config.RuntimeParams, "pool_max_conn_idle_time") d, err := time.ParseDuration(s) if err != nil { - return nil, fmt.Errorf("invalid pool_max_conn_idle_time: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_idle_time", err) } config.MaxConnIdleTime = d } else { @@ -360,7 +425,7 @@ func ParseConfig(connString string) (*Config, error) { delete(connConfig.Config.RuntimeParams, "pool_health_check_period") d, err := time.ParseDuration(s) if err != nil { - return nil, fmt.Errorf("invalid pool_health_check_period: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_health_check_period", err) } config.HealthCheckPeriod = d } else { @@ -371,7 +436,7 @@ func ParseConfig(connString string) (*Config, error) { delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter") d, err := time.ParseDuration(s) if err != nil { - return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err) + return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime_jitter", err) } config.MaxConnLifetimeJitter = d } @@ -472,7 +537,9 @@ func (p *Pool) checkMinConns() error { // TotalConns can include ones that are being destroyed but we should have // sleep(500ms) around all of the destroys to help prevent that from throwing // off this check - toCreate := p.minConns - p.Stat().TotalConns() + + // Create the number of connections needed to get to both minConns and minIdleConns + toCreate := max(p.minConns-p.Stat().TotalConns(), p.minIdleConns-p.Stat().IdleConns()) if toCreate > 0 { return p.createIdleResources(context.Background(), int(toCreate)) } @@ -521,7 +588,10 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) { }() } - for { + // Try to acquire from the connection pool up to maxConns + 1 times, so that + // any that fatal errors would empty the pool and still at least try 1 fresh + // connection. + for range p.maxConns + 1 { res, err := p.p.Acquire(ctx) if err != nil { return nil, err @@ -529,7 +599,8 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) { cr := res.Value() - if res.IdleDuration() > time.Second { + shouldPingParams := ShouldPingParams{Conn: cr.conn, IdleDuration: res.IdleDuration()} + if p.shouldPing(ctx, shouldPingParams) { err := cr.conn.Ping(ctx) if err != nil { res.Destroy() @@ -537,12 +608,25 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) { } } - if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) { - return cr.getConn(p, res), nil + if p.prepareConn != nil { + ok, err := p.prepareConn(ctx, cr.conn) + if !ok { + res.Destroy() + } + if err != nil { + if ok { + res.Release() + } + return nil, err + } + if !ok { + continue + } } - res.Destroy() + return cr.getConn(p, res), nil } + return nil, errors.New("pgxpool: detected infinite loop acquiring connection; likely bug in PrepareConn or BeforeAcquire hook") } // AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the @@ -565,11 +649,14 @@ func (p *Pool) AcquireAllIdle(ctx context.Context) []*Conn { conns := make([]*Conn, 0, len(resources)) for _, res := range resources { cr := res.Value() - if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) { - conns = append(conns, cr.getConn(p, res)) - } else { - res.Destroy() + if p.prepareConn != nil { + ok, err := p.prepareConn(ctx, cr.conn) + if !ok || err != nil { + res.Destroy() + continue + } } + conns = append(conns, cr.getConn(p, res)) } return conns diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go b/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go index cfa0c4c5..e02b6ac3 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go @@ -82,3 +82,10 @@ func (s *Stat) MaxLifetimeDestroyCount() int64 { func (s *Stat) MaxIdleDestroyCount() int64 { return s.idleDestroyCount } + +// EmptyAcquireWaitTime returns the cumulative time waited for successful acquires +// from the pool for a resource to be released or constructed because the pool was +// empty. +func (s *Stat) EmptyAcquireWaitTime() time.Duration { + return s.s.EmptyAcquireWaitTime() +} diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/rows.go b/event-processor/vendor/github.com/jackc/pgx/v5/rows.go index f23625d4..a5725fdd 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/rows.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/rows.go @@ -41,22 +41,19 @@ type Rows interface { // when there was an error executing the query. FieldDescriptions() []pgconn.FieldDescription - // Next prepares the next row for reading. It returns true if there is another - // row and false if no more rows are available or a fatal error has occurred. - // It automatically closes rows when all rows are read. + // Next prepares the next row for reading. It returns true if there is another row and false if no more rows are + // available or a fatal error has occurred. It automatically closes rows upon returning false (whether due to all rows + // having been read or due to an error). // - // Callers should check rows.Err() after rows.Next() returns false to detect - // whether result-set reading ended prematurely due to an error. See - // Conn.Query for details. + // Callers should check rows.Err() after rows.Next() returns false to detect whether result-set reading ended + // prematurely due to an error. See Conn.Query for details. // - // For simpler error handling, consider using the higher-level pgx v5 - // CollectRows() and ForEachRow() helpers instead. + // For simpler error handling, consider using the higher-level pgx v5 CollectRows() and ForEachRow() helpers instead. Next() bool - // Scan reads the values from the current row into dest values positionally. - // dest can include pointers to core types, values implementing the Scanner - // interface, and nil. nil will skip the value entirely. It is an error to - // call Scan without first calling Next() and checking that it returned true. + // Scan reads the values from the current row into dest values positionally. dest can include pointers to core types, + // values implementing the Scanner interface, and nil. nil will skip the value entirely. It is an error to call Scan + // without first calling Next() and checking that it returned true. Rows is automatically closed upon error. Scan(dest ...any) error // Values returns the decoded row values. As with Scan(), it is an error to @@ -188,6 +185,17 @@ func (rows *baseRows) Close() { } else if rows.queryTracer != nil { rows.queryTracer.TraceQueryEnd(rows.ctx, rows.conn, TraceQueryEndData{rows.commandTag, rows.err}) } + + // Zero references to other memory allocations. This allows them to be GC'd even when the Rows still referenced. In + // particular, when using pgxpool GC could be delayed as pgxpool.poolRows are allocated in large slices. + // + // https://github.com/jackc/pgx/pull/2269 + rows.values = nil + rows.scanPlans = nil + rows.scanTypes = nil + rows.ctx = nil + rows.sql = "" + rows.args = nil } func (rows *baseRows) CommandTag() pgconn.CommandTag { @@ -272,7 +280,7 @@ func (rows *baseRows) Scan(dest ...any) error { err := rows.scanPlans[i].Scan(values[i], dst) if err != nil { - err = ScanArgError{ColumnIndex: i, Err: err} + err = ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err} rows.fatal(err) return err } @@ -334,11 +342,16 @@ func (rows *baseRows) Conn() *Conn { type ScanArgError struct { ColumnIndex int + FieldName string Err error } func (e ScanArgError) Error() string { - return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err) + if e.FieldName == "?column?" { // Don't include the fieldname if it's unknown + return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err) + } + + return fmt.Sprintf("can't scan into dest[%d] (col: %s): %v", e.ColumnIndex, e.FieldName, e.Err) } func (e ScanArgError) Unwrap() error { @@ -366,7 +379,7 @@ func ScanRow(typeMap *pgtype.Map, fieldDescriptions []pgconn.FieldDescription, v err := typeMap.Scan(fieldDescriptions[i].DataTypeOID, fieldDescriptions[i].Format, values[i], d) if err != nil { - return ScanArgError{ColumnIndex: i, Err: err} + return ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err} } } @@ -468,6 +481,8 @@ func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) { return value, err } + // The defer rows.Close() won't have executed yet. If the query returned more than one row, rows would still be open. + // rows.Close() must be called before rows.Err() so we explicitly call it here. rows.Close() return value, rows.Err() } @@ -545,7 +560,7 @@ func (rs *mapRowScanner) ScanRow(rows Rows) error { return nil } -// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row +// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number of public fields as row // has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then the field will be // ignored. func RowToStructByPos[T any](row CollectableRow) (T, error) { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/stdlib/sql.go b/event-processor/vendor/github.com/jackc/pgx/v5/stdlib/sql.go index c1d00ab4..939b9636 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/stdlib/sql.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/stdlib/sql.go @@ -216,7 +216,8 @@ func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB { // OpenDBFromPool creates a new *sql.DB from the given *pgxpool.Pool. Note that this method automatically sets the // maximum number of idle connections in *sql.DB to zero, since they must be managed from the *pgxpool.Pool. This is -// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool. +// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool. Note +// that closing the returned *sql.DB will not close the *pgxpool.Pool. func OpenDBFromPool(pool *pgxpool.Pool, opts ...OptionOpenDB) *sql.DB { c := GetPoolConnector(pool, opts...) db := sql.OpenDB(c) @@ -470,7 +471,8 @@ func (c *Conn) ExecContext(ctx context.Context, query string, argsV []driver.Nam return nil, driver.ErrBadConn } - args := namedValueToInterface(argsV) + args := make([]any, len(argsV)) + convertNamedArguments(args, argsV) commandTag, err := c.conn.Exec(ctx, query, args...) // if we got a network error before we had a chance to send the query, retry @@ -487,8 +489,9 @@ func (c *Conn) QueryContext(ctx context.Context, query string, argsV []driver.Na return nil, driver.ErrBadConn } - args := []any{databaseSQLResultFormats} - args = append(args, namedValueToInterface(argsV)...) + args := make([]any, 1+len(argsV)) + args[0] = databaseSQLResultFormats + convertNamedArguments(args[1:], argsV) rows, err := c.conn.Query(ctx, query, args...) if err != nil { @@ -847,28 +850,14 @@ func (r *Rows) Next(dest []driver.Value) error { return nil } -func valueToInterface(argsV []driver.Value) []any { - args := make([]any, 0, len(argsV)) - for _, v := range argsV { - if v != nil { - args = append(args, v.(any)) - } else { - args = append(args, nil) - } - } - return args -} - -func namedValueToInterface(argsV []driver.NamedValue) []any { - args := make([]any, 0, len(argsV)) - for _, v := range argsV { +func convertNamedArguments(args []any, argsV []driver.NamedValue) { + for i, v := range argsV { if v.Value != nil { - args = append(args, v.Value.(any)) + args[i] = v.Value.(any) } else { - args = append(args, nil) + args[i] = nil } } - return args } type wrapTx struct { diff --git a/event-processor/vendor/github.com/jackc/pgx/v5/tx.go b/event-processor/vendor/github.com/jackc/pgx/v5/tx.go index 8feeb512..571e5e00 100644 --- a/event-processor/vendor/github.com/jackc/pgx/v5/tx.go +++ b/event-processor/vendor/github.com/jackc/pgx/v5/tx.go @@ -3,7 +3,6 @@ package pgx import ( "context" "errors" - "fmt" "strconv" "strings" @@ -48,6 +47,8 @@ type TxOptions struct { // BeginQuery is the SQL query that will be executed to begin the transaction. This allows using non-standard syntax // such as BEGIN PRIORITY HIGH with CockroachDB. If set this will override the other settings. BeginQuery string + // CommitQuery is the SQL query that will be executed to commit the transaction. + CommitQuery string } var emptyTxOptions TxOptions @@ -101,11 +102,14 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (Tx, error) { if err != nil { // begin should never fail unless there is an underlying connection issue or // a context timeout. In either case, the connection is possibly broken. - c.die(errors.New("failed to begin transaction")) + c.die() return nil, err } - return &dbTx{conn: c}, nil + return &dbTx{ + conn: c, + commitQuery: txOptions.CommitQuery, + }, nil } // Tx represents a database transaction. @@ -154,6 +158,7 @@ type dbTx struct { conn *Conn savepointNum int64 closed bool + commitQuery string } // Begin starts a pseudo nested transaction implemented with a savepoint. @@ -177,7 +182,12 @@ func (tx *dbTx) Commit(ctx context.Context) error { return ErrTxClosed } - commandTag, err := tx.conn.Exec(ctx, "commit") + commandSQL := "commit" + if tx.commitQuery != "" { + commandSQL = tx.commitQuery + } + + commandTag, err := tx.conn.Exec(ctx, commandSQL) tx.closed = true if err != nil { if tx.conn.PgConn().TxStatus() != 'I' { @@ -205,7 +215,7 @@ func (tx *dbTx) Rollback(ctx context.Context) error { tx.closed = true if err != nil { // A rollback failure leaves the connection in an undefined state - tx.conn.die(fmt.Errorf("rollback failed: %w", err)) + tx.conn.die() return err } diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/cmd/protoc-gen-go-plugin/main.go b/event-processor/vendor/github.com/knqyf263/go-plugin/cmd/protoc-gen-go-plugin/main.go index 0e642220..69457879 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/cmd/protoc-gen-go-plugin/main.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/cmd/protoc-gen-go-plugin/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/pluginpb" @@ -10,6 +11,7 @@ import ( func main() { var flags flag.FlagSet + disablePbGen := flags.Bool("disable_pb_gen", false, "disable .pb.go generation") protogen.Options{ParamFunc: flags.Set}.Run(func(plugin *protogen.Plugin) error { g, err := gen.NewGenerator(plugin) if err != nil { @@ -20,7 +22,7 @@ func main() { if !f.Generate { continue } - g.GenerateFiles(f) + g.GenerateFiles(f, gen.Options{DisablePBGen: *disablePbGen}) } plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/host.go b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/host.go index fb13c518..715a2f99 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/host.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/host.go @@ -17,7 +17,7 @@ func (gg *Generator) generateHostFile(f *fileInfo) { } // Build constraints - g.P("//go:build !tinygo.wasm") + g.P("//go:build !wasip1") gg.generateHeader(g, f) gg.genHostFunctions(g, f) @@ -142,7 +142,7 @@ func genHost(g *protogen.GeneratedFile, f *fileInfo, service *serviceInfo) { )) g.P(fmt.Sprintf(`o := &WazeroConfig{ newRuntime: DefaultWazeroRuntime(), - moduleConfig: %s(), + moduleConfig: %s().WithStartFunctions("_initialize"), } for _, opt := range opts { @@ -332,7 +332,7 @@ func genPluginMethod(g *protogen.GeneratedFile, f *fileInfo, method *protogen.Me results, err := p.malloc.Call(ctx, dataSize) %s dataPtr = results[0] - // This pointer is managed by TinyGo, but TinyGo is unaware of external usage. + // This pointer is managed by the Wasm module, which is unaware of external usage. // So, we have to free it when finished defer p.free.Call(ctx, dataPtr) diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/main.go b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/main.go index 3d96403e..05f14308 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/main.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/main.go @@ -89,6 +89,10 @@ type Generator struct { vtgen *vtgenerator.Generator } +type Options struct { + DisablePBGen bool +} + func NewGenerator(plugin *protogen.Plugin) (*Generator, error) { ext := &vtgenerator.Extensions{} featureNames := []string{"marshal", "unmarshal", "size"} @@ -103,7 +107,7 @@ func NewGenerator(plugin *protogen.Plugin) (*Generator, error) { continue } - // Replace google known types with custom types so that TinyGo can build them. + // Replace google known types with custom types so that they can be used in Wasm. walkMessages(f.Messages, func(message *protogen.Message) { for _, field := range message.Fields { replaceImport(field.Message) @@ -138,9 +142,9 @@ func replaceImport(m *protogen.Message) { } // GenerateFiles generates the contents of a .pb.go file. -func (gg *Generator) GenerateFiles(file *protogen.File) *protogen.GeneratedFile { +func (gg *Generator) GenerateFiles(file *protogen.File, opts Options) *protogen.GeneratedFile { f := gg.newFileInfo(file) - gg.generatePBFile(f) + gg.generatePBFile(f, opts.DisablePBGen) gg.generateHostFile(f) gg.generatePluginFile(f) gg.generateVTFile(f) @@ -148,8 +152,12 @@ func (gg *Generator) GenerateFiles(file *protogen.File) *protogen.GeneratedFile return nil } -func (gg *Generator) generatePBFile(f *fileInfo) { - filename := f.GeneratedFilenamePrefix + ".pb.go" +func (gg *Generator) generatePBFile(f *fileInfo, disabled bool) { + filename := f.GeneratedFilenamePrefix + if disabled { + filename += "_service" + } + filename += ".pb.go" g := gg.plugin.NewGeneratedFile(filename, f.GoImportPath) gg.generateHeader(g, f) @@ -165,14 +173,16 @@ func (gg *Generator) generatePBFile(f *fileInfo) { g.P() } - for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ { - gg.genImport(g, f, imps.Get(i)) - } - for _, enum := range f.allEnums { - genEnum(g, f, enum) - } - for _, message := range f.allMessages { - genMessage(g, f, message) + if !disabled { + for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ { + gg.genImport(g, f, imps.Get(i)) + } + for _, enum := range f.allEnums { + genEnum(g, f, enum) + } + for _, message := range f.allMessages { + genMessage(g, f, message) + } } for _, service := range f.allServices { genServiceInterface(g, f, service) @@ -252,7 +262,7 @@ func (gg *Generator) genImport(g *protogen.GeneratedFile, f *fileInfo, imp proto // Generate public imports by generating the imported file, parsing it, // and extracting every symbol that should receive a forwarding declaration. - impGen := gg.GenerateFiles(impFile) + impGen := gg.GenerateFiles(impFile, Options{}) impGen.Skip() b, err := impGen.Content() if err != nil { diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/options.go b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/options.go index e589fa01..6f20e607 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/options.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/options.go @@ -13,7 +13,7 @@ func (gg *Generator) generateOptionsFile(f *fileInfo) { } // Build constraints - g.P("//go:build !tinygo.wasm") + g.P("//go:build !wasip1") gg.generateHeader(g, f) g.P(fmt.Sprintf(`type wazeroConfigOption func(plugin *WazeroConfig) diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/plugin.go b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/plugin.go index a3c014f8..0f117ba9 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/gen/plugin.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/gen/plugin.go @@ -8,7 +8,7 @@ import ( ) func (gg *Generator) generatePluginFile(f *fileInfo) { - // This file will be imported by plugins written in TinyGo + // This file will be imported by plugins written in Go filename := f.GeneratedFilenamePrefix + "_plugin.pb.go" g := gg.plugin.NewGeneratedFile(filename, f.GoImportPath) @@ -17,7 +17,7 @@ func (gg *Generator) generatePluginFile(f *fileInfo) { } // Build constraints - g.P("//go:build tinygo.wasm") + g.P("//go:build wasip1") // Generate header gg.generateHeader(g, f) @@ -36,7 +36,7 @@ func genPlugin(g *protogen.GeneratedFile, f *fileInfo, service *serviceInfo) { // API version g.P("const ", service.GoName, "PluginAPIVersion = ", service.Version) g.P(fmt.Sprintf(` - //export %s_api_version + //go:wasmexport %s_api_version func _%s_api_version() uint64 { return %sPluginAPIVersion }`, @@ -54,7 +54,7 @@ func genPlugin(g *protogen.GeneratedFile, f *fileInfo, service *serviceInfo) { // Exported functions for _, method := range service.Methods { exportedName := toSnakeCase(service.GoName + method.GoName) - g.P("//export ", exportedName) + g.P("//go:wasmexport ", exportedName) g.P("func _", exportedName, "(ptr, size uint32) uint64 {") g.P("b := ", g.QualifiedGoIdent(pluginWasmPackage.Ident("PtrToByte")), "(ptr, size)") @@ -131,7 +131,7 @@ func genHostFunctions(g *protogen.GeneratedFile, f *fileInfo) { g.QualifiedGoIdent(method.Output.GoIdent), g.QualifiedGoIdent(pluginWasmPackage.Ident("ByteToPtr")), importedName, - g.QualifiedGoIdent(pluginWasmPackage.Ident("FreePtr")), + g.QualifiedGoIdent(pluginWasmPackage.Ident("Free")), g.QualifiedGoIdent(pluginWasmPackage.Ident("PtrToByte")), g.QualifiedGoIdent(method.Output.GoIdent), )) diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration.pb.go index 88790b04..8105397e 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/durationpb/duration.proto package durationpb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration_vtproto.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration_vtproto.pb.go index 3ecfd2c7..f8719c27 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration_vtproto.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/durationpb/duration_vtproto.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/durationpb/duration.proto package durationpb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp.pb.go index e027bbeb..1a366e8a 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/timestamppb/timestamp.proto package timestamppb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp_vtproto.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp_vtproto.pb.go index 1555b0bf..ee509418 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp_vtproto.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/timestamppb/timestamp_vtproto.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/timestamppb/timestamp.proto package timestamppb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers.pb.go index f98018b5..b380f503 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/wrapperspb/wrappers.proto package wrapperspb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers_vtproto.pb.go b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers_vtproto.pb.go index 222451ed..7802cab1 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers_vtproto.pb.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/types/known/wrapperspb/wrappers_vtproto.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-plugin. DO NOT EDIT. // versions: // protoc-gen-go-plugin v0.1.0 -// protoc v4.25.2 +// protoc v5.29.3 // source: types/known/wrapperspb/wrappers.proto package wrapperspb diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/host.go b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/host.go index 88b4c7aa..ec8b8705 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/host.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/host.go @@ -1,4 +1,4 @@ -//go:build !tinygo.wasm +//go:build !wasip1 // This file is designed to be imported by hosts. diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin.go b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin.go index 39217c95..689b7833 100644 --- a/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin.go +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin.go @@ -1,35 +1,54 @@ -//go:build tinygo.wasm +//go:build wasip1 && !tinygo.wasm // This file is designed to be imported by plugins. package wasm -// #include -import "C" - import ( "unsafe" ) -func PtrToByte(ptr, size uint32) []byte { - b := unsafe.Slice((*byte)(unsafe.Pointer(uintptr(ptr))), size) +// allocations keeps track of each allocated byte slice, keyed by a fake pointer. +// This map ensures the GC will not collect these slices while still in use. +var allocations = make(map[uint32][]byte) - return b -} - -func ByteToPtr(buf []byte) (uint32, uint32) { - if len(buf) == 0 { - return 0, 0 +// allocate creates a new byte slice of the given size and stores it in the +// allocations map so that it remains valid (not garbage-collected). +func allocate(size uint32) uint32 { + if size == 0 { + return 0 } + // Create a new byte slice on the Go heap + b := make([]byte, size) - size := C.ulong(len(buf)) - ptr := unsafe.Pointer(C.malloc(size)) + // Obtain the 'address' of the first element in b by converting its pointer to a uint32. + ptr := uint32(uintptr(unsafe.Pointer(&b[0]))) - copy(unsafe.Slice((*byte)(ptr), size), buf) + // Store the byte slice in the map, keyed by the pointer + allocations[ptr] = b + return ptr +} - return uint32(uintptr(ptr)), uint32(len(buf)) +//go:wasmexport malloc +func Malloc(size uint32) uint32 { + return allocate(size) } -func FreePtr(ptr uint32) { - C.free(unsafe.Pointer(uintptr(ptr))) +//go:wasmexport free +func Free(ptr uint32) { + // Remove the slice from the allocations map so the GC can reclaim it later. + delete(allocations, ptr) +} + +func PtrToByte(ptr, size uint32) []byte { + return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(ptr))), size) +} + +func ByteToPtr(buf []byte) (uint32, uint32) { + if len(buf) == 0 { + return 0, 0 + } + ptr := &buf[0] + unsafePtr := uintptr(unsafe.Pointer(ptr)) + return uint32(unsafePtr), uint32(len(buf)) } diff --git a/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin_tinygo.go b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin_tinygo.go new file mode 100644 index 00000000..f834fd04 --- /dev/null +++ b/event-processor/vendor/github.com/knqyf263/go-plugin/wasm/plugin_tinygo.go @@ -0,0 +1,35 @@ +//go:build tinygo.wasm + +// This file is designed to be imported by plugins. + +package wasm + +// #include +import "C" + +import ( + "unsafe" +) + +func PtrToByte(ptr, size uint32) []byte { + b := unsafe.Slice((*byte)(unsafe.Pointer(uintptr(ptr))), size) + + return b +} + +func ByteToPtr(buf []byte) (uint32, uint32) { + if len(buf) == 0 { + return 0, 0 + } + + size := C.ulong(len(buf)) + ptr := unsafe.Pointer(C.malloc(size)) + + copy(unsafe.Slice((*byte)(ptr), size), buf) + + return uint32(uintptr(ptr)), uint32(len(buf)) +} + +func Free(ptr uint32) { + C.free(unsafe.Pointer(uintptr(ptr))) +} diff --git a/event-processor/vendor/github.com/magiconair/properties/.gitignore b/event-processor/vendor/github.com/magiconair/properties/.gitignore deleted file mode 100644 index e7081ff5..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.sublime-project -*.sublime-workspace -*.un~ -*.swp -.idea/ -*.iml diff --git a/event-processor/vendor/github.com/magiconair/properties/CHANGELOG.md b/event-processor/vendor/github.com/magiconair/properties/CHANGELOG.md deleted file mode 100644 index 842e8e24..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/CHANGELOG.md +++ /dev/null @@ -1,205 +0,0 @@ -## Changelog - -### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022 - - * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge - - Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch. - - * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions - -### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022 - - * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error - - Thanks to [@ellie](https://github.com/ellie) for the patch. - - * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible - - This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the - author happy until it affects real users. - - Thanks to [@maage](https://github.com/maage) for the patch. - -### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021 - - * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments - - When reading comments \ are loaded correctly, but when writing they are then - replaced by \\. This leads to wrong comments when writing and reading multiple times. - - Thanks to [@doxsch](https://github.com/doxsch) for the patch. - -### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020 - - * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references - - Thanks to [@sriv](https://github.com/sriv) for the patch. - -### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020 - - * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference - - The change is include the key in the error message which is causing the circular - reference when parsing/loading the properties files. - - Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch. - -### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020 - - * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write - - This patch ensures that backslashes are escaped on write. Existing applications which - rely on the old behavior may need to be updated. - - Thanks to [@apesternikov](https://github.com/apesternikov) for the patch. - - * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL() - - Thanks to [@aliras1](https://github.com/aliras1) for the patch. - - * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write() - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - - * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - -### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019 - - * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request - - This patch ensures that in `LoadURL` the response body is always closed. - - Thanks to [@liubog2008](https://github.com/liubog2008) for the patch. - -### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018 - - * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading - - This adds the option to disable property expansion during loading. - - Thanks to [@kmala](https://github.com/kmala) for the patch. - -### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018 - - * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases. - - See PR for an example. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018 - - * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value - - Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail - with a `circular reference error`. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017 - - * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces - - * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled - - Thanks to [@mgurov](https://github.com/mgurov) for the fix. - -### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017 - - * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically - * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map - -### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017 - - * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency - * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc) - -### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017 - - * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER` - * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs - * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy - * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function - -### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016 - - * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL. - * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string. - * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) - -### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015 - - * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. - -### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015 - - * Vendored in gopkg.in/check.v1 - -### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015 - - * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) - -### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015 - - * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. - -### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015 - - * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) - -### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015 - - * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty - * Add clickable links to README - -### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014 - - * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with - [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). - -### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014 - - * Added support for single and multi-line comments (reading, writing and updating) - * The order of keys is now preserved - * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry - * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method - * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) - -### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014 - - * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one - -### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014 - - * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string - -### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014 - - * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys - * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties - -### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014 - -* Added support for time.Duration -* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom) -* Changed default of MustXXX() failure from panic to log.Fatal - -### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014 - -* Added MustGet... functions -* Added support for int and uint with range checks on 32 bit platforms - -### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014 - -* Renamed from goproperties to properties -* Added support for expansion of environment vars in - filenames and value expressions -* Fixed bug where value expressions were not at the - start of the string - -### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014 - -* Initial release diff --git a/event-processor/vendor/github.com/magiconair/properties/LICENSE.md b/event-processor/vendor/github.com/magiconair/properties/LICENSE.md deleted file mode 100644 index 79c87e3e..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/LICENSE.md +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2013-2020, Frank Schroeder - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/event-processor/vendor/github.com/magiconair/properties/README.md b/event-processor/vendor/github.com/magiconair/properties/README.md deleted file mode 100644 index e2edda02..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/README.md +++ /dev/null @@ -1,128 +0,0 @@ -[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) -[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties) -[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) -[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -# Overview - -#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why. - -properties is a Go library for reading and writing properties files. - -It supports reading from multiple files or URLs and Spring style recursive -property expansion of expressions like `${key}` to their corresponding value. -Value expressions can refer to other keys like in `${key}` or to environment -variables like in `${USER}`. Filenames can also contain environment variables -like in `/home/${USER}/myapp.properties`. - -Properties can be decoded into structs, maps, arrays and values through -struct tags. - -Comments and the order of keys are preserved. Comments can be modified -and can be written to the output. - -The properties library supports both ISO-8859-1 and UTF-8 encoded data. - -Starting from version 1.3.0 the behavior of the MustXXX() functions is -configurable by providing a custom `ErrorHandler` function. The default has -changed from `panic` to `log.Fatal` but this is configurable and custom -error handling functions can be provided. See the package documentation for -details. - -Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -## Getting Started - -```go -import ( - "flag" - "github.com/magiconair/properties" -) - -func main() { - // init from a file - p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) - - // or multiple files - p = properties.MustLoadFiles([]string{ - "${HOME}/config.properties", - "${HOME}/config-${USER}.properties", - }, properties.UTF8, true) - - // or from a map - p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) - - // or from a string - p = properties.MustLoadString("key=value\nabc=def") - - // or from a URL - p = properties.MustLoadURL("http://host/path") - - // or from multiple URLs - p = properties.MustLoadURL([]string{ - "http://host/config", - "http://host/config-${USER}", - }, true) - - // or from flags - p.MustFlag(flag.CommandLine) - - // get values through getters - host := p.MustGetString("host") - port := p.GetInt("port", 8080) - - // or through Decode - type Config struct { - Host string `properties:"host"` - Port int `properties:"port,default=9000"` - Accept []string `properties:"accept,default=image/png;image;gif"` - Timeout time.Duration `properties:"timeout,default=5s"` - } - var cfg Config - if err := p.Decode(&cfg); err != nil { - log.Fatal(err) - } -} - -``` - -## Installation and Upgrade - -``` -$ go get -u github.com/magiconair/properties -``` - -## License - -2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. - -## ToDo - -* Dump contents with passwords and secrets obscured - -## Updated Git tags - -#### 13 Feb 2018 - -I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags -and I've only recently learned that this doesn't play well with `git describe` 😞 - -I have replaced all lightweight tags with signed tags using this script which should -retain the commit date, name and email address. Please run `git pull --tags` to update them. - -Worst case you have to reclone the repo. - -```shell -#!/bin/bash -tag=$1 -echo "Updating $tag" -date=$(git show ${tag}^0 --format=%aD | head -1) -email=$(git show ${tag}^0 --format=%aE | head -1) -name=$(git show ${tag}^0 --format=%aN | head -1) -GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag} -``` - -I apologize for the inconvenience. - -Frank - diff --git a/event-processor/vendor/github.com/magiconair/properties/decode.go b/event-processor/vendor/github.com/magiconair/properties/decode.go deleted file mode 100644 index 8e6aa441..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/decode.go +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "reflect" - "strconv" - "strings" - "time" -) - -// Decode assigns property values to exported fields of a struct. -// -// Decode traverses v recursively and returns an error if a value cannot be -// converted to the field type or a required value is missing for a field. -// -// The following type dependent decodings are used: -// -// String, boolean, numeric fields have the value of the property key assigned. -// The property key name is the name of the field. A different key and a default -// value can be set in the field's tag. Fields without default value are -// required. If the value cannot be converted to the field type an error is -// returned. -// -// time.Duration fields have the result of time.ParseDuration() assigned. -// -// time.Time fields have the vaule of time.Parse() assigned. The default layout -// is time.RFC3339 but can be set in the field's tag. -// -// Arrays and slices of string, boolean, numeric, time.Duration and time.Time -// fields have the value interpreted as a comma separated list of values. The -// individual values are trimmed of whitespace and empty values are ignored. A -// default value can be provided as a semicolon separated list in the field's -// tag. -// -// Struct fields are decoded recursively using the field name plus "." as -// prefix. The prefix (without dot) can be overridden in the field's tag. -// Default values are not supported in the field's tag. Specify them on the -// fields of the inner struct instead. -// -// Map fields must have a key of type string and are decoded recursively by -// using the field's name plus ".' as prefix and the next element of the key -// name as map key. The prefix (without dot) can be overridden in the field's -// tag. Default values are not supported. -// -// Examples: -// -// // Field is ignored. -// Field int `properties:"-"` -// -// // Field is assigned value of 'Field'. -// Field int -// -// // Field is assigned value of 'myName'. -// Field int `properties:"myName"` -// -// // Field is assigned value of key 'myName' and has a default -// // value 15 if the key does not exist. -// Field int `properties:"myName,default=15"` -// -// // Field is assigned value of key 'Field' and has a default -// // value 15 if the key does not exist. -// Field int `properties:",default=15"` -// -// // Field is assigned value of key 'date' and the date -// // is in format 2006-01-02 -// Field time.Time `properties:"date,layout=2006-01-02"` -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas. -// Field []string -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas and has a default -// // value ["a", "b", "c"] if the key does not exist. -// Field []string `properties:",default=a;b;c"` -// -// // Field is decoded recursively with "Field." as key prefix. -// Field SomeStruct -// -// // Field is decoded recursively with "myName." as key prefix. -// Field SomeStruct `properties:"myName"` -// -// // Field is decoded recursively with "Field." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string -// -// // Field is decoded recursively with "myName." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string `properties:"myName"` -func (p *Properties) Decode(x interface{}) error { - t, v := reflect.TypeOf(x), reflect.ValueOf(x) - if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { - return fmt.Errorf("not a pointer to struct: %s", t) - } - if err := dec(p, "", nil, nil, v); err != nil { - return err - } - return nil -} - -func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error { - t := v.Type() - - // value returns the property value for key or the default if provided. - value := func() (string, error) { - if val, ok := p.Get(key); ok { - return val, nil - } - if def != nil { - return *def, nil - } - return "", fmt.Errorf("missing required key %s", key) - } - - // conv converts a string to a value of the given type. - conv := func(s string, t reflect.Type) (val reflect.Value, err error) { - var v interface{} - - switch { - case isDuration(t): - v, err = time.ParseDuration(s) - - case isTime(t): - layout := opts["layout"] - if layout == "" { - layout = time.RFC3339 - } - v, err = time.Parse(layout, s) - - case isBool(t): - v, err = boolVal(s), nil - - case isString(t): - v, err = s, nil - - case isFloat(t): - v, err = strconv.ParseFloat(s, 64) - - case isInt(t): - v, err = strconv.ParseInt(s, 10, 64) - - case isUint(t): - v, err = strconv.ParseUint(s, 10, 64) - - default: - return reflect.Zero(t), fmt.Errorf("unsupported type %s", t) - } - if err != nil { - return reflect.Zero(t), err - } - return reflect.ValueOf(v).Convert(t), nil - } - - // keydef returns the property key and the default value based on the - // name of the struct field and the options in the tag. - keydef := func(f reflect.StructField) (string, *string, map[string]string) { - _key, _opts := parseTag(f.Tag.Get("properties")) - - var _def *string - if d, ok := _opts["default"]; ok { - _def = &d - } - if _key != "" { - return _key, _def, _opts - } - return f.Name, _def, _opts - } - - switch { - case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t): - s, err := value() - if err != nil { - return err - } - val, err := conv(s, t) - if err != nil { - return err - } - v.Set(val) - - case isPtr(t): - return dec(p, key, def, opts, v.Elem()) - - case isStruct(t): - for i := 0; i < v.NumField(); i++ { - fv := v.Field(i) - fk, def, opts := keydef(t.Field(i)) - if !fv.CanSet() { - return fmt.Errorf("cannot set %s", t.Field(i).Name) - } - if fk == "-" { - continue - } - if key != "" { - fk = key + "." + fk - } - if err := dec(p, fk, def, opts, fv); err != nil { - return err - } - } - return nil - - case isArray(t): - val, err := value() - if err != nil { - return err - } - vals := split(val, ";") - a := reflect.MakeSlice(t, 0, len(vals)) - for _, s := range vals { - val, err := conv(s, t.Elem()) - if err != nil { - return err - } - a = reflect.Append(a, val) - } - v.Set(a) - - case isMap(t): - valT := t.Elem() - m := reflect.MakeMap(t) - for postfix := range p.FilterStripPrefix(key + ".").m { - pp := strings.SplitN(postfix, ".", 2) - mk, mv := pp[0], reflect.New(valT) - if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { - return err - } - m.SetMapIndex(reflect.ValueOf(mk), mv.Elem()) - } - v.Set(m) - - default: - return fmt.Errorf("unsupported type %s", t) - } - return nil -} - -// split splits a string on sep, trims whitespace of elements -// and omits empty elements -func split(s string, sep string) []string { - var a []string - for _, v := range strings.Split(s, sep) { - if v = strings.TrimSpace(v); v != "" { - a = append(a, v) - } - } - return a -} - -// parseTag parses a "key,k=v,k=v,..." -func parseTag(tag string) (key string, opts map[string]string) { - opts = map[string]string{} - for i, s := range strings.Split(tag, ",") { - if i == 0 { - key = s - continue - } - - pp := strings.SplitN(s, "=", 2) - if len(pp) == 1 { - opts[pp[0]] = "" - } else { - opts[pp[0]] = pp[1] - } - } - return key, opts -} - -func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice } -func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } -func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } -func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } -func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } -func isString(t reflect.Type) bool { return t.Kind() == reflect.String } -func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } -func isTime(t reflect.Type) bool { return t == reflect.TypeOf(time.Time{}) } -func isFloat(t reflect.Type) bool { - return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 -} -func isInt(t reflect.Type) bool { - return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64 -} -func isUint(t reflect.Type) bool { - return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64 -} diff --git a/event-processor/vendor/github.com/magiconair/properties/doc.go b/event-processor/vendor/github.com/magiconair/properties/doc.go deleted file mode 100644 index 7c797931..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/doc.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package properties provides functions for reading and writing -// ISO-8859-1 and UTF-8 encoded .properties files and has -// support for recursive property expansion. -// -// Java properties files are ISO-8859-1 encoded and use Unicode -// literals for characters outside the ISO character set. Unicode -// literals can be used in UTF-8 encoded properties files but -// aren't necessary. -// -// To load a single properties file use MustLoadFile(): -// -// p := properties.MustLoadFile(filename, properties.UTF8) -// -// To load multiple properties files use MustLoadFiles() -// which loads the files in the given order and merges the -// result. Missing properties files can be ignored if the -// 'ignoreMissing' flag is set to true. -// -// Filenames can contain environment variables which are expanded -// before loading. -// -// f1 := "/etc/myapp/myapp.conf" -// f2 := "/home/${USER}/myapp.conf" -// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) -// -// All of the different key/value delimiters ' ', ':' and '=' are -// supported as well as the comment characters '!' and '#' and -// multi-line values. -// -// ! this is a comment -// # and so is this -// -// # the following expressions are equal -// key value -// key=value -// key:value -// key = value -// key : value -// key = val\ -// ue -// -// Properties stores all comments preceding a key and provides -// GetComments() and SetComments() methods to retrieve and -// update them. The convenience functions GetComment() and -// SetComment() allow access to the last comment. The -// WriteComment() method writes properties files including -// the comments and with the keys in the original order. -// This can be used for sanitizing properties files. -// -// Property expansion is recursive and circular references -// and malformed expressions are not allowed and cause an -// error. Expansion of environment variables is supported. -// -// # standard property -// key = value -// -// # property expansion: key2 = value -// key2 = ${key} -// -// # recursive expansion: key3 = value -// key3 = ${key2} -// -// # circular reference (error) -// key = ${key} -// -// # malformed expression (error) -// key = ${ke -// -// # refers to the users' home dir -// home = ${HOME} -// -// # local key takes precedence over env var: u = foo -// USER = foo -// u = ${USER} -// -// The default property expansion format is ${key} but can be -// changed by setting different pre- and postfix values on the -// Properties object. -// -// p := properties.NewProperties() -// p.Prefix = "#[" -// p.Postfix = "]#" -// -// Properties provides convenience functions for getting typed -// values with default values if the key does not exist or the -// type conversion failed. -// -// # Returns true if the value is either "1", "on", "yes" or "true" -// # Returns false for every other value and the default value if -// # the key does not exist. -// v = p.GetBool("key", false) -// -// # Returns the value if the key exists and the format conversion -// # was successful. Otherwise, the default value is returned. -// v = p.GetInt64("key", 999) -// v = p.GetUint64("key", 999) -// v = p.GetFloat64("key", 123.0) -// v = p.GetString("key", "def") -// v = p.GetDuration("key", 999) -// -// As an alternative properties may be applied with the standard -// library's flag implementation at any time. -// -// # Standard configuration -// v = flag.Int("key", 999, "help message") -// flag.Parse() -// -// # Merge p into the flag set -// p.MustFlag(flag.CommandLine) -// -// Properties provides several MustXXX() convenience functions -// which will terminate the app if an error occurs. The behavior -// of the failure is configurable and the default is to call -// log.Fatal(err). To have the MustXXX() functions panic instead -// of logging the error set a different ErrorHandler before -// you use the Properties package. -// -// properties.ErrorHandler = properties.PanicHandler -// -// # Will panic instead of logging an error -// p := properties.MustLoadFile("config.properties") -// -// You can also provide your own ErrorHandler function. The only requirement -// is that the error handler function must exit after handling the error. -// -// properties.ErrorHandler = func(err error) { -// fmt.Println(err) -// os.Exit(1) -// } -// -// # Will write to stdout and then exit -// p := properties.MustLoadFile("config.properties") -// -// Properties can also be loaded into a struct via the `Decode` -// method, e.g. -// -// type S struct { -// A string `properties:"a,default=foo"` -// D time.Duration `properties:"timeout,default=5s"` -// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` -// } -// -// See `Decode()` method for the full documentation. -// -// The following documents provide a description of the properties -// file format. -// -// http://en.wikipedia.org/wiki/.properties -// -// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 -package properties diff --git a/event-processor/vendor/github.com/magiconair/properties/integrate.go b/event-processor/vendor/github.com/magiconair/properties/integrate.go deleted file mode 100644 index 35d0ae97..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/integrate.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import "flag" - -// MustFlag sets flags that are skipped by dst.Parse when p contains -// the respective key for flag.Flag.Name. -// -// It's use is recommended with command line arguments as in: -// -// flag.Parse() -// p.MustFlag(flag.CommandLine) -func (p *Properties) MustFlag(dst *flag.FlagSet) { - m := make(map[string]*flag.Flag) - dst.VisitAll(func(f *flag.Flag) { - m[f.Name] = f - }) - dst.Visit(func(f *flag.Flag) { - delete(m, f.Name) // overridden - }) - - for name, f := range m { - v, ok := p.Get(name) - if !ok { - continue - } - - if err := f.Value.Set(v); err != nil { - ErrorHandler(err) - } - } -} diff --git a/event-processor/vendor/github.com/magiconair/properties/lex.go b/event-processor/vendor/github.com/magiconair/properties/lex.go deleted file mode 100644 index 3d15a1f6..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/lex.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Parts of the lexer are from the template/text/parser package -// For these parts the following applies: -// -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file of the go 1.2 -// distribution. - -package properties - -import ( - "fmt" - "strconv" - "strings" - "unicode/utf8" -) - -// item represents a token or text string returned from the scanner. -type item struct { - typ itemType // The type of this item. - pos int // The starting position, in bytes, of this item in the input string. - val string // The value of this item. -} - -func (i item) String() string { - switch { - case i.typ == itemEOF: - return "EOF" - case i.typ == itemError: - return i.val - case len(i.val) > 10: - return fmt.Sprintf("%.10q...", i.val) - } - return fmt.Sprintf("%q", i.val) -} - -// itemType identifies the type of lex items. -type itemType int - -const ( - itemError itemType = iota // error occurred; value is text of error - itemEOF - itemKey // a key - itemValue // a value - itemComment // a comment -) - -// defines a constant for EOF -const eof = -1 - -// permitted whitespace characters space, FF and TAB -const whitespace = " \f\t" - -// stateFn represents the state of the scanner as a function that returns the next state. -type stateFn func(*lexer) stateFn - -// lexer holds the state of the scanner. -type lexer struct { - input string // the string being scanned - state stateFn // the next lexing function to enter - pos int // current position in the input - start int // start position of this item - width int // width of last rune read from input - lastPos int // position of most recent item returned by nextItem - runes []rune // scanned runes for this item - items chan item // channel of scanned items -} - -// next returns the next rune in the input. -func (l *lexer) next() rune { - if l.pos >= len(l.input) { - l.width = 0 - return eof - } - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = w - l.pos += l.width - return r -} - -// peek returns but does not consume the next rune in the input. -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one rune. Can only be called once per call of next. -func (l *lexer) backup() { - l.pos -= l.width -} - -// emit passes an item back to the client. -func (l *lexer) emit(t itemType) { - i := item{t, l.start, string(l.runes)} - l.items <- i - l.start = l.pos - l.runes = l.runes[:0] -} - -// ignore skips over the pending input before this point. -func (l *lexer) ignore() { - l.start = l.pos -} - -// appends the rune to the current value -func (l *lexer) appendRune(r rune) { - l.runes = append(l.runes, r) -} - -// accept consumes the next rune if it's from the valid set. -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - l.backup() - return false -} - -// acceptRun consumes a run of runes from the valid set. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// lineNumber reports which line we're on, based on the position of -// the previous item returned by nextItem. Doing it this way -// means we don't have to worry about peek double counting. -func (l *lexer) lineNumber() int { - return 1 + strings.Count(l.input[:l.lastPos], "\n") -} - -// errorf returns an error token and terminates the scan by passing -// back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { - l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} - return nil -} - -// nextItem returns the next item from the input. -func (l *lexer) nextItem() item { - i := <-l.items - l.lastPos = i.pos - return i -} - -// lex creates a new scanner for the input string. -func lex(input string) *lexer { - l := &lexer{ - input: input, - items: make(chan item), - runes: make([]rune, 0, 32), - } - go l.run() - return l -} - -// run runs the state machine for the lexer. -func (l *lexer) run() { - for l.state = lexBeforeKey(l); l.state != nil; { - l.state = l.state(l) - } -} - -// state functions - -// lexBeforeKey scans until a key begins. -func lexBeforeKey(l *lexer) stateFn { - switch r := l.next(); { - case isEOF(r): - l.emit(itemEOF) - return nil - - case isEOL(r): - l.ignore() - return lexBeforeKey - - case isComment(r): - return lexComment - - case isWhitespace(r): - l.ignore() - return lexBeforeKey - - default: - l.backup() - return lexKey - } -} - -// lexComment scans a comment line. The comment character has already been scanned. -func lexComment(l *lexer) stateFn { - l.acceptRun(whitespace) - l.ignore() - for { - switch r := l.next(); { - case isEOF(r): - l.ignore() - l.emit(itemEOF) - return nil - case isEOL(r): - l.emit(itemComment) - return lexBeforeKey - default: - l.appendRune(r) - } - } -} - -// lexKey scans the key up to a delimiter -func lexKey(l *lexer) stateFn { - var r rune - -Loop: - for { - switch r = l.next(); { - - case isEscape(r): - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - - case isEndOfKey(r): - l.backup() - break Loop - - case isEOF(r): - break Loop - - default: - l.appendRune(r) - } - } - - if len(l.runes) > 0 { - l.emit(itemKey) - } - - if isEOF(r) { - l.emit(itemEOF) - return nil - } - - return lexBeforeValue -} - -// lexBeforeValue scans the delimiter between key and value. -// Leading and trailing whitespace is ignored. -// We expect to be just after the key. -func lexBeforeValue(l *lexer) stateFn { - l.acceptRun(whitespace) - l.accept(":=") - l.acceptRun(whitespace) - l.ignore() - return lexValue -} - -// lexValue scans text until the end of the line. We expect to be just after the delimiter. -func lexValue(l *lexer) stateFn { - for { - switch r := l.next(); { - case isEscape(r): - if isEOL(l.peek()) { - l.next() - l.acceptRun(whitespace) - } else { - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - } - - case isEOL(r): - l.emit(itemValue) - l.ignore() - return lexBeforeKey - - case isEOF(r): - l.emit(itemValue) - l.emit(itemEOF) - return nil - - default: - l.appendRune(r) - } - } -} - -// scanEscapeSequence scans either one of the escaped characters -// or a unicode literal. We expect to be after the escape character. -func (l *lexer) scanEscapeSequence() error { - switch r := l.next(); { - - case isEscapedCharacter(r): - l.appendRune(decodeEscapedCharacter(r)) - return nil - - case atUnicodeLiteral(r): - return l.scanUnicodeLiteral() - - case isEOF(r): - return fmt.Errorf("premature EOF") - - // silently drop the escape character and append the rune as is - default: - l.appendRune(r) - return nil - } -} - -// scans a unicode literal in the form \uXXXX. We expect to be after the \u. -func (l *lexer) scanUnicodeLiteral() error { - // scan the digits - d := make([]rune, 4) - for i := 0; i < 4; i++ { - d[i] = l.next() - if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) { - return fmt.Errorf("invalid unicode literal") - } - } - - // decode the digits into a rune - r, err := strconv.ParseInt(string(d), 16, 0) - if err != nil { - return err - } - - l.appendRune(rune(r)) - return nil -} - -// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character. -func decodeEscapedCharacter(r rune) rune { - switch r { - case 'f': - return '\f' - case 'n': - return '\n' - case 'r': - return '\r' - case 't': - return '\t' - default: - return r - } -} - -// atUnicodeLiteral reports whether we are at a unicode literal. -// The escape character has already been consumed. -func atUnicodeLiteral(r rune) bool { - return r == 'u' -} - -// isComment reports whether we are at the start of a comment. -func isComment(r rune) bool { - return r == '#' || r == '!' -} - -// isEndOfKey reports whether the rune terminates the current key. -func isEndOfKey(r rune) bool { - return strings.ContainsRune(" \f\t\r\n:=", r) -} - -// isEOF reports whether we are at EOF. -func isEOF(r rune) bool { - return r == eof -} - -// isEOL reports whether we are at a new line character. -func isEOL(r rune) bool { - return r == '\n' || r == '\r' -} - -// isEscape reports whether the rune is the escape character which -// prefixes unicode literals and other escaped characters. -func isEscape(r rune) bool { - return r == '\\' -} - -// isEscapedCharacter reports whether we are at one of the characters that need escaping. -// The escape character has already been consumed. -func isEscapedCharacter(r rune) bool { - return strings.ContainsRune(" :=fnrt", r) -} - -// isWhitespace reports whether the rune is a whitespace character. -func isWhitespace(r rune) bool { - return strings.ContainsRune(whitespace, r) -} diff --git a/event-processor/vendor/github.com/magiconair/properties/load.go b/event-processor/vendor/github.com/magiconair/properties/load.go deleted file mode 100644 index 635368dc..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/load.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "strings" -) - -// Encoding specifies encoding of the input data. -type Encoding uint - -const ( - // utf8Default is a private placeholder for the zero value of Encoding to - // ensure that it has the correct meaning. UTF8 is the default encoding but - // was assigned a non-zero value which cannot be changed without breaking - // existing code. Clients should continue to use the public constants. - utf8Default Encoding = iota - - // UTF8 interprets the input data as UTF-8. - UTF8 - - // ISO_8859_1 interprets the input data as ISO-8859-1. - ISO_8859_1 -) - -type Loader struct { - // Encoding determines how the data from files and byte buffers - // is interpreted. For URLs the Content-Type header is used - // to determine the encoding of the data. - Encoding Encoding - - // DisableExpansion configures the property expansion of the - // returned property object. When set to true, the property values - // will not be expanded and the Property object will not be checked - // for invalid expansion expressions. - DisableExpansion bool - - // IgnoreMissing configures whether missing files or URLs which return - // 404 are reported as errors. When set to true, missing files and 404 - // status codes are not reported as errors. - IgnoreMissing bool -} - -// Load reads a buffer into a Properties struct. -func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { - return l.loadBytes(buf, l.Encoding) -} - -// LoadAll reads the content of multiple URLs or files in the given order into -// a Properties struct. If IgnoreMissing is true then a 404 status code or -// missing file will not be reported as error. Encoding sets the encoding for -// files. For the URLs see LoadURL for the Content-Type header and the -// encoding. -func (l *Loader) LoadAll(names []string) (*Properties, error) { - all := NewProperties() - for _, name := range names { - n, err := expandName(name) - if err != nil { - return nil, err - } - - var p *Properties - switch { - case strings.HasPrefix(n, "http://"): - p, err = l.LoadURL(n) - case strings.HasPrefix(n, "https://"): - p, err = l.LoadURL(n) - default: - p, err = l.LoadFile(n) - } - if err != nil { - return nil, err - } - all.Merge(p) - } - - all.DisableExpansion = l.DisableExpansion - if all.DisableExpansion { - return all, nil - } - return all, all.check() -} - -// LoadFile reads a file into a Properties struct. -// If IgnoreMissing is true then a missing file will not be -// reported as error. -func (l *Loader) LoadFile(filename string) (*Properties, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - if l.IgnoreMissing && os.IsNotExist(err) { - LogPrintf("properties: %s not found. skipping", filename) - return NewProperties(), nil - } - return nil, err - } - return l.loadBytes(data, l.Encoding) -} - -// LoadURL reads the content of the URL into a Properties struct. -// -// The encoding is determined via the Content-Type header which -// should be set to 'text/plain'. If the 'charset' parameter is -// missing, 'iso-8859-1' or 'latin1' the encoding is set to -// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the -// encoding is set to UTF-8. A missing content type header is -// interpreted as 'text/plain; charset=utf-8'. -func (l *Loader) LoadURL(url string) (*Properties, error) { - resp, err := http.Get(url) - if err != nil { - return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) - } - defer resp.Body.Close() - - if resp.StatusCode == 404 && l.IgnoreMissing { - LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) - return NewProperties(), nil - } - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) - } - - ct := resp.Header.Get("Content-Type") - ct = strings.Join(strings.Fields(ct), "") - var enc Encoding - switch strings.ToLower(ct) { - case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1": - enc = ISO_8859_1 - case "", "text/plain;charset=utf-8": - enc = UTF8 - default: - return nil, fmt.Errorf("properties: invalid content type %s", ct) - } - - return l.loadBytes(body, enc) -} - -func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { - p, err := parse(convert(buf, enc)) - if err != nil { - return nil, err - } - p.DisableExpansion = l.DisableExpansion - if p.DisableExpansion { - return p, nil - } - return p, p.check() -} - -// Load reads a buffer into a Properties struct. -func Load(buf []byte, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadBytes(buf) -} - -// LoadString reads an UTF8 string into a properties struct. -func LoadString(s string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadBytes([]byte(s)) -} - -// LoadMap creates a new Properties struct from a string map. -func LoadMap(m map[string]string) *Properties { - p := NewProperties() - for k, v := range m { - p.Set(k, v) - } - return p -} - -// LoadFile reads a file into a Properties struct. -func LoadFile(filename string, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadAll([]string{filename}) -} - -// LoadFiles reads multiple files in the given order into -// a Properties struct. If 'ignoreMissing' is true then -// non-existent files will not be reported as error. -func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(filenames) -} - -// LoadURL reads the content of the URL into a Properties struct. -// See Loader#LoadURL for details. -func LoadURL(url string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadAll([]string{url}) -} - -// LoadURLs reads the content of multiple URLs in the given order into a -// Properties struct. If IgnoreMissing is true then a 404 status code will -// not be reported as error. See Loader#LoadURL for the Content-Type header -// and the encoding. -func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} - return l.LoadAll(urls) -} - -// LoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. -func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(names) -} - -// MustLoadString reads an UTF8 string into a Properties struct and -// panics on error. -func MustLoadString(s string) *Properties { - return must(LoadString(s)) -} - -// MustLoadFile reads a file into a Properties struct and -// panics on error. -func MustLoadFile(filename string, enc Encoding) *Properties { - return must(LoadFile(filename, enc)) -} - -// MustLoadFiles reads multiple files in the given order into -// a Properties struct and panics on error. If 'ignoreMissing' -// is true then non-existent files will not be reported as error. -func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadFiles(filenames, enc, ignoreMissing)) -} - -// MustLoadURL reads the content of a URL into a Properties struct and -// panics on error. -func MustLoadURL(url string) *Properties { - return must(LoadURL(url)) -} - -// MustLoadURLs reads the content of multiple URLs in the given order into a -// Properties struct and panics on error. If 'ignoreMissing' is true then a 404 -// status code will not be reported as error. -func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { - return must(LoadURLs(urls, ignoreMissing)) -} - -// MustLoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. It panics on error. -func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadAll(names, enc, ignoreMissing)) -} - -func must(p *Properties, err error) *Properties { - if err != nil { - ErrorHandler(err) - } - return p -} - -// expandName expands ${ENV_VAR} expressions in a name. -// If the environment variable does not exist then it will be replaced -// with an empty string. Malformed expressions like "${ENV_VAR" will -// be reported as error. -func expandName(name string) (string, error) { - return expand(name, []string{}, "${", "}", make(map[string]string)) -} - -// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. -// For ISO-8859-1 we can convert each byte straight into a rune since the -// first 256 unicode code points cover ISO-8859-1. -func convert(buf []byte, enc Encoding) string { - switch enc { - case utf8Default, UTF8: - return string(buf) - case ISO_8859_1: - runes := make([]rune, len(buf)) - for i, b := range buf { - runes[i] = rune(b) - } - return string(runes) - default: - ErrorHandler(fmt.Errorf("unsupported encoding %v", enc)) - } - panic("ErrorHandler should exit") -} diff --git a/event-processor/vendor/github.com/magiconair/properties/parser.go b/event-processor/vendor/github.com/magiconair/properties/parser.go deleted file mode 100644 index fccfd39f..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/parser.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "runtime" -) - -type parser struct { - lex *lexer -} - -func parse(input string) (properties *Properties, err error) { - p := &parser{lex: lex(input)} - defer p.recover(&err) - - properties = NewProperties() - key := "" - comments := []string{} - - for { - token := p.expectOneOf(itemComment, itemKey, itemEOF) - switch token.typ { - case itemEOF: - goto done - case itemComment: - comments = append(comments, token.val) - continue - case itemKey: - key = token.val - if _, ok := properties.m[key]; !ok { - properties.k = append(properties.k, key) - } - } - - token = p.expectOneOf(itemValue, itemEOF) - if len(comments) > 0 { - properties.c[key] = comments - comments = []string{} - } - switch token.typ { - case itemEOF: - properties.m[key] = "" - goto done - case itemValue: - properties.m[key] = token.val - } - } - -done: - return properties, nil -} - -func (p *parser) errorf(format string, args ...interface{}) { - format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format) - panic(fmt.Errorf(format, args...)) -} - -func (p *parser) expectOneOf(expected ...itemType) (token item) { - token = p.lex.nextItem() - for _, v := range expected { - if token.typ == v { - return token - } - } - p.unexpected(token) - panic("unexpected token") -} - -func (p *parser) unexpected(token item) { - p.errorf(token.String()) -} - -// recover is the handler that turns panics into returns from the top level of Parse. -func (p *parser) recover(errp *error) { - e := recover() - if e != nil { - if _, ok := e.(runtime.Error); ok { - panic(e) - } - *errp = e.(error) - } -} diff --git a/event-processor/vendor/github.com/magiconair/properties/properties.go b/event-processor/vendor/github.com/magiconair/properties/properties.go deleted file mode 100644 index fb2f7b40..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/properties.go +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer. -// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. - -import ( - "bytes" - "fmt" - "io" - "log" - "os" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -const maxExpansionDepth = 64 - -// ErrorHandlerFunc defines the type of function which handles failures -// of the MustXXX() functions. An error handler function must exit -// the application after handling the error. -type ErrorHandlerFunc func(error) - -// ErrorHandler is the function which handles failures of the MustXXX() -// functions. The default is LogFatalHandler. -var ErrorHandler ErrorHandlerFunc = LogFatalHandler - -// LogHandlerFunc defines the function prototype for logging errors. -type LogHandlerFunc func(fmt string, args ...interface{}) - -// LogPrintf defines a log handler which uses log.Printf. -var LogPrintf LogHandlerFunc = log.Printf - -// LogFatalHandler handles the error by logging a fatal error and exiting. -func LogFatalHandler(err error) { - log.Fatal(err) -} - -// PanicHandler handles the error by panicking. -func PanicHandler(err error) { - panic(err) -} - -// ----------------------------------------------------------------------------- - -// A Properties contains the key/value pairs from the properties input. -// All values are stored in unexpanded form and are expanded at runtime -type Properties struct { - // Pre-/Postfix for property expansion. - Prefix string - Postfix string - - // DisableExpansion controls the expansion of properties on Get() - // and the check for circular references on Set(). When set to - // true Properties behaves like a simple key/value store and does - // not check for circular references on Get() or on Set(). - DisableExpansion bool - - // Stores the key/value pairs - m map[string]string - - // Stores the comments per key. - c map[string][]string - - // Stores the keys in order of appearance. - k []string - - // WriteSeparator specifies the separator of key and value while writing the properties. - WriteSeparator string -} - -// NewProperties creates a new Properties struct with the default -// configuration for "${key}" expressions. -func NewProperties() *Properties { - return &Properties{ - Prefix: "${", - Postfix: "}", - m: map[string]string{}, - c: map[string][]string{}, - k: []string{}, - } -} - -// Load reads a buffer into the given Properties struct. -func (p *Properties) Load(buf []byte, enc Encoding) error { - l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} - newProperties, err := l.LoadBytes(buf) - if err != nil { - return err - } - p.Merge(newProperties) - return nil -} - -// Get returns the expanded value for the given key if exists. -// Otherwise, ok is false. -func (p *Properties) Get(key string) (value string, ok bool) { - v, ok := p.m[key] - if p.DisableExpansion { - return v, ok - } - if !ok { - return "", false - } - - expanded, err := p.expand(key, v) - - // we guarantee that the expanded value is free of - // circular references and malformed expressions - // so we panic if we still get an error here. - if err != nil { - ErrorHandler(err) - } - - return expanded, true -} - -// MustGet returns the expanded value for the given key if exists. -// Otherwise, it panics. -func (p *Properties) MustGet(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// ClearComments removes the comments for all keys. -func (p *Properties) ClearComments() { - p.c = map[string][]string{} -} - -// ---------------------------------------------------------------------------- - -// GetComment returns the last comment before the given key or an empty string. -func (p *Properties) GetComment(key string) string { - comments, ok := p.c[key] - if !ok || len(comments) == 0 { - return "" - } - return comments[len(comments)-1] -} - -// ---------------------------------------------------------------------------- - -// GetComments returns all comments that appeared before the given key or nil. -func (p *Properties) GetComments(key string) []string { - if comments, ok := p.c[key]; ok { - return comments - } - return nil -} - -// ---------------------------------------------------------------------------- - -// SetComment sets the comment for the key. -func (p *Properties) SetComment(key, comment string) { - p.c[key] = []string{comment} -} - -// ---------------------------------------------------------------------------- - -// SetComments sets the comments for the key. If the comments are nil then -// all comments for this key are deleted. -func (p *Properties) SetComments(key string, comments []string) { - if comments == nil { - delete(p.c, key) - return - } - p.c[key] = comments -} - -// ---------------------------------------------------------------------------- - -// GetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the default value is returned. -func (p *Properties) GetBool(key string, def bool) bool { - v, err := p.getBool(key) - if err != nil { - return def - } - return v -} - -// MustGetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the function panics. -func (p *Properties) MustGetBool(key string) bool { - v, err := p.getBool(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getBool(key string) (value bool, err error) { - if v, ok := p.Get(key); ok { - return boolVal(v), nil - } - return false, invalidKeyError(key) -} - -func boolVal(v string) bool { - v = strings.ToLower(v) - return v == "1" || v == "true" || v == "yes" || v == "on" -} - -// ---------------------------------------------------------------------------- - -// GetDuration parses the expanded value as an time.Duration (in ns) if the -// key exists. If key does not exist or the value cannot be parsed the default -// value is returned. In almost all cases you want to use GetParsedDuration(). -func (p *Properties) GetDuration(key string, def time.Duration) time.Duration { - v, err := p.getInt64(key) - if err != nil { - return def - } - return time.Duration(v) -} - -// MustGetDuration parses the expanded value as an time.Duration (in ns) if -// the key exists. If key does not exist or the value cannot be parsed the -// function panics. In almost all cases you want to use MustGetParsedDuration(). -func (p *Properties) MustGetDuration(key string) time.Duration { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return time.Duration(v) -} - -// ---------------------------------------------------------------------------- - -// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration { - s, ok := p.Get(key) - if !ok { - return def - } - v, err := time.ParseDuration(s) - if err != nil { - return def - } - return v -} - -// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetParsedDuration(key string) time.Duration { - s, ok := p.Get(key) - if !ok { - ErrorHandler(invalidKeyError(key)) - } - v, err := time.ParseDuration(s) - if err != nil { - ErrorHandler(err) - } - return v -} - -// ---------------------------------------------------------------------------- - -// GetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetFloat64(key string, def float64) float64 { - v, err := p.getFloat64(key) - if err != nil { - return def - } - return v -} - -// MustGetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetFloat64(key string) float64 { - v, err := p.getFloat64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getFloat64(key string) (value float64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseFloat(v, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetInt(key string, def int) int { - v, err := p.getInt64(key) - if err != nil { - return def - } - return intRangeCheck(key, v) -} - -// MustGetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetInt(key string) int { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return intRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetInt64 parses the expanded value as an int64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetInt64(key string, def int64) int64 { - v, err := p.getInt64(key) - if err != nil { - return def - } - return v -} - -// MustGetInt64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetInt64(key string) int64 { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getInt64(key string) (value int64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseInt(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetUint parses the expanded value as an uint if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetUint(key string, def uint) uint { - v, err := p.getUint64(key) - if err != nil { - return def - } - return uintRangeCheck(key, v) -} - -// MustGetUint parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetUint(key string) uint { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return uintRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetUint64 parses the expanded value as an uint64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetUint64(key string, def uint64) uint64 { - v, err := p.getUint64(key) - if err != nil { - return def - } - return v -} - -// MustGetUint64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetUint64(key string) uint64 { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getUint64(key string) (value uint64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseUint(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetString returns the expanded value for the given key if exists or -// the default value otherwise. -func (p *Properties) GetString(key, def string) string { - if v, ok := p.Get(key); ok { - return v - } - return def -} - -// MustGetString returns the expanded value for the given key if exists or -// panics otherwise. -func (p *Properties) MustGetString(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// Filter returns a new properties object which contains all properties -// for which the key matches the pattern. -func (p *Properties) Filter(pattern string) (*Properties, error) { - re, err := regexp.Compile(pattern) - if err != nil { - return nil, err - } - - return p.FilterRegexp(re), nil -} - -// FilterRegexp returns a new properties object which contains all properties -// for which the key matches the regular expression. -func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { - pp := NewProperties() - for _, k := range p.k { - if re.MatchString(k) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterPrefix returns a new properties object with a subset of all keys -// with the given prefix. -func (p *Properties) FilterPrefix(prefix string) *Properties { - pp := NewProperties() - for _, k := range p.k { - if strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterStripPrefix returns a new properties object with a subset of all keys -// with the given prefix and the prefix removed from the keys. -func (p *Properties) FilterStripPrefix(prefix string) *Properties { - pp := NewProperties() - n := len(prefix) - for _, k := range p.k { - if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference - // TODO(fs): this function should probably return an error but the signature is fixed - pp.Set(k[n:], p.m[k]) - } - } - return pp -} - -// Len returns the number of keys. -func (p *Properties) Len() int { - return len(p.m) -} - -// Keys returns all keys in the same order as in the input. -func (p *Properties) Keys() []string { - keys := make([]string, len(p.k)) - copy(keys, p.k) - return keys -} - -// Set sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. If the value contains a -// circular reference or a malformed expression then -// an error is returned. -// An empty key is silently ignored. -func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { - if key == "" { - return "", false, nil - } - - // if expansion is disabled we allow circular references - if p.DisableExpansion { - prev, ok = p.Get(key) - p.m[key] = value - if !ok { - p.k = append(p.k, key) - } - return prev, ok, nil - } - - // to check for a circular reference we temporarily need - // to set the new value. If there is an error then revert - // to the previous state. Only if all tests are successful - // then we add the key to the p.k list. - prev, ok = p.Get(key) - p.m[key] = value - - // now check for a circular reference - _, err = p.expand(key, value) - if err != nil { - - // revert to the previous state - if ok { - p.m[key] = prev - } else { - delete(p.m, key) - } - - return "", false, err - } - - if !ok { - p.k = append(p.k, key) - } - - return prev, ok, nil -} - -// SetValue sets property key to the default string value -// as defined by fmt.Sprintf("%v"). -func (p *Properties) SetValue(key string, value interface{}) error { - _, _, err := p.Set(key, fmt.Sprintf("%v", value)) - return err -} - -// MustSet sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. An empty key is silently ignored. -func (p *Properties) MustSet(key, value string) (prev string, ok bool) { - prev, ok, err := p.Set(key, value) - if err != nil { - ErrorHandler(err) - } - return prev, ok -} - -// String returns a string of all expanded 'key = value' pairs. -func (p *Properties) String() string { - var s string - for _, key := range p.k { - value, _ := p.Get(key) - s = fmt.Sprintf("%s%s = %s\n", s, key, value) - } - return s -} - -// Sort sorts the properties keys in alphabetical order. -// This is helpfully before writing the properties. -func (p *Properties) Sort() { - sort.Strings(p.k) -} - -// Write writes all unexpanded 'key = value' pairs to the given writer. -// Write returns the number of bytes written and any write error encountered. -func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { - return p.WriteComment(w, "", enc) -} - -// WriteComment writes all unexpanced 'key = value' pairs to the given writer. -// If prefix is not empty then comments are written with a blank line and the -// given prefix. The prefix should be either "# " or "! " to be compatible with -// the properties file format. Otherwise, the properties parser will not be -// able to read the file back in. It returns the number of bytes written and -// any write error encountered. -func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) { - var x int - - for _, key := range p.k { - value := p.m[key] - - if prefix != "" { - if comments, ok := p.c[key]; ok { - // don't print comments if they are all empty - allEmpty := true - for _, c := range comments { - if c != "" { - allEmpty = false - break - } - } - - if !allEmpty { - // add a blank line between entries but not at the top - if len(comments) > 0 && n > 0 { - x, err = fmt.Fprintln(w) - if err != nil { - return - } - n += x - } - - for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) - if err != nil { - return - } - n += x - } - } - } - } - sep := " = " - if p.WriteSeparator != "" { - sep = p.WriteSeparator - } - x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc)) - if err != nil { - return - } - n += x - } - return -} - -// Map returns a copy of the properties as a map. -func (p *Properties) Map() map[string]string { - m := make(map[string]string) - for k, v := range p.m { - m[k] = v - } - return m -} - -// FilterFunc returns a copy of the properties which includes the values which passed all filters. -func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { - pp := NewProperties() -outer: - for k, v := range p.m { - for _, f := range filters { - if !f(k, v) { - continue outer - } - pp.Set(k, v) - } - } - return pp -} - -// ---------------------------------------------------------------------------- - -// Delete removes the key and its comments. -func (p *Properties) Delete(key string) { - delete(p.m, key) - delete(p.c, key) - newKeys := []string{} - for _, k := range p.k { - if k != key { - newKeys = append(newKeys, k) - } - } - p.k = newKeys -} - -// Merge merges properties, comments and keys from other *Properties into p -func (p *Properties) Merge(other *Properties) { - for _, k := range other.k { - if _, ok := p.m[k]; !ok { - p.k = append(p.k, k) - } - } - for k, v := range other.m { - p.m[k] = v - } - for k, v := range other.c { - p.c[k] = v - } -} - -// ---------------------------------------------------------------------------- - -// check expands all values and returns an error if a circular reference or -// a malformed expression was found. -func (p *Properties) check() error { - for key, value := range p.m { - if _, err := p.expand(key, value); err != nil { - return err - } - } - return nil -} - -func (p *Properties) expand(key, input string) (string, error) { - // no pre/postfix -> nothing to expand - if p.Prefix == "" && p.Postfix == "" { - return input, nil - } - - return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) -} - -// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. -// The function keeps track of the keys that were already expanded and stops if it -// detects a circular reference or a malformed expression of the form '(prefix)key'. -func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { - if len(keys) > maxExpansionDepth { - return "", fmt.Errorf("expansion too deep") - } - - for { - start := strings.Index(s, prefix) - if start == -1 { - return s, nil - } - - keyStart := start + len(prefix) - keyLen := strings.Index(s[keyStart:], postfix) - if keyLen == -1 { - return "", fmt.Errorf("malformed expression") - } - - end := keyStart + keyLen + len(postfix) - 1 - key := s[keyStart : keyStart+keyLen] - - // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) - - for _, k := range keys { - if key == k { - var b bytes.Buffer - b.WriteString("circular reference in:\n") - for _, k1 := range keys { - fmt.Fprintf(&b, "%s=%s\n", k1, values[k1]) - } - return "", fmt.Errorf(b.String()) - } - } - - val, ok := values[key] - if !ok { - val = os.Getenv(key) - } - new_val, err := expand(val, append(keys, key), prefix, postfix, values) - if err != nil { - return "", err - } - s = s[:start] + new_val + s[end+1:] - } -} - -// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. -func encode(s string, special string, enc Encoding) string { - switch enc { - case UTF8: - return encodeUtf8(s, special) - case ISO_8859_1: - return encodeIso(s, special) - default: - panic(fmt.Sprintf("unsupported encoding %v", enc)) - } -} - -func encodeUtf8(s string, special string) string { - v := "" - for pos := 0; pos < len(s); { - r, w := utf8.DecodeRuneInString(s[pos:]) - pos += w - v += escape(r, special) - } - return v -} - -func encodeIso(s string, special string) string { - var r rune - var w int - var v string - for pos := 0; pos < len(s); { - switch r, w = utf8.DecodeRuneInString(s[pos:]); { - case r < 1<<8: // single byte rune -> escape special chars only - v += escape(r, special) - case r < 1<<16: // two byte rune -> unicode literal - v += fmt.Sprintf("\\u%04x", r) - default: // more than two bytes per rune -> can't encode - v += "?" - } - pos += w - } - return v -} - -func escape(r rune, special string) string { - switch r { - case '\f': - return "\\f" - case '\n': - return "\\n" - case '\r': - return "\\r" - case '\t': - return "\\t" - case '\\': - return "\\\\" - default: - if strings.ContainsRune(special, r) { - return "\\" + string(r) - } - return string(r) - } -} - -func invalidKeyError(key string) error { - return fmt.Errorf("unknown property: %s", key) -} diff --git a/event-processor/vendor/github.com/magiconair/properties/rangecheck.go b/event-processor/vendor/github.com/magiconair/properties/rangecheck.go deleted file mode 100644 index dbd60b36..00000000 --- a/event-processor/vendor/github.com/magiconair/properties/rangecheck.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "math" -) - -// make this a var to overwrite it in a test -var is32Bit = ^uint(0) == math.MaxUint32 - -// intRangeCheck checks if the value fits into the int type and -// panics if it does not. -func intRangeCheck(key string, v int64) int { - if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return int(v) -} - -// uintRangeCheck checks if the value fits into the uint type and -// panics if it does not. -func uintRangeCheck(key string, v uint64) uint { - if is32Bit && v > math.MaxUint32 { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return uint(v) -} diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/event-processor/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md deleted file mode 100644 index c7582349..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md +++ /dev/null @@ -1,96 +0,0 @@ -## 1.5.0 - -* New option `IgnoreUntaggedFields` to ignore decoding to any fields - without `mapstructure` (or the configured tag name) set [GH-277] -* New option `ErrorUnset` which makes it an error if any fields - in a target struct are not set by the decoding process. [GH-225] -* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240] -* Decoding to slice from array no longer crashes [GH-265] -* Decode nested struct pointers to map [GH-271] -* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280] -* Fix issue where fields with `,omitempty` would sometimes decode - into a map with an empty string key [GH-281] - -## 1.4.3 - -* Fix cases where `json.Number` didn't decode properly [GH-261] - -## 1.4.2 - -* Custom name matchers to support any sort of casing, formatting, etc. for - field names. [GH-250] -* Fix possible panic in ComposeDecodeHookFunc [GH-251] - -## 1.4.1 - -* Fix regression where `*time.Time` value would be set to empty and not be sent - to decode hooks properly [GH-232] - -## 1.4.0 - -* A new decode hook type `DecodeHookFuncValue` has been added that has - access to the full values. [GH-183] -* Squash is now supported with embedded fields that are struct pointers [GH-205] -* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206] - -## 1.3.3 - -* Decoding maps from maps creates a settable value for decode hooks [GH-203] - -## 1.3.2 - -* Decode into interface type with a struct value is supported [GH-187] - -## 1.3.1 - -* Squash should only squash embedded structs. [GH-194] - -## 1.3.0 - -* Added `",omitempty"` support. This will ignore zero values in the source - structure when encoding. [GH-145] - -## 1.2.3 - -* Fix duplicate entries in Keys list with pointer values. [GH-185] - -## 1.2.2 - -* Do not add unsettable (unexported) values to the unused metadata key - or "remain" value. [GH-150] - -## 1.2.1 - -* Go modules checksum mismatch fix - -## 1.2.0 - -* Added support to capture unused values in a field using the `",remain"` value - in the mapstructure tag. There is an example to showcase usage. -* Added `DecoderConfig` option to always squash embedded structs -* `json.Number` can decode into `uint` types -* Empty slices are preserved and not replaced with nil slices -* Fix panic that can occur in when decoding a map into a nil slice of structs -* Improved package documentation for godoc - -## 1.1.2 - -* Fix error when decode hook decodes interface implementation into interface - type. [GH-140] - -## 1.1.1 - -* Fix panic that can happen in `decodePtr` - -## 1.1.0 - -* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] -* Support struct to struct decoding [GH-137] -* If source map value is nil, then destination map value is nil (instead of empty) -* If source slice value is nil, then destination slice value is nil (instead of empty) -* If source pointer is nil, then destination pointer is set to nil (instead of - allocated zero value of type) - -## 1.0.0 - -* Initial tagged stable release. diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/LICENSE b/event-processor/vendor/github.com/mitchellh/mapstructure/LICENSE deleted file mode 100644 index f9c841a5..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Mitchell Hashimoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/README.md b/event-processor/vendor/github.com/mitchellh/mapstructure/README.md deleted file mode 100644 index 0018dc7d..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) - -mapstructure is a Go library for decoding generic map values to structures -and vice versa, while providing helpful error handling. - -This library is most useful when decoding values from some data stream (JSON, -Gob, etc.) where you don't _quite_ know the structure of the underlying data -until you read a part of it. You can therefore read a `map[string]interface{}` -and use this library to decode it into the proper underlying native Go -structure. - -## Installation - -Standard `go get`: - -``` -$ go get github.com/mitchellh/mapstructure -``` - -## Usage & Example - -For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). - -The `Decode` function has examples associated with it there. - -## But Why?! - -Go offers fantastic standard libraries for decoding formats such as JSON. -The standard method is to have a struct pre-created, and populate that struct -from the bytes of the encoded format. This is great, but the problem is if -you have configuration or an encoding that changes slightly depending on -specific fields. For example, consider this JSON: - -```json -{ - "type": "person", - "name": "Mitchell" -} -``` - -Perhaps we can't populate a specific structure without first reading -the "type" field from the JSON. We could always do two passes over the -decoding of the JSON (reading the "type" first, and the rest later). -However, it is much simpler to just decode this into a `map[string]interface{}` -structure, read the "type" key, then use something like this library -to decode it into the proper structure. diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/event-processor/vendor/github.com/mitchellh/mapstructure/decode_hooks.go deleted file mode 100644 index 3a754ca7..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/decode_hooks.go +++ /dev/null @@ -1,279 +0,0 @@ -package mapstructure - -import ( - "encoding" - "errors" - "fmt" - "net" - "reflect" - "strconv" - "strings" - "time" -) - -// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns -// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. -func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { - // Create variables here so we can reference them with the reflect pkg - var f1 DecodeHookFuncType - var f2 DecodeHookFuncKind - var f3 DecodeHookFuncValue - - // Fill in the variables into this interface and the rest is done - // automatically using the reflect package. - potential := []interface{}{f1, f2, f3} - - v := reflect.ValueOf(h) - vt := v.Type() - for _, raw := range potential { - pt := reflect.ValueOf(raw).Type() - if vt.ConvertibleTo(pt) { - return v.Convert(pt).Interface() - } - } - - return nil -} - -// DecodeHookExec executes the given decode hook. This should be used -// since it'll naturally degrade to the older backwards compatible DecodeHookFunc -// that took reflect.Kind instead of reflect.Type. -func DecodeHookExec( - raw DecodeHookFunc, - from reflect.Value, to reflect.Value) (interface{}, error) { - - switch f := typedDecodeHook(raw).(type) { - case DecodeHookFuncType: - return f(from.Type(), to.Type(), from.Interface()) - case DecodeHookFuncKind: - return f(from.Kind(), to.Kind(), from.Interface()) - case DecodeHookFuncValue: - return f(from, to) - default: - return nil, errors.New("invalid decode hook signature") - } -} - -// ComposeDecodeHookFunc creates a single DecodeHookFunc that -// automatically composes multiple DecodeHookFuncs. -// -// The composed funcs are called in order, with the result of the -// previous transformation. -func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { - var err error - data := f.Interface() - - newFrom := f - for _, f1 := range fs { - data, err = DecodeHookExec(f1, newFrom, t) - if err != nil { - return nil, err - } - newFrom = reflect.ValueOf(data) - } - - return data, nil - } -} - -// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. -// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. -func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { - return func(a, b reflect.Value) (interface{}, error) { - var allErrs string - var out interface{} - var err error - - for _, f := range ff { - out, err = DecodeHookExec(f, a, b) - if err != nil { - allErrs += err.Error() + "\n" - continue - } - - return out, nil - } - - return nil, errors.New(allErrs) - } -} - -// StringToSliceHookFunc returns a DecodeHookFunc that converts -// string to []string by splitting on the given sep. -func StringToSliceHookFunc(sep string) DecodeHookFunc { - return func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - if f != reflect.String || t != reflect.Slice { - return data, nil - } - - raw := data.(string) - if raw == "" { - return []string{}, nil - } - - return strings.Split(raw, sep), nil - } -} - -// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts -// strings to time.Duration. -func StringToTimeDurationHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(time.Duration(5)) { - return data, nil - } - - // Convert it by parsing - return time.ParseDuration(data.(string)) - } -} - -// StringToIPHookFunc returns a DecodeHookFunc that converts -// strings to net.IP -func StringToIPHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(net.IP{}) { - return data, nil - } - - // Convert it by parsing - ip := net.ParseIP(data.(string)) - if ip == nil { - return net.IP{}, fmt.Errorf("failed parsing ip %v", data) - } - - return ip, nil - } -} - -// StringToIPNetHookFunc returns a DecodeHookFunc that converts -// strings to net.IPNet -func StringToIPNetHookFunc() DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(net.IPNet{}) { - return data, nil - } - - // Convert it by parsing - _, net, err := net.ParseCIDR(data.(string)) - return net, err - } -} - -// StringToTimeHookFunc returns a DecodeHookFunc that converts -// strings to time.Time. -func StringToTimeHookFunc(layout string) DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - if t != reflect.TypeOf(time.Time{}) { - return data, nil - } - - // Convert it by parsing - return time.Parse(layout, data.(string)) - } -} - -// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to -// the decoder. -// -// Note that this is significantly different from the WeaklyTypedInput option -// of the DecoderConfig. -func WeaklyTypedHook( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - dataVal := reflect.ValueOf(data) - switch t { - case reflect.String: - switch f { - case reflect.Bool: - if dataVal.Bool() { - return "1", nil - } - return "0", nil - case reflect.Float32: - return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil - case reflect.Int: - return strconv.FormatInt(dataVal.Int(), 10), nil - case reflect.Slice: - dataType := dataVal.Type() - elemKind := dataType.Elem().Kind() - if elemKind == reflect.Uint8 { - return string(dataVal.Interface().([]uint8)), nil - } - case reflect.Uint: - return strconv.FormatUint(dataVal.Uint(), 10), nil - } - } - - return data, nil -} - -func RecursiveStructToMapHookFunc() DecodeHookFunc { - return func(f reflect.Value, t reflect.Value) (interface{}, error) { - if f.Kind() != reflect.Struct { - return f.Interface(), nil - } - - var i interface{} = struct{}{} - if t.Type() != reflect.TypeOf(&i).Elem() { - return f.Interface(), nil - } - - m := make(map[string]interface{}) - t.Set(reflect.ValueOf(m)) - - return f.Interface(), nil - } -} - -// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies -// strings to the UnmarshalText function, when the target type -// implements the encoding.TextUnmarshaler interface -func TextUnmarshallerHookFunc() DecodeHookFuncType { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { - if f.Kind() != reflect.String { - return data, nil - } - result := reflect.New(t).Interface() - unmarshaller, ok := result.(encoding.TextUnmarshaler) - if !ok { - return data, nil - } - if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { - return nil, err - } - return result, nil - } -} diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/error.go b/event-processor/vendor/github.com/mitchellh/mapstructure/error.go deleted file mode 100644 index 47a99e5a..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/error.go +++ /dev/null @@ -1,50 +0,0 @@ -package mapstructure - -import ( - "errors" - "fmt" - "sort" - "strings" -) - -// Error implements the error interface and can represents multiple -// errors that occur in the course of a single decode. -type Error struct { - Errors []string -} - -func (e *Error) Error() string { - points := make([]string, len(e.Errors)) - for i, err := range e.Errors { - points[i] = fmt.Sprintf("* %s", err) - } - - sort.Strings(points) - return fmt.Sprintf( - "%d error(s) decoding:\n\n%s", - len(e.Errors), strings.Join(points, "\n")) -} - -// WrappedErrors implements the errwrap.Wrapper interface to make this -// return value more useful with the errwrap and go-multierror libraries. -func (e *Error) WrappedErrors() []error { - if e == nil { - return nil - } - - result := make([]error, len(e.Errors)) - for i, e := range e.Errors { - result[i] = errors.New(e) - } - - return result -} - -func appendErrors(errors []string, err error) []string { - switch e := err.(type) { - case *Error: - return append(errors, e.Errors...) - default: - return append(errors, e.Error()) - } -} diff --git a/event-processor/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/event-processor/vendor/github.com/mitchellh/mapstructure/mapstructure.go deleted file mode 100644 index 1efb22ac..00000000 --- a/event-processor/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ /dev/null @@ -1,1540 +0,0 @@ -// Package mapstructure exposes functionality to convert one arbitrary -// Go type into another, typically to convert a map[string]interface{} -// into a native Go structure. -// -// The Go structure can be arbitrarily complex, containing slices, -// other structs, etc. and the decoder will properly decode nested -// maps and so on into the proper structures in the native Go struct. -// See the examples to see what the decoder is capable of. -// -// The simplest function to start with is Decode. -// -// Field Tags -// -// When decoding to a struct, mapstructure will use the field name by -// default to perform the mapping. For example, if a struct has a field -// "Username" then mapstructure will look for a key in the source value -// of "username" (case insensitive). -// -// type User struct { -// Username string -// } -// -// You can change the behavior of mapstructure by using struct tags. -// The default struct tag that mapstructure looks for is "mapstructure" -// but you can customize it using DecoderConfig. -// -// Renaming Fields -// -// To rename the key that mapstructure looks for, use the "mapstructure" -// tag and set a value directly. For example, to change the "username" example -// above to "user": -// -// type User struct { -// Username string `mapstructure:"user"` -// } -// -// Embedded Structs and Squashing -// -// Embedded structs are treated as if they're another field with that name. -// By default, the two structs below are equivalent when decoding with -// mapstructure: -// -// type Person struct { -// Name string -// } -// -// type Friend struct { -// Person -// } -// -// type Friend struct { -// Person Person -// } -// -// This would require an input that looks like below: -// -// map[string]interface{}{ -// "person": map[string]interface{}{"name": "alice"}, -// } -// -// If your "person" value is NOT nested, then you can append ",squash" to -// your tag value and mapstructure will treat it as if the embedded struct -// were part of the struct directly. Example: -// -// type Friend struct { -// Person `mapstructure:",squash"` -// } -// -// Now the following input would be accepted: -// -// map[string]interface{}{ -// "name": "alice", -// } -// -// When decoding from a struct to a map, the squash tag squashes the struct -// fields into a single map. Using the example structs from above: -// -// Friend{Person: Person{Name: "alice"}} -// -// Will be decoded into a map: -// -// map[string]interface{}{ -// "name": "alice", -// } -// -// DecoderConfig has a field that changes the behavior of mapstructure -// to always squash embedded structs. -// -// Remainder Values -// -// If there are any unmapped keys in the source value, mapstructure by -// default will silently ignore them. You can error by setting ErrorUnused -// in DecoderConfig. If you're using Metadata you can also maintain a slice -// of the unused keys. -// -// You can also use the ",remain" suffix on your tag to collect all unused -// values in a map. The field with this tag MUST be a map type and should -// probably be a "map[string]interface{}" or "map[interface{}]interface{}". -// See example below: -// -// type Friend struct { -// Name string -// Other map[string]interface{} `mapstructure:",remain"` -// } -// -// Given the input below, Other would be populated with the other -// values that weren't used (everything but "name"): -// -// map[string]interface{}{ -// "name": "bob", -// "address": "123 Maple St.", -// } -// -// Omit Empty Values -// -// When decoding from a struct to any other value, you may use the -// ",omitempty" suffix on your tag to omit that value if it equates to -// the zero value. The zero value of all types is specified in the Go -// specification. -// -// For example, the zero type of a numeric type is zero ("0"). If the struct -// field value is zero and a numeric type, the field is empty, and it won't -// be encoded into the destination type. -// -// type Source struct { -// Age int `mapstructure:",omitempty"` -// } -// -// Unexported fields -// -// Since unexported (private) struct fields cannot be set outside the package -// where they are defined, the decoder will simply skip them. -// -// For this output type definition: -// -// type Exported struct { -// private string // this unexported field will be skipped -// Public string -// } -// -// Using this map as input: -// -// map[string]interface{}{ -// "private": "I will be ignored", -// "Public": "I made it through!", -// } -// -// The following struct will be decoded: -// -// type Exported struct { -// private: "" // field is left with an empty string (zero value) -// Public: "I made it through!" -// } -// -// Other Configuration -// -// mapstructure is highly configurable. See the DecoderConfig struct -// for other features and options that are supported. -package mapstructure - -import ( - "encoding/json" - "errors" - "fmt" - "reflect" - "sort" - "strconv" - "strings" -) - -// DecodeHookFunc is the callback function that can be used for -// data transformations. See "DecodeHook" in the DecoderConfig -// struct. -// -// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or -// DecodeHookFuncValue. -// Values are a superset of Types (Values can return types), and Types are a -// superset of Kinds (Types can return Kinds) and are generally a richer thing -// to use, but Kinds are simpler if you only need those. -// -// The reason DecodeHookFunc is multi-typed is for backwards compatibility: -// we started with Kinds and then realized Types were the better solution, -// but have a promise to not break backwards compat so we now support -// both. -type DecodeHookFunc interface{} - -// DecodeHookFuncType is a DecodeHookFunc which has complete information about -// the source and target types. -type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) - -// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the -// source and target types. -type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) - -// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target -// values. -type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) - -// DecoderConfig is the configuration that is used to create a new decoder -// and allows customization of various aspects of decoding. -type DecoderConfig struct { - // DecodeHook, if set, will be called before any decoding and any - // type conversion (if WeaklyTypedInput is on). This lets you modify - // the values before they're set down onto the resulting struct. The - // DecodeHook is called for every map and value in the input. This means - // that if a struct has embedded fields with squash tags the decode hook - // is called only once with all of the input data, not once for each - // embedded struct. - // - // If an error is returned, the entire decode will fail with that error. - DecodeHook DecodeHookFunc - - // If ErrorUnused is true, then it is an error for there to exist - // keys in the original map that were unused in the decoding process - // (extra keys). - ErrorUnused bool - - // If ErrorUnset is true, then it is an error for there to exist - // fields in the result that were not set in the decoding process - // (extra fields). This only applies to decoding to a struct. This - // will affect all nested structs as well. - ErrorUnset bool - - // ZeroFields, if set to true, will zero fields before writing them. - // For example, a map will be emptied before decoded values are put in - // it. If this is false, a map will be merged. - ZeroFields bool - - // If WeaklyTypedInput is true, the decoder will make the following - // "weak" conversions: - // - // - bools to string (true = "1", false = "0") - // - numbers to string (base 10) - // - bools to int/uint (true = 1, false = 0) - // - strings to int/uint (base implied by prefix) - // - int to bool (true if value != 0) - // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, - // FALSE, false, False. Anything else is an error) - // - empty array = empty map and vice versa - // - negative numbers to overflowed uint values (base 10) - // - slice of maps to a merged map - // - single values are converted to slices if required. Each - // element is weakly decoded. For example: "4" can become []int{4} - // if the target type is an int slice. - // - WeaklyTypedInput bool - - // Squash will squash embedded structs. A squash tag may also be - // added to an individual struct field using a tag. For example: - // - // type Parent struct { - // Child `mapstructure:",squash"` - // } - Squash bool - - // Metadata is the struct that will contain extra metadata about - // the decoding. If this is nil, then no metadata will be tracked. - Metadata *Metadata - - // Result is a pointer to the struct that will contain the decoded - // value. - Result interface{} - - // The tag name that mapstructure reads for field names. This - // defaults to "mapstructure" - TagName string - - // IgnoreUntaggedFields ignores all struct fields without explicit - // TagName, comparable to `mapstructure:"-"` as default behaviour. - IgnoreUntaggedFields bool - - // MatchName is the function used to match the map key to the struct - // field name or tag. Defaults to `strings.EqualFold`. This can be used - // to implement case-sensitive tag values, support snake casing, etc. - MatchName func(mapKey, fieldName string) bool -} - -// A Decoder takes a raw interface value and turns it into structured -// data, keeping track of rich error information along the way in case -// anything goes wrong. Unlike the basic top-level Decode method, you can -// more finely control how the Decoder behaves using the DecoderConfig -// structure. The top-level Decode method is just a convenience that sets -// up the most basic Decoder. -type Decoder struct { - config *DecoderConfig -} - -// Metadata contains information about decoding a structure that -// is tedious or difficult to get otherwise. -type Metadata struct { - // Keys are the keys of the structure which were successfully decoded - Keys []string - - // Unused is a slice of keys that were found in the raw value but - // weren't decoded since there was no matching field in the result interface - Unused []string - - // Unset is a slice of field names that were found in the result interface - // but weren't set in the decoding process since there was no matching value - // in the input - Unset []string -} - -// Decode takes an input structure and uses reflection to translate it to -// the output structure. output must be a pointer to a map or struct. -func Decode(input interface{}, output interface{}) error { - config := &DecoderConfig{ - Metadata: nil, - Result: output, - } - - decoder, err := NewDecoder(config) - if err != nil { - return err - } - - return decoder.Decode(input) -} - -// WeakDecode is the same as Decode but is shorthand to enable -// WeaklyTypedInput. See DecoderConfig for more info. -func WeakDecode(input, output interface{}) error { - config := &DecoderConfig{ - Metadata: nil, - Result: output, - WeaklyTypedInput: true, - } - - decoder, err := NewDecoder(config) - if err != nil { - return err - } - - return decoder.Decode(input) -} - -// DecodeMetadata is the same as Decode, but is shorthand to -// enable metadata collection. See DecoderConfig for more info. -func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { - config := &DecoderConfig{ - Metadata: metadata, - Result: output, - } - - decoder, err := NewDecoder(config) - if err != nil { - return err - } - - return decoder.Decode(input) -} - -// WeakDecodeMetadata is the same as Decode, but is shorthand to -// enable both WeaklyTypedInput and metadata collection. See -// DecoderConfig for more info. -func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { - config := &DecoderConfig{ - Metadata: metadata, - Result: output, - WeaklyTypedInput: true, - } - - decoder, err := NewDecoder(config) - if err != nil { - return err - } - - return decoder.Decode(input) -} - -// NewDecoder returns a new decoder for the given configuration. Once -// a decoder has been returned, the same configuration must not be used -// again. -func NewDecoder(config *DecoderConfig) (*Decoder, error) { - val := reflect.ValueOf(config.Result) - if val.Kind() != reflect.Ptr { - return nil, errors.New("result must be a pointer") - } - - val = val.Elem() - if !val.CanAddr() { - return nil, errors.New("result must be addressable (a pointer)") - } - - if config.Metadata != nil { - if config.Metadata.Keys == nil { - config.Metadata.Keys = make([]string, 0) - } - - if config.Metadata.Unused == nil { - config.Metadata.Unused = make([]string, 0) - } - - if config.Metadata.Unset == nil { - config.Metadata.Unset = make([]string, 0) - } - } - - if config.TagName == "" { - config.TagName = "mapstructure" - } - - if config.MatchName == nil { - config.MatchName = strings.EqualFold - } - - result := &Decoder{ - config: config, - } - - return result, nil -} - -// Decode decodes the given raw interface to the target pointer specified -// by the configuration. -func (d *Decoder) Decode(input interface{}) error { - return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) -} - -// Decodes an unknown data type into a specific reflection value. -func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { - var inputVal reflect.Value - if input != nil { - inputVal = reflect.ValueOf(input) - - // We need to check here if input is a typed nil. Typed nils won't - // match the "input == nil" below so we check that here. - if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { - input = nil - } - } - - if input == nil { - // If the data is nil, then we don't set anything, unless ZeroFields is set - // to true. - if d.config.ZeroFields { - outVal.Set(reflect.Zero(outVal.Type())) - - if d.config.Metadata != nil && name != "" { - d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) - } - } - return nil - } - - if !inputVal.IsValid() { - // If the input value is invalid, then we just set the value - // to be the zero value. - outVal.Set(reflect.Zero(outVal.Type())) - if d.config.Metadata != nil && name != "" { - d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) - } - return nil - } - - if d.config.DecodeHook != nil { - // We have a DecodeHook, so let's pre-process the input. - var err error - input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) - if err != nil { - return fmt.Errorf("error decoding '%s': %s", name, err) - } - } - - var err error - outputKind := getKind(outVal) - addMetaKey := true - switch outputKind { - case reflect.Bool: - err = d.decodeBool(name, input, outVal) - case reflect.Interface: - err = d.decodeBasic(name, input, outVal) - case reflect.String: - err = d.decodeString(name, input, outVal) - case reflect.Int: - err = d.decodeInt(name, input, outVal) - case reflect.Uint: - err = d.decodeUint(name, input, outVal) - case reflect.Float32: - err = d.decodeFloat(name, input, outVal) - case reflect.Struct: - err = d.decodeStruct(name, input, outVal) - case reflect.Map: - err = d.decodeMap(name, input, outVal) - case reflect.Ptr: - addMetaKey, err = d.decodePtr(name, input, outVal) - case reflect.Slice: - err = d.decodeSlice(name, input, outVal) - case reflect.Array: - err = d.decodeArray(name, input, outVal) - case reflect.Func: - err = d.decodeFunc(name, input, outVal) - default: - // If we reached this point then we weren't able to decode it - return fmt.Errorf("%s: unsupported type: %s", name, outputKind) - } - - // If we reached here, then we successfully decoded SOMETHING, so - // mark the key as used if we're tracking metainput. - if addMetaKey && d.config.Metadata != nil && name != "" { - d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) - } - - return err -} - -// This decodes a basic type (bool, int, string, etc.) and sets the -// value to "data" of that type. -func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { - if val.IsValid() && val.Elem().IsValid() { - elem := val.Elem() - - // If we can't address this element, then its not writable. Instead, - // we make a copy of the value (which is a pointer and therefore - // writable), decode into that, and replace the whole value. - copied := false - if !elem.CanAddr() { - copied = true - - // Make *T - copy := reflect.New(elem.Type()) - - // *T = elem - copy.Elem().Set(elem) - - // Set elem so we decode into it - elem = copy - } - - // Decode. If we have an error then return. We also return right - // away if we're not a copy because that means we decoded directly. - if err := d.decode(name, data, elem); err != nil || !copied { - return err - } - - // If we're a copy, we need to set te final result - val.Set(elem.Elem()) - return nil - } - - dataVal := reflect.ValueOf(data) - - // If the input data is a pointer, and the assigned type is the dereference - // of that exact pointer, then indirect it so that we can assign it. - // Example: *string to string - if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { - dataVal = reflect.Indirect(dataVal) - } - - if !dataVal.IsValid() { - dataVal = reflect.Zero(val.Type()) - } - - dataValType := dataVal.Type() - if !dataValType.AssignableTo(val.Type()) { - return fmt.Errorf( - "'%s' expected type '%s', got '%s'", - name, val.Type(), dataValType) - } - - val.Set(dataVal) - return nil -} - -func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataKind := getKind(dataVal) - - converted := true - switch { - case dataKind == reflect.String: - val.SetString(dataVal.String()) - case dataKind == reflect.Bool && d.config.WeaklyTypedInput: - if dataVal.Bool() { - val.SetString("1") - } else { - val.SetString("0") - } - case dataKind == reflect.Int && d.config.WeaklyTypedInput: - val.SetString(strconv.FormatInt(dataVal.Int(), 10)) - case dataKind == reflect.Uint && d.config.WeaklyTypedInput: - val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) - case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: - val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) - case dataKind == reflect.Slice && d.config.WeaklyTypedInput, - dataKind == reflect.Array && d.config.WeaklyTypedInput: - dataType := dataVal.Type() - elemKind := dataType.Elem().Kind() - switch elemKind { - case reflect.Uint8: - var uints []uint8 - if dataKind == reflect.Array { - uints = make([]uint8, dataVal.Len(), dataVal.Len()) - for i := range uints { - uints[i] = dataVal.Index(i).Interface().(uint8) - } - } else { - uints = dataVal.Interface().([]uint8) - } - val.SetString(string(uints)) - default: - converted = false - } - default: - converted = false - } - - if !converted { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - - return nil -} - -func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataKind := getKind(dataVal) - dataType := dataVal.Type() - - switch { - case dataKind == reflect.Int: - val.SetInt(dataVal.Int()) - case dataKind == reflect.Uint: - val.SetInt(int64(dataVal.Uint())) - case dataKind == reflect.Float32: - val.SetInt(int64(dataVal.Float())) - case dataKind == reflect.Bool && d.config.WeaklyTypedInput: - if dataVal.Bool() { - val.SetInt(1) - } else { - val.SetInt(0) - } - case dataKind == reflect.String && d.config.WeaklyTypedInput: - str := dataVal.String() - if str == "" { - str = "0" - } - - i, err := strconv.ParseInt(str, 0, val.Type().Bits()) - if err == nil { - val.SetInt(i) - } else { - return fmt.Errorf("cannot parse '%s' as int: %s", name, err) - } - case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) - i, err := jn.Int64() - if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) - } - val.SetInt(i) - default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - - return nil -} - -func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataKind := getKind(dataVal) - dataType := dataVal.Type() - - switch { - case dataKind == reflect.Int: - i := dataVal.Int() - if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) - } - val.SetUint(uint64(i)) - case dataKind == reflect.Uint: - val.SetUint(dataVal.Uint()) - case dataKind == reflect.Float32: - f := dataVal.Float() - if f < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %f overflows uint", - name, f) - } - val.SetUint(uint64(f)) - case dataKind == reflect.Bool && d.config.WeaklyTypedInput: - if dataVal.Bool() { - val.SetUint(1) - } else { - val.SetUint(0) - } - case dataKind == reflect.String && d.config.WeaklyTypedInput: - str := dataVal.String() - if str == "" { - str = "0" - } - - i, err := strconv.ParseUint(str, 0, val.Type().Bits()) - if err == nil { - val.SetUint(i) - } else { - return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) - } - case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) - i, err := strconv.ParseUint(string(jn), 0, 64) - if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) - } - val.SetUint(i) - default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - - return nil -} - -func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataKind := getKind(dataVal) - - switch { - case dataKind == reflect.Bool: - val.SetBool(dataVal.Bool()) - case dataKind == reflect.Int && d.config.WeaklyTypedInput: - val.SetBool(dataVal.Int() != 0) - case dataKind == reflect.Uint && d.config.WeaklyTypedInput: - val.SetBool(dataVal.Uint() != 0) - case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: - val.SetBool(dataVal.Float() != 0) - case dataKind == reflect.String && d.config.WeaklyTypedInput: - b, err := strconv.ParseBool(dataVal.String()) - if err == nil { - val.SetBool(b) - } else if dataVal.String() == "" { - val.SetBool(false) - } else { - return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) - } - default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - - return nil -} - -func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataKind := getKind(dataVal) - dataType := dataVal.Type() - - switch { - case dataKind == reflect.Int: - val.SetFloat(float64(dataVal.Int())) - case dataKind == reflect.Uint: - val.SetFloat(float64(dataVal.Uint())) - case dataKind == reflect.Float32: - val.SetFloat(dataVal.Float()) - case dataKind == reflect.Bool && d.config.WeaklyTypedInput: - if dataVal.Bool() { - val.SetFloat(1) - } else { - val.SetFloat(0) - } - case dataKind == reflect.String && d.config.WeaklyTypedInput: - str := dataVal.String() - if str == "" { - str = "0" - } - - f, err := strconv.ParseFloat(str, val.Type().Bits()) - if err == nil { - val.SetFloat(f) - } else { - return fmt.Errorf("cannot parse '%s' as float: %s", name, err) - } - case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) - i, err := jn.Float64() - if err != nil { - return fmt.Errorf( - "error decoding json.Number into %s: %s", name, err) - } - val.SetFloat(i) - default: - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - - return nil -} - -func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { - valType := val.Type() - valKeyType := valType.Key() - valElemType := valType.Elem() - - // By default we overwrite keys in the current map - valMap := val - - // If the map is nil or we're purposely zeroing fields, make a new map - if valMap.IsNil() || d.config.ZeroFields { - // Make a new map to hold our result - mapType := reflect.MapOf(valKeyType, valElemType) - valMap = reflect.MakeMap(mapType) - } - - // Check input type and based on the input type jump to the proper func - dataVal := reflect.Indirect(reflect.ValueOf(data)) - switch dataVal.Kind() { - case reflect.Map: - return d.decodeMapFromMap(name, dataVal, val, valMap) - - case reflect.Struct: - return d.decodeMapFromStruct(name, dataVal, val, valMap) - - case reflect.Array, reflect.Slice: - if d.config.WeaklyTypedInput { - return d.decodeMapFromSlice(name, dataVal, val, valMap) - } - - fallthrough - - default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) - } -} - -func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { - // Special case for BC reasons (covered by tests) - if dataVal.Len() == 0 { - val.Set(valMap) - return nil - } - - for i := 0; i < dataVal.Len(); i++ { - err := d.decode( - name+"["+strconv.Itoa(i)+"]", - dataVal.Index(i).Interface(), val) - if err != nil { - return err - } - } - - return nil -} - -func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { - valType := val.Type() - valKeyType := valType.Key() - valElemType := valType.Elem() - - // Accumulate errors - errors := make([]string, 0) - - // If the input data is empty, then we just match what the input data is. - if dataVal.Len() == 0 { - if dataVal.IsNil() { - if !val.IsNil() { - val.Set(dataVal) - } - } else { - // Set to empty allocated value - val.Set(valMap) - } - - return nil - } - - for _, k := range dataVal.MapKeys() { - fieldName := name + "[" + k.String() + "]" - - // First decode the key into the proper type - currentKey := reflect.Indirect(reflect.New(valKeyType)) - if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { - errors = appendErrors(errors, err) - continue - } - - // Next decode the data into the proper type - v := dataVal.MapIndex(k).Interface() - currentVal := reflect.Indirect(reflect.New(valElemType)) - if err := d.decode(fieldName, v, currentVal); err != nil { - errors = appendErrors(errors, err) - continue - } - - valMap.SetMapIndex(currentKey, currentVal) - } - - // Set the built up map to the value - val.Set(valMap) - - // If we had errors, return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil -} - -func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { - typ := dataVal.Type() - for i := 0; i < typ.NumField(); i++ { - // Get the StructField first since this is a cheap operation. If the - // field is unexported, then ignore it. - f := typ.Field(i) - if f.PkgPath != "" { - continue - } - - // Next get the actual value of this field and verify it is assignable - // to the map value. - v := dataVal.Field(i) - if !v.Type().AssignableTo(valMap.Type().Elem()) { - return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) - } - - tagValue := f.Tag.Get(d.config.TagName) - keyName := f.Name - - if tagValue == "" && d.config.IgnoreUntaggedFields { - continue - } - - // If Squash is set in the config, we squash the field down. - squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous - - v = dereferencePtrToStructIfNeeded(v, d.config.TagName) - - // Determine the name of the key in the map - if index := strings.Index(tagValue, ","); index != -1 { - if tagValue[:index] == "-" { - continue - } - // If "omitempty" is specified in the tag, it ignores empty values. - if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { - continue - } - - // If "squash" is specified in the tag, we squash the field down. - squash = squash || strings.Index(tagValue[index+1:], "squash") != -1 - if squash { - // When squashing, the embedded type can be a pointer to a struct. - if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { - v = v.Elem() - } - - // The final type must be a struct - if v.Kind() != reflect.Struct { - return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) - } - } - if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { - keyName = keyNameTagValue - } - } else if len(tagValue) > 0 { - if tagValue == "-" { - continue - } - keyName = tagValue - } - - switch v.Kind() { - // this is an embedded struct, so handle it differently - case reflect.Struct: - x := reflect.New(v.Type()) - x.Elem().Set(v) - - vType := valMap.Type() - vKeyType := vType.Key() - vElemType := vType.Elem() - mType := reflect.MapOf(vKeyType, vElemType) - vMap := reflect.MakeMap(mType) - - // Creating a pointer to a map so that other methods can completely - // overwrite the map if need be (looking at you decodeMapFromMap). The - // indirection allows the underlying map to be settable (CanSet() == true) - // where as reflect.MakeMap returns an unsettable map. - addrVal := reflect.New(vMap.Type()) - reflect.Indirect(addrVal).Set(vMap) - - err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) - if err != nil { - return err - } - - // the underlying map may have been completely overwritten so pull - // it indirectly out of the enclosing value. - vMap = reflect.Indirect(addrVal) - - if squash { - for _, k := range vMap.MapKeys() { - valMap.SetMapIndex(k, vMap.MapIndex(k)) - } - } else { - valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) - } - - default: - valMap.SetMapIndex(reflect.ValueOf(keyName), v) - } - } - - if val.CanAddr() { - val.Set(valMap) - } - - return nil -} - -func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { - // If the input data is nil, then we want to just set the output - // pointer to be nil as well. - isNil := data == nil - if !isNil { - switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { - case reflect.Chan, - reflect.Func, - reflect.Interface, - reflect.Map, - reflect.Ptr, - reflect.Slice: - isNil = v.IsNil() - } - } - if isNil { - if !val.IsNil() && val.CanSet() { - nilValue := reflect.New(val.Type()).Elem() - val.Set(nilValue) - } - - return true, nil - } - - // Create an element of the concrete (non pointer) type and decode - // into that. Then set the value of the pointer to this type. - valType := val.Type() - valElemType := valType.Elem() - if val.CanSet() { - realVal := val - if realVal.IsNil() || d.config.ZeroFields { - realVal = reflect.New(valElemType) - } - - if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { - return false, err - } - - val.Set(realVal) - } else { - if err := d.decode(name, data, reflect.Indirect(val)); err != nil { - return false, err - } - } - return false, nil -} - -func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { - // Create an element of the concrete (non pointer) type and decode - // into that. Then set the value of the pointer to this type. - dataVal := reflect.Indirect(reflect.ValueOf(data)) - if val.Type() != dataVal.Type() { - return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", - name, val.Type(), dataVal.Type(), data) - } - val.Set(dataVal) - return nil -} - -func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataValKind := dataVal.Kind() - valType := val.Type() - valElemType := valType.Elem() - sliceType := reflect.SliceOf(valElemType) - - // If we have a non array/slice type then we first attempt to convert. - if dataValKind != reflect.Array && dataValKind != reflect.Slice { - if d.config.WeaklyTypedInput { - switch { - // Slice and array we use the normal logic - case dataValKind == reflect.Slice, dataValKind == reflect.Array: - break - - // Empty maps turn into empty slices - case dataValKind == reflect.Map: - if dataVal.Len() == 0 { - val.Set(reflect.MakeSlice(sliceType, 0, 0)) - return nil - } - // Create slice of maps of other sizes - return d.decodeSlice(name, []interface{}{data}, val) - - case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: - return d.decodeSlice(name, []byte(dataVal.String()), val) - - // All other types we try to convert to the slice type - // and "lift" it into it. i.e. a string becomes a string slice. - default: - // Just re-try this function with data as a slice. - return d.decodeSlice(name, []interface{}{data}, val) - } - } - - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) - } - - // If the input value is nil, then don't allocate since empty != nil - if dataValKind != reflect.Array && dataVal.IsNil() { - return nil - } - - valSlice := val - if valSlice.IsNil() || d.config.ZeroFields { - // Make a new slice to hold our result, same size as the original data. - valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) - } - - // Accumulate any errors - errors := make([]string, 0) - - for i := 0; i < dataVal.Len(); i++ { - currentData := dataVal.Index(i).Interface() - for valSlice.Len() <= i { - valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) - } - currentField := valSlice.Index(i) - - fieldName := name + "[" + strconv.Itoa(i) + "]" - if err := d.decode(fieldName, currentData, currentField); err != nil { - errors = appendErrors(errors, err) - } - } - - // Finally, set the value to the slice we built up - val.Set(valSlice) - - // If there were errors, we return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil -} - -func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - dataValKind := dataVal.Kind() - valType := val.Type() - valElemType := valType.Elem() - arrayType := reflect.ArrayOf(valType.Len(), valElemType) - - valArray := val - - if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { - // Check input type - if dataValKind != reflect.Array && dataValKind != reflect.Slice { - if d.config.WeaklyTypedInput { - switch { - // Empty maps turn into empty arrays - case dataValKind == reflect.Map: - if dataVal.Len() == 0 { - val.Set(reflect.Zero(arrayType)) - return nil - } - - // All other types we try to convert to the array type - // and "lift" it into it. i.e. a string becomes a string array. - default: - // Just re-try this function with data as a slice. - return d.decodeArray(name, []interface{}{data}, val) - } - } - - return fmt.Errorf( - "'%s': source data must be an array or slice, got %s", name, dataValKind) - - } - if dataVal.Len() > arrayType.Len() { - return fmt.Errorf( - "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) - - } - - // Make a new array to hold our result, same size as the original data. - valArray = reflect.New(arrayType).Elem() - } - - // Accumulate any errors - errors := make([]string, 0) - - for i := 0; i < dataVal.Len(); i++ { - currentData := dataVal.Index(i).Interface() - currentField := valArray.Index(i) - - fieldName := name + "[" + strconv.Itoa(i) + "]" - if err := d.decode(fieldName, currentData, currentField); err != nil { - errors = appendErrors(errors, err) - } - } - - // Finally, set the value to the array we built up - val.Set(valArray) - - // If there were errors, we return those - if len(errors) > 0 { - return &Error{errors} - } - - return nil -} - -func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { - dataVal := reflect.Indirect(reflect.ValueOf(data)) - - // If the type of the value to write to and the data match directly, - // then we just set it directly instead of recursing into the structure. - if dataVal.Type() == val.Type() { - val.Set(dataVal) - return nil - } - - dataValKind := dataVal.Kind() - switch dataValKind { - case reflect.Map: - return d.decodeStructFromMap(name, dataVal, val) - - case reflect.Struct: - // Not the most efficient way to do this but we can optimize later if - // we want to. To convert from struct to struct we go to map first - // as an intermediary. - - // Make a new map to hold our result - mapType := reflect.TypeOf((map[string]interface{})(nil)) - mval := reflect.MakeMap(mapType) - - // Creating a pointer to a map so that other methods can completely - // overwrite the map if need be (looking at you decodeMapFromMap). The - // indirection allows the underlying map to be settable (CanSet() == true) - // where as reflect.MakeMap returns an unsettable map. - addrVal := reflect.New(mval.Type()) - - reflect.Indirect(addrVal).Set(mval) - if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { - return err - } - - result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) - return result - - default: - return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) - } -} - -func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { - dataValType := dataVal.Type() - if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { - return fmt.Errorf( - "'%s' needs a map with string keys, has '%s' keys", - name, dataValType.Key().Kind()) - } - - dataValKeys := make(map[reflect.Value]struct{}) - dataValKeysUnused := make(map[interface{}]struct{}) - for _, dataValKey := range dataVal.MapKeys() { - dataValKeys[dataValKey] = struct{}{} - dataValKeysUnused[dataValKey.Interface()] = struct{}{} - } - - targetValKeysUnused := make(map[interface{}]struct{}) - errors := make([]string, 0) - - // This slice will keep track of all the structs we'll be decoding. - // There can be more than one struct if there are embedded structs - // that are squashed. - structs := make([]reflect.Value, 1, 5) - structs[0] = val - - // Compile the list of all the fields that we're going to be decoding - // from all the structs. - type field struct { - field reflect.StructField - val reflect.Value - } - - // remainField is set to a valid field set with the "remain" tag if - // we are keeping track of remaining values. - var remainField *field - - fields := []field{} - for len(structs) > 0 { - structVal := structs[0] - structs = structs[1:] - - structType := structVal.Type() - - for i := 0; i < structType.NumField(); i++ { - fieldType := structType.Field(i) - fieldVal := structVal.Field(i) - if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { - // Handle embedded struct pointers as embedded structs. - fieldVal = fieldVal.Elem() - } - - // If "squash" is specified in the tag, we squash the field down. - squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous - remain := false - - // We always parse the tags cause we're looking for other tags too - tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") - for _, tag := range tagParts[1:] { - if tag == "squash" { - squash = true - break - } - - if tag == "remain" { - remain = true - break - } - } - - if squash { - if fieldVal.Kind() != reflect.Struct { - errors = appendErrors(errors, - fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) - } else { - structs = append(structs, fieldVal) - } - continue - } - - // Build our field - if remain { - remainField = &field{fieldType, fieldVal} - } else { - // Normal struct field, store it away - fields = append(fields, field{fieldType, fieldVal}) - } - } - } - - // for fieldType, field := range fields { - for _, f := range fields { - field, fieldValue := f.field, f.val - fieldName := field.Name - - tagValue := field.Tag.Get(d.config.TagName) - tagValue = strings.SplitN(tagValue, ",", 2)[0] - if tagValue != "" { - fieldName = tagValue - } - - rawMapKey := reflect.ValueOf(fieldName) - rawMapVal := dataVal.MapIndex(rawMapKey) - if !rawMapVal.IsValid() { - // Do a slower search by iterating over each key and - // doing case-insensitive search. - for dataValKey := range dataValKeys { - mK, ok := dataValKey.Interface().(string) - if !ok { - // Not a string key - continue - } - - if d.config.MatchName(mK, fieldName) { - rawMapKey = dataValKey - rawMapVal = dataVal.MapIndex(dataValKey) - break - } - } - - if !rawMapVal.IsValid() { - // There was no matching key in the map for the value in - // the struct. Remember it for potential errors and metadata. - targetValKeysUnused[fieldName] = struct{}{} - continue - } - } - - if !fieldValue.IsValid() { - // This should never happen - panic("field is not valid") - } - - // If we can't set the field, then it is unexported or something, - // and we just continue onwards. - if !fieldValue.CanSet() { - continue - } - - // Delete the key we're using from the unused map so we stop tracking - delete(dataValKeysUnused, rawMapKey.Interface()) - - // If the name is empty string, then we're at the root, and we - // don't dot-join the fields. - if name != "" { - fieldName = name + "." + fieldName - } - - if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { - errors = appendErrors(errors, err) - } - } - - // If we have a "remain"-tagged field and we have unused keys then - // we put the unused keys directly into the remain field. - if remainField != nil && len(dataValKeysUnused) > 0 { - // Build a map of only the unused values - remain := map[interface{}]interface{}{} - for key := range dataValKeysUnused { - remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() - } - - // Decode it as-if we were just decoding this map onto our map. - if err := d.decodeMap(name, remain, remainField.val); err != nil { - errors = appendErrors(errors, err) - } - - // Set the map to nil so we have none so that the next check will - // not error (ErrorUnused) - dataValKeysUnused = nil - } - - if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { - keys := make([]string, 0, len(dataValKeysUnused)) - for rawKey := range dataValKeysUnused { - keys = append(keys, rawKey.(string)) - } - sort.Strings(keys) - - err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) - errors = appendErrors(errors, err) - } - - if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { - keys := make([]string, 0, len(targetValKeysUnused)) - for rawKey := range targetValKeysUnused { - keys = append(keys, rawKey.(string)) - } - sort.Strings(keys) - - err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) - errors = appendErrors(errors, err) - } - - if len(errors) > 0 { - return &Error{errors} - } - - // Add the unused keys to the list of unused keys if we're tracking metadata - if d.config.Metadata != nil { - for rawKey := range dataValKeysUnused { - key := rawKey.(string) - if name != "" { - key = name + "." + key - } - - d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) - } - for rawKey := range targetValKeysUnused { - key := rawKey.(string) - if name != "" { - key = name + "." + key - } - - d.config.Metadata.Unset = append(d.config.Metadata.Unset, key) - } - } - - return nil -} - -func isEmptyValue(v reflect.Value) bool { - switch getKind(v) { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - } - return false -} - -func getKind(val reflect.Value) reflect.Kind { - kind := val.Kind() - - switch { - case kind >= reflect.Int && kind <= reflect.Int64: - return reflect.Int - case kind >= reflect.Uint && kind <= reflect.Uint64: - return reflect.Uint - case kind >= reflect.Float32 && kind <= reflect.Float64: - return reflect.Float32 - default: - return kind - } -} - -func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool { - for i := 0; i < typ.NumField(); i++ { - f := typ.Field(i) - if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields - return true - } - if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside - return true - } - } - return false -} - -func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value { - if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { - return v - } - deref := v.Elem() - derefT := deref.Type() - if isStructTypeConvertibleToMap(derefT, true, tagName) { - return deref - } - return v -} diff --git a/event-processor/vendor/github.com/prometheus/procfs/.golangci.yml b/event-processor/vendor/github.com/prometheus/procfs/.golangci.yml index 126df9e6..3c3bf910 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/event-processor/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,22 +1,45 @@ ---- +version: "2" linters: enable: - - errcheck - - godot - - gosimple - - govet - - ineffassign - - misspell - - revive - - staticcheck - - testifylint - - unused - -linter-settings: - godot: - capital: true - exclude: - # Ignore "See: URL" - - 'See:' - misspell: - locale: US + - forbidigo + - godot + - misspell + - revive + - testifylint + settings: + forbidigo: + forbid: + - pattern: ^fmt\.Print.*$ + msg: Do not commit print statements. + godot: + exclude: + # Ignore "See: URL". + - 'See:' + capital: true + misspell: + locale: US + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + settings: + goimports: + local-prefixes: + - github.com/prometheus/procfs + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/event-processor/vendor/github.com/prometheus/procfs/Makefile.common b/event-processor/vendor/github.com/prometheus/procfs/Makefile.common index 16172923..4de21512 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/Makefile.common +++ b/event-processor/vendor/github.com/prometheus/procfs/Makefile.common @@ -61,7 +61,8 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_ SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.59.0 +GOLANGCI_LINT_VERSION ?= v2.1.5 +GOLANGCI_FMT_OPTS ?= # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) @@ -156,9 +157,13 @@ $(GOTEST_DIR): @mkdir -p $@ .PHONY: common-format -common-format: +common-format: $(GOLANGCI_LINT) @echo ">> formatting code" $(GO) fmt $(pkgs) +ifdef GOLANGCI_LINT + @echo ">> formatting code with golangci-lint" + $(GOLANGCI_LINT) fmt $(GOLANGCI_FMT_OPTS) +endif .PHONY: common-vet common-vet: @@ -248,8 +253,8 @@ $(PROMU): cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu rm -r $(PROMU_TMP) -.PHONY: proto -proto: +.PHONY: common-proto +common-proto: @echo ">> generating code from proto files" @./scripts/genproto.sh @@ -275,3 +280,9 @@ $(1)_precheck: exit 1; \ fi endef + +govulncheck: install-govulncheck + govulncheck ./... + +install-govulncheck: + command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/event-processor/vendor/github.com/prometheus/procfs/README.md b/event-processor/vendor/github.com/prometheus/procfs/README.md index 1224816c..0718239c 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/README.md +++ b/event-processor/vendor/github.com/prometheus/procfs/README.md @@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`. The procfs library includes a set of test fixtures which include many example files from the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file which is extracted automatically during testing. To add/update the test fixtures, first -ensure the `fixtures` directory is up to date by removing the existing directory and then -extracting the ttar file using `make fixtures/.unpacked` or just `make test`. +ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then +extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`. ```bash rm -rf testdata/fixtures make test ``` -Next, make the required changes to the extracted files in the `fixtures` directory. When +Next, make the required changes to the extracted files in the `testdata/fixtures` directory. When the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file based on the updated `fixtures` directory. And finally, verify the changes using `git diff testdata/fixtures.ttar`. diff --git a/event-processor/vendor/github.com/prometheus/procfs/arp.go b/event-processor/vendor/github.com/prometheus/procfs/arp.go index cdcc8a7c..2e533441 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/arp.go +++ b/event-processor/vendor/github.com/prometheus/procfs/arp.go @@ -23,9 +23,9 @@ import ( // Learned from include/uapi/linux/if_arp.h. const ( - // completed entry (ha valid). + // Completed entry (ha valid). ATFComplete = 0x02 - // permanent entry. + // Permanent entry. ATFPermanent = 0x04 // Publish entry. ATFPublish = 0x08 diff --git a/event-processor/vendor/github.com/prometheus/procfs/fs.go b/event-processor/vendor/github.com/prometheus/procfs/fs.go index 4980c875..9bdaccc7 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/fs.go +++ b/event-processor/vendor/github.com/prometheus/procfs/fs.go @@ -24,8 +24,14 @@ type FS struct { isReal bool } -// DefaultMountPoint is the common mount point of the proc filesystem. -const DefaultMountPoint = fs.DefaultProcMountPoint +const ( + // DefaultMountPoint is the common mount point of the proc filesystem. + DefaultMountPoint = fs.DefaultProcMountPoint + + // SectorSize represents the size of a sector in bytes. + // It is specific to Linux block I/O operations. + SectorSize = 512 +) // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint. // It will error if the mount point directory can't be read or is a file. diff --git a/event-processor/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/event-processor/vendor/github.com/prometheus/procfs/fs_statfs_notype.go index 134767d6..1b5bdbdf 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/fs_statfs_notype.go +++ b/event-processor/vendor/github.com/prometheus/procfs/fs_statfs_notype.go @@ -17,7 +17,7 @@ package procfs // isRealProc returns true on architectures that don't have a Type argument -// in their Statfs_t struct -func isRealProc(mountPoint string) (bool, error) { +// in their Statfs_t struct. +func isRealProc(_ string) (bool, error) { return true, nil } diff --git a/event-processor/vendor/github.com/prometheus/procfs/fscache.go b/event-processor/vendor/github.com/prometheus/procfs/fscache.go index cf2e3eaa..7db86330 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/fscache.go +++ b/event-processor/vendor/github.com/prometheus/procfs/fscache.go @@ -162,7 +162,7 @@ type Fscacheinfo struct { ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64 // Number of release reqs ignored due to in-progress store ReleaseRequestsIgnoredDueToInProgressStore uint64 - // Number of page stores cancelled due to release req + // Number of page stores canceled due to release req PageStoresCancelledByReleaseRequests uint64 VmscanWaiting uint64 // Number of times async ops added to pending queues @@ -171,11 +171,11 @@ type Fscacheinfo struct { OpsRunning uint64 // Number of times async ops queued for processing OpsEnqueued uint64 - // Number of async ops cancelled + // Number of async ops canceled OpsCancelled uint64 // Number of async ops rejected due to object lookup/create failure OpsRejected uint64 - // Number of async ops initialised + // Number of async ops initialized OpsInitialised uint64 // Number of async ops queued for deferred release OpsDeferred uint64 diff --git a/event-processor/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/event-processor/vendor/github.com/prometheus/procfs/internal/fs/fs.go index 3c18c761..3a43e839 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/internal/fs/fs.go +++ b/event-processor/vendor/github.com/prometheus/procfs/internal/fs/fs.go @@ -28,6 +28,9 @@ const ( // DefaultConfigfsMountPoint is the common mount point of the configfs. DefaultConfigfsMountPoint = "/sys/kernel/config" + + // DefaultSelinuxMountPoint is the common mount point of the selinuxfs. + DefaultSelinuxMountPoint = "/sys/fs/selinux" ) // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an diff --git a/event-processor/vendor/github.com/prometheus/procfs/internal/util/parse.go b/event-processor/vendor/github.com/prometheus/procfs/internal/util/parse.go index 14272dc7..5a7d2df0 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ b/event-processor/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -14,6 +14,7 @@ package util import ( + "errors" "os" "strconv" "strings" @@ -110,3 +111,16 @@ func ParseBool(b string) *bool { } return &truth } + +// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX. +func ReadHexFromFile(path string) (uint64, error) { + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + hexString := strings.TrimSpace(string(data)) + if !strings.HasPrefix(hexString, "0x") { + return 0, errors.New("invalid format: hex string does not start with '0x'") + } + return strconv.ParseUint(hexString[2:], 16, 64) +} diff --git a/event-processor/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/event-processor/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go index 1ab875ce..d5404a6d 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go +++ b/event-processor/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go @@ -20,6 +20,8 @@ package util import ( "bytes" "os" + "strconv" + "strings" "syscall" ) @@ -48,3 +50,21 @@ func SysReadFile(file string) (string, error) { return string(bytes.TrimSpace(b[:n])), nil } + +// SysReadUintFromFile reads a file using SysReadFile and attempts to parse a uint64 from it. +func SysReadUintFromFile(path string) (uint64, error) { + data, err := SysReadFile(path) + if err != nil { + return 0, err + } + return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) +} + +// SysReadIntFromFile reads a file using SysReadFile and attempts to parse a int64 from it. +func SysReadIntFromFile(path string) (int64, error) { + data, err := SysReadFile(path) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) +} diff --git a/event-processor/vendor/github.com/prometheus/procfs/mdstat.go b/event-processor/vendor/github.com/prometheus/procfs/mdstat.go index 67a9d2b4..1fd4381b 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/mdstat.go +++ b/event-processor/vendor/github.com/prometheus/procfs/mdstat.go @@ -123,13 +123,16 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { finish := float64(0) pct := float64(0) recovering := strings.Contains(lines[syncLineIdx], "recovery") + reshaping := strings.Contains(lines[syncLineIdx], "reshape") resyncing := strings.Contains(lines[syncLineIdx], "resync") checking := strings.Contains(lines[syncLineIdx], "check") // Append recovery and resyncing state info. - if recovering || resyncing || checking { + if recovering || resyncing || checking || reshaping { if recovering { state = "recovering" + } else if reshaping { + state = "reshaping" } else if checking { state = "checking" } else { diff --git a/event-processor/vendor/github.com/prometheus/procfs/meminfo.go b/event-processor/vendor/github.com/prometheus/procfs/meminfo.go index 4b2c4050..937e1f96 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/meminfo.go +++ b/event-processor/vendor/github.com/prometheus/procfs/meminfo.go @@ -66,6 +66,10 @@ type Meminfo struct { // Memory which has been evicted from RAM, and is temporarily // on the disk SwapFree *uint64 + // Memory consumed by the zswap backend (compressed size) + Zswap *uint64 + // Amount of anonymous memory stored in zswap (original size) + Zswapped *uint64 // Memory which is waiting to get written back to the disk Dirty *uint64 // Memory which is actively being written back to the disk @@ -85,6 +89,8 @@ type Meminfo struct { // amount of memory dedicated to the lowest level of page // tables. PageTables *uint64 + // secondary page tables. + SecPageTables *uint64 // NFS pages sent to the server, but not yet committed to // stable storage NFSUnstable *uint64 @@ -129,15 +135,18 @@ type Meminfo struct { Percpu *uint64 HardwareCorrupted *uint64 AnonHugePages *uint64 + FileHugePages *uint64 ShmemHugePages *uint64 ShmemPmdMapped *uint64 CmaTotal *uint64 CmaFree *uint64 + Unaccepted *uint64 HugePagesTotal *uint64 HugePagesFree *uint64 HugePagesRsvd *uint64 HugePagesSurp *uint64 Hugepagesize *uint64 + Hugetlb *uint64 DirectMap4k *uint64 DirectMap2M *uint64 DirectMap1G *uint64 @@ -161,6 +170,8 @@ type Meminfo struct { MlockedBytes *uint64 SwapTotalBytes *uint64 SwapFreeBytes *uint64 + ZswapBytes *uint64 + ZswappedBytes *uint64 DirtyBytes *uint64 WritebackBytes *uint64 AnonPagesBytes *uint64 @@ -171,6 +182,7 @@ type Meminfo struct { SUnreclaimBytes *uint64 KernelStackBytes *uint64 PageTablesBytes *uint64 + SecPageTablesBytes *uint64 NFSUnstableBytes *uint64 BounceBytes *uint64 WritebackTmpBytes *uint64 @@ -182,11 +194,14 @@ type Meminfo struct { PercpuBytes *uint64 HardwareCorruptedBytes *uint64 AnonHugePagesBytes *uint64 + FileHugePagesBytes *uint64 ShmemHugePagesBytes *uint64 ShmemPmdMappedBytes *uint64 CmaTotalBytes *uint64 CmaFreeBytes *uint64 + UnacceptedBytes *uint64 HugepagesizeBytes *uint64 + HugetlbBytes *uint64 DirectMap4kBytes *uint64 DirectMap2MBytes *uint64 DirectMap1GBytes *uint64 @@ -287,6 +302,12 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "SwapFree:": m.SwapFree = &val m.SwapFreeBytes = &valBytes + case "Zswap:": + m.Zswap = &val + m.ZswapBytes = &valBytes + case "Zswapped:": + m.Zswapped = &val + m.ZswapBytes = &valBytes case "Dirty:": m.Dirty = &val m.DirtyBytes = &valBytes @@ -317,6 +338,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "PageTables:": m.PageTables = &val m.PageTablesBytes = &valBytes + case "SecPageTables:": + m.SecPageTables = &val + m.SecPageTablesBytes = &valBytes case "NFS_Unstable:": m.NFSUnstable = &val m.NFSUnstableBytes = &valBytes @@ -350,6 +374,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "AnonHugePages:": m.AnonHugePages = &val m.AnonHugePagesBytes = &valBytes + case "FileHugePages:": + m.FileHugePages = &val + m.FileHugePagesBytes = &valBytes case "ShmemHugePages:": m.ShmemHugePages = &val m.ShmemHugePagesBytes = &valBytes @@ -362,6 +389,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "CmaFree:": m.CmaFree = &val m.CmaFreeBytes = &valBytes + case "Unaccepted:": + m.Unaccepted = &val + m.UnacceptedBytes = &valBytes case "HugePages_Total:": m.HugePagesTotal = &val case "HugePages_Free:": @@ -373,6 +403,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "Hugepagesize:": m.Hugepagesize = &val m.HugepagesizeBytes = &valBytes + case "Hugetlb:": + m.Hugetlb = &val + m.HugetlbBytes = &valBytes case "DirectMap4k:": m.DirectMap4k = &val m.DirectMap4kBytes = &valBytes diff --git a/event-processor/vendor/github.com/prometheus/procfs/mountstats.go b/event-processor/vendor/github.com/prometheus/procfs/mountstats.go index 75a3b6c8..50caa732 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/mountstats.go +++ b/event-processor/vendor/github.com/prometheus/procfs/mountstats.go @@ -45,11 +45,11 @@ const ( fieldTransport11TCPLen = 13 fieldTransport11UDPLen = 10 - // kernel version >= 4.14 MaxLen + // Kernel version >= 4.14 MaxLen // See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393 fieldTransport11RDMAMaxLen = 28 - // kernel version <= 4.2 MinLen + // Kernel version <= 4.2 MinLen // See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331 fieldTransport11RDMAMinLen = 20 ) @@ -601,11 +601,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats switch statVersion { case statVersion10: var expectedLength int - if protocol == "tcp" { + switch protocol { + case "tcp": expectedLength = fieldTransport10TCPLen - } else if protocol == "udp" { + case "udp": expectedLength = fieldTransport10UDPLen - } else { + default: return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss) } if len(ss) != expectedLength { @@ -613,13 +614,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats } case statVersion11: var expectedLength int - if protocol == "tcp" { + switch protocol { + case "tcp": expectedLength = fieldTransport11TCPLen - } else if protocol == "udp" { + case "udp": expectedLength = fieldTransport11UDPLen - } else if protocol == "rdma" { + case "rdma": expectedLength = fieldTransport11RDMAMinLen - } else { + default: return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss) } if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) || @@ -655,11 +657,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats // For the udp RPC transport there is no connection count, connect idle time, // or idle time (fields #3, #4, and #5); all other fields are the same. So // we set them to 0 here. - if protocol == "udp" { + switch protocol { + case "udp": ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...) - } else if protocol == "tcp" { + case "tcp": ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...) - } else if protocol == "rdma" { + case "rdma": ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...) } diff --git a/event-processor/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/event-processor/vendor/github.com/prometheus/procfs/net_dev_snmp6.go new file mode 100644 index 00000000..f50b38e3 --- /dev/null +++ b/event-processor/vendor/github.com/prometheus/procfs/net_dev_snmp6.go @@ -0,0 +1,96 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "errors" + "io" + "os" + "strconv" + "strings" +) + +// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc//net/dev_snmp6/. +// The outer map's keys are interface names and the inner map's keys are stat names. +// +// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type. +type NetDevSNMP6 map[string]map[string]uint64 + +// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/ +// directory. +func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) { + return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6")) +} + +// Returns kernel/system statistics read from interface files within the /proc//net/dev_snmp6/ +// directory. +func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) { + return newNetDevSNMP6(p.path("net/dev_snmp6")) +} + +// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory. +func newNetDevSNMP6(dir string) (NetDevSNMP6, error) { + netDevSNMP6 := make(NetDevSNMP6) + + // The net/dev_snmp6 folders contain one file per interface + ifaceFiles, err := os.ReadDir(dir) + if err != nil { + // On systems with IPv6 disabled, this directory won't exist. + // Do nothing. + if errors.Is(err, os.ErrNotExist) { + return netDevSNMP6, err + } + return netDevSNMP6, err + } + + for _, iFaceFile := range ifaceFiles { + f, err := os.Open(dir + "/" + iFaceFile.Name()) + if err != nil { + return netDevSNMP6, err + } + defer f.Close() + + netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f) + if err != nil { + return netDevSNMP6, err + } + } + + return netDevSNMP6, nil +} + +func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) { + m := make(map[string]uint64) + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + stat := strings.Fields(scanner.Text()) + if len(stat) < 2 { + continue + } + key, val := stat[0], stat[1] + + // Expect stat name to contain "6" or be "ifIndex" + if strings.Contains(key, "6") || key == "ifIndex" { + v, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return m, err + } + + m[key] = v + } + } + return m, scanner.Err() +} diff --git a/event-processor/vendor/github.com/prometheus/procfs/net_ip_socket.go b/event-processor/vendor/github.com/prometheus/procfs/net_ip_socket.go index b70f1fc7..19e3378f 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/event-processor/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -25,7 +25,7 @@ import ( ) const ( - // readLimit is used by io.LimitReader while reading the content of the + // Maximum size limit used by io.LimitReader while reading the content of the // /proc/net/udp{,6} files. The number of lines inside such a file is dynamic // as each line represents a single used socket. // In theory, the number of available sockets is 65535 (2^16 - 1) per IP. @@ -50,12 +50,12 @@ type ( // UsedSockets shows the total number of parsed lines representing the // number of used sockets. UsedSockets uint64 - // Drops shows the total number of dropped packets of all UPD sockets. + // Drops shows the total number of dropped packets of all UDP sockets. Drops *uint64 } - // netIPSocketLine represents the fields parsed from a single line - // in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped. + // A single line parser for fields from /proc/net/{t,u}dp{,6}. + // Fields which are not used by IPSocket are skipped. // Drops is non-nil for udp{,6}, but nil for tcp{,6}. // For the proc file format details, see https://linux.die.net/man/5/proc. netIPSocketLine struct { diff --git a/event-processor/vendor/github.com/prometheus/procfs/net_protocols.go b/event-processor/vendor/github.com/prometheus/procfs/net_protocols.go index b6c77b70..8d4b1ac0 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/net_protocols.go +++ b/event-processor/vendor/github.com/prometheus/procfs/net_protocols.go @@ -115,22 +115,24 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro if err != nil { return nil, err } - if fields[4] == enabled { + switch fields[4] { + case enabled: line.Pressure = 1 - } else if fields[4] == disabled { + case disabled: line.Pressure = 0 - } else { + default: line.Pressure = -1 } line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64) if err != nil { return nil, err } - if fields[6] == enabled { + switch fields[6] { + case enabled: line.Slab = true - } else if fields[6] == disabled { + case disabled: line.Slab = false - } else { + default: return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name) } line.ModuleName = fields[7] @@ -168,11 +170,12 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro } for i := 0; i < len(capabilities); i++ { - if capabilities[i] == "y" { + switch capabilities[i] { + case "y": *capabilityFields[i] = true - } else if capabilities[i] == "n" { + case "n": *capabilityFields[i] = false - } else { + default: return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i) } } diff --git a/event-processor/vendor/github.com/prometheus/procfs/net_tcp.go b/event-processor/vendor/github.com/prometheus/procfs/net_tcp.go index 52776295..0396d720 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/net_tcp.go +++ b/event-processor/vendor/github.com/prometheus/procfs/net_tcp.go @@ -25,24 +25,28 @@ type ( // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCP() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp")) } // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp6. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp6")) } // NetTCPSummary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp")) } // NetTCP6Summary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp6. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp6")) } diff --git a/event-processor/vendor/github.com/prometheus/procfs/net_unix.go b/event-processor/vendor/github.com/prometheus/procfs/net_unix.go index d868cebd..d7e0cacb 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/net_unix.go +++ b/event-processor/vendor/github.com/prometheus/procfs/net_unix.go @@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) { return &nu, nil } -func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) { +func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) { fields := strings.Fields(line) l := len(fields) - if l < min { - return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l) + if l < minFields { + return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l) } // Field offsets are as follows: @@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, } // Path field is optional. - if l > min { + if l > minFields { // Path occurs at either index 6 or 7 depending on whether inode is // already present. pathIdx := 7 diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc.go b/event-processor/vendor/github.com/prometheus/procfs/proc.go index 14279636..368187fa 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc.go @@ -37,9 +37,9 @@ type Proc struct { type Procs []Proc var ( - ErrFileParse = errors.New("Error Parsing File") - ErrFileRead = errors.New("Error Reading File") - ErrMountPoint = errors.New("Error Accessing Mount point") + ErrFileParse = errors.New("error parsing file") + ErrFileRead = errors.New("error reading file") + ErrMountPoint = errors.New("error accessing mount point") ) func (p Procs) Len() int { return len(p) } @@ -79,7 +79,7 @@ func (fs FS) Self() (Proc, error) { if err != nil { return Proc{}, err } - pid, err := strconv.Atoi(strings.Replace(p, string(fs.proc), "", -1)) + pid, err := strconv.Atoi(strings.ReplaceAll(p, string(fs.proc), "")) if err != nil { return Proc{}, err } diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_cgroup.go b/event-processor/vendor/github.com/prometheus/procfs/proc_cgroup.go index daeed7f5..4a64347c 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -24,7 +24,7 @@ import ( ) // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a -// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource +// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_io.go b/event-processor/vendor/github.com/prometheus/procfs/proc_io.go index 776f3497..d15b66dd 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_io.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_io.go @@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) { ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + "read_bytes: %d\nwrite_bytes: %d\n" + - "cancelled_write_bytes: %d\n" + "cancelled_write_bytes: %d\n" //nolint:misspell _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_netstat.go b/event-processor/vendor/github.com/prometheus/procfs/proc_netstat.go index 8e3ff4d7..4248c171 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_netstat.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_netstat.go @@ -209,232 +209,232 @@ func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) { case "TcpExt": switch key { case "SyncookiesSent": - procNetstat.TcpExt.SyncookiesSent = &value + procNetstat.SyncookiesSent = &value case "SyncookiesRecv": - procNetstat.TcpExt.SyncookiesRecv = &value + procNetstat.SyncookiesRecv = &value case "SyncookiesFailed": - procNetstat.TcpExt.SyncookiesFailed = &value + procNetstat.SyncookiesFailed = &value case "EmbryonicRsts": - procNetstat.TcpExt.EmbryonicRsts = &value + procNetstat.EmbryonicRsts = &value case "PruneCalled": - procNetstat.TcpExt.PruneCalled = &value + procNetstat.PruneCalled = &value case "RcvPruned": - procNetstat.TcpExt.RcvPruned = &value + procNetstat.RcvPruned = &value case "OfoPruned": - procNetstat.TcpExt.OfoPruned = &value + procNetstat.OfoPruned = &value case "OutOfWindowIcmps": - procNetstat.TcpExt.OutOfWindowIcmps = &value + procNetstat.OutOfWindowIcmps = &value case "LockDroppedIcmps": - procNetstat.TcpExt.LockDroppedIcmps = &value + procNetstat.LockDroppedIcmps = &value case "ArpFilter": - procNetstat.TcpExt.ArpFilter = &value + procNetstat.ArpFilter = &value case "TW": - procNetstat.TcpExt.TW = &value + procNetstat.TW = &value case "TWRecycled": - procNetstat.TcpExt.TWRecycled = &value + procNetstat.TWRecycled = &value case "TWKilled": - procNetstat.TcpExt.TWKilled = &value + procNetstat.TWKilled = &value case "PAWSActive": - procNetstat.TcpExt.PAWSActive = &value + procNetstat.PAWSActive = &value case "PAWSEstab": - procNetstat.TcpExt.PAWSEstab = &value + procNetstat.PAWSEstab = &value case "DelayedACKs": - procNetstat.TcpExt.DelayedACKs = &value + procNetstat.DelayedACKs = &value case "DelayedACKLocked": - procNetstat.TcpExt.DelayedACKLocked = &value + procNetstat.DelayedACKLocked = &value case "DelayedACKLost": - procNetstat.TcpExt.DelayedACKLost = &value + procNetstat.DelayedACKLost = &value case "ListenOverflows": - procNetstat.TcpExt.ListenOverflows = &value + procNetstat.ListenOverflows = &value case "ListenDrops": - procNetstat.TcpExt.ListenDrops = &value + procNetstat.ListenDrops = &value case "TCPHPHits": - procNetstat.TcpExt.TCPHPHits = &value + procNetstat.TCPHPHits = &value case "TCPPureAcks": - procNetstat.TcpExt.TCPPureAcks = &value + procNetstat.TCPPureAcks = &value case "TCPHPAcks": - procNetstat.TcpExt.TCPHPAcks = &value + procNetstat.TCPHPAcks = &value case "TCPRenoRecovery": - procNetstat.TcpExt.TCPRenoRecovery = &value + procNetstat.TCPRenoRecovery = &value case "TCPSackRecovery": - procNetstat.TcpExt.TCPSackRecovery = &value + procNetstat.TCPSackRecovery = &value case "TCPSACKReneging": - procNetstat.TcpExt.TCPSACKReneging = &value + procNetstat.TCPSACKReneging = &value case "TCPSACKReorder": - procNetstat.TcpExt.TCPSACKReorder = &value + procNetstat.TCPSACKReorder = &value case "TCPRenoReorder": - procNetstat.TcpExt.TCPRenoReorder = &value + procNetstat.TCPRenoReorder = &value case "TCPTSReorder": - procNetstat.TcpExt.TCPTSReorder = &value + procNetstat.TCPTSReorder = &value case "TCPFullUndo": - procNetstat.TcpExt.TCPFullUndo = &value + procNetstat.TCPFullUndo = &value case "TCPPartialUndo": - procNetstat.TcpExt.TCPPartialUndo = &value + procNetstat.TCPPartialUndo = &value case "TCPDSACKUndo": - procNetstat.TcpExt.TCPDSACKUndo = &value + procNetstat.TCPDSACKUndo = &value case "TCPLossUndo": - procNetstat.TcpExt.TCPLossUndo = &value + procNetstat.TCPLossUndo = &value case "TCPLostRetransmit": - procNetstat.TcpExt.TCPLostRetransmit = &value + procNetstat.TCPLostRetransmit = &value case "TCPRenoFailures": - procNetstat.TcpExt.TCPRenoFailures = &value + procNetstat.TCPRenoFailures = &value case "TCPSackFailures": - procNetstat.TcpExt.TCPSackFailures = &value + procNetstat.TCPSackFailures = &value case "TCPLossFailures": - procNetstat.TcpExt.TCPLossFailures = &value + procNetstat.TCPLossFailures = &value case "TCPFastRetrans": - procNetstat.TcpExt.TCPFastRetrans = &value + procNetstat.TCPFastRetrans = &value case "TCPSlowStartRetrans": - procNetstat.TcpExt.TCPSlowStartRetrans = &value + procNetstat.TCPSlowStartRetrans = &value case "TCPTimeouts": - procNetstat.TcpExt.TCPTimeouts = &value + procNetstat.TCPTimeouts = &value case "TCPLossProbes": - procNetstat.TcpExt.TCPLossProbes = &value + procNetstat.TCPLossProbes = &value case "TCPLossProbeRecovery": - procNetstat.TcpExt.TCPLossProbeRecovery = &value + procNetstat.TCPLossProbeRecovery = &value case "TCPRenoRecoveryFail": - procNetstat.TcpExt.TCPRenoRecoveryFail = &value + procNetstat.TCPRenoRecoveryFail = &value case "TCPSackRecoveryFail": - procNetstat.TcpExt.TCPSackRecoveryFail = &value + procNetstat.TCPSackRecoveryFail = &value case "TCPRcvCollapsed": - procNetstat.TcpExt.TCPRcvCollapsed = &value + procNetstat.TCPRcvCollapsed = &value case "TCPDSACKOldSent": - procNetstat.TcpExt.TCPDSACKOldSent = &value + procNetstat.TCPDSACKOldSent = &value case "TCPDSACKOfoSent": - procNetstat.TcpExt.TCPDSACKOfoSent = &value + procNetstat.TCPDSACKOfoSent = &value case "TCPDSACKRecv": - procNetstat.TcpExt.TCPDSACKRecv = &value + procNetstat.TCPDSACKRecv = &value case "TCPDSACKOfoRecv": - procNetstat.TcpExt.TCPDSACKOfoRecv = &value + procNetstat.TCPDSACKOfoRecv = &value case "TCPAbortOnData": - procNetstat.TcpExt.TCPAbortOnData = &value + procNetstat.TCPAbortOnData = &value case "TCPAbortOnClose": - procNetstat.TcpExt.TCPAbortOnClose = &value + procNetstat.TCPAbortOnClose = &value case "TCPDeferAcceptDrop": - procNetstat.TcpExt.TCPDeferAcceptDrop = &value + procNetstat.TCPDeferAcceptDrop = &value case "IPReversePathFilter": - procNetstat.TcpExt.IPReversePathFilter = &value + procNetstat.IPReversePathFilter = &value case "TCPTimeWaitOverflow": - procNetstat.TcpExt.TCPTimeWaitOverflow = &value + procNetstat.TCPTimeWaitOverflow = &value case "TCPReqQFullDoCookies": - procNetstat.TcpExt.TCPReqQFullDoCookies = &value + procNetstat.TCPReqQFullDoCookies = &value case "TCPReqQFullDrop": - procNetstat.TcpExt.TCPReqQFullDrop = &value + procNetstat.TCPReqQFullDrop = &value case "TCPRetransFail": - procNetstat.TcpExt.TCPRetransFail = &value + procNetstat.TCPRetransFail = &value case "TCPRcvCoalesce": - procNetstat.TcpExt.TCPRcvCoalesce = &value + procNetstat.TCPRcvCoalesce = &value case "TCPRcvQDrop": - procNetstat.TcpExt.TCPRcvQDrop = &value + procNetstat.TCPRcvQDrop = &value case "TCPOFOQueue": - procNetstat.TcpExt.TCPOFOQueue = &value + procNetstat.TCPOFOQueue = &value case "TCPOFODrop": - procNetstat.TcpExt.TCPOFODrop = &value + procNetstat.TCPOFODrop = &value case "TCPOFOMerge": - procNetstat.TcpExt.TCPOFOMerge = &value + procNetstat.TCPOFOMerge = &value case "TCPChallengeACK": - procNetstat.TcpExt.TCPChallengeACK = &value + procNetstat.TCPChallengeACK = &value case "TCPSYNChallenge": - procNetstat.TcpExt.TCPSYNChallenge = &value + procNetstat.TCPSYNChallenge = &value case "TCPFastOpenActive": - procNetstat.TcpExt.TCPFastOpenActive = &value + procNetstat.TCPFastOpenActive = &value case "TCPFastOpenActiveFail": - procNetstat.TcpExt.TCPFastOpenActiveFail = &value + procNetstat.TCPFastOpenActiveFail = &value case "TCPFastOpenPassive": - procNetstat.TcpExt.TCPFastOpenPassive = &value + procNetstat.TCPFastOpenPassive = &value case "TCPFastOpenPassiveFail": - procNetstat.TcpExt.TCPFastOpenPassiveFail = &value + procNetstat.TCPFastOpenPassiveFail = &value case "TCPFastOpenListenOverflow": - procNetstat.TcpExt.TCPFastOpenListenOverflow = &value + procNetstat.TCPFastOpenListenOverflow = &value case "TCPFastOpenCookieReqd": - procNetstat.TcpExt.TCPFastOpenCookieReqd = &value + procNetstat.TCPFastOpenCookieReqd = &value case "TCPFastOpenBlackhole": - procNetstat.TcpExt.TCPFastOpenBlackhole = &value + procNetstat.TCPFastOpenBlackhole = &value case "TCPSpuriousRtxHostQueues": - procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value + procNetstat.TCPSpuriousRtxHostQueues = &value case "BusyPollRxPackets": - procNetstat.TcpExt.BusyPollRxPackets = &value + procNetstat.BusyPollRxPackets = &value case "TCPAutoCorking": - procNetstat.TcpExt.TCPAutoCorking = &value + procNetstat.TCPAutoCorking = &value case "TCPFromZeroWindowAdv": - procNetstat.TcpExt.TCPFromZeroWindowAdv = &value + procNetstat.TCPFromZeroWindowAdv = &value case "TCPToZeroWindowAdv": - procNetstat.TcpExt.TCPToZeroWindowAdv = &value + procNetstat.TCPToZeroWindowAdv = &value case "TCPWantZeroWindowAdv": - procNetstat.TcpExt.TCPWantZeroWindowAdv = &value + procNetstat.TCPWantZeroWindowAdv = &value case "TCPSynRetrans": - procNetstat.TcpExt.TCPSynRetrans = &value + procNetstat.TCPSynRetrans = &value case "TCPOrigDataSent": - procNetstat.TcpExt.TCPOrigDataSent = &value + procNetstat.TCPOrigDataSent = &value case "TCPHystartTrainDetect": - procNetstat.TcpExt.TCPHystartTrainDetect = &value + procNetstat.TCPHystartTrainDetect = &value case "TCPHystartTrainCwnd": - procNetstat.TcpExt.TCPHystartTrainCwnd = &value + procNetstat.TCPHystartTrainCwnd = &value case "TCPHystartDelayDetect": - procNetstat.TcpExt.TCPHystartDelayDetect = &value + procNetstat.TCPHystartDelayDetect = &value case "TCPHystartDelayCwnd": - procNetstat.TcpExt.TCPHystartDelayCwnd = &value + procNetstat.TCPHystartDelayCwnd = &value case "TCPACKSkippedSynRecv": - procNetstat.TcpExt.TCPACKSkippedSynRecv = &value + procNetstat.TCPACKSkippedSynRecv = &value case "TCPACKSkippedPAWS": - procNetstat.TcpExt.TCPACKSkippedPAWS = &value + procNetstat.TCPACKSkippedPAWS = &value case "TCPACKSkippedSeq": - procNetstat.TcpExt.TCPACKSkippedSeq = &value + procNetstat.TCPACKSkippedSeq = &value case "TCPACKSkippedFinWait2": - procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value + procNetstat.TCPACKSkippedFinWait2 = &value case "TCPACKSkippedTimeWait": - procNetstat.TcpExt.TCPACKSkippedTimeWait = &value + procNetstat.TCPACKSkippedTimeWait = &value case "TCPACKSkippedChallenge": - procNetstat.TcpExt.TCPACKSkippedChallenge = &value + procNetstat.TCPACKSkippedChallenge = &value case "TCPWinProbe": - procNetstat.TcpExt.TCPWinProbe = &value + procNetstat.TCPWinProbe = &value case "TCPKeepAlive": - procNetstat.TcpExt.TCPKeepAlive = &value + procNetstat.TCPKeepAlive = &value case "TCPMTUPFail": - procNetstat.TcpExt.TCPMTUPFail = &value + procNetstat.TCPMTUPFail = &value case "TCPMTUPSuccess": - procNetstat.TcpExt.TCPMTUPSuccess = &value + procNetstat.TCPMTUPSuccess = &value case "TCPWqueueTooBig": - procNetstat.TcpExt.TCPWqueueTooBig = &value + procNetstat.TCPWqueueTooBig = &value } case "IpExt": switch key { case "InNoRoutes": - procNetstat.IpExt.InNoRoutes = &value + procNetstat.InNoRoutes = &value case "InTruncatedPkts": - procNetstat.IpExt.InTruncatedPkts = &value + procNetstat.InTruncatedPkts = &value case "InMcastPkts": - procNetstat.IpExt.InMcastPkts = &value + procNetstat.InMcastPkts = &value case "OutMcastPkts": - procNetstat.IpExt.OutMcastPkts = &value + procNetstat.OutMcastPkts = &value case "InBcastPkts": - procNetstat.IpExt.InBcastPkts = &value + procNetstat.InBcastPkts = &value case "OutBcastPkts": - procNetstat.IpExt.OutBcastPkts = &value + procNetstat.OutBcastPkts = &value case "InOctets": - procNetstat.IpExt.InOctets = &value + procNetstat.InOctets = &value case "OutOctets": - procNetstat.IpExt.OutOctets = &value + procNetstat.OutOctets = &value case "InMcastOctets": - procNetstat.IpExt.InMcastOctets = &value + procNetstat.InMcastOctets = &value case "OutMcastOctets": - procNetstat.IpExt.OutMcastOctets = &value + procNetstat.OutMcastOctets = &value case "InBcastOctets": - procNetstat.IpExt.InBcastOctets = &value + procNetstat.InBcastOctets = &value case "OutBcastOctets": - procNetstat.IpExt.OutBcastOctets = &value + procNetstat.OutBcastOctets = &value case "InCsumErrors": - procNetstat.IpExt.InCsumErrors = &value + procNetstat.InCsumErrors = &value case "InNoECTPkts": - procNetstat.IpExt.InNoECTPkts = &value + procNetstat.InNoECTPkts = &value case "InECT1Pkts": - procNetstat.IpExt.InECT1Pkts = &value + procNetstat.InECT1Pkts = &value case "InECT0Pkts": - procNetstat.IpExt.InECT0Pkts = &value + procNetstat.InECT0Pkts = &value case "InCEPkts": - procNetstat.IpExt.InCEPkts = &value + procNetstat.InCEPkts = &value case "ReasmOverlaps": - procNetstat.IpExt.ReasmOverlaps = &value + procNetstat.ReasmOverlaps = &value } } } diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_smaps.go b/event-processor/vendor/github.com/prometheus/procfs/proc_smaps.go index 09060e82..9a297afc 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -19,7 +19,6 @@ package procfs import ( "bufio" "errors" - "fmt" "os" "regexp" "strconv" @@ -29,7 +28,7 @@ import ( ) var ( - // match the header line before each mapped zone in `/proc/pid/smaps`. + // Match the header line before each mapped zone in `/proc/pid/smaps`. procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) ) @@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) { func (s *ProcSMapsRollup) parseLine(line string) error { kv := strings.SplitN(line, ":", 2) if len(kv) != 2 { - fmt.Println(line) return errors.New("invalid net/dev line, missing colon") } diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_snmp.go b/event-processor/vendor/github.com/prometheus/procfs/proc_snmp.go index b9d2cf64..4bdc90b0 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_snmp.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_snmp.go @@ -173,138 +173,138 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { case "Ip": switch key { case "Forwarding": - procSnmp.Ip.Forwarding = &value + procSnmp.Forwarding = &value case "DefaultTTL": - procSnmp.Ip.DefaultTTL = &value + procSnmp.DefaultTTL = &value case "InReceives": - procSnmp.Ip.InReceives = &value + procSnmp.InReceives = &value case "InHdrErrors": - procSnmp.Ip.InHdrErrors = &value + procSnmp.InHdrErrors = &value case "InAddrErrors": - procSnmp.Ip.InAddrErrors = &value + procSnmp.InAddrErrors = &value case "ForwDatagrams": - procSnmp.Ip.ForwDatagrams = &value + procSnmp.ForwDatagrams = &value case "InUnknownProtos": - procSnmp.Ip.InUnknownProtos = &value + procSnmp.InUnknownProtos = &value case "InDiscards": - procSnmp.Ip.InDiscards = &value + procSnmp.InDiscards = &value case "InDelivers": - procSnmp.Ip.InDelivers = &value + procSnmp.InDelivers = &value case "OutRequests": - procSnmp.Ip.OutRequests = &value + procSnmp.OutRequests = &value case "OutDiscards": - procSnmp.Ip.OutDiscards = &value + procSnmp.OutDiscards = &value case "OutNoRoutes": - procSnmp.Ip.OutNoRoutes = &value + procSnmp.OutNoRoutes = &value case "ReasmTimeout": - procSnmp.Ip.ReasmTimeout = &value + procSnmp.ReasmTimeout = &value case "ReasmReqds": - procSnmp.Ip.ReasmReqds = &value + procSnmp.ReasmReqds = &value case "ReasmOKs": - procSnmp.Ip.ReasmOKs = &value + procSnmp.ReasmOKs = &value case "ReasmFails": - procSnmp.Ip.ReasmFails = &value + procSnmp.ReasmFails = &value case "FragOKs": - procSnmp.Ip.FragOKs = &value + procSnmp.FragOKs = &value case "FragFails": - procSnmp.Ip.FragFails = &value + procSnmp.FragFails = &value case "FragCreates": - procSnmp.Ip.FragCreates = &value + procSnmp.FragCreates = &value } case "Icmp": switch key { case "InMsgs": - procSnmp.Icmp.InMsgs = &value + procSnmp.InMsgs = &value case "InErrors": procSnmp.Icmp.InErrors = &value case "InCsumErrors": procSnmp.Icmp.InCsumErrors = &value case "InDestUnreachs": - procSnmp.Icmp.InDestUnreachs = &value + procSnmp.InDestUnreachs = &value case "InTimeExcds": - procSnmp.Icmp.InTimeExcds = &value + procSnmp.InTimeExcds = &value case "InParmProbs": - procSnmp.Icmp.InParmProbs = &value + procSnmp.InParmProbs = &value case "InSrcQuenchs": - procSnmp.Icmp.InSrcQuenchs = &value + procSnmp.InSrcQuenchs = &value case "InRedirects": - procSnmp.Icmp.InRedirects = &value + procSnmp.InRedirects = &value case "InEchos": - procSnmp.Icmp.InEchos = &value + procSnmp.InEchos = &value case "InEchoReps": - procSnmp.Icmp.InEchoReps = &value + procSnmp.InEchoReps = &value case "InTimestamps": - procSnmp.Icmp.InTimestamps = &value + procSnmp.InTimestamps = &value case "InTimestampReps": - procSnmp.Icmp.InTimestampReps = &value + procSnmp.InTimestampReps = &value case "InAddrMasks": - procSnmp.Icmp.InAddrMasks = &value + procSnmp.InAddrMasks = &value case "InAddrMaskReps": - procSnmp.Icmp.InAddrMaskReps = &value + procSnmp.InAddrMaskReps = &value case "OutMsgs": - procSnmp.Icmp.OutMsgs = &value + procSnmp.OutMsgs = &value case "OutErrors": - procSnmp.Icmp.OutErrors = &value + procSnmp.OutErrors = &value case "OutDestUnreachs": - procSnmp.Icmp.OutDestUnreachs = &value + procSnmp.OutDestUnreachs = &value case "OutTimeExcds": - procSnmp.Icmp.OutTimeExcds = &value + procSnmp.OutTimeExcds = &value case "OutParmProbs": - procSnmp.Icmp.OutParmProbs = &value + procSnmp.OutParmProbs = &value case "OutSrcQuenchs": - procSnmp.Icmp.OutSrcQuenchs = &value + procSnmp.OutSrcQuenchs = &value case "OutRedirects": - procSnmp.Icmp.OutRedirects = &value + procSnmp.OutRedirects = &value case "OutEchos": - procSnmp.Icmp.OutEchos = &value + procSnmp.OutEchos = &value case "OutEchoReps": - procSnmp.Icmp.OutEchoReps = &value + procSnmp.OutEchoReps = &value case "OutTimestamps": - procSnmp.Icmp.OutTimestamps = &value + procSnmp.OutTimestamps = &value case "OutTimestampReps": - procSnmp.Icmp.OutTimestampReps = &value + procSnmp.OutTimestampReps = &value case "OutAddrMasks": - procSnmp.Icmp.OutAddrMasks = &value + procSnmp.OutAddrMasks = &value case "OutAddrMaskReps": - procSnmp.Icmp.OutAddrMaskReps = &value + procSnmp.OutAddrMaskReps = &value } case "IcmpMsg": switch key { case "InType3": - procSnmp.IcmpMsg.InType3 = &value + procSnmp.InType3 = &value case "OutType3": - procSnmp.IcmpMsg.OutType3 = &value + procSnmp.OutType3 = &value } case "Tcp": switch key { case "RtoAlgorithm": - procSnmp.Tcp.RtoAlgorithm = &value + procSnmp.RtoAlgorithm = &value case "RtoMin": - procSnmp.Tcp.RtoMin = &value + procSnmp.RtoMin = &value case "RtoMax": - procSnmp.Tcp.RtoMax = &value + procSnmp.RtoMax = &value case "MaxConn": - procSnmp.Tcp.MaxConn = &value + procSnmp.MaxConn = &value case "ActiveOpens": - procSnmp.Tcp.ActiveOpens = &value + procSnmp.ActiveOpens = &value case "PassiveOpens": - procSnmp.Tcp.PassiveOpens = &value + procSnmp.PassiveOpens = &value case "AttemptFails": - procSnmp.Tcp.AttemptFails = &value + procSnmp.AttemptFails = &value case "EstabResets": - procSnmp.Tcp.EstabResets = &value + procSnmp.EstabResets = &value case "CurrEstab": - procSnmp.Tcp.CurrEstab = &value + procSnmp.CurrEstab = &value case "InSegs": - procSnmp.Tcp.InSegs = &value + procSnmp.InSegs = &value case "OutSegs": - procSnmp.Tcp.OutSegs = &value + procSnmp.OutSegs = &value case "RetransSegs": - procSnmp.Tcp.RetransSegs = &value + procSnmp.RetransSegs = &value case "InErrs": - procSnmp.Tcp.InErrs = &value + procSnmp.InErrs = &value case "OutRsts": - procSnmp.Tcp.OutRsts = &value + procSnmp.OutRsts = &value case "InCsumErrors": procSnmp.Tcp.InCsumErrors = &value } diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_snmp6.go b/event-processor/vendor/github.com/prometheus/procfs/proc_snmp6.go index 3059cc6a..fb7fd399 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_snmp6.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_snmp6.go @@ -182,161 +182,161 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { case "Ip6": switch key { case "InReceives": - procSnmp6.Ip6.InReceives = &value + procSnmp6.InReceives = &value case "InHdrErrors": - procSnmp6.Ip6.InHdrErrors = &value + procSnmp6.InHdrErrors = &value case "InTooBigErrors": - procSnmp6.Ip6.InTooBigErrors = &value + procSnmp6.InTooBigErrors = &value case "InNoRoutes": - procSnmp6.Ip6.InNoRoutes = &value + procSnmp6.InNoRoutes = &value case "InAddrErrors": - procSnmp6.Ip6.InAddrErrors = &value + procSnmp6.InAddrErrors = &value case "InUnknownProtos": - procSnmp6.Ip6.InUnknownProtos = &value + procSnmp6.InUnknownProtos = &value case "InTruncatedPkts": - procSnmp6.Ip6.InTruncatedPkts = &value + procSnmp6.InTruncatedPkts = &value case "InDiscards": - procSnmp6.Ip6.InDiscards = &value + procSnmp6.InDiscards = &value case "InDelivers": - procSnmp6.Ip6.InDelivers = &value + procSnmp6.InDelivers = &value case "OutForwDatagrams": - procSnmp6.Ip6.OutForwDatagrams = &value + procSnmp6.OutForwDatagrams = &value case "OutRequests": - procSnmp6.Ip6.OutRequests = &value + procSnmp6.OutRequests = &value case "OutDiscards": - procSnmp6.Ip6.OutDiscards = &value + procSnmp6.OutDiscards = &value case "OutNoRoutes": - procSnmp6.Ip6.OutNoRoutes = &value + procSnmp6.OutNoRoutes = &value case "ReasmTimeout": - procSnmp6.Ip6.ReasmTimeout = &value + procSnmp6.ReasmTimeout = &value case "ReasmReqds": - procSnmp6.Ip6.ReasmReqds = &value + procSnmp6.ReasmReqds = &value case "ReasmOKs": - procSnmp6.Ip6.ReasmOKs = &value + procSnmp6.ReasmOKs = &value case "ReasmFails": - procSnmp6.Ip6.ReasmFails = &value + procSnmp6.ReasmFails = &value case "FragOKs": - procSnmp6.Ip6.FragOKs = &value + procSnmp6.FragOKs = &value case "FragFails": - procSnmp6.Ip6.FragFails = &value + procSnmp6.FragFails = &value case "FragCreates": - procSnmp6.Ip6.FragCreates = &value + procSnmp6.FragCreates = &value case "InMcastPkts": - procSnmp6.Ip6.InMcastPkts = &value + procSnmp6.InMcastPkts = &value case "OutMcastPkts": - procSnmp6.Ip6.OutMcastPkts = &value + procSnmp6.OutMcastPkts = &value case "InOctets": - procSnmp6.Ip6.InOctets = &value + procSnmp6.InOctets = &value case "OutOctets": - procSnmp6.Ip6.OutOctets = &value + procSnmp6.OutOctets = &value case "InMcastOctets": - procSnmp6.Ip6.InMcastOctets = &value + procSnmp6.InMcastOctets = &value case "OutMcastOctets": - procSnmp6.Ip6.OutMcastOctets = &value + procSnmp6.OutMcastOctets = &value case "InBcastOctets": - procSnmp6.Ip6.InBcastOctets = &value + procSnmp6.InBcastOctets = &value case "OutBcastOctets": - procSnmp6.Ip6.OutBcastOctets = &value + procSnmp6.OutBcastOctets = &value case "InNoECTPkts": - procSnmp6.Ip6.InNoECTPkts = &value + procSnmp6.InNoECTPkts = &value case "InECT1Pkts": - procSnmp6.Ip6.InECT1Pkts = &value + procSnmp6.InECT1Pkts = &value case "InECT0Pkts": - procSnmp6.Ip6.InECT0Pkts = &value + procSnmp6.InECT0Pkts = &value case "InCEPkts": - procSnmp6.Ip6.InCEPkts = &value + procSnmp6.InCEPkts = &value } case "Icmp6": switch key { case "InMsgs": - procSnmp6.Icmp6.InMsgs = &value + procSnmp6.InMsgs = &value case "InErrors": procSnmp6.Icmp6.InErrors = &value case "OutMsgs": - procSnmp6.Icmp6.OutMsgs = &value + procSnmp6.OutMsgs = &value case "OutErrors": - procSnmp6.Icmp6.OutErrors = &value + procSnmp6.OutErrors = &value case "InCsumErrors": procSnmp6.Icmp6.InCsumErrors = &value case "InDestUnreachs": - procSnmp6.Icmp6.InDestUnreachs = &value + procSnmp6.InDestUnreachs = &value case "InPktTooBigs": - procSnmp6.Icmp6.InPktTooBigs = &value + procSnmp6.InPktTooBigs = &value case "InTimeExcds": - procSnmp6.Icmp6.InTimeExcds = &value + procSnmp6.InTimeExcds = &value case "InParmProblems": - procSnmp6.Icmp6.InParmProblems = &value + procSnmp6.InParmProblems = &value case "InEchos": - procSnmp6.Icmp6.InEchos = &value + procSnmp6.InEchos = &value case "InEchoReplies": - procSnmp6.Icmp6.InEchoReplies = &value + procSnmp6.InEchoReplies = &value case "InGroupMembQueries": - procSnmp6.Icmp6.InGroupMembQueries = &value + procSnmp6.InGroupMembQueries = &value case "InGroupMembResponses": - procSnmp6.Icmp6.InGroupMembResponses = &value + procSnmp6.InGroupMembResponses = &value case "InGroupMembReductions": - procSnmp6.Icmp6.InGroupMembReductions = &value + procSnmp6.InGroupMembReductions = &value case "InRouterSolicits": - procSnmp6.Icmp6.InRouterSolicits = &value + procSnmp6.InRouterSolicits = &value case "InRouterAdvertisements": - procSnmp6.Icmp6.InRouterAdvertisements = &value + procSnmp6.InRouterAdvertisements = &value case "InNeighborSolicits": - procSnmp6.Icmp6.InNeighborSolicits = &value + procSnmp6.InNeighborSolicits = &value case "InNeighborAdvertisements": - procSnmp6.Icmp6.InNeighborAdvertisements = &value + procSnmp6.InNeighborAdvertisements = &value case "InRedirects": - procSnmp6.Icmp6.InRedirects = &value + procSnmp6.InRedirects = &value case "InMLDv2Reports": - procSnmp6.Icmp6.InMLDv2Reports = &value + procSnmp6.InMLDv2Reports = &value case "OutDestUnreachs": - procSnmp6.Icmp6.OutDestUnreachs = &value + procSnmp6.OutDestUnreachs = &value case "OutPktTooBigs": - procSnmp6.Icmp6.OutPktTooBigs = &value + procSnmp6.OutPktTooBigs = &value case "OutTimeExcds": - procSnmp6.Icmp6.OutTimeExcds = &value + procSnmp6.OutTimeExcds = &value case "OutParmProblems": - procSnmp6.Icmp6.OutParmProblems = &value + procSnmp6.OutParmProblems = &value case "OutEchos": - procSnmp6.Icmp6.OutEchos = &value + procSnmp6.OutEchos = &value case "OutEchoReplies": - procSnmp6.Icmp6.OutEchoReplies = &value + procSnmp6.OutEchoReplies = &value case "OutGroupMembQueries": - procSnmp6.Icmp6.OutGroupMembQueries = &value + procSnmp6.OutGroupMembQueries = &value case "OutGroupMembResponses": - procSnmp6.Icmp6.OutGroupMembResponses = &value + procSnmp6.OutGroupMembResponses = &value case "OutGroupMembReductions": - procSnmp6.Icmp6.OutGroupMembReductions = &value + procSnmp6.OutGroupMembReductions = &value case "OutRouterSolicits": - procSnmp6.Icmp6.OutRouterSolicits = &value + procSnmp6.OutRouterSolicits = &value case "OutRouterAdvertisements": - procSnmp6.Icmp6.OutRouterAdvertisements = &value + procSnmp6.OutRouterAdvertisements = &value case "OutNeighborSolicits": - procSnmp6.Icmp6.OutNeighborSolicits = &value + procSnmp6.OutNeighborSolicits = &value case "OutNeighborAdvertisements": - procSnmp6.Icmp6.OutNeighborAdvertisements = &value + procSnmp6.OutNeighborAdvertisements = &value case "OutRedirects": - procSnmp6.Icmp6.OutRedirects = &value + procSnmp6.OutRedirects = &value case "OutMLDv2Reports": - procSnmp6.Icmp6.OutMLDv2Reports = &value + procSnmp6.OutMLDv2Reports = &value case "InType1": - procSnmp6.Icmp6.InType1 = &value + procSnmp6.InType1 = &value case "InType134": - procSnmp6.Icmp6.InType134 = &value + procSnmp6.InType134 = &value case "InType135": - procSnmp6.Icmp6.InType135 = &value + procSnmp6.InType135 = &value case "InType136": - procSnmp6.Icmp6.InType136 = &value + procSnmp6.InType136 = &value case "InType143": - procSnmp6.Icmp6.InType143 = &value + procSnmp6.InType143 = &value case "OutType133": - procSnmp6.Icmp6.OutType133 = &value + procSnmp6.OutType133 = &value case "OutType135": - procSnmp6.Icmp6.OutType135 = &value + procSnmp6.OutType135 = &value case "OutType136": - procSnmp6.Icmp6.OutType136 = &value + procSnmp6.OutType136 = &value case "OutType143": - procSnmp6.Icmp6.OutType143 = &value + procSnmp6.OutType143 = &value } case "Udp6": switch key { @@ -355,7 +355,7 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { case "InCsumErrors": procSnmp6.Udp6.InCsumErrors = &value case "IgnoredMulti": - procSnmp6.Udp6.IgnoredMulti = &value + procSnmp6.IgnoredMulti = &value } case "UdpLite6": switch key { diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_stat.go b/event-processor/vendor/github.com/prometheus/procfs/proc_stat.go index 06a8d931..3328556b 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_stat.go @@ -101,6 +101,12 @@ type ProcStat struct { RSS int // Soft limit in bytes on the rss of the process. RSSLimit uint64 + // The address above which program text can run. + StartCode uint64 + // The address below which program text can run. + EndCode uint64 + // The address of the start (i.e., bottom) of the stack. + StartStack uint64 // CPU number last executed on. Processor uint // Real-time scheduling priority, a number in the range 1 to 99 for processes @@ -177,9 +183,9 @@ func (p Proc) Stat() (ProcStat, error) { &s.VSize, &s.RSS, &s.RSSLimit, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, + &s.StartCode, + &s.EndCode, + &s.StartStack, &ignoreUint64, &ignoreUint64, &ignoreUint64, diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_statm.go b/event-processor/vendor/github.com/prometheus/procfs/proc_statm.go new file mode 100644 index 00000000..ed579842 --- /dev/null +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_statm.go @@ -0,0 +1,116 @@ +// Copyright 2025 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "os" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// - https://man7.org/linux/man-pages/man5/proc_pid_statm.5.html + +// ProcStatm Provides memory usage information for a process, measured in memory pages. +// Read from /proc/[pid]/statm. +type ProcStatm struct { + // The process ID. + PID int + // total program size (same as VmSize in status) + Size uint64 + // resident set size (same as VmRSS in status) + Resident uint64 + // number of resident shared pages (i.e., backed by a file) + Shared uint64 + // text (code) + Text uint64 + // library (unused since Linux 2.6; always 0) + Lib uint64 + // data + stack + Data uint64 + // dirty pages (unused since Linux 2.6; always 0) + Dt uint64 +} + +// NewStatm returns the current status information of the process. +// Deprecated: Use p.Statm() instead. +func (p Proc) NewStatm() (ProcStatm, error) { + return p.Statm() +} + +// Statm returns the current memory usage information of the process. +func (p Proc) Statm() (ProcStatm, error) { + data, err := util.ReadFileNoStat(p.path("statm")) + if err != nil { + return ProcStatm{}, err + } + + statmSlice, err := parseStatm(data) + if err != nil { + return ProcStatm{}, err + } + + procStatm := ProcStatm{ + PID: p.PID, + Size: statmSlice[0], + Resident: statmSlice[1], + Shared: statmSlice[2], + Text: statmSlice[3], + Lib: statmSlice[4], + Data: statmSlice[5], + Dt: statmSlice[6], + } + + return procStatm, nil +} + +// parseStatm return /proc/[pid]/statm data to uint64 slice. +func parseStatm(data []byte) ([]uint64, error) { + var statmSlice []uint64 + statmItems := strings.Fields(string(data)) + for i := 0; i < len(statmItems); i++ { + statmItem, err := strconv.ParseUint(statmItems[i], 10, 64) + if err != nil { + return nil, err + } + statmSlice = append(statmSlice, statmItem) + } + return statmSlice, nil +} + +// SizeBytes returns the process of total program size in bytes. +func (s ProcStatm) SizeBytes() uint64 { + return s.Size * uint64(os.Getpagesize()) +} + +// ResidentBytes returns the process of resident set size in bytes. +func (s ProcStatm) ResidentBytes() uint64 { + return s.Resident * uint64(os.Getpagesize()) +} + +// SHRBytes returns the process of share memory size in bytes. +func (s ProcStatm) SHRBytes() uint64 { + return s.Shared * uint64(os.Getpagesize()) +} + +// TextBytes returns the process of text (code) size in bytes. +func (s ProcStatm) TextBytes() uint64 { + return s.Text * uint64(os.Getpagesize()) +} + +// DataBytes returns the process of data + stack size in bytes. +func (s ProcStatm) DataBytes() uint64 { + return s.Data * uint64(os.Getpagesize()) +} diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_status.go b/event-processor/vendor/github.com/prometheus/procfs/proc_status.go index a055197c..dd8aa568 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_status.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_status.go @@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt } } case "NSpid": - s.NSpids = calcNSPidsList(vString) + nspids, err := calcNSPidsList(vString) + if err != nil { + return err + } + s.NSpids = nspids case "VmPeak": s.VmPeak = vUintBytes case "VmSize": @@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 { return g } -func calcNSPidsList(nspidsString string) []uint64 { - s := strings.Split(nspidsString, " ") +func calcNSPidsList(nspidsString string) ([]uint64, error) { + s := strings.Split(nspidsString, "\t") var nspids []uint64 for _, nspid := range s { - nspid, _ := strconv.ParseUint(nspid, 10, 64) - if nspid == 0 { - continue + nspid, err := strconv.ParseUint(nspid, 10, 64) + if err != nil { + return nil, err } nspids = append(nspids, nspid) } - return nspids + return nspids, nil } diff --git a/event-processor/vendor/github.com/prometheus/procfs/proc_sys.go b/event-processor/vendor/github.com/prometheus/procfs/proc_sys.go index 5eefbe2e..3810d1ac 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/proc_sys.go +++ b/event-processor/vendor/github.com/prometheus/procfs/proc_sys.go @@ -21,7 +21,7 @@ import ( ) func sysctlToPath(sysctl string) string { - return strings.Replace(sysctl, ".", "/", -1) + return strings.ReplaceAll(sysctl, ".", "/") } func (fs FS) SysctlStrings(sysctl string) ([]string, error) { diff --git a/event-processor/vendor/github.com/prometheus/procfs/softirqs.go b/event-processor/vendor/github.com/prometheus/procfs/softirqs.go index 28708e07..403e6ae7 100644 --- a/event-processor/vendor/github.com/prometheus/procfs/softirqs.go +++ b/event-processor/vendor/github.com/prometheus/procfs/softirqs.go @@ -68,8 +68,8 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { if len(parts) < 2 { continue } - switch { - case parts[0] == "HI:": + switch parts[0] { + case "HI:": perCPU := parts[1:] softirqs.Hi = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -77,7 +77,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "TIMER:": + case "TIMER:": perCPU := parts[1:] softirqs.Timer = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -85,7 +85,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "NET_TX:": + case "NET_TX:": perCPU := parts[1:] softirqs.NetTx = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -93,7 +93,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "NET_RX:": + case "NET_RX:": perCPU := parts[1:] softirqs.NetRx = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -101,7 +101,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "BLOCK:": + case "BLOCK:": perCPU := parts[1:] softirqs.Block = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -109,7 +109,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "IRQ_POLL:": + case "IRQ_POLL:": perCPU := parts[1:] softirqs.IRQPoll = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -117,7 +117,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "TASKLET:": + case "TASKLET:": perCPU := parts[1:] softirqs.Tasklet = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -125,7 +125,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "SCHED:": + case "SCHED:": perCPU := parts[1:] softirqs.Sched = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -133,7 +133,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "HRTIMER:": + case "HRTIMER:": perCPU := parts[1:] softirqs.HRTimer = make([]uint64, len(perCPU)) for i, count := range perCPU { @@ -141,7 +141,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err) } } - case parts[0] == "RCU:": + case "RCU:": perCPU := parts[1:] softirqs.RCU = make([]uint64, len(perCPU)) for i, count := range perCPU { diff --git a/event-processor/vendor/github.com/rs/cors/cors.go b/event-processor/vendor/github.com/rs/cors/cors.go index da80d343..724f242a 100644 --- a/event-processor/vendor/github.com/rs/cors/cors.go +++ b/event-processor/vendor/github.com/rs/cors/cors.go @@ -364,9 +364,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { // Note: the Fetch standard guarantees that at most one // Access-Control-Request-Headers header is present in the preflight request; // see step 5.2 in https://fetch.spec.whatwg.org/#cors-preflight-fetch-0. - reqHeaders, found := first(r.Header, "Access-Control-Request-Headers") - if found && !c.allowedHeadersAll && !c.allowedHeaders.Subsumes(reqHeaders[0]) { - c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders[0]) + // However, some gateways split that header into multiple headers of the same name; + // see https://github.com/rs/cors/issues/184. + reqHeaders, found := r.Header["Access-Control-Request-Headers"] + if found && !c.allowedHeadersAll && !c.allowedHeaders.Accepts(reqHeaders) { + c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) return } if c.allowedOriginsAll { @@ -391,9 +393,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { if len(c.maxAge) > 0 { headers["Access-Control-Max-Age"] = c.maxAge } - if c.Log != nil { - c.logf(" Preflight response headers: %v", headers) - } + c.logf(" Preflight response headers: %v", headers) } // handleActualRequest handles simple cross-origin requests, actual request or redirects @@ -440,9 +440,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { if c.allowCredentials { headers["Access-Control-Allow-Credentials"] = headerTrue } - if c.Log != nil { - c.logf(" Actual response added headers: %v", headers) - } + c.logf(" Actual response added headers: %v", headers) } // convenience method. checks if a logger is set. diff --git a/event-processor/vendor/github.com/rs/cors/internal/sortedset.go b/event-processor/vendor/github.com/rs/cors/internal/sortedset.go index 513da20f..844f3f9e 100644 --- a/event-processor/vendor/github.com/rs/cors/internal/sortedset.go +++ b/event-processor/vendor/github.com/rs/cors/internal/sortedset.go @@ -52,46 +52,134 @@ func (set SortedSet) String() string { return strings.Join(elems, ",") } -// Subsumes reports whether csv is a sequence of comma-separated names that are -// - all elements of set, -// - sorted in lexicographically order, +// Accepts reports whether values is a sequence of list-based field values +// whose elements are +// - all members of set, +// - sorted in lexicographical order, // - unique. -func (set SortedSet) Subsumes(csv string) bool { - if csv == "" { - return true +func (set SortedSet) Accepts(values []string) bool { + var ( // effectively constant + maxLen = maxOWSBytes + set.maxLen + maxOWSBytes + 1 // +1 for comma + ) + var ( + posOfLastNameSeen = -1 + name string + commaFound bool + emptyElements int + ok bool + ) + for _, s := range values { + for { + // As a defense against maliciously long names in s, + // we process only a small number of s's leading bytes per iteration. + name, s, commaFound = cutAtComma(s, maxLen) + name, ok = trimOWS(name, maxOWSBytes) + if !ok { + return false + } + if name == "" { + // RFC 9110 requires recipients to tolerate + // "a reasonable number of empty list elements"; see + // https://httpwg.org/specs/rfc9110.html#abnf.extension.recipient. + emptyElements++ + if emptyElements > maxEmptyElements { + return false + } + if !commaFound { // We have now exhausted the names in s. + break + } + continue + } + pos, ok := set.m[name] + if !ok { + return false + } + // The names in s are expected to be sorted in lexicographical order + // and to each appear at most once. + // Therefore, the positions (in set) of the names that + // appear in s should form a strictly increasing sequence. + // If that's not actually the case, bail out. + if pos <= posOfLastNameSeen { + return false + } + posOfLastNameSeen = pos + if !commaFound { // We have now exhausted the names in s. + break + } + } + } + return true +} + +const ( + maxOWSBytes = 1 // number of leading/trailing OWS bytes tolerated + maxEmptyElements = 16 // number of empty list elements tolerated +) + +func cutAtComma(s string, n int) (before, after string, found bool) { + // Note: this implementation draws inspiration from strings.Cut's. + end := min(len(s), n) + if i := strings.IndexByte(s[:end], ','); i >= 0 { + after = s[i+1:] // deal with this first to save one bounds check + return s[:i], after, true + } + return s, "", false +} + +// TrimOWS trims up to n bytes of [optional whitespace (OWS)] +// from the start of and/or the end of s. +// If no more than n bytes of OWS are found at the start of s +// and no more than n bytes of OWS are found at the end of s, +// it returns the trimmed result and true. +// Otherwise, it returns the original string and false. +// +// [optional whitespace (OWS)]: https://httpwg.org/specs/rfc9110.html#whitespace +func trimOWS(s string, n int) (trimmed string, ok bool) { + if s == "" { + return s, true + } + trimmed, ok = trimRightOWS(s, n) + if !ok { + return s, false } - posOfLastNameSeen := -1 - chunkSize := set.maxLen + 1 // (to accommodate for at least one comma) - for { - // As a defense against maliciously long names in csv, - // we only process at most chunkSize bytes per iteration. - end := min(len(csv), chunkSize) - comma := strings.IndexByte(csv[:end], ',') - var name string - if comma == -1 { - name = csv - } else { - name = csv[:comma] + trimmed, ok = trimLeftOWS(trimmed, n) + if !ok { + return s, false + } + return trimmed, true +} + +func trimLeftOWS(s string, n int) (string, bool) { + sCopy := s + var i int + for len(s) > 0 { + if i > n { + return sCopy, false } - pos, found := set.m[name] - if !found { - return false + if !(s[0] == ' ' || s[0] == '\t') { + break } - // The names in csv are expected to be sorted in lexicographical order - // and appear at most once in csv. - // Therefore, the positions (in set) of the names that - // appear in csv should form a strictly increasing sequence. - // If that's not actually the case, bail out. - if pos <= posOfLastNameSeen { - return false + s = s[1:] + i++ + } + return s, true +} + +func trimRightOWS(s string, n int) (string, bool) { + sCopy := s + var i int + for len(s) > 0 { + if i > n { + return sCopy, false } - posOfLastNameSeen = pos - if comma < 0 { // We've now processed all the names in csv. + last := len(s) - 1 + if !(s[last] == ' ' || s[last] == '\t') { break } - csv = csv[comma+1:] + s = s[:last] + i++ } - return true + return s, true } // TODO: when updating go directive to 1.21 or later, diff --git a/event-processor/vendor/github.com/rs/cors/utils.go b/event-processor/vendor/github.com/rs/cors/utils.go index 7019f45c..41b0c283 100644 --- a/event-processor/vendor/github.com/rs/cors/utils.go +++ b/event-processor/vendor/github.com/rs/cors/utils.go @@ -1,7 +1,6 @@ package cors import ( - "net/http" "strings" ) @@ -24,11 +23,3 @@ func convert(s []string, f func(string) string) []string { } return out } - -func first(hdrs http.Header, k string) ([]string, bool) { - v, found := hdrs[k] - if !found || len(v) == 0 { - return nil, false - } - return v[:1], true -} diff --git a/event-processor/vendor/github.com/rs/zerolog/CNAME b/event-processor/vendor/github.com/rs/zerolog/CNAME deleted file mode 100644 index 9ce57a6e..00000000 --- a/event-processor/vendor/github.com/rs/zerolog/CNAME +++ /dev/null @@ -1 +0,0 @@ -zerolog.io \ No newline at end of file diff --git a/event-processor/vendor/github.com/rs/zerolog/CONTRIBUTING.md b/event-processor/vendor/github.com/rs/zerolog/CONTRIBUTING.md new file mode 100644 index 00000000..a09e9e21 --- /dev/null +++ b/event-processor/vendor/github.com/rs/zerolog/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Contributing to Zerolog + +Thank you for your interest in contributing to **Zerolog**! + +Zerolog is a **feature-complete**, high-performance logging library designed to be **lean** and **non-bloated**. The focus of ongoing development is on **bug fixes**, **performance improvements**, and **modernization efforts** (such as keeping up with Go best practices and compatibility with newer Go versions). + +## What We're Looking For + +We welcome contributions in the following areas: + +- **Bug Fixes**: If you find an issue or unexpected behavior, please open an issue and/or submit a fix. +- **Performance Optimizations**: Improvements that reduce memory usage, allocation count, or CPU cycles without introducing complexity are appreciated. +- **Modernization**: Compatibility updates for newer Go versions or idiomatic improvements that do not increase library size or complexity. +- **Documentation Enhancements**: Corrections, clarifications, and improvements to documentation or code comments. + +## What We're *Not* Looking For + +Zerolog is intended to remain **minimalistic and efficient**. Therefore, we are **not accepting**: + +- New features that add optional behaviors or extend API surface area. +- Built-in support for frameworks or external systems (e.g., bindings, integrations). +- General-purpose abstractions or configuration helpers. + +If you're unsure whether a change aligns with the project's philosophy, feel free to open an issue for discussion before submitting a PR. + +## Contributing Guidelines + +1. **Fork the repository** +2. **Create a branch** for your fix or improvement +3. **Write tests** to cover your changes +4. Ensure `go test ./...` passes +5. Run `go fmt` and `go vet` to ensure code consistency +6. **Submit a pull request** with a clear explanation of the motivation and impact + +## Code Style + +- Keep the code simple, efficient, and idiomatic. +- Avoid introducing new dependencies. +- Preserve backwards compatibility unless explicitly discussed. + +--- + +We appreciate your effort in helping us keep Zerolog fast, minimal, and reliable! diff --git a/event-processor/vendor/github.com/rs/zerolog/README.md b/event-processor/vendor/github.com/rs/zerolog/README.md index 1306a6c1..9d4e8e8d 100644 --- a/event-processor/vendor/github.com/rs/zerolog/README.md +++ b/event-processor/vendor/github.com/rs/zerolog/README.md @@ -366,6 +366,37 @@ log.Info().Str("foo", "bar").Msg("Hello World") // Output: 2006-01-02T15:04:05Z07:00 | INFO | ***Hello World**** foo:BAR ``` +To use custom advanced formatting: + +```go +output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true, + PartsOrder: []string{"level", "one", "two", "three", "message"}, + FieldsExclude: []string{"one", "two", "three"}} +output.FormatLevel = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%-6s", i)) } +output.FormatFieldName = func(i interface{}) string { return fmt.Sprintf("%s:", i) } +output.FormatPartValueByName = func(i interface{}, s string) string { + var ret string + switch s { + case "one": + ret = strings.ToUpper(fmt.Sprintf("%s", i)) + case "two": + ret = strings.ToLower(fmt.Sprintf("%s", i)) + case "three": + ret = strings.ToLower(fmt.Sprintf("(%s)", i)) + } + return ret +} +log := zerolog.New(output) + +log.Info().Str("foo", "bar"). + Str("two", "TEST_TWO"). + Str("one", "test_one"). + Str("three", "test_three"). + Msg("Hello World") + +// Output: INFO TEST_ONE test_two (test_three) Hello World foo:bar +``` + ### Sub dictionary ```go diff --git a/event-processor/vendor/github.com/rs/zerolog/_config.yml b/event-processor/vendor/github.com/rs/zerolog/_config.yml deleted file mode 100644 index a1e896d7..00000000 --- a/event-processor/vendor/github.com/rs/zerolog/_config.yml +++ /dev/null @@ -1 +0,0 @@ -remote_theme: rs/gh-readme diff --git a/event-processor/vendor/github.com/rs/zerolog/console.go b/event-processor/vendor/github.com/rs/zerolog/console.go index 7e65e86f..6c881ef6 100644 --- a/event-processor/vendor/github.com/rs/zerolog/console.go +++ b/event-processor/vendor/github.com/rs/zerolog/console.go @@ -47,6 +47,10 @@ const ( // Formatter transforms the input into a formatted string. type Formatter func(interface{}) string +// FormatterByFieldName transforms the input into a formatted string, +// being able to differentiate formatting based on field name. +type FormatterByFieldName func(interface{}, string) string + // ConsoleWriter parses the JSON input and writes it in an // (optionally) colorized, human-friendly format to Out. type ConsoleWriter struct { @@ -85,6 +89,9 @@ type ConsoleWriter struct { FormatFieldValue Formatter FormatErrFieldName Formatter FormatErrFieldValue Formatter + // If this is configured it is used for "part" values and + // has precedence on FormatFieldValue + FormatPartValueByName FormatterByFieldName FormatExtra func(map[string]interface{}, *bytes.Buffer) error @@ -282,8 +289,9 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer // writePart appends a formatted part to buf. func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{}, p string) { var f Formatter + var fvn FormatterByFieldName - if w.PartsExclude != nil && len(w.PartsExclude) > 0 { + if len(w.PartsExclude) > 0 { for _, exclude := range w.PartsExclude { if exclude == p { return @@ -317,14 +325,21 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{}, f = w.FormatCaller } default: - if w.FormatFieldValue == nil { - f = consoleDefaultFormatFieldValue - } else { + if w.FormatPartValueByName != nil { + fvn = w.FormatPartValueByName + } else if w.FormatFieldValue != nil { f = w.FormatFieldValue + } else { + f = consoleDefaultFormatFieldValue } } - var s = f(evt[p]) + var s string + if f == nil { + s = fvn(evt[p], p) + } else { + s = f(evt[p]) + } if len(s) > 0 { if buf.Len() > 0 { diff --git a/event-processor/vendor/github.com/rs/zerolog/log.go b/event-processor/vendor/github.com/rs/zerolog/log.go index 6c1d4ead..ea2cd62b 100644 --- a/event-processor/vendor/github.com/rs/zerolog/log.go +++ b/event-processor/vendor/github.com/rs/zerolog/log.go @@ -494,7 +494,7 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event { if level != NoLevel && LevelFieldName != "" { e.Str(LevelFieldName, LevelFieldMarshalFunc(level)) } - if l.context != nil && len(l.context) > 1 { + if len(l.context) > 1 { e.buf = enc.AppendObjectData(e.buf, l.context) } if l.stack { diff --git a/event-processor/vendor/github.com/rs/zerolog/sampler.go b/event-processor/vendor/github.com/rs/zerolog/sampler.go index 83ce2ed3..19e04bd4 100644 --- a/event-processor/vendor/github.com/rs/zerolog/sampler.go +++ b/event-processor/vendor/github.com/rs/zerolog/sampler.go @@ -47,6 +47,9 @@ type BasicSampler struct { // Sample implements the Sampler interface. func (s *BasicSampler) Sample(lvl Level) bool { n := s.N + if n == 0 { + return false + } if n == 1 { return true } @@ -87,7 +90,7 @@ func (s *BurstSampler) inc() uint32 { now := TimestampFunc().UnixNano() resetAt := atomic.LoadInt64(&s.resetAt) var c uint32 - if now > resetAt { + if now >= resetAt { c = 1 atomic.StoreUint32(&s.counter, c) newResetAt := now + s.Period.Nanoseconds() diff --git a/event-processor/vendor/github.com/rs/zerolog/writer.go b/event-processor/vendor/github.com/rs/zerolog/writer.go index 41b394d7..0fc5ff59 100644 --- a/event-processor/vendor/github.com/rs/zerolog/writer.go +++ b/event-processor/vendor/github.com/rs/zerolog/writer.go @@ -213,6 +213,15 @@ func (w *FilteredLevelWriter) WriteLevel(level Level, p []byte) (int, error) { return len(p), nil } +// Call the underlying writer's Close method if it is an io.Closer. Otherwise +// does nothing. +func (w *FilteredLevelWriter) Close() error { + if closer, ok := w.Writer.(io.Closer); ok { + return closer.Close() + } + return nil +} + var triggerWriterPool = &sync.Pool{ New: func() interface{} { return bytes.NewBuffer(make([]byte, 0, 1024)) diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go index fb4087d9..3604294e 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go @@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error { return nil } +func (jt JSONTime) String() string { + return time.Time(jt).String() +} + type Token struct { Username string `json:"username"` UserID string `json:"user_id"` @@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) { return nil, errors.New("unknown authorization format") } - token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) { + token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) { return key, nil }) if err != nil { diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go index 79432fec..24b0d6e3 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go @@ -27,7 +27,7 @@ func SetReady() { } // ReadyHandler handles ready probes. -func ReadyHandler(w http.ResponseWriter, r *http.Request) { +func ReadyHandler(w http.ResponseWriter, _ *http.Request) { if IsReady() { // Make it simple: do nothing and have 200 OK return @@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) { } // LiveHandler handles live probes. -func LiveHandler(w http.ResponseWriter, r *http.Request) { +func LiveHandler(http.ResponseWriter, *http.Request) { // Make it simple: do nothing and have 200 OK } diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go index cb9487d6..822eb440 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go @@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, const CorrelationHeader = "correlation-id" -func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { +func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { var corrID string md, ok := metadata.FromIncomingContext(ctx) diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/integration.pb.gw.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/integration.pb.gw.go index f4e052f3..4c175124 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/integration.pb.gw.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/integration.pb.gw.go @@ -10,6 +10,7 @@ package api import ( "context" + "errors" "io" "net/http" @@ -24,328 +25,264 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_IntegrationController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client IntegrationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Integration - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Integration + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_IntegrationController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server IntegrationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Integration - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Integration + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Create(ctx, &protoReq) return msg, metadata, err - } func request_IntegrationController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client IntegrationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - val, ok = pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_IntegrationController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server IntegrationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - val, ok = pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Read(ctx, &protoReq) return msg, metadata, err - } func request_IntegrationController_Update_0(ctx context.Context, marshaler runtime.Marshaler, client IntegrationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Integration - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Integration + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_IntegrationController_Update_0(ctx context.Context, marshaler runtime.Marshaler, server IntegrationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Integration - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Integration + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Update(ctx, &protoReq) return msg, metadata, err - } func request_IntegrationController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client IntegrationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - val, ok = pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_IntegrationController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server IntegrationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - val, ok = pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Delete(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_IntegrationController_List_0 = &utilities.DoubleArray{Encoding: map[string]int{"type": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) +var filter_IntegrationController_List_0 = &utilities.DoubleArray{Encoding: map[string]int{"type": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} func request_IntegrationController_List_0(ctx context.Context, marshaler runtime.Marshaler, client IntegrationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_IntegrationController_List_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.List(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_IntegrationController_List_0(ctx context.Context, marshaler runtime.Marshaler, server IntegrationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIntegrationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListIntegrationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["type"] + val, ok := pathParams["type"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "type") } - protoReq.Type, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "type", err) } - if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_IntegrationController_List_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.List(ctx, &protoReq) return msg, metadata, err - } // RegisterIntegrationControllerHandlerServer registers the http handlers for service IntegrationController to "mux". // UnaryRPC :call IntegrationControllerServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterIntegrationControllerHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server IntegrationControllerServer) error { - - mux.Handle("POST", pattern_IntegrationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_IntegrationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Create", runtime.WithHTTPPathPattern("/api/v1/integration")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Create", runtime.WithHTTPPathPattern("/api/v1/integration")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -357,20 +294,15 @@ func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_IntegrationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_IntegrationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Read", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Read", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -382,20 +314,15 @@ func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_IntegrationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_IntegrationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Update", runtime.WithHTTPPathPattern("/api/v1/integration/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Update", runtime.WithHTTPPathPattern("/api/v1/integration/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -407,20 +334,15 @@ func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_IntegrationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_IntegrationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Delete", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/Delete", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -432,20 +354,15 @@ func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_IntegrationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_IntegrationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/List", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/list")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/integration.IntegrationController/List", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -457,9 +374,7 @@ func RegisterIntegrationControllerHandlerServer(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -486,7 +401,6 @@ func RegisterIntegrationControllerHandlerFromEndpoint(ctx context.Context, mux * } }() }() - return RegisterIntegrationControllerHandler(ctx, mux, conn) } @@ -500,16 +414,13 @@ func RegisterIntegrationControllerHandler(ctx context.Context, mux *runtime.Serv // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "IntegrationControllerClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "IntegrationControllerClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "IntegrationControllerClient" to call the correct interceptors. +// "IntegrationControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client IntegrationControllerClient) error { - - mux.Handle("POST", pattern_IntegrationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_IntegrationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Create", runtime.WithHTTPPathPattern("/api/v1/integration")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Create", runtime.WithHTTPPathPattern("/api/v1/integration")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -520,18 +431,13 @@ func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_IntegrationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_IntegrationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Read", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Read", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -542,18 +448,13 @@ func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_IntegrationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_IntegrationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Update", runtime.WithHTTPPathPattern("/api/v1/integration/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Update", runtime.WithHTTPPathPattern("/api/v1/integration/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -564,18 +465,13 @@ func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_IntegrationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_IntegrationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Delete", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/Delete", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -586,18 +482,13 @@ func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_IntegrationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_IntegrationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/List", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/list")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/integration.IntegrationController/List", runtime.WithHTTPPathPattern("/api/v1/integration/{type}/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -608,34 +499,23 @@ func RegisterIntegrationControllerHandlerClient(ctx context.Context, mux *runtim runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_IntegrationController_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( pattern_IntegrationController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "integration"}, "")) - - pattern_IntegrationController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "integration", "type", "id"}, "")) - + pattern_IntegrationController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "integration", "type", "id"}, "")) pattern_IntegrationController_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "integration", "id"}, "")) - pattern_IntegrationController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "integration", "type", "id"}, "")) - - pattern_IntegrationController_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "integration", "type", "list"}, "")) + pattern_IntegrationController_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "integration", "type", "list"}, "")) ) var ( forward_IntegrationController_Create_0 = runtime.ForwardResponseMessage - - forward_IntegrationController_Read_0 = runtime.ForwardResponseMessage - + forward_IntegrationController_Read_0 = runtime.ForwardResponseMessage forward_IntegrationController_Update_0 = runtime.ForwardResponseMessage - forward_IntegrationController_Delete_0 = runtime.ForwardResponseMessage - - forward_IntegrationController_List_0 = runtime.ForwardResponseMessage + forward_IntegrationController_List_0 = runtime.ForwardResponseMessage ) diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notification.pb.gw.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notification.pb.gw.go index 5702548c..81d196a5 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notification.pb.gw.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notification.pb.gw.go @@ -10,6 +10,7 @@ package api import ( "context" + "errors" "io" "net/http" @@ -24,290 +25,249 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_NotificationController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Notification - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Notification + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Notification - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq Notification + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Create(ctx, &protoReq) return msg, metadata, err - } func request_NotificationController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadNotificationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadNotificationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ReadNotificationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ReadNotificationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Read(ctx, &protoReq) return msg, metadata, err - } func request_NotificationController_Update_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Notification - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Notification + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_Update_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Notification - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - var ( - val string - ok bool - err error - _ = err + protoReq Notification + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Update(ctx, &protoReq) return msg, metadata, err - } func request_NotificationController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteNotificationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteNotificationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteNotificationReq - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq DeleteNotificationReq + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.Delete(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_NotificationController_List_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +var filter_NotificationController_List_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_NotificationController_List_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListNotificationReq - var metadata runtime.ServerMetadata - + var ( + protoReq ListNotificationReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NotificationController_List_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.List(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_List_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListNotificationReq - var metadata runtime.ServerMetadata - + var ( + protoReq ListNotificationReq + metadata runtime.ServerMetadata + ) if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NotificationController_List_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.List(ctx, &protoReq) return msg, metadata, err - } -var ( - filter_NotificationController_DefaultTemplate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +var filter_NotificationController_DefaultTemplate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_NotificationController_DefaultTemplate_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DefaultTemplateReq - var metadata runtime.ServerMetadata - + var ( + protoReq DefaultTemplateReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NotificationController_DefaultTemplate_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DefaultTemplate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_NotificationController_DefaultTemplate_0(ctx context.Context, marshaler runtime.Marshaler, server NotificationControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DefaultTemplateReq - var metadata runtime.ServerMetadata - + var ( + protoReq DefaultTemplateReq + metadata runtime.ServerMetadata + ) if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NotificationController_DefaultTemplate_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.DefaultTemplate(ctx, &protoReq) return msg, metadata, err - } // RegisterNotificationControllerHandlerServer registers the http handlers for service NotificationController to "mux". // UnaryRPC :call NotificationControllerServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterNotificationControllerHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server NotificationControllerServer) error { - - mux.Handle("POST", pattern_NotificationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_NotificationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Create", runtime.WithHTTPPathPattern("/api/v1/notification")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Create", runtime.WithHTTPPathPattern("/api/v1/notification")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -319,20 +279,15 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Read", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Read", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -344,20 +299,15 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_NotificationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_NotificationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Update", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Update", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -369,20 +319,15 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_NotificationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_NotificationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Delete", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/Delete", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -394,20 +339,15 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/List", runtime.WithHTTPPathPattern("/api/v1/notification/list")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/List", runtime.WithHTTPPathPattern("/api/v1/notification/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -419,20 +359,15 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_DefaultTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_DefaultTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/DefaultTemplate", runtime.WithHTTPPathPattern("/api/v1/notification/default-template")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notification.NotificationController/DefaultTemplate", runtime.WithHTTPPathPattern("/api/v1/notification/default-template")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -444,9 +379,7 @@ func RegisterNotificationControllerHandlerServer(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_DefaultTemplate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -473,7 +406,6 @@ func RegisterNotificationControllerHandlerFromEndpoint(ctx context.Context, mux } }() }() - return RegisterNotificationControllerHandler(ctx, mux, conn) } @@ -487,16 +419,13 @@ func RegisterNotificationControllerHandler(ctx context.Context, mux *runtime.Ser // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "NotificationControllerClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "NotificationControllerClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "NotificationControllerClient" to call the correct interceptors. +// "NotificationControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client NotificationControllerClient) error { - - mux.Handle("POST", pattern_NotificationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_NotificationController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Create", runtime.WithHTTPPathPattern("/api/v1/notification")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Create", runtime.WithHTTPPathPattern("/api/v1/notification")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -507,18 +436,13 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Read", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Read", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -529,18 +453,13 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("PATCH", pattern_NotificationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPatch, pattern_NotificationController_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Update", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Update", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -551,18 +470,13 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("DELETE", pattern_NotificationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodDelete, pattern_NotificationController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Delete", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/Delete", runtime.WithHTTPPathPattern("/api/v1/notification/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -573,18 +487,13 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/List", runtime.WithHTTPPathPattern("/api/v1/notification/list")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/List", runtime.WithHTTPPathPattern("/api/v1/notification/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -595,18 +504,13 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_NotificationController_DefaultTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_NotificationController_DefaultTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/DefaultTemplate", runtime.WithHTTPPathPattern("/api/v1/notification/default-template")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notification.NotificationController/DefaultTemplate", runtime.WithHTTPPathPattern("/api/v1/notification/default-template")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -617,38 +521,25 @@ func RegisterNotificationControllerHandlerClient(ctx context.Context, mux *runti runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_NotificationController_DefaultTemplate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_NotificationController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "notification"}, "")) - - pattern_NotificationController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) - - pattern_NotificationController_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) - - pattern_NotificationController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) - - pattern_NotificationController_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "notification", "list"}, "")) - + pattern_NotificationController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "notification"}, "")) + pattern_NotificationController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) + pattern_NotificationController_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) + pattern_NotificationController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "notification", "id"}, "")) + pattern_NotificationController_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "notification", "list"}, "")) pattern_NotificationController_DefaultTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "notification", "default-template"}, "")) ) var ( - forward_NotificationController_Create_0 = runtime.ForwardResponseMessage - - forward_NotificationController_Read_0 = runtime.ForwardResponseMessage - - forward_NotificationController_Update_0 = runtime.ForwardResponseMessage - - forward_NotificationController_Delete_0 = runtime.ForwardResponseMessage - - forward_NotificationController_List_0 = runtime.ForwardResponseMessage - + forward_NotificationController_Create_0 = runtime.ForwardResponseMessage + forward_NotificationController_Read_0 = runtime.ForwardResponseMessage + forward_NotificationController_Update_0 = runtime.ForwardResponseMessage + forward_NotificationController_Delete_0 = runtime.ForwardResponseMessage + forward_NotificationController_List_0 = runtime.ForwardResponseMessage forward_NotificationController_DefaultTemplate_0 = runtime.ForwardResponseMessage ) diff --git a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notifier.pb.gw.go b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notifier.pb.gw.go index e3fb5d17..992540ef 100644 --- a/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notifier.pb.gw.go +++ b/event-processor/vendor/github.com/runtime-radar/runtime-radar/notifier/api/notifier.pb.gw.go @@ -10,6 +10,7 @@ package api import ( "context" + "errors" "io" "net/http" @@ -24,54 +25,56 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_Notifier_Notify_0(ctx context.Context, marshaler runtime.Marshaler, client NotifierClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq NotifyReq - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq NotifyReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } msg, err := client.Notify(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_Notifier_Notify_0(ctx context.Context, marshaler runtime.Marshaler, server NotifierServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq NotifyReq - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq NotifyReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Notify(ctx, &protoReq) return msg, metadata, err - } // RegisterNotifierHandlerServer registers the http handlers for service Notifier to "mux". // UnaryRPC :call NotifierServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterNotifierHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterNotifierHandlerServer(ctx context.Context, mux *runtime.ServeMux, server NotifierServer) error { - - mux.Handle("POST", pattern_Notifier_Notify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Notifier_Notify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/notifier.Notifier/Notify", runtime.WithHTTPPathPattern("/api/v1/notify")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/notifier.Notifier/Notify", runtime.WithHTTPPathPattern("/api/v1/notify")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -83,9 +86,7 @@ func RegisterNotifierHandlerServer(ctx context.Context, mux *runtime.ServeMux, s runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_Notifier_Notify_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -112,7 +113,6 @@ func RegisterNotifierHandlerFromEndpoint(ctx context.Context, mux *runtime.Serve } }() }() - return RegisterNotifierHandler(ctx, mux, conn) } @@ -126,16 +126,13 @@ func RegisterNotifierHandler(ctx context.Context, mux *runtime.ServeMux, conn *g // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "NotifierClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "NotifierClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "NotifierClient" to call the correct interceptors. +// "NotifierClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterNotifierHandlerClient(ctx context.Context, mux *runtime.ServeMux, client NotifierClient) error { - - mux.Handle("POST", pattern_Notifier_Notify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Notifier_Notify_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/notifier.Notifier/Notify", runtime.WithHTTPPathPattern("/api/v1/notify")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/notifier.Notifier/Notify", runtime.WithHTTPPathPattern("/api/v1/notify")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -146,11 +143,8 @@ func RegisterNotifierHandlerClient(ctx context.Context, mux *runtime.ServeMux, c runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_Notifier_Notify_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/.envrc b/event-processor/vendor/github.com/sagikazarmark/locafero/.envrc index 3ce7171a..2e0f9f5f 100644 --- a/event-processor/vendor/github.com/sagikazarmark/locafero/.envrc +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/.envrc @@ -1,4 +1,4 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" fi use flake . --impure diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/finder.go b/event-processor/vendor/github.com/sagikazarmark/locafero/finder.go index 754c8b26..ef8d5471 100644 --- a/event-processor/vendor/github.com/sagikazarmark/locafero/finder.go +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/finder.go @@ -27,7 +27,7 @@ type Finder struct { // It provides the capability to search for entries with depth, // meaning it can target deeper locations within the directory structure. // - // It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns. + // It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns. // // Examples: // - config.yaml @@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { // pool.Go(func() ([]string, error) { // // If the name contains any glob character, perform a glob match - // if strings.ContainsAny(searchName, "*?[]\\^") { + // if strings.ContainsAny(searchName, globMatch) { // return globWalkSearch(fsys, searchPath, searchName, f.Type) // } // @@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) { // If the name contains any glob character, perform a glob match - if strings.ContainsAny(item.name, "*?[]\\^") { + if strings.ContainsAny(item.name, globMatch) { return globWalkSearch(fsys, item.path, item.name, f.Type) } diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/flake.lock b/event-processor/vendor/github.com/sagikazarmark/locafero/flake.lock index 46d28f80..df2a8cce 100644 --- a/event-processor/vendor/github.com/sagikazarmark/locafero/flake.lock +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1725907707, + "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=", + "owner": "cachix", + "repo": "devenv", + "rev": "2bbbbc468fc02257265a79652a8350651cca495a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", "type": "github" }, "original": { @@ -60,11 +138,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -82,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -95,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": [ + "devenv", + "flake-compat" + ], "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -153,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -187,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1694343207, - "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1725910328, + "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "78058d810644f5ed276804ce7ea9e82d92bee293", + "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4", "type": "github" }, "original": { @@ -217,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -232,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -249,7 +433,7 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "systems": { @@ -266,6 +450,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/flake.nix b/event-processor/vendor/github.com/sagikazarmark/locafero/flake.nix index 209ecf28..312f1ec8 100644 --- a/event-processor/vendor/github.com/sagikazarmark/locafero/flake.nix +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/flake.nix @@ -20,6 +20,7 @@ default = { languages = { go.enable = true; + go.package = pkgs.lib.mkDefault pkgs.go_1_23; }; packages = with pkgs; [ @@ -34,11 +35,27 @@ ci = devenv.shells.default; - ci_1_20 = { + ci_1_21 = { imports = [ devenv.shells.ci ]; languages = { - go.package = pkgs.go_1_20; + go.package = pkgs.go_1_21; + }; + }; + + ci_1_22 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_22; + }; + }; + + ci_1_23 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_23; }; }; }; diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/glob.go b/event-processor/vendor/github.com/sagikazarmark/locafero/glob.go new file mode 100644 index 00000000..00f833e9 --- /dev/null +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/glob.go @@ -0,0 +1,5 @@ +//go:build !windows + +package locafero + +const globMatch = "*?[]\\^" diff --git a/event-processor/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/event-processor/vendor/github.com/sagikazarmark/locafero/glob_windows.go new file mode 100644 index 00000000..7aec2b24 --- /dev/null +++ b/event-processor/vendor/github.com/sagikazarmark/locafero/glob_windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package locafero + +// See [filepath.Match]: +// +// On Windows, escaping is disabled. Instead, '\\' is treated as path separator. +const globMatch = "*?[]^" diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/event-processor/vendor/github.com/sagikazarmark/slog-shim/.editorconfig deleted file mode 100644 index 1fb0e1be..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 4 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.nix] -indent_size = 2 - -[{Makefile,*.mk}] -indent_style = tab - -[Taskfile.yaml] -indent_size = 2 diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.envrc b/event-processor/vendor/github.com/sagikazarmark/slog-shim/.envrc deleted file mode 100644 index 3ce7171a..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" -fi -use flake . --impure diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/event-processor/vendor/github.com/sagikazarmark/slog-shim/.gitignore deleted file mode 100644 index dc6d8b58..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.devenv/ -/.direnv/ -/.task/ -/build/ diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/event-processor/vendor/github.com/sagikazarmark/slog-shim/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/README.md b/event-processor/vendor/github.com/sagikazarmark/slog-shim/README.md deleted file mode 100644 index 1f5be85e..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# [slog](https://pkg.go.dev/log/slog) shim - -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square) -[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org) - -Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library. -Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately, -especially since updating to Go 1.21 is a decision that most libraries won't make overnight. - -Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog). -While it's generally advised against using experimental packages in production, -this one served as a sort of backport package for the last few years, -incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`). - -This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`. - -**How does it achieve backwards compatibility?** - -Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is. -(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.) - -This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`. -Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly. - -For older Go versions, the library might become unstable after removing the shim. -However, since those older versions are no longer supported, the promise of backward compatibility remains intact. - -## Installation - -```shell -go get github.com/sagikazarmark/slog-shim -``` - -## Usage - -Import this package into your library and use it in your public API: - -```go -package mylib - -import slog "github.com/sagikazarmark/slog-shim" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21): - -```go -package main - -import "log/slog" - -// OR - -import "golang.org/x/exp/slog" - -mylib.New(slog.Default()) -``` - -**Make sure consumers are aware that your API behaves differently on different Go versions.** - -Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code: - -```diff -package mylib - -- import slog "github.com/sagikazarmark/slog-shim" -+ import "log/slog" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -## License - -The project is licensed under a [BSD-style license](LICENSE). diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr.go deleted file mode 100644 index 89608bf3..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr_120.go deleted file mode 100644 index b6648133..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/attr_120.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.lock deleted file mode 100644 index 7e8898e9..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.lock +++ /dev/null @@ -1,273 +0,0 @@ -{ - "nodes": { - "devenv": { - "inputs": { - "flake-compat": "flake-compat", - "nix": "nix", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", - "owner": "cachix", - "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "lowdown-src": { - "flake": false, - "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", - "type": "github" - }, - "original": { - "owner": "kristapsdz", - "repo": "lowdown", - "type": "github" - } - }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", - "owner": "domenkozar", - "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "relaxed-flakes", - "repo": "nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1694345580, - "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "master", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.nix deleted file mode 100644 index 7239bbc2..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/flake.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ - inputs = { - # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - nixpkgs.url = "github:NixOS/nixpkgs/master"; - flake-parts.url = "github:hercules-ci/flake-parts"; - devenv.url = "github:cachix/devenv"; - }; - - outputs = inputs@{ flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } { - imports = [ - inputs.devenv.flakeModule - ]; - - systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; - - perSystem = { config, self', inputs', pkgs, system, ... }: rec { - devenv.shells = { - default = { - languages = { - go.enable = true; - go.package = pkgs.lib.mkDefault pkgs.go_1_21; - }; - - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; - - ci = devenv.shells.default; - - ci_1_19 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_19; - }; - }; - - ci_1_20 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_20; - }; - }; - - ci_1_21 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_21; - }; - }; - }; - }; - }; -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler.go deleted file mode 100644 index f55556ae..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler_120.go deleted file mode 100644 index 67005757..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/handler_120.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler.go deleted file mode 100644 index 7c22bd81..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go deleted file mode 100644 index 7b14f10b..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/level.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/level.go deleted file mode 100644 index 07288cf8..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/level.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/level_120.go deleted file mode 100644 index d3feb942..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/level_120.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger.go deleted file mode 100644 index e80036be..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "context" - "log" - "log/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger_120.go deleted file mode 100644 index 97ebdd5e..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/logger_120.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "context" - "log" - - "golang.org/x/exp/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/record.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/record.go deleted file mode 100644 index 85ad1f78..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/record.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/record_120.go deleted file mode 100644 index c2eaf4e7..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/record_120.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler.go deleted file mode 100644 index 45f6cfcb..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go deleted file mode 100644 index a69d63cc..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/value.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/value.go deleted file mode 100644 index 61173eb9..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/value.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/event-processor/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/event-processor/vendor/github.com/sagikazarmark/slog-shim/value_120.go deleted file mode 100644 index 0f9f871e..00000000 --- a/event-processor/vendor/github.com/sagikazarmark/slog-shim/value_120.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/event-processor/vendor/github.com/spf13/cast/README.md b/event-processor/vendor/github.com/spf13/cast/README.md index 58141f02..1be666a4 100644 --- a/event-processor/vendor/github.com/spf13/cast/README.md +++ b/event-processor/vendor/github.com/spf13/cast/README.md @@ -1,9 +1,9 @@ # cast -[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast) ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square) -[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go diff --git a/event-processor/vendor/github.com/spf13/cast/caste.go b/event-processor/vendor/github.com/spf13/cast/caste.go index d49bbf83..4181a2e7 100644 --- a/event-processor/vendor/github.com/spf13/cast/caste.go +++ b/event-processor/vendor/github.com/spf13/cast/caste.go @@ -18,6 +18,14 @@ import ( var errNegativeNotAllowed = errors.New("unable to cast negative value") +type float64EProvider interface { + Float64() (float64, error) +} + +type float64Provider interface { + Float64() float64 +} + // ToTimeE casts an interface to a time.Time type. func ToTimeE(i interface{}) (tim time.Time, err error) { return ToTimeInDefaultLocationE(i, time.UTC) @@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) { d, err = time.ParseDuration(s + "ns") } return - case json.Number: + case float64EProvider: var v float64 v, err = s.Float64() d = time.Duration(v) return + case float64Provider: + d = time.Duration(s.Float64()) + return default: err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i) return @@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) { return v, nil } return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) - case json.Number: + case float64EProvider: v, err := s.Float64() if err == nil { return v, nil } return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case float64Provider: + return s.Float64(), nil case bool: if s { return 1, nil @@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) { return float32(v), nil } return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) - case json.Number: + case float64EProvider: v, err := s.Float64() if err == nil { return float32(v), nil } return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case float64Provider: + return float32(s.Float64()), nil case bool: if s { return 1, nil @@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) { switch s := i.(type) { case string: - v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0) if err == nil { if v < 0 { return 0, errNegativeNotAllowed } - return uint64(v), nil + return v, nil } return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) case json.Number: @@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} { return nil } - var errorType = reflect.TypeOf((*error)(nil)).Elem() - var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + errorType := reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem() v := reflect.ValueOf(a) for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { @@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) { // ToStringMapStringE casts an interface to a map[string]string type. func ToStringMapStringE(i interface{}) (map[string]string, error) { - var m = map[string]string{} + m := map[string]string{} switch v := i.(type) { case map[string]string: @@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) { // ToStringMapStringSliceE casts an interface to a map[string][]string type. func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { - var m = map[string][]string{} + m := map[string][]string{} switch v := i.(type) { case map[string][]string: @@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { // ToStringMapBoolE casts an interface to a map[string]bool type. func ToStringMapBoolE(i interface{}) (map[string]bool, error) { - var m = map[string]bool{} + m := map[string]bool{} switch v := i.(type) { case map[interface{}]interface{}: @@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) { // ToStringMapE casts an interface to a map[string]interface{} type. func ToStringMapE(i interface{}) (map[string]interface{}, error) { - var m = map[string]interface{}{} + m := map[string]interface{}{} switch v := i.(type) { case map[interface{}]interface{}: @@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) { // ToStringMapIntE casts an interface to a map[string]int{} type. func ToStringMapIntE(i interface{}) (map[string]int, error) { - var m = map[string]int{} + m := map[string]int{} if i == nil { return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) } @@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) { // ToStringMapInt64E casts an interface to a map[string]int64{} type. func ToStringMapInt64E(i interface{}) (map[string]int64, error) { - var m = map[string]int64{} + m := map[string]int64{} if i == nil { return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) } @@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool { return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone } -var ( - timeFormats = []timeFormat{ - // Keep common formats at the top. - {"2006-01-02", timeFormatNoTimezone}, - {time.RFC3339, timeFormatNumericTimezone}, - {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone - {time.RFC1123Z, timeFormatNumericTimezone}, - {time.RFC1123, timeFormatNamedTimezone}, - {time.RFC822Z, timeFormatNumericTimezone}, - {time.RFC822, timeFormatNamedTimezone}, - {time.RFC850, timeFormatNamedTimezone}, - {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() - {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon - {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon - {"2006-01-02 15:04:05", timeFormatNoTimezone}, - {time.ANSIC, timeFormatNoTimezone}, - {time.UnixDate, timeFormatNamedTimezone}, - {time.RubyDate, timeFormatNumericTimezone}, - {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, - {"02 Jan 2006", timeFormatNoTimezone}, - {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, - {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, - {time.Kitchen, timeFormatTimeOnly}, - {time.Stamp, timeFormatTimeOnly}, - {time.StampMilli, timeFormatTimeOnly}, - {time.StampMicro, timeFormatTimeOnly}, - {time.StampNano, timeFormatTimeOnly}, - } -) +var timeFormats = []timeFormat{ + // Keep common formats at the top. + {"2006-01-02", timeFormatNoTimezone}, + {time.RFC3339, timeFormatNumericTimezone}, + {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone + {time.RFC1123Z, timeFormatNumericTimezone}, + {time.RFC1123, timeFormatNamedTimezone}, + {time.RFC822Z, timeFormatNumericTimezone}, + {time.RFC822, timeFormatNamedTimezone}, + {time.RFC850, timeFormatNamedTimezone}, + {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() + {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon + {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon + {"2006-01-02 15:04:05", timeFormatNoTimezone}, + {time.ANSIC, timeFormatNoTimezone}, + {time.UnixDate, timeFormatNamedTimezone}, + {time.RubyDate, timeFormatNumericTimezone}, + {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, + {"02 Jan 2006", timeFormatNoTimezone}, + {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, + {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, + {time.Kitchen, timeFormatTimeOnly}, + {time.Stamp, timeFormatTimeOnly}, + {time.StampMilli, timeFormatTimeOnly}, + {time.StampMicro, timeFormatTimeOnly}, + {time.StampNano, timeFormatTimeOnly}, +} func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) { - for _, format := range formats { if d, e = time.Parse(format.format, s); e == nil { diff --git a/event-processor/vendor/github.com/spf13/pflag/README.md b/event-processor/vendor/github.com/spf13/pflag/README.md index 7eacc5bd..388c4e5e 100644 --- a/event-processor/vendor/github.com/spf13/pflag/README.md +++ b/event-processor/vendor/github.com/spf13/pflag/README.md @@ -284,6 +284,33 @@ func main() { } ``` +### Using pflag with go test +`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`). +For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details. + +For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this: +```bash +go test /your/tests -run ^YourTest -v --your-test-pflags +``` +will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags. +To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package. + +**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()` +```go +import ( + goflag "flag" + flag "github.com/spf13/pflag" +) + +var ip *int = flag.Int("flagname", 1234, "help message for flagname") + +func main() { + flag.CommandLine.AddGoFlagSet(goflag.CommandLine) + flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine) + flag.Parse() +} +``` + ## More info You can see the full reference documentation of the pflag package diff --git a/event-processor/vendor/github.com/spf13/pflag/bool_func.go b/event-processor/vendor/github.com/spf13/pflag/bool_func.go new file mode 100644 index 00000000..83d77afa --- /dev/null +++ b/event-processor/vendor/github.com/spf13/pflag/bool_func.go @@ -0,0 +1,40 @@ +package pflag + +// -- func Value +type boolfuncValue func(string) error + +func (f boolfuncValue) Set(s string) error { return f(s) } + +func (f boolfuncValue) Type() string { return "boolfunc" } + +func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package + +func (f boolfuncValue) IsBoolFlag() bool { return true } + +// BoolFunc defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed +// on the command line. +func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) { + f.BoolFuncP(name, "", usage, fn) +} + +// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) { + var val Value = boolfuncValue(fn) + flag := f.VarPF(val, name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// BoolFunc defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed +// on the command line. +func BoolFunc(name string, usage string, fn func(string) error) { + CommandLine.BoolFuncP(name, "", usage, fn) +} + +// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash. +func BoolFuncP(name, shorthand string, usage string, fn func(string) error) { + CommandLine.BoolFuncP(name, shorthand, usage, fn) +} diff --git a/event-processor/vendor/github.com/spf13/pflag/count.go b/event-processor/vendor/github.com/spf13/pflag/count.go index a0b2679f..d49c0143 100644 --- a/event-processor/vendor/github.com/spf13/pflag/count.go +++ b/event-processor/vendor/github.com/spf13/pflag/count.go @@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int { // Count defines a count flag with specified name, default value, and usage string. // The return value is the address of an int variable that stores the value of the flag. -// A count flag will add 1 to its value evey time it is found on the command line +// A count flag will add 1 to its value every time it is found on the command line func Count(name string, usage string) *int { return CommandLine.CountP(name, "", usage) } diff --git a/event-processor/vendor/github.com/spf13/pflag/errors.go b/event-processor/vendor/github.com/spf13/pflag/errors.go new file mode 100644 index 00000000..ff11b66b --- /dev/null +++ b/event-processor/vendor/github.com/spf13/pflag/errors.go @@ -0,0 +1,149 @@ +package pflag + +import "fmt" + +// notExistErrorMessageType specifies which flavor of "flag does not exist" +// is printed by NotExistError. This allows the related errors to be grouped +// under a single NotExistError struct without making a breaking change to +// the error message text. +type notExistErrorMessageType int + +const ( + flagNotExistMessage notExistErrorMessageType = iota + flagNotDefinedMessage + flagNoSuchFlagMessage + flagUnknownFlagMessage + flagUnknownShorthandFlagMessage +) + +// NotExistError is the error returned when trying to access a flag that +// does not exist in the FlagSet. +type NotExistError struct { + name string + specifiedShorthands string + messageType notExistErrorMessageType +} + +// Error implements error. +func (e *NotExistError) Error() string { + switch e.messageType { + case flagNotExistMessage: + return fmt.Sprintf("flag %q does not exist", e.name) + + case flagNotDefinedMessage: + return fmt.Sprintf("flag accessed but not defined: %s", e.name) + + case flagNoSuchFlagMessage: + return fmt.Sprintf("no such flag -%v", e.name) + + case flagUnknownFlagMessage: + return fmt.Sprintf("unknown flag: --%s", e.name) + + case flagUnknownShorthandFlagMessage: + c := rune(e.name[0]) + return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands) + } + + panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType)) +} + +// GetSpecifiedName returns the name of the flag (without dashes) as it +// appeared in the parsed arguments. +func (e *NotExistError) GetSpecifiedName() string { + return e.name +} + +// GetSpecifiedShortnames returns the group of shorthand arguments +// (without dashes) that the flag appeared within. If the flag was not in a +// shorthand group, this will return an empty string. +func (e *NotExistError) GetSpecifiedShortnames() string { + return e.specifiedShorthands +} + +// ValueRequiredError is the error returned when a flag needs an argument but +// no argument was provided. +type ValueRequiredError struct { + flag *Flag + specifiedName string + specifiedShorthands string +} + +// Error implements error. +func (e *ValueRequiredError) Error() string { + if len(e.specifiedShorthands) > 0 { + c := rune(e.specifiedName[0]) + return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands) + } + + return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName) +} + +// GetFlag returns the flag for which the error occurred. +func (e *ValueRequiredError) GetFlag() *Flag { + return e.flag +} + +// GetSpecifiedName returns the name of the flag (without dashes) as it +// appeared in the parsed arguments. +func (e *ValueRequiredError) GetSpecifiedName() string { + return e.specifiedName +} + +// GetSpecifiedShortnames returns the group of shorthand arguments +// (without dashes) that the flag appeared within. If the flag was not in a +// shorthand group, this will return an empty string. +func (e *ValueRequiredError) GetSpecifiedShortnames() string { + return e.specifiedShorthands +} + +// InvalidValueError is the error returned when an invalid value is used +// for a flag. +type InvalidValueError struct { + flag *Flag + value string + cause error +} + +// Error implements error. +func (e *InvalidValueError) Error() string { + flag := e.flag + var flagName string + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) + } else { + flagName = fmt.Sprintf("--%s", flag.Name) + } + return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause) +} + +// Unwrap implements errors.Unwrap. +func (e *InvalidValueError) Unwrap() error { + return e.cause +} + +// GetFlag returns the flag for which the error occurred. +func (e *InvalidValueError) GetFlag() *Flag { + return e.flag +} + +// GetValue returns the invalid value that was provided. +func (e *InvalidValueError) GetValue() string { + return e.value +} + +// InvalidSyntaxError is the error returned when a bad flag name is passed on +// the command line. +type InvalidSyntaxError struct { + specifiedFlag string +} + +// Error implements error. +func (e *InvalidSyntaxError) Error() string { + return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag) +} + +// GetSpecifiedName returns the exact flag (with dashes) as it +// appeared in the parsed arguments. +func (e *InvalidSyntaxError) GetSpecifiedFlag() string { + return e.specifiedFlag +} diff --git a/event-processor/vendor/github.com/spf13/pflag/flag.go b/event-processor/vendor/github.com/spf13/pflag/flag.go index 7c058de3..d4dfbc5e 100644 --- a/event-processor/vendor/github.com/spf13/pflag/flag.go +++ b/event-processor/vendor/github.com/spf13/pflag/flag.go @@ -27,23 +27,32 @@ unaffected. Define flags using flag.String(), Bool(), Int(), etc. This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + var ip = flag.Int("flagname", 1234, "help message for flagname") + If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") } + Or you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") + For such flags, the default value is just the initial value of the variable. After all flags are defined, call + flag.Parse() + to parse the command line into the defined flags. Flags may then be used directly. If you're using the flags themselves, they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar) @@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1. The pflag package also defines some new functions that are not in flag, that give one-letter shorthands for flags. You can use these by appending 'P' to the name of any function that defines a flag. + var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") } flag.VarP(&flagval, "varname", "v", "help message") + Shorthand letters can be used with single dashes on the command line. Boolean shorthand flags can be combined with other shorthand flags. Command line flag syntax: + --flag // boolean flags only --flag=x Unlike the flag package, a single dash before an option means something different than a double dash. Single dashes signify a series of shorthand letters for flags. All but the last shorthand letter must be boolean flags. + // boolean flags -f -abc @@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag { func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { flag := f.Lookup(name) if flag == nil { - err := fmt.Errorf("flag accessed but not defined: %s", name) + err := &NotExistError{name: name, messageType: flagNotDefinedMessage} return nil, err } @@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int { func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) @@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) @@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro func (f *FlagSet) MarkHidden(name string) error { flag := f.Lookup(name) if flag == nil { - return fmt.Errorf("flag %q does not exist", name) + return &NotExistError{name: name, messageType: flagNotExistMessage} } flag.Hidden = true return nil @@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error { normalName := f.normalizeFlagName(name) flag, ok := f.formal[normalName] if !ok { - return fmt.Errorf("no such flag -%v", name) + return &NotExistError{name: name, messageType: flagNoSuchFlagMessage} } err := flag.Value.Set(value) if err != nil { - var flagName string - if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { - flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) - } else { - flagName = fmt.Sprintf("--%s", flag.Name) + return &InvalidValueError{ + flag: flag, + value: value, + cause: err, } - return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) } if !flag.Changed { @@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error { normalName := f.normalizeFlagName(name) flag, ok := f.formal[normalName] if !ok { - return fmt.Errorf("no such flag -%v", name) + return &NotExistError{name: name, messageType: flagNoSuchFlagMessage} } if flag.Annotations == nil { flag.Annotations = map[string][]string{} @@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() { func (f *Flag) defaultIsZeroValue() bool { switch f.Value.(type) { case boolFlag: - return f.DefValue == "false" + return f.DefValue == "false" || f.DefValue == "" case *durationValue: // Beginning in Go 1.7, duration zero values are "0s" return f.DefValue == "0" || f.DefValue == "0s" @@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool { case *intSliceValue, *stringSliceValue, *stringArrayValue: return f.DefValue == "[]" default: - switch f.Value.String() { + switch f.DefValue { case "false": return true case "": @@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { name = flag.Value.Type() switch name { - case "bool": + case "bool", "boolfunc": name = "" + case "func": + name = "value" case "float64": name = "float" case "int64": @@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { switch flag.Value.Type() { case "string": line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) - case "bool": + case "bool", "boolfunc": if flag.NoOptDefVal != "true" { line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) } @@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) { CommandLine.VarP(value, name, shorthand, usage) } -// failf prints to standard error a formatted error and usage message and +// fail prints an error message and usage message to standard error and // returns the error. -func (f *FlagSet) failf(format string, a ...interface{}) error { - err := fmt.Errorf(format, a...) +func (f *FlagSet) fail(err error) error { if f.errorHandling != ContinueOnError { fmt.Fprintln(f.Output(), err) f.usage() @@ -934,9 +946,9 @@ func (f *FlagSet) usage() { } } -//--unknown (args will be empty) -//--unknown --next-flag ... (args will be --next-flag ...) -//--unknown arg ... (args will be arg ...) +// --unknown (args will be empty) +// --unknown --next-flag ... (args will be --next-flag ...) +// --unknown arg ... (args will be arg ...) func stripUnknownFlagValue(args []string) []string { if len(args) == 0 { //--unknown @@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin a = args name := s[2:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { - err = f.failf("bad flag syntax: %s", s) + err = f.fail(&InvalidSyntaxError{specifiedFlag: s}) return } @@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin return stripUnknownFlagValue(a), nil default: - err = f.failf("unknown flag: --%s", name) + err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage}) return } } @@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin a = a[1:] } else { // '--flag' (arg was required) - err = f.failf("flag needs an argument: %s", s) + err = f.fail(&ValueRequiredError{ + flag: flag, + specifiedName: name, + }) return } err = fn(flag, value) if err != nil { - f.failf(err.Error()) + f.fail(err) } return } @@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { outArgs = args - if strings.HasPrefix(shorthands, "test.") { + if isGotestShorthandFlag(shorthands) { return } @@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse outArgs = stripUnknownFlagValue(outArgs) return default: - err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) + err = f.fail(&NotExistError{ + name: string(c), + specifiedShorthands: shorthands, + messageType: flagUnknownShorthandFlagMessage, + }) return } } @@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse outArgs = args[1:] } else { // '-f' (arg was required) - err = f.failf("flag needs an argument: %q in -%s", c, shorthands) + err = f.fail(&ValueRequiredError{ + flag: flag, + specifiedName: string(c), + specifiedShorthands: shorthands, + }) return } @@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse err = fn(flag, value) if err != nil { - f.failf(err.Error()) + f.fail(err) } return } @@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error { } f.parsed = true - if len(arguments) < 0 { + if len(arguments) == 0 { return nil } diff --git a/event-processor/vendor/github.com/spf13/pflag/func.go b/event-processor/vendor/github.com/spf13/pflag/func.go new file mode 100644 index 00000000..9f4d88f2 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/pflag/func.go @@ -0,0 +1,37 @@ +package pflag + +// -- func Value +type funcValue func(string) error + +func (f funcValue) Set(s string) error { return f(s) } + +func (f funcValue) Type() string { return "func" } + +func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package + +// Func defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}={value}" (or equivalent) is +// parsed on the command line, with "{value}" as an argument. +func (f *FlagSet) Func(name string, usage string, fn func(string) error) { + f.FuncP(name, "", usage, fn) +} + +// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) { + var val Value = funcValue(fn) + f.VarP(val, name, shorthand, usage) +} + +// Func defines a func flag with specified name, callback function and usage string. +// +// The callback function will be called every time "--{name}={value}" (or equivalent) is +// parsed on the command line, with "{value}" as an argument. +func Func(name string, usage string, fn func(string) error) { + CommandLine.FuncP(name, "", usage, fn) +} + +// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash. +func FuncP(name, shorthand string, usage string, fn func(string) error) { + CommandLine.FuncP(name, shorthand, usage, fn) +} diff --git a/event-processor/vendor/github.com/spf13/pflag/golangflag.go b/event-processor/vendor/github.com/spf13/pflag/golangflag.go index d3dd72b7..f563907e 100644 --- a/event-processor/vendor/github.com/spf13/pflag/golangflag.go +++ b/event-processor/vendor/github.com/spf13/pflag/golangflag.go @@ -10,6 +10,15 @@ import ( "strings" ) +// go test flags prefixes +func isGotestFlag(flag string) bool { + return strings.HasPrefix(flag, "-test.") +} + +func isGotestShorthandFlag(flag string) bool { + return strings.HasPrefix(flag, "test.") +} + // flagValueWrapper implements pflag.Value around a flag.Value. The main // difference here is the addition of the Type method that returns a string // name of the type. As this is generally unknown, we approximate that with @@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { } f.addedGoFlagSets = append(f.addedGoFlagSets, newSet) } + +// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(), +// since by default those are skipped by pflag.Parse(). +// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)` +func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error { + var skippedFlags []string + for _, f := range osArgs { + if isGotestFlag(f) { + skippedFlags = append(skippedFlags, f) + } + } + return goFlagSet.Parse(skippedFlags) +} diff --git a/event-processor/vendor/github.com/spf13/pflag/ipnet_slice.go b/event-processor/vendor/github.com/spf13/pflag/ipnet_slice.go index 6b541aa8..c6e89da1 100644 --- a/event-processor/vendor/github.com/spf13/pflag/ipnet_slice.go +++ b/event-processor/vendor/github.com/spf13/pflag/ipnet_slice.go @@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string { func ipNetSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") - // Emtpy string would cause a slice with one (empty) entry + // Empty string would cause a slice with one (empty) entry if len(val) == 0 { return []net.IPNet{}, nil } diff --git a/event-processor/vendor/github.com/spf13/pflag/text.go b/event-processor/vendor/github.com/spf13/pflag/text.go new file mode 100644 index 00000000..886d5a3d --- /dev/null +++ b/event-processor/vendor/github.com/spf13/pflag/text.go @@ -0,0 +1,81 @@ +package pflag + +import ( + "encoding" + "fmt" + "reflect" +) + +// following is copied from go 1.23.4 flag.go +type textValue struct{ p encoding.TextUnmarshaler } + +func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue { + ptrVal := reflect.ValueOf(p) + if ptrVal.Kind() != reflect.Ptr { + panic("variable value type must be a pointer") + } + defVal := reflect.ValueOf(val) + if defVal.Kind() == reflect.Ptr { + defVal = defVal.Elem() + } + if defVal.Type() != ptrVal.Type().Elem() { + panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem())) + } + ptrVal.Elem().Set(defVal) + return textValue{p} +} + +func (v textValue) Set(s string) error { + return v.p.UnmarshalText([]byte(s)) +} + +func (v textValue) Get() interface{} { + return v.p +} + +func (v textValue) String() string { + if m, ok := v.p.(encoding.TextMarshaler); ok { + if b, err := m.MarshalText(); err == nil { + return string(b) + } + } + return "" +} + +//end of copy + +func (v textValue) Type() string { + return reflect.ValueOf(v.p).Type().Name() +} + +// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name +func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag accessed but not defined: %s", name) + } + if flag.Value.Type() != reflect.TypeOf(out).Name() { + return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type()) + } + return out.UnmarshalText([]byte(flag.Value.String())) +} + +// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p. +func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) { + f.VarP(newTextValue(value, p), name, "", usage) +} + +// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) { + f.VarP(newTextValue(value, p), name, shorthand, usage) +} + +// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p. +func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) { + CommandLine.VarP(newTextValue(value, p), name, "", usage) +} + +// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash. +func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) { + CommandLine.VarP(newTextValue(value, p), name, shorthand, usage) +} diff --git a/event-processor/vendor/github.com/spf13/pflag/time.go b/event-processor/vendor/github.com/spf13/pflag/time.go new file mode 100644 index 00000000..dc024807 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/pflag/time.go @@ -0,0 +1,118 @@ +package pflag + +import ( + "fmt" + "strings" + "time" +) + +// TimeValue adapts time.Time for use as a flag. +type timeValue struct { + *time.Time + formats []string +} + +func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue { + *p = val + return &timeValue{ + Time: p, + formats: formats, + } +} + +// Set time.Time value from string based on accepted formats. +func (d *timeValue) Set(s string) error { + s = strings.TrimSpace(s) + for _, f := range d.formats { + v, err := time.Parse(f, s) + if err != nil { + continue + } + *d.Time = v + return nil + } + + formatsString := "" + for i, f := range d.formats { + if i > 0 { + formatsString += ", " + } + formatsString += fmt.Sprintf("`%s`", f) + } + + return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString) +} + +// Type name for time.Time flags. +func (d *timeValue) Type() string { + return "time" +} + +func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) } + +// GetTime return the time value of a flag with the given name +func (f *FlagSet) GetTime(name string) (time.Time, error) { + flag := f.Lookup(name) + if flag == nil { + err := fmt.Errorf("flag accessed but not defined: %s", name) + return time.Time{}, err + } + + if flag.Value.Type() != "time" { + err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type()) + return time.Time{}, err + } + + val, ok := flag.Value.(*timeValue) + if !ok { + return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value) + } + + return *val.Time, nil +} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) { + f.TimeVarP(p, name, "", value, formats, usage) +} + +// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) { + f.VarP(newTimeValue(value, p, formats), name, shorthand, usage) +} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) { + CommandLine.TimeVarP(p, name, "", value, formats, usage) +} + +// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash. +func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) { + CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage) +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time { + return f.TimeP(name, "", value, formats, usage) +} + +// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time { + p := new(time.Time) + f.TimeVarP(p, name, shorthand, value, formats, usage) + return p +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func Time(name string, value time.Time, formats []string, usage string) *time.Time { + return CommandLine.TimeP(name, "", value, formats, usage) +} + +// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash. +func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time { + return CommandLine.TimeP(name, shorthand, value, formats, usage) +} diff --git a/event-processor/vendor/github.com/spf13/viper/.envrc b/event-processor/vendor/github.com/spf13/viper/.envrc index 3ce7171a..2e0f9f5f 100644 --- a/event-processor/vendor/github.com/spf13/viper/.envrc +++ b/event-processor/vendor/github.com/spf13/viper/.envrc @@ -1,4 +1,4 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" fi use flake . --impure diff --git a/event-processor/vendor/github.com/spf13/viper/.golangci.yaml b/event-processor/vendor/github.com/spf13/viper/.golangci.yaml index acd9eeba..474f4163 100644 --- a/event-processor/vendor/github.com/spf13/viper/.golangci.yaml +++ b/event-processor/vendor/github.com/spf13/viper/.golangci.yaml @@ -7,8 +7,16 @@ linters-settings: - standard - default - prefix(github.com/spf13/viper) - golint: - min-confidence: 0 + gocritic: + # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage. + enabled-tags: + - diagnostic + - experimental + - opinionated + - style + disabled-checks: + - importShadow + - unnamedResult goimports: local-prefixes: github.com/spf13/viper @@ -20,8 +28,9 @@ linters: - dupl - durationcheck - exhaustive - - exportloopref - gci + - gocritic + - godot - gofmt - gofumpt - goimports @@ -62,9 +71,7 @@ linters: # - gochecknoinits # - gocognit # - goconst - # - gocritic # - gocyclo - # - godot # - gosec # - gosimple # - ifshort diff --git a/event-processor/vendor/github.com/spf13/viper/README.md b/event-processor/vendor/github.com/spf13/viper/README.md index 78102fbe..769a5d90 100644 --- a/event-processor/vendor/github.com/spf13/viper/README.md +++ b/event-processor/vendor/github.com/spf13/viper/README.md @@ -3,7 +3,8 @@ > > **Thank you!** -![Viper](.github/logo.png?raw=true) +![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e) + [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration) [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go) @@ -11,7 +12,7 @@ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-61CFDD.svg?style=flat-square) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper) **Go configuration with fangs!** @@ -39,7 +40,7 @@ Many Go projects are built using Viper including: go get github.com/spf13/viper ``` -**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. +**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies. ## What is Viper? @@ -418,7 +419,9 @@ in a Key/Value store such as etcd or Consul. These values take precedence over default values, but are overridden by configuration values retrieved from disk, flags, or environment variables. -Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve +Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`. + +Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve configuration from the K/V store, which means that you can store your configuration values encrypted and have them automatically decrypted if you have the correct gpg keyring. Encryption is optional. @@ -430,7 +433,7 @@ independently of it. K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001. ```bash -$ go get github.com/bketelsen/crypt/bin/crypt +$ go get github.com/sagikazarmark/crypt/bin/crypt $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json ``` @@ -563,6 +566,9 @@ 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 has been provided. +The zero value will also be returned if the value is set, but fails to parse +as the requested type. + Example: ```go viper.GetString("logfile") // case-insensitive Setting & Getting @@ -797,7 +803,7 @@ if err != nil { } ``` -Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. +Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. ### Decoding custom formats @@ -831,13 +837,15 @@ func yamlStringSettings() string { ## Viper or Vipers? -Viper comes ready to use out of the box. There is no configuration or -initialization needed to begin using Viper. Since most applications will want -to use a single central repository for their configuration, the viper package -provides this. It is similar to a singleton. +Viper comes with a global instance (singleton) out of the box. + +Although it makes setting up configuration easy, +using it is generally discouraged as it makes testing harder and can lead to unexpected behavior. + +The best practice is to initialize a Viper instance and pass that around when necessary. -In all of the examples above, they demonstrate using viper in its singleton -style approach. +The global instance _MAY_ be deprecated in the future. +See [#1855](https://github.com/spf13/viper/issues/1855) for more details. ### Working with multiple vipers diff --git a/event-processor/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/event-processor/vendor/github.com/spf13/viper/TROUBLESHOOTING.md index c4e36c68..b68993d4 100644 --- a/event-processor/vendor/github.com/spf13/viper/TROUBLESHOOTING.md +++ b/event-processor/vendor/github.com/spf13/viper/TROUBLESHOOTING.md @@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of: ``` As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`. -Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch). +Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch). The solution is easy: switch to using Go Modules. -Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that. +Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that. **tl;dr* `export GO111MODULE=on` diff --git a/event-processor/vendor/github.com/spf13/viper/UPDATES.md b/event-processor/vendor/github.com/spf13/viper/UPDATES.md new file mode 100644 index 00000000..ccf413ed --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/UPDATES.md @@ -0,0 +1,126 @@ +# Update Log + +**This document details any major updates required to use new features or improvements in Viper.** + +## v1.20.x + +### New file searching API + +Viper now includes a new file searching API that allows users to customize how Viper looks for config files. + +Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation: + +```go +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} +``` + +It is supposed to return a list of paths to config files. + +The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood. + +You can supply your own implementation using `WithFinder`: + +```go +v := viper.NewWithOptions( + viper.WithFinder(&MyFinder{}), +) +``` + +For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder) +and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package. + +### New encoding API + +Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data: + +```go +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} +``` + +By default, Viper includes the following codecs: + +- JSON +- TOML +- YAML +- Dotenv + +The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding) + +Customizing the encoding layer is possible by providing a custom registry of codecs: + +- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry) +- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry) +- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry) + +You can supply the registry of codecs to Viper using the appropriate `With*Registry` function: + +```go +codecRegistry := viper.NewCodecRegistry() + +codecRegistry.RegisterCodec("myformat", &MyCodec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` + +### BREAKING: HCL, Java properties, INI removed from core + +In order to reduce third-party dependencies, Viper dropped support for the following formats from the core: + +- HCL +- Java properties +- INI + +You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding): + +```go +import ( + "github.com/go-viper/encoding/hcl" + "github.com/go-viper/encoding/javaproperties" + "github.com/go-viper/encoding/ini" +) + +codecRegistry := viper.NewCodecRegistry() + +{ + codec := hcl.Codec{} + + codecRegistry.RegisterCodec("hcl", codec) + codecRegistry.RegisterCodec("tfvars", codec) + +} + +{ + codec := &javaproperties.Codec{} + + codecRegistry.RegisterCodec("properties", codec) + codecRegistry.RegisterCodec("props", codec) + codecRegistry.RegisterCodec("prop", codec) +} + +codecRegistry.RegisterCodec("ini", ini.Codec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` diff --git a/event-processor/vendor/github.com/spf13/viper/encoding.go b/event-processor/vendor/github.com/spf13/viper/encoding.go new file mode 100644 index 00000000..a7da5586 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/encoding.go @@ -0,0 +1,181 @@ +package viper + +import ( + "errors" + "strings" + "sync" + + "github.com/spf13/viper/internal/encoding/dotenv" + "github.com/spf13/viper/internal/encoding/json" + "github.com/spf13/viper/internal/encoding/toml" + "github.com/spf13/viper/internal/encoding/yaml" +) + +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} + +// TODO: consider adding specific errors for not found scenarios + +// EncoderRegistry returns an [Encoder] for a given format. +// +// Format is case-insensitive. +// +// [EncoderRegistry] returns an error if no [Encoder] is registered for the format. +type EncoderRegistry interface { + Encoder(format string) (Encoder, error) +} + +// DecoderRegistry returns an [Decoder] for a given format. +// +// Format is case-insensitive. +// +// [DecoderRegistry] returns an error if no [Decoder] is registered for the format. +type DecoderRegistry interface { + Decoder(format string) (Decoder, error) +} + +// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces. +type CodecRegistry interface { + EncoderRegistry + DecoderRegistry +} + +// WithEncoderRegistry sets a custom [EncoderRegistry]. +func WithEncoderRegistry(r EncoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + }) +} + +// WithDecoderRegistry sets a custom [DecoderRegistry]. +func WithDecoderRegistry(r DecoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.decoderRegistry = r + }) +} + +// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry]. +func WithCodecRegistry(r CodecRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + v.decoderRegistry = r + }) +} + +// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s. +type DefaultCodecRegistry struct { + codecs map[string]Codec + + mu sync.RWMutex + once sync.Once +} + +// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s. +func NewCodecRegistry() *DefaultCodecRegistry { + r := &DefaultCodecRegistry{} + + r.init() + + return r +} + +func (r *DefaultCodecRegistry) init() { + r.once.Do(func() { + r.codecs = map[string]Codec{} + }) +} + +// RegisterCodec registers a custom [Codec]. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error { + r.init() + + r.mu.Lock() + defer r.mu.Unlock() + + r.codecs[strings.ToLower(format)] = codec + + return nil +} + +// Encoder implements the [EncoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) { + encoder, ok := r.codec(format) + if !ok { + return nil, errors.New("encoder not found for this format") + } + + return encoder, nil +} + +// Decoder implements the [DecoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) { + decoder, ok := r.codec(format) + if !ok { + return nil, errors.New("decoder not found for this format") + } + + return decoder, nil +} + +func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) { + r.mu.Lock() + defer r.mu.Unlock() + + format = strings.ToLower(format) + + if r.codecs != nil { + codec, ok := r.codecs[format] + if ok { + return codec, true + } + } + + switch format { + case "yaml", "yml": + return yaml.Codec{}, true + + case "json": + return json.Codec{}, true + + case "toml": + return toml.Codec{}, true + + case "dotenv", "env": + return &dotenv.Codec{}, true + } + + return nil, false +} diff --git a/event-processor/vendor/github.com/spf13/viper/experimental.go b/event-processor/vendor/github.com/spf13/viper/experimental.go new file mode 100644 index 00000000..6e19e8a1 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/experimental.go @@ -0,0 +1,8 @@ +package viper + +// ExperimentalBindStruct tells Viper to use the new bind struct feature. +func ExperimentalBindStruct() Option { + return optionFunc(func(v *Viper) { + v.experimentalBindStruct = true + }) +} diff --git a/event-processor/vendor/github.com/spf13/viper/file.go b/event-processor/vendor/github.com/spf13/viper/file.go new file mode 100644 index 00000000..50a40581 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/file.go @@ -0,0 +1,104 @@ +package viper + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/sagikazarmark/locafero" + "github.com/spf13/afero" +) + +// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files. +func ExperimentalFinder() Option { + return optionFunc(func(v *Viper) { + v.experimentalFinder = true + }) +} + +// Search for a config file. +func (v *Viper) findConfigFile() (string, error) { + finder := v.finder + + if finder == nil && v.experimentalFinder { + 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, + } + } + + if finder != nil { + return v.findConfigFileWithFinder(finder) + } + + return v.findConfigFileOld() +} + +func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) { + results, err := finder.Find(v.fs) + if err != nil { + return "", err + } + + if len(results) == 0 { + return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} + } + + // We call clean on the final result to ensure that the path is in its canonical form. + // This is mostly for consistent path handling and to make sure tests pass. + return results[0], nil +} + +// Search all configPaths for any config file. +// Returns the first path that exists (and is a config file). +func (v *Viper) findConfigFileOld() (string, error) { + v.logger.Info("searching for config in paths", "paths", v.configPaths) + + for _, cp := range v.configPaths { + file := v.searchInPath(cp) + if file != "" { + return file, nil + } + } + return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} +} + +func (v *Viper) searchInPath(in string) (filename string) { + v.logger.Debug("searching for config in path", "path", in) + for _, ext := range SupportedExts { + v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext)) + if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b { + v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext)) + return filepath.Join(in, v.configName+"."+ext) + } + } + + if v.configType != "" { + if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b { + return filepath.Join(in, v.configName) + } + } + + return "" +} + +// exists checks if file exists. +func exists(fs afero.Fs, path string) (bool, error) { + stat, err := fs.Stat(path) + if err == nil { + return !stat.IsDir(), nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} diff --git a/event-processor/vendor/github.com/spf13/viper/finder.go b/event-processor/vendor/github.com/spf13/viper/finder.go new file mode 100644 index 00000000..9b203ea6 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/finder.go @@ -0,0 +1,55 @@ +package viper + +import ( + "errors" + + "github.com/spf13/afero" +) + +// WithFinder sets a custom [Finder]. +func WithFinder(f Finder) Option { + return optionFunc(func(v *Viper) { + if f == nil { + return + } + + v.finder = f + }) +} + +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} + +// Finders combines multiple finders into one. +func Finders(finders ...Finder) Finder { + return &combinedFinder{finders: finders} +} + +// combinedFinder is a Finder that combines multiple finders. +type combinedFinder struct { + finders []Finder +} + +// Find implements the [Finder] interface. +func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) { + var results []string + var errs []error + + for _, finder := range c.finders { + if finder == nil { + continue + } + + r, err := finder.Find(fsys) + if err != nil { + errs = append(errs, err) + continue + } + + results = append(results, r...) + } + + return results, errors.Join(errs...) +} diff --git a/event-processor/vendor/github.com/spf13/viper/flags.go b/event-processor/vendor/github.com/spf13/viper/flags.go index ddb4da60..de033ed5 100644 --- a/event-processor/vendor/github.com/spf13/viper/flags.go +++ b/event-processor/vendor/github.com/spf13/viper/flags.go @@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) { } // pflagValue is a wrapper around *pflag.flag -// that implements FlagValue +// that implements FlagValue. type pflagValue struct { flag *pflag.Flag } diff --git a/event-processor/vendor/github.com/spf13/viper/flake.lock b/event-processor/vendor/github.com/spf13/viper/flake.lock index 78da5109..d76dfbdd 100644 --- a/event-processor/vendor/github.com/spf13/viper/flake.lock +++ b/event-processor/vendor/github.com/spf13/viper/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1724763216, + "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=", + "owner": "cachix", + "repo": "devenv", + "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1687972261, - "narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "e85df562088573305e55906eaa964341f8cb0d9f", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1687762428, - "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -56,12 +134,33 @@ } }, "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -79,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -92,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { "inputs": { - "lowdown-src": "lowdown-src", "nixpkgs": [ "devenv", + "cachix", + "devenv", + "poetry2nix", "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -150,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1685564631, - "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=", + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -184,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1678872516, - "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.11", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1687886075, - "narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1724748588, + "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a565059a348422af5af9026b5174dc5c0dcefdae", + "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99", "type": "github" }, "original": { @@ -214,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -229,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1686050334, - "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -246,7 +433,37 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, diff --git a/event-processor/vendor/github.com/spf13/viper/flake.nix b/event-processor/vendor/github.com/spf13/viper/flake.nix index 9b26c3fc..52ad7d58 100644 --- a/event-processor/vendor/github.com/spf13/viper/flake.nix +++ b/event-processor/vendor/github.com/spf13/viper/flake.nix @@ -20,6 +20,7 @@ default = { languages = { go.enable = true; + go.package = pkgs.go_1_23; }; pre-commit.hooks = { diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/decoder.go deleted file mode 100644 index 8a7b1dbc..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/decoder.go +++ /dev/null @@ -1,61 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Decoder decodes the contents of b into v. -// It's primarily used for decoding contents of a file into a map[string]any. -type Decoder interface { - Decode(b []byte, v map[string]any) error -} - -const ( - // ErrDecoderNotFound is returned when there is no decoder registered for a format. - ErrDecoderNotFound = encodingError("decoder not found for this format") - - // ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format. - ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format") -) - -// DecoderRegistry can choose an appropriate Decoder based on the provided format. -type DecoderRegistry struct { - decoders map[string]Decoder - - mu sync.RWMutex -} - -// NewDecoderRegistry returns a new, initialized DecoderRegistry. -func NewDecoderRegistry() *DecoderRegistry { - return &DecoderRegistry{ - decoders: make(map[string]Decoder), - } -} - -// RegisterDecoder registers a Decoder for a format. -// Registering a Decoder for an already existing format is not supported. -func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.decoders[format]; ok { - return ErrDecoderFormatAlreadyRegistered - } - - e.decoders[format] = enc - - return nil -} - -// Decode calls the underlying Decoder based on the format. -func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error { - e.mu.RLock() - decoder, ok := e.decoders[format] - e.mu.RUnlock() - - if !ok { - return ErrDecoderNotFound - } - - return decoder.Decode(b, v) -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go index 1340c730..8bfe0a9d 100644 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go +++ b/event-processor/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go @@ -8,8 +8,8 @@ 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]any, m map[string]any, prefix string, delimiter string) map[string]any { +// TODO: move it to a common place. +func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { if shadow != nil && prefix != "" && shadow[prefix] != nil { // prefix is shadowed => nothing more to flatten return shadow diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/encoder.go deleted file mode 100644 index 65958596..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/encoder.go +++ /dev/null @@ -1,60 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Encoder encodes the contents of v into a byte representation. -// It's primarily used for encoding a map[string]any into a file format. -type Encoder interface { - Encode(v map[string]any) ([]byte, error) -} - -const ( - // ErrEncoderNotFound is returned when there is no encoder registered for a format. - ErrEncoderNotFound = encodingError("encoder not found for this format") - - // ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format. - ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format") -) - -// EncoderRegistry can choose an appropriate Encoder based on the provided format. -type EncoderRegistry struct { - encoders map[string]Encoder - - mu sync.RWMutex -} - -// NewEncoderRegistry returns a new, initialized EncoderRegistry. -func NewEncoderRegistry() *EncoderRegistry { - return &EncoderRegistry{ - encoders: make(map[string]Encoder), - } -} - -// RegisterEncoder registers an Encoder for a format. -// Registering a Encoder for an already existing format is not supported. -func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.encoders[format]; ok { - return ErrEncoderFormatAlreadyRegistered - } - - e.encoders[format] = enc - - return nil -} - -func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) { - e.mu.RLock() - encoder, ok := e.encoders[format] - e.mu.RUnlock() - - if !ok { - return nil, ErrEncoderNotFound - } - - return encoder.Encode(v) -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/error.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/error.go deleted file mode 100644 index e4cde02d..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/error.go +++ /dev/null @@ -1,7 +0,0 @@ -package encoding - -type encodingError string - -func (e encodingError) Error() string { - return string(e) -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go deleted file mode 100644 index d7fa8a1b..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go +++ /dev/null @@ -1,40 +0,0 @@ -package hcl - -import ( - "bytes" - "encoding/json" - - "github.com/hashicorp/hcl" - "github.com/hashicorp/hcl/hcl/printer" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding. -// TODO: add printer config to the codec? -type Codec struct{} - -func (Codec) Encode(v map[string]any) ([]byte, error) { - b, err := json.Marshal(v) - if err != nil { - return nil, err - } - - // TODO: use printer.Format? Is the trailing newline an issue? - - ast, err := hcl.Parse(string(b)) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - - err = printer.Fprint(&buf, ast.Node) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (Codec) Decode(b []byte, v map[string]any) error { - return hcl.Unmarshal(b, &v) -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go deleted file mode 100644 index d91cf59d..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go +++ /dev/null @@ -1,99 +0,0 @@ -package ini - -import ( - "bytes" - "sort" - "strings" - - "github.com/spf13/cast" - "gopkg.in/ini.v1" -) - -// LoadOptions contains all customized options used for load data source(s). -// This type is added here for convenience: this way consumers can import a single package called "ini". -type LoadOptions = ini.LoadOptions - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding. -type Codec struct { - KeyDelimiter string - LoadOptions LoadOptions -} - -func (c Codec) Encode(v map[string]any) ([]byte, error) { - cfg := ini.Empty() - ini.PrettyFormat = false - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - sectionName, keyName := "", key - - lastSep := strings.LastIndex(key, ".") - if lastSep != -1 { - sectionName = key[:(lastSep)] - keyName = key[(lastSep + 1):] - } - - // TODO: is this a good idea? - if sectionName == "default" { - sectionName = "" - } - - cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key])) - } - - var buf bytes.Buffer - - _, err := cfg.WriteTo(&buf) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c Codec) Decode(b []byte, v map[string]any) error { - cfg := ini.Empty(c.LoadOptions) - - err := cfg.Append(b) - if err != nil { - return err - } - - sections := cfg.Sections() - - for i := 0; i < len(sections); i++ { - section := sections[i] - keys := section.Keys() - - for j := 0; j < len(keys); j++ { - key := keys[j] - value := cfg.Section(section.Name()).Key(key.Name()).String() - - deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter())) - - // set innermost value - deepestMap[key.Name()] = value - } - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go deleted file mode 100644 index c1919a38..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package ini - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// 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]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]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// 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]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]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go deleted file mode 100644 index e92e5172..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go +++ /dev/null @@ -1,86 +0,0 @@ -package javaproperties - -import ( - "bytes" - "sort" - "strings" - - "github.com/magiconair/properties" - "github.com/spf13/cast" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding. -type Codec struct { - KeyDelimiter string - - // Store read properties on the object so that we can write back in order with comments. - // This will only be used if the configuration read is a properties file. - // TODO: drop this feature in v2 - // TODO: make use of the global properties object optional - Properties *properties.Properties -} - -func (c *Codec) Encode(v map[string]any) ([]byte, error) { - if c.Properties == nil { - c.Properties = properties.NewProperties() - } - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - _, _, err := c.Properties.Set(key, cast.ToString(flattened[key])) - if err != nil { - return nil, err - } - } - - var buf bytes.Buffer - - _, err := c.Properties.WriteComment(&buf, "#", properties.UTF8) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -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 { - return err - } - - for _, key := range c.Properties.Keys() { - // ignore existence check: we know it's there - value, _ := c.Properties.Get(key) - - // recursively build nested maps - path := strings.Split(key, c.keyDelimiter()) - lastKey := strings.ToLower(path[len(path)-1]) - deepestMap := deepSearch(v, path[0:len(path)-1]) - - // set innermost value - deepestMap[lastKey] = value - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go deleted file mode 100644 index 8386920a..00000000 --- a/event-processor/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package javaproperties - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// 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]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]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// 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]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]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct.go b/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct.go new file mode 100644 index 00000000..89302c21 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct.go @@ -0,0 +1,5 @@ +//go:build viper_bind_struct + +package features + +const BindStruct = true diff --git a/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go b/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go new file mode 100644 index 00000000..edfaf73b --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go @@ -0,0 +1,5 @@ +//go:build !viper_bind_struct + +package features + +const BindStruct = false diff --git a/event-processor/vendor/github.com/spf13/viper/internal/features/finder.go b/event-processor/vendor/github.com/spf13/viper/internal/features/finder.go new file mode 100644 index 00000000..983ea3a9 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/internal/features/finder.go @@ -0,0 +1,5 @@ +//go:build viper_finder + +package features + +const Finder = true diff --git a/event-processor/vendor/github.com/spf13/viper/internal/features/finder_default.go b/event-processor/vendor/github.com/spf13/viper/internal/features/finder_default.go new file mode 100644 index 00000000..89bcb06e --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/internal/features/finder_default.go @@ -0,0 +1,5 @@ +//go:build !viper_finder + +package features + +const Finder = false diff --git a/event-processor/vendor/github.com/spf13/viper/logger.go b/event-processor/vendor/github.com/spf13/viper/logger.go index 8938053b..828042f2 100644 --- a/event-processor/vendor/github.com/spf13/viper/logger.go +++ b/event-processor/vendor/github.com/spf13/viper/logger.go @@ -2,46 +2,9 @@ package viper import ( "context" - - slog "github.com/sagikazarmark/slog-shim" + "log/slog" ) -// 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 ...any) - - // Debug logs a Debug event. - // - // A verbose series of information events. - // They are useful when debugging the system. - Debug(msg string, keyvals ...any) - - // Info logs an Info event. - // - // General information about what's happening inside the system. - Info(msg string, keyvals ...any) - - // Warn logs a Warn(ing) event. - // - // Non-critical events that should be looked at. - 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 ...any) -} - // WithLogger sets a custom logger. func WithLogger(l *slog.Logger) Option { return optionFunc(func(v *Viper) { diff --git a/event-processor/vendor/github.com/spf13/viper/remote.go b/event-processor/vendor/github.com/spf13/viper/remote.go new file mode 100644 index 00000000..bdde7de2 --- /dev/null +++ b/event-processor/vendor/github.com/spf13/viper/remote.go @@ -0,0 +1,256 @@ +package viper + +import ( + "bytes" + "fmt" + "io" + "reflect" + "slices" +) + +// SupportedRemoteProviders are universally supported remote providers. +var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} + +func resetRemote() { + SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} +} + +type remoteConfigFactory interface { + Get(rp RemoteProvider) (io.Reader, error) + Watch(rp RemoteProvider) (io.Reader, error) + WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) +} + +type RemoteResponse struct { + Value []byte + Error error +} + +// RemoteConfig is optional, see the remote package. +var RemoteConfig remoteConfigFactory + +// UnsupportedRemoteProviderError denotes encountering an unsupported remote +// provider. Currently only etcd and Consul are supported. +type UnsupportedRemoteProviderError string + +// Error returns the formatted remote provider error. +func (str UnsupportedRemoteProviderError) Error() string { + return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) +} + +// RemoteConfigError denotes encountering an error while trying to +// pull the configuration from the remote provider. +type RemoteConfigError string + +// Error returns the formatted remote provider error. +func (rce RemoteConfigError) Error() string { + return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) +} + +type defaultRemoteProvider struct { + provider string + endpoint string + path string + secretKeyring string +} + +func (rp defaultRemoteProvider) Provider() string { + return rp.provider +} + +func (rp defaultRemoteProvider) Endpoint() string { + return rp.endpoint +} + +func (rp defaultRemoteProvider) Path() string { + return rp.path +} + +func (rp defaultRemoteProvider) SecretKeyring() string { + return rp.secretKeyring +} + +// RemoteProvider stores the configuration necessary +// to connect to a remote key/value store. +// Optional secretKeyring to unencrypt encrypted values +// can be provided. +type RemoteProvider interface { + Provider() string + Endpoint() string + Path() string + SecretKeyring() string +} + +// AddRemoteProvider adds a remote configuration source. +// Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +func AddRemoteProvider(provider, endpoint, path string) error { + return v.AddRemoteProvider(provider, endpoint, path) +} + +func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { + if !slices.Contains(SupportedRemoteProviders, provider) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +// AddSecureRemoteProvider adds a remote configuration source. +// Secure Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt. +func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) +} + +func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + if !slices.Contains(SupportedRemoteProviders, provider) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + secretKeyring: secretkeyring, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { + for _, y := range v.remoteProviders { + if reflect.DeepEqual(y, p) { + return true + } + } + return false +} + +// ReadRemoteConfig attempts to get configuration from a remote source +// and read it in the remote configuration registry. +func ReadRemoteConfig() error { return v.ReadRemoteConfig() } + +func (v *Viper) ReadRemoteConfig() error { + return v.getKeyValueConfig() +} + +func WatchRemoteConfig() error { return v.WatchRemoteConfig() } +func (v *Viper) WatchRemoteConfig() error { + return v.watchKeyValueConfig() +} + +func (v *Viper) WatchRemoteConfigOnChannel() error { + return v.watchKeyValueConfigOnChannel() +} + +// Retrieve the first found remote configuration. +func (v *Viper) getKeyValueConfig() error { + if RemoteConfig == nil { + return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") + } + + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.getRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) + + continue + } + + v.kvstore = val + + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Get(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfigOnChannel() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + respc, _ := RemoteConfig.WatchChannel(rp) + // Todo: Add quit channel + go func(rc <-chan *RemoteResponse) { + for { + b := <-rc + reader := bytes.NewReader(b.Value) + v.unmarshalReader(reader, v.kvstore) + } + }(respc) + return nil + } + return RemoteConfigError("No Files Found") +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfig() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.watchRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) + + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Watch(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} diff --git a/event-processor/vendor/github.com/spf13/viper/util.go b/event-processor/vendor/github.com/spf13/viper/util.go index 52116ac4..2a08074b 100644 --- a/event-processor/vendor/github.com/spf13/viper/util.go +++ b/event-processor/vendor/github.com/spf13/viper/util.go @@ -12,13 +12,13 @@ package viper import ( "fmt" + "log/slog" "os" "path/filepath" "runtime" "strings" "unicode" - slog "github.com/sagikazarmark/slog-shim" "github.com/spf13/cast" ) @@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string { return "" } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - func userHomeDir() string { if runtime.GOOS == "windows" { home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") @@ -156,7 +147,7 @@ func safeMul(a, b uint) uint { return c } -// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes +// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes. func parseSizeInBytes(sizeStr string) uint { sizeStr = strings.TrimSpace(sizeStr) lastChar := len(sizeStr) - 1 diff --git a/event-processor/vendor/github.com/spf13/viper/viper.go b/event-processor/vendor/github.com/spf13/viper/viper.go index c1eab71b..a58d757b 100644 --- a/event-processor/vendor/github.com/spf13/viper/viper.go +++ b/event-processor/vendor/github.com/spf13/viper/viper.go @@ -25,29 +25,23 @@ import ( "errors" "fmt" "io" + "log/slog" "os" "path/filepath" "reflect" + "slices" "strconv" "strings" "sync" "time" "github.com/fsnotify/fsnotify" - "github.com/mitchellh/mapstructure" - slog "github.com/sagikazarmark/slog-shim" + "github.com/go-viper/mapstructure/v2" "github.com/spf13/afero" "github.com/spf13/cast" "github.com/spf13/pflag" - "github.com/spf13/viper/internal/encoding" - "github.com/spf13/viper/internal/encoding/dotenv" - "github.com/spf13/viper/internal/encoding/hcl" - "github.com/spf13/viper/internal/encoding/ini" - "github.com/spf13/viper/internal/encoding/javaproperties" - "github.com/spf13/viper/internal/encoding/json" - "github.com/spf13/viper/internal/encoding/toml" - "github.com/spf13/viper/internal/encoding/yaml" + "github.com/spf13/viper/internal/features" ) // ConfigMarshalError happens when failing to marshal the configuration. @@ -62,24 +56,10 @@ func (e ConfigMarshalError) Error() string { var v *Viper -type RemoteResponse struct { - Value []byte - Error error -} - func init() { v = New() } -type remoteConfigFactory interface { - Get(rp RemoteProvider) (io.Reader, error) - Watch(rp RemoteProvider) (io.Reader, error) - WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) -} - -// RemoteConfig is optional, see the remote package -var RemoteConfig remoteConfigFactory - // UnsupportedConfigError denotes encountering an unsupported // configuration filetype. type UnsupportedConfigError string @@ -89,24 +69,6 @@ func (str UnsupportedConfigError) Error() string { return fmt.Sprintf("Unsupported Config Type %q", string(str)) } -// UnsupportedRemoteProviderError denotes encountering an unsupported remote -// provider. Currently only etcd and Consul are supported. -type UnsupportedRemoteProviderError string - -// Error returns the formatted remote provider error. -func (str UnsupportedRemoteProviderError) Error() string { - return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) -} - -// RemoteConfigError denotes encountering an error while trying to -// pull the configuration from the remote provider. -type RemoteConfigError string - -// Error returns the formatted remote provider error -func (rce RemoteConfigError) Error() string { - return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) -} - // ConfigFileNotFoundError denotes failing to find configuration file. type ConfigFileNotFoundError struct { name, locations string @@ -126,7 +88,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string { } // A DecoderConfigOption can be passed to viper.Unmarshal to configure -// mapstructure.DecoderConfig options +// mapstructure.DecoderConfig options. type DecoderConfigOption func(*mapstructure.DecoderConfig) // DecodeHook returns a DecoderConfigOption which overrides the default @@ -189,6 +151,8 @@ type Viper struct { // The filesystem to read config from. fs afero.Fs + finder Finder + // A set of remote providers to search for the configuration remoteProviders []*defaultRemoteProvider @@ -199,9 +163,6 @@ type Viper struct { configPermissions os.FileMode envPrefix string - // Specific commands for ini parsing - iniLoadOptions ini.LoadOptions - automaticEnvApplied bool envKeyReplacer StringReplacer allowEmptyEnv bool @@ -220,9 +181,13 @@ type Viper struct { logger *slog.Logger - // TODO: should probably be protected with a mutex - encoderRegistry *encoding.EncoderRegistry - decoderRegistry *encoding.DecoderRegistry + encoderRegistry EncoderRegistry + decoderRegistry DecoderRegistry + + decodeHook mapstructure.DecodeHookFunc + + experimentalFinder bool + experimentalBindStruct bool } // New returns an initialized Viper instance. @@ -243,7 +208,13 @@ func New() *Viper { v.typeByDefValue = false v.logger = slog.New(&discardHandler{}) - v.resetEncoding() + codecRegistry := NewCodecRegistry() + + v.encoderRegistry = codecRegistry + v.decoderRegistry = codecRegistry + + v.experimentalFinder = features.Finder + v.experimentalBindStruct = features.BindStruct return v } @@ -279,10 +250,25 @@ type StringReplacer interface { // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys. func EnvKeyReplacer(r StringReplacer) Option { return optionFunc(func(v *Viper) { + if r == nil { + return + } + v.envKeyReplacer = r }) } +// WithDecodeHook sets a default decode hook for mapstructure. +func WithDecodeHook(h mapstructure.DecodeHookFunc) Option { + return optionFunc(func(v *Viper) { + if h == nil { + return + } + + v.decodeHook = h + }) +} + // NewWithOptions creates a new Viper instance. func NewWithOptions(opts ...Option) *Viper { v := New() @@ -291,138 +277,32 @@ func NewWithOptions(opts ...Option) *Viper { opt.apply(v) } - v.resetEncoding() - return v } +// SetOptions sets the options on the global Viper instance. +// +// Be careful when using this function: subsequent calls may override options you set. +// It's always better to use a local Viper instance. +func SetOptions(opts ...Option) { + for _, opt := range opts { + opt.apply(v) + } +} + // Reset is intended for testing, will reset all to default settings. // In the public interface for the viper package so applications // can use it in their testing as well. func Reset() { v = New() SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} - SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} -} - -// TODO: make this lazy initialization instead -func (v *Viper) resetEncoding() { - encoderRegistry := encoding.NewEncoderRegistry() - decoderRegistry := encoding.NewDecoderRegistry() - - { - codec := yaml.Codec{} - - encoderRegistry.RegisterEncoder("yaml", codec) - decoderRegistry.RegisterDecoder("yaml", codec) - - encoderRegistry.RegisterEncoder("yml", codec) - decoderRegistry.RegisterDecoder("yml", codec) - } - - { - codec := json.Codec{} - - encoderRegistry.RegisterEncoder("json", codec) - decoderRegistry.RegisterDecoder("json", codec) - } - - { - codec := toml.Codec{} - - encoderRegistry.RegisterEncoder("toml", codec) - decoderRegistry.RegisterDecoder("toml", codec) - } - - { - codec := hcl.Codec{} - - encoderRegistry.RegisterEncoder("hcl", codec) - decoderRegistry.RegisterDecoder("hcl", codec) - - encoderRegistry.RegisterEncoder("tfvars", codec) - decoderRegistry.RegisterDecoder("tfvars", codec) - } - - { - codec := ini.Codec{ - KeyDelimiter: v.keyDelim, - LoadOptions: v.iniLoadOptions, - } - - encoderRegistry.RegisterEncoder("ini", codec) - decoderRegistry.RegisterDecoder("ini", codec) - } - - { - codec := &javaproperties.Codec{ - KeyDelimiter: v.keyDelim, - } - - encoderRegistry.RegisterEncoder("properties", codec) - decoderRegistry.RegisterDecoder("properties", codec) - - encoderRegistry.RegisterEncoder("props", codec) - decoderRegistry.RegisterDecoder("props", codec) - - encoderRegistry.RegisterEncoder("prop", codec) - decoderRegistry.RegisterDecoder("prop", codec) - } - - { - codec := &dotenv.Codec{} - encoderRegistry.RegisterEncoder("dotenv", codec) - decoderRegistry.RegisterDecoder("dotenv", codec) - - encoderRegistry.RegisterEncoder("env", codec) - decoderRegistry.RegisterDecoder("env", codec) - } - - v.encoderRegistry = encoderRegistry - v.decoderRegistry = decoderRegistry -} - -type defaultRemoteProvider struct { - provider string - endpoint string - path string - secretKeyring string -} - -func (rp defaultRemoteProvider) Provider() string { - return rp.provider -} - -func (rp defaultRemoteProvider) Endpoint() string { - return rp.endpoint -} - -func (rp defaultRemoteProvider) Path() string { - return rp.path -} - -func (rp defaultRemoteProvider) SecretKeyring() string { - return rp.secretKeyring -} - -// RemoteProvider stores the configuration necessary -// to connect to a remote key/value store. -// Optional secretKeyring to unencrypt encrypted values -// can be provided. -type RemoteProvider interface { - Provider() string - Endpoint() string - Path() string - SecretKeyring() string + resetRemote() } // SupportedExts are universally supported extensions. var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} -// SupportedRemoteProviders are universally supported remote providers. -var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} - // OnConfigChange sets the event handler that is called when a config file changes. func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } @@ -439,7 +319,7 @@ func (v *Viper) WatchConfig() { initWG := sync.WaitGroup{} initWG.Add(1) go func() { - watcher, err := newWatcher() + watcher, err := fsnotify.NewWatcher() if err != nil { v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err)) os.Exit(1) @@ -573,90 +453,20 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile } func AddConfigPath(in string) { v.AddConfigPath(in) } func (v *Viper) AddConfigPath(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath")) + } + if in != "" { absin := absPathify(v.logger, in) v.logger.Info("adding path to search paths", "path", absin) - if !stringInSlice(absin, v.configPaths) { + if !slices.Contains(v.configPaths, absin) { v.configPaths = append(v.configPaths, absin) } } } -// AddRemoteProvider adds a remote configuration source. -// Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp" -func AddRemoteProvider(provider, endpoint, path string) error { - return v.AddRemoteProvider(provider, endpoint, path) -} - -func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -// AddSecureRemoteProvider adds a remote configuration source. -// Secure Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port consul requires ip:port -// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp" -// Secure Remote Providers are implemented with github.com/bketelsen/crypt -func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) -} - -func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - secretKeyring: secretkeyring, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { - for _, y := range v.remoteProviders { - if reflect.DeepEqual(y, p) { - return true - } - } - return false -} - // 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. @@ -827,10 +637,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string // "foo.bar.baz" in a lower-priority map func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string { // unify input map - var m map[string]any - switch mi.(type) { - case map[string]string, map[string]FlagValue: - m = cast.ToStringMap(mi) + var m map[string]interface{} + switch miv := mi.(type) { + case map[string]string: + m = castMapStringToMapInterface(miv) + case map[string]FlagValue: + m = castMapFlagToMapInterface(miv) default: return "" } @@ -957,10 +769,12 @@ func (v *Viper) Sub(key string) *Viper { } if reflect.TypeOf(data).Kind() == reflect.Map { - subv.parents = append(v.parents, strings.ToLower(key)) + subv.parents = append([]string(nil), v.parents...) + subv.parents = append(subv.parents, strings.ToLower(key)) subv.automaticEnvApplied = v.automaticEnvApplied subv.envPrefix = v.envPrefix subv.envKeyReplacer = v.envKeyReplacer + subv.keyDelim = v.keyDelim subv.config = cast.ToStringMap(data) return subv } @@ -1002,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 { return cast.ToInt64(v.Get(key)) } +// GetUint8 returns the value associated with the key as an unsigned integer. +func GetUint8(key string) uint8 { return v.GetUint8(key) } + +func (v *Viper) GetUint8(key string) uint8 { + return cast.ToUint8(v.Get(key)) +} + // GetUint returns the value associated with the key as an unsigned integer. func GetUint(key string) uint { return v.GetUint(key) } @@ -1101,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { - return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) + return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...)) } // Unmarshal unmarshals the config into a Struct. Make sure that the tags @@ -1111,28 +932,91 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { - return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) + keys := v.AllKeys() + + if v.experimentalBindStruct { + // TODO: make this optional? + structKeys, err := v.decodeStructKeys(rawVal, opts...) + if err != nil { + return err + } + + keys = append(keys, structKeys...) + } + + // TODO: struct keys should be enough? + return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...)) +} + +func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) { + var structKeyMap map[string]any + + err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...)) + if err != nil { + return nil, err + } + + flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "") + + r := make([]string, 0, len(flattenedStructKeyMap)) + for v := range flattenedStructKeyMap { + r = append(r, v) + } + + return r, nil } // defaultDecoderConfig returns default mapstructure.DecoderConfig with support -// of time.Duration values & string slices -func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { +// of time.Duration values & string slices. +func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { + decodeHook := v.decodeHook + if decodeHook == nil { + decodeHook = mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToTimeDurationHookFunc(), + // mapstructure.StringToSliceHookFunc(","), + stringToWeakSliceHookFunc(","), + ) + } + c := &mapstructure.DecoderConfig{ Metadata: nil, - Result: output, WeaklyTypedInput: true, - DecodeHook: mapstructure.ComposeDecodeHookFunc( - mapstructure.StringToTimeDurationHookFunc(), - mapstructure.StringToSliceHookFunc(","), - ), + DecodeHook: decodeHook, } + for _, opt := range opts { opt(c) } + + // Do not allow overwriting the output + c.Result = output + return c } -// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality +// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice. +// This function removes that check. +// TODO: implement a function that checks if the value can be converted to the return type and use it instead. +func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality. func decode(input any, config *mapstructure.DecoderConfig) error { decoder, err := mapstructure.NewDecoder(config) if err != nil { @@ -1148,10 +1032,23 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { - config := defaultDecoderConfig(rawVal, opts...) + config := v.defaultDecoderConfig(rawVal, opts...) config.ErrorUnused = true - return decode(v.AllSettings(), config) + keys := v.AllKeys() + + if v.experimentalBindStruct { + // TODO: make this optional? + structKeys, err := v.decodeStructKeys(rawVal, opts...) + if err != nil { + return err + } + + keys = append(keys, structKeys...) + } + + // TODO: struct keys should be enough? + return decode(v.getSettings(keys), config) } // BindPFlags binds a full flag set to the configuration, using each flag's long @@ -1405,11 +1302,11 @@ 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]any is returned in order to enable cast.ToStringMap +// 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 { + if val == "" { return map[string]any{} } r := csv.NewReader(strings.NewReader(val)) @@ -1429,11 +1326,11 @@ func stringToStringConv(val string) any { } // 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]any is returned in order to enable cast.ToStringMap +// 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 { + if val == "" { return map[string]any{} } ss := strings.Split(val, ",") @@ -1481,13 +1378,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { // RegisterAlias creates an alias that provides another accessor for the same key. // This enables one to change a name without breaking the application. -func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } +func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) } -func (v *Viper) RegisterAlias(alias string, key string) { +func (v *Viper) RegisterAlias(alias, key string) { v.registerAlias(alias, strings.ToLower(key)) } -func (v *Viper) registerAlias(alias string, key string) { +func (v *Viper) registerAlias(alias, key string) { alias = strings.ToLower(alias) if alias != key && alias != v.realKey(key) { _, exists := v.aliases[alias] @@ -1590,7 +1487,7 @@ func (v *Viper) ReadInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1621,7 +1518,7 @@ func (v *Viper) MergeInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1638,19 +1535,29 @@ 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]any) - return v.unmarshalReader(in, v.config) + config := make(map[string]any) + + err := v.unmarshalReader(in, config) + if err != nil { + return err + } + + v.config = config + + return nil } // MergeConfig merges a new configuration with an existing config. func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } func (v *Viper) MergeConfig(in io.Reader) error { - cfg := make(map[string]any) - if err := v.unmarshalReader(in, cfg); err != nil { + config := make(map[string]any) + + if err := v.unmarshalReader(in, config); err != nil { return err } - return v.MergeConfigMap(cfg) + + return v.MergeConfigMap(config) } // MergeConfigMap merges the configuration from the map given with an existing config. @@ -1694,6 +1601,19 @@ func (v *Viper) WriteConfigAs(filename string) error { return v.writeConfig(filename, true) } +// WriteConfigTo writes current configuration to an [io.Writer]. +func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) } + +func (v *Viper) WriteConfigTo(w io.Writer) error { + format := strings.ToLower(v.getConfigType()) + + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + return v.marshalWriter(w, format) +} + // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } @@ -1720,7 +1640,7 @@ func (v *Viper) writeConfig(filename string, force bool) error { return fmt.Errorf("config type could not be determined for %s", filename) } - if !stringInSlice(configType, SupportedExts) { + if !slices.Contains(SupportedExts, configType) { return UnsupportedConfigError(configType) } if v.config == nil { @@ -1743,22 +1663,30 @@ func (v *Viper) writeConfig(filename string, force bool) error { return f.Sync() } -// Unmarshal a Reader into a map. -// Should probably be an unexported function. -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]any) error { + format := strings.ToLower(v.getConfigType()) + if format == "" { + return errors.New("cannot decode configuration: unable to determine config type") + } + buf := new(bytes.Buffer) buf.ReadFrom(in) - switch format := strings.ToLower(v.getConfigType()); format { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env": - err := v.decoderRegistry.Decode(format, buf.Bytes(), c) - if err != nil { - return ConfigParseError{err} - } + // TODO: remove this once SupportedExts is deprecated/removed + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + // TODO: return [UnsupportedConfigError] if the registry does not contain the format + // TODO: consider deprecating this error type + decoder, err := v.decoderRegistry.Decoder(format) + if err != nil { + return ConfigParseError{err} + } + + err = decoder.Decode(buf.Bytes(), c) + if err != nil { + return ConfigParseError{err} } insensitiviseMap(c) @@ -1766,20 +1694,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error { } // Marshal a map into Writer. -func (v *Viper) marshalWriter(f afero.File, configType string) error { +func (v *Viper) marshalWriter(w io.Writer, configType string) error { c := v.AllSettings() - switch configType { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env": - b, err := v.encoderRegistry.Encode(configType, c) - if err != nil { - return ConfigMarshalError{err} - } - _, err = f.WriteString(string(b)) - if err != nil { - return ConfigMarshalError{err} - } + encoder, err := v.encoderRegistry.Encoder(configType) + if err != nil { + return ConfigMarshalError{err} + } + + b, err := encoder.Encode(c) + if err != nil { + return ConfigMarshalError{err} + } + + _, err = w.Write(b) + if err != nil { + return ConfigMarshalError{err} } + return nil } @@ -1911,108 +1843,8 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) { } } -// ReadRemoteConfig attempts to get configuration from a remote source -// and read it in the remote configuration registry. -func ReadRemoteConfig() error { return v.ReadRemoteConfig() } - -func (v *Viper) ReadRemoteConfig() error { - return v.getKeyValueConfig() -} - -func WatchRemoteConfig() error { return v.WatchRemoteConfig() } -func (v *Viper) WatchRemoteConfig() error { - return v.watchKeyValueConfig() -} - -func (v *Viper) WatchRemoteConfigOnChannel() error { - return v.watchKeyValueConfigOnChannel() -} - -// Retrieve the first found remote configuration. -func (v *Viper) getKeyValueConfig() error { - if RemoteConfig == nil { - return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") - } - - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.getRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) - - continue - } - - v.kvstore = val - - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Get(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfigOnChannel() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - respc, _ := RemoteConfig.WatchChannel(rp) - // Todo: Add quit channel - go func(rc <-chan *RemoteResponse) { - for { - b := <-rc - reader := bytes.NewReader(b.Value) - v.unmarshalReader(reader, v.kvstore) - } - }(respc) - return nil - } - return RemoteConfigError("No Files Found") -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfig() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.watchRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) - - continue - } - v.kvstore = val - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Watch(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - // AllKeys returns all keys holding a value, regardless of where they are set. -// Nested keys are returned with a v.keyDelim separator +// Nested keys are returned with a v.keyDelim separator. func AllKeys() []string { return v.AllKeys() } func (v *Viper) AllKeys() []string { @@ -2098,9 +1930,13 @@ outer: func AllSettings() map[string]any { return v.AllSettings() } func (v *Viper) AllSettings() map[string]any { + return v.getSettings(v.AllKeys()) +} + +func (v *Viper) getSettings(keys []string) 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() { + for _, k := range keys { value := v.Get(k) if value == nil { // should not happen, since AllKeys() returns only keys holding a value, @@ -2128,6 +1964,10 @@ func (v *Viper) SetFs(fs afero.Fs) { func SetConfigName(in string) { v.SetConfigName(in) } func (v *Viper) SetConfigName(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName")) + } + if in != "" { v.configName = in v.configFile = "" @@ -2151,13 +1991,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) { v.configPermissions = perm.Perm() } -// IniLoadOptions sets the load options for ini parsing. -func IniLoadOptions(in ini.LoadOptions) Option { - return optionFunc(func(v *Viper) { - v.iniLoadOptions = in - }) -} - func (v *Viper) getConfigType() string { if v.configType != "" { return v.configType diff --git a/event-processor/vendor/github.com/spf13/viper/viper_go1_15.go b/event-processor/vendor/github.com/spf13/viper/viper_go1_15.go deleted file mode 100644 index 7fc6aff3..00000000 --- a/event-processor/vendor/github.com/spf13/viper/viper_go1_15.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build !finder - -package viper - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/spf13/afero" -) - -// Search all configPaths for any config file. -// Returns the first path that exists (and is a config file). -func (v *Viper) findConfigFile() (string, error) { - v.logger.Info("searching for config in paths", "paths", v.configPaths) - - for _, cp := range v.configPaths { - file := v.searchInPath(cp) - if file != "" { - return file, nil - } - } - return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} -} - -func (v *Viper) searchInPath(in string) (filename string) { - v.logger.Debug("searching for config in path", "path", in) - for _, ext := range SupportedExts { - v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext)) - if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b { - v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext)) - return filepath.Join(in, v.configName+"."+ext) - } - } - - if v.configType != "" { - if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b { - return filepath.Join(in, v.configName) - } - } - - return "" -} - -// Check if file Exists -func exists(fs afero.Fs, path string) (bool, error) { - stat, err := fs.Stat(path) - if err == nil { - return !stat.IsDir(), nil - } - if os.IsNotExist(err) { - return false, nil - } - return false, err -} diff --git a/event-processor/vendor/github.com/spf13/viper/viper_go1_16.go b/event-processor/vendor/github.com/spf13/viper/viper_go1_16.go deleted file mode 100644 index d96a1bd2..00000000 --- a/event-processor/vendor/github.com/spf13/viper/viper_go1_16.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build finder - -package viper - -import ( - "fmt" - - "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) { - 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, - } - - results, err := finder.Find(v.fs) - if err != nil { - return "", err - } - - if len(results) == 0 { - return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} - } - - return results[0], nil -} diff --git a/event-processor/vendor/github.com/spf13/viper/watch.go b/event-processor/vendor/github.com/spf13/viper/watch.go deleted file mode 100644 index e98fce89..00000000 --- a/event-processor/vendor/github.com/spf13/viper/watch.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows - -package viper - -import "github.com/fsnotify/fsnotify" - -type watcher = fsnotify.Watcher - -func newWatcher() (*watcher, error) { - return fsnotify.NewWatcher() -} diff --git a/event-processor/vendor/github.com/spf13/viper/watch_unsupported.go b/event-processor/vendor/github.com/spf13/viper/watch_unsupported.go deleted file mode 100644 index 70764056..00000000 --- a/event-processor/vendor/github.com/spf13/viper/watch_unsupported.go +++ /dev/null @@ -1,31 +0,0 @@ -//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) - -package viper - -import ( - "fmt" - "runtime" - - "github.com/fsnotify/fsnotify" -) - -func newWatcher() (*watcher, error) { - return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) -} - -type watcher struct { - Events chan fsnotify.Event - Errors chan error -} - -func (*watcher) Close() error { - return nil -} - -func (*watcher) Add(name string) error { - return nil -} - -func (*watcher) Remove(name string) error { - return nil -} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/LICENSE b/event-processor/vendor/go.yaml.in/yaml/v3/LICENSE new file mode 100644 index 00000000..2683e4bb --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/LICENSE @@ -0,0 +1,50 @@ + +This project is covered by two different licenses: MIT and Apache. + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/NOTICE b/event-processor/vendor/go.yaml.in/yaml/v3/NOTICE new file mode 100644 index 00000000..866d74a7 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/NOTICE @@ -0,0 +1,13 @@ +Copyright 2011-2016 Canonical Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/README.md b/event-processor/vendor/go.yaml.in/yaml/v3/README.md new file mode 100644 index 00000000..15a85a63 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/README.md @@ -0,0 +1,171 @@ +go.yaml.in/yaml +=============== + +YAML Support for the Go Language + + +## Introduction + +The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode +and decode [YAML](https://yaml.org/) values. + +It was originally developed within [Canonical](https://www.canonical.com) as +part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go +port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to +parse and generate YAML data quickly and reliably. + + +## Project Status + +This project started as a fork of the extremely popular [go-yaml]( +https://github.com/go-yaml/yaml/) +project, and is being maintained by the official [YAML organization]( +https://github.com/yaml/). + +The YAML team took over ongoing maintenance and development of the project after +discussion with go-yaml's author, @niemeyer, following his decision to +[label the project repository as "unmaintained"]( +https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025. + +We have put together a team of dedicated maintainers including representatives +of go-yaml's most important downstream projects. + +We will strive to earn the trust of the various go-yaml forks to switch back to +this repository as their upstream. + +Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you +would like to contribute or be involved. + + +## Compatibility + +The `yaml` package supports most of YAML 1.2, but preserves some behavior from +1.1 for backwards compatibility. + +Specifically, v3 of the `yaml` package: + +* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being + decoded into a typed bool value. + Otherwise they behave as a string. + Booleans in YAML 1.2 are `true`/`false` only. +* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than + `0o777` as specified in YAML 1.2, because most parsers still use the old + format. + Octals in the `0o777` format are supported though, so new files work. +* Does not support base-60 floats. + These are gone from YAML 1.2, and were actually never supported by this + package as it's clearly a poor choice. + + +## Installation and Usage + +The import path for the package is *go.yaml.in/yaml/v3*. + +To install it, run: + +```bash +go get go.yaml.in/yaml/v3 +``` + + +## API Documentation + +See: + + +## API Stability + +The package API for yaml v3 will remain stable as described in [gopkg.in]( +https://gopkg.in). + + +## Example + +```go +package main + +import ( + "fmt" + "log" + + "go.yaml.in/yaml/v3" +) + +var data = ` +a: Easy! +b: + c: 2 + d: [3, 4] +` + +// Note: struct fields must be public in order for unmarshal to +// correctly populate the data. +type T struct { + A string + B struct { + RenamedC int `yaml:"c"` + D []int `yaml:",flow"` + } +} + +func main() { + t := T{} + + err := yaml.Unmarshal([]byte(data), &t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t:\n%v\n\n", t) + + d, err := yaml.Marshal(&t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t dump:\n%s\n\n", string(d)) + + m := make(map[interface{}]interface{}) + + err = yaml.Unmarshal([]byte(data), &m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m:\n%v\n\n", m) + + d, err = yaml.Marshal(&m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m dump:\n%s\n\n", string(d)) +} +``` + +This example will generate the following output: + +``` +--- t: +{Easy! {2 [3 4]}} + +--- t dump: +a: Easy! +b: + c: 2 + d: [3, 4] + + +--- m: +map[a:Easy! b:map[c:2 d:[3 4]]] + +--- m dump: +a: Easy! +b: + c: 2 + d: + - 3 + - 4 +``` + + +## License + +The yaml package is licensed under the MIT and Apache License 2.0 licenses. +Please see the LICENSE file for details. diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/apic.go b/event-processor/vendor/go.yaml.in/yaml/v3/apic.go new file mode 100644 index 00000000..05fd305d --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/apic.go @@ -0,0 +1,747 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "io" +) + +func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { + //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) + + // Check if we can move the queue at the beginning of the buffer. + if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { + if parser.tokens_head != len(parser.tokens) { + copy(parser.tokens, parser.tokens[parser.tokens_head:]) + } + parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] + parser.tokens_head = 0 + } + parser.tokens = append(parser.tokens, *token) + if pos < 0 { + return + } + copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) + parser.tokens[parser.tokens_head+pos] = *token +} + +// Create a new parser object. +func yaml_parser_initialize(parser *yaml_parser_t) bool { + *parser = yaml_parser_t{ + raw_buffer: make([]byte, 0, input_raw_buffer_size), + buffer: make([]byte, 0, input_buffer_size), + } + return true +} + +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + +// String read handler. +func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + if parser.input_pos == len(parser.input) { + return 0, io.EOF + } + n = copy(buffer, parser.input[parser.input_pos:]) + parser.input_pos += n + return n, nil +} + +// Reader read handler. +func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + return parser.input_reader.Read(buffer) +} + +// Set a string input. +func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_string_read_handler + parser.input = input + parser.input_pos = 0 +} + +// Set a file input. +func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_reader_read_handler + parser.input_reader = r +} + +// Set the source encoding. +func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { + if parser.encoding != yaml_ANY_ENCODING { + panic("must set the encoding only once") + } + parser.encoding = encoding +} + +// Create a new emitter object. +func yaml_emitter_initialize(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{ + buffer: make([]byte, output_buffer_size), + raw_buffer: make([]byte, 0, output_raw_buffer_size), + states: make([]yaml_emitter_state_t, 0, initial_stack_size), + events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, + } +} + +// Destroy an emitter object. +func yaml_emitter_delete(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{} +} + +// String write handler. +func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + *emitter.output_buffer = append(*emitter.output_buffer, buffer...) + return nil +} + +// yaml_writer_write_handler uses emitter.output_writer to write the +// emitted text. +func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + _, err := emitter.output_writer.Write(buffer) + return err +} + +// Set a string output. +func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_string_write_handler + emitter.output_buffer = output_buffer +} + +// Set a file output. +func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_writer_write_handler + emitter.output_writer = w +} + +// Set the output encoding. +func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { + if emitter.encoding != yaml_ANY_ENCODING { + panic("must set the output encoding only once") + } + emitter.encoding = encoding +} + +// Set the canonical output style. +func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { + emitter.canonical = canonical +} + +// Set the indentation increment. +func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { + if indent < 2 || indent > 9 { + indent = 2 + } + emitter.best_indent = indent +} + +// Set the preferred line width. +func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { + if width < 0 { + width = -1 + } + emitter.best_width = width +} + +// Set if unescaped non-ASCII characters are allowed. +func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { + emitter.unicode = unicode +} + +// Set the preferred line break character. +func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { + emitter.line_break = line_break +} + +///* +// * Destroy a token object. +// */ +// +//YAML_DECLARE(void) +//yaml_token_delete(yaml_token_t *token) +//{ +// assert(token); // Non-NULL token object expected. +// +// switch (token.type) +// { +// case YAML_TAG_DIRECTIVE_TOKEN: +// yaml_free(token.data.tag_directive.handle); +// yaml_free(token.data.tag_directive.prefix); +// break; +// +// case YAML_ALIAS_TOKEN: +// yaml_free(token.data.alias.value); +// break; +// +// case YAML_ANCHOR_TOKEN: +// yaml_free(token.data.anchor.value); +// break; +// +// case YAML_TAG_TOKEN: +// yaml_free(token.data.tag.handle); +// yaml_free(token.data.tag.suffix); +// break; +// +// case YAML_SCALAR_TOKEN: +// yaml_free(token.data.scalar.value); +// break; +// +// default: +// break; +// } +// +// memset(token, 0, sizeof(yaml_token_t)); +//} +// +///* +// * Check if a string is a valid UTF-8 sequence. +// * +// * Check 'reader.c' for more details on UTF-8 encoding. +// */ +// +//static int +//yaml_check_utf8(yaml_char_t *start, size_t length) +//{ +// yaml_char_t *end = start+length; +// yaml_char_t *pointer = start; +// +// while (pointer < end) { +// unsigned char octet; +// unsigned int width; +// unsigned int value; +// size_t k; +// +// octet = pointer[0]; +// width = (octet & 0x80) == 0x00 ? 1 : +// (octet & 0xE0) == 0xC0 ? 2 : +// (octet & 0xF0) == 0xE0 ? 3 : +// (octet & 0xF8) == 0xF0 ? 4 : 0; +// value = (octet & 0x80) == 0x00 ? octet & 0x7F : +// (octet & 0xE0) == 0xC0 ? octet & 0x1F : +// (octet & 0xF0) == 0xE0 ? octet & 0x0F : +// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; +// if (!width) return 0; +// if (pointer+width > end) return 0; +// for (k = 1; k < width; k ++) { +// octet = pointer[k]; +// if ((octet & 0xC0) != 0x80) return 0; +// value = (value << 6) + (octet & 0x3F); +// } +// if (!((width == 1) || +// (width == 2 && value >= 0x80) || +// (width == 3 && value >= 0x800) || +// (width == 4 && value >= 0x10000))) return 0; +// +// pointer += width; +// } +// +// return 1; +//} +// + +// Create STREAM-START. +func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + encoding: encoding, + } +} + +// Create STREAM-END. +func yaml_stream_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + } +} + +// Create DOCUMENT-START. +func yaml_document_start_event_initialize( + event *yaml_event_t, + version_directive *yaml_version_directive_t, + tag_directives []yaml_tag_directive_t, + implicit bool, +) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: implicit, + } +} + +// Create DOCUMENT-END. +func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + implicit: implicit, + } +} + +// Create ALIAS. +func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + anchor: anchor, + } + return true +} + +// Create SCALAR. +func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + anchor: anchor, + tag: tag, + value: value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-START. +func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-END. +func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + } + return true +} + +// Create MAPPING-START. +func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } +} + +// Create MAPPING-END. +func yaml_mapping_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + } +} + +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + +///* +// * Create a document object. +// */ +// +//YAML_DECLARE(int) +//yaml_document_initialize(document *yaml_document_t, +// version_directive *yaml_version_directive_t, +// tag_directives_start *yaml_tag_directive_t, +// tag_directives_end *yaml_tag_directive_t, +// start_implicit int, end_implicit int) +//{ +// struct { +// error yaml_error_type_t +// } context +// struct { +// start *yaml_node_t +// end *yaml_node_t +// top *yaml_node_t +// } nodes = { NULL, NULL, NULL } +// version_directive_copy *yaml_version_directive_t = NULL +// struct { +// start *yaml_tag_directive_t +// end *yaml_tag_directive_t +// top *yaml_tag_directive_t +// } tag_directives_copy = { NULL, NULL, NULL } +// value yaml_tag_directive_t = { NULL, NULL } +// mark yaml_mark_t = { 0, 0, 0 } +// +// assert(document) // Non-NULL document object is expected. +// assert((tag_directives_start && tag_directives_end) || +// (tag_directives_start == tag_directives_end)) +// // Valid tag directives are expected. +// +// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error +// +// if (version_directive) { +// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) +// if (!version_directive_copy) goto error +// version_directive_copy.major = version_directive.major +// version_directive_copy.minor = version_directive.minor +// } +// +// if (tag_directives_start != tag_directives_end) { +// tag_directive *yaml_tag_directive_t +// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) +// goto error +// for (tag_directive = tag_directives_start +// tag_directive != tag_directives_end; tag_directive ++) { +// assert(tag_directive.handle) +// assert(tag_directive.prefix) +// if (!yaml_check_utf8(tag_directive.handle, +// strlen((char *)tag_directive.handle))) +// goto error +// if (!yaml_check_utf8(tag_directive.prefix, +// strlen((char *)tag_directive.prefix))) +// goto error +// value.handle = yaml_strdup(tag_directive.handle) +// value.prefix = yaml_strdup(tag_directive.prefix) +// if (!value.handle || !value.prefix) goto error +// if (!PUSH(&context, tag_directives_copy, value)) +// goto error +// value.handle = NULL +// value.prefix = NULL +// } +// } +// +// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, +// tag_directives_copy.start, tag_directives_copy.top, +// start_implicit, end_implicit, mark, mark) +// +// return 1 +// +//error: +// STACK_DEL(&context, nodes) +// yaml_free(version_directive_copy) +// while (!STACK_EMPTY(&context, tag_directives_copy)) { +// value yaml_tag_directive_t = POP(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// } +// STACK_DEL(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// +// return 0 +//} +// +///* +// * Destroy a document object. +// */ +// +//YAML_DECLARE(void) +//yaml_document_delete(document *yaml_document_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// tag_directive *yaml_tag_directive_t +// +// context.error = YAML_NO_ERROR // Eliminate a compiler warning. +// +// assert(document) // Non-NULL document object is expected. +// +// while (!STACK_EMPTY(&context, document.nodes)) { +// node yaml_node_t = POP(&context, document.nodes) +// yaml_free(node.tag) +// switch (node.type) { +// case YAML_SCALAR_NODE: +// yaml_free(node.data.scalar.value) +// break +// case YAML_SEQUENCE_NODE: +// STACK_DEL(&context, node.data.sequence.items) +// break +// case YAML_MAPPING_NODE: +// STACK_DEL(&context, node.data.mapping.pairs) +// break +// default: +// assert(0) // Should not happen. +// } +// } +// STACK_DEL(&context, document.nodes) +// +// yaml_free(document.version_directive) +// for (tag_directive = document.tag_directives.start +// tag_directive != document.tag_directives.end +// tag_directive++) { +// yaml_free(tag_directive.handle) +// yaml_free(tag_directive.prefix) +// } +// yaml_free(document.tag_directives.start) +// +// memset(document, 0, sizeof(yaml_document_t)) +//} +// +///** +// * Get a document node. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_node(document *yaml_document_t, index int) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (index > 0 && document.nodes.start + index <= document.nodes.top) { +// return document.nodes.start + index - 1 +// } +// return NULL +//} +// +///** +// * Get the root object. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_root_node(document *yaml_document_t) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (document.nodes.top != document.nodes.start) { +// return document.nodes.start +// } +// return NULL +//} +// +///* +// * Add a scalar node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_scalar(document *yaml_document_t, +// tag *yaml_char_t, value *yaml_char_t, length int, +// style yaml_scalar_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// value_copy *yaml_char_t = NULL +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// assert(value) // Non-NULL value is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (length < 0) { +// length = strlen((char *)value) +// } +// +// if (!yaml_check_utf8(value, length)) goto error +// value_copy = yaml_malloc(length+1) +// if (!value_copy) goto error +// memcpy(value_copy, value, length) +// value_copy[length] = '\0' +// +// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// yaml_free(tag_copy) +// yaml_free(value_copy) +// +// return 0 +//} +// +///* +// * Add a sequence node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_sequence(document *yaml_document_t, +// tag *yaml_char_t, style yaml_sequence_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_item_t +// end *yaml_node_item_t +// top *yaml_node_item_t +// } items = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error +// +// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, items) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Add a mapping node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_mapping(document *yaml_document_t, +// tag *yaml_char_t, style yaml_mapping_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_pair_t +// end *yaml_node_pair_t +// top *yaml_node_pair_t +// } pairs = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error +// +// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, pairs) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Append an item to a sequence node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_sequence_item(document *yaml_document_t, +// sequence int, item int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// assert(document) // Non-NULL document is required. +// assert(sequence > 0 +// && document.nodes.start + sequence <= document.nodes.top) +// // Valid sequence id is required. +// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) +// // A sequence node is required. +// assert(item > 0 && document.nodes.start + item <= document.nodes.top) +// // Valid item id is required. +// +// if (!PUSH(&context, +// document.nodes.start[sequence-1].data.sequence.items, item)) +// return 0 +// +// return 1 +//} +// +///* +// * Append a pair of a key and a value to a mapping node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_mapping_pair(document *yaml_document_t, +// mapping int, key int, value int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// pair yaml_node_pair_t +// +// assert(document) // Non-NULL document is required. +// assert(mapping > 0 +// && document.nodes.start + mapping <= document.nodes.top) +// // Valid mapping id is required. +// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) +// // A mapping node is required. +// assert(key > 0 && document.nodes.start + key <= document.nodes.top) +// // Valid key id is required. +// assert(value > 0 && document.nodes.start + value <= document.nodes.top) +// // Valid value id is required. +// +// pair.key = key +// pair.value = value +// +// if (!PUSH(&context, +// document.nodes.start[mapping-1].data.mapping.pairs, pair)) +// return 0 +// +// return 1 +//} +// +// diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/decode.go b/event-processor/vendor/go.yaml.in/yaml/v3/decode.go new file mode 100644 index 00000000..02e2b17b --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/decode.go @@ -0,0 +1,1018 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding" + "encoding/base64" + "fmt" + "io" + "math" + "reflect" + "strconv" + "time" +) + +// ---------------------------------------------------------------------------- +// Parser, produces a node tree out of a libyaml event stream. + +type parser struct { + parser yaml_parser_t + event yaml_event_t + doc *Node + anchors map[string]*Node + doneInit bool + textless bool +} + +func newParser(b []byte) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + if len(b) == 0 { + b = []byte{'\n'} + } + yaml_parser_set_input_string(&p.parser, b) + return &p +} + +func newParserFromReader(r io.Reader) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + yaml_parser_set_input_reader(&p.parser, r) + return &p +} + +func (p *parser) init() { + if p.doneInit { + return + } + p.anchors = make(map[string]*Node) + p.expect(yaml_STREAM_START_EVENT) + p.doneInit = true +} + +func (p *parser) destroy() { + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) + } + yaml_parser_delete(&p.parser) +} + +// expect consumes an event from the event stream and +// checks that it's of the expected type. +func (p *parser) expect(e yaml_event_type_t) { + if p.event.typ == yaml_NO_EVENT { + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } + } + if p.event.typ == yaml_STREAM_END_EVENT { + failf("attempted to go past the end of stream; corrupted value?") + } + if p.event.typ != e { + p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) + p.fail() + } + yaml_event_delete(&p.event) + p.event.typ = yaml_NO_EVENT +} + +// peek peeks at the next event in the event stream, +// puts the results into p.event and returns the event type. +func (p *parser) peek() yaml_event_type_t { + if p.event.typ != yaml_NO_EVENT { + return p.event.typ + } + // It's curious choice from the underlying API to generally return a + // positive result on success, but on this case return true in an error + // scenario. This was the source of bugs in the past (issue #666). + if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { + p.fail() + } + return p.event.typ +} + +func (p *parser) fail() { + var where string + var line int + if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } else if p.parser.problem_mark.line != 0 { + line = p.parser.problem_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } + if line != 0 { + where = "line " + strconv.Itoa(line) + ": " + } + var msg string + if len(p.parser.problem) > 0 { + msg = p.parser.problem + } else { + msg = "unknown problem parsing YAML content" + } + failf("%s%s", where, msg) +} + +func (p *parser) anchor(n *Node, anchor []byte) { + if anchor != nil { + n.Anchor = string(anchor) + p.anchors[n.Anchor] = n + } +} + +func (p *parser) parse() *Node { + p.init() + switch p.peek() { + case yaml_SCALAR_EVENT: + return p.scalar() + case yaml_ALIAS_EVENT: + return p.alias() + case yaml_MAPPING_START_EVENT: + return p.mapping() + case yaml_SEQUENCE_START_EVENT: + return p.sequence() + case yaml_DOCUMENT_START_EVENT: + return p.document() + case yaml_STREAM_END_EVENT: + // Happens when attempting to decode an empty buffer. + return nil + case yaml_TAIL_COMMENT_EVENT: + panic("internal error: unexpected tail comment event (please report)") + default: + panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) + } +} + +func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { + var style Style + if tag != "" && tag != "!" { + tag = shortTag(tag) + style = TaggedStyle + } else if defaultTag != "" { + tag = defaultTag + } else if kind == ScalarNode { + tag, _ = resolve("", value) + } + n := &Node{ + Kind: kind, + Tag: tag, + Value: value, + Style: style, + } + if !p.textless { + n.Line = p.event.start_mark.line + 1 + n.Column = p.event.start_mark.column + 1 + n.HeadComment = string(p.event.head_comment) + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + } + return n +} + +func (p *parser) parseChild(parent *Node) *Node { + child := p.parse() + parent.Content = append(parent.Content, child) + return child +} + +func (p *parser) document() *Node { + n := p.node(DocumentNode, "", "", "") + p.doc = n + p.expect(yaml_DOCUMENT_START_EVENT) + p.parseChild(n) + if p.peek() == yaml_DOCUMENT_END_EVENT { + n.FootComment = string(p.event.foot_comment) + } + p.expect(yaml_DOCUMENT_END_EVENT) + return n +} + +func (p *parser) alias() *Node { + n := p.node(AliasNode, "", "", string(p.event.anchor)) + n.Alias = p.anchors[n.Value] + if n.Alias == nil { + failf("unknown anchor '%s' referenced", n.Value) + } + p.expect(yaml_ALIAS_EVENT) + return n +} + +func (p *parser) scalar() *Node { + var parsedStyle = p.event.scalar_style() + var nodeStyle Style + switch { + case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: + nodeStyle = DoubleQuotedStyle + case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: + nodeStyle = SingleQuotedStyle + case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: + nodeStyle = LiteralStyle + case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: + nodeStyle = FoldedStyle + } + var nodeValue = string(p.event.value) + var nodeTag = string(p.event.tag) + var defaultTag string + if nodeStyle == 0 { + if nodeValue == "<<" { + defaultTag = mergeTag + } + } else { + defaultTag = strTag + } + n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) + n.Style |= nodeStyle + p.anchor(n, p.event.anchor) + p.expect(yaml_SCALAR_EVENT) + return n +} + +func (p *parser) sequence() *Node { + n := p.node(SequenceNode, seqTag, string(p.event.tag), "") + if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { + n.Style |= FlowStyle + } + p.anchor(n, p.event.anchor) + p.expect(yaml_SEQUENCE_START_EVENT) + for p.peek() != yaml_SEQUENCE_END_EVENT { + p.parseChild(n) + } + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + p.expect(yaml_SEQUENCE_END_EVENT) + return n +} + +func (p *parser) mapping() *Node { + n := p.node(MappingNode, mapTag, string(p.event.tag), "") + block := true + if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { + block = false + n.Style |= FlowStyle + } + p.anchor(n, p.event.anchor) + p.expect(yaml_MAPPING_START_EVENT) + for p.peek() != yaml_MAPPING_END_EVENT { + k := p.parseChild(n) + if block && k.FootComment != "" { + // Must be a foot comment for the prior value when being dedented. + if len(n.Content) > 2 { + n.Content[len(n.Content)-3].FootComment = k.FootComment + k.FootComment = "" + } + } + v := p.parseChild(n) + if k.FootComment == "" && v.FootComment != "" { + k.FootComment = v.FootComment + v.FootComment = "" + } + if p.peek() == yaml_TAIL_COMMENT_EVENT { + if k.FootComment == "" { + k.FootComment = string(p.event.foot_comment) + } + p.expect(yaml_TAIL_COMMENT_EVENT) + } + } + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) + if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { + n.Content[len(n.Content)-2].FootComment = n.FootComment + n.FootComment = "" + } + p.expect(yaml_MAPPING_END_EVENT) + return n +} + +// ---------------------------------------------------------------------------- +// Decoder, unmarshals a node into a provided value. + +type decoder struct { + doc *Node + aliases map[*Node]bool + terrors []string + + stringMapType reflect.Type + generalMapType reflect.Type + + knownFields bool + uniqueKeys bool + decodeCount int + aliasCount int + aliasDepth int + + mergedFields map[interface{}]bool +} + +var ( + nodeType = reflect.TypeOf(Node{}) + durationType = reflect.TypeOf(time.Duration(0)) + stringMapType = reflect.TypeOf(map[string]interface{}{}) + generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) + ifaceType = generalMapType.Elem() + timeType = reflect.TypeOf(time.Time{}) + ptrTimeType = reflect.TypeOf(&time.Time{}) +) + +func newDecoder() *decoder { + d := &decoder{ + stringMapType: stringMapType, + generalMapType: generalMapType, + uniqueKeys: true, + } + d.aliases = make(map[*Node]bool) + return d +} + +func (d *decoder) terror(n *Node, tag string, out reflect.Value) { + if n.Tag != "" { + tag = n.Tag + } + value := n.Value + if tag != seqTag && tag != mapTag { + if len(value) > 10 { + value = " `" + value[:7] + "...`" + } else { + value = " `" + value + "`" + } + } + d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) +} + +func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { + err := u.UnmarshalYAML(n) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { + terrlen := len(d.terrors) + err := u.UnmarshalYAML(func(v interface{}) (err error) { + defer handleErr(&err) + d.unmarshal(n, reflect.ValueOf(v)) + if len(d.terrors) > terrlen { + issues := d.terrors[terrlen:] + d.terrors = d.terrors[:terrlen] + return &TypeError{issues} + } + return nil + }) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +// d.prepare initializes and dereferences pointers and calls UnmarshalYAML +// if a value is found to implement it. +// It returns the initialized and dereferenced out value, whether +// unmarshalling was already done by UnmarshalYAML, and if so whether +// its types unmarshalled appropriately. +// +// If n holds a null value, prepare returns before doing anything. +func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { + if n.ShortTag() == nullTag { + return out, false, false + } + again := true + for again { + again = false + if out.Kind() == reflect.Ptr { + if out.IsNil() { + out.Set(reflect.New(out.Type().Elem())) + } + out = out.Elem() + again = true + } + if out.CanAddr() { + outi := out.Addr().Interface() + if u, ok := outi.(Unmarshaler); ok { + good = d.callUnmarshaler(n, u) + return out, true, good + } + if u, ok := outi.(obsoleteUnmarshaler); ok { + good = d.callObsoleteUnmarshaler(n, u) + return out, true, good + } + } + } + return out, false, false +} + +func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { + if n.ShortTag() == nullTag { + return reflect.Value{} + } + for _, num := range index { + for { + if v.Kind() == reflect.Ptr { + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + continue + } + break + } + v = v.Field(num) + } + return v +} + +const ( + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion + alias_ratio_range_low = 400000 + + // 4,000,000 decode operations is ~5MB of dense object declarations, or + // ~4.5MB of dense object declarations with 10% alias expansion + alias_ratio_range_high = 4000000 + + // alias_ratio_range is the range over which we scale allowed alias ratios + alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) +) + +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= alias_ratio_range_low: + // allow 99% to come from alias expansion for small-to-medium documents + return 0.99 + case decodeCount >= alias_ratio_range_high: + // allow 10% to come from alias expansion for very large documents + return 0.10 + default: + // scale smoothly from 99% down to 10% over the range. + // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. + // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). + return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) + } +} + +func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { + d.decodeCount++ + if d.aliasDepth > 0 { + d.aliasCount++ + } + if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { + failf("document contains excessive aliasing") + } + if out.Type() == nodeType { + out.Set(reflect.ValueOf(n).Elem()) + return true + } + switch n.Kind { + case DocumentNode: + return d.document(n, out) + case AliasNode: + return d.alias(n, out) + } + out, unmarshaled, good := d.prepare(n, out) + if unmarshaled { + return good + } + switch n.Kind { + case ScalarNode: + good = d.scalar(n, out) + case MappingNode: + good = d.mapping(n, out) + case SequenceNode: + good = d.sequence(n, out) + case 0: + if n.IsZero() { + return d.null(out) + } + fallthrough + default: + failf("cannot decode node with unknown kind %d", n.Kind) + } + return good +} + +func (d *decoder) document(n *Node, out reflect.Value) (good bool) { + if len(n.Content) == 1 { + d.doc = n + d.unmarshal(n.Content[0], out) + return true + } + return false +} + +func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { + if d.aliases[n] { + // TODO this could actually be allowed in some circumstances. + failf("anchor '%s' value contains itself", n.Value) + } + d.aliases[n] = true + d.aliasDepth++ + good = d.unmarshal(n.Alias, out) + d.aliasDepth-- + delete(d.aliases, n) + return good +} + +var zeroValue reflect.Value + +func resetMap(out reflect.Value) { + for _, k := range out.MapKeys() { + out.SetMapIndex(k, zeroValue) + } +} + +func (d *decoder) null(out reflect.Value) bool { + if out.CanAddr() { + switch out.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + out.Set(reflect.Zero(out.Type())) + return true + } + } + return false +} + +func (d *decoder) scalar(n *Node, out reflect.Value) bool { + var tag string + var resolved interface{} + if n.indicatedString() { + tag = strTag + resolved = n.Value + } else { + tag, resolved = resolve(n.Tag, n.Value) + if tag == binaryTag { + data, err := base64.StdEncoding.DecodeString(resolved.(string)) + if err != nil { + failf("!!binary value contains invalid base64 data") + } + resolved = string(data) + } + } + if resolved == nil { + return d.null(out) + } + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + // We've resolved to exactly the type we want, so use that. + out.Set(resolvedv) + return true + } + // Perhaps we can use the value as a TextUnmarshaler to + // set its value. + if out.CanAddr() { + u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) + if ok { + var text []byte + if tag == binaryTag { + text = []byte(resolved.(string)) + } else { + // We let any value be unmarshaled into TextUnmarshaler. + // That might be more lax than we'd like, but the + // TextUnmarshaler itself should bowl out any dubious values. + text = []byte(n.Value) + } + err := u.UnmarshalText(text) + if err != nil { + fail(err) + } + return true + } + } + switch out.Kind() { + case reflect.String: + if tag == binaryTag { + out.SetString(resolved.(string)) + return true + } + out.SetString(n.Value) + return true + case reflect.Interface: + out.Set(reflect.ValueOf(resolved)) + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + // This used to work in v2, but it's very unfriendly. + isDuration := out.Type() == durationType + + switch resolved := resolved.(type) { + case int: + if !isDuration && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case int64: + if !isDuration && !out.OverflowInt(resolved) { + out.SetInt(resolved) + return true + } + case uint64: + if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case float64: + if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + return true + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch resolved := resolved.(type) { + case int: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case int64: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case uint64: + if !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case float64: + if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + } + case reflect.Bool: + switch resolved := resolved.(type) { + case bool: + out.SetBool(resolved) + return true + case string: + // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). + // It only works if explicitly attempting to unmarshal into a typed bool value. + switch resolved { + case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": + out.SetBool(true) + return true + case "n", "N", "no", "No", "NO", "off", "Off", "OFF": + out.SetBool(false) + return true + } + } + case reflect.Float32, reflect.Float64: + switch resolved := resolved.(type) { + case int: + out.SetFloat(float64(resolved)) + return true + case int64: + out.SetFloat(float64(resolved)) + return true + case uint64: + out.SetFloat(float64(resolved)) + return true + case float64: + out.SetFloat(resolved) + return true + } + case reflect.Struct: + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + out.Set(resolvedv) + return true + } + case reflect.Ptr: + panic("yaml internal error: please report the issue") + } + d.terror(n, tag, out) + return false +} + +func settableValueOf(i interface{}) reflect.Value { + v := reflect.ValueOf(i) + sv := reflect.New(v.Type()).Elem() + sv.Set(v) + return sv +} + +func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { + l := len(n.Content) + + var iface reflect.Value + switch out.Kind() { + case reflect.Slice: + out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Array: + if l != out.Len() { + failf("invalid array: want %d elements but got %d", out.Len(), l) + } + case reflect.Interface: + // No type hints. Will have to use a generic sequence. + iface = out + out = settableValueOf(make([]interface{}, l)) + default: + d.terror(n, seqTag, out) + return false + } + et := out.Type().Elem() + + j := 0 + for i := 0; i < l; i++ { + e := reflect.New(et).Elem() + if ok := d.unmarshal(n.Content[i], e); ok { + out.Index(j).Set(e) + j++ + } + } + if out.Kind() != reflect.Array { + out.Set(out.Slice(0, j)) + } + if iface.IsValid() { + iface.Set(out) + } + return true +} + +func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { + l := len(n.Content) + if d.uniqueKeys { + nerrs := len(d.terrors) + for i := 0; i < l; i += 2 { + ni := n.Content[i] + for j := i + 2; j < l; j += 2 { + nj := n.Content[j] + if ni.Kind == nj.Kind && ni.Value == nj.Value { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) + } + } + } + if len(d.terrors) > nerrs { + return false + } + } + switch out.Kind() { + case reflect.Struct: + return d.mappingStruct(n, out) + case reflect.Map: + // okay + case reflect.Interface: + iface := out + if isStringMap(n) { + out = reflect.MakeMap(d.stringMapType) + } else { + out = reflect.MakeMap(d.generalMapType) + } + iface.Set(out) + default: + d.terror(n, mapTag, out) + return false + } + + outt := out.Type() + kt := outt.Key() + et := outt.Elem() + + stringMapType := d.stringMapType + generalMapType := d.generalMapType + if outt.Elem() == ifaceType { + if outt.Key().Kind() == reflect.String { + d.stringMapType = outt + } else if outt.Key() == ifaceType { + d.generalMapType = outt + } + } + + mergedFields := d.mergedFields + d.mergedFields = nil + + var mergeNode *Node + + mapIsNew := false + if out.IsNil() { + out.Set(reflect.MakeMap(outt)) + mapIsNew = true + } + for i := 0; i < l; i += 2 { + if isMerge(n.Content[i]) { + mergeNode = n.Content[i+1] + continue + } + k := reflect.New(kt).Elem() + if d.unmarshal(n.Content[i], k) { + if mergedFields != nil { + ki := k.Interface() + if d.getPossiblyUnhashableKey(mergedFields, ki) { + continue + } + d.setPossiblyUnhashableKey(mergedFields, ki, true) + } + kkind := k.Kind() + if kkind == reflect.Interface { + kkind = k.Elem().Kind() + } + if kkind == reflect.Map || kkind == reflect.Slice { + failf("invalid map key: %#v", k.Interface()) + } + e := reflect.New(et).Elem() + if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { + out.SetMapIndex(k, e) + } + } + } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } + + d.stringMapType = stringMapType + d.generalMapType = generalMapType + return true +} + +func isStringMap(n *Node) bool { + if n.Kind != MappingNode { + return false + } + l := len(n.Content) + for i := 0; i < l; i += 2 { + shortTag := n.Content[i].ShortTag() + if shortTag != strTag && shortTag != mergeTag { + return false + } + } + return true +} + +func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { + sinfo, err := getStructInfo(out.Type()) + if err != nil { + panic(err) + } + + var inlineMap reflect.Value + var elemType reflect.Type + if sinfo.InlineMap != -1 { + inlineMap = out.Field(sinfo.InlineMap) + elemType = inlineMap.Type().Elem() + } + + for _, index := range sinfo.InlineUnmarshalers { + field := d.fieldByIndex(n, out, index) + d.prepare(n, field) + } + + mergedFields := d.mergedFields + d.mergedFields = nil + var mergeNode *Node + var doneFields []bool + if d.uniqueKeys { + doneFields = make([]bool, len(sinfo.FieldsList)) + } + name := settableValueOf("") + l := len(n.Content) + for i := 0; i < l; i += 2 { + ni := n.Content[i] + if isMerge(ni) { + mergeNode = n.Content[i+1] + continue + } + if !d.unmarshal(ni, name) { + continue + } + sname := name.String() + if mergedFields != nil { + if mergedFields[sname] { + continue + } + mergedFields[sname] = true + } + if info, ok := sinfo.FieldsMap[sname]; ok { + if d.uniqueKeys { + if doneFields[info.Id] { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) + continue + } + doneFields[info.Id] = true + } + var field reflect.Value + if info.Inline == nil { + field = out.Field(info.Num) + } else { + field = d.fieldByIndex(n, out, info.Inline) + } + d.unmarshal(n.Content[i+1], field) + } else if sinfo.InlineMap != -1 { + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + value := reflect.New(elemType).Elem() + d.unmarshal(n.Content[i+1], value) + inlineMap.SetMapIndex(name, value) + } else if d.knownFields { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) + } + } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } + return true +} + +func failWantMap() { + failf("map merge requires map or sequence of maps as the value") +} + +func (d *decoder) setPossiblyUnhashableKey(m map[interface{}]bool, key interface{}, value bool) { + defer func() { + if err := recover(); err != nil { + failf("%v", err) + } + }() + m[key] = value +} + +func (d *decoder) getPossiblyUnhashableKey(m map[interface{}]bool, key interface{}) bool { + defer func() { + if err := recover(); err != nil { + failf("%v", err) + } + }() + return m[key] +} + +func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { + mergedFields := d.mergedFields + if mergedFields == nil { + d.mergedFields = make(map[interface{}]bool) + for i := 0; i < len(parent.Content); i += 2 { + k := reflect.New(ifaceType).Elem() + if d.unmarshal(parent.Content[i], k) { + d.setPossiblyUnhashableKey(d.mergedFields, k.Interface(), true) + } + } + } + + switch merge.Kind { + case MappingNode: + d.unmarshal(merge, out) + case AliasNode: + if merge.Alias != nil && merge.Alias.Kind != MappingNode { + failWantMap() + } + d.unmarshal(merge, out) + case SequenceNode: + for i := 0; i < len(merge.Content); i++ { + ni := merge.Content[i] + if ni.Kind == AliasNode { + if ni.Alias != nil && ni.Alias.Kind != MappingNode { + failWantMap() + } + } else if ni.Kind != MappingNode { + failWantMap() + } + d.unmarshal(ni, out) + } + default: + failWantMap() + } + + d.mergedFields = mergedFields +} + +func isMerge(n *Node) bool { + return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/emitterc.go b/event-processor/vendor/go.yaml.in/yaml/v3/emitterc.go new file mode 100644 index 00000000..ab4e03ba --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/emitterc.go @@ -0,0 +1,2054 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" + "fmt" +) + +// Flush the buffer if needed. +func flush(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) { + return yaml_emitter_flush(emitter) + } + return true +} + +// Put a character to the output buffer. +func put(emitter *yaml_emitter_t, value byte) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + emitter.buffer[emitter.buffer_pos] = value + emitter.buffer_pos++ + emitter.column++ + return true +} + +// Put a line break to the output buffer. +func put_break(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + switch emitter.line_break { + case yaml_CR_BREAK: + emitter.buffer[emitter.buffer_pos] = '\r' + emitter.buffer_pos += 1 + case yaml_LN_BREAK: + emitter.buffer[emitter.buffer_pos] = '\n' + emitter.buffer_pos += 1 + case yaml_CRLN_BREAK: + emitter.buffer[emitter.buffer_pos+0] = '\r' + emitter.buffer[emitter.buffer_pos+1] = '\n' + emitter.buffer_pos += 2 + default: + panic("unknown line break setting") + } + if emitter.column == 0 { + emitter.space_above = true + } + emitter.column = 0 + emitter.line++ + // [Go] Do this here and below and drop from everywhere else (see commented lines). + emitter.indention = true + return true +} + +// Copy a character from a string into buffer. +func write(emitter *yaml_emitter_t, s []byte, i *int) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + p := emitter.buffer_pos + w := width(s[*i]) + switch w { + case 4: + emitter.buffer[p+3] = s[*i+3] + fallthrough + case 3: + emitter.buffer[p+2] = s[*i+2] + fallthrough + case 2: + emitter.buffer[p+1] = s[*i+1] + fallthrough + case 1: + emitter.buffer[p+0] = s[*i+0] + default: + panic("unknown character width") + } + emitter.column++ + emitter.buffer_pos += w + *i += w + return true +} + +// Write a whole string into buffer. +func write_all(emitter *yaml_emitter_t, s []byte) bool { + for i := 0; i < len(s); { + if !write(emitter, s, &i) { + return false + } + } + return true +} + +// Copy a line break character from a string into buffer. +func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { + if s[*i] == '\n' { + if !put_break(emitter) { + return false + } + *i++ + } else { + if !write(emitter, s, i) { + return false + } + if emitter.column == 0 { + emitter.space_above = true + } + emitter.column = 0 + emitter.line++ + // [Go] Do this here and above and drop from everywhere else (see commented lines). + emitter.indention = true + } + return true +} + +// Set an emitter error and return false. +func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_EMITTER_ERROR + emitter.problem = problem + return false +} + +// Emit an event. +func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.events = append(emitter.events, *event) + for !yaml_emitter_need_more_events(emitter) { + event := &emitter.events[emitter.events_head] + if !yaml_emitter_analyze_event(emitter, event) { + return false + } + if !yaml_emitter_state_machine(emitter, event) { + return false + } + yaml_event_delete(event) + emitter.events_head++ + } + return true +} + +// Check if we need to accumulate more events before emitting. +// +// We accumulate extra +// - 1 event for DOCUMENT-START +// - 2 events for SEQUENCE-START +// - 3 events for MAPPING-START +func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { + if emitter.events_head == len(emitter.events) { + return true + } + var accumulate int + switch emitter.events[emitter.events_head].typ { + case yaml_DOCUMENT_START_EVENT: + accumulate = 1 + break + case yaml_SEQUENCE_START_EVENT: + accumulate = 2 + break + case yaml_MAPPING_START_EVENT: + accumulate = 3 + break + default: + return false + } + if len(emitter.events)-emitter.events_head > accumulate { + return false + } + var level int + for i := emitter.events_head; i < len(emitter.events); i++ { + switch emitter.events[i].typ { + case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: + level++ + case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: + level-- + } + if level == 0 { + return false + } + } + return true +} + +// Append a directive to the directives stack. +func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { + for i := 0; i < len(emitter.tag_directives); i++ { + if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") + } + } + + // [Go] Do we actually need to copy this given garbage collection + // and the lack of deallocating destructors? + tag_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(tag_copy.handle, value.handle) + copy(tag_copy.prefix, value.prefix) + emitter.tag_directives = append(emitter.tag_directives, tag_copy) + return true +} + +// Increase the indentation level. +func yaml_emitter_increase_indent_compact(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool { + emitter.indents = append(emitter.indents, emitter.indent) + if emitter.indent < 0 { + if flow { + emitter.indent = emitter.best_indent + } else { + emitter.indent = 0 + } + } else if !indentless { + // [Go] This was changed so that indentations are more regular. + if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { + // The first indent inside a sequence will just skip the "- " indicator. + emitter.indent += 2 + } else { + // Everything else aligns to the chosen indentation. + emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent) + if compact_seq { + // The value compact_seq passed in is almost always set to `false` when this function is called, + // except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we + // are increasing the indent to account for sequence nodes, which will be correct because we need to + // subtract 2 to account for the - at the beginning of the sequence node. + emitter.indent = emitter.indent - 2 + } + } + } + return true +} + +// State dispatcher. +func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { + switch emitter.state { + default: + case yaml_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event) + + case yaml_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, true) + + case yaml_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, false) + + case yaml_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event) + + case yaml_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event) + + case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) + + case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) + + case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) + + case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) + + case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) + + case yaml_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) + + case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, false) + + case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, true) + + case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, false) + + case yaml_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") + } + panic("invalid emitter state") +} + +// Expect STREAM-START. +func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_STREAM_START_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") + } + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = event.encoding + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = yaml_UTF8_ENCODING + } + } + if emitter.best_indent < 2 || emitter.best_indent > 9 { + emitter.best_indent = 2 + } + if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { + emitter.best_width = 80 + } + if emitter.best_width < 0 { + emitter.best_width = 1<<31 - 1 + } + if emitter.line_break == yaml_ANY_BREAK { + emitter.line_break = yaml_LN_BREAK + } + + emitter.indent = -1 + emitter.line = 0 + emitter.column = 0 + emitter.whitespace = true + emitter.indention = true + emitter.space_above = true + emitter.foot_indent = -1 + + if emitter.encoding != yaml_UTF8_ENCODING { + if !yaml_emitter_write_bom(emitter) { + return false + } + } + emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE + return true +} + +// Expect DOCUMENT-START or STREAM-END. +func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + + if event.typ == yaml_DOCUMENT_START_EVENT { + + if event.version_directive != nil { + if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { + return false + } + } + + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { + return false + } + if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { + return false + } + } + + for i := 0; i < len(default_tag_directives); i++ { + tag_directive := &default_tag_directives[i] + if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { + return false + } + } + + implicit := event.implicit + if !first || emitter.canonical { + implicit = false + } + + if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if event.version_directive != nil { + implicit = false + if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if len(event.tag_directives) > 0 { + implicit = false + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { + return false + } + if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if yaml_emitter_check_empty_document(emitter) { + implicit = false + } + if !implicit { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { + return false + } + if emitter.canonical || true { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if len(emitter.head_comment) > 0 { + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !put_break(emitter) { + return false + } + } + + emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE + return true + } + + if event.typ == yaml_STREAM_END_EVENT { + if emitter.open_ended { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_END_STATE + return true + } + + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") +} + +// yaml_emitter_increase_indent preserves the original signature and delegates to +// yaml_emitter_increase_indent_compact without compact-sequence indentation +func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { + return yaml_emitter_increase_indent_compact(emitter, flow, indentless, false) +} + +// yaml_emitter_process_line_comment preserves the original signature and delegates to +// yaml_emitter_process_line_comment_linebreak passing false for linebreak +func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { + return yaml_emitter_process_line_comment_linebreak(emitter, false) +} + +// Expect the root node. +func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect DOCUMENT-END. +func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_DOCUMENT_END_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") + } + // [Go] Force document foot separation. + emitter.foot_indent = 0 + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.foot_indent = -1 + if !yaml_emitter_write_indent(emitter) { + return false + } + if !event.implicit { + // [Go] Allocate the slice elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_DOCUMENT_START_STATE + emitter.tag_directives = emitter.tag_directives[:0] + return true +} + +// Expect a flow item node. +func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_SEQUENCE_END_EVENT { + if emitter.canonical && !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.column == 0 || emitter.canonical && !first { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + + return true + } + + if !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if emitter.column == 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) + } else { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) + } + if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { + return false + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a flow key node. +func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_MAPPING_END_EVENT { + if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + + if !first && !trail { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if !yaml_emitter_process_head_comment(emitter) { + return false + } + + if emitter.column == 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a flow value node. +func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { + return false + } + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) + } else { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) + } + if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { + return false + } + if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a block item node. +func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + // emitter.mapping context tells us if we are currently in a mapping context. + // emiiter.column tells us which column we are in in the yaml output. 0 is the first char of the column. + // emitter.indentation tells us if the last character was an indentation character. + // emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements. + // So, `seq` means that we are in a mapping context, and we are either at the first char of the column or + // the last character was not an indentation character, and we consider '- ' part of the indentation + // for sequence elements. + seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) && + emitter.compact_sequence_indent + if !yaml_emitter_increase_indent_compact(emitter, false, false, seq) { + return false + } + } + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) + if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +// Expect a block key node. +func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, false) { + return false + } + } + if !yaml_emitter_process_head_comment(emitter) { + return false + } + if event.typ == yaml_MAPPING_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if len(emitter.line_comment) > 0 { + // [Go] A line comment was provided for the key. That's unusual as the + // scanner associates line comments with the value. Either way, + // save the line comment and render it appropriately later. + emitter.key_line_comment = emitter.line_comment + emitter.line_comment = nil + } + if yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block value node. +func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { + return false + } + } + if len(emitter.key_line_comment) > 0 { + // [Go] Line comments are generally associated with the value, but when there's + // no value on the same line as a mapping key they end up attached to the + // key itself. + if event.typ == yaml_SCALAR_EVENT { + if len(emitter.line_comment) == 0 { + // A scalar is coming and it has no line comments by itself yet, + // so just let it handle the line comment as usual. If it has a + // line comment, we can't have both so the one from the key is lost. + emitter.line_comment = emitter.key_line_comment + emitter.key_line_comment = nil + } + } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { + // An indented block follows, so write the comment right now. + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + if !yaml_emitter_process_line_comment(emitter) { + return false + } + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + } + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) + if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { + return false + } + if !yaml_emitter_process_line_comment(emitter) { + return false + } + if !yaml_emitter_process_foot_comment(emitter) { + return false + } + return true +} + +func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 +} + +// Expect a node. +func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, + root bool, sequence bool, mapping bool, simple_key bool) bool { + + emitter.root_context = root + emitter.sequence_context = sequence + emitter.mapping_context = mapping + emitter.simple_key_context = simple_key + + switch event.typ { + case yaml_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event) + case yaml_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event) + case yaml_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event) + case yaml_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event) + default: + return yaml_emitter_set_emitter_error(emitter, + fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) + } +} + +// Expect ALIAS. +func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SCALAR. +func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_select_scalar_style(emitter, event) { + return false + } + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + if !yaml_emitter_process_scalar(emitter) { + return false + } + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SEQUENCE-START. +func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || + yaml_emitter_check_empty_sequence(emitter) { + emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE + } + return true +} + +// Expect MAPPING-START. +func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || + yaml_emitter_check_empty_mapping(emitter) { + emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE + } + return true +} + +// Check if the document content is an empty scalar. +func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { + return false // [Go] Huh? +} + +// Check if the next events represent an empty sequence. +func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT +} + +// Check if the next events represent an empty mapping. +func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT +} + +// Check if the next node can be expressed as a simple key. +func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { + length := 0 + switch emitter.events[emitter.events_head].typ { + case yaml_ALIAS_EVENT: + length += len(emitter.anchor_data.anchor) + case yaml_SCALAR_EVENT: + if emitter.scalar_data.multiline { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + + len(emitter.scalar_data.value) + case yaml_SEQUENCE_START_EVENT: + if !yaml_emitter_check_empty_sequence(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + case yaml_MAPPING_START_EVENT: + if !yaml_emitter_check_empty_mapping(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + default: + return false + } + return length <= 128 +} + +// Determine an acceptable scalar style. +func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 + if no_tag && !event.implicit && !event.quoted_implicit { + return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") + } + + style := event.scalar_style() + if style == yaml_ANY_SCALAR_STYLE { + style = yaml_PLAIN_SCALAR_STYLE + } + if emitter.canonical { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + if emitter.simple_key_context && emitter.scalar_data.multiline { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + if style == yaml_PLAIN_SCALAR_STYLE { + if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || + emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if no_tag && !event.implicit { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { + if !emitter.scalar_data.single_quoted_allowed { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { + if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + + if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { + emitter.tag_data.handle = []byte{'!'} + } + emitter.scalar_data.style = style + return true +} + +// Write an anchor. +func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { + if emitter.anchor_data.anchor == nil { + return true + } + c := []byte{'&'} + if emitter.anchor_data.alias { + c[0] = '*' + } + if !yaml_emitter_write_indicator(emitter, c, true, false, false) { + return false + } + return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) +} + +// Write a tag. +func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { + if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { + return true + } + if len(emitter.tag_data.handle) > 0 { + if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { + return false + } + if len(emitter.tag_data.suffix) > 0 { + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + } + } else { + // [Go] Allocate these slices elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { + return false + } + } + return true +} + +// Write a scalar. +func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { + switch emitter.scalar_data.style { + case yaml_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) + + case yaml_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) + } + panic("unknown scalar style") +} + +// Write a head comment. +func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { + if len(emitter.tail_comment) > 0 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { + return false + } + emitter.tail_comment = emitter.tail_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } + } + + if len(emitter.head_comment) == 0 { + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.head_comment) { + return false + } + emitter.head_comment = emitter.head_comment[:0] + return true +} + +// Write an line comment. +func yaml_emitter_process_line_comment_linebreak(emitter *yaml_emitter_t, linebreak bool) bool { + if len(emitter.line_comment) == 0 { + // The next 3 lines are needed to resolve an issue with leading newlines + // See https://github.com/go-yaml/yaml/issues/755 + // When linebreak is set to true, put_break will be called and will add + // the needed newline. + if linebreak && !put_break(emitter) { + return false + } + return true + } + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !yaml_emitter_write_comment(emitter, emitter.line_comment) { + return false + } + emitter.line_comment = emitter.line_comment[:0] + return true +} + +// Write a foot comment. +func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { + if len(emitter.foot_comment) == 0 { + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { + return false + } + emitter.foot_comment = emitter.foot_comment[:0] + emitter.foot_indent = emitter.indent + if emitter.foot_indent < 0 { + emitter.foot_indent = 0 + } + return true +} + +// Check if a %YAML directive is valid. +func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { + if version_directive.major != 1 || version_directive.minor != 1 { + return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") + } + return true +} + +// Check if a %TAG directive is valid. +func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { + handle := tag_directive.handle + prefix := tag_directive.prefix + if len(handle) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") + } + if handle[0] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") + } + if handle[len(handle)-1] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") + } + for i := 1; i < len(handle)-1; i += width(handle[i]) { + if !is_alpha(handle, i) { + return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") + } + } + if len(prefix) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") + } + return true +} + +// Check if an anchor is valid. +func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { + if len(anchor) == 0 { + problem := "anchor value must not be empty" + if alias { + problem = "alias value must not be empty" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + for i := 0; i < len(anchor); i += width(anchor[i]) { + if !is_alpha(anchor, i) { + problem := "anchor value must contain alphanumerical characters only" + if alias { + problem = "alias value must contain alphanumerical characters only" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + } + emitter.anchor_data.anchor = anchor + emitter.anchor_data.alias = alias + return true +} + +// Check if a tag is valid. +func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { + if len(tag) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") + } + for i := 0; i < len(emitter.tag_directives); i++ { + tag_directive := &emitter.tag_directives[i] + if bytes.HasPrefix(tag, tag_directive.prefix) { + emitter.tag_data.handle = tag_directive.handle + emitter.tag_data.suffix = tag[len(tag_directive.prefix):] + return true + } + } + emitter.tag_data.suffix = tag + return true +} + +// Check if a scalar is valid. +func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { + var ( + block_indicators = false + flow_indicators = false + line_breaks = false + special_characters = false + tab_characters = false + + leading_space = false + leading_break = false + trailing_space = false + trailing_break = false + break_space = false + space_break = false + + preceded_by_whitespace = false + followed_by_whitespace = false + previous_space = false + previous_break = false + ) + + emitter.scalar_data.value = value + + if len(value) == 0 { + emitter.scalar_data.multiline = false + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = false + return true + } + + if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { + block_indicators = true + flow_indicators = true + } + + preceded_by_whitespace = true + for i, w := 0, 0; i < len(value); i += w { + w = width(value[i]) + followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) + + if i == 0 { + switch value[i] { + case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': + flow_indicators = true + block_indicators = true + case '?', ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '-': + if followed_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } else { + switch value[i] { + case ',', '?', '[', ']', '{', '}': + flow_indicators = true + case ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '#': + if preceded_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } + + if value[i] == '\t' { + tab_characters = true + } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { + special_characters = true + } + if is_space(value, i) { + if i == 0 { + leading_space = true + } + if i+width(value[i]) == len(value) { + trailing_space = true + } + if previous_break { + break_space = true + } + previous_space = true + previous_break = false + } else if is_break(value, i) { + line_breaks = true + if i == 0 { + leading_break = true + } + if i+width(value[i]) == len(value) { + trailing_break = true + } + if previous_space { + space_break = true + } + previous_space = false + previous_break = true + } else { + previous_space = false + previous_break = false + } + + // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. + preceded_by_whitespace = is_blankz(value, i) + } + + emitter.scalar_data.multiline = line_breaks + emitter.scalar_data.flow_plain_allowed = true + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = true + + if leading_space || leading_break || trailing_space || trailing_break { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if trailing_space { + emitter.scalar_data.block_allowed = false + } + if break_space { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || tab_characters || special_characters { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || special_characters { + emitter.scalar_data.block_allowed = false + } + if line_breaks { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if flow_indicators { + emitter.scalar_data.flow_plain_allowed = false + } + if block_indicators { + emitter.scalar_data.block_plain_allowed = false + } + return true +} + +// Check if the event data is valid. +func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + emitter.anchor_data.anchor = nil + emitter.tag_data.handle = nil + emitter.tag_data.suffix = nil + emitter.scalar_data.value = nil + + if len(event.head_comment) > 0 { + emitter.head_comment = event.head_comment + } + if len(event.line_comment) > 0 { + emitter.line_comment = event.line_comment + } + if len(event.foot_comment) > 0 { + emitter.foot_comment = event.foot_comment + } + if len(event.tail_comment) > 0 { + emitter.tail_comment = event.tail_comment + } + + switch event.typ { + case yaml_ALIAS_EVENT: + if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { + return false + } + + case yaml_SCALAR_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + if !yaml_emitter_analyze_scalar(emitter, event.value) { + return false + } + + case yaml_SEQUENCE_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + + case yaml_MAPPING_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + } + return true +} + +// Write the BOM character. +func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { + if !flush(emitter) { + return false + } + pos := emitter.buffer_pos + emitter.buffer[pos+0] = '\xEF' + emitter.buffer[pos+1] = '\xBB' + emitter.buffer[pos+2] = '\xBF' + emitter.buffer_pos += 3 + return true +} + +func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { + indent := emitter.indent + if indent < 0 { + indent = 0 + } + if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { + if !put_break(emitter) { + return false + } + } + if emitter.foot_indent == indent { + if !put_break(emitter) { + return false + } + } + for emitter.column < indent { + if !put(emitter, ' ') { + return false + } + } + emitter.whitespace = true + //emitter.indention = true + emitter.space_above = false + emitter.foot_indent = -1 + return true +} + +func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, indicator) { + return false + } + emitter.whitespace = is_whitespace + emitter.indention = (emitter.indention && is_indention) + emitter.open_ended = false + return true +} + +func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + for i := 0; i < len(value); { + var must_write bool + switch value[i] { + case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': + must_write = true + default: + must_write = is_alpha(value, i) + } + if must_write { + if !write(emitter, value, &i) { + return false + } + } else { + w := width(value[i]) + for k := 0; k < w; k++ { + octet := value[i] + i++ + if !put(emitter, '%') { + return false + } + + c := octet >> 4 + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + + c = octet & 0x0f + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + } + } + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + if len(value) > 0 && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + + if len(value) > 0 { + emitter.whitespace = false + } + emitter.indention = false + if emitter.root_context { + emitter.open_ended = true + } + + return true +} + +func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { + return false + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if value[i] == '\'' { + if !put(emitter, '\'') { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + spaces := false + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { + return false + } + + for i := 0; i < len(value); { + if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || + is_bom(value, i) || is_break(value, i) || + value[i] == '"' || value[i] == '\\' { + + octet := value[i] + + var w int + var v rune + switch { + case octet&0x80 == 0x00: + w, v = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, v = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, v = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, v = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = value[i+k] + v = (v << 6) + (rune(octet) & 0x3F) + } + i += w + + if !put(emitter, '\\') { + return false + } + + var ok bool + switch v { + case 0x00: + ok = put(emitter, '0') + case 0x07: + ok = put(emitter, 'a') + case 0x08: + ok = put(emitter, 'b') + case 0x09: + ok = put(emitter, 't') + case 0x0A: + ok = put(emitter, 'n') + case 0x0b: + ok = put(emitter, 'v') + case 0x0c: + ok = put(emitter, 'f') + case 0x0d: + ok = put(emitter, 'r') + case 0x1b: + ok = put(emitter, 'e') + case 0x22: + ok = put(emitter, '"') + case 0x5c: + ok = put(emitter, '\\') + case 0x85: + ok = put(emitter, 'N') + case 0xA0: + ok = put(emitter, '_') + case 0x2028: + ok = put(emitter, 'L') + case 0x2029: + ok = put(emitter, 'P') + default: + if v <= 0xFF { + ok = put(emitter, 'x') + w = 2 + } else if v <= 0xFFFF { + ok = put(emitter, 'u') + w = 4 + } else { + ok = put(emitter, 'U') + w = 8 + } + for k := (w - 1) * 4; ok && k >= 0; k -= 4 { + digit := byte((v >> uint(k)) & 0x0F) + if digit < 10 { + ok = put(emitter, digit+'0') + } else { + ok = put(emitter, digit+'A'-10) + } + } + } + if !ok { + return false + } + spaces = false + } else if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if is_space(value, i+1) { + if !put(emitter, '\\') { + return false + } + } + i += width(value[i]) + } else if !write(emitter, value, &i) { + return false + } + spaces = true + } else { + if !write(emitter, value, &i) { + return false + } + spaces = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { + if is_space(value, 0) || is_break(value, 0) { + indent_hint := []byte{'0' + byte(emitter.best_indent)} + if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { + return false + } + } + + emitter.open_ended = false + + var chomp_hint [1]byte + if len(value) == 0 { + chomp_hint[0] = '-' + } else { + i := len(value) - 1 + for value[i]&0xC0 == 0x80 { + i-- + } + if !is_break(value, i) { + chomp_hint[0] = '-' + } else if i == 0 { + chomp_hint[0] = '+' + emitter.open_ended = true + } else { + i-- + for value[i]&0xC0 == 0x80 { + i-- + } + if is_break(value, i) { + chomp_hint[0] = '+' + emitter.open_ended = true + } + } + } + if chomp_hint[0] != 0 { + if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { + return false + } + } + return true +} + +func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !yaml_emitter_process_line_comment_linebreak(emitter, true) { + return false + } + //emitter.indention = true + emitter.whitespace = true + breaks := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + + return true +} + +func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !yaml_emitter_process_line_comment_linebreak(emitter, true) { + return false + } + + //emitter.indention = true + emitter.whitespace = true + + breaks := true + leading_spaces := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !breaks && !leading_spaces && value[i] == '\n' { + k := 0 + for is_break(value, k) { + k += width(value[k]) + } + if !is_blankz(value, k) { + if !put_break(emitter) { + return false + } + } + } + if !write_break(emitter, value, &i) { + return false + } + //emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + leading_spaces = is_blank(value, i) + } + if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + emitter.indention = false + breaks = false + } + } + return true +} + +func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { + breaks := false + pound := false + for i := 0; i < len(comment); { + if is_break(comment, i) { + if !write_break(emitter, comment, &i) { + return false + } + //emitter.indention = true + breaks = true + pound = false + } else { + if breaks && !yaml_emitter_write_indent(emitter) { + return false + } + if !pound { + if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { + return false + } + pound = true + } + if !write(emitter, comment, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + if !breaks && !put_break(emitter) { + return false + } + + emitter.whitespace = true + //emitter.indention = true + return true +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/encode.go b/event-processor/vendor/go.yaml.in/yaml/v3/encode.go new file mode 100644 index 00000000..de9e72a3 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/encode.go @@ -0,0 +1,577 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding" + "fmt" + "io" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +type encoder struct { + emitter yaml_emitter_t + event yaml_event_t + out []byte + flow bool + indent int + doneInit bool +} + +func newEncoder() *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_string(&e.emitter, &e.out) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func newEncoderWithWriter(w io.Writer) *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_writer(&e.emitter, w) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func (e *encoder) init() { + if e.doneInit { + return + } + if e.indent == 0 { + e.indent = 4 + } + e.emitter.best_indent = e.indent + yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) + e.emit() + e.doneInit = true +} + +func (e *encoder) finish() { + e.emitter.open_ended = false + yaml_stream_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) destroy() { + yaml_emitter_delete(&e.emitter) +} + +func (e *encoder) emit() { + // This will internally delete the e.event value. + e.must(yaml_emitter_emit(&e.emitter, &e.event)) +} + +func (e *encoder) must(ok bool) { + if !ok { + msg := e.emitter.problem + if msg == "" { + msg = "unknown problem generating YAML content" + } + failf("%s", msg) + } +} + +func (e *encoder) marshalDoc(tag string, in reflect.Value) { + e.init() + var node *Node + if in.IsValid() { + node, _ = in.Interface().(*Node) + } + if node != nil && node.Kind == DocumentNode { + e.nodev(in) + } else { + yaml_document_start_event_initialize(&e.event, nil, nil, true) + e.emit() + e.marshal(tag, in) + yaml_document_end_event_initialize(&e.event, true) + e.emit() + } +} + +func (e *encoder) marshal(tag string, in reflect.Value) { + tag = shortTag(tag) + if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { + e.nilv() + return + } + iface := in.Interface() + switch value := iface.(type) { + case *Node: + e.nodev(in) + return + case Node: + if !in.CanAddr() { + var n = reflect.New(in.Type()).Elem() + n.Set(in) + in = n + } + e.nodev(in.Addr()) + return + case time.Time: + e.timev(tag, in) + return + case *time.Time: + e.timev(tag, in.Elem()) + return + case time.Duration: + e.stringv(tag, reflect.ValueOf(value.String())) + return + case Marshaler: + v, err := value.MarshalYAML() + if err != nil { + fail(err) + } + if v == nil { + e.nilv() + return + } + e.marshal(tag, reflect.ValueOf(v)) + return + case encoding.TextMarshaler: + text, err := value.MarshalText() + if err != nil { + fail(err) + } + in = reflect.ValueOf(string(text)) + case nil: + e.nilv() + return + } + switch in.Kind() { + case reflect.Interface: + e.marshal(tag, in.Elem()) + case reflect.Map: + e.mapv(tag, in) + case reflect.Ptr: + e.marshal(tag, in.Elem()) + case reflect.Struct: + e.structv(tag, in) + case reflect.Slice, reflect.Array: + e.slicev(tag, in) + case reflect.String: + e.stringv(tag, in) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + e.intv(tag, in) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + e.uintv(tag, in) + case reflect.Float32, reflect.Float64: + e.floatv(tag, in) + case reflect.Bool: + e.boolv(tag, in) + default: + panic("cannot marshal type: " + in.Type().String()) + } +} + +func (e *encoder) mapv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + keys := keyList(in.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + e.marshal("", k) + e.marshal("", in.MapIndex(k)) + } + }) +} + +func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { + for _, num := range index { + for { + if v.Kind() == reflect.Ptr { + if v.IsNil() { + return reflect.Value{} + } + v = v.Elem() + continue + } + break + } + v = v.Field(num) + } + return v +} + +func (e *encoder) structv(tag string, in reflect.Value) { + sinfo, err := getStructInfo(in.Type()) + if err != nil { + panic(err) + } + e.mappingv(tag, func() { + for _, info := range sinfo.FieldsList { + var value reflect.Value + if info.Inline == nil { + value = in.Field(info.Num) + } else { + value = e.fieldByIndex(in, info.Inline) + if !value.IsValid() { + continue + } + } + if info.OmitEmpty && isZero(value) { + continue + } + e.marshal("", reflect.ValueOf(info.Key)) + e.flow = info.Flow + e.marshal("", value) + } + if sinfo.InlineMap >= 0 { + m := in.Field(sinfo.InlineMap) + if m.Len() > 0 { + e.flow = false + keys := keyList(m.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + if _, found := sinfo.FieldsMap[k.String()]; found { + panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) + } + e.marshal("", k) + e.flow = false + e.marshal("", m.MapIndex(k)) + } + } + } + }) +} + +func (e *encoder) mappingv(tag string, f func()) { + implicit := tag == "" + style := yaml_BLOCK_MAPPING_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_MAPPING_STYLE + } + yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) + e.emit() + f() + yaml_mapping_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) slicev(tag string, in reflect.Value) { + implicit := tag == "" + style := yaml_BLOCK_SEQUENCE_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + n := in.Len() + for i := 0; i < n; i++ { + e.marshal("", in.Index(i)) + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.emit() +} + +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60Float(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base60float.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + +// isOldBool returns whether s is bool notation as defined in YAML 1.1. +// +// We continue to force strings that YAML 1.1 would interpret as booleans to be +// rendered as quotes strings so that the marshalled output valid for YAML 1.1 +// parsing. +func isOldBool(s string) (result bool) { + switch s { + case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", + "n", "N", "no", "No", "NO", "off", "Off", "OFF": + return true + default: + return false + } +} + +func (e *encoder) stringv(tag string, in reflect.Value) { + var style yaml_scalar_style_t + s := in.String() + canUsePlain := true + switch { + case !utf8.ValidString(s): + if tag == binaryTag { + failf("explicitly tagged !!binary data must be base64-encoded") + } + if tag != "" { + failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + } + // It can't be encoded directly as YAML so use a binary tag + // and encode it as base64. + tag = binaryTag + s = encodeBase64(s) + case tag == "": + // Check to see if it would resolve to a specific + // tag when encoded unquoted. If it doesn't, + // there's no need to quote it. + rtag, _ := resolve("", s) + canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) + } + // Note: it's possible for user code to emit invalid YAML + // if they explicitly specify a tag and a string containing + // text that's incompatible with that tag. + switch { + case strings.Contains(s, "\n"): + if e.flow { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } else { + style = yaml_LITERAL_SCALAR_STYLE + } + case canUsePlain: + style = yaml_PLAIN_SCALAR_STYLE + default: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + e.emitScalar(s, "", tag, style, nil, nil, nil, nil) +} + +func (e *encoder) boolv(tag string, in reflect.Value) { + var s string + if in.Bool() { + s = "true" + } else { + s = "false" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) intv(tag string, in reflect.Value) { + s := strconv.FormatInt(in.Int(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) uintv(tag string, in reflect.Value) { + s := strconv.FormatUint(in.Uint(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) timev(tag string, in reflect.Value) { + t := in.Interface().(time.Time) + s := t.Format(time.RFC3339Nano) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) floatv(tag string, in reflect.Value) { + // Issue #352: When formatting, use the precision of the underlying value + precision := 64 + if in.Kind() == reflect.Float32 { + precision = 32 + } + + s := strconv.FormatFloat(in.Float(), 'g', -1, precision) + switch s { + case "+Inf": + s = ".inf" + case "-Inf": + s = "-.inf" + case "NaN": + s = ".nan" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) nilv() { + e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) +} + +func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { + // TODO Kill this function. Replace all initialize calls by their underlining Go literals. + implicit := tag == "" + if !implicit { + tag = longTag(tag) + } + e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) + e.event.head_comment = head + e.event.line_comment = line + e.event.foot_comment = foot + e.event.tail_comment = tail + e.emit() +} + +func (e *encoder) nodev(in reflect.Value) { + e.node(in.Interface().(*Node), "") +} + +func (e *encoder) node(node *Node, tail string) { + // Zero nodes behave as nil. + if node.Kind == 0 && node.IsZero() { + e.nilv() + return + } + + // If the tag was not explicitly requested, and dropping it won't change the + // implicit tag of the value, don't include it in the presentation. + var tag = node.Tag + var stag = shortTag(tag) + var forceQuoting bool + if tag != "" && node.Style&TaggedStyle == 0 { + if node.Kind == ScalarNode { + if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { + tag = "" + } else { + rtag, _ := resolve("", node.Value) + if rtag == stag { + tag = "" + } else if stag == strTag { + tag = "" + forceQuoting = true + } + } + } else { + var rtag string + switch node.Kind { + case MappingNode: + rtag = mapTag + case SequenceNode: + rtag = seqTag + } + if rtag == stag { + tag = "" + } + } + } + + switch node.Kind { + case DocumentNode: + yaml_document_start_event_initialize(&e.event, nil, nil, true) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + for _, node := range node.Content { + e.node(node, "") + } + yaml_document_end_event_initialize(&e.event, true) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case SequenceNode: + style := yaml_BLOCK_SEQUENCE_STYLE + if node.Style&FlowStyle != 0 { + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + for _, node := range node.Content { + e.node(node, "") + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case MappingNode: + style := yaml_BLOCK_MAPPING_STYLE + if node.Style&FlowStyle != 0 { + style = yaml_FLOW_MAPPING_STYLE + } + yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) + e.event.tail_comment = []byte(tail) + e.event.head_comment = []byte(node.HeadComment) + e.emit() + + // The tail logic below moves the foot comment of prior keys to the following key, + // since the value for each key may be a nested structure and the foot needs to be + // processed only the entirety of the value is streamed. The last tail is processed + // with the mapping end event. + var tail string + for i := 0; i+1 < len(node.Content); i += 2 { + k := node.Content[i] + foot := k.FootComment + if foot != "" { + kopy := *k + kopy.FootComment = "" + k = &kopy + } + e.node(k, tail) + tail = foot + + v := node.Content[i+1] + e.node(v, "") + } + + yaml_mapping_end_event_initialize(&e.event) + e.event.tail_comment = []byte(tail) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case AliasNode: + yaml_alias_event_initialize(&e.event, []byte(node.Value)) + e.event.head_comment = []byte(node.HeadComment) + e.event.line_comment = []byte(node.LineComment) + e.event.foot_comment = []byte(node.FootComment) + e.emit() + + case ScalarNode: + value := node.Value + if !utf8.ValidString(value) { + if stag == binaryTag { + failf("explicitly tagged !!binary data must be base64-encoded") + } + if stag != "" { + failf("cannot marshal invalid UTF-8 data as %s", stag) + } + // It can't be encoded directly as YAML so use a binary tag + // and encode it as base64. + tag = binaryTag + value = encodeBase64(value) + } + + style := yaml_PLAIN_SCALAR_STYLE + switch { + case node.Style&DoubleQuotedStyle != 0: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + case node.Style&SingleQuotedStyle != 0: + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + case node.Style&LiteralStyle != 0: + style = yaml_LITERAL_SCALAR_STYLE + case node.Style&FoldedStyle != 0: + style = yaml_FOLDED_SCALAR_STYLE + case strings.Contains(value, "\n"): + style = yaml_LITERAL_SCALAR_STYLE + case forceQuoting: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) + default: + failf("cannot encode node with unknown kind %d", node.Kind) + } +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/parserc.go b/event-processor/vendor/go.yaml.in/yaml/v3/parserc.go new file mode 100644 index 00000000..25fe8236 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/parserc.go @@ -0,0 +1,1274 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" +) + +// The parser implements the following grammar: +// +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// implicit_document ::= block_node DOCUMENT-END* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// block_node_or_indentless_sequence ::= +// ALIAS +// | properties (block_content | indentless_block_sequence)? +// | block_content +// | indentless_block_sequence +// block_node ::= ALIAS +// | properties block_content? +// | block_content +// flow_node ::= ALIAS +// | properties flow_content? +// | flow_content +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// block_content ::= block_collection | flow_collection | SCALAR +// flow_content ::= flow_collection | SCALAR +// block_collection ::= block_sequence | block_mapping +// flow_collection ::= flow_sequence | flow_mapping +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// block_mapping ::= BLOCK-MAPPING_START +// ((KEY block_node_or_indentless_sequence?)? +// (VALUE block_node_or_indentless_sequence?)?)* +// BLOCK-END +// flow_sequence ::= FLOW-SEQUENCE-START +// (flow_sequence_entry FLOW-ENTRY)* +// flow_sequence_entry? +// FLOW-SEQUENCE-END +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// flow_mapping ::= FLOW-MAPPING-START +// (flow_mapping_entry FLOW-ENTRY)* +// flow_mapping_entry? +// FLOW-MAPPING-END +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + +// Peek the next token in the token queue. +func peek_token(parser *yaml_parser_t) *yaml_token_t { + if parser.token_available || yaml_parser_fetch_more_tokens(parser) { + token := &parser.tokens[parser.tokens_head] + yaml_parser_unfold_comments(parser, token) + return token + } + return nil +} + +// yaml_parser_unfold_comments walks through the comments queue and joins all +// comments behind the position of the provided token into the respective +// top-level comment slices in the parser. +func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { + for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { + comment := &parser.comments[parser.comments_head] + if len(comment.head) > 0 { + if token.typ == yaml_BLOCK_END_TOKEN { + // No heads on ends, so keep comment.head for a follow up token. + break + } + if len(parser.head_comment) > 0 { + parser.head_comment = append(parser.head_comment, '\n') + } + parser.head_comment = append(parser.head_comment, comment.head...) + } + if len(comment.foot) > 0 { + if len(parser.foot_comment) > 0 { + parser.foot_comment = append(parser.foot_comment, '\n') + } + parser.foot_comment = append(parser.foot_comment, comment.foot...) + } + if len(comment.line) > 0 { + if len(parser.line_comment) > 0 { + parser.line_comment = append(parser.line_comment, '\n') + } + parser.line_comment = append(parser.line_comment, comment.line...) + } + *comment = yaml_comment_t{} + parser.comments_head++ + } +} + +// Remove the next token from the queue (must be called after peek_token). +func skip_token(parser *yaml_parser_t) { + parser.token_available = false + parser.tokens_parsed++ + parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN + parser.tokens_head++ +} + +// Get the next event. +func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { + // Erase the event object. + *event = yaml_event_t{} + + // No events after the end of the stream or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { + return true + } + + // Generate the next event. + return yaml_parser_state_machine(parser, event) +} + +// Set parser error. +func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +// State dispatcher. +func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { + //trace("yaml_parser_state_machine", "state:", parser.state.String()) + + switch parser.state { + case yaml_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event) + + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, true) + + case yaml_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, false) + + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event) + + case yaml_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event) + + case yaml_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, true, false) + + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, true, true) + + case yaml_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, false, false) + + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, true) + + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, false) + + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event) + + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, true) + + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, false) + + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, true) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, false) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) + + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, true) + + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, true) + + default: + panic("invalid parser state") + } +} + +// Parse the production: +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// +// ************ +func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_STREAM_START_TOKEN { + return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) + } + parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + encoding: token.encoding, + } + skip_token(parser) + return true +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// +// * +// +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +// ************************* +func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { + + token := peek_token(parser) + if token == nil { + return false + } + + // Parse extra document end indicators. + if !implicit { + for token.typ == yaml_DOCUMENT_END_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && + token.typ != yaml_TAG_DIRECTIVE_TOKEN && + token.typ != yaml_DOCUMENT_START_TOKEN && + token.typ != yaml_STREAM_END_TOKEN { + // Parse an implicit document. + if !yaml_parser_process_directives(parser, nil, nil) { + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_BLOCK_NODE_STATE + + var head_comment []byte + if len(parser.head_comment) > 0 { + // [Go] Scan the header comment backwards, and if an empty line is found, break + // the header so the part before the last empty line goes into the + // document header, while the bottom of it goes into a follow up event. + for i := len(parser.head_comment) - 1; i > 0; i-- { + if parser.head_comment[i] == '\n' { + if i == len(parser.head_comment)-1 { + head_comment = parser.head_comment[:i] + parser.head_comment = parser.head_comment[i+1:] + break + } else if parser.head_comment[i-1] == '\n' { + head_comment = parser.head_comment[:i-1] + parser.head_comment = parser.head_comment[i+1:] + break + } + } + } + } + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + + head_comment: head_comment, + } + + } else if token.typ != yaml_STREAM_END_TOKEN { + // Parse an explicit document. + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + start_mark := token.start_mark + if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { + return false + } + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_DOCUMENT_START_TOKEN { + yaml_parser_set_parser_error(parser, + "did not find expected ", token.start_mark) + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE + end_mark := token.end_mark + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: false, + } + skip_token(parser) + + } else { + // Parse the stream end. + parser.state = yaml_PARSE_END_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + } + + return true +} + +// Parse the productions: +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +// *********** +func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || + token.typ == yaml_TAG_DIRECTIVE_TOKEN || + token.typ == yaml_DOCUMENT_START_TOKEN || + token.typ == yaml_DOCUMENT_END_TOKEN || + token.typ == yaml_STREAM_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + return yaml_parser_process_empty_scalar(parser, event, + token.start_mark) + } + return yaml_parser_parse_node(parser, event, true, false) +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// +// ************* +// +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + start_mark := token.start_mark + end_mark := token.start_mark + + implicit := true + if token.typ == yaml_DOCUMENT_END_TOKEN { + end_mark = token.end_mark + skip_token(parser) + implicit = false + } + + parser.tag_directives = parser.tag_directives[:0] + + parser.state = yaml_PARSE_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + start_mark: start_mark, + end_mark: end_mark, + implicit: implicit, + } + yaml_parser_set_event_comments(parser, event) + if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { + event.foot_comment = event.head_comment + event.head_comment = nil + } + return true +} + +func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { + event.head_comment = parser.head_comment + event.line_comment = parser.line_comment + event.foot_comment = parser.foot_comment + parser.head_comment = nil + parser.line_comment = nil + parser.foot_comment = nil + parser.tail_comment = nil + parser.stem_comment = nil +} + +// Parse the productions: +// block_node_or_indentless_sequence ::= +// +// ALIAS +// ***** +// | properties (block_content | indentless_block_sequence)? +// ********** * +// | block_content | indentless_block_sequence +// * +// +// block_node ::= ALIAS +// +// ***** +// | properties block_content? +// ********** * +// | block_content +// * +// +// flow_node ::= ALIAS +// +// ***** +// | properties flow_content? +// ********** * +// | flow_content +// * +// +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// +// ************************* +// +// block_content ::= block_collection | flow_collection | SCALAR +// +// ****** +// +// flow_content ::= flow_collection | SCALAR +// +// ****** +func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { + //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_ALIAS_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + anchor: token.value, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + + start_mark := token.start_mark + end_mark := token.start_mark + + var tag_token bool + var tag_handle, tag_suffix, anchor []byte + var tag_mark yaml_mark_t + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + start_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } else if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + start_mark = token.start_mark + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + var tag []byte + if tag_token { + if len(tag_handle) == 0 { + tag = tag_suffix + tag_suffix = nil + } else { + for i := range parser.tag_directives { + if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { + tag = append([]byte(nil), parser.tag_directives[i].prefix...) + tag = append(tag, tag_suffix...) + break + } + } + if len(tag) == 0 { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark) + return false + } + } + } + + implicit := len(tag) == 0 + if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_SCALAR_TOKEN { + var plain_implicit, quoted_implicit bool + end_mark = token.end_mark + if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { + plain_implicit = true + } else if len(tag) == 0 { + quoted_implicit = true + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + value: token.value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(token.style), + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { + // [Go] Some of the events below can be merged as they differ only on style. + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), + } + yaml_parser_set_event_comments(parser, event) + return true + } + if token.typ == yaml_FLOW_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + yaml_parser_set_event_comments(parser, event) + return true + } + if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + if parser.stem_comment != nil { + event.head_comment = parser.stem_comment + parser.stem_comment = nil + } + return true + } + if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), + } + if parser.stem_comment != nil { + event.head_comment = parser.stem_comment + parser.stem_comment = nil + } + return true + } + if len(anchor) > 0 || len(tag) > 0 { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + quoted_implicit: false, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true + } + + context := "while parsing a flow node" + if block { + context = "while parsing a block node" + } + yaml_parser_set_parser_error_context(parser, context, start_mark, + "did not find expected node content", token.start_mark) + return false +} + +// Parse the productions: +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// +// ******************** *********** * ********* +func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + if token == nil { + return false + } + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + prior_head_len := len(parser.head_comment) + skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } else { + parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } + if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", context_mark, + "did not find expected '-' indicator", token.start_mark) +} + +// Parse the productions: +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// +// *********** * +func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + prior_head_len := len(parser.head_comment) + skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && + token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? + } + return true +} + +// Split stem comment from head comment. +// +// When a sequence or map is found under a sequence entry, the former head comment +// is assigned to the underlying sequence or map as a whole, not the individual +// sequence or map entry as would be expected otherwise. To handle this case the +// previous head comment is moved aside as the stem comment. +func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { + if stem_len == 0 { + return + } + + token := peek_token(parser) + if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { + return + } + + parser.stem_comment = parser.head_comment[:stem_len] + if len(parser.head_comment) == stem_len { + parser.head_comment = nil + } else { + // Copy suffix to prevent very strange bugs if someone ever appends + // further bytes to the prefix in the stem_comment slice above. + parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) + } +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ******************* +// ((KEY block_node_or_indentless_sequence?)? +// *** * +// (VALUE block_node_or_indentless_sequence?)?)* +// +// BLOCK-END +// ********* +func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + if token == nil { + return false + } + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + // [Go] A tail comment was left from the prior mapping value processed. Emit an event + // as it needs to be processed with that value and not the following key. + if len(parser.tail_comment) > 0 { + *event = yaml_event_t{ + typ: yaml_TAIL_COMMENT_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + foot_comment: parser.tail_comment, + } + parser.tail_comment = nil + return true + } + + if token.typ == yaml_KEY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } else { + parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } else if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", context_mark, + "did not find expected key", token.start_mark) +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ((KEY block_node_or_indentless_sequence?)? +// +// (VALUE block_node_or_indentless_sequence?)?)* +// ***** * +// BLOCK-END +func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence ::= FLOW-SEQUENCE-START +// +// ******************* +// (flow_sequence_entry FLOW-ENTRY)* +// * ********** +// flow_sequence_entry? +// * +// FLOW-SEQUENCE-END +// ***************** +// +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// +// * +func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + if token == nil { + return false + } + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", context_mark, + "did not find expected ',' or ']'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + implicit: true, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + skip_token(parser) + return true + } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + + skip_token(parser) + return true +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// +// *** * +func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + mark := token.end_mark + skip_token(parser) + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// +// ***** * +func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// +// * +func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? + } + return true +} + +// Parse the productions: +// flow_mapping ::= FLOW-MAPPING-START +// +// ****************** +// (flow_mapping_entry FLOW-ENTRY)* +// * ********** +// flow_mapping_entry? +// ****************** +// FLOW-MAPPING-END +// **************** +// +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// - *** * +func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", context_mark, + "did not find expected ',' or '}'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } else { + parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + yaml_parser_set_event_comments(parser, event) + skip_token(parser) + return true +} + +// Parse the productions: +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// - ***** * +func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { + token := peek_token(parser) + if token == nil { + return false + } + if empty { + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Generate an empty scalar event. +func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: mark, + end_mark: mark, + value: nil, // Empty + implicit: true, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true +} + +var default_tag_directives = []yaml_tag_directive_t{ + {[]byte("!"), []byte("!")}, + {[]byte("!!"), []byte("tag:yaml.org,2002:")}, +} + +// Parse directives. +func yaml_parser_process_directives(parser *yaml_parser_t, + version_directive_ref **yaml_version_directive_t, + tag_directives_ref *[]yaml_tag_directive_t) bool { + + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + + token := peek_token(parser) + if token == nil { + return false + } + + for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { + if version_directive != nil { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token.start_mark) + return false + } + if token.major != 1 || token.minor != 1 { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token.start_mark) + return false + } + version_directive = &yaml_version_directive_t{ + major: token.major, + minor: token.minor, + } + } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { + value := yaml_tag_directive_t{ + handle: token.value, + prefix: token.prefix, + } + if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { + return false + } + tag_directives = append(tag_directives, value) + } + + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + + for i := range default_tag_directives { + if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { + return false + } + } + + if version_directive_ref != nil { + *version_directive_ref = version_directive + } + if tag_directives_ref != nil { + *tag_directives_ref = tag_directives + } + return true +} + +// Append a tag directive to the directives stack. +func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { + for i := range parser.tag_directives { + if bytes.Equal(value.handle, parser.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) + } + } + + // [Go] I suspect the copy is unnecessary. This was likely done + // because there was no way to track ownership of the data. + value_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(value_copy.handle, value.handle) + copy(value_copy.prefix, value.prefix) + parser.tag_directives = append(parser.tag_directives, value_copy) + return true +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/readerc.go b/event-processor/vendor/go.yaml.in/yaml/v3/readerc.go new file mode 100644 index 00000000..56af2453 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/readerc.go @@ -0,0 +1,434 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "io" +) + +// Set the reader error and return 0. +func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { + parser.error = yaml_READER_ERROR + parser.problem = problem + parser.problem_offset = offset + parser.problem_value = value + return false +} + +// Byte order marks. +const ( + bom_UTF8 = "\xef\xbb\xbf" + bom_UTF16LE = "\xff\xfe" + bom_UTF16BE = "\xfe\xff" +) + +// Determine the input stream encoding by checking the BOM symbol. If no BOM is +// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. +func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { + // Ensure that we had enough bytes in the raw buffer. + for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { + if !yaml_parser_update_raw_buffer(parser) { + return false + } + } + + // Determine the encoding. + buf := parser.raw_buffer + pos := parser.raw_buffer_pos + avail := len(buf) - pos + if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { + parser.encoding = yaml_UTF16LE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { + parser.encoding = yaml_UTF16BE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { + parser.encoding = yaml_UTF8_ENCODING + parser.raw_buffer_pos += 3 + parser.offset += 3 + } else { + parser.encoding = yaml_UTF8_ENCODING + } + return true +} + +// Update the raw buffer. +func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { + size_read := 0 + + // Return if the raw buffer is full. + if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { + return true + } + + // Return on EOF. + if parser.eof { + return true + } + + // Move the remaining bytes in the raw buffer to the beginning. + if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { + copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) + } + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] + parser.raw_buffer_pos = 0 + + // Call the read handler to fill the buffer. + size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] + if err == io.EOF { + parser.eof = true + } else if err != nil { + return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) + } + return true +} + +// Ensure that the buffer contains at least `length` characters. +// Return true on success, false on failure. +// +// The length is supposed to be significantly less that the buffer size. +func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { + if parser.read_handler == nil { + panic("read handler must be set") + } + + // [Go] This function was changed to guarantee the requested length size at EOF. + // The fact we need to do this is pretty awful, but the description above implies + // for that to be the case, and there are tests + + // If the EOF flag is set and the raw buffer is empty, do nothing. + if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { + // [Go] ACTUALLY! Read the documentation of this function above. + // This is just broken. To return true, we need to have the + // given length in the buffer. Not doing that means every single + // check that calls this function to make sure the buffer has a + // given length is Go) panicking; or C) accessing invalid memory. + //return true + } + + // Return if the buffer contains enough characters. + if parser.unread >= length { + return true + } + + // Determine the input encoding if it is not known yet. + if parser.encoding == yaml_ANY_ENCODING { + if !yaml_parser_determine_encoding(parser) { + return false + } + } + + // Move the unread characters to the beginning of the buffer. + buffer_len := len(parser.buffer) + if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { + copy(parser.buffer, parser.buffer[parser.buffer_pos:]) + buffer_len -= parser.buffer_pos + parser.buffer_pos = 0 + } else if parser.buffer_pos == buffer_len { + buffer_len = 0 + parser.buffer_pos = 0 + } + + // Open the whole buffer for writing, and cut it before returning. + parser.buffer = parser.buffer[:cap(parser.buffer)] + + // Fill the buffer until it has enough characters. + first := true + for parser.unread < length { + + // Fill the raw buffer if necessary. + if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { + if !yaml_parser_update_raw_buffer(parser) { + parser.buffer = parser.buffer[:buffer_len] + return false + } + } + first = false + + // Decode the raw buffer. + inner: + for parser.raw_buffer_pos != len(parser.raw_buffer) { + var value rune + var width int + + raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos + + // Decode the next character. + switch parser.encoding { + case yaml_UTF8_ENCODING: + // Decode a UTF-8 character. Check RFC 3629 + // (http://www.ietf.org/rfc/rfc3629.txt) for more details. + // + // The following table (taken from the RFC) is used for + // decoding. + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+------------------------------------ + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // + // Additionally, the characters in the range 0xD800-0xDFFF + // are prohibited as they are reserved for use with UTF-16 + // surrogate pairs. + + // Determine the length of the UTF-8 sequence. + octet := parser.raw_buffer[parser.raw_buffer_pos] + switch { + case octet&0x80 == 0x00: + width = 1 + case octet&0xE0 == 0xC0: + width = 2 + case octet&0xF0 == 0xE0: + width = 3 + case octet&0xF8 == 0xF0: + width = 4 + default: + // The leading octet is invalid. + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser.offset, int(octet)) + } + + // Check if the raw buffer contains an incomplete character. + if width > raw_unread { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser.offset, -1) + } + break inner + } + + // Decode the leading octet. + switch { + case octet&0x80 == 0x00: + value = rune(octet & 0x7F) + case octet&0xE0 == 0xC0: + value = rune(octet & 0x1F) + case octet&0xF0 == 0xE0: + value = rune(octet & 0x0F) + case octet&0xF8 == 0xF0: + value = rune(octet & 0x07) + default: + value = 0 + } + + // Check and decode the trailing octets. + for k := 1; k < width; k++ { + octet = parser.raw_buffer[parser.raw_buffer_pos+k] + + // Check if the octet is valid. + if (octet & 0xC0) != 0x80 { + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser.offset+k, int(octet)) + } + + // Decode the octet. + value = (value << 6) + rune(octet&0x3F) + } + + // Check the length of the sequence against the value. + switch { + case width == 1: + case width == 2 && value >= 0x80: + case width == 3 && value >= 0x800: + case width == 4 && value >= 0x10000: + default: + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser.offset, -1) + } + + // Check the range of the value. + if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser.offset, int(value)) + } + + case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: + var low, high int + if parser.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + low, high = 1, 0 + } + + // The UTF-16 encoding is not as simple as one might + // naively think. Check RFC 2781 + // (http://www.ietf.org/rfc/rfc2781.txt). + // + // Normally, two subsequent bytes describe a Unicode + // character. However a special technique (called a + // surrogate pair) is used for specifying character + // values larger than 0xFFFF. + // + // A surrogate pair consists of two pseudo-characters: + // high surrogate area (0xD800-0xDBFF) + // low surrogate area (0xDC00-0xDFFF) + // + // The following formulas are used for decoding + // and encoding characters using surrogate pairs: + // + // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + // W1 = 110110yyyyyyyyyy + // W2 = 110111xxxxxxxxxx + // + // where U is the character value, W1 is the high surrogate + // area, W2 is the low surrogate area. + + // Check for incomplete UTF-16 character. + if raw_unread < 2 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser.offset, -1) + } + break inner + } + + // Get the character. + value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) + + // Check for unexpected low surrogate area. + if value&0xFC00 == 0xDC00 { + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser.offset, int(value)) + } + + // Check for a high surrogate area. + if value&0xFC00 == 0xD800 { + width = 4 + + // Check for incomplete surrogate pair. + if raw_unread < 4 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser.offset, -1) + } + break inner + } + + // Get the next character. + value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) + + // Check for a low surrogate area. + if value2&0xFC00 != 0xDC00 { + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser.offset+2, int(value2)) + } + + // Generate the value of the surrogate pair. + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) + } else { + width = 2 + } + + default: + panic("impossible") + } + + // Check if the character is in the allowed range: + // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + // | [#x10000-#x10FFFF] (32 bit) + switch { + case value == 0x09: + case value == 0x0A: + case value == 0x0D: + case value >= 0x20 && value <= 0x7E: + case value == 0x85: + case value >= 0xA0 && value <= 0xD7FF: + case value >= 0xE000 && value <= 0xFFFD: + case value >= 0x10000 && value <= 0x10FFFF: + default: + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser.offset, int(value)) + } + + // Move the raw pointers. + parser.raw_buffer_pos += width + parser.offset += width + + // Finally put the character into the buffer. + if value <= 0x7F { + // 0000 0000-0000 007F . 0xxxxxxx + parser.buffer[buffer_len+0] = byte(value) + buffer_len += 1 + } else if value <= 0x7FF { + // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) + parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) + buffer_len += 2 + } else if value <= 0xFFFF { + // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) + buffer_len += 3 + } else { + // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) + buffer_len += 4 + } + + parser.unread++ + } + + // On EOF, put NUL into the buffer and return. + if parser.eof { + parser.buffer[buffer_len] = 0 + buffer_len++ + parser.unread++ + break + } + } + // [Go] Read the documentation of this function above. To return true, + // we need to have the given length in the buffer. Not doing that means + // every single check that calls this function to make sure the buffer + // has a given length is Go) panicking; or C) accessing invalid memory. + // This happens here due to the EOF above breaking early. + for buffer_len < length { + parser.buffer[buffer_len] = 0 + buffer_len++ + } + parser.buffer = parser.buffer[:buffer_len] + return true +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/resolve.go b/event-processor/vendor/go.yaml.in/yaml/v3/resolve.go new file mode 100644 index 00000000..64ae8880 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/resolve.go @@ -0,0 +1,326 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "encoding/base64" + "math" + "regexp" + "strconv" + "strings" + "time" +) + +type resolveMapItem struct { + value interface{} + tag string +} + +var resolveTable = make([]byte, 256) +var resolveMap = make(map[string]resolveMapItem) + +func init() { + t := resolveTable + t[int('+')] = 'S' // Sign + t[int('-')] = 'S' + for _, c := range "0123456789" { + t[int(c)] = 'D' // Digit + } + for _, c := range "yYnNtTfFoO~" { + t[int(c)] = 'M' // In map + } + t[int('.')] = '.' // Float (potentially in map) + + var resolveMapList = []struct { + v interface{} + tag string + l []string + }{ + {true, boolTag, []string{"true", "True", "TRUE"}}, + {false, boolTag, []string{"false", "False", "FALSE"}}, + {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, + {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, + {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, + {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, + {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, + {"<<", mergeTag, []string{"<<"}}, + } + + m := resolveMap + for _, item := range resolveMapList { + for _, s := range item.l { + m[s] = resolveMapItem{item.v, item.tag} + } + } +} + +const ( + nullTag = "!!null" + boolTag = "!!bool" + strTag = "!!str" + intTag = "!!int" + floatTag = "!!float" + timestampTag = "!!timestamp" + seqTag = "!!seq" + mapTag = "!!map" + binaryTag = "!!binary" + mergeTag = "!!merge" +) + +var longTags = make(map[string]string) +var shortTags = make(map[string]string) + +func init() { + for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { + ltag := longTag(stag) + longTags[stag] = ltag + shortTags[ltag] = stag + } +} + +const longTagPrefix = "tag:yaml.org,2002:" + +func shortTag(tag string) string { + if strings.HasPrefix(tag, longTagPrefix) { + if stag, ok := shortTags[tag]; ok { + return stag + } + return "!!" + tag[len(longTagPrefix):] + } + return tag +} + +func longTag(tag string) string { + if strings.HasPrefix(tag, "!!") { + if ltag, ok := longTags[tag]; ok { + return ltag + } + return longTagPrefix + tag[2:] + } + return tag +} + +func resolvableTag(tag string) bool { + switch tag { + case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: + return true + } + return false +} + +var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) + +func resolve(tag string, in string) (rtag string, out interface{}) { + tag = shortTag(tag) + if !resolvableTag(tag) { + return tag, in + } + + defer func() { + switch tag { + case "", rtag, strTag, binaryTag: + return + case floatTag: + if rtag == intTag { + switch v := out.(type) { + case int64: + rtag = floatTag + out = float64(v) + return + case int: + rtag = floatTag + out = float64(v) + return + } + } + } + failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) + }() + + // Any data is accepted as a !!str or !!binary. + // Otherwise, the prefix is enough of a hint about what it might be. + hint := byte('N') + if in != "" { + hint = resolveTable[in[0]] + } + if hint != 0 && tag != strTag && tag != binaryTag { + // Handle things we can lookup in a map. + if item, ok := resolveMap[in]; ok { + return item.tag, item.value + } + + // Base 60 floats are a bad idea, were dropped in YAML 1.2, and + // are purposefully unsupported here. They're still quoted on + // the way out for compatibility with other parser, though. + + switch hint { + case 'M': + // We've already checked the map above. + + case '.': + // Not in the map, so maybe a normal float. + floatv, err := strconv.ParseFloat(in, 64) + if err == nil { + return floatTag, floatv + } + + case 'D', 'S': + // Int, float, or timestamp. + // Only try values as a timestamp if the value is unquoted or there's an explicit + // !!timestamp tag. + if tag == "" || tag == timestampTag { + t, ok := parseTimestamp(in) + if ok { + return timestampTag, t + } + } + + plain := strings.Replace(in, "_", "", -1) + intv, err := strconv.ParseInt(plain, 0, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain, 0, 64) + if err == nil { + return intTag, uintv + } + if yamlStyleFloat.MatchString(plain) { + floatv, err := strconv.ParseFloat(plain, 64) + if err == nil { + return floatTag, floatv + } + } + if strings.HasPrefix(plain, "0b") { + intv, err := strconv.ParseInt(plain[2:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 2, 64) + if err == nil { + return intTag, uintv + } + } else if strings.HasPrefix(plain, "-0b") { + intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) + if err == nil { + if true || intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + } + // Octals as introduced in version 1.2 of the spec. + // Octals from the 1.1 spec, spelled as 0777, are still + // decoded by default in v3 as well for compatibility. + // May be dropped in v4 depending on how usage evolves. + if strings.HasPrefix(plain, "0o") { + intv, err := strconv.ParseInt(plain[2:], 8, 64) + if err == nil { + if intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 8, 64) + if err == nil { + return intTag, uintv + } + } else if strings.HasPrefix(plain, "-0o") { + intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) + if err == nil { + if true || intv == int64(int(intv)) { + return intTag, int(intv) + } else { + return intTag, intv + } + } + } + default: + panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") + } + } + return strTag, in +} + +// encodeBase64 encodes s as base64 that is broken up into multiple lines +// as appropriate for the resulting length. +func encodeBase64(s string) string { + const lineLen = 70 + encLen := base64.StdEncoding.EncodedLen(len(s)) + lines := encLen/lineLen + 1 + buf := make([]byte, encLen*2+lines) + in := buf[0:encLen] + out := buf[encLen:] + base64.StdEncoding.Encode(in, []byte(s)) + k := 0 + for i := 0; i < len(in); i += lineLen { + j := i + lineLen + if j > len(in) { + j = len(in) + } + k += copy(out[k:], in[i:j]) + if lines > 1 { + out[k] = '\n' + k++ + } + } + return string(out[:k]) +} + +// This is a subset of the formats allowed by the regular expression +// defined at http://yaml.org/type/timestamp.html. +var allowedTimestampFormats = []string{ + "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. + "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". + "2006-1-2 15:4:5.999999999", // space separated with no time zone + "2006-1-2", // date only + // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" + // from the set of examples. +} + +// parseTimestamp parses s as a timestamp string and +// returns the timestamp and reports whether it succeeded. +// Timestamp formats are defined at http://yaml.org/type/timestamp.html +func parseTimestamp(s string) (time.Time, bool) { + // TODO write code to check all the formats supported by + // http://yaml.org/type/timestamp.html instead of using time.Parse. + + // Quick check: all date formats start with YYYY-. + i := 0 + for ; i < len(s); i++ { + if c := s[i]; c < '0' || c > '9' { + break + } + } + if i != 4 || i == len(s) || s[i] != '-' { + return time.Time{}, false + } + for _, format := range allowedTimestampFormats { + if t, err := time.Parse(format, s); err == nil { + return t, true + } + } + return time.Time{}, false +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/scannerc.go b/event-processor/vendor/go.yaml.in/yaml/v3/scannerc.go new file mode 100644 index 00000000..30b1f089 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/scannerc.go @@ -0,0 +1,3040 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "bytes" + "fmt" +) + +// Introduction +// ************ +// +// The following notes assume that you are familiar with the YAML specification +// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in +// some cases we are less restrictive that it requires. +// +// The process of transforming a YAML stream into a sequence of events is +// divided on two steps: Scanning and Parsing. +// +// The Scanner transforms the input stream into a sequence of tokens, while the +// parser transform the sequence of tokens produced by the Scanner into a +// sequence of parsing events. +// +// The Scanner is rather clever and complicated. The Parser, on the contrary, +// is a straightforward implementation of a recursive-descendant parser (or, +// LL(1) parser, as it is usually called). +// +// Actually there are two issues of Scanning that might be called "clever", the +// rest is quite straightforward. The issues are "block collection start" and +// "simple keys". Both issues are explained below in details. +// +// Here the Scanning step is explained and implemented. We start with the list +// of all the tokens produced by the Scanner together with short descriptions. +// +// Now, tokens: +// +// STREAM-START(encoding) # The stream start. +// STREAM-END # The stream end. +// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. +// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. +// DOCUMENT-START # '---' +// DOCUMENT-END # '...' +// BLOCK-SEQUENCE-START # Indentation increase denoting a block +// BLOCK-MAPPING-START # sequence or a block mapping. +// BLOCK-END # Indentation decrease. +// FLOW-SEQUENCE-START # '[' +// FLOW-SEQUENCE-END # ']' +// BLOCK-SEQUENCE-START # '{' +// BLOCK-SEQUENCE-END # '}' +// BLOCK-ENTRY # '-' +// FLOW-ENTRY # ',' +// KEY # '?' or nothing (simple keys). +// VALUE # ':' +// ALIAS(anchor) # '*anchor' +// ANCHOR(anchor) # '&anchor' +// TAG(handle,suffix) # '!handle!suffix' +// SCALAR(value,style) # A scalar. +// +// The following two tokens are "virtual" tokens denoting the beginning and the +// end of the stream: +// +// STREAM-START(encoding) +// STREAM-END +// +// We pass the information about the input stream encoding with the +// STREAM-START token. +// +// The next two tokens are responsible for tags: +// +// VERSION-DIRECTIVE(major,minor) +// TAG-DIRECTIVE(handle,prefix) +// +// Example: +// +// %YAML 1.1 +// %TAG ! !foo +// %TAG !yaml! tag:yaml.org,2002: +// --- +// +// The correspoding sequence of tokens: +// +// STREAM-START(utf-8) +// VERSION-DIRECTIVE(1,1) +// TAG-DIRECTIVE("!","!foo") +// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") +// DOCUMENT-START +// STREAM-END +// +// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole +// line. +// +// The document start and end indicators are represented by: +// +// DOCUMENT-START +// DOCUMENT-END +// +// Note that if a YAML stream contains an implicit document (without '---' +// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be +// produced. +// +// In the following examples, we present whole documents together with the +// produced tokens. +// +// 1. An implicit document: +// +// 'a scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// STREAM-END +// +// 2. An explicit document: +// +// --- +// 'a scalar' +// ... +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// SCALAR("a scalar",single-quoted) +// DOCUMENT-END +// STREAM-END +// +// 3. Several documents in a stream: +// +// 'a scalar' +// --- +// 'another scalar' +// --- +// 'yet another scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// DOCUMENT-START +// SCALAR("another scalar",single-quoted) +// DOCUMENT-START +// SCALAR("yet another scalar",single-quoted) +// STREAM-END +// +// We have already introduced the SCALAR token above. The following tokens are +// used to describe aliases, anchors, tag, and scalars: +// +// ALIAS(anchor) +// ANCHOR(anchor) +// TAG(handle,suffix) +// SCALAR(value,style) +// +// The following series of examples illustrate the usage of these tokens: +// +// 1. A recursive sequence: +// +// &A [ *A ] +// +// Tokens: +// +// STREAM-START(utf-8) +// ANCHOR("A") +// FLOW-SEQUENCE-START +// ALIAS("A") +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A tagged scalar: +// +// !!float "3.14" # A good approximation. +// +// Tokens: +// +// STREAM-START(utf-8) +// TAG("!!","float") +// SCALAR("3.14",double-quoted) +// STREAM-END +// +// 3. Various scalar styles: +// +// --- # Implicit empty plain scalars do not produce tokens. +// --- a plain scalar +// --- 'a single-quoted scalar' +// --- "a double-quoted scalar" +// --- |- +// a literal scalar +// --- >- +// a folded +// scalar +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// DOCUMENT-START +// SCALAR("a plain scalar",plain) +// DOCUMENT-START +// SCALAR("a single-quoted scalar",single-quoted) +// DOCUMENT-START +// SCALAR("a double-quoted scalar",double-quoted) +// DOCUMENT-START +// SCALAR("a literal scalar",literal) +// DOCUMENT-START +// SCALAR("a folded scalar",folded) +// STREAM-END +// +// Now it's time to review collection-related tokens. We will start with +// flow collections: +// +// FLOW-SEQUENCE-START +// FLOW-SEQUENCE-END +// FLOW-MAPPING-START +// FLOW-MAPPING-END +// FLOW-ENTRY +// KEY +// VALUE +// +// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and +// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' +// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the +// indicators '?' and ':', which are used for denoting mapping keys and values, +// are represented by the KEY and VALUE tokens. +// +// The following examples show flow collections: +// +// 1. A flow sequence: +// +// [item 1, item 2, item 3] +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-SEQUENCE-START +// SCALAR("item 1",plain) +// FLOW-ENTRY +// SCALAR("item 2",plain) +// FLOW-ENTRY +// SCALAR("item 3",plain) +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A flow mapping: +// +// { +// a simple key: a value, # Note that the KEY token is produced. +// ? a complex key: another value, +// } +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// FLOW-ENTRY +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// FLOW-ENTRY +// FLOW-MAPPING-END +// STREAM-END +// +// A simple key is a key which is not denoted by the '?' indicator. Note that +// the Scanner still produce the KEY token whenever it encounters a simple key. +// +// For scanning block collections, the following tokens are used (note that we +// repeat KEY and VALUE here): +// +// BLOCK-SEQUENCE-START +// BLOCK-MAPPING-START +// BLOCK-END +// BLOCK-ENTRY +// KEY +// VALUE +// +// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation +// increase that precedes a block collection (cf. the INDENT token in Python). +// The token BLOCK-END denote indentation decrease that ends a block collection +// (cf. the DEDENT token in Python). However YAML has some syntax pecularities +// that makes detections of these tokens more complex. +// +// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators +// '-', '?', and ':' correspondingly. +// +// The following examples show how the tokens BLOCK-SEQUENCE-START, +// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: +// +// 1. Block sequences: +// +// - item 1 +// - item 2 +// - +// - item 3.1 +// - item 3.2 +// - +// key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 3.1",plain) +// BLOCK-ENTRY +// SCALAR("item 3.2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Block mappings: +// +// a simple key: a value # The KEY token is produced here. +// ? a complex key +// : another value +// a mapping: +// key 1: value 1 +// key 2: value 2 +// a sequence: +// - item 1 +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// KEY +// SCALAR("a mapping",plain) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML does not always require to start a new block collection from a new +// line. If the current line contains only '-', '?', and ':' indicators, a new +// block collection may start at the current line. The following examples +// illustrate this case: +// +// 1. Collections in a sequence: +// +// - - item 1 +// - item 2 +// - key 1: value 1 +// key 2: value 2 +// - ? complex key +// : complex value +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("complex key") +// VALUE +// SCALAR("complex value") +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Collections in a mapping: +// +// ? a sequence +// : - item 1 +// - item 2 +// ? a mapping +// : key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// KEY +// SCALAR("a mapping",plain) +// VALUE +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML also permits non-indented sequences if they are included into a block +// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: +// +// key: +// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key",plain) +// VALUE +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// + +// Ensure that the buffer contains the required number of characters. +// Return true on success, false on failure (reader error or memory error). +func cache(parser *yaml_parser_t, length int) bool { + // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) + return parser.unread >= length || yaml_parser_update_buffer(parser, length) +} + +// Advance the buffer pointer. +func skip(parser *yaml_parser_t) { + if !is_blank(parser.buffer, parser.buffer_pos) { + parser.newlines = 0 + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) +} + +func skip_line(parser *yaml_parser_t) { + if is_crlf(parser.buffer, parser.buffer_pos) { + parser.mark.index += 2 + parser.mark.column = 0 + parser.mark.line++ + parser.unread -= 2 + parser.buffer_pos += 2 + parser.newlines++ + } else if is_break(parser.buffer, parser.buffer_pos) { + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) + parser.newlines++ + } +} + +// Copy a character to a string buffer and advance pointers. +func read(parser *yaml_parser_t, s []byte) []byte { + if !is_blank(parser.buffer, parser.buffer_pos) { + parser.newlines = 0 + } + w := width(parser.buffer[parser.buffer_pos]) + if w == 0 { + panic("invalid character sequence") + } + if len(s) == 0 { + s = make([]byte, 0, 32) + } + if w == 1 && len(s)+w <= cap(s) { + s = s[:len(s)+1] + s[len(s)-1] = parser.buffer[parser.buffer_pos] + parser.buffer_pos++ + } else { + s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) + parser.buffer_pos += w + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + return s +} + +// Copy a line break character to a string buffer and advance pointers. +func read_line(parser *yaml_parser_t, s []byte) []byte { + buf := parser.buffer + pos := parser.buffer_pos + switch { + case buf[pos] == '\r' && buf[pos+1] == '\n': + // CR LF . LF + s = append(s, '\n') + parser.buffer_pos += 2 + parser.mark.index++ + parser.unread-- + case buf[pos] == '\r' || buf[pos] == '\n': + // CR|LF . LF + s = append(s, '\n') + parser.buffer_pos += 1 + case buf[pos] == '\xC2' && buf[pos+1] == '\x85': + // NEL . LF + s = append(s, '\n') + parser.buffer_pos += 2 + case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): + // LS|PS . LS|PS + s = append(s, buf[parser.buffer_pos:pos+3]...) + parser.buffer_pos += 3 + default: + return s + } + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.newlines++ + return s +} + +// Get the next token. +func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { + // Erase the token object. + *token = yaml_token_t{} // [Go] Is this necessary? + + // No tokens after STREAM-END or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR { + return true + } + + // Ensure that the tokens queue contains enough tokens. + if !parser.token_available { + if !yaml_parser_fetch_more_tokens(parser) { + return false + } + } + + // Fetch the next token from the queue. + *token = parser.tokens[parser.tokens_head] + parser.tokens_head++ + parser.tokens_parsed++ + parser.token_available = false + + if token.typ == yaml_STREAM_END_TOKEN { + parser.stream_end_produced = true + } + return true +} + +// Set the scanner error and return false. +func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { + parser.error = yaml_SCANNER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = parser.mark + return false +} + +func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { + context := "while parsing a tag" + if directive { + context = "while parsing a %TAG directive" + } + return yaml_parser_set_scanner_error(parser, context, context_mark, problem) +} + +func trace(args ...interface{}) func() { + pargs := append([]interface{}{"+++"}, args...) + fmt.Println(pargs...) + pargs = append([]interface{}{"---"}, args...) + return func() { fmt.Println(pargs...) } +} + +// Ensure that the tokens queue contains at least one token which can be +// returned to the Parser. +func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { + // While we need more tokens to fetch, do it. + for { + // [Go] The comment parsing logic requires a lookahead of two tokens + // so that foot comments may be parsed in time of associating them + // with the tokens that are parsed before them, and also for line + // comments to be transformed into head comments in some edge cases. + if parser.tokens_head < len(parser.tokens)-2 { + // If a potential simple key is at the head position, we need to fetch + // the next token to disambiguate it. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { + return false + } else if !valid { + break + } + } + // Fetch the next token. + if !yaml_parser_fetch_next_token(parser) { + return false + } + } + + parser.token_available = true + return true +} + +// The dispatcher for token fetchers. +func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { + // Ensure that the buffer is initialized. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we just started scanning. Fetch STREAM-START then. + if !parser.stream_start_produced { + return yaml_parser_fetch_stream_start(parser) + } + + scan_mark := parser.mark + + // Eat whitespaces and comments until we reach the next token. + if !yaml_parser_scan_to_next_token(parser) { + return false + } + + // [Go] While unrolling indents, transform the head comments of prior + // indentation levels observed after scan_start into foot comments at + // the respective indexes. + + // Check the indentation level against the current column. + if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { + return false + } + + // Ensure that the buffer contains at least 4 characters. 4 is the length + // of the longest indicators ('--- ' and '... '). + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + // Is it the end of the stream? + if is_z(parser.buffer, parser.buffer_pos) { + return yaml_parser_fetch_stream_end(parser) + } + + // Is it a directive? + if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { + return yaml_parser_fetch_directive(parser) + } + + buf := parser.buffer + pos := parser.buffer_pos + + // Is it the document start indicator? + if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) + } + + // Is it the document end indicator? + if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) + } + + comment_mark := parser.mark + if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { + // Associate any following comments with the prior token. + comment_mark = parser.tokens[len(parser.tokens)-1].start_mark + } + defer func() { + if !ok { + return + } + if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { + // Sequence indicators alone have no line comments. It becomes + // a head comment for whatever follows. + return + } + if !yaml_parser_scan_line_comment(parser, comment_mark) { + ok = false + return + } + }() + + // Is it the flow sequence start indicator? + if buf[pos] == '[' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) + } + + // Is it the flow mapping start indicator? + if parser.buffer[parser.buffer_pos] == '{' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) + } + + // Is it the flow sequence end indicator? + if parser.buffer[parser.buffer_pos] == ']' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_SEQUENCE_END_TOKEN) + } + + // Is it the flow mapping end indicator? + if parser.buffer[parser.buffer_pos] == '}' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_MAPPING_END_TOKEN) + } + + // Is it the flow entry indicator? + if parser.buffer[parser.buffer_pos] == ',' { + return yaml_parser_fetch_flow_entry(parser) + } + + // Is it the block entry indicator? + if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { + return yaml_parser_fetch_block_entry(parser) + } + + // Is it the key indicator? + if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_key(parser) + } + + // Is it the value indicator? + if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_value(parser) + } + + // Is it an alias? + if parser.buffer[parser.buffer_pos] == '*' { + return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) + } + + // Is it an anchor? + if parser.buffer[parser.buffer_pos] == '&' { + return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) + } + + // Is it a tag? + if parser.buffer[parser.buffer_pos] == '!' { + return yaml_parser_fetch_tag(parser) + } + + // Is it a literal scalar? + if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, true) + } + + // Is it a folded scalar? + if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, false) + } + + // Is it a single-quoted scalar? + if parser.buffer[parser.buffer_pos] == '\'' { + return yaml_parser_fetch_flow_scalar(parser, true) + } + + // Is it a double-quoted scalar? + if parser.buffer[parser.buffer_pos] == '"' { + return yaml_parser_fetch_flow_scalar(parser, false) + } + + // Is it a plain scalar? + // + // A plain scalar may start with any non-blank characters except + // + // '-', '?', ':', ',', '[', ']', '{', '}', + // '#', '&', '*', '!', '|', '>', '\'', '\"', + // '%', '@', '`'. + // + // In the block context (and, for the '-' indicator, in the flow context + // too), it may also start with the characters + // + // '-', '?', ':' + // + // if it is followed by a non-space character. + // + // The last rule is more restrictive than the specification requires. + // [Go] TODO Make this logic more reasonable. + //switch parser.buffer[parser.buffer_pos] { + //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': + //} + if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || + parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || + parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || + (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level == 0 && + (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && + !is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_plain_scalar(parser) + } + + // If we don't determine the token type so far, it is an error. + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser.mark, + "found character that cannot start any token") +} + +func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { + if !simple_key.possible { + return false, true + } + + // The 1.2 specification says: + // + // "If the ? indicator is omitted, parsing needs to see past the + // implicit key to recognize it as such. To limit the amount of + // lookahead required, the “:” indicator must appear at most 1024 + // Unicode characters beyond the start of the key. In addition, the key + // is restricted to a single line." + // + if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { + // Check if the potential simple key to be removed is required. + if simple_key.required { + return false, yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + return false, true + } + return true, true +} + +// Check if a simple key may start at the current position and add it if +// needed. +func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { + // A simple key is required at the current position if the scanner is in + // the block context and the current column coincides with the indentation + // level. + + required := parser.flow_level == 0 && parser.indent == parser.mark.column + + // + // If the current position may start a simple key, save it. + // + if parser.simple_key_allowed { + simple_key := yaml_simple_key_t{ + possible: true, + required: required, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + } + + if !yaml_parser_remove_simple_key(parser) { + return false + } + parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 + } + return true +} + +// Remove a potential simple key at the current flow level. +func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { + i := len(parser.simple_keys) - 1 + if parser.simple_keys[i].possible { + // If the key is required, it is an error. + if parser.simple_keys[i].required { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", parser.simple_keys[i].mark, + "could not find expected ':'") + } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) + } + return true +} + +// max_flow_level limits the flow_level +const max_flow_level = 10000 + +// Increase the flow level and resize the simple key list if needed. +func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { + // Reset the simple key on the next level. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ + possible: false, + required: false, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + }) + + // Increase the flow level. + parser.flow_level++ + if parser.flow_level > max_flow_level { + return yaml_parser_set_scanner_error(parser, + "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_flow_level)) + } + return true +} + +// Decrease the flow level. +func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { + if parser.flow_level > 0 { + parser.flow_level-- + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] + } + return true +} + +// max_indents limits the indents stack size +const max_indents = 10000 + +// Push the current indentation level to the stack and set the new level +// the current column is greater than the indentation level. In this case, +// append or insert the specified token into the token queue. +func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + if parser.indent < column { + // Push the current indentation level to the stack and set the new + // indentation level. + parser.indents = append(parser.indents, parser.indent) + parser.indent = column + if len(parser.indents) > max_indents { + return yaml_parser_set_scanner_error(parser, + "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_indents)) + } + + // Create a token and insert it into the queue. + token := yaml_token_t{ + typ: typ, + start_mark: mark, + end_mark: mark, + } + if number > -1 { + number -= parser.tokens_parsed + } + yaml_insert_token(parser, number, &token) + } + return true +} + +// Pop indentation levels from the indents stack until the current level +// becomes less or equal to the column. For each indentation level, append +// the BLOCK-END token. +func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + block_mark := scan_mark + block_mark.index-- + + // Loop through the indentation levels in the stack. + for parser.indent > column { + + // [Go] Reposition the end token before potential following + // foot comments of parent blocks. For that, search + // backwards for recent comments that were at the same + // indent as the block that is ending now. + stop_index := block_mark.index + for i := len(parser.comments) - 1; i >= 0; i-- { + comment := &parser.comments[i] + + if comment.end_mark.index < stop_index { + // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. + // If requested indent column is < 0, then the document is over and everything else + // is a foot anyway. + break + } + if comment.start_mark.column == parser.indent+1 { + // This is a good match. But maybe there's a former comment + // at that same indent level, so keep searching. + block_mark = comment.start_mark + } + + // While the end of the former comment matches with + // the start of the following one, we know there's + // nothing in between and scanning is still safe. + stop_index = comment.scan_mark.index + } + + // Create a token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_END_TOKEN, + start_mark: block_mark, + end_mark: block_mark, + } + yaml_insert_token(parser, -1, &token) + + // Pop the indentation level. + parser.indent = parser.indents[len(parser.indents)-1] + parser.indents = parser.indents[:len(parser.indents)-1] + } + return true +} + +// Initialize the scanner and produce the STREAM-START token. +func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { + + // Set the initial indentation. + parser.indent = -1 + + // Initialize the simple key stack. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + parser.simple_keys_by_tok = make(map[int]int) + + // A simple key is allowed at the beginning of the stream. + parser.simple_key_allowed = true + + // We have started. + parser.stream_start_produced = true + + // Create the STREAM-START token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_START_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + encoding: parser.encoding, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the STREAM-END token and shut down the scanner. +func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { + + // Force new line. + if parser.mark.column != 0 { + parser.mark.column = 0 + parser.mark.line++ + } + + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the STREAM-END token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. +func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. + token := yaml_token_t{} + if !yaml_parser_scan_directive(parser, &token) { + return false + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the DOCUMENT-START or DOCUMENT-END token. +func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1, parser.mark) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Consume the token. + start_mark := parser.mark + + skip(parser) + skip(parser) + skip(parser) + + end_mark := parser.mark + + // Create the DOCUMENT-START or DOCUMENT-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. +func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { + + // The indicators '[' and '{' may start a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // Increase the flow level. + if !yaml_parser_increase_flow_level(parser) { + return false + } + + // A simple key may follow the indicators '[' and '{'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. +func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset any potential simple key on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Decrease the flow level. + if !yaml_parser_decrease_flow_level(parser) { + return false + } + + // No simple keys after the indicators ']' and '}'. + parser.simple_key_allowed = false + + // Consume the token. + + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-ENTRY token. +func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after ','. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_FLOW_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the BLOCK-ENTRY token. +func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { + // Check if the scanner is in the block context. + if parser.flow_level == 0 { + // Check if we are allowed to start a new entry. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "block sequence entries are not allowed in this context") + } + // Add the BLOCK-SEQUENCE-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { + return false + } + } else { + // It is an error for the '-' indicator to occur in the flow context, + // but we let the Parser detect and report about it because the Parser + // is able to point to the context. + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '-'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the BLOCK-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the KEY token. +func yaml_parser_fetch_key(parser *yaml_parser_t) bool { + + // In the block context, additional checks are required. + if parser.flow_level == 0 { + // Check if we are allowed to start a new key (not nessesary simple). + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping keys are not allowed in this context") + } + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '?' in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the KEY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the VALUE token. +func yaml_parser_fetch_value(parser *yaml_parser_t) bool { + + simple_key := &parser.simple_keys[len(parser.simple_keys)-1] + + // Have we found a simple key? + if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { + return false + + } else if valid { + + // Create the KEY token and insert it into the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: simple_key.mark, + end_mark: simple_key.mark, + } + yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) + + // In the block context, we may need to add the BLOCK-MAPPING-START token. + if !yaml_parser_roll_indent(parser, simple_key.mark.column, + simple_key.token_number, + yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { + return false + } + + // Remove the simple key. + simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) + + // A simple key cannot follow another simple key. + parser.simple_key_allowed = false + + } else { + // The ':' indicator follows a complex key. + + // In the block context, extra checks are required. + if parser.flow_level == 0 { + + // Check if we are allowed to start a complex value. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping values are not allowed in this context") + } + + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Simple keys after ':' are allowed in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + } + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the VALUE token and append it to the queue. + token := yaml_token_t{ + typ: yaml_VALUE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the ALIAS or ANCHOR token. +func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // An anchor or an alias could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow an anchor or an alias. + parser.simple_key_allowed = false + + // Create the ALIAS or ANCHOR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_anchor(parser, &token, typ) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the TAG token. +func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { + // A tag could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a tag. + parser.simple_key_allowed = false + + // Create the TAG token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_tag(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. +func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { + // Remove any potential simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // A simple key may follow a block scalar. + parser.simple_key_allowed = true + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_block_scalar(parser, &token, literal) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. +func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_flow_scalar(parser, &token, single) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,plain) token. +func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_plain_scalar(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Eat whitespaces and comments until the next token is found. +func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { + + scan_mark := parser.mark + + // Until the next token is not found. + for { + // Allow the BOM mark to start a line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { + skip(parser) + } + + // Eat whitespaces. + // Tabs are allowed: + // - in the flow context + // - in the block context, but not at the beginning of the line or + // after '-', '?', or ':' (complex value). + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if we just had a line comment under a sequence entry that + // looks more like a header to the following content. Similar to this: + // + // - # The comment + // - Some data + // + // If so, transform the line comment to a head comment and reposition. + if len(parser.comments) > 0 && len(parser.tokens) > 1 { + tokenA := parser.tokens[len(parser.tokens)-2] + tokenB := parser.tokens[len(parser.tokens)-1] + comment := &parser.comments[len(parser.comments)-1] + if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { + // If it was in the prior line, reposition so it becomes a + // header of the follow up token. Otherwise, keep it in place + // so it becomes a header of the former. + comment.head = comment.line + comment.line = nil + if comment.start_mark.line == parser.mark.line-1 { + comment.token_mark = parser.mark + } + } + } + + // Eat a comment until a line break. + if parser.buffer[parser.buffer_pos] == '#' { + if !yaml_parser_scan_comments(parser, scan_mark) { + return false + } + } + + // If it is a line break, eat it. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + + // In the block context, a new line may start a simple key. + if parser.flow_level == 0 { + parser.simple_key_allowed = true + } + } else { + break // We have found a token. + } + } + + return true +} + +// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. +// +// Scope: +// +// %YAML 1.1 # a comment \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { + // Eat '%'. + start_mark := parser.mark + skip(parser) + + // Scan the directive name. + var name []byte + if !yaml_parser_scan_directive_name(parser, start_mark, &name) { + return false + } + + // Is it a YAML directive? + if bytes.Equal(name, []byte("YAML")) { + // Scan the VERSION directive value. + var major, minor int8 + if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { + return false + } + end_mark := parser.mark + + // Create a VERSION-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_VERSION_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + major: major, + minor: minor, + } + + // Is it a TAG directive? + } else if bytes.Equal(name, []byte("TAG")) { + // Scan the TAG directive value. + var handle, prefix []byte + if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { + return false + } + end_mark := parser.mark + + // Create a TAG-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_TAG_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + prefix: prefix, + } + + // Unknown directive. + } else { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unknown directive name") + return false + } + + // Eat the rest of the line including any comments. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + if parser.buffer[parser.buffer_pos] == '#' { + // [Go] Discard this inline comment for the time being. + //if !yaml_parser_scan_line_comment(parser, start_mark) { + // return false + //} + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + return true +} + +// Scan the directive name. +// +// Scope: +// +// %YAML 1.1 # a comment \n +// ^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^ +func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { + // Consume the directive name. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + var s []byte + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the name is empty. + if len(s) == 0 { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name") + return false + } + + // Check for an blank character after the name. + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character") + return false + } + *name = s + return true +} + +// Scan the value of VERSION-DIRECTIVE. +// +// Scope: +// +// %YAML 1.1 # a comment \n +// ^^^^^^ +func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the major version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { + return false + } + + // Eat '.'. + if parser.buffer[parser.buffer_pos] != '.' { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character") + } + + skip(parser) + + // Consume the minor version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { + return false + } + return true +} + +const max_number_length = 2 + +// Scan the version number of VERSION-DIRECTIVE. +// +// Scope: +// +// %YAML 1.1 # a comment \n +// ^ +// %YAML 1.1 # a comment \n +// ^ +func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { + + // Repeat while the next character is digit. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var value, length int8 + for is_digit(parser.buffer, parser.buffer_pos) { + // Check if the number is too long. + length++ + if length > max_number_length { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number") + } + value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the number was present. + if length == 0 { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number") + } + *number = value + return true +} + +// Scan the value of a TAG-DIRECTIVE token. +// +// Scope: +// +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { + var handle_value, prefix_value []byte + + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a handle. + if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { + return false + } + + // Expect a whitespace. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blank(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace") + return false + } + + // Eat whitespaces. + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a prefix. + if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { + return false + } + + // Expect a whitespace or line break. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break") + return false + } + + *handle = handle_value + *prefix = prefix_value + return true +} + +func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { + var s []byte + + // Eat the indicator character. + start_mark := parser.mark + skip(parser) + + // Consume the value. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + end_mark := parser.mark + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if len(s) == 0 || + !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || + parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '`') { + context := "while scanning an alias" + if typ == yaml_ANCHOR_TOKEN { + context = "while scanning an anchor" + } + yaml_parser_set_scanner_error(parser, context, start_mark, + "did not find expected alphabetic or numeric character") + return false + } + + // Create a token. + *token = yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + value: s, + } + + return true +} + +/* + * Scan a TAG token. + */ + +func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { + var handle, suffix []byte + + start_mark := parser.mark + + // Check if the tag is in the canonical form. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + if parser.buffer[parser.buffer_pos+1] == '<' { + // Keep the handle as '' + + // Eat '!<' + skip(parser) + skip(parser) + + // Consume the tag value. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + + // Check for '>' and eat it. + if parser.buffer[parser.buffer_pos] != '>' { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'") + return false + } + + skip(parser) + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { + return false + } + + // Check if it is, indeed, handle. + if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { + // Scan the suffix now. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + } else { + // It wasn't a handle after all. Scan the rest of the tag. + if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { + return false + } + + // Set the handle to '!'. + handle = []byte{'!'} + + // A special case: the '!' tag. Set the handle to '' and the + // suffix to '!'. + if len(suffix) == 0 { + handle, suffix = suffix, handle + } + } + } + + // Check the character which ends the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break") + return false + } + + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_TAG_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + suffix: suffix, + } + return true +} + +// Scan a tag handle. +func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { + // Check the initial '!' character. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] != '!' { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + + var s []byte + + // Copy the '!' character. + s = read(parser, s) + + // Copy all subsequent alphabetical and numerical characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the trailing character is '!' and copy it. + if parser.buffer[parser.buffer_pos] == '!' { + s = read(parser, s) + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be a part of URI. + if directive && string(s) != "!" { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + } + + *handle = s + return true +} + +// Scan a tag. +func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { + //size_t length = head ? strlen((char *)head) : 0 + var s []byte + hasTag := len(head) > 0 + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if len(head) > 1 { + s = append(s, head[1:]...) + } + + // Scan the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // [Go] TODO Convert this into more reasonable logic. + for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || + parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || + parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || + parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || + parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || + parser.buffer[parser.buffer_pos] == '%' { + // Check if it is a URI-escape sequence. + if parser.buffer[parser.buffer_pos] == '%' { + if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { + return false + } + } else { + s = read(parser, s) + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + hasTag = true + } + + if !hasTag { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected tag URI") + return false + } + *uri = s + return true +} + +// Decode an URI-escape sequence corresponding to a single UTF-8 character. +func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { + + // Decode the required number of characters. + w := 1024 + for w > 0 { + // Check for a URI-escaped octet. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + + if !(parser.buffer[parser.buffer_pos] == '%' && + is_hex(parser.buffer, parser.buffer_pos+1) && + is_hex(parser.buffer, parser.buffer_pos+2)) { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find URI escaped octet") + } + + // Get the octet. + octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) + + // If it is the leading octet, determine the length of the UTF-8 sequence. + if w == 1024 { + w = width(octet) + if w == 0 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect leading UTF-8 octet") + } + } else { + // Check if the trailing octet is correct. + if octet&0xC0 != 0x80 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect trailing UTF-8 octet") + } + } + + // Copy the octet and move the pointers. + *s = append(*s, octet) + skip(parser) + skip(parser) + skip(parser) + w-- + } + return true +} + +// Scan a block scalar. +func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { + // Eat the indicator '|' or '>'. + start_mark := parser.mark + skip(parser) + + // Scan the additional block scalar indicators. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check for a chomping indicator. + var chomping, increment int + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + // Set the chomping method and eat the indicator. + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + + // Check for an indentation indicator. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_digit(parser.buffer, parser.buffer_pos) { + // Check that the indentation is greater than 0. + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + + // Get the indentation level and eat the indicator. + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + } + + } else if is_digit(parser.buffer, parser.buffer_pos) { + // Do the same as above, but in the opposite order. + + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + } + } + + // Eat whitespaces and comments to the end of the line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.buffer[parser.buffer_pos] == '#' { + if !yaml_parser_scan_line_comment(parser, start_mark) { + return false + } + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + end_mark := parser.mark + + // Set the indentation level if it was specified. + var indent int + if increment > 0 { + if parser.indent >= 0 { + indent = parser.indent + increment + } else { + indent = increment + } + } + + // Scan the leading line breaks and determine the indentation level if needed. + var s, leading_break, trailing_breaks []byte + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + + // Scan the block scalar content. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var leading_blank, trailing_blank bool + for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { + // We are at the beginning of a non-empty line. + + // Is it a trailing whitespace? + trailing_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Check if we need to fold the leading line break. + if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { + // Do we need to join the lines by space? + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } + } else { + s = append(s, leading_break...) + } + leading_break = leading_break[:0] + + // Append the remaining line breaks. + s = append(s, trailing_breaks...) + trailing_breaks = trailing_breaks[:0] + + // Is it a leading whitespace? + leading_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Consume the current line. + for !is_breakz(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + leading_break = read_line(parser, leading_break) + + // Eat the following indentation spaces and line breaks. + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + } + + // Chomp the tail. + if chomping != -1 { + s = append(s, leading_break...) + } + if chomping == 1 { + s = append(s, trailing_breaks...) + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_LITERAL_SCALAR_STYLE, + } + if !literal { + token.style = yaml_FOLDED_SCALAR_STYLE + } + return true +} + +// Scan indentation spaces and line breaks for a block scalar. Determine the +// indentation level if needed. +func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { + *end_mark = parser.mark + + // Eat the indentation spaces and line breaks. + max_indent := 0 + for { + // Eat the indentation spaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.mark.column > max_indent { + max_indent = parser.mark.column + } + + // Check for a tab character messing the indentation. + if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an indentation space is expected") + } + + // Have we found a non-empty line? + if !is_break(parser.buffer, parser.buffer_pos) { + break + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + // [Go] Should really be returning breaks instead. + *breaks = read_line(parser, *breaks) + *end_mark = parser.mark + } + + // Determine the indentation level if needed. + if *indent == 0 { + *indent = max_indent + if *indent < parser.indent+1 { + *indent = parser.indent + 1 + } + if *indent < 1 { + *indent = 1 + } + } + return true +} + +// Scan a quoted scalar. +func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { + // Eat the left quote. + start_mark := parser.mark + skip(parser) + + // Consume the content of the quoted scalar. + var s, leading_break, trailing_breaks, whitespaces []byte + for { + // Check that there are no document indicators at the beginning of the line. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator") + return false + } + + // Check for EOF. + if is_z(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream") + return false + } + + // Consume non-blank characters. + leading_blanks := false + for !is_blankz(parser.buffer, parser.buffer_pos) { + if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { + // Is is an escaped single quote. + s = append(s, '\'') + skip(parser) + skip(parser) + + } else if single && parser.buffer[parser.buffer_pos] == '\'' { + // It is a right single quote. + break + } else if !single && parser.buffer[parser.buffer_pos] == '"' { + // It is a right double quote. + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { + // It is an escaped line break. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + skip(parser) + skip_line(parser) + leading_blanks = true + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' { + // It is an escape sequence. + code_length := 0 + + // Check the escape character. + switch parser.buffer[parser.buffer_pos+1] { + case '0': + s = append(s, 0) + case 'a': + s = append(s, '\x07') + case 'b': + s = append(s, '\x08') + case 't', '\t': + s = append(s, '\x09') + case 'n': + s = append(s, '\x0A') + case 'v': + s = append(s, '\x0B') + case 'f': + s = append(s, '\x0C') + case 'r': + s = append(s, '\x0D') + case 'e': + s = append(s, '\x1B') + case ' ': + s = append(s, '\x20') + case '"': + s = append(s, '"') + case '\'': + s = append(s, '\'') + case '\\': + s = append(s, '\\') + case 'N': // NEL (#x85) + s = append(s, '\xC2') + s = append(s, '\x85') + case '_': // #xA0 + s = append(s, '\xC2') + s = append(s, '\xA0') + case 'L': // LS (#x2028) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA8') + case 'P': // PS (#x2029) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA9') + case 'x': + code_length = 2 + case 'u': + code_length = 4 + case 'U': + code_length = 8 + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character") + return false + } + + skip(parser) + skip(parser) + + // Consume an arbitrary escape code. + if code_length > 0 { + var value int + + // Scan the character value. + if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { + return false + } + for k := 0; k < code_length; k++ { + if !is_hex(parser.buffer, parser.buffer_pos+k) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number") + return false + } + value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) + } + + // Check the value and write the character. + if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code") + return false + } + if value <= 0x7F { + s = append(s, byte(value)) + } else if value <= 0x7FF { + s = append(s, byte(0xC0+(value>>6))) + s = append(s, byte(0x80+(value&0x3F))) + } else if value <= 0xFFFF { + s = append(s, byte(0xE0+(value>>12))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } else { + s = append(s, byte(0xF0+(value>>18))) + s = append(s, byte(0x80+((value>>12)&0x3F))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } + + // Advance the pointer. + for k := 0; k < code_length; k++ { + skip(parser) + } + } + } else { + // It is a non-escaped non-blank character. + s = read(parser, s) + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we are at the end of the scalar. + if single { + if parser.buffer[parser.buffer_pos] == '\'' { + break + } + } else { + if parser.buffer[parser.buffer_pos] == '"' { + break + } + } + + // Consume blank characters. + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Join the whitespaces or fold line breaks. + if leading_blanks { + // Do we need to fold line breaks? + if len(leading_break) > 0 && leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Eat the right quote. + skip(parser) + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_SINGLE_QUOTED_SCALAR_STYLE, + } + if !single { + token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + return true +} + +// Scan a plain scalar. +func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { + + var s, leading_break, trailing_breaks, whitespaces []byte + var leading_blanks bool + var indent = parser.indent + 1 + + start_mark := parser.mark + end_mark := parser.mark + + // Consume the content of the plain scalar. + for { + // Check for a document indicator. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + break + } + + // Check for a comment. + if parser.buffer[parser.buffer_pos] == '#' { + break + } + + // Consume non-blank characters. + for !is_blankz(parser.buffer, parser.buffer_pos) { + + // Check for indicators that may end a plain scalar. + if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level > 0 && + (parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}')) { + break + } + + // Check if we need to join whitespaces and breaks. + if leading_blanks || len(whitespaces) > 0 { + if leading_blanks { + // Do we need to fold line breaks? + if leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + leading_blanks = false + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Copy the character. + s = read(parser, s) + + end_mark = parser.mark + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Is it the end? + if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { + break + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + + // Check for tab characters that abuse indentation. + if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violates indentation") + return false + } + + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check indentation level. + if parser.flow_level == 0 && parser.mark.column < indent { + break + } + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_PLAIN_SCALAR_STYLE, + } + + // Note that we change the 'simple_key_allowed' flag. + if leading_blanks { + parser.simple_key_allowed = true + } + return true +} + +func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { + if parser.newlines > 0 { + return true + } + + var start_mark yaml_mark_t + var text []byte + + for peek := 0; peek < 512; peek++ { + if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { + break + } + if is_blank(parser.buffer, parser.buffer_pos+peek) { + continue + } + if parser.buffer[parser.buffer_pos+peek] == '#' { + seen := parser.mark.index + peek + for { + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_breakz(parser.buffer, parser.buffer_pos) { + if parser.mark.index >= seen { + break + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } else if parser.mark.index >= seen { + if len(text) == 0 { + start_mark = parser.mark + } + text = read(parser, text) + } else { + skip(parser) + } + } + } + break + } + if len(text) > 0 { + parser.comments = append(parser.comments, yaml_comment_t{ + token_mark: token_mark, + start_mark: start_mark, + line: text, + }) + } + return true +} + +func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { + token := parser.tokens[len(parser.tokens)-1] + + if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { + token = parser.tokens[len(parser.tokens)-2] + } + + var token_mark = token.start_mark + var start_mark yaml_mark_t + var next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } + + var recent_empty = false + var first_empty = parser.newlines <= 1 + + var line = parser.mark.line + var column = parser.mark.column + + var text []byte + + // The foot line is the place where a comment must start to + // still be considered as a foot of the prior content. + // If there's some content in the currently parsed line, then + // the foot is the line below it. + var foot_line = -1 + if scan_mark.line > 0 { + foot_line = parser.mark.line - parser.newlines + 1 + if parser.newlines == 0 && parser.mark.column > 1 { + foot_line++ + } + } + + var peek = 0 + for ; peek < 512; peek++ { + if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { + break + } + column++ + if is_blank(parser.buffer, parser.buffer_pos+peek) { + continue + } + c := parser.buffer[parser.buffer_pos+peek] + var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') + if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { + // Got line break or terminator. + if close_flow || !recent_empty { + if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { + // This is the first empty line and there were no empty lines before, + // so this initial part of the comment is a foot of the prior token + // instead of being a head for the following one. Split it up. + // Alternatively, this might also be the last comment inside a flow + // scope, so it must be a footer. + if len(text) > 0 { + if start_mark.column-1 < next_indent { + // If dedented it's unrelated to the prior token. + token_mark = start_mark + } + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: token_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, + foot: text, + }) + scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} + token_mark = scan_mark + text = nil + } + } else { + if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { + text = append(text, '\n') + } + } + } + if !is_break(parser.buffer, parser.buffer_pos+peek) { + break + } + first_empty = false + recent_empty = true + column = 0 + line++ + continue + } + + if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { + // The comment at the different indentation is a foot of the + // preceding data rather than a head of the upcoming one. + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: token_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, + foot: text, + }) + scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} + token_mark = scan_mark + text = nil + } + + if parser.buffer[parser.buffer_pos+peek] != '#' { + break + } + + if len(text) == 0 { + start_mark = yaml_mark_t{parser.mark.index + peek, line, column} + } else { + text = append(text, '\n') + } + + recent_empty = false + + // Consume until after the consumed comment line. + seen := parser.mark.index + peek + for { + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_breakz(parser.buffer, parser.buffer_pos) { + if parser.mark.index >= seen { + break + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } else if parser.mark.index >= seen { + text = read(parser, text) + } else { + skip(parser) + } + } + + peek = 0 + column = 0 + line = parser.mark.line + next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } + } + + if len(text) > 0 { + parser.comments = append(parser.comments, yaml_comment_t{ + scan_mark: scan_mark, + token_mark: start_mark, + start_mark: start_mark, + end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, + head: text, + }) + } + return true +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/sorter.go b/event-processor/vendor/go.yaml.in/yaml/v3/sorter.go new file mode 100644 index 00000000..9210ece7 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/sorter.go @@ -0,0 +1,134 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yaml + +import ( + "reflect" + "unicode" +) + +type keyList []reflect.Value + +func (l keyList) Len() int { return len(l) } +func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l keyList) Less(i, j int) bool { + a := l[i] + b := l[j] + ak := a.Kind() + bk := b.Kind() + for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { + a = a.Elem() + ak = a.Kind() + } + for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { + b = b.Elem() + bk = b.Kind() + } + af, aok := keyFloat(a) + bf, bok := keyFloat(b) + if aok && bok { + if af != bf { + return af < bf + } + if ak != bk { + return ak < bk + } + return numLess(a, b) + } + if ak != reflect.String || bk != reflect.String { + return ak < bk + } + ar, br := []rune(a.String()), []rune(b.String()) + digits := false + for i := 0; i < len(ar) && i < len(br); i++ { + if ar[i] == br[i] { + digits = unicode.IsDigit(ar[i]) + continue + } + al := unicode.IsLetter(ar[i]) + bl := unicode.IsLetter(br[i]) + if al && bl { + return ar[i] < br[i] + } + if al || bl { + if digits { + return al + } else { + return bl + } + } + var ai, bi int + var an, bn int64 + if ar[i] == '0' || br[i] == '0' { + for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { + if ar[j] != '0' { + an = 1 + bn = 1 + break + } + } + } + for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { + an = an*10 + int64(ar[ai]-'0') + } + for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { + bn = bn*10 + int64(br[bi]-'0') + } + if an != bn { + return an < bn + } + if ai != bi { + return ai < bi + } + return ar[i] < br[i] + } + return len(ar) < len(br) +} + +// keyFloat returns a float value for v if it is a number/bool +// and whether it is a number/bool or not. +func keyFloat(v reflect.Value) (f float64, ok bool) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(v.Int()), true + case reflect.Float32, reflect.Float64: + return v.Float(), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return float64(v.Uint()), true + case reflect.Bool: + if v.Bool() { + return 1, true + } + return 0, true + } + return 0, false +} + +// numLess returns whether a < b. +// a and b must necessarily have the same kind. +func numLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return a.Int() < b.Int() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Bool: + return !a.Bool() && b.Bool() + } + panic("not a number") +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/writerc.go b/event-processor/vendor/go.yaml.in/yaml/v3/writerc.go new file mode 100644 index 00000000..266d0b09 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/writerc.go @@ -0,0 +1,48 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +// Set the writer error and return false. +func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_WRITER_ERROR + emitter.problem = problem + return false +} + +// Flush the output buffer. +func yaml_emitter_flush(emitter *yaml_emitter_t) bool { + if emitter.write_handler == nil { + panic("write handler not set") + } + + // Check if the buffer is empty. + if emitter.buffer_pos == 0 { + return true + } + + if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + return true +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/yaml.go b/event-processor/vendor/go.yaml.in/yaml/v3/yaml.go new file mode 100644 index 00000000..0b101cd2 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/yaml.go @@ -0,0 +1,703 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package yaml implements YAML support for the Go language. +// +// Source code and other details for the project are available at GitHub: +// +// https://github.com/yaml/go-yaml +package yaml + +import ( + "errors" + "fmt" + "io" + "reflect" + "strings" + "sync" + "unicode/utf8" +) + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a YAML document. +type Unmarshaler interface { + UnmarshalYAML(value *Node) error +} + +type obsoleteUnmarshaler interface { + UnmarshalYAML(unmarshal func(interface{}) error) error +} + +// The Marshaler interface may be implemented by types to customize their +// behavior when being marshaled into a YAML document. The returned value +// is marshaled in place of the original value implementing Marshaler. +// +// If an error is returned by MarshalYAML, the marshaling procedure stops +// and returns with the provided error. +type Marshaler interface { + MarshalYAML() (interface{}, error) +} + +// Unmarshal decodes the first document found within the in byte slice +// and assigns decoded values into the out value. +// +// Maps and pointers (to a struct, string, int, etc) are accepted as out +// values. If an internal pointer within a struct is not initialized, +// the yaml package will initialize it if necessary for unmarshalling +// the provided data. The out parameter must not be nil. +// +// The type of the decoded values should be compatible with the respective +// values in out. If one or more values cannot be decoded due to a type +// mismatches, decoding continues partially until the end of the YAML +// content, and a *yaml.TypeError is returned with details for all +// missed values. +// +// Struct fields are only unmarshalled if they are exported (have an +// upper case first letter), and are unmarshalled using the field name +// lowercased as the default key. Custom keys may be defined via the +// "yaml" name in the field tag: the content preceding the first comma +// is used as the key, and the following comma-separated options are +// used to tweak the marshalling process (see Marshal). +// Conflicting names result in a runtime error. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// var t T +// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) +// +// See the documentation of Marshal for the format of tags and a list of +// supported tag options. +func Unmarshal(in []byte, out interface{}) (err error) { + return unmarshal(in, out, false) +} + +// A Decoder reads and decodes YAML values from an input stream. +type Decoder struct { + parser *parser + knownFields bool +} + +// NewDecoder returns a new decoder that reads from r. +// +// The decoder introduces its own buffering and may read +// data from r beyond the YAML values requested. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + parser: newParserFromReader(r), + } +} + +// KnownFields ensures that the keys in decoded mappings to +// exist as fields in the struct being decoded into. +func (dec *Decoder) KnownFields(enable bool) { + dec.knownFields = enable +} + +// Decode reads the next YAML-encoded value from its input +// and stores it in the value pointed to by v. +// +// See the documentation for Unmarshal for details about the +// conversion of YAML into a Go value. +func (dec *Decoder) Decode(v interface{}) (err error) { + d := newDecoder() + d.knownFields = dec.knownFields + defer handleErr(&err) + node := dec.parser.parse() + if node == nil { + return io.EOF + } + out := reflect.ValueOf(v) + if out.Kind() == reflect.Ptr && !out.IsNil() { + out = out.Elem() + } + d.unmarshal(node, out) + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Decode decodes the node and stores its data into the value pointed to by v. +// +// See the documentation for Unmarshal for details about the +// conversion of YAML into a Go value. +func (n *Node) Decode(v interface{}) (err error) { + d := newDecoder() + defer handleErr(&err) + out := reflect.ValueOf(v) + if out.Kind() == reflect.Ptr && !out.IsNil() { + out = out.Elem() + } + d.unmarshal(n, out) + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +func unmarshal(in []byte, out interface{}, strict bool) (err error) { + defer handleErr(&err) + d := newDecoder() + p := newParser(in) + defer p.destroy() + node := p.parse() + if node != nil { + v := reflect.ValueOf(out) + if v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + d.unmarshal(node, v) + } + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Marshal serializes the value provided into a YAML document. The structure +// of the generated document will reflect the structure of the value itself. +// Maps and pointers (to struct, string, int, etc) are accepted as the in value. +// +// Struct fields are only marshalled if they are exported (have an upper case +// first letter), and are marshalled using the field name lowercased as the +// default key. Custom keys may be defined via the "yaml" name in the field +// tag: the content preceding the first comma is used as the key, and the +// following comma-separated options are used to tweak the marshalling process. +// Conflicting names result in a runtime error. +// +// The field tag format accepted is: +// +// `(...) yaml:"[][,[,]]" (...)` +// +// The following flags are currently supported: +// +// omitempty Only include the field if it's not set to the zero +// value for the type or to empty slices or maps. +// Zero valued structs will be omitted if all their public +// fields are zero, unless they implement an IsZero +// method (see the IsZeroer interface type), in which +// case the field will be excluded if IsZero returns true. +// +// flow Marshal using a flow style (useful for structs, +// sequences and maps). +// +// inline Inline the field, which must be a struct or a map, +// causing all of its fields or keys to be processed as if +// they were part of the outer struct. For maps, keys must +// not conflict with the yaml keys of other struct fields. +// +// In addition, if the key is "-", the field is ignored. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" +// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" +func Marshal(in interface{}) (out []byte, err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(in)) + e.finish() + out = e.out + return +} + +// An Encoder writes YAML values to an output stream. +type Encoder struct { + encoder *encoder +} + +// NewEncoder returns a new encoder that writes to w. +// The Encoder should be closed after use to flush all data +// to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + encoder: newEncoderWithWriter(w), + } +} + +// Encode writes the YAML encoding of v to the stream. +// If multiple items are encoded to the stream, the +// second and subsequent document will be preceded +// with a "---" document separator, but the first will not. +// +// See the documentation for Marshal for details about the conversion of Go +// values to YAML. +func (e *Encoder) Encode(v interface{}) (err error) { + defer handleErr(&err) + e.encoder.marshalDoc("", reflect.ValueOf(v)) + return nil +} + +// Encode encodes value v and stores its representation in n. +// +// See the documentation for Marshal for details about the +// conversion of Go values into YAML. +func (n *Node) Encode(v interface{}) (err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(v)) + e.finish() + p := newParser(e.out) + p.textless = true + defer p.destroy() + doc := p.parse() + *n = *doc.Content[0] + return nil +} + +// SetIndent changes the used indentation used when encoding. +func (e *Encoder) SetIndent(spaces int) { + if spaces < 0 { + panic("yaml: cannot indent to a negative number of spaces") + } + e.encoder.indent = spaces +} + +// CompactSeqIndent makes it so that '- ' is considered part of the indentation. +func (e *Encoder) CompactSeqIndent() { + e.encoder.emitter.compact_sequence_indent = true +} + +// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation. +func (e *Encoder) DefaultSeqIndent() { + e.encoder.emitter.compact_sequence_indent = false +} + +// Close closes the encoder by writing any remaining data. +// It does not write a stream terminating string "...". +func (e *Encoder) Close() (err error) { + defer handleErr(&err) + e.encoder.finish() + return nil +} + +func handleErr(err *error) { + if v := recover(); v != nil { + if e, ok := v.(yamlError); ok { + *err = e.err + } else { + panic(v) + } + } +} + +type yamlError struct { + err error +} + +func fail(err error) { + panic(yamlError{err}) +} + +func failf(format string, args ...interface{}) { + panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) +} + +// A TypeError is returned by Unmarshal when one or more fields in +// the YAML document cannot be properly decoded into the requested +// types. When this error is returned, the value is still +// unmarshaled partially. +type TypeError struct { + Errors []string +} + +func (e *TypeError) Error() string { + return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) +} + +type Kind uint32 + +const ( + DocumentNode Kind = 1 << iota + SequenceNode + MappingNode + ScalarNode + AliasNode +) + +type Style uint32 + +const ( + TaggedStyle Style = 1 << iota + DoubleQuotedStyle + SingleQuotedStyle + LiteralStyle + FoldedStyle + FlowStyle +) + +// Node represents an element in the YAML document hierarchy. While documents +// are typically encoded and decoded into higher level types, such as structs +// and maps, Node is an intermediate representation that allows detailed +// control over the content being decoded or encoded. +// +// It's worth noting that although Node offers access into details such as +// line numbers, colums, and comments, the content when re-encoded will not +// have its original textual representation preserved. An effort is made to +// render the data plesantly, and to preserve comments near the data they +// describe, though. +// +// Values that make use of the Node type interact with the yaml package in the +// same way any other type would do, by encoding and decoding yaml data +// directly or indirectly into them. +// +// For example: +// +// var person struct { +// Name string +// Address yaml.Node +// } +// err := yaml.Unmarshal(data, &person) +// +// Or by itself: +// +// var person Node +// err := yaml.Unmarshal(data, &person) +type Node struct { + // Kind defines whether the node is a document, a mapping, a sequence, + // a scalar value, or an alias to another node. The specific data type of + // scalar nodes may be obtained via the ShortTag and LongTag methods. + Kind Kind + + // Style allows customizing the apperance of the node in the tree. + Style Style + + // Tag holds the YAML tag defining the data type for the value. + // When decoding, this field will always be set to the resolved tag, + // even when it wasn't explicitly provided in the YAML content. + // When encoding, if this field is unset the value type will be + // implied from the node properties, and if it is set, it will only + // be serialized into the representation if TaggedStyle is used or + // the implicit tag diverges from the provided one. + Tag string + + // Value holds the unescaped and unquoted represenation of the value. + Value string + + // Anchor holds the anchor name for this node, which allows aliases to point to it. + Anchor string + + // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. + Alias *Node + + // Content holds contained nodes for documents, mappings, and sequences. + Content []*Node + + // HeadComment holds any comments in the lines preceding the node and + // not separated by an empty line. + HeadComment string + + // LineComment holds any comments at the end of the line where the node is in. + LineComment string + + // FootComment holds any comments following the node and before empty lines. + FootComment string + + // Line and Column hold the node position in the decoded YAML text. + // These fields are not respected when encoding the node. + Line int + Column int +} + +// IsZero returns whether the node has all of its fields unset. +func (n *Node) IsZero() bool { + return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && + n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 +} + +// LongTag returns the long form of the tag that indicates the data type for +// the node. If the Tag field isn't explicitly defined, one will be computed +// based on the node properties. +func (n *Node) LongTag() string { + return longTag(n.ShortTag()) +} + +// ShortTag returns the short form of the YAML tag that indicates data type for +// the node. If the Tag field isn't explicitly defined, one will be computed +// based on the node properties. +func (n *Node) ShortTag() string { + if n.indicatedString() { + return strTag + } + if n.Tag == "" || n.Tag == "!" { + switch n.Kind { + case MappingNode: + return mapTag + case SequenceNode: + return seqTag + case AliasNode: + if n.Alias != nil { + return n.Alias.ShortTag() + } + case ScalarNode: + tag, _ := resolve("", n.Value) + return tag + case 0: + // Special case to make the zero value convenient. + if n.IsZero() { + return nullTag + } + } + return "" + } + return shortTag(n.Tag) +} + +func (n *Node) indicatedString() bool { + return n.Kind == ScalarNode && + (shortTag(n.Tag) == strTag || + (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) +} + +// SetString is a convenience function that sets the node to a string value +// and defines its style in a pleasant way depending on its content. +func (n *Node) SetString(s string) { + n.Kind = ScalarNode + if utf8.ValidString(s) { + n.Value = s + n.Tag = strTag + } else { + n.Value = encodeBase64(s) + n.Tag = binaryTag + } + if strings.Contains(n.Value, "\n") { + n.Style = LiteralStyle + } +} + +// -------------------------------------------------------------------------- +// Maintain a mapping of keys to structure field indexes + +// The code in this section was copied from mgo/bson. + +// structInfo holds details for the serialization of fields of +// a given struct. +type structInfo struct { + FieldsMap map[string]fieldInfo + FieldsList []fieldInfo + + // InlineMap is the number of the field in the struct that + // contains an ,inline map, or -1 if there's none. + InlineMap int + + // InlineUnmarshalers holds indexes to inlined fields that + // contain unmarshaler values. + InlineUnmarshalers [][]int +} + +type fieldInfo struct { + Key string + Num int + OmitEmpty bool + Flow bool + // Id holds the unique field identifier, so we can cheaply + // check for field duplicates without maintaining an extra map. + Id int + + // Inline holds the field index if the field is part of an inlined struct. + Inline []int +} + +var structMap = make(map[reflect.Type]*structInfo) +var fieldMapMutex sync.RWMutex +var unmarshalerType reflect.Type + +func init() { + var v Unmarshaler + unmarshalerType = reflect.ValueOf(&v).Elem().Type() +} + +func getStructInfo(st reflect.Type) (*structInfo, error) { + fieldMapMutex.RLock() + sinfo, found := structMap[st] + fieldMapMutex.RUnlock() + if found { + return sinfo, nil + } + + n := st.NumField() + fieldsMap := make(map[string]fieldInfo) + fieldsList := make([]fieldInfo, 0, n) + inlineMap := -1 + inlineUnmarshalers := [][]int(nil) + for i := 0; i != n; i++ { + field := st.Field(i) + if field.PkgPath != "" && !field.Anonymous { + continue // Private field + } + + info := fieldInfo{Num: i} + + tag := field.Tag.Get("yaml") + if tag == "" && strings.Index(string(field.Tag), ":") < 0 { + tag = string(field.Tag) + } + if tag == "-" { + continue + } + + inline := false + fields := strings.Split(tag, ",") + if len(fields) > 1 { + for _, flag := range fields[1:] { + switch flag { + case "omitempty": + info.OmitEmpty = true + case "flow": + info.Flow = true + case "inline": + inline = true + default: + return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) + } + } + tag = fields[0] + } + + if inline { + switch field.Type.Kind() { + case reflect.Map: + if inlineMap >= 0 { + return nil, errors.New("multiple ,inline maps in struct " + st.String()) + } + if field.Type.Key() != reflect.TypeOf("") { + return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) + } + inlineMap = info.Num + case reflect.Struct, reflect.Ptr: + ftype := field.Type + for ftype.Kind() == reflect.Ptr { + ftype = ftype.Elem() + } + if ftype.Kind() != reflect.Struct { + return nil, errors.New("option ,inline may only be used on a struct or map field") + } + if reflect.PtrTo(ftype).Implements(unmarshalerType) { + inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) + } else { + sinfo, err := getStructInfo(ftype) + if err != nil { + return nil, err + } + for _, index := range sinfo.InlineUnmarshalers { + inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) + } + for _, finfo := range sinfo.FieldsList { + if _, found := fieldsMap[finfo.Key]; found { + msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + if finfo.Inline == nil { + finfo.Inline = []int{i, finfo.Num} + } else { + finfo.Inline = append([]int{i}, finfo.Inline...) + } + finfo.Id = len(fieldsList) + fieldsMap[finfo.Key] = finfo + fieldsList = append(fieldsList, finfo) + } + } + default: + return nil, errors.New("option ,inline may only be used on a struct or map field") + } + continue + } + + if tag != "" { + info.Key = tag + } else { + info.Key = strings.ToLower(field.Name) + } + + if _, found = fieldsMap[info.Key]; found { + msg := "duplicated key '" + info.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + + info.Id = len(fieldsList) + fieldsList = append(fieldsList, info) + fieldsMap[info.Key] = info + } + + sinfo = &structInfo{ + FieldsMap: fieldsMap, + FieldsList: fieldsList, + InlineMap: inlineMap, + InlineUnmarshalers: inlineUnmarshalers, + } + + fieldMapMutex.Lock() + structMap[st] = sinfo + fieldMapMutex.Unlock() + return sinfo, nil +} + +// IsZeroer is used to check whether an object is zero to +// determine whether it should be omitted when marshaling +// with the omitempty flag. One notable implementation +// is time.Time. +type IsZeroer interface { + IsZero() bool +} + +func isZero(v reflect.Value) bool { + kind := v.Kind() + if z, ok := v.Interface().(IsZeroer); ok { + if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { + return true + } + return z.IsZero() + } + switch kind { + case reflect.String: + return len(v.String()) == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Slice: + return v.Len() == 0 + case reflect.Map: + return v.Len() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Struct: + vt := v.Type() + for i := v.NumField() - 1; i >= 0; i-- { + if vt.Field(i).PkgPath != "" { + continue // Private field + } + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/yamlh.go b/event-processor/vendor/go.yaml.in/yaml/v3/yamlh.go new file mode 100644 index 00000000..f59aa40f --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/yamlh.go @@ -0,0 +1,811 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +import ( + "fmt" + "io" +) + +// The version directive data. +type yaml_version_directive_t struct { + major int8 // The major version number. + minor int8 // The minor version number. +} + +// The tag directive data. +type yaml_tag_directive_t struct { + handle []byte // The tag handle. + prefix []byte // The tag prefix. +} + +type yaml_encoding_t int + +// The stream encoding. +const ( + // Let the parser choose the encoding. + yaml_ANY_ENCODING yaml_encoding_t = iota + + yaml_UTF8_ENCODING // The default UTF-8 encoding. + yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. + yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. +) + +type yaml_break_t int + +// Line break types. +const ( + // Let the parser choose the break type. + yaml_ANY_BREAK yaml_break_t = iota + + yaml_CR_BREAK // Use CR for line breaks (Mac style). + yaml_LN_BREAK // Use LN for line breaks (Unix style). + yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). +) + +type yaml_error_type_t int + +// Many bad things could happen with the parser and emitter. +const ( + // No error is produced. + yaml_NO_ERROR yaml_error_type_t = iota + + yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. + yaml_READER_ERROR // Cannot read or decode the input stream. + yaml_SCANNER_ERROR // Cannot scan the input stream. + yaml_PARSER_ERROR // Cannot parse the input stream. + yaml_COMPOSER_ERROR // Cannot compose a YAML document. + yaml_WRITER_ERROR // Cannot write to the output stream. + yaml_EMITTER_ERROR // Cannot emit a YAML stream. +) + +// The pointer position. +type yaml_mark_t struct { + index int // The position index. + line int // The position line. + column int // The position column. +} + +// Node Styles + +type yaml_style_t int8 + +type yaml_scalar_style_t yaml_style_t + +// Scalar styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 + + yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. + yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. + yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. + yaml_LITERAL_SCALAR_STYLE // The literal scalar style. + yaml_FOLDED_SCALAR_STYLE // The folded scalar style. +) + +type yaml_sequence_style_t yaml_style_t + +// Sequence styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota + + yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. + yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. +) + +type yaml_mapping_style_t yaml_style_t + +// Mapping styles. +const ( + // Let the emitter choose the style. + yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota + + yaml_BLOCK_MAPPING_STYLE // The block mapping style. + yaml_FLOW_MAPPING_STYLE // The flow mapping style. +) + +// Tokens + +type yaml_token_type_t int + +// Token types. +const ( + // An empty token. + yaml_NO_TOKEN yaml_token_type_t = iota + + yaml_STREAM_START_TOKEN // A STREAM-START token. + yaml_STREAM_END_TOKEN // A STREAM-END token. + + yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. + yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. + yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. + yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. + + yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. + yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. + yaml_BLOCK_END_TOKEN // A BLOCK-END token. + + yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. + yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. + yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. + yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. + + yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. + yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. + yaml_KEY_TOKEN // A KEY token. + yaml_VALUE_TOKEN // A VALUE token. + + yaml_ALIAS_TOKEN // An ALIAS token. + yaml_ANCHOR_TOKEN // An ANCHOR token. + yaml_TAG_TOKEN // A TAG token. + yaml_SCALAR_TOKEN // A SCALAR token. +) + +func (tt yaml_token_type_t) String() string { + switch tt { + case yaml_NO_TOKEN: + return "yaml_NO_TOKEN" + case yaml_STREAM_START_TOKEN: + return "yaml_STREAM_START_TOKEN" + case yaml_STREAM_END_TOKEN: + return "yaml_STREAM_END_TOKEN" + case yaml_VERSION_DIRECTIVE_TOKEN: + return "yaml_VERSION_DIRECTIVE_TOKEN" + case yaml_TAG_DIRECTIVE_TOKEN: + return "yaml_TAG_DIRECTIVE_TOKEN" + case yaml_DOCUMENT_START_TOKEN: + return "yaml_DOCUMENT_START_TOKEN" + case yaml_DOCUMENT_END_TOKEN: + return "yaml_DOCUMENT_END_TOKEN" + case yaml_BLOCK_SEQUENCE_START_TOKEN: + return "yaml_BLOCK_SEQUENCE_START_TOKEN" + case yaml_BLOCK_MAPPING_START_TOKEN: + return "yaml_BLOCK_MAPPING_START_TOKEN" + case yaml_BLOCK_END_TOKEN: + return "yaml_BLOCK_END_TOKEN" + case yaml_FLOW_SEQUENCE_START_TOKEN: + return "yaml_FLOW_SEQUENCE_START_TOKEN" + case yaml_FLOW_SEQUENCE_END_TOKEN: + return "yaml_FLOW_SEQUENCE_END_TOKEN" + case yaml_FLOW_MAPPING_START_TOKEN: + return "yaml_FLOW_MAPPING_START_TOKEN" + case yaml_FLOW_MAPPING_END_TOKEN: + return "yaml_FLOW_MAPPING_END_TOKEN" + case yaml_BLOCK_ENTRY_TOKEN: + return "yaml_BLOCK_ENTRY_TOKEN" + case yaml_FLOW_ENTRY_TOKEN: + return "yaml_FLOW_ENTRY_TOKEN" + case yaml_KEY_TOKEN: + return "yaml_KEY_TOKEN" + case yaml_VALUE_TOKEN: + return "yaml_VALUE_TOKEN" + case yaml_ALIAS_TOKEN: + return "yaml_ALIAS_TOKEN" + case yaml_ANCHOR_TOKEN: + return "yaml_ANCHOR_TOKEN" + case yaml_TAG_TOKEN: + return "yaml_TAG_TOKEN" + case yaml_SCALAR_TOKEN: + return "yaml_SCALAR_TOKEN" + } + return "" +} + +// The token structure. +type yaml_token_t struct { + // The token type. + typ yaml_token_type_t + + // The start/end of the token. + start_mark, end_mark yaml_mark_t + + // The stream encoding (for yaml_STREAM_START_TOKEN). + encoding yaml_encoding_t + + // The alias/anchor/scalar value or tag/tag directive handle + // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). + value []byte + + // The tag suffix (for yaml_TAG_TOKEN). + suffix []byte + + // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). + prefix []byte + + // The scalar style (for yaml_SCALAR_TOKEN). + style yaml_scalar_style_t + + // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). + major, minor int8 +} + +// Events + +type yaml_event_type_t int8 + +// Event types. +const ( + // An empty event. + yaml_NO_EVENT yaml_event_type_t = iota + + yaml_STREAM_START_EVENT // A STREAM-START event. + yaml_STREAM_END_EVENT // A STREAM-END event. + yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. + yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. + yaml_ALIAS_EVENT // An ALIAS event. + yaml_SCALAR_EVENT // A SCALAR event. + yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. + yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. + yaml_MAPPING_START_EVENT // A MAPPING-START event. + yaml_MAPPING_END_EVENT // A MAPPING-END event. + yaml_TAIL_COMMENT_EVENT +) + +var eventStrings = []string{ + yaml_NO_EVENT: "none", + yaml_STREAM_START_EVENT: "stream start", + yaml_STREAM_END_EVENT: "stream end", + yaml_DOCUMENT_START_EVENT: "document start", + yaml_DOCUMENT_END_EVENT: "document end", + yaml_ALIAS_EVENT: "alias", + yaml_SCALAR_EVENT: "scalar", + yaml_SEQUENCE_START_EVENT: "sequence start", + yaml_SEQUENCE_END_EVENT: "sequence end", + yaml_MAPPING_START_EVENT: "mapping start", + yaml_MAPPING_END_EVENT: "mapping end", + yaml_TAIL_COMMENT_EVENT: "tail comment", +} + +func (e yaml_event_type_t) String() string { + if e < 0 || int(e) >= len(eventStrings) { + return fmt.Sprintf("unknown event %d", e) + } + return eventStrings[e] +} + +// The event structure. +type yaml_event_t struct { + + // The event type. + typ yaml_event_type_t + + // The start and end of the event. + start_mark, end_mark yaml_mark_t + + // The document encoding (for yaml_STREAM_START_EVENT). + encoding yaml_encoding_t + + // The version directive (for yaml_DOCUMENT_START_EVENT). + version_directive *yaml_version_directive_t + + // The list of tag directives (for yaml_DOCUMENT_START_EVENT). + tag_directives []yaml_tag_directive_t + + // The comments + head_comment []byte + line_comment []byte + foot_comment []byte + tail_comment []byte + + // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). + anchor []byte + + // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + tag []byte + + // The scalar value (for yaml_SCALAR_EVENT). + value []byte + + // Is the document start/end indicator implicit, or the tag optional? + // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). + implicit bool + + // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). + quoted_implicit bool + + // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + style yaml_style_t +} + +func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } +func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } +func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } + +// Nodes + +const ( + yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. + yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. + yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. + yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. + yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. + yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. + + yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. + yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. + + // Not in original libyaml. + yaml_BINARY_TAG = "tag:yaml.org,2002:binary" + yaml_MERGE_TAG = "tag:yaml.org,2002:merge" + + yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. + yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. + yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. +) + +type yaml_node_type_t int + +// Node types. +const ( + // An empty node. + yaml_NO_NODE yaml_node_type_t = iota + + yaml_SCALAR_NODE // A scalar node. + yaml_SEQUENCE_NODE // A sequence node. + yaml_MAPPING_NODE // A mapping node. +) + +// An element of a sequence node. +type yaml_node_item_t int + +// An element of a mapping node. +type yaml_node_pair_t struct { + key int // The key of the element. + value int // The value of the element. +} + +// The node structure. +type yaml_node_t struct { + typ yaml_node_type_t // The node type. + tag []byte // The node tag. + + // The node data. + + // The scalar parameters (for yaml_SCALAR_NODE). + scalar struct { + value []byte // The scalar value. + length int // The length of the scalar value. + style yaml_scalar_style_t // The scalar style. + } + + // The sequence parameters (for YAML_SEQUENCE_NODE). + sequence struct { + items_data []yaml_node_item_t // The stack of sequence items. + style yaml_sequence_style_t // The sequence style. + } + + // The mapping parameters (for yaml_MAPPING_NODE). + mapping struct { + pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). + pairs_start *yaml_node_pair_t // The beginning of the stack. + pairs_end *yaml_node_pair_t // The end of the stack. + pairs_top *yaml_node_pair_t // The top of the stack. + style yaml_mapping_style_t // The mapping style. + } + + start_mark yaml_mark_t // The beginning of the node. + end_mark yaml_mark_t // The end of the node. + +} + +// The document structure. +type yaml_document_t struct { + + // The document nodes. + nodes []yaml_node_t + + // The version directive. + version_directive *yaml_version_directive_t + + // The list of tag directives. + tag_directives_data []yaml_tag_directive_t + tag_directives_start int // The beginning of the tag directives list. + tag_directives_end int // The end of the tag directives list. + + start_implicit int // Is the document start indicator implicit? + end_implicit int // Is the document end indicator implicit? + + // The start/end of the document. + start_mark, end_mark yaml_mark_t +} + +// The prototype of a read handler. +// +// The read handler is called when the parser needs to read more bytes from the +// source. The handler should write not more than size bytes to the buffer. +// The number of written bytes should be set to the size_read variable. +// +// [in,out] data A pointer to an application data specified by +// +// yaml_parser_set_input(). +// +// [out] buffer The buffer to write the data from the source. +// [in] size The size of the buffer. +// [out] size_read The actual number of bytes read from the source. +// +// On success, the handler should return 1. If the handler failed, +// the returned value should be 0. On EOF, the handler should set the +// size_read to 0 and return 1. +type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) + +// This structure holds information about a potential simple key. +type yaml_simple_key_t struct { + possible bool // Is a simple key possible? + required bool // Is a simple key required? + token_number int // The number of the token. + mark yaml_mark_t // The position mark. +} + +// The states of the parser. +type yaml_parser_state_t int + +const ( + yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota + + yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. + yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. + yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. + yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. + yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. + yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. + yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. + yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. + yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. + yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. + yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. + yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. + yaml_PARSE_END_STATE // Expect nothing. +) + +func (ps yaml_parser_state_t) String() string { + switch ps { + case yaml_PARSE_STREAM_START_STATE: + return "yaml_PARSE_STREAM_START_STATE" + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_START_STATE: + return "yaml_PARSE_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return "yaml_PARSE_DOCUMENT_CONTENT_STATE" + case yaml_PARSE_DOCUMENT_END_STATE: + return "yaml_PARSE_DOCUMENT_END_STATE" + case yaml_PARSE_BLOCK_NODE_STATE: + return "yaml_PARSE_BLOCK_NODE_STATE" + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" + case yaml_PARSE_FLOW_NODE_STATE: + return "yaml_PARSE_FLOW_NODE_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" + case yaml_PARSE_END_STATE: + return "yaml_PARSE_END_STATE" + } + return "" +} + +// This structure holds aliases data. +type yaml_alias_data_t struct { + anchor []byte // The anchor. + index int // The node id. + mark yaml_mark_t // The anchor mark. +} + +// The parser structure. +// +// All members are internal. Manage the structure using the +// yaml_parser_ family of functions. +type yaml_parser_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + + problem string // Error description. + + // The byte about which the problem occurred. + problem_offset int + problem_value int + problem_mark yaml_mark_t + + // The error context. + context string + context_mark yaml_mark_t + + // Reader stuff + + read_handler yaml_read_handler_t // Read handler. + + input_reader io.Reader // File input data. + input []byte // String input data. + input_pos int + + eof bool // EOF flag + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + unread int // The number of unread characters in the buffer. + + newlines int // The number of line breaks since last non-break/non-blank character + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The input encoding. + + offset int // The offset of the current position (in bytes). + mark yaml_mark_t // The mark of the current position. + + // Comments + + head_comment []byte // The current head comments + line_comment []byte // The current line comments + foot_comment []byte // The current foot comments + tail_comment []byte // Foot comment that happens at the end of a block. + stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) + + comments []yaml_comment_t // The folded comments for all parsed tokens + comments_head int + + // Scanner stuff + + stream_start_produced bool // Have we started to scan the input stream? + stream_end_produced bool // Have we reached the end of the input stream? + + flow_level int // The number of unclosed '[' and '{' indicators. + + tokens []yaml_token_t // The tokens queue. + tokens_head int // The head of the tokens queue. + tokens_parsed int // The number of tokens fetched from the queue. + token_available bool // Does the tokens queue contain a token ready for dequeueing. + + indent int // The current indentation level. + indents []int // The indentation levels stack. + + simple_key_allowed bool // May a simple key occur at the current position? + simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number + + // Parser stuff + + state yaml_parser_state_t // The current parser state. + states []yaml_parser_state_t // The parser states stack. + marks []yaml_mark_t // The stack of marks. + tag_directives []yaml_tag_directive_t // The list of TAG directives. + + // Dumper stuff + + aliases []yaml_alias_data_t // The alias data. + + document *yaml_document_t // The currently parsed document. +} + +type yaml_comment_t struct { + scan_mark yaml_mark_t // Position where scanning for comments started + token_mark yaml_mark_t // Position after which tokens will be associated with this comment + start_mark yaml_mark_t // Position of '#' comment mark + end_mark yaml_mark_t // Position where comment terminated + + head []byte + line []byte + foot []byte +} + +// Emitter Definitions + +// The prototype of a write handler. +// +// The write handler is called when the emitter needs to flush the accumulated +// characters to the output. The handler should write @a size bytes of the +// @a buffer to the output. +// +// @param[in,out] data A pointer to an application data specified by +// +// yaml_emitter_set_output(). +// +// @param[in] buffer The buffer with bytes to be written. +// @param[in] size The size of the buffer. +// +// @returns On success, the handler should return @c 1. If the handler failed, +// the returned value should be @c 0. +type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error + +type yaml_emitter_state_t int + +// The emitter states. +const ( + // Expect STREAM-START. + yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota + + yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. + yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out + yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. + yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out + yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. + yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. + yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. + yaml_EMIT_END_STATE // Expect nothing. +) + +// The emitter structure. +// +// All members are internal. Manage the structure using the @c yaml_emitter_ +// family of functions. +type yaml_emitter_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + problem string // Error description. + + // Writer stuff + + write_handler yaml_write_handler_t // Write handler. + + output_buffer *[]byte // String output data. + output_writer io.Writer // File output data. + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The stream encoding. + + // Emitter stuff + + canonical bool // If the output is in the canonical style? + best_indent int // The number of indentation spaces. + best_width int // The preferred width of the output lines. + unicode bool // Allow unescaped non-ASCII characters? + line_break yaml_break_t // The preferred line break. + + state yaml_emitter_state_t // The current emitter state. + states []yaml_emitter_state_t // The stack of states. + + events []yaml_event_t // The event queue. + events_head int // The head of the event queue. + + indents []int // The stack of indentation levels. + + tag_directives []yaml_tag_directive_t // The list of tag directives. + + indent int // The current indentation level. + + compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements? + + flow_level int // The current flow level. + + root_context bool // Is it the document root context? + sequence_context bool // Is it a sequence context? + mapping_context bool // Is it a mapping context? + simple_key_context bool // Is it a simple mapping key context? + + line int // The current line. + column int // The current column. + whitespace bool // If the last character was a whitespace? + indention bool // If the last character was an indentation character (' ', '-', '?', ':')? + open_ended bool // If an explicit document end is required? + + space_above bool // Is there's an empty line above? + foot_indent int // The indent used to write the foot comment above, or -1 if none. + + // Anchor analysis. + anchor_data struct { + anchor []byte // The anchor value. + alias bool // Is it an alias? + } + + // Tag analysis. + tag_data struct { + handle []byte // The tag handle. + suffix []byte // The tag suffix. + } + + // Scalar analysis. + scalar_data struct { + value []byte // The scalar value. + multiline bool // Does the scalar contain line breaks? + flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? + block_plain_allowed bool // Can the scalar be expressed in the block plain style? + single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? + block_allowed bool // Can the scalar be expressed in the literal or folded styles? + style yaml_scalar_style_t // The output style. + } + + // Comments + head_comment []byte + line_comment []byte + foot_comment []byte + tail_comment []byte + + key_line_comment []byte + + // Dumper stuff + + opened bool // If the stream was already opened? + closed bool // If the stream was already closed? + + // The information associated with the document nodes. + anchors *struct { + references int // The number of references. + anchor int // The anchor id. + serialized bool // If the node has been emitted? + } + + last_anchor_id int // The last assigned anchor id. + + document *yaml_document_t // The currently emitted document. +} diff --git a/event-processor/vendor/go.yaml.in/yaml/v3/yamlprivateh.go b/event-processor/vendor/go.yaml.in/yaml/v3/yamlprivateh.go new file mode 100644 index 00000000..dea1ba96 --- /dev/null +++ b/event-processor/vendor/go.yaml.in/yaml/v3/yamlprivateh.go @@ -0,0 +1,198 @@ +// +// Copyright (c) 2011-2019 Canonical Ltd +// Copyright (c) 2006-2010 Kirill Simonov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package yaml + +const ( + // The size of the input raw buffer. + input_raw_buffer_size = 512 + + // The size of the input buffer. + // It should be possible to decode the whole raw buffer. + input_buffer_size = input_raw_buffer_size * 3 + + // The size of the output buffer. + output_buffer_size = 128 + + // The size of the output raw buffer. + // It should be possible to encode the whole output buffer. + output_raw_buffer_size = (output_buffer_size*2 + 2) + + // The size of other stacks and queues. + initial_stack_size = 16 + initial_queue_size = 16 + initial_string_size = 16 +) + +// Check if the character at the specified position is an alphabetical +// character, a digit, '_', or '-'. +func is_alpha(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' +} + +// Check if the character at the specified position is a digit. +func is_digit(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' +} + +// Get the value of a digit. +func as_digit(b []byte, i int) int { + return int(b[i]) - '0' +} + +// Check if the character at the specified position is a hex-digit. +func is_hex(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' +} + +// Get the value of a hex-digit. +func as_hex(b []byte, i int) int { + bi := b[i] + if bi >= 'A' && bi <= 'F' { + return int(bi) - 'A' + 10 + } + if bi >= 'a' && bi <= 'f' { + return int(bi) - 'a' + 10 + } + return int(bi) - '0' +} + +// Check if the character is ASCII. +func is_ascii(b []byte, i int) bool { + return b[i] <= 0x7F +} + +// Check if the character at the start of the buffer can be printed unescaped. +func is_printable(b []byte, i int) bool { + return ((b[i] == 0x0A) || // . == #x0A + (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E + (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF + (b[i] > 0xC2 && b[i] < 0xED) || + (b[i] == 0xED && b[i+1] < 0xA0) || + (b[i] == 0xEE) || + (b[i] == 0xEF && // #xE000 <= . <= #xFFFD + !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF + !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) +} + +// Check if the character at the specified position is NUL. +func is_z(b []byte, i int) bool { + return b[i] == 0x00 +} + +// Check if the beginning of the buffer is a BOM. +func is_bom(b []byte, i int) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +// Check if the character at the specified position is space. +func is_space(b []byte, i int) bool { + return b[i] == ' ' +} + +// Check if the character at the specified position is tab. +func is_tab(b []byte, i int) bool { + return b[i] == '\t' +} + +// Check if the character at the specified position is blank (space or tab). +func is_blank(b []byte, i int) bool { + //return is_space(b, i) || is_tab(b, i) + return b[i] == ' ' || b[i] == '\t' +} + +// Check if the character at the specified position is a line break. +func is_break(b []byte, i int) bool { + return (b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) +} + +func is_crlf(b []byte, i int) bool { + return b[i] == '\r' && b[i+1] == '\n' +} + +// Check if the character is a line break or NUL. +func is_breakz(b []byte, i int) bool { + //return is_break(b, i) || is_z(b, i) + return ( + // is_break: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + // is_z: + b[i] == 0) +} + +// Check if the character is a line break, space, or NUL. +func is_spacez(b []byte, i int) bool { + //return is_space(b, i) || is_breakz(b, i) + return ( + // is_space: + b[i] == ' ' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Check if the character is a line break, space, tab, or NUL. +func is_blankz(b []byte, i int) bool { + //return is_blank(b, i) || is_breakz(b, i) + return ( + // is_blank: + b[i] == ' ' || b[i] == '\t' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Determine the width of the character. +func width(b byte) int { + // Don't replace these by a switch without first + // confirming that it is being inlined. + if b&0x80 == 0x00 { + return 1 + } + if b&0xE0 == 0xC0 { + return 2 + } + if b&0xF0 == 0xE0 { + return 3 + } + if b&0xF8 == 0xF0 { + return 4 + } + return 0 + +} diff --git a/event-processor/vendor/golang.org/x/exp/constraints/constraints.go b/event-processor/vendor/golang.org/x/exp/constraints/constraints.go deleted file mode 100644 index 2c033dff..00000000 --- a/event-processor/vendor/golang.org/x/exp/constraints/constraints.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package constraints defines a set of useful constraints to be used -// with type parameters. -package constraints - -// Signed is a constraint that permits any signed integer type. -// If future releases of Go add new predeclared signed integer types, -// this constraint will be modified to include them. -type Signed interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 -} - -// Unsigned is a constraint that permits any unsigned integer type. -// If future releases of Go add new predeclared unsigned integer types, -// this constraint will be modified to include them. -type Unsigned interface { - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// Integer is a constraint that permits any integer type. -// If future releases of Go add new predeclared integer types, -// this constraint will be modified to include them. -type Integer interface { - Signed | Unsigned -} - -// Float is a constraint that permits any floating-point type. -// If future releases of Go add new predeclared floating-point types, -// this constraint will be modified to include them. -type Float interface { - ~float32 | ~float64 -} - -// Complex is a constraint that permits any complex numeric type. -// If future releases of Go add new predeclared complex numeric types, -// this constraint will be modified to include them. -type Complex interface { - ~complex64 | ~complex128 -} - -// Ordered is a constraint that permits any ordered type: any type -// that supports the operators < <= >= >. -// If future releases of Go add new ordered types, -// this constraint will be modified to include them. -type Ordered interface { - Integer | Float | ~string -} diff --git a/event-processor/vendor/golang.org/x/exp/slices/cmp.go b/event-processor/vendor/golang.org/x/exp/slices/cmp.go deleted file mode 100644 index fbf1934a..00000000 --- a/event-processor/vendor/golang.org/x/exp/slices/cmp.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// min is a version of the predeclared function from the Go 1.21 release. -func min[T constraints.Ordered](a, b T) T { - if a < b || isNaN(a) { - return a - } - return b -} - -// max is a version of the predeclared function from the Go 1.21 release. -func max[T constraints.Ordered](a, b T) T { - if a > b || isNaN(a) { - return a - } - return b -} - -// cmpLess is a copy of cmp.Less from the Go 1.21 release. -func cmpLess[T constraints.Ordered](x, y T) bool { - return (isNaN(x) && !isNaN(y)) || x < y -} - -// cmpCompare is a copy of cmp.Compare from the Go 1.21 release. -func cmpCompare[T constraints.Ordered](x, y T) int { - xNaN := isNaN(x) - yNaN := isNaN(y) - if xNaN && yNaN { - return 0 - } - if xNaN || x < y { - return -1 - } - if yNaN || x > y { - return +1 - } - return 0 -} diff --git a/event-processor/vendor/golang.org/x/exp/slices/slices.go b/event-processor/vendor/golang.org/x/exp/slices/slices.go deleted file mode 100644 index 46ceac34..00000000 --- a/event-processor/vendor/golang.org/x/exp/slices/slices.go +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package slices defines various functions useful with slices of any type. -package slices - -import ( - "unsafe" - - "golang.org/x/exp/constraints" -) - -// Equal reports whether two slices are equal: the same length and all -// elements equal. If the lengths are different, Equal returns false. -// Otherwise, the elements are compared in increasing index order, and the -// comparison stops at the first unequal pair. -// Floating point NaNs are not considered equal. -func Equal[S ~[]E, E comparable](s1, s2 S) bool { - if len(s1) != len(s2) { - return false - } - for i := range s1 { - if s1[i] != s2[i] { - return false - } - } - return true -} - -// EqualFunc reports whether two slices are equal using an equality -// function on each pair of elements. If the lengths are different, -// EqualFunc returns false. Otherwise, the elements are compared in -// increasing index order, and the comparison stops at the first index -// for which eq returns false. -func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool { - if len(s1) != len(s2) { - return false - } - for i, v1 := range s1 { - v2 := s2[i] - if !eq(v1, v2) { - return false - } - } - return true -} - -// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair -// of elements. The elements are compared sequentially, starting at index 0, -// until one element is not equal to the other. -// The result of comparing the first non-matching elements is returned. -// If both slices are equal until one of them ends, the shorter slice is -// considered less than the longer one. -// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. -func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmpCompare(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// CompareFunc is like [Compare] but uses a custom comparison function on each -// pair of elements. -// The result is the first non-zero result of cmp; if cmp always -// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), -// and +1 if len(s1) > len(s2). -func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmp(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// Index returns the index of the first occurrence of v in s, -// or -1 if not present. -func Index[S ~[]E, E comparable](s S, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 -} - -// IndexFunc returns the first index i satisfying f(s[i]), -// or -1 if none do. -func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { - for i := range s { - if f(s[i]) { - return i - } - } - return -1 -} - -// Contains reports whether v is present in s. -func Contains[S ~[]E, E comparable](s S, v E) bool { - return Index(s, v) >= 0 -} - -// ContainsFunc reports whether at least one -// element e of s satisfies f(e). -func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool { - return IndexFunc(s, f) >= 0 -} - -// Insert inserts the values v... into s at index i, -// returning the modified slice. -// The elements at s[i:] are shifted up to make room. -// In the returned slice r, r[i] == v[0], -// and r[i+len(v)] == value originally at r[i]. -// Insert panics if i is out of range. -// This function is O(len(s) + len(v)). -func Insert[S ~[]E, E any](s S, i int, v ...E) S { - m := len(v) - if m == 0 { - return s - } - n := len(s) - if i == n { - return append(s, v...) - } - if n+m > cap(s) { - // Use append rather than make so that we bump the size of - // the slice up to the next storage class. - // This is what Grow does but we don't call Grow because - // that might copy the values twice. - s2 := append(s[:i], make(S, n+m-i)...) - copy(s2[i:], v) - copy(s2[i+m:], s[i:]) - return s2 - } - s = s[:n+m] - - // before: - // s: aaaaaaaabbbbccccccccdddd - // ^ ^ ^ ^ - // i i+m n n+m - // after: - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // - // a are the values that don't move in s. - // v are the values copied in from v. - // b and c are the values from s that are shifted up in index. - // d are the values that get overwritten, never to be seen again. - - if !overlaps(v, s[i+m:]) { - // Easy case - v does not overlap either the c or d regions. - // (It might be in some of a or b, or elsewhere entirely.) - // The data we copy up doesn't write to v at all, so just do it. - - copy(s[i+m:], s[i:]) - - // Now we have - // s: aaaaaaaabbbbbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // Note the b values are duplicated. - - copy(s[i:], v) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s - } - - // The hard case - v overlaps c or d. We can't just shift up - // the data because we'd move or clobber the values we're trying - // to insert. - // So instead, write v on top of d, then rotate. - copy(s[n:], v) - - // Now we have - // s: aaaaaaaabbbbccccccccvvvv - // ^ ^ ^ ^ - // i i+m n n+m - - rotateRight(s[i:], m) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s -} - -// clearSlice sets all elements up to the length of s to the zero value of E. -// We may use the builtin clear func instead, and remove clearSlice, when upgrading -// to Go 1.21+. -func clearSlice[S ~[]E, E any](s S) { - var zero E - for i := range s { - s[i] = zero - } -} - -// Delete removes the elements s[i:j] from s, returning the modified slice. -// Delete panics if j > len(s) or s[i:j] is not a valid slice of s. -// Delete is O(len(s)-i), so if many items must be deleted, it is better to -// make a single call deleting them all together than to delete one at a time. -// Delete zeroes the elements s[len(s)-(j-i):len(s)]. -func Delete[S ~[]E, E any](s S, i, j int) S { - _ = s[i:j:len(s)] // bounds check - - if i == j { - return s - } - - oldlen := len(s) - s = append(s[:i], s[j:]...) - clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC - return s -} - -// DeleteFunc removes any elements from s for which del returns true, -// returning the modified slice. -// DeleteFunc zeroes the elements between the new length and the original length. -func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { - i := IndexFunc(s, del) - if i == -1 { - return s - } - // Don't start copying elements until we find one to delete. - for j := i + 1; j < len(s); j++ { - if v := s[j]; !del(v) { - s[i] = v - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Replace replaces the elements s[i:j] by the given v, and returns the -// modified slice. Replace panics if s[i:j] is not a valid slice of s. -// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length. -func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { - _ = s[i:j] // verify that i:j is a valid subslice - - if i == j { - return Insert(s, i, v...) - } - if j == len(s) { - return append(s[:i], v...) - } - - tot := len(s[:i]) + len(v) + len(s[j:]) - if tot > cap(s) { - // Too big to fit, allocate and copy over. - s2 := append(s[:i], make(S, tot-i)...) // See Insert - copy(s2[i:], v) - copy(s2[i+len(v):], s[j:]) - return s2 - } - - r := s[:tot] - - if i+len(v) <= j { - // Easy, as v fits in the deleted portion. - copy(r[i:], v) - if i+len(v) != j { - copy(r[i+len(v):], s[j:]) - } - clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC - return r - } - - // We are expanding (v is bigger than j-i). - // The situation is something like this: - // (example has i=4,j=8,len(s)=16,len(v)=6) - // s: aaaaxxxxbbbbbbbbyy - // ^ ^ ^ ^ - // i j len(s) tot - // a: prefix of s - // x: deleted range - // b: more of s - // y: area to expand into - - if !overlaps(r[i+len(v):], v) { - // Easy, as v is not clobbered by the first copy. - copy(r[i+len(v):], s[j:]) - copy(r[i:], v) - return r - } - - // This is a situation where we don't have a single place to which - // we can copy v. Parts of it need to go to two different places. - // We want to copy the prefix of v into y and the suffix into x, then - // rotate |y| spots to the right. - // - // v[2:] v[:2] - // | | - // s: aaaavvvvbbbbbbbbvv - // ^ ^ ^ ^ - // i j len(s) tot - // - // If either of those two destinations don't alias v, then we're good. - y := len(v) - (j - i) // length of y portion - - if !overlaps(r[i:j], v) { - copy(r[i:j], v[y:]) - copy(r[len(s):], v[:y]) - rotateRight(r[i:], y) - return r - } - if !overlaps(r[len(s):], v) { - copy(r[len(s):], v[:y]) - copy(r[i:j], v[y:]) - rotateRight(r[i:], y) - return r - } - - // Now we know that v overlaps both x and y. - // That means that the entirety of b is *inside* v. - // So we don't need to preserve b at all; instead we - // can copy v first, then copy the b part of v out of - // v to the right destination. - k := startIdx(v, s[j:]) - copy(r[i:], v) - copy(r[i+len(v):], r[i+k:]) - return r -} - -// Clone returns a copy of the slice. -// The elements are copied using assignment, so this is a shallow clone. -func Clone[S ~[]E, E any](s S) S { - // Preserve nil in case it matters. - if s == nil { - return nil - } - return append(S([]E{}), s...) -} - -// Compact replaces consecutive runs of equal elements with a single copy. -// This is like the uniq command found on Unix. -// Compact modifies the contents of the slice s and returns the modified slice, -// which may have a smaller length. -// Compact zeroes the elements between the new length and the original length. -func Compact[S ~[]E, E comparable](s S) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if s[k] != s[k-1] { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// CompactFunc is like [Compact] but uses an equality function to compare elements. -// For runs of elements that compare equal, CompactFunc keeps the first one. -// CompactFunc zeroes the elements between the new length and the original length. -func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if !eq(s[k], s[k-1]) { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Grow increases the slice's capacity, if necessary, to guarantee space for -// another n elements. After Grow(n), at least n elements can be appended -// to the slice without another allocation. If n is negative or too large to -// allocate the memory, Grow panics. -func Grow[S ~[]E, E any](s S, n int) S { - if n < 0 { - panic("cannot be negative") - } - if n -= cap(s) - len(s); n > 0 { - // TODO(https://go.dev/issue/53888): Make using []E instead of S - // to workaround a compiler bug where the runtime.growslice optimization - // does not take effect. Revert when the compiler is fixed. - s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)] - } - return s -} - -// Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. -func Clip[S ~[]E, E any](s S) S { - return s[:len(s):len(s)] -} - -// Rotation algorithm explanation: -// -// rotate left by 2 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join first parts -// 89234567 01 -// recursively rotate first left part by 2 -// 23456789 01 -// join at the end -// 2345678901 -// -// rotate left by 8 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join last parts -// 89 23456701 -// recursively rotate second part left by 6 -// 89 01234567 -// join at the end -// 8901234567 - -// TODO: There are other rotate algorithms. -// This algorithm has the desirable property that it moves each element exactly twice. -// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes. -// The follow-cycles algorithm can be 1-write but it is not very cache friendly. - -// rotateLeft rotates b left by n spaces. -// s_final[i] = s_orig[i+r], wrapping around. -func rotateLeft[E any](s []E, r int) { - for r != 0 && r != len(s) { - if r*2 <= len(s) { - swap(s[:r], s[len(s)-r:]) - s = s[:len(s)-r] - } else { - swap(s[:len(s)-r], s[r:]) - s, r = s[len(s)-r:], r*2-len(s) - } - } -} -func rotateRight[E any](s []E, r int) { - rotateLeft(s, len(s)-r) -} - -// swap swaps the contents of x and y. x and y must be equal length and disjoint. -func swap[E any](x, y []E) { - for i := 0; i < len(x); i++ { - x[i], y[i] = y[i], x[i] - } -} - -// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap. -func overlaps[E any](a, b []E) bool { - if len(a) == 0 || len(b) == 0 { - return false - } - elemSize := unsafe.Sizeof(a[0]) - if elemSize == 0 { - return false - } - // TODO: use a runtime/unsafe facility once one becomes available. See issue 12445. - // Also see crypto/internal/alias/alias.go:AnyOverlap - return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) && - uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1) -} - -// startIdx returns the index in haystack where the needle starts. -// prerequisite: the needle must be aliased entirely inside the haystack. -func startIdx[E any](haystack, needle []E) int { - p := &needle[0] - for i := range haystack { - if p == &haystack[i] { - return i - } - } - // TODO: what if the overlap is by a non-integral number of Es? - panic("needle not found") -} - -// Reverse reverses the elements of the slice in place. -func Reverse[S ~[]E, E any](s S) { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } -} diff --git a/event-processor/vendor/golang.org/x/exp/slices/sort.go b/event-processor/vendor/golang.org/x/exp/slices/sort.go deleted file mode 100644 index f58bbc7b..00000000 --- a/event-processor/vendor/golang.org/x/exp/slices/sort.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp - -package slices - -import ( - "math/bits" - - "golang.org/x/exp/constraints" -) - -// Sort sorts a slice of any ordered type in ascending order. -// When sorting floating-point numbers, NaNs are ordered before other values. -func Sort[S ~[]E, E constraints.Ordered](x S) { - n := len(x) - pdqsortOrdered(x, 0, n, bits.Len(uint(n))) -} - -// SortFunc sorts the slice x in ascending order as determined by the cmp -// function. This sort is not guaranteed to be stable. -// cmp(a, b) should return a negative number when a < b, a positive number when -// a > b and zero when a == b or when a is not comparable to b in the sense -// of the formal definition of Strict Weak Ordering. -// -// SortFunc requires that cmp is a strict weak ordering. -// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. -// To indicate 'uncomparable', return 0 from the function. -func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - n := len(x) - pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp) -} - -// SortStableFunc sorts the slice x while keeping the original order of equal -// elements, using cmp to compare elements in the same way as [SortFunc]. -func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - stableCmpFunc(x, len(x), cmp) -} - -// IsSorted reports whether x is sorted in ascending order. -func IsSorted[S ~[]E, E constraints.Ordered](x S) bool { - for i := len(x) - 1; i > 0; i-- { - if cmpLess(x[i], x[i-1]) { - return false - } - } - return true -} - -// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the -// comparison function as defined by [SortFunc]. -func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool { - for i := len(x) - 1; i > 0; i-- { - if cmp(x[i], x[i-1]) < 0 { - return false - } - } - return true -} - -// Min returns the minimal value in x. It panics if x is empty. -// For floating-point numbers, Min propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Min[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Min: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = min(m, x[i]) - } - return m -} - -// MinFunc returns the minimal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one minimal element -// according to the cmp function, MinFunc returns the first one. -func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MinFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) < 0 { - m = x[i] - } - } - return m -} - -// Max returns the maximal value in x. It panics if x is empty. -// For floating-point E, Max propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Max[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Max: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = max(m, x[i]) - } - return m -} - -// MaxFunc returns the maximal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one maximal element -// according to the cmp function, MaxFunc returns the first one. -func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MaxFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) > 0 { - m = x[i] - } - } - return m -} - -// BinarySearch searches for target in a sorted slice and returns the position -// where target is found, or the position where target would appear in the -// sort order; it also returns a bool saying whether the target is really found -// in the slice. The slice must be sorted in increasing order. -func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) { - // Inlining is faster than calling BinarySearchFunc with a lambda. - n := len(x) - // Define x[-1] < target and x[n] >= target. - // Invariant: x[i-1] < target, x[j] >= target. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmpLess(x[h], target) { - i = h + 1 // preserves x[i-1] < target - } else { - j = h // preserves x[j] >= target - } - } - // i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i. - return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target))) -} - -// BinarySearchFunc works like [BinarySearch], but uses a custom comparison -// function. The slice must be sorted in increasing order, where "increasing" -// is defined by cmp. cmp should return 0 if the slice element matches -// the target, a negative number if the slice element precedes the target, -// or a positive number if the slice element follows the target. -// cmp must implement the same ordering as the slice, such that if -// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice. -func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) { - n := len(x) - // Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 . - // Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmp(x[h], target) < 0 { - i = h + 1 // preserves cmp(x[i - 1], target) < 0 - } else { - j = h // preserves cmp(x[j], target) >= 0 - } - } - // i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i. - return i, i < n && cmp(x[i], target) == 0 -} - -type sortedHint int // hint for pdqsort when choosing the pivot - -const ( - unknownHint sortedHint = iota - increasingHint - decreasingHint -) - -// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf -type xorshift uint64 - -func (r *xorshift) Next() uint64 { - *r ^= *r << 13 - *r ^= *r >> 17 - *r ^= *r << 5 - return uint64(*r) -} - -func nextPowerOfTwo(length int) uint { - return 1 << bits.Len(uint(length)) -} - -// isNaN reports whether x is a NaN without requiring the math package. -// This will always return false if T is not floating-point. -func isNaN[T constraints.Ordered](x T) bool { - return x != x -} diff --git a/event-processor/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/event-processor/vendor/golang.org/x/exp/slices/zsortanyfunc.go deleted file mode 100644 index 06f2c7a2..00000000 --- a/event-processor/vendor/golang.org/x/exp/slices/zsortanyfunc.go +++ /dev/null @@ -1,479 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -// insertionSortCmpFunc sorts data[a:b] using insertion sort. -func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownCmpFunc implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) { - child++ - } - if !(cmp(data[first+root], data[first+child]) < 0) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownCmpFunc(data, i, hi, first, cmp) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownCmpFunc(data, lo, i, first, cmp) - } -} - -// pdqsortCmpFunc sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortCmpFunc(data, a, b, cmp) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortCmpFunc(data, a, b, cmp) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsCmpFunc(data, a, b, cmp) - limit-- - } - - pivot, hint := choosePivotCmpFunc(data, a, b, cmp) - if hint == decreasingHint { - reverseRangeCmpFunc(data, a, b, cmp) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortCmpFunc(data, a, b, cmp) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) { - mid := partitionEqualCmpFunc(data, a, b, pivot, cmp) - a = mid - continue - } - - mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortCmpFunc(data, a, mid, limit, cmp) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortCmpFunc(data, mid+1, b, limit, cmp) - b = mid - } - } -} - -// partitionCmpFunc does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/event-processor/vendor/golang.org/x/exp/slices/zsortordered.go b/event-processor/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c39..00000000 --- a/event-processor/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/attr.go b/event-processor/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/doc.go b/event-processor/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf867..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/event-processor/vendor/golang.org/x/exp/slog/handler.go b/event-processor/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb8..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/event-processor/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/event-processor/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/event-processor/vendor/golang.org/x/exp/slog/json_handler.go b/event-processor/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada86..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/level.go b/event-processor/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0a..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/logger.go b/event-processor/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec993..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/noplog.bench b/event-processor/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/event-processor/vendor/golang.org/x/exp/slog/record.go b/event-processor/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/text_handler.go b/event-processor/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b71..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/value.go b/event-processor/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46f..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/value_119.go b/event-processor/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d732..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/event-processor/vendor/golang.org/x/exp/slog/value_120.go b/event-processor/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c093..00000000 --- a/event-processor/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/event-processor/vendor/golang.org/x/net/http2/frame.go b/event-processor/vendor/golang.org/x/net/http2/frame.go index 97bd8b06..db3264da 100644 --- a/event-processor/vendor/golang.org/x/net/http2/frame.go +++ b/event-processor/vendor/golang.org/x/net/http2/frame.go @@ -39,7 +39,7 @@ const ( FrameContinuation FrameType = 0x9 ) -var frameName = map[FrameType]string{ +var frameNames = [...]string{ FrameData: "DATA", FrameHeaders: "HEADERS", FramePriority: "PRIORITY", @@ -53,10 +53,10 @@ var frameName = map[FrameType]string{ } func (t FrameType) String() string { - if s, ok := frameName[t]; ok { - return s + if int(t) < len(frameNames) { + return frameNames[t] } - return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) + return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t) } // Flags is a bitmask of HTTP/2 flags. @@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{ // might be 0). type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) -var frameParsers = map[FrameType]frameParser{ +var frameParsers = [...]frameParser{ FrameData: parseDataFrame, FrameHeaders: parseHeadersFrame, FramePriority: parsePriorityFrame, @@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{ } func typeFrameParser(t FrameType) frameParser { - if f := frameParsers[t]; f != nil { - return f + if int(t) < len(frameParsers) { + return frameParsers[t] } return parseUnknownFrame } @@ -509,7 +509,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { } if fh.Length > fr.maxReadSize { if fh == invalidHTTP1LookingFrameHeader() { - return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge) } return nil, ErrFrameTooLarge } diff --git a/event-processor/vendor/golang.org/x/net/http2/http2.go b/event-processor/vendor/golang.org/x/net/http2/http2.go index 6c18ea23..ea5ae629 100644 --- a/event-processor/vendor/golang.org/x/net/http2/http2.go +++ b/event-processor/vendor/golang.org/x/net/http2/http2.go @@ -11,8 +11,6 @@ // requires Go 1.6 or later) // // See https://http2.github.io/ for more information on HTTP/2. -// -// See https://http2.golang.org/ for a test server running this code. package http2 // import "golang.org/x/net/http2" import ( diff --git a/event-processor/vendor/golang.org/x/net/trace/events.go b/event-processor/vendor/golang.org/x/net/trace/events.go index c646a695..3aaffdd1 100644 --- a/event-processor/vendor/golang.org/x/net/trace/events.go +++ b/event-processor/vendor/golang.org/x/net/trace/events.go @@ -508,7 +508,7 @@ const eventsHTML = ` {{$el.When}} {{$el.ElapsedTime}} - {{$el.Title}} + {{$el.Title}} {{if $.Expanded}} diff --git a/event-processor/vendor/golang.org/x/sync/errgroup/errgroup.go b/event-processor/vendor/golang.org/x/sync/errgroup/errgroup.go index cb6bb9ad..1d8cffae 100644 --- a/event-processor/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/event-processor/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -12,8 +12,6 @@ package errgroup import ( "context" "fmt" - "runtime" - "runtime/debug" "sync" ) @@ -33,10 +31,6 @@ type Group struct { errOnce sync.Once err error - - mu sync.Mutex - panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked. - abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit). } func (g *Group) done() { @@ -56,22 +50,13 @@ func WithContext(ctx context.Context) (*Group, context.Context) { return &Group{cancel: cancel}, ctx } -// Wait blocks until all function calls from the Go method have returned -// normally, then returns the first non-nil error (if any) from them. -// -// If any of the calls panics, Wait panics with a [PanicValue]; -// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit. +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. func (g *Group) Wait() error { g.wg.Wait() if g.cancel != nil { g.cancel(g.err) } - if g.panicValue != nil { - panic(g.panicValue) - } - if g.abnormal { - runtime.Goexit() - } return g.err } @@ -81,53 +66,31 @@ func (g *Group) Wait() error { // It blocks until the new goroutine can be added without the number of // goroutines in the group exceeding the configured limit. // -// The first goroutine in the group that returns a non-nil error, panics, or -// invokes [runtime.Goexit] will cancel the associated Context, if any. +// The first goroutine in the group that returns a non-nil error will +// cancel the associated Context, if any. The error will be returned +// by Wait. func (g *Group) Go(f func() error) { if g.sem != nil { g.sem <- token{} } - g.add(f) -} - -func (g *Group) add(f func() error) { g.wg.Add(1) go func() { defer g.done() - normalReturn := false - defer func() { - if normalReturn { - return - } - v := recover() - g.mu.Lock() - defer g.mu.Unlock() - if !g.abnormal { - if g.cancel != nil { - g.cancel(g.err) - } - g.abnormal = true - } - if v != nil && g.panicValue == nil { - switch v := v.(type) { - case error: - g.panicValue = PanicError{ - Recovered: v, - Stack: debug.Stack(), - } - default: - g.panicValue = PanicValue{ - Recovered: v, - Stack: debug.Stack(), - } - } - } - }() - err := f() - normalReturn = true - if err != nil { + // It is tempting to propagate panics from f() + // up to the goroutine that calls Wait, but + // it creates more problems than it solves: + // - it delays panics arbitrarily, + // making bugs harder to detect; + // - it turns f's panic stack into a mere value, + // hiding it from crash-monitoring tools; + // - it risks deadlocks that hide the panic entirely, + // if f's panic leaves the program in a state + // that prevents the Wait call from being reached. + // See #53757, #74275, #74304, #74306. + + if err := f(); err != nil { g.errOnce.Do(func() { g.err = err if g.cancel != nil { @@ -152,7 +115,19 @@ func (g *Group) TryGo(f func() error) bool { } } - g.add(f) + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() return true } @@ -174,34 +149,3 @@ func (g *Group) SetLimit(n int) { } g.sem = make(chan token, n) } - -// PanicError wraps an error recovered from an unhandled panic -// when calling a function passed to Go or TryGo. -type PanicError struct { - Recovered error - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicError) Error() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} - -func (p PanicError) Unwrap() error { return p.Recovered } - -// PanicValue wraps a value that does not implement the error interface, -// recovered from an unhandled panic when calling a function passed to Go or -// TryGo. -type PanicValue struct { - Recovered any - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicValue) String() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} diff --git a/event-processor/vendor/golang.org/x/sys/unix/mkerrors.sh b/event-processor/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c..d1c8b264 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/event-processor/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/event-processor/vendor/golang.org/x/sys/unix/syscall_darwin.go b/event-processor/vendor/golang.org/x/sys/unix/syscall_darwin.go index 798f61ad..7838ca5d 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/event-processor/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,14 +602,9 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) const minIovec = 8 func Readv(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = readv(fd, iovecs) @@ -618,9 +613,6 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { } func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = preadv(fd, iovecs, offset) @@ -629,10 +621,6 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -644,10 +632,6 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -707,45 +691,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } } -func darwinMajorMinPatch() (maj, min, patch int, err error) { - var un Utsname - err = Uname(&un) - if err != nil { - return - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range un.Release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return 0, 0, 0, ENOTSUP - } - case b == 0: - break Loop - default: - return 0, 0, 0, ENOTSUP - } - } - if c != 2 { - return 0, 0, 0, ENOTSUP - } - return mmp[0], mmp[1], mmp[2], nil -} - -func darwinKernelVersionMin(maj, min, patch int) bool { - actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() - if err != nil { - return false - } - return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) -} - +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux.go index 4f432bfe..b6db27d9 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -319,6 +319,7 @@ const ( AUDIT_INTEGRITY_POLICY_RULE = 0x70f AUDIT_INTEGRITY_RULE = 0x70d AUDIT_INTEGRITY_STATUS = 0x70a + AUDIT_INTEGRITY_USERSPACE = 0x710 AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f AUDIT_IPE_ACCESS = 0x58c @@ -327,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -491,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -527,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -554,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -843,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2023-03-01)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x30 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -936,11 +942,10 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 + ETHTOOL_FAMILY_NAME = "ethtool" + ETHTOOL_FAMILY_VERSION = 0x1 ETHTOOL_FEC_AUTO = 0x2 ETHTOOL_FEC_BASER = 0x10 ETHTOOL_FEC_LLRS = 0x20 @@ -1203,13 +1208,18 @@ const ( FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 FAN_EPIDFD = -0x2 + FAN_ERRNO_BITS = 0x8 + FAN_ERRNO_MASK = 0xff + FAN_ERRNO_SHIFT = 0x18 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 + FAN_EVENT_INFO_TYPE_RANGE = 0x6 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_FS_ERROR = 0x8000 @@ -1224,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1240,6 +1253,7 @@ const ( FAN_OPEN_EXEC = 0x1000 FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 + FAN_PRE_ACCESS = 0x100000 FAN_Q_OVERFLOW = 0x4000 FAN_RENAME = 0x10000000 FAN_REPORT_DFID_NAME = 0xc00 @@ -1247,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1266,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1574,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1625,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1687,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1809,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2485,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2644,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2724,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2787,7 +2813,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1e + RTA_MAX = 0x1f RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -2864,10 +2890,12 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELANYCAST = 0x3d RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELLINKPROP = 0x6d RTM_DELMDB = 0x55 + RTM_DELMULTICAST = 0x39 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 @@ -2917,11 +2945,13 @@ const ( RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 + RTM_NEWANYCAST = 0x3c RTM_NEWCACHEREPORT = 0x60 RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWLINKPROP = 0x6c RTM_NEWMDB = 0x54 + RTM_NEWMULTICAST = 0x38 RTM_NEWNDUSEROPT = 0x44 RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 @@ -2970,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -2987,11 +3018,12 @@ const ( RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 RWF_ATOMIC = 0x40 + RWF_DONTCACHE = 0x80 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x7f + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3271,6 +3303,7 @@ const ( STATX_BTIME = 0x800 STATX_CTIME = 0x80 STATX_DIOALIGN = 0x2000 + STATX_DIO_READ_ALIGN = 0x20000 STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 @@ -3322,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xe + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3392,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3503,6 +3534,7 @@ const ( TP_STATUS_WRONG_FORMAT = 0x4 TRACEFS_MAGIC = 0x74726163 TS_COMM_LEN = 0x20 + UBI_IOCECNFO = 0xc01c6f06 UDF_SUPER_MAGIC = 0x15013346 UDP_CORK = 0x1 UDP_ENCAP = 0x64 @@ -3515,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3559,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3673,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 75207613..1c37f9fb 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -372,6 +374,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c68acda5..6f54d34a 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -373,6 +375,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index a8c607ab..783ec5c1 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -378,6 +380,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 18563dd8..ca83d3ba 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 22912cda..607e611c 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -365,6 +367,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 29344eb3..b9cb5bd3 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 20d51fb9..65b078a6 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 321b6090..5298a303 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 9bacdf1e..7bc557c8 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c2242726..152399bb 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -426,6 +428,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 6270c8ee..1a1ce240 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 9966c194..4231a1fb 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 848e5fcc..21c0e952 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -362,6 +364,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 669b2adb..f00d1cd7 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -434,6 +436,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 4834e575..bc8d539e 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 @@ -473,6 +475,7 @@ const ( SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff3..aca56ee4 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb45069..2ea1ef58 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e50297..d22c8af3 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec5..5ee264ae 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a..f9f03ebf 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a33..87c2118e 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b99622..391ad102 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9..56561577 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc..0482b52e 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfb..71806f08 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b4463650..e35a7105 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c1..2aea4767 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 84053916..6c9bb4e5 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790..680bc991 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f..620f2710 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux.go index a46abe64..cd236443 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,10 @@ type Statx_t struct { Atomic_write_unit_min uint32 Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 _ [1]uint32 - _ [9]uint64 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2226,8 +2229,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -2314,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2594,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -3802,7 +3813,16 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2d + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3842,7 +3862,17 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -3949,7 +3979,12 @@ const ( ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb ETHTOOL_A_RINGS_CQE_SIZE = 0xc ETHTOOL_A_RINGS_TX_PUSH = 0xd - ETHTOOL_A_RINGS_MAX = 0x10 + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 ETHTOOL_A_CHANNELS_UNSPEC = 0x0 ETHTOOL_A_CHANNELS_HEADER = 0x1 ETHTOOL_A_CHANNELS_RX_MAX = 0x2 @@ -4015,7 +4050,9 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x6 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4101,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4613,6 +4663,7 @@ const ( NL80211_ATTR_AKM_SUITES = 0x4c NL80211_ATTR_AP_ISOLATE = 0x60 NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a NL80211_ATTR_AUTH_DATA = 0x9c NL80211_ATTR_AUTH_TYPE = 0x35 NL80211_ATTR_BANDS = 0xef @@ -4623,6 +4674,7 @@ const ( NL80211_ATTR_BSS_BASIC_RATES = 0x24 NL80211_ATTR_BSS = 0x2f NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 NL80211_ATTR_BSS_HT_OPMODE = 0x6d NL80211_ATTR_BSSID = 0xf5 NL80211_ATTR_BSS_SELECT = 0xe3 @@ -4682,6 +4734,7 @@ const ( NL80211_ATTR_DTIM_PERIOD = 0xd NL80211_ATTR_DURATION = 0x57 NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 NL80211_ATTR_EML_CAPABILITY = 0x13d NL80211_ATTR_EXT_CAPA = 0xa9 NL80211_ATTR_EXT_CAPA_MASK = 0xaa @@ -4717,6 +4770,7 @@ const ( NL80211_ATTR_HIDDEN_SSID = 0x7e NL80211_ATTR_HT_CAPABILITY = 0x1f NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 NL80211_ATTR_IE_ASSOC_RESP = 0x80 NL80211_ATTR_IE = 0x2a NL80211_ATTR_IE_PROBE_RESP = 0x7f @@ -4747,9 +4801,10 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14d + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 NL80211_ATTR_MAX_MATCH_SETS = 0x85 NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 @@ -4774,9 +4829,12 @@ const ( NL80211_ATTR_MGMT_SUBTYPE = 0x29 NL80211_ATTR_MLD_ADDR = 0x13a NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 NL80211_ATTR_MLO_LINK_ID = 0x139 NL80211_ATTR_MLO_LINKS = 0x138 NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 NL80211_ATTR_MNTR_FLAGS = 0x17 NL80211_ATTR_MPATH_INFO = 0x1b NL80211_ATTR_MPATH_NEXT_HOP = 0x1a @@ -4809,12 +4867,14 @@ const ( NL80211_ATTR_PORT_AUTHORIZED = 0x103 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 NL80211_ATTR_PREV_BSSID = 0x4f NL80211_ATTR_PRIVACY = 0x46 NL80211_ATTR_PROBE_RESP = 0x91 NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 NL80211_ATTR_PROTOCOL_FEATURES = 0xad NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 NL80211_ATTR_QOS_MAP = 0xc7 NL80211_ATTR_RADAR_BACKGROUND = 0x134 NL80211_ATTR_RADAR_EVENT = 0xa8 @@ -4943,7 +5003,9 @@ const ( NL80211_ATTR_WIPHY_FREQ = 0x26 NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 @@ -4978,6 +5040,8 @@ const ( NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 NL80211_BAND_ATTR_MAX = 0xd NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc NL80211_BAND_ATTR_VHT_CAPA = 0x8 NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 @@ -5001,6 +5065,10 @@ const ( NL80211_BSS_BEACON_INTERVAL = 0x4 NL80211_BSS_BEACON_TSF = 0xd NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 NL80211_BSS_CAPABILITY = 0x5 NL80211_BSS_CHAIN_SIGNAL = 0x13 NL80211_BSS_CHAN_WIDTH_10 = 0x1 @@ -5032,6 +5100,9 @@ const ( NL80211_BSS_STATUS = 0x9 NL80211_BSS_STATUS_IBSS_JOINED = 0x2 NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 NL80211_CHAN_HT20 = 0x1 NL80211_CHAN_HT40MINUS = 0x2 NL80211_CHAN_HT40PLUS = 0x3 @@ -5117,7 +5188,8 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9b + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5161,6 +5233,7 @@ const ( NL80211_CMD_SET_COALESCE = 0x65 NL80211_CMD_SET_CQM = 0x3f NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 NL80211_CMD_SET_INTERFACE = 0x6 NL80211_CMD_SET_KEY = 0xa NL80211_CMD_SET_MAC_ACL = 0x5d @@ -5180,6 +5253,7 @@ const ( NL80211_CMD_SET_SAR_SPECS = 0x8c NL80211_CMD_SET_STATION = 0x12 NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 NL80211_CMD_SET_WDS_PEER = 0x42 NL80211_CMD_SET_WIPHY = 0x2 @@ -5247,6 +5321,7 @@ const ( NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 @@ -5262,6 +5337,7 @@ const ( NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 @@ -5281,9 +5357,12 @@ const ( NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c NL80211_EXT_FEATURE_RRM = 0x1 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 @@ -5295,8 +5374,10 @@ const ( NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f NL80211_EXT_FEATURE_SECURE_RTT = 0x38 NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 NL80211_EXT_FEATURE_TXQS = 0x1c NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 @@ -5343,7 +5424,10 @@ const ( NL80211_FREQUENCY_ATTR_2MHZ = 0x16 NL80211_FREQUENCY_ATTR_4MHZ = 0x17 NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 NL80211_FREQUENCY_ATTR_DISABLED = 0x2 @@ -5351,12 +5435,14 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b NL80211_FREQUENCY_ATTR_NO_HE = 0x13 @@ -5364,8 +5450,11 @@ const ( NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_OFFSET = 0x14 NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c NL80211_FREQUENCY_ATTR_RADAR = 0x5 NL80211_FREQUENCY_ATTR_WMM = 0x12 NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 @@ -5430,6 +5519,7 @@ const ( NL80211_IFTYPE_STATION = 0x2 NL80211_IFTYPE_UNSPECIFIED = 0x0 NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 NL80211_KCK_EXT_LEN = 0x18 NL80211_KCK_LEN = 0x10 NL80211_KEK_EXT_LEN = 0x20 @@ -5458,9 +5548,10 @@ const ( NL80211_MAX_SUPP_HT_RATES = 0x4d NL80211_MAX_SUPP_RATES = 0x20 NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 @@ -5703,11 +5794,16 @@ const ( NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c NL80211_RATE_INFO_BITRATE32 = 0x5 NL80211_RATE_INFO_BITRATE = 0x1 NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 @@ -5753,6 +5849,8 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 NL80211_RATE_INFO_SHORT_GI = 0x4 NL80211_RATE_INFO_VHT_MCS = 0x6 NL80211_RATE_INFO_VHT_NSS = 0x7 @@ -5770,14 +5868,19 @@ const ( NL80211_REKEY_DATA_KEK = 0x1 NL80211_REKEY_DATA_REPLAY_CTR = 0x3 NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 NL80211_RRF_AUTO_BW = 0x800 NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 NL80211_RRF_GO_CONCURRENT = 0x1000 NL80211_RRF_IR_CONCURRENT = 0x1000 NL80211_RRF_NO_160MHZ = 0x10000 NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 NL80211_RRF_NO_80MHZ = 0x8000 NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 NL80211_RRF_NO_HE = 0x20000 NL80211_RRF_NO_HT40 = 0x6000 NL80211_RRF_NO_HT40MINUS = 0x2000 @@ -5788,7 +5891,10 @@ const ( NL80211_RRF_NO_IR = 0x80 NL80211_RRF_NO_OFDM = 0x1 NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 NL80211_RRF_PTMP_ONLY = 0x40 NL80211_RRF_PTP_ONLY = 0x20 NL80211_RXMGMT_FLAG_ANSWERED = 0x1 @@ -5849,6 +5955,7 @@ const ( NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 NL80211_STA_FLAG_TDLS_PEER = 0x6 NL80211_STA_FLAG_WME = 0x3 NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 @@ -6007,6 +6114,13 @@ const ( NL80211_VHT_CAPABILITY_LEN = 0xc NL80211_VHT_NSS_MAX = 0x8 NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 NL80211_WMMR_AIFSN = 0x3 NL80211_WMMR_CW_MAX = 0x2 NL80211_WMMR_CW_MIN = 0x1 @@ -6038,6 +6152,7 @@ const ( NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fd402da4..485f2d3a 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -338,6 +338,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index eb7a5e18..ecbd1ad8 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -351,6 +351,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index d78ac108..02f0463a 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -329,6 +329,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index cd06d47f..6f4d400d 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -330,6 +330,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2f28fe26..cd532cfa 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -331,6 +331,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 71d6cac2..41336208 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8596d453..eaa37eb7 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index cd60ea18..98ae6a1e 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b0ae420c..cae19615 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 83597287..6ce3b4e0 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,7 +285,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -341,6 +341,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 69eb6a5c..c7429c6a 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5f583cb6..4bf4baf4 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index ad05b51a..e9709d70 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -358,6 +358,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cf3ce900..fb44268c 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -353,6 +353,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 590b5673..9c38265c 100644 --- a/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/event-processor/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -335,6 +335,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/event-processor/vendor/golang.org/x/telemetry/.dockerignore b/event-processor/vendor/golang.org/x/telemetry/.dockerignore new file mode 100644 index 00000000..416ae44a --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.dockerignore @@ -0,0 +1,17 @@ +.git +.localstorage +node_modules +devtools +.eslint* +.gitignore +.prettier* +.stylelint* +CONTRIBUTING.md +LICENSE +npm +npx +package-lock.json +package.json +PATENTS +README.md +tsconfig.json \ No newline at end of file diff --git a/event-processor/vendor/golang.org/x/telemetry/.eslintrc.json b/event-processor/vendor/golang.org/x/telemetry/.eslintrc.json new file mode 100644 index 00000000..ba5e242b --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "root": true, + "ignorePatterns": ["*.min.js"] +} diff --git a/event-processor/vendor/golang.org/x/telemetry/.gitattributes b/event-processor/vendor/golang.org/x/telemetry/.gitattributes new file mode 100644 index 00000000..f529a114 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.gitattributes @@ -0,0 +1,14 @@ +# Treat all files in the repo as binary, with no git magic updating +# line endings. This produces predictable results in different environments. +# +# Windows users contributing to Go will need to use a modern version +# of git and editors capable of LF line endings. +# +# Windows .bat files are known to have multiple bugs when run with LF +# endings. So if they are checked in with CRLF endings, there should +# be a test like the one in test/winbatch.go in the go repository. +# (See golang.org/issue/37791.) +# +# See golang.org/issue/9281. + +* -text diff --git a/event-processor/vendor/golang.org/x/telemetry/.gitignore b/event-processor/vendor/golang.org/x/telemetry/.gitignore new file mode 100644 index 00000000..46770c48 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.gitignore @@ -0,0 +1,2 @@ +node_modules +.localstorage \ No newline at end of file diff --git a/event-processor/vendor/golang.org/x/telemetry/.prettierrc.json b/event-processor/vendor/golang.org/x/telemetry/.prettierrc.json new file mode 100644 index 00000000..91c0b944 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.prettierrc.json @@ -0,0 +1 @@ +{"proseWrap": "always"} diff --git a/event-processor/vendor/golang.org/x/telemetry/.stylelintrc.json b/event-processor/vendor/golang.org/x/telemetry/.stylelintrc.json new file mode 100644 index 00000000..adccf47b --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/.stylelintrc.json @@ -0,0 +1,11 @@ +{ + "extends": ["stylelint-config-standard"], + "rules": { + "declaration-property-value-allowed-list": { + "/color/": ["/^var\\(--/", "transparent"] + }, + "unit-disallowed-list": ["px"], + "selector-class-pattern": "^[a-zA-Z\\-]+$" + }, + "ignoreFiles": ["**/*.min.css"] +} diff --git a/event-processor/vendor/golang.org/x/telemetry/CONTRIBUTING.md b/event-processor/vendor/golang.org/x/telemetry/CONTRIBUTING.md new file mode 100644 index 00000000..e913373f --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these +five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the +[golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead +of the issue tracker. The gophers there will answer or ask you to file an issue +if you've tripped over a bug. + +## Contributing code + +Please read the +[Contribution Guidelines](https://golang.org/doc/contribute.html) before sending +patches. + +Unless otherwise noted, the Go source files are distributed under the BSD-style +license found in the LICENSE file. diff --git a/event-processor/vendor/golang.org/x/exp/LICENSE b/event-processor/vendor/golang.org/x/telemetry/LICENSE similarity index 100% rename from event-processor/vendor/golang.org/x/exp/LICENSE rename to event-processor/vendor/golang.org/x/telemetry/LICENSE diff --git a/event-processor/vendor/golang.org/x/exp/PATENTS b/event-processor/vendor/golang.org/x/telemetry/PATENTS similarity index 100% rename from event-processor/vendor/golang.org/x/exp/PATENTS rename to event-processor/vendor/golang.org/x/telemetry/PATENTS diff --git a/event-processor/vendor/golang.org/x/telemetry/README.md b/event-processor/vendor/golang.org/x/telemetry/README.md new file mode 100644 index 00000000..81a15749 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/README.md @@ -0,0 +1,62 @@ +# Go Telemetry + +This repository holds the Go Telemetry server code and libraries, used for +hosting [telemetry.go.dev](https://telemetry.go.dev) and instrumenting Go +toolchain programs with opt-in telemetry. + +**Warning**: this repository is intended for use only in tools maintained by +the Go team, including tools in the Go distribution and auxiliary tools like +[gopls](https://pkg.go.dev/golang.org/x/tools/gopls) or +[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck). There are +no compatibility guarantees for any of the packages here: public APIs will +change in breaking ways as the telemetry integration is refined. + +## Notable Packages + +- The [x/telemetry/counter](https://pkg.go.dev/golang.org/x/telemetry/counter) + package provides a library for instrumenting programs with counters and stack + reports. +- The [x/telemetry/upload](https://pkg.go.dev/golang.org/x/telemetry/upload) + package provides a hook for Go toolchain programs to upload telemetry data, + if the user has opted in to telemetry uploading. +- The [x/telemetry/cmd/gotelemetry](https://pkg.go.dev/pkg/golang.org/x/telemetry/cmd/gotelemetry) + command is used for managing telemetry data and configuration. +- The [x/telemetry/config](https://pkg.go.dev/pkg/golang.org/x/telemetry/config) + package defines the subset of telemetry data that has been approved for + uploading by the telemetry proposal process. +- The [x/telemetry/godev](https://pkg.go.dev/pkg/golang.org/x/telemetry/godev) directory defines + the services running at [telemetry.go.dev](https://telemetry.go.dev). + +## Contributing + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/telemetry. + +The main issue tracker for the telemetry repository is located at +https://go.dev/issues. Prefix your issue with "x/telemetry:" in +the subject line, so it is easy to find. + +### Linting & Formatting + +This repository uses [eslint](https://eslint.org/) to format TS files, +[stylelint](https://stylelint.io/) to format CSS files, and +[prettier](https://prettier.io/) to format TS, CSS, Markdown, and YAML files. + +See the style guides: + +- [TypeScript](https://google.github.io/styleguide/tsguide.html) +- [CSS](https://go.dev/wiki/CSSStyleGuide) + +It is encouraged that all TS and CSS code be run through formatters before +submitting a change. However, it is not a strict requirement enforced by CI. + +### Installing npm Dependencies: + +1. Install [docker](https://docs.docker.com/get-docker/) +2. Run `./npm install` + +### Run ESLint, Stylelint, & Prettier + + ./npm run all diff --git a/event-processor/vendor/golang.org/x/telemetry/counter/counter.go b/event-processor/vendor/golang.org/x/telemetry/counter/counter.go new file mode 100644 index 00000000..fe2d0f69 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/counter/counter.go @@ -0,0 +1,146 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +// The implementation of this package and tests are located in +// internal/counter, which can be shared with the upload package. +// TODO(hyangah): use of type aliases prevents nice documentation +// rendering in go doc or pkgsite. Fix this either by avoiding +// type aliasing or restructuring the internal/counter package. +import ( + "flag" + "path" + "runtime/debug" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// Inc increments the counter with the given name. +func Inc(name string) { + New(name).Inc() +} + +// Add adds n to the counter with the given name. +func Add(name string, n int64) { + New(name).Add(n) +} + +// New returns a counter with the given name. +// New can be called in global initializers and will be compiled down to +// linker-initialized data. That is, calling New to initialize a global +// has no cost at program startup. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func New(name string) *Counter { + // Note: not calling DefaultFile.New in order to keep this + // function something the compiler can inline and convert + // into static data initializations, with no init-time footprint. + // TODO(hyangah): is it trivial enough for the compiler to inline? + return counter.New(name) +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter = counter.Counter + +// A StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter = counter.StackCounter + +// NewStack returns a new stack counter with the given name and depth. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func NewStack(name string, depth int) *StackCounter { + return counter.NewStack(name, depth) +} + +// Open prepares telemetry counters for recording to the file system. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Open should only be called from short-lived processes such as command line +// tools. If your process is long-running, use [OpenAndRotate]. +func Open() { + counter.Open(false) +} + +// OpenAndRotate is like [Open], but also schedules a rotation of the counter +// file when it expires. +// +// See golang/go#68497 for background on why [OpenAndRotate] is a separate API. +// +// TODO(rfindley): refactor Open and OpenAndRotate for Go 1.24. +func OpenAndRotate() { + counter.Open(true) +} + +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open(false) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +// +// For instance, CountFlags("gopls/flag:", *flag.CommandLine) +func CountFlags(prefix string, fs flag.FlagSet) { + fs.Visit(func(f *flag.Flag) { + New(prefix + f.Name).Inc() + }) +} + +// CountCommandLineFlags creates a counter for every flag +// that is set in the default flag.CommandLine FlagSet using +// the counter name binaryName+"/flag:"+flagName where +// binaryName is the base name of the Path embedded in the +// binary's build info. If the binary does not have embedded build +// info, the "flag:"+flagName counter will be incremented. +// +// CountCommandLineFlags must be called after flags are parsed +// with flag.Parse. +// +// For instance, if the -S flag is passed to cmd/compile and +// CountCommandLineFlags is called after flags are parsed, +// the "compile/flag:S" counter will be incremented. +func CountCommandLineFlags() { + prefix := "flag:" + if buildInfo, ok := debug.ReadBuildInfo(); ok && buildInfo.Path != "" { + prefix = path.Base(buildInfo.Path) + "/" + prefix + } + CountFlags(prefix, *flag.CommandLine) +} diff --git a/event-processor/vendor/golang.org/x/telemetry/counter/doc.go b/event-processor/vendor/golang.org/x/telemetry/counter/doc.go new file mode 100644 index 00000000..639e9ea3 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/counter/doc.go @@ -0,0 +1,58 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package counter implements a simple counter system for collecting +// totally public telemetry data. +// +// There are two kinds of counters, basic counters and stack counters. +// Basic counters are created by [New]. +// Stack counters are created by [NewStack]. +// Both are incremented by calling Inc(). +// +// Basic counters are very cheap. Stack counters are more expensive, as they +// require parsing the stack. (Stack counters are implemented as basic counters +// whose names are the concatenation of the name and the stack trace. There is +// an upper limit on the size of this name, about 4K bytes. If the name is too +// long the stack will be truncated and "truncated" appended.) +// +// When counter files expire they are turned into reports by the upload +// package. The first time any counter file is created for a user, a random day +// of the week is selected on which counter files will expire. For the first +// week, that day is more than 7 days (but not more than two weeks) in the +// future. After that the counter files expire weekly on the same day of the +// week. +// +// # Counter Naming +// +// Counter names passed to [New] and [NewStack] should follow these +// conventions: +// +// - Names cannot contain whitespace or newlines. +// +// - Names must be valid unicode, with no unprintable characters. +// +// - Names may contain at most one ':'. In the counter "foo:bar", we refer to +// "foo" as the "chart name" and "bar" as the "bucket name". +// +// - The '/' character should partition counter names into a hierarchy. The +// root of this hierarchy should identify the logical entity that "owns" +// the counter. This could be an application, such as "gopls" in the case +// of "gopls/client:vscode", or a shared library, such as "crash" in the +// case of the "crash/crash" counter owned by the crashmonitor library. If +// the entity name itself contains a '/', that's ok: "cmd/go/flag" is fine. +// +// - Words should be '-' separated, as in "gopls/completion/errors-latency" +// +// - Histograms should use bucket names identifying upper bounds with '<'. +// For example given two counters "gopls/completion/latency:<50ms" and +// "gopls/completion/latency:<100ms", the "<100ms" bucket counts events +// with latency in the half-open interval [50ms, 100ms). +// +// # Debugging +// +// The GODEBUG environment variable can enable printing of additional debug +// information for counters. Adding GODEBUG=countertrace=1 to the environment +// of a process using counters causes the x/telemetry/counter package to log +// counter information to stderr. +package counter diff --git a/event-processor/vendor/golang.org/x/telemetry/dir.go b/event-processor/vendor/golang.org/x/telemetry/dir.go new file mode 100644 index 00000000..5931669e --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/dir.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Dir returns the telemetry directory. +func Dir() string { + return telemetry.Default.Dir() +} diff --git a/event-processor/vendor/golang.org/x/telemetry/doc.go b/event-processor/vendor/golang.org/x/telemetry/doc.go new file mode 100644 index 00000000..073f40d2 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/doc.go @@ -0,0 +1 @@ +package telemetry diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/config/config.go b/event-processor/vendor/golang.org/x/telemetry/internal/config/config.go new file mode 100644 index 00000000..533a889c --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/config/config.go @@ -0,0 +1,140 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package config provides methods for loading and querying a +// telemetry upload config file. +package config + +import ( + "encoding/json" + "os" + "strings" + + "golang.org/x/telemetry/internal/telemetry" +) + +// Config is a wrapper around telemetry.UploadConfig that provides some +// convenience methods for checking the contents of a report. +type Config struct { + *telemetry.UploadConfig + program map[string]bool + goos map[string]bool + goarch map[string]bool + goversion map[string]bool + pgversion map[pgkey]bool + pgcounter map[pgkey]bool + pgcounterprefix map[pgkey]bool + pgstack map[pgkey]bool + rate map[pgkey]float64 +} + +type pgkey struct { + program, key string +} + +func ReadConfig(file string) (*Config, error) { + data, err := os.ReadFile(file) + if err != nil { + return nil, err + } + var cfg telemetry.UploadConfig + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + return NewConfig(&cfg), nil +} + +func NewConfig(cfg *telemetry.UploadConfig) *Config { + ucfg := Config{UploadConfig: cfg} + ucfg.goos = set(ucfg.GOOS) + ucfg.goarch = set(ucfg.GOARCH) + ucfg.goversion = set(ucfg.GoVersion) + ucfg.program = make(map[string]bool, len(ucfg.Programs)) + ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.rate = make(map[pgkey]float64) + for _, p := range ucfg.Programs { + ucfg.program[p.Name] = true + for _, v := range p.Versions { + ucfg.pgversion[pgkey{p.Name, v}] = true + } + for _, c := range p.Counters { + for _, e := range Expand(c.Name) { + ucfg.pgcounter[pgkey{p.Name, e}] = true + ucfg.rate[pgkey{p.Name, e}] = c.Rate + } + prefix, _, found := strings.Cut(c.Name, ":") + if found { + ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true + } + } + for _, s := range p.Stacks { + ucfg.pgstack[pgkey{p.Name, s.Name}] = true + ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate + } + } + return &ucfg +} + +func (r *Config) HasProgram(s string) bool { + return r.program[s] +} + +func (r *Config) HasGOOS(s string) bool { + return r.goos[s] +} + +func (r *Config) HasGOARCH(s string) bool { + return r.goarch[s] +} + +func (r *Config) HasGoVersion(s string) bool { + return r.goversion[s] +} + +func (r *Config) HasVersion(program, version string) bool { + return r.pgversion[pgkey{program, version}] +} + +func (r *Config) HasCounter(program, counter string) bool { + return r.pgcounter[pgkey{program, counter}] +} + +func (r *Config) HasCounterPrefix(program, prefix string) bool { + return r.pgcounterprefix[pgkey{program, prefix}] +} + +func (r *Config) HasStack(program, stack string) bool { + return r.pgstack[pgkey{program, stack}] +} + +func (r *Config) Rate(program, name string) float64 { + return r.rate[pgkey{program, name}] +} + +func set(slice []string) map[string]bool { + s := make(map[string]bool, len(slice)) + for _, v := range slice { + s[v] = true + } + return s +} + +// Expand takes a counter defined with buckets and expands it into distinct +// strings for each bucket. +func Expand(counter string) []string { + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { + buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",") + for _, b := range buckets { + counters = append(counters, prefix+b) + } + } else { + counters = append(counters, prefix) + } + return counters +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download.go b/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download.go new file mode 100644 index 00000000..e60ab7e9 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download.go @@ -0,0 +1,86 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package configstore abstracts interaction with the telemetry config server. +// Telemetry config (golang.org/x/telemetry/config) is distributed as a go +// module containing go.mod and config.json. Programs that upload collected +// counters download the latest config using `go mod download`. This provides +// verification of downloaded configuration and cacheability. +package configstore + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync/atomic" + + "golang.org/x/telemetry/internal/telemetry" +) + +const ( + ModulePath = "golang.org/x/telemetry/config" + configFileName = "config.json" +) + +// needNoConsole is used on windows to set the windows.CREATE_NO_WINDOW +// creation flag. +var needNoConsole = func(cmd *exec.Cmd) {} + +var downloads int64 + +// Downloads reports, for testing purposes, the number of times [Download] has +// been called. +func Downloads() int64 { + return atomic.LoadInt64(&downloads) +} + +// Download fetches the requested telemetry UploadConfig using "go mod +// download". If envOverlay is provided, it is appended to the environment used +// for invoking the go command. +// +// The second result is the canonical version of the requested configuration. +func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) { + atomic.AddInt64(&downloads, 1) + + if version == "" { + version = "latest" + } + modVer := ModulePath + "@" + version + var stdout, stderr bytes.Buffer + cmd := exec.Command("go", "mod", "download", "-json", modVer) + needNoConsole(cmd) + cmd.Env = append(os.Environ(), envOverlay...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + var info struct { + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err == nil && info.Error != "" { + return nil, "", fmt.Errorf("failed to download config module: %v", info.Error) + } + return nil, "", fmt.Errorf("failed to download config module: %w\n%s", err, &stderr) + } + + var info struct { + Dir string + Version string + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err != nil || info.Dir == "" { + return nil, "", fmt.Errorf("failed to download config module (invalid JSON): %w", err) + } + data, err := os.ReadFile(filepath.Join(info.Dir, configFileName)) + if err != nil { + return nil, "", fmt.Errorf("invalid config module: %w", err) + } + cfg := new(telemetry.UploadConfig) + if err := json.Unmarshal(data, cfg); err != nil { + return nil, "", fmt.Errorf("invalid config: %w", err) + } + return cfg, info.Version, nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go b/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go new file mode 100644 index 00000000..1368de19 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package configstore + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + needNoConsole = needNoConsoleWindows +} + +func needNoConsoleWindows(cmd *exec.Cmd) { + // The uploader main process is likely a daemonized process with no console. + // (see x/telemetry/start_windows.go) The console creation behavior when + // a parent is a console process without console is not clearly documented + // but empirically we observed the new console is created and attached to the + // subprocess in the default setup. + // + // Ensure no new console is attached to the subprocess by setting CREATE_NO_WINDOW. + // https://learn.microsoft.com/en-us/windows/console/creation-of-a-console + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.CREATE_NO_WINDOW, + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/counter/counter.go b/event-processor/vendor/golang.org/x/telemetry/internal/counter/counter.go new file mode 100644 index 00000000..c08115e5 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/counter/counter.go @@ -0,0 +1,401 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal/counter implements the internals of the public counter package. +// In addition to the public API, this package also includes APIs to parse and +// manage the counter files, needed by the upload package. +package counter + +import ( + "fmt" + "os" + "runtime" + "strings" + "sync/atomic" +) + +var ( + // Note: not using internal/godebug, so that internal/godebug can use + // internal/counter. + debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") + CrashOnBugs = false // for testing; if set, exit on fatal log messages +) + +// debugPrintf formats a debug message if GODEBUG=countertrace=1. +func debugPrintf(format string, args ...any) { + if debugCounter { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter: "+format, args...) + } +} + +// debugFatalf logs a fatal error if GODEBUG=countertrace=1. +func debugFatalf(format string, args ...any) { + if debugCounter || CrashOnBugs { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter bug: "+format, args...) + os.Exit(1) + } +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter struct { + name string + file *file + + next atomic.Pointer[Counter] + state counterState + ptr counterPtr +} + +func (c *Counter) Name() string { + return c.name +} + +type counterPtr struct { + m *mappedFile + count *atomic.Uint64 +} + +type counterState struct { + bits atomic.Uint64 +} + +func (s *counterState) load() counterStateBits { + return counterStateBits(s.bits.Load()) +} + +func (s *counterState) update(old *counterStateBits, new counterStateBits) bool { + if s.bits.CompareAndSwap(uint64(*old), uint64(new)) { + *old = new + return true + } + return false +} + +type counterStateBits uint64 + +const ( + stateReaders counterStateBits = 1<<30 - 1 + stateLocked counterStateBits = stateReaders + stateHavePtr counterStateBits = 1 << 30 + stateExtraShift = 31 + stateExtra counterStateBits = 1<<64 - 1<> stateExtraShift } + +func (b counterStateBits) incReader() counterStateBits { return b + 1 } +func (b counterStateBits) decReader() counterStateBits { return b - 1 } +func (b counterStateBits) setLocked() counterStateBits { return b | stateLocked } +func (b counterStateBits) clearLocked() counterStateBits { return b &^ stateLocked } +func (b counterStateBits) setHavePtr() counterStateBits { return b | stateHavePtr } +func (b counterStateBits) clearHavePtr() counterStateBits { return b &^ stateHavePtr } +func (b counterStateBits) clearExtra() counterStateBits { return b &^ stateExtra } +func (b counterStateBits) addExtra(n uint64) counterStateBits { + const maxExtra = uint64(stateExtra) >> stateExtraShift // 0x1ffffffff + x := b.extra() + if x+n < x || x+n > maxExtra { + x = maxExtra + } else { + x += n + } + return b.clearExtra() | counterStateBits(x)< count=%d\n", c.name, extra, sum) + } + + // Took care of refreshing ptr and flushing extra. + // Now we can release the lock, unless of course + // another goroutine cleared havePtr or added to extra, + // in which case we go around again. + if !c.state.update(&state, state.clearLocked()) { + continue + } + debugPrintf("releaseLock %s: unlocked\n", c.name) + return + } +} + +// add wraps the atomic.Uint64.Add operation to handle integer overflow. +func (c *Counter) add(n uint64) uint64 { + count := c.ptr.count + for { + old := count.Load() + sum := old + n + if sum < old { + sum = ^uint64(0) + } + if count.CompareAndSwap(old, sum) { + runtime.KeepAlive(c.ptr.m) + return sum + } + } +} + +func (c *Counter) invalidate() { + for { + state := c.state.load() + if !state.havePtr() { + debugPrintf("invalidate %s: no ptr\n", c.name) + return + } + if c.state.update(&state, state.clearHavePtr()) { + debugPrintf("invalidate %s: cleared havePtr\n", c.name) + return + } + } +} + +func (c *Counter) refresh() { + for { + state := c.state.load() + if state.havePtr() || state.readers() > 0 || state.extra() == 0 { + debugPrintf("refresh %s: havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + return + } + if c.state.update(&state, state.setLocked()) { + debugPrintf("refresh %s: locked havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + c.releaseLock(state) + return + } + } +} + +// Read reads the given counter. +// This is the implementation of x/telemetry/counter/countertest.ReadCounter. +func Read(c *Counter) (uint64, error) { + if c.file.current.Load() == nil { + return c.state.load().extra(), nil + } + pf, err := readFile(c.file) + if err != nil { + return 0, err + } + v, ok := pf.Count[DecodeStack(c.Name())] + if !ok { + return v, fmt.Errorf("not found:%q", DecodeStack(c.Name())) + } + return v, nil +} + +func readFile(f *file) (*File, error) { + if f == nil { + debugPrintf("No file") + return nil, fmt.Errorf("counter is not initialized - was Open called?") + } + + // Note: don't call f.rotate here as this will enqueue a follow-up rotation. + f.rotate1() + + if f.err != nil { + return nil, fmt.Errorf("failed to rotate mapped file - %v", f.err) + } + current := f.current.Load() + if current == nil { + return nil, fmt.Errorf("counter has no mapped file") + } + name := current.f.Name() + data, err := ReadMapped(name) + if err != nil { + return nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, fmt.Errorf("failed to parse: %v", err) + } + return pf, nil +} + +// ReadFile reads the counters and stack counters from the given file. +// This is the implementation of x/telemetry/counter/countertest.ReadFile. +func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) { + // TODO: Document the format of the stackCounters names. + + data, err := ReadMapped(name) + if err != nil { + return nil, nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse: %v", err) + } + counters = make(map[string]uint64) + stackCounters = make(map[string]uint64) + for k, v := range pf.Count { + if IsStackCounter(k) { + stackCounters[DecodeStack(k)] = v + } else { + counters[k] = v + } + } + return counters, stackCounters, nil +} + +// ReadMapped reads the contents of the given file by memory mapping. +// +// This avoids file synchronization issues. +func ReadMapped(name string) ([]byte, error) { + f, err := os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + mapping, err := memmap(f) + if err != nil { + return nil, err + } + data := make([]byte, fi.Size()) + copy(data, mapping.Data) + munmap(mapping) + return data, nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/counter/file.go b/event-processor/vendor/golang.org/x/telemetry/internal/counter/file.go new file mode 100644 index 00000000..872a6f6a --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -0,0 +1,814 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "errors" + "fmt" + "math/rand" + "os" + "path" + "path/filepath" + "runtime" + "runtime/debug" + "sync" + "sync/atomic" + "time" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" + "golang.org/x/telemetry/internal/telemetry" +) + +// A file is a counter file. +type file struct { + // Linked list of all known counters. + // (Linked list insertion is easy to make lock-free, + // and we don't want the initial counters incremented + // by a program to cause significant contention.) + counters atomic.Pointer[Counter] // head of list + end Counter // list ends at &end instead of nil + + mu sync.Mutex + buildInfo *debug.BuildInfo + timeBegin, timeEnd time.Time + err error + // current holds the current file mapping, which may change when the file is + // rotated or extended. + // + // current may be read without holding mu, but may be nil. + // + // The cleanup logic for file mappings is complicated, because invalidating + // counter pointers is reentrant: [file.invalidateCounters] may call + // [file.lookup], which acquires mu. Therefore, writing current must be done + // as follows: + // 1. record the previous value of current + // 2. Store a new value in current + // 3. unlock mu + // 4. call invalidateCounters + // 5. close the previous mapped value from (1) + // TODO(rfindley): simplify + current atomic.Pointer[mappedFile] +} + +var defaultFile file + +// register ensures that the counter c is registered with the file. +func (f *file) register(c *Counter) { + debugPrintf("register %s %p\n", c.Name(), c) + + // If counter is not registered with file, register it. + // Doing this lazily avoids init-time work + // as well as any execution cost at all for counters + // that are not used in a given program. + wroteNext := false + for wroteNext || c.next.Load() == nil { + head := f.counters.Load() + next := head + if next == nil { + next = &f.end + } + debugPrintf("register %s next %p\n", c.Name(), next) + if !wroteNext { + if !c.next.CompareAndSwap(nil, next) { + debugPrintf("register %s cas failed %p\n", c.Name(), c.next.Load()) + continue + } + wroteNext = true + } else { + c.next.Store(next) + } + if f.counters.CompareAndSwap(head, c) { + debugPrintf("registered %s %p\n", c.Name(), f.counters.Load()) + return + } + debugPrintf("register %s cas2 failed %p %p\n", c.Name(), f.counters.Load(), head) + } +} + +// invalidateCounters marks as invalid all the pointers +// held by f's counters and then refreshes them. +// +// invalidateCounters cannot be called while holding f.mu, +// because a counter refresh may call f.lookup. +func (f *file) invalidateCounters() { + // Mark every counter as needing to refresh its count pointer. + if head := f.counters.Load(); head != nil { + for c := head; c != &f.end; c = c.next.Load() { + c.invalidate() + } + for c := head; c != &f.end; c = c.next.Load() { + c.refresh() + } + } +} + +// lookup looks up the counter with the given name in the file, +// allocating it if needed, and returns a pointer to the atomic.Uint64 +// containing the counter data. +// If the file has not been opened yet, lookup returns nil. +func (f *file) lookup(name string) counterPtr { + current := f.current.Load() + if current == nil { + debugPrintf("lookup %s - no mapped file\n", name) + return counterPtr{} + } + ptr := f.newCounter(name) + if ptr == nil { + return counterPtr{} + } + return counterPtr{current, ptr} +} + +// ErrDisabled is the error returned when telemetry is disabled. +var ErrDisabled = errors.New("counter: disabled as Go telemetry is off") + +var ( + errNoBuildInfo = errors.New("counter: missing build info") + errCorrupt = errors.New("counter: corrupt counter file") +) + +// weekEnd returns the day of the week on which uploads occur (and therefore +// counters expire). +// +// Reads the weekends file, creating one if none exists. +func weekEnd() (time.Weekday, error) { + // If there is no 'weekends' file create it and initialize it + // to a random day of the week. There is a short interval for + // a race. + weekends := filepath.Join(telemetry.Default.LocalDir(), "weekends") + day := fmt.Sprintf("%d\n", rand.Intn(7)) + if _, err := os.ReadFile(weekends); err != nil { + if err := os.MkdirAll(telemetry.Default.LocalDir(), 0777); err != nil { + debugPrintf("%v: could not create telemetry.LocalDir %s", err, telemetry.Default.LocalDir()) + return 0, err + } + if err = os.WriteFile(weekends, []byte(day), 0666); err != nil { + return 0, err + } + } + + // race is over, read the file + buf, err := os.ReadFile(weekends) + // There is no reasonable way of recovering from errors + // so we just fail + if err != nil { + return 0, err + } + buf = bytes.TrimSpace(buf) + if len(buf) == 0 { + return 0, fmt.Errorf("empty weekends file") + } + weekend := time.Weekday(buf[0] - '0') // 0 is Sunday + // paranoia to make sure the value is legal + weekend %= 7 + if weekend < 0 { + weekend += 7 + } + return weekend, nil +} + +// rotate checks to see whether the file f needs to be rotated, +// meaning to start a new counter file with a different date in the name. +// rotate is also used to open the file initially, meaning f.current can be nil. +// In general rotate should be called just once for each file. +// rotate will arrange a timer to call itself again when necessary. +func (f *file) rotate() { + expiry := f.rotate1() + if !expiry.IsZero() { + delay := time.Until(expiry) + // Some tests set CounterTime to a time in the past, causing delay to be + // negative. Avoid infinite loops by delaying at least a short interval. + // + // TODO(rfindley): instead, just also mock AfterFunc. + const minDelay = 1 * time.Minute + if delay < minDelay { + delay = minDelay + } + // TODO(rsc): Does this do the right thing for laptops closing? + time.AfterFunc(delay, f.rotate) + } +} + +func nop() {} + +// CounterTime returns the current UTC time. +// Mutable for testing. +var CounterTime = func() time.Time { + return time.Now().UTC() +} + +// counterSpan returns the current time span for a counter file, as determined +// by [CounterTime] and the [weekEnd]. +func counterSpan() (begin, end time.Time, _ error) { + year, month, day := CounterTime().Date() + begin = time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + // files always begin today, but expire on the next day of the week + // from the 'weekends' file. + weekend, err := weekEnd() + if err != nil { + return time.Time{}, time.Time{}, err + } + incr := int(weekend - begin.Weekday()) + if incr <= 0 { + incr += 7 // ensure that end is later than begin + } + end = time.Date(year, month, day+incr, 0, 0, 0, 0, time.UTC) + return begin, end, nil +} + +// rotate1 rotates the current counter file, returning its expiry, or the zero +// time if rotation failed. +func (f *file) rotate1() time.Time { + // Cleanup must be performed while unlocked, since invalidateCounters may + // involve calls to f.lookup. + var previous *mappedFile // read below while holding the f.mu. + defer func() { + // Counters must be invalidated whenever the mapped file changes. + if next := f.current.Load(); next != previous { + f.invalidateCounters() + // Ensure that the previous counter mapped file is closed. + if previous != nil { + previous.close() // safe to call multiple times + } + } + }() + + f.mu.Lock() + defer f.mu.Unlock() + + previous = f.current.Load() + + if f.err != nil { + return time.Time{} // already in failed state; nothing to do + } + + fail := func(err error) { + debugPrintf("rotate: %v", err) + f.err = err + f.current.Store(nil) + } + + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // TODO(rfindley): do we ever want to make ErrDisabled recoverable? + // Specifically, if f.err is ErrDisabled, should we check again during when + // rotating? + fail(ErrDisabled) + return time.Time{} + } + + if f.buildInfo == nil { + bi, ok := debug.ReadBuildInfo() + if !ok { + fail(errNoBuildInfo) + return time.Time{} + } + f.buildInfo = bi + } + + begin, end, err := counterSpan() + if err != nil { + fail(err) + return time.Time{} + } + if f.timeBegin.Equal(begin) && f.timeEnd.Equal(end) { + return f.timeEnd // nothing to do + } + f.timeBegin, f.timeEnd = begin, end + + goVers, progPath, progVers := telemetry.ProgramInfo(f.buildInfo) + meta := fmt.Sprintf("TimeBegin: %s\nTimeEnd: %s\nProgram: %s\nVersion: %s\nGoVersion: %s\nGOOS: %s\nGOARCH: %s\n\n", + f.timeBegin.Format(time.RFC3339), f.timeEnd.Format(time.RFC3339), + progPath, progVers, goVers, runtime.GOOS, runtime.GOARCH) + if len(meta) > maxMetaLen { // should be impossible for our use + fail(fmt.Errorf("metadata too long")) + return time.Time{} + } + + if progVers != "" { + progVers = "@" + progVers + } + baseName := fmt.Sprintf("%s%s-%s-%s-%s-%s.%s.count", + path.Base(progPath), + progVers, + goVers, + runtime.GOOS, + runtime.GOARCH, + f.timeBegin.Format(telemetry.DateOnly), + FileVersion, + ) + dir := telemetry.Default.LocalDir() + if err := os.MkdirAll(dir, 0777); err != nil { + fail(fmt.Errorf("making local dir: %v", err)) + return time.Time{} + } + name := filepath.Join(dir, baseName) + + m, err := openMapped(name, meta) + if err != nil { + // Mapping failed: + // If there used to be a mapped file, after cleanup + // incrementing counters will only change their internal state. + // (before cleanup the existing mapped file would be updated) + fail(fmt.Errorf("openMapped: %v", err)) + return time.Time{} + } + + debugPrintf("using %v", m.f.Name()) + f.current.Store(m) + return f.timeEnd +} + +func (f *file) newCounter(name string) *atomic.Uint64 { + v, cleanup := f.newCounter1(name) + cleanup() + return v +} + +func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { + f.mu.Lock() + defer f.mu.Unlock() + + current := f.current.Load() + if current == nil { + return nil, nop + } + debugPrintf("newCounter %s in %s\n", name, current.f.Name()) + if v, _, _, _ := current.lookup(name); v != nil { + return v, nop + } + v, newM, err := current.newCounter(name) + if err != nil { + debugPrintf("newCounter %s: %v\n", name, err) + return nil, nop + } + + cleanup = nop + if newM != nil { + f.current.Store(newM) + cleanup = func() { + f.invalidateCounters() + current.close() + } + } + return v, cleanup +} + +var ( + openOnce sync.Once + // rotating reports whether the call to Open had rotate = true. + // + // In golang/go#68497, we observed that file rotation can break runtime + // deadlock detection. To minimize the fix for 1.23, we are splitting the + // Open API into one version that rotates the counter file, and another that + // does not. The rotating variable guards against use of both APIs from the + // same process. + rotating bool +) + +// Open associates counting with the defaultFile. +// The returned function is for testing only, and should +// be called after all Inc()s are finished, but before +// any reports are generated. +// (Otherwise expired count files will not be deleted on Windows.) +func Open(rotate bool) func() { + if telemetry.DisabledOnPlatform { + return func() {} + } + close := func() {} + openOnce.Do(func() { + rotating = rotate + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. + return + } + debugPrintf("Open(%v)", rotate) + if rotate { + defaultFile.rotate() // calls rotate1 and schedules a rotation + } else { + defaultFile.rotate1() + } + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + if rotating != rotate { + panic("BUG: Open called with inconsistent values for 'rotate'") + } + return close +} + +const ( + FileVersion = "v1" + hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" + recordUnit = 32 + maxMetaLen = 512 + numHash = 512 // 2kB for hash table + maxNameLen = 4 * 1024 + limitOff = 0 + hashOff = 4 + pageSize = 16 * 1024 + minFileLen = 16 * 1024 +) + +// A mappedFile is a counter file mmapped into memory. +// +// The file layout for a mappedFile m is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, hdrLen: header, containing metadata; see [mappedHeader] +// hdrLen+limitOff, 4: uint32 allocation limit (byte offset of the end of counter records) +// hdrLen+hashOff, 4*numHash: hash table, stores uint32 heads of a linked list of records, keyed by name hash +// hdrLen+hashOff+4*numHash to limit: counter records: see record syntax below +// +// The record layout is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, 8: uint64 counter value +// 8, 12: uint32 name length +// 12, 16: uint32 offset of next record in linked list +// 16, name length: counter name +type mappedFile struct { + meta string + hdrLen uint32 + zero [4]byte + closeOnce sync.Once + f *os.File + mapping *mmap.Data +} + +// openMapped opens and memory maps a file. +// +// name is the path to the file. +// +// meta is the file metadata, which must match the metadata of the file on disk +// exactly. +// +// existing should be nil the first time this is called for a file, +// and when remapping, should be the previous mappedFile. +func openMapped(name, meta string) (_ *mappedFile, err error) { + hdr, err := mappedHeader(meta) + if err != nil { + return nil, err + } + + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + // Note: using local variable m here, not return value, + // so that return nil, err does not set m = nil and break the code in the defer. + m := &mappedFile{ + f: f, + meta: meta, + } + + defer func() { + if err != nil { + m.close() + } + }() + + info, err := f.Stat() + if err != nil { + return nil, err + } + + // Establish file header and initial data area if not already present. + if info.Size() < minFileLen { + if _, err := f.WriteAt(hdr, 0); err != nil { + return nil, err + } + // Write zeros at the end of the file to extend it to minFileLen. + if _, err := f.WriteAt(m.zero[:], int64(minFileLen-len(m.zero))); err != nil { + return nil, err + } + info, err = f.Stat() + if err != nil { + return nil, err + } + if info.Size() < minFileLen { + return nil, fmt.Errorf("counter: writing file did not extend it") + } + } + + // Map into memory. + mapping, err := memmap(f) + if err != nil { + return nil, err + } + m.mapping = mapping + if !bytes.HasPrefix(m.mapping.Data, hdr) { + // TODO(rfindley): we can and should do better here, reading the mapped + // header length and comparing headers exactly. + return nil, fmt.Errorf("counter: header mismatch") + } + m.hdrLen = uint32(len(hdr)) + + return m, nil +} + +func mappedHeader(meta string) ([]byte, error) { + if len(meta) > maxMetaLen { + return nil, fmt.Errorf("counter: metadata too large") + } + np := round(len(hdrPrefix), 4) + n := round(np+4+len(meta), 32) + hdr := make([]byte, n) + copy(hdr, hdrPrefix) + *(*uint32)(unsafe.Pointer(&hdr[np])) = uint32(n) + copy(hdr[np+4:], meta) + return hdr, nil +} + +func (m *mappedFile) place(limit uint32, name string) (start, end uint32) { + if limit == 0 { + // first record in file + limit = m.hdrLen + hashOff + 4*numHash + } + n := round(uint32(16+len(name)), recordUnit) + start = round(limit, recordUnit) // should already be rounded but just in case + // Note: Checking for crossing a page boundary would be + // start/pageSize != (start+n-1)/pageSize, + // but we are checking for reaching the page end, so no -1. + // The page end is reserved for use by extend. + // See the comment in m.extend. + if start/pageSize != (start+n)/pageSize { + // bump start to next page + start = round(limit, pageSize) + } + return start, start + n +} + +var memmap = mmap.Mmap +var munmap = mmap.Munmap + +func (m *mappedFile) close() { + m.closeOnce.Do(func() { + if m.mapping != nil { + munmap(m.mapping) + m.mapping = nil + } + if m.f != nil { + m.f.Close() // best effort + m.f = nil + } + }) +} + +// hash returns the hash code for name. +// The implementation is FNV-1a. +// This hash function is a fixed detail of the file format. +// It cannot be changed without also changing the file format version. +func hash(name string) uint32 { + const ( + offset32 = 2166136261 + prime32 = 16777619 + ) + h := uint32(offset32) + for i := 0; i < len(name); i++ { + c := name[i] + h = (h ^ uint32(c)) * prime32 + } + return (h ^ (h >> 16)) % numHash +} + +func (m *mappedFile) load32(off uint32) uint32 { + if int64(off) >= int64(len(m.mapping.Data)) { + return 0 + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).Load() +} + +func (m *mappedFile) cas32(off, old, new uint32) bool { + if int64(off) >= int64(len(m.mapping.Data)) { + panic("bad cas32") // return false would probably loop + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).CompareAndSwap(old, new) +} + +// entryAt reads a counter record at the given byte offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Uint64, ok bool) { + if off < m.hdrLen+hashOff || int64(off)+16 > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + nameLen := m.load32(off+8) & 0x00ffffff + if nameLen == 0 || int64(off)+16+int64(nameLen) > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + name = m.mapping.Data[off+16 : off+16+nameLen] + next = m.load32(off + 12) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return name, next, v, true +} + +// writeEntryAt writes a new counter record at the given offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +// +// writeEntryAt only returns false in the presence of some form of corruption: +// an offset outside the bounds of the record region in the mapped file. +func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, v *atomic.Uint64, ok bool) { + // TODO(rfindley): shouldn't this first condition be off < m.hdrLen+hashOff+4*numHash? + if off < m.hdrLen+hashOff || int64(off)+16+int64(len(name)) > int64(len(m.mapping.Data)) { + return nil, nil, false + } + copy(m.mapping.Data[off+16:], name) + atomic.StoreUint32((*uint32)(unsafe.Pointer(&m.mapping.Data[off+8])), uint32(len(name))|0xff000000) + next = (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off+12])) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return next, v, true +} + +// lookup searches the mapped file for a counter record with the given name, returning: +// - v: the mapped counter value +// - headOff: the offset of the head pointer (see [mappedFile]) +// - head: the value of the head pointer +// - ok: whether lookup succeeded +func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32, ok bool) { + h := hash(name) + headOff = m.hdrLen + hashOff + h*4 + head = m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return nil, 0, 0, false + } + if string(ename) == name { + return v, headOff, head, true + } + off = next + } + return nil, headOff, head, true +} + +// newCounter allocates and writes a new counter record with the given name. +// +// If name is already recorded in the file, newCounter returns the existing counter. +func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, err error) { + if len(name) > maxNameLen { + return nil, nil, fmt.Errorf("counter name too long") + } + orig := m + defer func() { + if m != orig { + if err != nil { + m.close() + } else { + m1 = m + } + } + }() + + v, headOff, head, ok := m.lookup(name) + for tries := 0; !ok; tries++ { + if tries >= 10 { + debugFatalf("corrupt: failed to remap after 10 tries") + return nil, nil, errCorrupt + } + // Lookup found an invalid pointer, + // perhaps because the file has grown larger than the mapping. + limit := m.load32(m.hdrLen + limitOff) + if limit, datalen := int64(limit), int64(len(m.mapping.Data)); limit <= datalen { + // Mapping doesn't need to grow, so lookup found actual corruption, + // in the form of an entry pointer that exceeds the recorded allocation + // limit. This should never happen, unless the actual file contents are + // corrupt. + debugFatalf("corrupt: limit %d is within mapping length %d", limit, datalen) + return nil, nil, errCorrupt + } + // That the recorded limit is greater than the mapped data indicates that + // an external process has extended the file. Re-map to pick up this extension. + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, nil, err + } + if limit, datalen := int64(limit), int64(len(newM.mapping.Data)); limit > datalen { + // We've re-mapped, yet limit still exceeds the data length. This + // indicates that the underlying file was somehow truncated, or the + // recorded limit is corrupt. + debugFatalf("corrupt: limit %d exceeds file size %d", limit, datalen) + return nil, nil, errCorrupt + } + // If m != orig, this is at least the second time around the loop + // trying to open the mapping. Close the previous attempt. + if m != orig { + m.close() + } + m = newM + v, headOff, head, ok = m.lookup(name) + } + if v != nil { + return v, nil, nil + } + + // Reserve space for new record. + // We are competing against other programs using the same file, + // so we use a compare-and-swap on the allocation limit in the header. + var start, end uint32 + for { + // Determine where record should end, and grow file if needed. + limit := m.load32(m.hdrLen + limitOff) + start, end = m.place(limit, name) + debugPrintf("place %s at %#x-%#x\n", name, start, end) + if int64(end) > int64(len(m.mapping.Data)) { + newM, err := m.extend(end) + if err != nil { + return nil, nil, err + } + if m != orig { + m.close() + } + m = newM + continue + } + + // Attempt to reserve that space for our record. + if m.cas32(m.hdrLen+limitOff, limit, end) { + break + } + } + + // Write record. + next, v, ok := m.writeEntryAt(start, name) + if !ok { + debugFatalf("corrupt: failed to write entry: %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) + return nil, nil, errCorrupt // more likely our math is wrong + } + + // Link record into hash chain, making sure not to introduce a duplicate. + // We know name does not appear in the chain starting at head. + for { + next.Store(head) + if m.cas32(headOff, head, start) { + return v, nil, nil + } + + // Check new elements in chain for duplicates. + old := head + head = m.load32(headOff) + for off := head; off != old; { + ename, enext, v, ok := m.entryAt(off) + if !ok { + return nil, nil, errCorrupt + } + if string(ename) == name { + next.Store(^uint32(0)) // mark ours as dead + return v, nil, nil + } + off = enext + } + } +} + +func (m *mappedFile) extend(end uint32) (*mappedFile, error) { + end = round(end, pageSize) + info, err := m.f.Stat() + if err != nil { + return nil, err + } + if info.Size() < int64(end) { + // Note: multiple processes could be calling extend at the same time, + // but this write only writes the last 4 bytes of the page. + // The last 4 bytes of the page are reserved for this purpose and hold no data. + // (In m.place, if a new record would extend to the very end of the page, + // it is placed in the next page instead.) + // So it is fine if multiple processes extend at the same time. + if _, err := m.f.WriteAt(m.zero[:], int64(end)-int64(len(m.zero))); err != nil { + return nil, err + } + } + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, err + } + if int64(len(newM.mapping.Data)) < int64(end) { + // File system or logic bug: new file is somehow not extended. + // See go.dev/issue/68311, where this appears to have been happening. + newM.close() + return nil, errCorrupt + } + return newM, err +} + +// round returns x rounded up to the next multiple of unit, +// which must be a power of two. +func round[T int | uint32](x T, unit T) T { + return (x + unit - 1) &^ (unit - 1) +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/counter/parse.go b/event-processor/vendor/golang.org/x/telemetry/internal/counter/parse.go new file mode 100644 index 00000000..a42a3513 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/counter/parse.go @@ -0,0 +1,82 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "fmt" + "strings" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" +) + +type File struct { + Meta map[string]string + Count map[string]uint64 +} + +func Parse(filename string, data []byte) (*File, error) { + if !bytes.HasPrefix(data, []byte(hdrPrefix)) || len(data) < pageSize { + if len(data) < pageSize { + return nil, fmt.Errorf("%s: file too short (%d<%d)", filename, len(data), pageSize) + } + return nil, fmt.Errorf("%s: wrong hdr (not %q)", filename, hdrPrefix) + } + corrupt := func() (*File, error) { + // TODO(rfindley): return a useful error message. + return nil, fmt.Errorf("%s: corrupt counter file", filename) + } + + f := &File{ + Meta: make(map[string]string), + Count: make(map[string]uint64), + } + np := round(len(hdrPrefix), 4) + hdrLen := *(*uint32)(unsafe.Pointer(&data[np])) + if hdrLen > pageSize { + return corrupt() + } + meta := data[np+4 : hdrLen] + if i := bytes.IndexByte(meta, 0); i >= 0 { + meta = meta[:i] + } + m := &mappedFile{ + meta: string(meta), + hdrLen: hdrLen, + mapping: &mmap.Data{Data: data}, + } + + lines := strings.Split(m.meta, "\n") + for _, line := range lines { + if line == "" { + continue + } + k, v, ok := strings.Cut(line, ": ") + if !ok { + return corrupt() + } + f.Meta[k] = v + } + + for i := uint32(0); i < numHash; i++ { + headOff := hdrLen + hashOff + i*4 + head := m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return corrupt() + } + if _, ok := f.Count[string(ename)]; ok { + return corrupt() + } + ctrName := DecodeStack(string(ename)) + f.Count[ctrName] = v.Load() + off = next + } + } + return f, nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go b/event-processor/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go new file mode 100644 index 00000000..3e7ffdeb --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go @@ -0,0 +1,212 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "fmt" + "runtime" + "strings" + "sync" +) + +// On the disk, and upstream, stack counters look like sets of +// regular counters with names that include newlines. + +// a StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter struct { + name string + depth int + file *file + + mu sync.Mutex + // as this is a detail of the implementation, it could be replaced + // by a more efficient mechanism + stacks []stack +} + +type stack struct { + pcs []uintptr + counter *Counter +} + +func NewStack(name string, depth int) *StackCounter { + return &StackCounter{name: name, depth: depth, file: &defaultFile} +} + +// Inc increments a stack counter. It computes the caller's stack and +// looks up the corresponding counter. It then increments that counter, +// creating it if necessary. +func (c *StackCounter) Inc() { + pcs := make([]uintptr, c.depth) + n := runtime.Callers(2, pcs) // caller of Inc + pcs = pcs[:n] + + c.mu.Lock() + defer c.mu.Unlock() + + // Existing counter? + var ctr *Counter + for _, s := range c.stacks { + if eq(s.pcs, pcs) { + if s.counter != nil { + ctr = s.counter + break + } + } + } + + if ctr == nil { + // Create new counter. + ctr = &Counter{ + name: EncodeStack(pcs, c.name), + file: c.file, + } + c.stacks = append(c.stacks, stack{pcs: pcs, counter: ctr}) + } + + ctr.Inc() +} + +// EncodeStack returns the name of the counter to +// use for the given stack of program counters. +// The name encodes the stack. +func EncodeStack(pcs []uintptr, prefix string) string { + var locs []string + lastImport := "" + frs := runtime.CallersFrames(pcs) + for { + fr, more := frs.Next() + // TODO(adonovan): this CutLast(".") operation isn't + // appropriate for generic function symbols. + path, fname := cutLastDot(fr.Function) + if path == lastImport { + path = `"` // (a ditto mark) + } else { + lastImport = path + } + var loc string + if fr.Func != nil { + // Use function-relative line numbering. + // f:+2 means two lines into function f. + // f:-1 should never happen, but be conservative. + // + // An inlined call is replaced by a NOP instruction + // with the correct pclntab information. + _, entryLine := fr.Func.FileLine(fr.Entry) + loc = fmt.Sprintf("%s.%s:%+d,+0x%x", path, fname, fr.Line-entryLine, fr.PC-fr.Entry) + } else { + // The function is non-Go code or is fully inlined: + // use absolute line number within enclosing file. + // + // For inlined calls, the PC and Entry values + // both refer to the enclosing combined function. + // For example, both these PCs are relative to "caller": + // + // callee:=1,+0x12 ('=' means inlined) + // caller:+2,+0x34 + loc = fmt.Sprintf("%s.%s:=%d,+0x%x", path, fname, fr.Line, fr.PC-fr.Entry) + } + locs = append(locs, loc) + if !more { + break + } + } + + name := prefix + "\n" + strings.Join(locs, "\n") + if len(name) > maxNameLen { + const bad = "\ntruncated\n" + name = name[:maxNameLen-len(bad)] + bad + } + return name +} + +// DecodeStack expands the (compressed) stack encoded in the counter name. +func DecodeStack(ename string) string { + if !strings.Contains(ename, "\n") { + return ename // not a stack counter + } + lines := strings.Split(ename, "\n") + var lastPath string // empty or ends with . + for i, line := range lines { + path, rest := cutLastDot(line) + if len(path) == 0 { + continue // unchanged + } + if len(path) == 1 && path[0] == '"' { + lines[i] = lastPath + rest + } else { + lastPath = path + "." + // line unchanged + } + } + return strings.Join(lines, "\n") // trailing \n? +} + +// input is . +// output is (import path, function name) +func cutLastDot(x string) (before, after string) { + i := strings.LastIndex(x, ".") + if i < 0 { + return "", x + } + return x[:i], x[i+1:] +} + +// Names reports all the counter names associated with a StackCounter. +func (c *StackCounter) Names() []string { + c.mu.Lock() + defer c.mu.Unlock() + names := make([]string, len(c.stacks)) + for i, s := range c.stacks { + names[i] = s.counter.Name() + } + return names +} + +// Counters returns the known Counters for a StackCounter. +// There may be more in the count file. +func (c *StackCounter) Counters() []*Counter { + c.mu.Lock() + defer c.mu.Unlock() + counters := make([]*Counter, len(c.stacks)) + for i, s := range c.stacks { + counters[i] = s.counter + } + return counters +} + +func eq(a, b []uintptr) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// ReadStack reads the given stack counter. +// This is the implementation of +// golang.org/x/telemetry/counter/countertest.ReadStackCounter. +func ReadStack(c *StackCounter) (map[string]uint64, error) { + ret := map[string]uint64{} + for _, ctr := range c.Counters() { + v, err := Read(ctr) + if err != nil { + return nil, err + } + ret[DecodeStack(ctr.Name())] = v + } + return ret, nil +} + +// IsStackCounter reports whether the counter name is for a stack counter. +func IsStackCounter(name string) bool { + return strings.Contains(name, "\n") +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go b/event-processor/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go new file mode 100644 index 00000000..53966ad2 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go @@ -0,0 +1,336 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crashmonitor + +// This file defines a monitor that reports arbitrary Go runtime +// crashes to telemetry. + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "reflect" + "runtime/debug" + "strconv" + "strings" + + "golang.org/x/telemetry/internal/counter" +) + +// Parent sets up the parent side of the crashmonitor. It requires +// exclusive use of a writable pipe connected to the child process's stdin. +func Parent(pipe *os.File) { + writeSentinel(pipe) + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + debug.SetCrashOutput(pipe, debug.CrashOptions{}) // ignore error +} + +// Child runs the part of the crashmonitor that runs in the child process. +// It expects its stdin to be connected via a pipe to the parent which has +// run Parent. +func Child() { + // Wait for parent process's dying gasp. + // If the parent dies for any reason this read will return. + data, err := io.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("failed to read from input pipe: %v", err) + } + + // If the only line is the sentinel, it wasn't a crash. + if bytes.Count(data, []byte("\n")) < 2 { + childExitHook() + os.Exit(0) // parent exited without crash report + } + + log.Printf("parent reported crash:\n%s", data) + + // Parse the stack out of the crash report + // and record a telemetry count for it. + name, err := telemetryCounterName(data) + if err != nil { + // Keep count of how often this happens + // so that we can investigate if necessary. + incrementCounter("crash/malformed") + + // Something went wrong. + // Save the crash securely in the file system. + f, err := os.CreateTemp(os.TempDir(), "*.crash") + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(data); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + log.Printf("failed to report crash to telemetry: %v", err) + log.Fatalf("crash report saved at %s", f.Name()) + } + + incrementCounter(name) + + childExitHook() + log.Fatalf("telemetry crash recorded") +} + +// (stubbed by test) +var ( + incrementCounter = func(name string) { counter.New(name).Inc() } + childExitHook = func() {} +) + +// The sentinel function returns its address. The difference between +// this value as observed by calls in two different processes of the +// same executable tells us the relative offset of their text segments. +// +// It would be nice if SetCrashOutput took care of this as it's fiddly +// and likely to confuse every user at first. +func sentinel() uint64 { + return uint64(reflect.ValueOf(sentinel).Pointer()) +} + +func writeSentinel(out io.Writer) { + fmt.Fprintf(out, "sentinel %x\n", sentinel()) +} + +// telemetryCounterName parses a crash report produced by the Go +// runtime, extracts the stack of the first runnable goroutine, +// converts each line into telemetry form ("symbol:relative-line"), +// and returns this as the name of a counter. +func telemetryCounterName(crash []byte) (string, error) { + pcs, err := parseStackPCs(string(crash)) + if err != nil { + return "", err + } + + // Limit the number of frames we request. + pcs = pcs[:min(len(pcs), 16)] + + if len(pcs) == 0 { + // This can occur if all goroutines are idle, as when + // caught in a deadlock, or killed by an async signal + // while blocked. + // + // TODO(adonovan): consider how to report such + // situations. Reporting a goroutine in [sleep] or + // [select] state could be quite confusing without + // further information about the nature of the crash, + // as the problem is not local to the code location. + // + // For now, we keep count of this situation so that we + // can access whether it needs a more involved solution. + return "crash/no-running-goroutine", nil + } + + // This string appears at the start of all + // crashmonitor-generated counter names. + // + // It is tempting to expose this as a parameter of Start, but + // it is not without risk. What value should most programs + // provide? There's no point giving the name of the executable + // as this is already recorded by telemetry. What if the + // application runs in multiple modes? Then it might be useful + // to record the mode. The problem is that an application with + // multiple modes probably doesn't know its mode by line 1 of + // main.main: it might require flag or argument parsing, or + // even validation of an environment variable, and we really + // want to steer users aware from any logic before Start. The + // flags and arguments will be wrong in the child process, and + // every extra conditional branch creates a risk that the + // recursively executed child program will behave not like the + // monitor but like the application. If the child process + // exits before calling Start, then the parent application + // will not have a monitor, and its crash reports will be + // discarded (written in to a pipe that is never read). + // + // So for now, we use this constant string. + const prefix = "crash/crash" + return counter.EncodeStack(pcs, prefix), nil +} + +// parseStackPCs parses the parent process's program counters for the +// first running goroutine out of a GOTRACEBACK=system traceback, +// adjusting them so that they are valid for the child process's text +// segment. +// +// This function returns only program counter values, ensuring that +// there is no possibility of strings from the crash report (which may +// contain PII) leaking into the telemetry system. +func parseStackPCs(crash string) ([]uintptr, error) { + // getSymbol parses the symbol name out of a line of the form: + // SYMBOL(ARGS) + // + // Note: SYMBOL may contain parens "pkg.(*T).method". However, type + // parameters are always replaced with ..., so they cannot introduce + // more parens. e.g., "pkg.(*T[...]).method". + // + // ARGS can contain parens. We want the first paren that is not + // immediately preceded by a ".". + // + // TODO(prattmic): This is mildly complicated and is only used to find + // runtime.sigpanic, so perhaps simplify this by checking explicitly + // for sigpanic. + getSymbol := func(line string) (string, error) { + var prev rune + for i, c := range line { + if line[i] != '(' { + prev = c + continue + } + if prev == '.' { + prev = c + continue + } + return line[:i], nil + } + return "", fmt.Errorf("no symbol for stack frame: %s", line) + } + + // getPC parses the PC out of a line of the form: + // \tFILE:LINE +0xRELPC sp=... fp=... pc=... + getPC := func(line string) (uint64, error) { + _, pcstr, ok := strings.Cut(line, " pc=") // e.g. pc=0x%x + if !ok { + return 0, fmt.Errorf("no pc= for stack frame: %s", line) + } + return strconv.ParseUint(pcstr, 0, 64) // 0 => allow 0x prefix + } + + var ( + pcs []uintptr + parentSentinel uint64 + childSentinel = sentinel() + on = false // are we in the first running goroutine? + lines = strings.Split(crash, "\n") + symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. + currSymbol string + prevSymbol string // symbol of the most recent previous frame with a PC. + ) + for i := 0; i < len(lines); i++ { + line := lines[i] + + // Read sentinel value. + if parentSentinel == 0 && strings.HasPrefix(line, "sentinel ") { + _, err := fmt.Sscanf(line, "sentinel %x", &parentSentinel) + if err != nil { + return nil, fmt.Errorf("can't read sentinel line") + } + continue + } + + // Search for "goroutine GID [STATUS]" + if !on { + if strings.HasPrefix(line, "goroutine ") && + strings.Contains(line, " [running]:") { + on = true + + if parentSentinel == 0 { + return nil, fmt.Errorf("no sentinel value in crash report") + } + } + continue + } + + // A blank line marks end of a goroutine stack. + if line == "" { + break + } + + // Skip the final "created by SYMBOL in goroutine GID" part. + if strings.HasPrefix(line, "created by ") { + break + } + + // Expect a pair of lines: + // SYMBOL(ARGS) + // \tFILE:LINE +0xRELPC sp=0x%x fp=0x%x pc=0x%x + // Note: SYMBOL may contain parens "pkg.(*T).method" + // The RELPC is sometimes missing. + + if symLine { + var err error + currSymbol, err = getSymbol(line) + if err != nil { + return nil, fmt.Errorf("error extracting symbol: %v", err) + } + + symLine = false // Next line is FILE:LINE. + } else { + // Parse the PC, and correct for the parent and child's + // different mappings of the text section. + pc, err := getPC(line) + if err != nil { + // Inlined frame, perhaps; skip it. + + // Done with this frame. Next line is a new frame. + // + // Don't update prevSymbol; we only want to + // track frames with a PC. + currSymbol = "" + symLine = true + continue + } + + pc = pc - parentSentinel + childSentinel + + // If the previous frame was sigpanic, then this frame + // was a trap (e.g., SIGSEGV). + // + // Typically all middle frames are calls, and report + // the "return PC". That is, the instruction following + // the CALL where the callee will eventually return to. + // + // runtime.CallersFrames is aware of this property and + // will decrement each PC by 1 to "back up" to the + // location of the CALL, which is the actual line + // number the user expects. + // + // This does not work for traps, as a trap is not a + // call, so the reported PC is not the return PC, but + // the actual PC of the trap. + // + // runtime.Callers is aware of this and will + // intentionally increment trap PCs in order to correct + // for the decrement performed by + // runtime.CallersFrames. See runtime.tracebackPCs and + // runtume.(*unwinder).symPC. + // + // We must emulate the same behavior, otherwise we will + // report the location of the instruction immediately + // prior to the trap, which may be on a different line, + // or even a different inlined functions. + // + // TODO(prattmic): The runtime applies the same trap + // behavior for other "injected calls", see injectCall + // in runtime.(*unwinder).next. Do we want to handle + // those as well? I don't believe we'd ever see + // runtime.asyncPreempt or runtime.debugCallV2 in a + // typical crash. + if prevSymbol == "runtime.sigpanic" { + pc++ + } + + pcs = append(pcs, uintptr(pc)) + + // Done with this frame. Next line is a new frame. + prevSymbol = currSymbol + currSymbol = "" + symLine = true + } + } + return pcs, nil +} + +func min(x, y int) int { + if x < y { + return x + } else { + return y + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap.go b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap.go new file mode 100644 index 00000000..2febe3ec --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package is a lightly modified version of the mmap code +// in github.com/google/codesearch/index. + +// The mmap package provides an abstraction for memory mapping files +// on different platforms. +package mmap + +import ( + "os" +) + +// The backing file is never closed, so Data +// remains valid for the lifetime of the process. +type Data struct { + // TODO(pjw): might be better to define versions of Data + // for the 3 specializations + f *os.File + Data []byte + // Some windows magic + Windows interface{} +} + +// Mmap maps the given file into memory. +// When remapping a file, pass the most recently returned Data. +func Mmap(f *os.File) (*Data, error) { + return mmapFile(f) +} + +// Munmap unmaps the given file from memory. +func Munmap(d *Data) error { + return munmapFile(d) +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go new file mode 100644 index 00000000..610ab1a1 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go @@ -0,0 +1,25 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || wasip1 || plan9 + +package mmap + +import ( + "io" + "os" +) + +// mmapFile on other systems doesn't mmap the file. It just reads everything. +func mmapFile(f *os.File) (*Data, error) { + b, err := io.ReadAll(f) + if err != nil { + return nil, err + } + return &Data{f, b, nil}, nil +} + +func munmapFile(_ *Data) error { + return nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go new file mode 100644 index 00000000..72ad91d5 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go @@ -0,0 +1,47 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix + +package mmap + +import ( + "fmt" + "io/fs" + "os" + "syscall" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + pagesize := int64(os.Getpagesize()) + if int64(int(size+(pagesize-1))) != size+(pagesize-1) { + return nil, fmt.Errorf("%s: too large for mmap", f.Name()) + } + n := int(size) + if n == 0 { + return &Data{f, nil, nil}, nil + } + mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size + data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} + } + return &Data{f, data[:n], nil}, nil +} + +func munmapFile(d *Data) error { + if len(d.Data) == 0 { + return nil + } + err := syscall.Munmap(d.Data) + if err != nil { + return &fs.PathError{Op: "munmap", Path: d.f.Name(), Err: err} + } + return nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go new file mode 100644 index 00000000..2e8dfbea --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go @@ -0,0 +1,52 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mmap + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + if size == 0 { + return &Data{f, nil, nil}, nil + } + // set the min and max sizes to zero to map the whole file, as described in + // https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object#file-mapping-size + h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, syscall.PAGE_READWRITE, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) + } + // the mapping extends from zero to the end of the file mapping + // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile + addr, err := windows.MapViewOfFile(h, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, 0) + if err != nil { + return nil, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) + } + // Note: previously, we called windows.VirtualQuery here to get the exact + // size of the memory mapped region, but VirtualQuery reported sizes smaller + // than the actual file size (hypothesis: VirtualQuery only reports pages in + // a certain state, and newly written pages may not be counted). + return &Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil +} + +func munmapFile(d *Data) error { + err := windows.UnmapViewOfFile(uintptr(unsafe.Pointer(&d.Data[0]))) + x, ok := d.Windows.(windows.Handle) + if ok { + windows.CloseHandle(x) + } + d.f.Close() + return err +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go new file mode 100644 index 00000000..71953018 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// TODO(rfindley): replace uses of DateOnly with time.DateOnly once we no +// longer support building gopls with go 1.19. +const DateOnly = "2006-01-02" diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dir.go b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dir.go new file mode 100644 index 00000000..0673be56 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/dir.go @@ -0,0 +1,163 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package telemetry manages the telemetry mode file. +package telemetry + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +// Default is the default directory containing Go telemetry configuration and +// data. +// +// If Default is uninitialized, Default.Mode will be "off". As a consequence, +// no data should be written to the directory, and so the path values of +// LocalDir, UploadDir, etc. must not matter. +// +// Default is a global for convenience and testing, but should not be mutated +// outside of tests. +// +// TODO(rfindley): it would be nice to completely eliminate this global state, +// or at least push it in the golang.org/x/telemetry package +var Default Dir + +// A Dir holds paths to telemetry data inside a directory. +type Dir struct { + dir, local, upload, debug, modefile string +} + +// NewDir creates a new Dir encapsulating paths in the given dir. +// +// NewDir does not create any new directories or files--it merely encapsulates +// the telemetry directory layout. +func NewDir(dir string) Dir { + return Dir{ + dir: dir, + local: filepath.Join(dir, "local"), + upload: filepath.Join(dir, "upload"), + debug: filepath.Join(dir, "debug"), + modefile: filepath.Join(dir, "mode"), + } +} + +func init() { + cfgDir, err := os.UserConfigDir() + if err != nil { + return + } + Default = NewDir(filepath.Join(cfgDir, "go", "telemetry")) +} + +func (d Dir) Dir() string { + return d.dir +} + +func (d Dir) LocalDir() string { + return d.local +} + +func (d Dir) UploadDir() string { + return d.upload +} + +func (d Dir) DebugDir() string { + return d.debug +} + +func (d Dir) ModeFile() string { + return d.modefile +} + +// SetMode updates the telemetry mode with the given mode. +// Acceptable values for mode are "on", "off", or "local". +// +// SetMode always writes the mode file, and explicitly records the date at +// which the modefile was updated. This means that calling SetMode with "on" +// effectively resets the timeout before the next telemetry report is uploaded. +func (d Dir) SetMode(mode string) error { + return d.SetModeAsOf(mode, time.Now()) +} + +// SetModeAsOf is like SetMode, but accepts an explicit time to use to +// back-date the mode state. This exists only for testing purposes. +func (d Dir) SetModeAsOf(mode string, asofTime time.Time) error { + mode = strings.TrimSpace(mode) + switch mode { + case "on", "off", "local": + default: + return fmt.Errorf("invalid telemetry mode: %q", mode) + } + if d.modefile == "" { + return fmt.Errorf("cannot determine telemetry mode file name") + } + // TODO(rfindley): why is this not 777, consistent with the use of 666 below? + if err := os.MkdirAll(filepath.Dir(d.modefile), 0755); err != nil { + return fmt.Errorf("cannot create a telemetry mode file: %w", err) + } + + asof := asofTime.UTC().Format(DateOnly) + // Defensively guarantee that we can parse the asof time. + if _, err := time.Parse(DateOnly, asof); err != nil { + return fmt.Errorf("internal error: invalid mode date %q: %v", asof, err) + } + + data := []byte(mode + " " + asof) + return os.WriteFile(d.modefile, data, 0666) +} + +// Mode returns the current telemetry mode, as well as the time that the mode +// was effective. +// +// If there is no effective time, the second result is the zero time. +// +// If Mode is "off", no data should be written to the telemetry directory, and +// the other paths values referenced by Dir should be considered undefined. +// This accounts for the case where initializing [Default] fails, and therefore +// local telemetry paths are unknown. +func (d Dir) Mode() (string, time.Time) { + if d.modefile == "" { + return "off", time.Time{} // it's likely LocalDir/UploadDir are empty too. Turn off telemetry. + } + data, err := os.ReadFile(d.modefile) + if err != nil { + return "local", time.Time{} // default + } + mode := string(data) + mode = strings.TrimSpace(mode) + + // Forward compatibility for https://go.dev/issue/63142#issuecomment-1734025130 + // + // If the modefile contains a date, return it. + if idx := strings.Index(mode, " "); idx >= 0 { + d, err := time.Parse(DateOnly, mode[idx+1:]) + if err != nil { + d = time.Time{} + } + return mode[:idx], d + } + + return mode, time.Time{} +} + +// DisabledOnPlatform indicates whether telemetry is disabled +// due to bugs in the current platform. +// +// TODO(rfindley): move to a more appropriate file. +const DisabledOnPlatform = false || + // The following platforms could potentially be supported in the future: + runtime.GOOS == "openbsd" || // #60614 + runtime.GOOS == "solaris" || // #60968 #60970 + runtime.GOOS == "android" || // #60967 + runtime.GOOS == "illumos" || // #65544 + // These platforms fundamentally can't be supported: + runtime.GOOS == "js" || // #60971 + runtime.GOOS == "wasip1" || // #60971 + runtime.GOOS == "plan9" || // https://github.com/golang/go/issues/57540#issuecomment-1470766639 + runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" // mips lacks cross-process 64-bit atomics diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go new file mode 100644 index 00000000..5ff7d34f --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -0,0 +1,57 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "go/version" + "os" + "path/filepath" + "runtime/debug" + "strings" +) + +// IsToolchainProgram reports whether a program with the given path is a Go +// toolchain program. +func IsToolchainProgram(progPath string) bool { + return strings.HasPrefix(progPath, "cmd/") +} + +// ProgramInfo extracts the go version, program package path, and program +// version to use for counter files. +// +// For programs in the Go toolchain, the program version will be the same as +// the Go version, and will typically be of the form "go1.2.3", not a semantic +// version of the form "v1.2.3". Go versions may also include spaces and +// special characters. +func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { + goVers = info.GoVersion + if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") || !version.IsValid(goVers) { + goVers = "devel" + } + + progPath = info.Path + if progPath == "" { + progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + + // Main module version information is not populated for the cmd module, but + // we can re-use the Go version here. + if IsToolchainProgram(progPath) { + progVers = goVers + } else { + progVers = info.Main.Version + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). + progVers = "devel" + } + } + + return goVers, progPath, progVers +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/types.go b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/types.go new file mode 100644 index 00000000..0fd61f8d --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/telemetry/types.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig struct { + GOOS []string + GOARCH []string + GoVersion []string + SampleRate float64 + Programs []*ProgramConfig +} + +type ProgramConfig struct { + // the counter names may have to be + // repeated for each program. (e.g., if the counters are in a package + // that is used in more than one program.) + Name string + Versions []string // versions present in a counterconfig + Counters []CounterConfig `json:",omitempty"` + Stacks []CounterConfig `json:",omitempty"` +} + +type CounterConfig struct { + Name string // The "collapsed" counter: :{,,...} + Rate float64 // If X <= Rate, report this counter + Depth int `json:",omitempty"` // for stack counters +} + +// A Report is the weekly aggregate of counters. +type Report struct { + Week string // End day this report covers (YYYY-MM-DD) + LastWeek string // Week field from latest previous report uploaded + X float64 // A random probability used to determine which counters are uploaded + Programs []*ProgramReport + Config string // version of UploadConfig used +} + +type ProgramReport struct { + Program string // Package path of the program. + Version string // Program version. Go version if the program is part of the go distribution. Module version, otherwise. + GoVersion string // Go version used to build the program. + GOOS string + GOARCH string + Counters map[string]int64 + Stacks map[string]int64 +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/Doc.txt b/event-processor/vendor/golang.org/x/telemetry/internal/upload/Doc.txt new file mode 100644 index 00000000..45601e65 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/Doc.txt @@ -0,0 +1,45 @@ +The upload process converts count files into reports, and +uploads reports. There will be only one report, named YYYY-MM-DD.json, +for a given day. + +First phase. Look at the localdir (os.UserConfigdir()/go/telemetry/local) +and find all .count and .json files. Find the count files that are no +longer active by looking at their metadata. + +Second phase. Group the inactive count files by their expiry date, and +for each date generate the local report and the upload report. (The upload +report only contains the counters in the upload configuration.) The upload +report is saved in the local directory with a name like YYYY-MM-DD.json, if +there is no file already existing with that name. +If the local report is different, it is saved in the local directory +with a name like local.YYYY-MM-DD.json. The new upload report is +added to the list of .json files from the first phase. At this point +the count files are no longer needed and can be deleted. + +Third phase. Look at the .json files in the list from the first phase. +If the name starts with local, skip it. If there is a file with the +identical name in the upload directory, remove the one in the local directory. +Otherwise try to upload the one in the local directory, +If the upload succeeds, move the file to the uploaded directory. + + +There are various error conditions. +1. Several processes could look at localdir and see work to do. +1A. They could see different sets of expired count files for some day. + This could happen if another process is removing count files. In this + case there is already a YYYY-MM-DD.json file either in localdir + or updatedir, so the process seeing fewer count files will not generate + a report. +1B. They could see the same count files, and no report in either directory. + They will both generate (in memory) reports and check to see if there + is a YYYY-MM-DD.json file in either directory. They could both then + write two files with the same name, but different X values, but + otherwise the same contents. The X values are very close to the front + of the file. Assuming reasonable file system semantics one version of + the file will be written. To minimize this, just before writing reports + the code checks again to see if they exist. +1C. Once there is an existing well-formed file YYYY-MM-DD.json in localdir + eventually the upload will succeed, and the file will be moved to updatedir. + It is possible that other processes will not see the file in updatedir and + upload it again and also move it to uploaddir. This is harmless as all + the uploaded files are identical. diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/date.go b/event-processor/vendor/golang.org/x/telemetry/internal/upload/date.go new file mode 100644 index 00000000..d6d67a16 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/date.go @@ -0,0 +1,85 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "os" + "sync" + "time" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// time and date handling + +var distantPast = 21 * 24 * time.Hour + +// reports that are too old (21 days) are not uploaded +func (u *uploader) tooOld(date string, uploadStartTime time.Time) bool { + t, err := time.Parse(telemetry.DateOnly, date) + if err != nil { + u.logger.Printf("tooOld: %v", err) + return false + } + age := uploadStartTime.Sub(t) + return age > distantPast +} + +// counterDateSpan parses the counter file named fname and returns the (begin, +// end) span recorded in its metadata, or an error if this data could not be +// extracted. +func (u *uploader) counterDateSpan(fname string) (begin, end time.Time, _ error) { + parsed, err := u.parseCountFile(fname) + if err != nil { + return time.Time{}, time.Time{}, err + } + timeBegin, ok := parsed.Meta["TimeBegin"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeBegin") + } + begin, err = time.Parse(time.RFC3339, timeBegin) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeBegin: %v", err) + } + timeEnd, ok := parsed.Meta["TimeEnd"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeEnd") + } + end, err = time.Parse(time.RFC3339, timeEnd) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeEnd: %v", err) + } + return begin, end, nil +} + +// avoid parsing count files multiple times +type parsedCache struct { + mu sync.Mutex + m map[string]*counter.File +} + +func (u *uploader) parseCountFile(fname string) (*counter.File, error) { + u.cache.mu.Lock() + defer u.cache.mu.Unlock() + if u.cache.m == nil { + u.cache.m = make(map[string]*counter.File) + } + if f, ok := u.cache.m[fname]; ok { + return f, nil + } + buf, err := os.ReadFile(fname) + if err != nil { + return nil, fmt.Errorf("parse ReadFile: %v for %s", err, fname) + } + f, err := counter.Parse(fname, buf) + if err != nil { + + return nil, fmt.Errorf("parse Parse: %v for %s", err, fname) + } + u.cache.m[fname] = f + return f, nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/findwork.go b/event-processor/vendor/golang.org/x/telemetry/internal/upload/findwork.go new file mode 100644 index 00000000..2b165be3 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/findwork.go @@ -0,0 +1,102 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "os" + "path/filepath" + "strings" +) + +// files to handle +type work struct { + // absolute file names + countfiles []string // count files to process + readyfiles []string // old reports to upload + // relative names + uploaded map[string]bool // reports that have been uploaded +} + +// find all the files that look like counter files or reports +// that need to be uploaded. (There may be unexpected leftover files +// and uploading is supposed to be idempotent.) +func (u *uploader) findWork() work { + localdir, uploaddir := u.dir.LocalDir(), u.dir.UploadDir() + var ans work + fis, err := os.ReadDir(localdir) + if err != nil { + u.logger.Printf("Could not find work: failed to read local dir %s: %v", localdir, err) + return ans + } + + mode, asof := u.dir.Mode() + u.logger.Printf("Finding work: mode %s asof %s", mode, asof) + + // count files end in .v1.count + // reports end in .json. If they are not to be uploaded they + // start with local. + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".v1.count") { + fname := filepath.Join(localdir, fi.Name()) + _, expiry, err := u.counterDateSpan(fname) + switch { + case err != nil: + u.logger.Printf("Error reading expiry for count file %s: %v", fi.Name(), err) + case expiry.After(u.startTime): + u.logger.Printf("Skipping count file %s: still active", fi.Name()) + default: + u.logger.Printf("Collecting count file %s", fi.Name()) + ans.countfiles = append(ans.countfiles, fname) + } + } else if strings.HasPrefix(fi.Name(), "local.") { + // skip + } else if strings.HasSuffix(fi.Name(), ".json") && mode == "on" { + // Collect reports that are ready for upload. + reportDate := u.uploadReportDate(fi.Name()) + if !asof.IsZero() && !reportDate.IsZero() { + // If both the mode asof date and the report date are present, do the + // right thing... + // + // (see https://github.com/golang/go/issues/63142#issuecomment-1734025130) + if asof.Before(reportDate) { + // Note: since this report was created after telemetry was enabled, + // we can only assume that the process that created it checked that + // the counter data contained therein was all from after the asof + // date. + // + // TODO(rfindley): store the begin date in reports, so that we can + // verify this assumption. + u.logger.Printf("Uploadable: %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } else { + // ...otherwise fall back on the old behavior of uploading all + // unuploaded files. + // + // TODO(rfindley): invert this logic following more testing. We + // should only upload if we know both the asof date and the report + // date, and they are acceptable. + u.logger.Printf("Uploadable (missing date): %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } + } + + fis, err = os.ReadDir(uploaddir) + if err != nil { + os.MkdirAll(uploaddir, 0777) + return ans + } + // There should be only one of these per day; maybe sometime + // we'll want to clean the directory. + ans.uploaded = make(map[string]bool) + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".json") { + u.logger.Printf("Already uploaded: %s", fi.Name()) + ans.uploaded[fi.Name()] = true + } + } + return ans +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/reports.go b/event-processor/vendor/golang.org/x/telemetry/internal/upload/reports.go new file mode 100644 index 00000000..34bb29d8 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/reports.go @@ -0,0 +1,344 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "crypto/rand" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/telemetry/internal/config" + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// reports generates reports from inactive count files +func (u *uploader) reports(todo *work) ([]string, error) { + if mode, _ := u.dir.Mode(); mode == "off" { + return nil, nil // no reports + } + thisInstant := u.startTime + today := thisInstant.Format(telemetry.DateOnly) + lastWeek := latestReport(todo.uploaded) + if lastWeek >= today { //should never happen + lastWeek = "" + } + u.logger.Printf("Last week: %s, today: %s", lastWeek, today) + countFiles := make(map[string][]string) // expiry date string->filenames + earliest := make(map[string]time.Time) // earliest begin time for any counter + for _, f := range todo.countfiles { + begin, end, err := u.counterDateSpan(f) + if err != nil { + // This shouldn't happen: we should have already skipped count files that + // don't contain valid start or end times. + u.logger.Printf("BUG: failed to parse expiry for collected count file: %v", err) + continue + } + + if end.Before(thisInstant) { + expiry := end.Format(dateFormat) + countFiles[expiry] = append(countFiles[expiry], f) + if earliest[expiry].IsZero() || earliest[expiry].After(begin) { + earliest[expiry] = begin + } + } + } + for expiry, files := range countFiles { + if notNeeded(expiry, *todo) { + u.logger.Printf("Files for %s not needed, deleting %v", expiry, files) + // The report already exists. + // There's another check in createReport. + u.deleteFiles(files) + continue + } + fname, err := u.createReport(earliest[expiry], expiry, files, lastWeek) + if err != nil { + u.logger.Printf("Failed to create report for %s: %v", expiry, err) + continue + } + if fname != "" { + u.logger.Printf("Ready to upload: %s", filepath.Base(fname)) + todo.readyfiles = append(todo.readyfiles, fname) + } + } + return todo.readyfiles, nil +} + +// latestReport returns the YYYY-MM-DD of the last report uploaded +// or the empty string if there are no reports. +func latestReport(uploaded map[string]bool) string { + var latest string + for name := range uploaded { + if strings.HasSuffix(name, ".json") { + if name > latest { + latest = name + } + } + } + if latest == "" { + return "" + } + // strip off the .json + return latest[:len(latest)-len(".json")] +} + +// notNeeded returns true if the report for date has already been created +func notNeeded(date string, todo work) bool { + if todo.uploaded != nil && todo.uploaded[date+".json"] { + return true + } + // maybe the report is already in todo.readyfiles + for _, f := range todo.readyfiles { + if strings.Contains(f, date) { + return true + } + } + return false +} + +func (u *uploader) deleteFiles(files []string) { + for _, f := range files { + if err := os.Remove(f); err != nil { + // this could be a race condition. + // conversely, on Windows, err may be nil and + // the file not deleted if anyone has it open. + u.logger.Printf("%v failed to remove %s", err, f) + } + } +} + +// createReport creates local and upload report files by +// combining all the count files for the expiryDate, and +// returns the upload report file's path. +// It may delete the count files once local and upload report +// files are successfully created. +func (u *uploader) createReport(start time.Time, expiryDate string, countFiles []string, lastWeek string) (string, error) { + uploadOK := true + mode, asof := u.dir.Mode() + if mode != "on" { + u.logger.Printf("No upload config or mode %q is not 'on'", mode) + uploadOK = false // no config, nothing to upload + } + if u.tooOld(expiryDate, u.startTime) { + u.logger.Printf("Expiry date %s is too old", expiryDate) + uploadOK = false + } + // If the mode is recorded with an asof date, don't upload if the report + // includes any data on or before the asof date. + if !asof.IsZero() && !asof.Before(start) { + u.logger.Printf("As-of date %s is not before start %s", asof, start) + uploadOK = false + } + // TODO(rfindley): check that all the x.Meta are consistent for GOOS, GOARCH, etc. + report := &telemetry.Report{ + Config: u.configVersion, + X: computeRandom(), // json encodes all the bits + Week: expiryDate, + LastWeek: lastWeek, + } + if report.X > u.config.SampleRate && u.config.SampleRate > 0 { + u.logger.Printf("X: %f > SampleRate:%f, not uploadable", report.X, u.config.SampleRate) + uploadOK = false + } + var succeeded bool + for _, f := range countFiles { + fok := false + x, err := u.parseCountFile(f) + if err != nil { + u.logger.Printf("Unparseable count file %s: %v", filepath.Base(f), err) + continue + } + prog := findProgReport(x.Meta, report) + for k, v := range x.Count { + if counter.IsStackCounter(k) { + // stack + prog.Stacks[k] += int64(v) + } else { + // counter + prog.Counters[k] += int64(v) + } + succeeded = true + fok = true + } + if !fok { + u.logger.Printf("no counters found in %s", f) + } + } + if !succeeded { + return "", fmt.Errorf("none of the %d count files for %s contained counters", len(countFiles), expiryDate) + } + // 1. generate the local report + localContents, err := json.MarshalIndent(report, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal report for %s: %v", expiryDate, err) + } + // check that the report can be read back + // TODO(pjw): remove for production? + var report2 telemetry.Report + if err := json.Unmarshal(localContents, &report2); err != nil { + return "", fmt.Errorf("failed to unmarshal local report for %s: %v", expiryDate, err) + } + + var uploadContents []byte + if uploadOK { + // 2. create the uploadable version + cfg := config.NewConfig(u.config) + upload := &telemetry.Report{ + Week: report.Week, + LastWeek: report.LastWeek, + X: report.X, + Config: report.Config, + } + for _, p := range report.Programs { + // does the uploadConfig want this program? + // if so, copy over the Stacks and Counters + // that the uploadConfig mentions. + if !cfg.HasGoVersion(p.GoVersion) || !cfg.HasProgram(p.Program) || !cfg.HasVersion(p.Program, p.Version) { + continue + } + x := &telemetry.ProgramReport{ + Program: p.Program, + Version: p.Version, + GOOS: p.GOOS, + GOARCH: p.GOARCH, + GoVersion: p.GoVersion, + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + upload.Programs = append(upload.Programs, x) + for k, v := range p.Counters { + if cfg.HasCounter(p.Program, k) && report.X <= cfg.Rate(p.Program, k) { + x.Counters[k] = v + } + } + // and the same for Stacks + // this can be made more efficient, when it matters + for k, v := range p.Stacks { + before, _, _ := strings.Cut(k, "\n") + if cfg.HasStack(p.Program, before) && report.X <= cfg.Rate(p.Program, before) { + x.Stacks[k] = v + } + } + } + + uploadContents, err = json.MarshalIndent(upload, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal upload report for %s: %v", expiryDate, err) + } + } + localFileName := filepath.Join(u.dir.LocalDir(), "local."+expiryDate+".json") + uploadFileName := filepath.Join(u.dir.LocalDir(), expiryDate+".json") + + /* Prepare to write files */ + // if either file exists, someone has been here ahead of us + // (there is still a race, but this check shortens the open window) + if _, err := os.Stat(localFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("local report %s already exists", localFileName) + } + if _, err := os.Stat(uploadFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("report %s already exists", uploadFileName) + } + // write the uploadable file + var errUpload, errLocal error + if uploadOK { + _, errUpload = exclusiveWrite(uploadFileName, uploadContents) + } + // write the local file + _, errLocal = exclusiveWrite(localFileName, localContents) + /* Wrote the files */ + + // even though these errors won't occur, what should happen + // if errUpload == nil and it is ok to upload, and errLocal != nil? + if errLocal != nil { + return "", fmt.Errorf("failed to write local file %s (%v)", localFileName, errLocal) + } + if errUpload != nil { + return "", fmt.Errorf("failed to write upload file %s (%v)", uploadFileName, errUpload) + } + u.logger.Printf("Created %s, deleting %d count files", filepath.Base(uploadFileName), len(countFiles)) + u.deleteFiles(countFiles) + if uploadOK { + return uploadFileName, nil + } + return "", nil +} + +// exclusiveWrite attempts to create filename exclusively, and if successful, +// writes content to the resulting file handle. +// +// It returns a boolean indicating whether the exclusive handle was acquired, +// and an error indicating whether the operation succeeded. +// If the file already exists, exclusiveWrite returns (false, nil). +func exclusiveWrite(filename string, content []byte) (_ bool, rerr error) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + if os.IsExist(err) { + return false, nil + } + return false, err + } + defer func() { + if err := f.Close(); err != nil && rerr == nil { + rerr = err + } + }() + if _, err := f.Write(content); err != nil { + return false, err + } + return true, nil +} + +// return an existing ProgremReport, or create anew +func findProgReport(meta map[string]string, report *telemetry.Report) *telemetry.ProgramReport { + for _, prog := range report.Programs { + if prog.Program == meta["Program"] && prog.Version == meta["Version"] && + prog.GoVersion == meta["GoVersion"] && prog.GOOS == meta["GOOS"] && + prog.GOARCH == meta["GOARCH"] { + return prog + } + } + prog := telemetry.ProgramReport{ + Program: meta["Program"], + Version: meta["Version"], + GoVersion: meta["GoVersion"], + GOOS: meta["GOOS"], + GOARCH: meta["GOARCH"], + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + report.Programs = append(report.Programs, &prog) + return &prog +} + +// computeRandom returns a cryptographic random float64 in the range [0, 1], +// with 52 bits of precision. +func computeRandom() float64 { + for { + b := make([]byte, 8) + _, err := rand.Read(b) + if err != nil { + panic(fmt.Sprintf("rand.Read failed: %v", err)) + } + // and turn it into a float64 + x := math.Float64frombits(binary.LittleEndian.Uint64(b)) + if math.IsNaN(x) || math.IsInf(x, 0) { + continue + } + x = math.Abs(x) + if x < 0x1p-1000 { // avoid underflow patterns + continue + } + frac, _ := math.Frexp(x) // 52 bits of randomness + return frac*2 - 1 + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/run.go b/event-processor/vendor/golang.org/x/telemetry/internal/upload/run.go new file mode 100644 index 00000000..e9c8dc20 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/run.go @@ -0,0 +1,226 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "io" + "log" + "os" + "path" + "path/filepath" + "runtime/debug" + "strings" + "time" + + "golang.org/x/telemetry/internal/configstore" + "golang.org/x/telemetry/internal/telemetry" +) + +// RunConfig configures non-default behavior of a call to Run. +// +// All fields are optional, for testing or observability. +type RunConfig struct { + TelemetryDir string // if set, overrides the telemetry data directory + UploadURL string // if set, overrides the telemetry upload endpoint + LogWriter io.Writer // if set, used for detailed logging of the upload process + Env []string // if set, appended to the config download environment + StartTime time.Time // if set, overrides the upload start time +} + +// Run generates and uploads reports, as allowed by the mode file. +func Run(config RunConfig) error { + defer func() { + if err := recover(); err != nil { + log.Printf("upload recover: %v", err) + } + }() + uploader, err := newUploader(config) + if err != nil { + return err + } + defer uploader.Close() + return uploader.Run() +} + +// uploader encapsulates a single upload operation, carrying parameters and +// shared state. +type uploader struct { + // config is used to select counters to upload. + config *telemetry.UploadConfig // + configVersion string // version of the config + dir telemetry.Dir // the telemetry dir to process + + uploadServerURL string + startTime time.Time + + cache parsedCache + + logFile *os.File + logger *log.Logger +} + +// newUploader creates a new uploader to use for running the upload for the +// given config. +// +// Uploaders should only be used for one call to [uploader.Run]. +func newUploader(rcfg RunConfig) (*uploader, error) { + // Determine the upload directory. + var dir telemetry.Dir + if rcfg.TelemetryDir != "" { + dir = telemetry.NewDir(rcfg.TelemetryDir) + } else { + dir = telemetry.Default + } + + // Determine the upload URL. + uploadURL := rcfg.UploadURL + if uploadURL == "" { + uploadURL = "https://telemetry.go.dev/upload" + } + + // Determine the upload logger. + // + // This depends on the provided rcfg.LogWriter and the presence of + // dir.DebugDir, as follows: + // 1. If LogWriter is present, log to it. + // 2. If DebugDir is present, log to a file within it. + // 3. If both LogWriter and DebugDir are present, log to a multi writer. + // 4. If neither LogWriter nor DebugDir are present, log to a noop logger. + var logWriters []io.Writer + logFile, err := debugLogFile(dir.DebugDir()) + if err != nil { + logFile = nil + } + if logFile != nil { + logWriters = append(logWriters, logFile) + } + if rcfg.LogWriter != nil { + logWriters = append(logWriters, rcfg.LogWriter) + } + var logWriter io.Writer + switch len(logWriters) { + case 0: + logWriter = io.Discard + case 1: + logWriter = logWriters[0] + default: + logWriter = io.MultiWriter(logWriters...) + } + logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile) + + // Fetch the upload config, if it is not provided. + var ( + config *telemetry.UploadConfig + configVersion string + ) + + if mode, _ := dir.Mode(); mode == "on" { + // golang/go#68946: only download the upload config if it will be used. + // + // TODO(rfindley): This is a narrow change aimed at minimally fixing the + // associated bug. In the future, we should read the mode only once during + // the upload process. + config, configVersion, err = configstore.Download("latest", rcfg.Env) + if err != nil { + return nil, err + } + } else { + config = &telemetry.UploadConfig{} + configVersion = "v0.0.0-0" + } + + // Set the start time, if it is not provided. + startTime := time.Now().UTC() + if !rcfg.StartTime.IsZero() { + startTime = rcfg.StartTime + } + + return &uploader{ + config: config, + configVersion: configVersion, + dir: dir, + uploadServerURL: uploadURL, + startTime: startTime, + + logFile: logFile, + logger: logger, + }, nil +} + +// Close cleans up any resources associated with the uploader. +func (u *uploader) Close() error { + if u.logFile == nil { + return nil + } + return u.logFile.Close() +} + +// Run generates and uploads reports +func (u *uploader) Run() error { + if telemetry.DisabledOnPlatform { + return nil + } + todo := u.findWork() + ready, err := u.reports(&todo) + if err != nil { + u.logger.Printf("Error building reports: %v", err) + return fmt.Errorf("reports failed: %v", err) + } + u.logger.Printf("Uploading %d reports", len(ready)) + for _, f := range ready { + u.uploadReport(f) + } + return nil +} + +// debugLogFile arranges to write a log file in the given debug directory, if +// it exists. +func debugLogFile(debugDir string) (*os.File, error) { + fd, err := os.Stat(debugDir) + if os.IsNotExist(err) { + return nil, nil + } + if err != nil { + return nil, err + } + if !fd.IsDir() { + return nil, fmt.Errorf("debug path %q is not a directory", debugDir) + } + info, ok := debug.ReadBuildInfo() + if !ok { + return nil, fmt.Errorf("no build info") + } + year, month, day := time.Now().UTC().Date() + goVers := info.GoVersion + // E.g., goVers:"go1.22-20240109-RC01 cl/597041403 +dcbe772469 X:loopvar" + words := strings.Fields(goVers) + goVers = words[0] + progPkgPath := info.Path + if progPkgPath == "" { + progPkgPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + prog := path.Base(progPkgPath) + progVers := info.Main.Version + if progVers == "(devel)" { // avoid special characters in created file names + progVers = "devel" + } + logBase := strings.ReplaceAll( + fmt.Sprintf("%s-%s-%s-%4d%02d%02d-%d.log", prog, progVers, goVers, year, month, day, os.Getpid()), + " ", "") + fname := filepath.Join(debugDir, logBase) + if _, err := os.Stat(fname); err == nil { + // This process previously called upload.Run + return nil, nil + } + f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return nil, nil // this process previously called upload.Run + } + return nil, err + } + return f, nil +} diff --git a/event-processor/vendor/golang.org/x/telemetry/internal/upload/upload.go b/event-processor/vendor/golang.org/x/telemetry/internal/upload/upload.go new file mode 100644 index 00000000..419745f6 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/internal/upload/upload.go @@ -0,0 +1,117 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "bytes" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "golang.org/x/telemetry/internal/telemetry" +) + +var ( + dateRE = regexp.MustCompile(`(\d\d\d\d-\d\d-\d\d)[.]json$`) + dateFormat = telemetry.DateOnly + // TODO(rfindley): use dateFormat throughout. +) + +// uploadReportDate returns the date component of the upload file name, or "" if the +// date was unmatched. +func (u *uploader) uploadReportDate(fname string) time.Time { + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("malformed report name: missing date: %q", filepath.Base(fname)) + return time.Time{} + } + d, err := time.Parse(dateFormat, match[1]) + if err != nil { + u.logger.Printf("malformed report name: bad date: %q", filepath.Base(fname)) + return time.Time{} + } + return d +} + +func (u *uploader) uploadReport(fname string) { + thisInstant := u.startTime + // TODO(rfindley): use uploadReportDate here, once we've done a gopls release. + + // first make sure it is not in the future + today := thisInstant.Format(telemetry.DateOnly) + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("Report name %q missing date", filepath.Base(fname)) + } else if match[1] > today { + u.logger.Printf("Report date for %q is later than today (%s)", filepath.Base(fname), today) + return // report is in the future, which shouldn't happen + } + buf, err := os.ReadFile(fname) + if err != nil { + u.logger.Printf("%v reading %s", err, fname) + return + } + if u.uploadReportContents(fname, buf) { + // anything left to do? + } +} + +// try to upload the report, 'true' if successful +func (u *uploader) uploadReportContents(fname string, buf []byte) bool { + fdate := strings.TrimSuffix(filepath.Base(fname), ".json") + fdate = fdate[len(fdate)-len(telemetry.DateOnly):] + + newname := filepath.Join(u.dir.UploadDir(), fdate+".json") + + // Lock the upload, to prevent duplicate uploads. + { + lockname := newname + ".lock" + lockfile, err := os.OpenFile(lockname, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + u.logger.Printf("Failed to acquire lock %s: %v", lockname, err) + return false + } + _ = lockfile.Close() + defer os.Remove(lockname) + } + + if _, err := os.Stat(newname); err == nil { + // Another process uploaded but failed to clean up (or hasn't yet cleaned + // up). Ensure that cleanup occurs. + u.logger.Printf("After acquire: report already uploaded") + _ = os.Remove(fname) + return false + } + + endpoint := u.uploadServerURL + "/" + fdate + b := bytes.NewReader(buf) + resp, err := http.Post(endpoint, "application/json", b) + if err != nil { + u.logger.Printf("Error upload %s to %s: %v", filepath.Base(fname), endpoint, err) + return false + } + // hope for a 200, remove file on a 4xx, otherwise it will be retried by another process + if resp.StatusCode != 200 { + u.logger.Printf("Failed to upload %s to %s: %s", filepath.Base(fname), endpoint, resp.Status) + if resp.StatusCode >= 400 && resp.StatusCode < 500 { + err := os.Remove(fname) + if err == nil { + u.logger.Printf("Removed local/%s", filepath.Base(fname)) + } else { + u.logger.Printf("Error removing local/%s: %v", filepath.Base(fname), err) + } + } + return false + } + // Store a copy of the uploaded report in the uploaded directory. + if err := os.WriteFile(newname, buf, 0644); err == nil { + os.Remove(fname) // if it exists + } + u.logger.Printf("Uploaded %s to %q", fdate+".json", endpoint) + return true +} diff --git a/event-processor/vendor/golang.org/x/telemetry/mode.go b/event-processor/vendor/golang.org/x/telemetry/mode.go new file mode 100644 index 00000000..8cdcd134 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/mode.go @@ -0,0 +1,38 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Mode returns the current telemetry mode. +// +// The telemetry mode is a global value that controls both the local collection +// and uploading of telemetry data. Possible mode values are: +// - "on": both collection and uploading is enabled +// - "local": collection is enabled, but uploading is disabled +// - "off": both collection and uploading are disabled +// +// When mode is "on", or "local", telemetry data is written to the local file +// system and may be inspected with the [gotelemetry] command. +// +// If an error occurs while reading the telemetry mode from the file system, +// Mode returns the default value "local". +// +// [gotelemetry]: https://pkg.go.dev/golang.org/x/telemetry/cmd/gotelemetry +func Mode() string { + mode, _ := telemetry.Default.Mode() + return mode +} + +// SetMode sets the global telemetry mode to the given value. +// +// See the documentation of [Mode] for a description of the supported mode +// values. +// +// An error is returned if the provided mode value is invalid, or if an error +// occurs while persisting the mode value to the file system. +func SetMode(mode string) error { + return telemetry.Default.SetMode(mode) +} diff --git a/event-processor/vendor/golang.org/x/telemetry/npm b/event-processor/vendor/golang.org/x/telemetry/npm new file mode 100644 index 00000000..a5455cfb --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/npm @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npm \ + node:18.16.0-slim \ + $@ diff --git a/event-processor/vendor/golang.org/x/telemetry/npx b/event-processor/vendor/golang.org/x/telemetry/npx new file mode 100644 index 00000000..47bb38bb --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/npx @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npx \ + node:18.16.0-slim \ + $@ diff --git a/event-processor/vendor/golang.org/x/telemetry/package-lock.json b/event-processor/vendor/golang.org/x/telemetry/package-lock.json new file mode 100644 index 00000000..9c86033e --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/package-lock.json @@ -0,0 +1,4363 @@ +{ + "name": "workspace", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.1.1.tgz", + "integrity": "sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz", + "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.4.tgz", + "integrity": "sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@observablehq/plot": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.9.tgz", + "integrity": "sha512-vwV6bzQsGjv2XrPEpc3Voixcz2e5EVvCSzzcs/uW9KXO5ZM8GdMVXtNTaRwYXUOk98nbiYFCFwzMaIyRjrt9IA==", + "dependencies": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz", + "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "dependencies": { + "binary-search-bounds": "^2.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", + "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1", + "@csstools/media-query-list-parser": "^2.0.4", + "@csstools/selector-specificity": "^2.2.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.1.3", + "css-functions-list": "^3.1.0", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.27.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.12", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^12.0.0" + }, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/package.json b/event-processor/vendor/golang.org/x/telemetry/package.json new file mode 100644 index 00000000..3680ce22 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/package.json @@ -0,0 +1,23 @@ +{ + "scripts": { + "eslint": "eslint . --fix", + "stylelint": "stylelint '**/*.css' --fix", + "prettier": "prettier --write **/*.{css,ts,md,yaml} !**/*.min.css", + "all": "run-s --continue-on-error eslint stylelint prettier" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + }, + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/start.go b/event-processor/vendor/golang.org/x/telemetry/start.go new file mode 100644 index 00000000..9c0519a6 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/start.go @@ -0,0 +1,354 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "sync" + "time" + + "golang.org/x/sync/errgroup" + "golang.org/x/telemetry/counter" + "golang.org/x/telemetry/internal/crashmonitor" + "golang.org/x/telemetry/internal/telemetry" + "golang.org/x/telemetry/internal/upload" +) + +// Config controls the behavior of [Start]. +type Config struct { + // ReportCrashes, if set, will enable crash reporting. + // ReportCrashes uses the [debug.SetCrashOutput] mechanism, which is a + // process-wide resource. + // Do not make other calls to that function within your application. + // ReportCrashes is a non-functional unless the program is built with go1.23+. + ReportCrashes bool + + // Upload causes this program to periodically upload approved counters + // from the local telemetry database to telemetry.go.dev. + // + // This option has no effect unless the user has given consent + // to enable data collection, for example by running + // cmd/gotelemetry or affirming the gopls dialog. + // + // (This feature is expected to be used only by gopls. + // Longer term, the go command may become the sole program + // responsible for uploading.) + Upload bool + + // TelemetryDir, if set, will specify an alternate telemetry + // directory to write data to. If not set, it uses the default + // directory. + // This field is intended to be used for isolating testing environments. + TelemetryDir string + + // UploadStartTime, if set, overrides the time used as the upload start time, + // which is the time used by the upload logic to determine whether counter + // file data should be uploaded. Only counter files that have expired before + // the start time are considered for upload. + // + // This field can be used to simulate a future upload that collects recently + // modified counters. + UploadStartTime time.Time + + // UploadURL, if set, overrides the URL used to receive uploaded reports. If + // unset, this URL defaults to https://telemetry.go.dev/upload. + UploadURL string +} + +// Start initializes telemetry using the specified configuration. +// +// Start opens the local telemetry database so that counter increment +// operations are durably recorded in the local file system. +// +// If [Config.Upload] is set, and the user has opted in to telemetry +// uploading, this process may attempt to upload approved counters +// to telemetry.go.dev. +// +// If [Config.ReportCrashes] is set, any fatal crash will be +// recorded by incrementing a counter named for the stack of the +// first running goroutine in the traceback. +// +// If either of these flags is set, Start re-executes the current +// executable as a child process, in a special mode in which it +// acts as a telemetry sidecar for the parent process (the application). +// In that mode, the call to Start will never return, so Start must +// be called immediately within main, even before such things as +// inspecting the command line. The application should avoid expensive +// steps or external side effects in init functions, as they will +// be executed twice (parent and child). +// +// Start returns a StartResult, which may be awaited via [StartResult.Wait] to +// wait for all work done by Start to complete. +func Start(config Config) *StartResult { + switch v := os.Getenv(telemetryChildVar); v { + case "": + // The subprocess started by parent has GO_TELEMETRY_CHILD=1. + return parent(config) + case "1": + child(config) // child will exit the process when it's done. + case "2": + // Do nothing: this was executed directly or indirectly by a child. + default: + log.Fatalf("unexpected value for %q: %q", telemetryChildVar, v) + } + + return &StartResult{} +} + +// MaybeChild executes the telemetry child logic if the calling program is +// the telemetry child process, and does nothing otherwise. It is meant to be +// called as the first thing in a program that uses telemetry.Start but cannot +// call telemetry.Start immediately when it starts. +func MaybeChild(config Config) { + if v := os.Getenv(telemetryChildVar); v == "1" { + child(config) // child will exit the process when it's done. + } + // other values of the telemetryChildVar environment variable + // will be handled by telemetry.Start. +} + +// A StartResult is a handle to the result of a call to [Start]. Call +// [StartResult.Wait] to wait for the completion of all work done on behalf of +// Start. +type StartResult struct { + wg sync.WaitGroup +} + +// Wait waits for the completion of all work initiated by [Start]. +func (res *StartResult) Wait() { + if res == nil { + return + } + res.wg.Wait() +} + +var daemonize = func(cmd *exec.Cmd) {} + +// If telemetryChildVar is set to "1" in the environment, this is the telemetry +// child. +// +// If telemetryChildVar is set to "2", this is a child of the child, and no +// further forking should occur. +const telemetryChildVar = "GO_TELEMETRY_CHILD" + +// If telemetryUploadVar is set to "1" in the environment, the upload token has been +// acquired by the parent, and the child should attempt an upload. +const telemetryUploadVar = "GO_TELEMETRY_CHILD_UPLOAD" + +func parent(config Config) *StartResult { + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + result := new(StartResult) + + mode, _ := telemetry.Default.Mode() + if mode == "off" { + // Telemetry is turned off. Crash reporting doesn't work without telemetry + // at least set to "local". The upload process runs in both "on" and "local" modes. + // In local mode the upload process builds local reports but does not do the upload. + return result + } + + counter.Open() + + if _, err := os.Stat(telemetry.Default.LocalDir()); err != nil { + // There was a problem statting LocalDir, which is needed for both + // crash monitoring and counter uploading. Most likely, there was an + // error creating telemetry.LocalDir in the counter.Open call above. + // Don't start the child. + return result + } + + childShouldUpload := config.Upload && acquireUploadToken() + reportCrashes := config.ReportCrashes + + if reportCrashes || childShouldUpload { + startChild(reportCrashes, childShouldUpload, result) + } + + return result +} + +func startChild(reportCrashes, upload bool, result *StartResult) { + // This process is the application (parent). + // Fork+exec the telemetry child. + exe, err := os.Executable() + if err != nil { + // There was an error getting os.Executable. It's possible + // for this to happen on AIX if os.Args[0] is not an absolute + // path and we can't find os.Args[0] in PATH. + log.Printf("failed to start telemetry sidecar: os.Executable: %v", err) + return + } + cmd := exec.Command(exe, "** telemetry **") // this unused arg is just for ps(1) + daemonize(cmd) + cmd.Env = append(os.Environ(), telemetryChildVar+"=1") + if upload { + cmd.Env = append(cmd.Env, telemetryUploadVar+"=1") + } + cmd.Dir = telemetry.Default.LocalDir() + + // The child process must write to a log file, not + // the stderr file it inherited from the parent, as + // the child may outlive the parent but should not prolong + // the life of any pipes created (by the grandparent) + // to gather the output of the parent. + // + // By default, we discard the child process's stderr, + // but in line with the uploader, log to a file in debug + // only if that directory was created by the user. + fd, err := os.Stat(telemetry.Default.DebugDir()) + if err != nil { + if !os.IsNotExist(err) { + log.Printf("failed to stat debug directory: %v", err) + return + } + } else if fd.IsDir() { + // local/debug exists and is a directory. Set stderr to a log file path + // in local/debug. + childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log") + childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) + if err != nil { + log.Printf("opening sidecar log file for child: %v", err) + return + } + defer childLog.Close() + cmd.Stderr = childLog + } + + var crashOutputFile *os.File + if reportCrashes { + pipe, err := cmd.StdinPipe() + if err != nil { + log.Printf("StdinPipe: %v", err) + return + } + + crashOutputFile = pipe.(*os.File) // (this conversion is safe) + } + + if err := cmd.Start(); err != nil { + // The child couldn't be started. Log the failure. + log.Printf("can't start telemetry child process: %v", err) + return + } + if reportCrashes { + crashmonitor.Parent(crashOutputFile) + } + result.wg.Add(1) + go func() { + cmd.Wait() // Release resources if cmd happens not to outlive this process. + result.wg.Done() + }() +} + +func child(config Config) { + log.SetPrefix(fmt.Sprintf("telemetry-sidecar (pid %v): ", os.Getpid())) + + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + + // golang/go#67211: be sure to set telemetryChildVar before running the + // child, because the child itself invokes the go command to download the + // upload config. If the telemetryChildVar variable is still set to "1", + // that delegated go command may think that it is itself a telemetry + // child. + // + // On the other hand, if telemetryChildVar were simply unset, then the + // delegated go commands would fork themselves recursively. Short-circuit + // this recursion. + os.Setenv(telemetryChildVar, "2") + upload := os.Getenv(telemetryUploadVar) == "1" + + // The crashmonitor and/or upload process may themselves record counters. + counter.Open() + + // Start crashmonitoring and uploading depending on what's requested + // and wait for the longer running child to complete before exiting: + // if we collected a crash before the upload finished, wait for the + // upload to finish before exiting + var g errgroup.Group + + if config.ReportCrashes { + g.Go(func() error { + crashmonitor.Child() + return nil + }) + } + if upload { + g.Go(func() error { + uploaderChild(config.UploadStartTime, config.UploadURL) + return nil + }) + } + g.Wait() + + os.Exit(0) +} + +func uploaderChild(asof time.Time, uploadURL string) { + if err := upload.Run(upload.RunConfig{ + UploadURL: uploadURL, + LogWriter: os.Stderr, + StartTime: asof, + }); err != nil { + log.Printf("upload failed: %v", err) + } +} + +// acquireUploadToken acquires a token permitting the caller to upload. +// To limit the frequency of uploads, only one token is issue per +// machine per time period. +// The boolean indicates whether the token was acquired. +func acquireUploadToken() bool { + if telemetry.Default.LocalDir() == "" { + // The telemetry dir wasn't initialized properly, probably because + // os.UserConfigDir did not complete successfully. In that case + // there are no counters to upload, so we should just do nothing. + return false + } + tokenfile := filepath.Join(telemetry.Default.LocalDir(), "upload.token") + const period = 24 * time.Hour + + // A process acquires a token by successfully creating a + // well-known file. If the file already exists and has an + // mtime age less then than the period, the process does + // not acquire the token. If the file is older than the + // period, the process is allowed to remove the file and + // try to re-create it. + fi, err := os.Stat(tokenfile) + if err == nil { + if time.Since(fi.ModTime()) < period { + return false + } + // There's a possible race here where two processes check the + // token file and see that it's older than the period, then the + // first one removes it and creates another, and then a second one + // removes the newly created file and creates yet another + // file. Then both processes would act as though they had the token. + // This is very rare, but it's also okay because we're only grabbing + // the token to do rate limiting, not for correctness. + _ = os.Remove(tokenfile) + } else if !os.IsNotExist(err) { + log.Printf("error acquiring upload taken: statting token file: %v", err) + return false + } + + f, err := os.OpenFile(tokenfile, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return false + } + log.Printf("error acquiring upload token: creating token file: %v", err) + return false + } + _ = f.Close() + return true +} diff --git a/event-processor/vendor/golang.org/x/telemetry/start_posix.go b/event-processor/vendor/golang.org/x/telemetry/start_posix.go new file mode 100644 index 00000000..078b2353 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/start_posix.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package telemetry + +import ( + "os/exec" + "syscall" +) + +func init() { + daemonize = daemonizePosix +} + +func daemonizePosix(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/start_windows.go b/event-processor/vendor/golang.org/x/telemetry/start_windows.go new file mode 100644 index 00000000..ceb2c029 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/start_windows.go @@ -0,0 +1,29 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package telemetry + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + daemonize = daemonizeWindows +} + +func daemonizeWindows(cmd *exec.Cmd) { + // Set DETACHED_PROCESS creation flag so that closing + // the console window the parent process was run in + // does not kill the child. + // See documentation of creation flags in the Microsoft documentation: + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.DETACHED_PROCESS, + } +} diff --git a/event-processor/vendor/golang.org/x/telemetry/tsconfig.json b/event-processor/vendor/golang.org/x/telemetry/tsconfig.json new file mode 100644 index 00000000..7833e310 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/tsconfig.json @@ -0,0 +1,26 @@ +{ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "node", + + "strict": true, + "allowUnusedLabels": false, + "allowUnreachableCode": false, + "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "checkJs": true, + + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, +} \ No newline at end of file diff --git a/event-processor/vendor/golang.org/x/telemetry/types_alias.go b/event-processor/vendor/golang.org/x/telemetry/types_alias.go new file mode 100644 index 00000000..83ba7e05 --- /dev/null +++ b/event-processor/vendor/golang.org/x/telemetry/types_alias.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig = telemetry.UploadConfig + +type ProgramConfig = telemetry.ProgramConfig + +type CounterConfig = telemetry.CounterConfig + +// A Report is what's uploaded (or saved locally) +type Report = telemetry.Report + +type ProgramReport = telemetry.ProgramReport diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index 436b03cb..1aa7afb9 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -57,7 +57,7 @@ type asmArch struct { // include the first integer register and first floating-point register. Accessing // any of them counts as writing to result. retRegs []string - // writeResult is a list of instructions that will change result register implicity. + // writeResult is a list of instructions that will change result register implicitly. writeResult []string // calculated during initialization sizes types.Sizes diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go index 1413ee13..1914bb47 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go @@ -9,11 +9,11 @@ package assign import ( _ "embed" - "fmt" "go/ast" "go/token" "go/types" "reflect" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -48,31 +48,84 @@ func run(pass *analysis.Pass) (any, error) { // If LHS and RHS have different cardinality, they can't be the same. return } + + // Delete redundant LHS, RHS pairs, taking care + // to include intervening commas. + var ( + exprs []string // expressions appearing on both sides (x = x) + edits []analysis.TextEdit + runStartLHS, runStartRHS token.Pos // non-zero => within a run + ) for i, lhs := range stmt.Lhs { rhs := stmt.Rhs[i] - if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || - analysisutil.HasSideEffects(pass.TypesInfo, rhs) || - isMapIndex(pass.TypesInfo, lhs) { - continue // expressions may not be equal - } - if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { - continue // short-circuit the heavy-weight gofmt check + isSelfAssign := false + var le string + + if !analysisutil.HasSideEffects(pass.TypesInfo, lhs) && + !analysisutil.HasSideEffects(pass.TypesInfo, rhs) && + !isMapIndex(pass.TypesInfo, lhs) && + reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check + + le = analysisinternal.Format(pass.Fset, lhs) + re := analysisinternal.Format(pass.Fset, rhs) + if le == re { + isSelfAssign = true + } } - le := analysisinternal.Format(pass.Fset, lhs) - re := analysisinternal.Format(pass.Fset, rhs) - if le == re { - pass.Report(analysis.Diagnostic{ - Pos: stmt.Pos(), Message: fmt.Sprintf("self-assignment of %s to %s", re, le), - SuggestedFixes: []analysis.SuggestedFix{{ - Message: "Remove self-assignment", - TextEdits: []analysis.TextEdit{{ - Pos: stmt.Pos(), - End: stmt.End(), - }}}, - }, - }) + + if isSelfAssign { + exprs = append(exprs, le) + if !runStartLHS.IsValid() { + // Start of a new run of self-assignments. + if i > 0 { + runStartLHS = stmt.Lhs[i-1].End() + runStartRHS = stmt.Rhs[i-1].End() + } else { + runStartLHS = lhs.Pos() + runStartRHS = rhs.Pos() + } + } + } else if runStartLHS.IsValid() { + // End of a run of self-assignments. + endLHS, endRHS := stmt.Lhs[i-1].End(), stmt.Rhs[i-1].End() + if runStartLHS == stmt.Lhs[0].Pos() { + endLHS, endRHS = lhs.Pos(), rhs.Pos() + } + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: endLHS}, + analysis.TextEdit{Pos: runStartRHS, End: endRHS}, + ) + runStartLHS, runStartRHS = 0, 0 } } + + // If a run of self-assignments continues to the end of the statement, close it. + if runStartLHS.IsValid() { + last := len(stmt.Lhs) - 1 + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: stmt.Lhs[last].End()}, + analysis.TextEdit{Pos: runStartRHS, End: stmt.Rhs[last].End()}, + ) + } + + if len(exprs) == 0 { + return + } + + if len(exprs) == len(stmt.Lhs) { + // If every part of the statement is a self-assignment, + // remove the whole statement. + edits = []analysis.TextEdit{{Pos: stmt.Pos(), End: stmt.End()}} + } + + pass.Report(analysis.Diagnostic{ + Pos: stmt.Pos(), + Message: "self-assignment of " + strings.Join(exprs, ", "), + SuggestedFixes: []analysis.SuggestedFix{{ + Message: "Remove self-assignment", + TextEdits: edits, + }}, + }) }) return nil, nil diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 25c98a97..ed2284e6 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -153,7 +153,8 @@ func isLocalType(pass *analysis.Pass, typ types.Type) bool { return isLocalType(pass, x.Elem()) case interface{ Obj() *types.TypeName }: // *Named or *TypeParam (aliases were removed already) // names in package foo are local to foo_test too - return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") + return x.Obj().Pkg() != nil && + strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") } return false } diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go index ba94fd68..ff9c8b4f 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go @@ -28,9 +28,9 @@ var Analyzer = &analysis.Analyzer{ // Per-architecture checks for instructions. // Assume comments, leading and trailing spaces are removed. type arch struct { - isFPWrite func(string) bool - isFPRead func(string) bool - isBranch func(string) bool + isFPWrite func(string) bool + isFPRead func(string) bool + isUnconditionalBranch func(string) bool } var re = regexp.MustCompile @@ -48,8 +48,8 @@ var arches = map[string]arch{ "amd64": { isFPWrite: re(`,\s*BP$`).MatchString, // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely. isFPRead: re(`\bBP\b`).MatchString, - isBranch: func(s string) bool { - return hasAnyPrefix(s, "J", "RET") + isUnconditionalBranch: func(s string) bool { + return hasAnyPrefix(s, "JMP", "RET") }, }, "arm64": { @@ -70,49 +70,16 @@ var arches = map[string]arch{ return false }, isFPRead: re(`\bR29\b`).MatchString, - isBranch: func(s string) bool { + isUnconditionalBranch: func(s string) bool { // Get just the instruction if i := strings.IndexFunc(s, unicode.IsSpace); i > 0 { s = s[:i] } - return arm64Branch[s] + return s == "B" || s == "JMP" || s == "RET" }, }, } -// arm64 has many control flow instructions. -// ^(B|RET) isn't sufficient or correct (e.g. BIC, BFI aren't control flow.) -// It's easier to explicitly enumerate them in a map than to write a regex. -// Borrowed from Go tree, cmd/asm/internal/arch/arm64.go -var arm64Branch = map[string]bool{ - "B": true, - "BL": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CBZ": true, - "CBZW": true, - "CBNZ": true, - "CBNZW": true, - "JMP": true, - "TBNZ": true, - "TBZ": true, - "RET": true, -} - func run(pass *analysis.Pass) (any, error) { arch, ok := arches[build.Default.GOARCH] if !ok { @@ -164,7 +131,7 @@ func run(pass *analysis.Pass) (any, error) { active = false continue } - if arch.isFPRead(line) || arch.isBranch(line) { + if arch.isFPRead(line) || arch.isUnconditionalBranch(line) { active = false continue } diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go index 64df1b10..2580a0ac 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go @@ -88,7 +88,7 @@ func run(pass *analysis.Pass) (any, error) { // // TODO: consider allowing the "last" go/defer/Go statement to be followed by // N "trivial" statements, possibly under a recursive definition of "trivial" - // so that that checker could, for example, conclude that a go statement is + // so that checker could, for example, conclude that a go statement is // followed by an if statement made of only trivial statements and trivial expressions, // and hence the go statement could still be checked. forEachLastStmt(body.List, func(last ast.Stmt) { diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index a28ed365..159a95ae 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/internal/analysisinternal" + "golang.org/x/tools/internal/astutil" "golang.org/x/tools/internal/fmtstr" "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/versions" @@ -540,7 +541,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", name) + pass.ReportRangef(call.Args[firstArg], "%s call has arguments but no formatting directives", name) } return } @@ -552,7 +553,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C if err != nil { // All error messages are in predicate form ("call has a problem") // so that they may be affixed into a subject ("log.Printf "). - pass.ReportRangef(call.Args[idx], "%s %s", name, err) + pass.ReportRangef(formatArg, "%s %s", name, err) return } @@ -560,20 +561,21 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C maxArgIndex := firstArg - 1 anyIndex := false // Check formats against args. - for _, operation := range operations { - if operation.Prec.Index != -1 || - operation.Width.Index != -1 || - operation.Verb.Index != -1 { + for _, op := range operations { + if op.Prec.Index != -1 || + op.Width.Index != -1 || + op.Verb.Index != -1 { anyIndex = true } - if !okPrintfArg(pass, call, &maxArgIndex, firstArg, name, operation) { + rng := opRange(formatArg, op) + if !okPrintfArg(pass, call, rng, &maxArgIndex, firstArg, name, op) { // One error per format is enough. return } - if operation.Verb.Verb == 'w' { + if op.Verb.Verb == 'w' { switch kind { case KindNone, KindPrint, KindPrintf: - pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", name) + pass.ReportRangef(rng, "%s does not support error-wrapping directive %%w", name) return } } @@ -594,6 +596,18 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C } } +// opRange returns the source range for the specified printf operation, +// such as the position of the %v substring of "...%v...". +func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range { + if lit, ok := formatArg.(*ast.BasicLit); ok { + start, end, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End) + if err == nil { + return analysisinternal.Range(start, end) // position of "%v" + } + } + return formatArg // entire format string +} + // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask. type printfArgType int @@ -657,7 +671,7 @@ var printVerbs = []printVerb{ // okPrintfArg compares the operation to the arguments actually present, // reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index. // If the final argument is ellipsissed, there's little it can do for that. -func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { +func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { verb := operation.Verb.Verb var v printVerb found := false @@ -680,7 +694,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if !formatter { if !found { - pass.ReportRangef(call, "%s format %s has unknown verb %c", name, operation.Text, verb) + pass.ReportRangef(rng, "%s format %s has unknown verb %c", name, operation.Text, verb) return false } for _, flag := range operation.Flags { @@ -690,7 +704,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs continue } if !strings.ContainsRune(v.flags, rune(flag)) { - pass.ReportRangef(call, "%s format %s has unrecognized flag %c", name, operation.Text, flag) + pass.ReportRangef(rng, "%s format %s has unrecognized flag %c", name, operation.Text, flag) return false } } @@ -707,7 +721,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // If len(argIndexes)>0, we have something like %.*s and all // indexes in argIndexes must be an integer. for _, argIndex := range argIndexes { - if !argCanBeChecked(pass, call, argIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, argIndex, firstArg, operation, name) { return } arg := call.Args[argIndex] @@ -716,7 +730,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) + pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) return false } } @@ -738,12 +752,12 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // Now check verb's type. verbArgIndex := operation.Verb.ArgIndex - if !argCanBeChecked(pass, call, verbArgIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, verbArgIndex, firstArg, operation, name) { return false } arg := call.Args[verbArgIndex] if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' { - pass.ReportRangef(call, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) + pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) return false } if reason, ok := matchArgType(pass, v.typ, arg); !ok { @@ -755,12 +769,14 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) + pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) return false } - if v.typ&argString != 0 && v.verb != 'T' && !strings.Contains(operation.Flags, "#") { + // Detect recursive formatting via value's String/Error methods. + // The '#' flag suppresses the methods, except with %x, %X, and %q. + if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) { if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) + pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) return false } } @@ -844,7 +860,7 @@ func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { // argCanBeChecked reports whether the specified argument is statically present; // it may be beyond the list of arguments or in a terminal slice... argument, which // means we can't see it. -func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { +func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { if argIndex <= 0 { // Shouldn't happen, so catch it with prejudice. panic("negative argIndex") @@ -861,7 +877,7 @@ func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg // There are bad indexes in the format or there are fewer arguments than the format needs. // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". arg := argIndex - firstArg + 1 // People think of arguments as 1-indexed. - pass.ReportRangef(call, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) + pass.ReportRangef(rng, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) return false } diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index a23721cd..7dbff1e4 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/typesinternal" ) //go:embed doc.go @@ -60,12 +61,11 @@ func describe(typ, inType types.Type, inName string) string { } func typeName(t types.Type) string { - type hasTypeName interface{ Obj() *types.TypeName } // Alias, Named, TypeParam - switch t := t.(type) { - case *types.Basic: - return t.Name() - case hasTypeName: - return t.Obj().Name() + if basic, ok := t.(*types.Basic); ok { + return basic.Name() // may be (e.g.) "untyped int", which has no TypeName + } + if tname := typesinternal.TypeNameFor(t); tname != nil { + return tname.Name() } return "" } diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go index 13a99973..cc90f733 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go @@ -107,7 +107,7 @@ func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, s // Embedded struct. Nothing to do for now, but that // may change, depending on what happens with issue 7363. - // TODO(adonovan): investigate, now that that issue is fixed. + // TODO(adonovan): investigate, now that issue is fixed. if field.Anonymous() { return } diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 9f59006e..d4e9b025 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -447,18 +447,6 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { } } -type tokenRange struct { - p, e token.Pos -} - -func (r tokenRange) Pos() token.Pos { - return r.p -} - -func (r tokenRange) End() token.Pos { - return r.e -} - func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { // Want functions with 0 results and 1 parameter. if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || @@ -476,8 +464,9 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 { // Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters. // We have currently decided to also warn before compilation/package loading. This can help users in IDEs. - at := tokenRange{tparams.Opening, tparams.Closing} - pass.ReportRangef(at, "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix) + pass.ReportRangef(analysisinternal.Range(tparams.Opening, tparams.Closing), + "%s has type parameters: it will not be run by go test as a %sXXX function", + fn.Name.Name, prefix) } if !isTestSuffix(fn.Name.Name[len(prefix):]) { diff --git a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index 932f1347..556ffed7 100644 --- a/event-processor/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/event-processor/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -26,6 +26,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/analysisinternal" ) //go:embed doc.go @@ -59,23 +60,62 @@ func init() { // The context.With{Cancel,Deadline,Timeout} entries are // effectively redundant wrt the lostcancel analyzer. funcs = stringSetFlag{ - "context.WithCancel": true, - "context.WithDeadline": true, - "context.WithTimeout": true, - "context.WithValue": true, - "errors.New": true, - "fmt.Errorf": true, - "fmt.Sprint": true, - "fmt.Sprintf": true, - "slices.Clip": true, - "slices.Compact": true, - "slices.CompactFunc": true, - "slices.Delete": true, - "slices.DeleteFunc": true, - "slices.Grow": true, - "slices.Insert": true, - "slices.Replace": true, - "sort.Reverse": true, + "context.WithCancel": true, + "context.WithDeadline": true, + "context.WithTimeout": true, + "context.WithValue": true, + "errors.New": true, + "fmt.Append": true, + "fmt.Appendf": true, + "fmt.Appendln": true, + "fmt.Errorf": true, + "fmt.Sprint": true, + "fmt.Sprintf": true, + "fmt.Sprintln": true, + "maps.All": true, + "maps.Clone": true, + "maps.Collect": true, + "maps.Equal": true, + "maps.EqualFunc": true, + "maps.Keys": true, + "maps.Values": true, + "slices.All": true, + "slices.AppendSeq": true, + "slices.Backward": true, + "slices.BinarySearch": true, + "slices.BinarySearchFunc": true, + "slices.Chunk": true, + "slices.Clip": true, + "slices.Clone": true, + "slices.Collect": true, + "slices.Compact": true, + "slices.CompactFunc": true, + "slices.Compare": true, + "slices.CompareFunc": true, + "slices.Concat": true, + "slices.Contains": true, + "slices.ContainsFunc": true, + "slices.Delete": true, + "slices.DeleteFunc": true, + "slices.Equal": true, + "slices.EqualFunc": true, + "slices.Grow": true, + "slices.Index": true, + "slices.IndexFunc": true, + "slices.Insert": true, + "slices.IsSorted": true, + "slices.IsSortedFunc": true, + "slices.Max": true, + "slices.MaxFunc": true, + "slices.Min": true, + "slices.MinFunc": true, + "slices.Repeat": true, + "slices.Replace": true, + "slices.Sorted": true, + "slices.SortedFunc": true, + "slices.SortedStableFunc": true, + "slices.Values": true, + "sort.Reverse": true, } Analyzer.Flags.Var(&funcs, "funcs", "comma-separated list of functions whose results must be used") @@ -114,14 +154,16 @@ func run(pass *analysis.Pass) (any, error) { // method (e.g. foo.String()) if types.Identical(sig, sigNoArgsStringResult) { if stringMethods[fn.Name()] { - pass.Reportf(call.Lparen, "result of (%s).%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of (%s).%s call not used", sig.Recv().Type(), fn.Name()) } } } else { // package-level function (e.g. fmt.Errorf) if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] { - pass.Reportf(call.Lparen, "result of %s.%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of %s.%s call not used", fn.Pkg().Path(), fn.Name()) } } diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/event-processor/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6e34df46..0fb4e7ee 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/event-processor/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -113,7 +113,7 @@ func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Nod // childrenOf elides the FuncType node beneath FuncDecl. // Add it back here for TypeParams, Params, Results, // all FieldLists). But we don't add it back for the "func" token - // even though it is is the tree at FuncDecl.Type.Func. + // even though it is the tree at FuncDecl.Type.Func. if decl, ok := node.(*ast.FuncDecl); ok { if fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv { path = append(path, decl.Type) @@ -207,6 +207,9 @@ func childrenOf(n ast.Node) []ast.Node { return false // no recursion }) + // TODO(adonovan): be more careful about missing (!Pos.Valid) + // tokens in trees produced from invalid input. + // Then add fake Nodes for bare tokens. switch n := n.(type) { case *ast.ArrayType: @@ -226,9 +229,12 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) + if n.Lbrace.IsValid() { + children = append(children, tok(n.Lbrace, len("{"))) + } + if n.Rbrace.IsValid() { + children = append(children, tok(n.Rbrace, len("}"))) + } case *ast.BranchStmt: children = append(children, @@ -304,9 +310,12 @@ func childrenOf(n ast.Node) []ast.Node { // TODO(adonovan): Field.{Doc,Comment,Tag}? case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), // or len("[") - tok(n.Closing, len(")"))) // or len("]") + if n.Opening.IsValid() { + children = append(children, tok(n.Opening, len("("))) + } + if n.Closing.IsValid() { + children = append(children, tok(n.Closing, len(")"))) + } case *ast.File: // TODO test: Doc diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/event-processor/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index 5c8dbbb7..4ad05493 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/event-processor/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -67,6 +67,10 @@ var abort = new(int) // singleton, to signal termination of Apply // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. +// +// This type is not to be confused with [inspector.Cursor] from +// package [golang.org/x/tools/go/ast/inspector], which provides +// stateless navigation of immutable syntax trees. type Cursor struct { parent ast.Node name string diff --git a/event-processor/vendor/golang.org/x/tools/internal/astutil/edge/edge.go b/event-processor/vendor/golang.org/x/tools/go/ast/edge/edge.go similarity index 100% rename from event-processor/vendor/golang.org/x/tools/internal/astutil/edge/edge.go rename to event-processor/vendor/golang.org/x/tools/go/ast/edge/edge.go diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/cursor.go new file mode 100644 index 00000000..31c8d2f2 --- /dev/null +++ b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/cursor.go @@ -0,0 +1,502 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package inspector + +import ( + "fmt" + "go/ast" + "go/token" + "iter" + "reflect" + + "golang.org/x/tools/go/ast/edge" +) + +// A Cursor represents an [ast.Node]. It is immutable. +// +// Two Cursors compare equal if they represent the same node. +// +// Call [Inspector.Root] to obtain a valid cursor for the virtual root +// node of the traversal. +// +// Use the following methods to navigate efficiently around the tree: +// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing]; +// - for children, use [Cursor.Child], [Cursor.Children], +// [Cursor.FirstChild], and [Cursor.LastChild]; +// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling]; +// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode], +// [Cursor.Inspect], and [Cursor.Preorder]. +// +// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for +// information about the edges in a tree: which field (and slice +// element) of the parent node holds the child. +type Cursor struct { + in *Inspector + index int32 // index of push node; -1 for virtual root node +} + +// Root returns a cursor for the virtual root node, +// whose children are the files provided to [New]. +// +// Its [Cursor.Node] and [Cursor.Stack] methods return nil. +func (in *Inspector) Root() Cursor { + return Cursor{in, -1} +} + +// At returns the cursor at the specified index in the traversal, +// which must have been obtained from [Cursor.Index] on a Cursor +// belonging to the same Inspector (see [Cursor.Inspector]). +func (in *Inspector) At(index int32) Cursor { + if index < 0 { + panic("negative index") + } + if int(index) >= len(in.events) { + panic("index out of range for this inspector") + } + if in.events[index].index < index { + panic("invalid index") // (a push, not a pop) + } + return Cursor{in, index} +} + +// Inspector returns the cursor's Inspector. +func (c Cursor) Inspector() *Inspector { return c.in } + +// Index returns the index of this cursor position within the package. +// +// Clients should not assume anything about the numeric Index value +// except that it increases monotonically throughout the traversal. +// It is provided for use with [At]. +// +// Index must not be called on the Root node. +func (c Cursor) Index() int32 { + if c.index < 0 { + panic("Index called on Root node") + } + return c.index +} + +// Node returns the node at the current cursor position, +// or nil for the cursor returned by [Inspector.Root]. +func (c Cursor) Node() ast.Node { + if c.index < 0 { + return nil + } + return c.in.events[c.index].node +} + +// String returns information about the cursor's node, if any. +func (c Cursor) String() string { + if c.in == nil { + return "(invalid)" + } + if c.index < 0 { + return "(root)" + } + return reflect.TypeOf(c.Node()).String() +} + +// indices return the [start, end) half-open interval of event indices. +func (c Cursor) indices() (int32, int32) { + if c.index < 0 { + return 0, int32(len(c.in.events)) // root: all events + } else { + return c.index, c.in.events[c.index].index + 1 // just one subtree + } +} + +// Preorder returns an iterator over the nodes of the subtree +// represented by c in depth-first order. Each node in the sequence is +// represented by a Cursor that allows access to the Node, but may +// also be used to start a new traversal, or to obtain the stack of +// nodes enclosing the cursor. +// +// The traversal sequence is determined by [ast.Inspect]. The types +// argument, if non-empty, enables type-based filtering of events. The +// function f if is called only for nodes whose type matches an +// element of the types slice. +// +// If you need control over descent into subtrees, +// or need both pre- and post-order notifications, use [Cursor.Inspect] +func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain types: skip. + i = pop + 1 + continue + } + } + i++ + } + } +} + +// Inspect visits the nodes of the subtree represented by c in +// depth-first order. It calls f(n) for each node n before it +// visits n's children. If f returns true, Inspect invokes f +// recursively for each of the non-nil children of the node. +// +// Each node is represented by a Cursor that allows access to the +// Node, but may also be used to start a new traversal, or to obtain +// the stack of nodes enclosing the cursor. +// +// The complete traversal sequence is determined by [ast.Inspect]. +// The types argument, if non-empty, enables type-based filtering of +// events. The function f if is called only for nodes whose type +// matches an element of the types slice. +func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { + mask := maskOf(types) + events := c.in.events + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { + // push + pop := ev.index + if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || + events[pop].typ&mask == 0 { + // The user opted not to descend, or the + // subtree does not contain types: + // skip past the pop. + i = pop + 1 + continue + } + } + i++ + } +} + +// Enclosing returns an iterator over the nodes enclosing the current +// current node, starting with the Cursor itself. +// +// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// The types argument, if non-empty, enables type-based filtering of +// events: the sequence includes only enclosing nodes whose type +// matches an element of the types slice. +func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { + if c.index < 0 { + panic("Cursor.Enclosing called on Root node") + } + + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + for i := c.index; i >= 0; i = events[i].parent { + if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + } + } +} + +// Parent returns the parent of the current node. +// +// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Parent() Cursor { + if c.index < 0 { + panic("Cursor.Parent called on Root node") + } + + return Cursor{c.in, c.in.events[c.index].parent} +} + +// ParentEdge returns the identity of the field in the parent node +// that holds this cursor's node, and if it is a list, the index within it. +// +// For example, f(x, y) is a CallExpr whose three children are Idents. +// f has edge kind [edge.CallExpr_Fun] and index -1. +// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. +// +// If called on a child of the Root node, it returns ([edge.Invalid], -1). +// +// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) ParentEdge() (edge.Kind, int) { + if c.index < 0 { + panic("Cursor.ParentEdge called on Root node") + } + events := c.in.events + pop := events[c.index].index + return unpackEdgeKindAndIndex(events[pop].parent) +} + +// ChildAt returns the cursor for the child of the +// current node identified by its edge and index. +// The index must be -1 if the edge.Kind is not a slice. +// The indicated child node must exist. +// +// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. +func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { + target := packEdgeKindAndIndex(k, idx) + + // Unfortunately there's no shortcut to looping. + events := c.in.events + i := c.index + 1 + for { + pop := events[i].index + if pop < i { + break + } + if events[pop].parent == target { + return Cursor{c.in, i} + } + i = pop + 1 + } + panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) +} + +// Child returns the cursor for n, which must be a direct child of c's Node. +// +// Child must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Child(n ast.Node) Cursor { + if c.index < 0 { + panic("Cursor.Child called on Root node") + } + + if false { + // reference implementation + for child := range c.Children() { + if child.Node() == n { + return child + } + } + + } else { + // optimized implementation + events := c.in.events + for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { + if events[i].node == n { + return Cursor{c.in, i} + } + } + } + panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) +} + +// NextSibling returns the cursor for the next sibling node in the same list +// (for example, of files, decls, specs, statements, fields, or expressions) as +// the current node. It returns (zero, false) if the node is the last node in +// the list, or is not part of a list. +// +// NextSibling must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) NextSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.NextSibling called on Root node") + } + + events := c.in.events + i := events[c.index].index + 1 // after corresponding pop + if i < int32(len(events)) { + if events[i].index > i { // push? + return Cursor{c.in, i}, true + } + } + return Cursor{}, false +} + +// PrevSibling returns the cursor for the previous sibling node in the +// same list (for example, of files, decls, specs, statements, fields, +// or expressions) as the current node. It returns zero if the node is +// the first node in the list, or is not part of a list. +// +// It must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) PrevSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.PrevSibling called on Root node") + } + + events := c.in.events + i := c.index - 1 + if i >= 0 { + if j := events[i].index; j < i { // pop? + return Cursor{c.in, j}, true + } + } + return Cursor{}, false +} + +// FirstChild returns the first direct child of the current node, +// or zero if it has no children. +func (c Cursor) FirstChild() (Cursor, bool) { + events := c.in.events + i := c.index + 1 // i=0 if c is root + if i < int32(len(events)) && events[i].index > i { // push? + return Cursor{c.in, i}, true + } + return Cursor{}, false +} + +// LastChild returns the last direct child of the current node, +// or zero if it has no children. +func (c Cursor) LastChild() (Cursor, bool) { + events := c.in.events + if c.index < 0 { // root? + if len(events) > 0 { + // return push of final event (a pop) + return Cursor{c.in, events[len(events)-1].index}, true + } + } else { + j := events[c.index].index - 1 // before corresponding pop + // Inv: j == c.index if c has no children + // or j is last child's pop. + if j > c.index { // c has children + return Cursor{c.in, events[j].index}, true + } + } + return Cursor{}, false +} + +// Children returns an iterator over the direct children of the +// current node, if any. +// +// When using Children, NextChild, and PrevChild, bear in mind that a +// Node's children may come from different fields, some of which may +// be lists of nodes without a distinguished intervening container +// such as [ast.BlockStmt]. +// +// For example, [ast.CaseClause] has a field List of expressions and a +// field Body of statements, so the children of a CaseClause are a mix +// of expressions and statements. Other nodes that have "uncontained" +// list fields include: +// +// - [ast.ValueSpec] (Names, Values) +// - [ast.CompositeLit] (Type, Elts) +// - [ast.IndexListExpr] (X, Indices) +// - [ast.CallExpr] (Fun, Args) +// - [ast.AssignStmt] (Lhs, Rhs) +// +// So, do not assume that the previous sibling of an ast.Stmt is also +// an ast.Stmt, or if it is, that they are executed sequentially, +// unless you have established that, say, its parent is a BlockStmt +// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. +// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, +// even though they are not executed in sequence. +func (c Cursor) Children() iter.Seq[Cursor] { + return func(yield func(Cursor) bool) { + c, ok := c.FirstChild() + for ok && yield(c) { + c, ok = c.NextSibling() + } + } +} + +// Contains reports whether c contains or is equal to c2. +// +// Both Cursors must belong to the same [Inspector]; +// neither may be its Root node. +func (c Cursor) Contains(c2 Cursor) bool { + if c.in != c2.in { + panic("different inspectors") + } + events := c.in.events + return c.index <= c2.index && events[c2.index].index <= events[c.index].index +} + +// FindNode returns the cursor for node n if it belongs to the subtree +// rooted at c. It returns zero if n is not found. +func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { + + // FindNode is equivalent to this code, + // but more convenient and 15-20% faster: + if false { + for candidate := range c.Preorder(n) { + if candidate.Node() == n { + return candidate, true + } + } + return Cursor{}, false + } + + // TODO(adonovan): opt: should we assume Node.Pos is accurate + // and combine type-based filtering with position filtering + // like FindByPos? + + mask := maskOf([]ast.Node{n}) + events := c.in.events + + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && ev.node == n { + return Cursor{c.in, i}, true + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain type of n: skip. + i = pop + } + } + } + return Cursor{}, false +} + +// FindByPos returns the cursor for the innermost node n in the tree +// rooted at c such that n.Pos() <= start && end <= n.End(). +// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) +// +// It returns zero if none is found. +// Precondition: start <= end. +// +// See also [astutil.PathEnclosingInterval], which +// tolerates adjoining whitespace. +func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { + if end < start { + panic("end < start") + } + events := c.in.events + + // This algorithm could be implemented using c.Inspect, + // but it is about 2.5x slower. + + best := int32(-1) // push index of latest (=innermost) node containing range + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + n := ev.node + var nodeEnd token.Pos + if file, ok := n.(*ast.File); ok { + nodeEnd = file.FileEnd + // Note: files may be out of Pos order. + if file.FileStart > start { + i = ev.index // disjoint, after; skip to next file + continue + } + } else { + nodeEnd = n.End() + if n.Pos() > start { + break // disjoint, after; stop + } + } + // Inv: node.{Pos,FileStart} <= start + if end <= nodeEnd { + // node fully contains target range + best = i + } else if nodeEnd < start { + i = ev.index // disjoint, before; skip forward + } + } + } + if best >= 0 { + return Cursor{c.in, best}, true + } + return Cursor{}, false +} diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/inspector.go index 674490a6..a703cdfc 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/inspector.go +++ b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/inspector.go @@ -13,10 +13,19 @@ // This representation is sometimes called a "balanced parenthesis tree." // // Experiments suggest the inspector's traversals are about 2.5x faster -// than ast.Inspect, but it may take around 5 traversals for this +// than [ast.Inspect], but it may take around 5 traversals for this // benefit to amortize the inspector's construction cost. // If efficiency is the primary concern, do not use Inspector for // one-off traversals. +// +// The [Cursor] type provides a more flexible API for efficient +// navigation of syntax trees in all four "cardinal directions". For +// example, traversals may be nested, so you can find each node of +// type A and then search within it for nodes of type B. Or you can +// traverse from a node to its immediate neighbors: its parent, its +// previous and next sibling, or its first and last child. We +// recommend using methods of Cursor in preference to Inspector where +// possible. package inspector // There are four orthogonal features in a traversal: @@ -37,9 +46,8 @@ package inspector import ( "go/ast" - _ "unsafe" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) // An Inspector provides methods for inspecting @@ -48,18 +56,12 @@ type Inspector struct { events []event } -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *Inspector) []event { return in.events } - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex func packEdgeKindAndIndex(ek edge.Kind, index int) int32 { return int32(uint32(index+1)<<7 | uint32(ek)) } // unpackEdgeKindAndIndex unpacks the edge kind and edge index (within // an []ast.Node slice) from the parent field of a pop event. -// -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) { // The "parent" field of a pop node holds the // edge Kind in the lower 7 bits and the index+1 @@ -83,15 +85,21 @@ type event struct { // TODO: Experiment with storing only the second word of event.node (unsafe.Pointer). // Type can be recovered from the sole bit in typ. +// [Tried this, wasn't faster. --adonovan] // Preorder visits all the nodes of the files supplied to New in // depth-first order. It calls f(n) for each node n before it visits // n's children. // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Preorder] method provides a richer alternative interface. +// Example: +// +// for c := range in.Root().Preorder(types) { ... } func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // Because it avoids postorder calls to f, and the pruning // check, Preorder is almost twice as fast as Nodes. The two @@ -131,10 +139,18 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // of the non-nil children of the node, followed by a call of // f(n, false). // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f if is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// ... +// return true +// } func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) { mask := maskOf(types) for i := int32(0); i < int32(len(in.events)); { @@ -168,6 +184,15 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proc // supplies each call to f an additional argument, the current // traversal stack. The stack's first element is the outermost node, // an *ast.File; its last is the innermost, n. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// stack := slices.Collect(c.Enclosing()) +// ... +// return true +// }) func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) { mask := maskOf(types) var stack []ast.Node @@ -233,7 +258,7 @@ type visitor struct { type item struct { index int32 // index of current node's push event parentIndex int32 // index of parent node's push event - typAccum uint64 // accumulated type bits of current node's descendents + typAccum uint64 // accumulated type bits of current node's descendants edgeKindAndIndex int32 // edge.Kind and index, bit packed } diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index e936c67c..9852331a 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - _ "unsafe" ) const ( @@ -217,7 +215,6 @@ func typeOf(n ast.Node) uint64 { return 0 } -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf func maskOf(nodes []ast.Node) uint64 { if len(nodes) == 0 { return math.MaxUint64 // match all node types diff --git a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/walk.go b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/walk.go index 5a42174a..5f1c93c8 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ast/inspector/walk.go +++ b/event-processor/vendor/golang.org/x/tools/go/ast/inspector/walk.go @@ -13,7 +13,7 @@ import ( "fmt" "go/ast" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) { diff --git a/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/graph.go b/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/graph.go index 26225e7d..f66f4c73 100644 --- a/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/graph.go +++ b/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/graph.go @@ -658,7 +658,7 @@ func (b *builder) call(c ssa.CallInstruction) { } func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) { - // When f has no paremeters (including receiver), there is no type + // When f has no parameters (including receiver), there is no type // flow here. Also, f's body and parameters might be missing, such // as when vta is used within the golang.org/x/tools/go/analysis // framework (see github.com/golang/go/issues/50670). @@ -803,7 +803,7 @@ func (b *builder) nodeFromVal(val ssa.Value) node { return function{f: v} case *ssa.Parameter, *ssa.FreeVar, ssa.Instruction: // ssa.Param, ssa.FreeVar, and a specific set of "register" instructions, - // satisifying the ssa.Value interface, can serve as local variables. + // satisfying the ssa.Value interface, can serve as local variables. return local{val: v} default: panic(fmt.Errorf("unsupported value %v in node creation", val)) diff --git a/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go b/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go index bdd39397..adef1282 100644 --- a/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go +++ b/event-processor/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go @@ -245,7 +245,7 @@ func (b *Builder) create(leaves []*leaf) node { } else if n == 1 { return leaves[0] } - // Note: we can do a more sophisicated algorithm by: + // Note: we can do a more sophisticated algorithm by: // - sorting the leaves ahead of time, // - taking the prefix and branching bit of the min and max key, // - binary searching for the branching bit, diff --git a/event-processor/vendor/golang.org/x/tools/go/loader/doc.go b/event-processor/vendor/golang.org/x/tools/go/loader/doc.go index e35b1fd7..769a1fcf 100644 --- a/event-processor/vendor/golang.org/x/tools/go/loader/doc.go +++ b/event-processor/vendor/golang.org/x/tools/go/loader/doc.go @@ -164,7 +164,7 @@ package loader // entry is created in this cache by startLoad the first time the // package is imported. The first goroutine to request an entry becomes // responsible for completing the task and broadcasting completion to -// subsequent requestors, which block until then. +// subsequent requesters, which block until then. // // Type checking occurs in (parallel) postorder: we cannot type-check a // set of files until we have loaded and type-checked all of their diff --git a/event-processor/vendor/golang.org/x/tools/go/packages/doc.go b/event-processor/vendor/golang.org/x/tools/go/packages/doc.go index f1931d10..366aab6b 100644 --- a/event-processor/vendor/golang.org/x/tools/go/packages/doc.go +++ b/event-processor/vendor/golang.org/x/tools/go/packages/doc.go @@ -76,6 +76,8 @@ uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. +See also [golang.org/x/tools/go/packages/internal/linecount] +for an example application. # The driver protocol diff --git a/event-processor/vendor/golang.org/x/tools/go/packages/golist.go b/event-processor/vendor/golang.org/x/tools/go/packages/golist.go index 96e43cd8..89f89dd2 100644 --- a/event-processor/vendor/golang.org/x/tools/go/packages/golist.go +++ b/event-processor/vendor/golang.org/x/tools/go/packages/golist.go @@ -224,13 +224,22 @@ extractQueries: return response.dr, nil } +// abs returns an absolute representation of path, based on cfg.Dir. +func (cfg *Config) abs(path string) (string, error) { + if filepath.IsAbs(path) { + return path, nil + } + // In case cfg.Dir is relative, pass it to filepath.Abs. + return filepath.Abs(filepath.Join(cfg.Dir, path)) +} + func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { for _, query := range queries { // TODO(matloob): Do only one query per directory. fdir := filepath.Dir(query) // Pass absolute path of directory to go list so that it knows to treat it as a directory, // not a package path. - pattern, err := filepath.Abs(fdir) + pattern, err := state.cfg.abs(fdir) if err != nil { return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err) } @@ -703,9 +712,8 @@ func (state *golistState) getGoVersion() (int, error) { // getPkgPath finds the package path of a directory if it's relative to a root // directory. func (state *golistState) getPkgPath(dir string) (string, bool, error) { - absDir, err := filepath.Abs(dir) - if err != nil { - return "", false, err + if !filepath.IsAbs(dir) { + panic("non-absolute dir passed to getPkgPath") } roots, err := state.determineRootDirs() if err != nil { @@ -715,7 +723,7 @@ func (state *golistState) getPkgPath(dir string) (string, bool, error) { for rdir, rpath := range roots { // Make sure that the directory is in the module, // to avoid creating a path relative to another module. - if !strings.HasPrefix(absDir, rdir) { + if !strings.HasPrefix(dir, rdir) { continue } // TODO(matloob): This doesn't properly handle symlinks. diff --git a/event-processor/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/event-processor/vendor/golang.org/x/tools/go/packages/golist_overlay.go index d823c474..d9d5a45c 100644 --- a/event-processor/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/event-processor/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -55,7 +55,7 @@ func (state *golistState) determineRootDirsModules() (map[string]string, error) } if mod.Dir != "" && mod.Path != "" { // This is a valid module; add it to the map. - absDir, err := filepath.Abs(mod.Dir) + absDir, err := state.cfg.abs(mod.Dir) if err != nil { return nil, err } diff --git a/event-processor/vendor/golang.org/x/tools/go/ssa/builder.go b/event-processor/vendor/golang.org/x/tools/go/ssa/builder.go index 84ccbc09..a5ef8fb4 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ssa/builder.go +++ b/event-processor/vendor/golang.org/x/tools/go/ssa/builder.go @@ -25,7 +25,7 @@ package ssa // populating fields such as Function.Body, .Params, and others. // // Building may create additional methods, including: -// - wrapper methods (e.g. for embeddding, or implicit &recv) +// - wrapper methods (e.g. for embedding, or implicit &recv) // - bound method closures (e.g. for use(recv.f)) // - thunks (e.g. for use(I.f) or use(T.f)) // - generic instances (e.g. to produce f[int] from f[any]). @@ -138,7 +138,7 @@ type builder struct { finished int // finished is the length of the prefix of fns containing built functions. // The task of building shared functions within the builder. - // Shared functions are ones the the builder may either create or lookup. + // Shared functions are ones the builder may either create or lookup. // These may be built by other builders in parallel. // The task is done when the builder has finished iterating, and it // waits for all shared functions to finish building. @@ -2920,6 +2920,9 @@ func (b *builder) buildParamsOnly(fn *Function) { for i, n := 0, params.Len(); i < n; i++ { fn.addParamVar(params.At(i)) } + + // clear out other function state (keep consistent with finishBody) + fn.subst = nil } // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. diff --git a/event-processor/vendor/golang.org/x/tools/go/ssa/func.go b/event-processor/vendor/golang.org/x/tools/go/ssa/func.go index 2d52309b..f48bd718 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ssa/func.go +++ b/event-processor/vendor/golang.org/x/tools/go/ssa/func.go @@ -386,6 +386,8 @@ func (f *Function) finishBody() { f.results = nil // (used by lifting) f.deferstack = nil // (used by lifting) f.vars = nil // (used by lifting) + + // clear out other function state (keep consistent with buildParamsOnly) f.subst = nil numberRegisters(f) // uses f.namedRegisters diff --git a/event-processor/vendor/golang.org/x/tools/go/ssa/sanity.go b/event-processor/vendor/golang.org/x/tools/go/ssa/sanity.go index b11680a1..c47a137c 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ssa/sanity.go +++ b/event-processor/vendor/golang.org/x/tools/go/ssa/sanity.go @@ -27,9 +27,10 @@ type sanity struct { } // sanityCheck performs integrity checking of the SSA representation -// of the function fn and returns true if it was valid. Diagnostics -// are written to reporter if non-nil, os.Stderr otherwise. Some -// diagnostics are only warnings and do not imply a negative result. +// of the function fn (which must have been "built") and returns true +// if it was valid. Diagnostics are written to reporter if non-nil, +// os.Stderr otherwise. Some diagnostics are only warnings and do not +// imply a negative result. // // Sanity-checking is intended to facilitate the debugging of code // transformation passes. diff --git a/event-processor/vendor/golang.org/x/tools/go/ssa/subst.go b/event-processor/vendor/golang.org/x/tools/go/ssa/subst.go index b4ea1685..362dce12 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ssa/subst.go +++ b/event-processor/vendor/golang.org/x/tools/go/ssa/subst.go @@ -543,7 +543,7 @@ func (subst *subster) signature(t *types.Signature) types.Type { // We are choosing not to support tparams.Len() > 0 until a need has been observed in practice. // // There are some known usages for types.Types coming from types.{Eval,CheckExpr}. - // To support tparams.Len() > 0, we just need to do the following [psuedocode]: + // To support tparams.Len() > 0, we just need to do the following [pseudocode]: // targs := {subst.replacements[tparams[i]]]}; Instantiate(ctxt, t, targs, false) assert(tparams.Len() == 0, "Substituting types.Signatures with generic functions are currently unsupported.") diff --git a/event-processor/vendor/golang.org/x/tools/go/ssa/util.go b/event-processor/vendor/golang.org/x/tools/go/ssa/util.go index e53b31ff..932eb6cb 100644 --- a/event-processor/vendor/golang.org/x/tools/go/ssa/util.go +++ b/event-processor/vendor/golang.org/x/tools/go/ssa/util.go @@ -25,7 +25,7 @@ type unit struct{} //// Sanity checking utilities -// assert panics with the mesage msg if p is false. +// assert panics with the message msg if p is false. // Avoid combining with expensive string formatting. func assert(p bool, msg string) { if !p { diff --git a/event-processor/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/event-processor/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 16ed3c17..d3c2913b 100644 --- a/event-processor/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/event-processor/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -603,7 +603,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { type hasTypeParams interface { TypeParams() *types.TypeParamList } - // abstraction of *types.{Named,TypeParam} + // abstraction of *types.{Alias,Named,TypeParam} type hasObj interface { Obj() *types.TypeName } diff --git a/event-processor/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/event-processor/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index c4d10de3..e46aab02 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/event-processor/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -22,7 +22,6 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/cursor" "golang.org/x/tools/internal/typesinternal" ) @@ -526,7 +525,7 @@ func CanImport(from, to string) bool { func DeleteStmt(fset *token.FileSet, astFile *ast.File, stmt ast.Stmt, report func(string, ...any)) []analysis.TextEdit { // TODO: pass in the cursor to a ast.Stmt. callers should provide the Cursor insp := inspector.New([]*ast.File{astFile}) - root := cursor.Root(insp) + root := insp.Root() cstmt, ok := root.FindNode(stmt) if !ok { report("%s not found in file", stmt.Pos()) @@ -620,8 +619,8 @@ Outer: // otherwise remove the line edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()} if from.IsValid() || to.IsValid() { - // remove just the statment. - // we can't tell if there is a ; or whitespace right after the statment + // remove just the statement. + // we can't tell if there is a ; or whitespace right after the statement // ideally we'd like to remove the former and leave the latter // (if gofmt has run, there likely won't be a ;) // In type switches we know there's a semicolon somewhere after the statement, @@ -671,3 +670,14 @@ func IsStdPackage(path string) bool { } return !strings.Contains(path[:slash], ".") && path != "testdata" } + +// Range returns an [analysis.Range] for the specified start and end positions. +func Range(pos, end token.Pos) analysis.Range { + return tokenRange{pos, end} +} + +// tokenRange is an implementation of the [analysis.Range] interface. +type tokenRange struct{ StartPos, EndPos token.Pos } + +func (r tokenRange) Pos() token.Pos { return r.StartPos } +func (r tokenRange) End() token.Pos { return r.EndPos } diff --git a/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go b/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go deleted file mode 100644 index 78d874a8..00000000 --- a/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -// Package cursor augments [inspector.Inspector] with [Cursor] -// functionality allowing more flexibility and control during -// inspection. -// -// This package is a temporary private extension of inspector until -// proposal #70859 is accepted, and which point it will be moved into -// the inspector package, and [Root] will become a method of -// Inspector. -package cursor - -import ( - "fmt" - "go/ast" - "go/token" - "iter" - "reflect" - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// A Cursor represents an [ast.Node]. It is immutable. -// -// Two Cursors compare equal if they represent the same node. -// -// Call [Root] to obtain a valid cursor. -type Cursor struct { - in *inspector.Inspector - index int32 // index of push node; -1 for virtual root node -} - -// Root returns a cursor for the virtual root node, -// whose children are the files provided to [New]. -// -// Its [Cursor.Node] and [Cursor.Stack] methods return nil. -func Root(in *inspector.Inspector) Cursor { - return Cursor{in, -1} -} - -// At returns the cursor at the specified index in the traversal, -// which must have been obtained from [Cursor.Index] on a Cursor -// belonging to the same Inspector (see [Cursor.Inspector]). -func At(in *inspector.Inspector, index int32) Cursor { - if index < 0 { - panic("negative index") - } - events := events(in) - if int(index) >= len(events) { - panic("index out of range for this inspector") - } - if events[index].index < index { - panic("invalid index") // (a push, not a pop) - } - return Cursor{in, index} -} - -// Inspector returns the cursor's Inspector. -func (c Cursor) Inspector() *inspector.Inspector { return c.in } - -// Index returns the index of this cursor position within the package. -// -// Clients should not assume anything about the numeric Index value -// except that it increases monotonically throughout the traversal. -// It is provided for use with [At]. -// -// Index must not be called on the Root node. -func (c Cursor) Index() int32 { - if c.index < 0 { - panic("Index called on Root node") - } - return c.index -} - -// Node returns the node at the current cursor position, -// or nil for the cursor returned by [Inspector.Root]. -func (c Cursor) Node() ast.Node { - if c.index < 0 { - return nil - } - return c.events()[c.index].node -} - -// String returns information about the cursor's node, if any. -func (c Cursor) String() string { - if c.in == nil { - return "(invalid)" - } - if c.index < 0 { - return "(root)" - } - return reflect.TypeOf(c.Node()).String() -} - -// indices return the [start, end) half-open interval of event indices. -func (c Cursor) indices() (int32, int32) { - if c.index < 0 { - return 0, int32(len(c.events())) // root: all events - } else { - return c.index, c.events()[c.index].index + 1 // just one subtree - } -} - -// Preorder returns an iterator over the nodes of the subtree -// represented by c in depth-first order. Each node in the sequence is -// represented by a Cursor that allows access to the Node, but may -// also be used to start a new traversal, or to obtain the stack of -// nodes enclosing the cursor. -// -// The traversal sequence is determined by [ast.Inspect]. The types -// argument, if non-empty, enables type-based filtering of events. The -// function f if is called only for nodes whose type matches an -// element of the types slice. -// -// If you need control over descent into subtrees, -// or need both pre- and post-order notifications, use [Cursor.Inspect] -func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain types: skip. - i = pop + 1 - continue - } - } - i++ - } - } -} - -// Inspect visits the nodes of the subtree represented by c in -// depth-first order. It calls f(n) for each node n before it -// visits n's children. If f returns true, Inspect invokes f -// recursively for each of the non-nil children of the node. -// -// Each node is represented by a Cursor that allows access to the -// Node, but may also be used to start a new traversal, or to obtain -// the stack of nodes enclosing the cursor. -// -// The complete traversal sequence is determined by [ast.Inspect]. -// The types argument, if non-empty, enables type-based filtering of -// events. The function f if is called only for nodes whose type -// matches an element of the types slice. -func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { - mask := maskOf(types) - events := c.events() - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { - // push - pop := ev.index - if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || - events[pop].typ&mask == 0 { - // The user opted not to descend, or the - // subtree does not contain types: - // skip past the pop. - i = pop + 1 - continue - } - } - i++ - } -} - -// Enclosing returns an iterator over the nodes enclosing the current -// current node, starting with the Cursor itself. -// -// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// The types argument, if non-empty, enables type-based filtering of -// events: the sequence includes only enclosing nodes whose type -// matches an element of the types slice. -func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { - if c.index < 0 { - panic("Cursor.Enclosing called on Root node") - } - - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - for i := c.index; i >= 0; i = events[i].parent { - if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - } - } -} - -// Parent returns the parent of the current node. -// -// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Parent() Cursor { - if c.index < 0 { - panic("Cursor.Parent called on Root node") - } - - return Cursor{c.in, c.events()[c.index].parent} -} - -// ParentEdge returns the identity of the field in the parent node -// that holds this cursor's node, and if it is a list, the index within it. -// -// For example, f(x, y) is a CallExpr whose three children are Idents. -// f has edge kind [edge.CallExpr_Fun] and index -1. -// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. -// -// If called on a child of the Root node, it returns ([edge.Invalid], -1). -// -// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) ParentEdge() (edge.Kind, int) { - if c.index < 0 { - panic("Cursor.ParentEdge called on Root node") - } - events := c.events() - pop := events[c.index].index - return unpackEdgeKindAndIndex(events[pop].parent) -} - -// ChildAt returns the cursor for the child of the -// current node identified by its edge and index. -// The index must be -1 if the edge.Kind is not a slice. -// The indicated child node must exist. -// -// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. -func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { - target := packEdgeKindAndIndex(k, idx) - - // Unfortunately there's no shortcut to looping. - events := c.events() - i := c.index + 1 - for { - pop := events[i].index - if pop < i { - break - } - if events[pop].parent == target { - return Cursor{c.in, i} - } - i = pop + 1 - } - panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) -} - -// Child returns the cursor for n, which must be a direct child of c's Node. -// -// Child must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Child(n ast.Node) Cursor { - if c.index < 0 { - panic("Cursor.Child called on Root node") - } - - if false { - // reference implementation - for child := range c.Children() { - if child.Node() == n { - return child - } - } - - } else { - // optimized implementation - events := c.events() - for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { - if events[i].node == n { - return Cursor{c.in, i} - } - } - } - panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) -} - -// NextSibling returns the cursor for the next sibling node in the same list -// (for example, of files, decls, specs, statements, fields, or expressions) as -// the current node. It returns (zero, false) if the node is the last node in -// the list, or is not part of a list. -// -// NextSibling must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) NextSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.NextSibling called on Root node") - } - - events := c.events() - i := events[c.index].index + 1 // after corresponding pop - if i < int32(len(events)) { - if events[i].index > i { // push? - return Cursor{c.in, i}, true - } - } - return Cursor{}, false -} - -// PrevSibling returns the cursor for the previous sibling node in the -// same list (for example, of files, decls, specs, statements, fields, -// or expressions) as the current node. It returns zero if the node is -// the first node in the list, or is not part of a list. -// -// It must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) PrevSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.PrevSibling called on Root node") - } - - events := c.events() - i := c.index - 1 - if i >= 0 { - if j := events[i].index; j < i { // pop? - return Cursor{c.in, j}, true - } - } - return Cursor{}, false -} - -// FirstChild returns the first direct child of the current node, -// or zero if it has no children. -func (c Cursor) FirstChild() (Cursor, bool) { - events := c.events() - i := c.index + 1 // i=0 if c is root - if i < int32(len(events)) && events[i].index > i { // push? - return Cursor{c.in, i}, true - } - return Cursor{}, false -} - -// LastChild returns the last direct child of the current node, -// or zero if it has no children. -func (c Cursor) LastChild() (Cursor, bool) { - events := c.events() - if c.index < 0 { // root? - if len(events) > 0 { - // return push of final event (a pop) - return Cursor{c.in, events[len(events)-1].index}, true - } - } else { - j := events[c.index].index - 1 // before corresponding pop - // Inv: j == c.index if c has no children - // or j is last child's pop. - if j > c.index { // c has children - return Cursor{c.in, events[j].index}, true - } - } - return Cursor{}, false -} - -// Children returns an iterator over the direct children of the -// current node, if any. -// -// When using Children, NextChild, and PrevChild, bear in mind that a -// Node's children may come from different fields, some of which may -// be lists of nodes without a distinguished intervening container -// such as [ast.BlockStmt]. -// -// For example, [ast.CaseClause] has a field List of expressions and a -// field Body of statements, so the children of a CaseClause are a mix -// of expressions and statements. Other nodes that have "uncontained" -// list fields include: -// -// - [ast.ValueSpec] (Names, Values) -// - [ast.CompositeLit] (Type, Elts) -// - [ast.IndexListExpr] (X, Indices) -// - [ast.CallExpr] (Fun, Args) -// - [ast.AssignStmt] (Lhs, Rhs) -// -// So, do not assume that the previous sibling of an ast.Stmt is also -// an ast.Stmt, or if it is, that they are executed sequentially, -// unless you have established that, say, its parent is a BlockStmt -// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. -// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, -// even though they are not executed in sequence. -func (c Cursor) Children() iter.Seq[Cursor] { - return func(yield func(Cursor) bool) { - c, ok := c.FirstChild() - for ok && yield(c) { - c, ok = c.NextSibling() - } - } -} - -// Contains reports whether c contains or is equal to c2. -// -// Both Cursors must belong to the same [Inspector]; -// neither may be its Root node. -func (c Cursor) Contains(c2 Cursor) bool { - if c.in != c2.in { - panic("different inspectors") - } - events := c.events() - return c.index <= c2.index && events[c2.index].index <= events[c.index].index -} - -// FindNode returns the cursor for node n if it belongs to the subtree -// rooted at c. It returns zero if n is not found. -func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { - - // FindNode is equivalent to this code, - // but more convenient and 15-20% faster: - if false { - for candidate := range c.Preorder(n) { - if candidate.Node() == n { - return candidate, true - } - } - return Cursor{}, false - } - - // TODO(adonovan): opt: should we assume Node.Pos is accurate - // and combine type-based filtering with position filtering - // like FindByPos? - - mask := maskOf([]ast.Node{n}) - events := c.events() - - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && ev.node == n { - return Cursor{c.in, i}, true - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain type of n: skip. - i = pop - } - } - } - return Cursor{}, false -} - -// FindByPos returns the cursor for the innermost node n in the tree -// rooted at c such that n.Pos() <= start && end <= n.End(). -// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) -// -// It returns zero if none is found. -// Precondition: start <= end. -// -// See also [astutil.PathEnclosingInterval], which -// tolerates adjoining whitespace. -func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { - if end < start { - panic("end < start") - } - events := c.events() - - // This algorithm could be implemented using c.Inspect, - // but it is about 2.5x slower. - - best := int32(-1) // push index of latest (=innermost) node containing range - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - n := ev.node - var nodeEnd token.Pos - if file, ok := n.(*ast.File); ok { - nodeEnd = file.FileEnd - // Note: files may be out of Pos order. - if file.FileStart > start { - i = ev.index // disjoint, after; skip to next file - continue - } - } else { - nodeEnd = n.End() - if n.Pos() > start { - break // disjoint, after; stop - } - } - // Inv: node.{Pos,FileStart} <= start - if end <= nodeEnd { - // node fully contains target range - best = i - } else if nodeEnd < start { - i = ev.index // disjoint, before; skip forward - } - } - } - if best >= 0 { - return Cursor{c.in, best}, true - } - return Cursor{}, false -} diff --git a/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go b/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go deleted file mode 100644 index 0257d61d..00000000 --- a/event-processor/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -package cursor - -import ( - "go/ast" - _ "unsafe" // for go:linkname - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// This file defines backdoor access to inspector. - -// Copied from inspector.event; must remain in sync. -// (Note that the linkname effects a type coercion too.) -type event struct { - node ast.Node - typ uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events - index int32 // index of corresponding push or pop event (relative to this event's index, +ve=push, -ve=pop) - parent int32 // index of parent's push node (push nodes only); or edge and index, bit packed (pop nodes only) -} - -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf -func maskOf(nodes []ast.Node) uint64 - -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *inspector.Inspector) []event - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex -func packEdgeKindAndIndex(edge.Kind, int) int32 - -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex -func unpackEdgeKindAndIndex(int32) (edge.Kind, int) - -func (c Cursor) events() []event { return events(c.in) } diff --git a/event-processor/vendor/golang.org/x/tools/internal/astutil/util.go b/event-processor/vendor/golang.org/x/tools/internal/astutil/util.go index 1862668a..f06dbda3 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/astutil/util.go +++ b/event-processor/vendor/golang.org/x/tools/internal/astutil/util.go @@ -71,6 +71,8 @@ func PosInStringLiteral(lit *ast.BasicLit, offset int) (token.Pos, error) { // In practice, the second call is nearly always used only to pop the // stack, and it is surprisingly tricky to do this correctly; see // https://go.dev/issue/73319. +// +// TODO(adonovan): replace with [ast.PreorderStack] when go1.25 is assured. func PreorderStack(root ast.Node, stack []ast.Node, f func(n ast.Node, stack []ast.Node) bool) { before := len(stack) ast.Inspect(root, func(n ast.Node) bool { diff --git a/event-processor/vendor/golang.org/x/tools/internal/imports/fix.go b/event-processor/vendor/golang.org/x/tools/internal/imports/fix.go index 89b96381..50b6ca51 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/event-processor/vendor/golang.org/x/tools/internal/imports/fix.go @@ -27,12 +27,13 @@ import ( "unicode" "unicode/utf8" + "maps" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/stdlib" - "maps" ) // importToGroup is a list of functions which map from an import path to @@ -290,8 +291,8 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro return nil } -// if there is a trailing major version, remove it -func withoutVersion(nm string) string { +// WithoutVersion removes a trailing major version, if there is one. +func WithoutVersion(nm string) string { if v := path.Base(nm); len(v) > 0 && v[0] == 'v' { if _, err := strconv.Atoi(v[1:]); err == nil { // this is, for instance, called with rand/v2 and returns rand @@ -313,7 +314,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { } known := p.knownPackages[imp.ImportPath] if known != nil && known.Name != "" { - return withoutVersion(known.Name) + return WithoutVersion(known.Name) } return ImportPathToAssumedName(imp.ImportPath) } diff --git a/event-processor/vendor/golang.org/x/tools/internal/imports/imports.go b/event-processor/vendor/golang.org/x/tools/internal/imports/imports.go index 2215a128..b5f5218b 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/event-processor/vendor/golang.org/x/tools/internal/imports/imports.go @@ -93,7 +93,7 @@ func FixImports(ctx context.Context, filename string, src []byte, goroot string, // env is needed. func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) { // Don't use parse() -- we don't care about fragments or statement lists - // here, and we need to work with unparseable files. + // here, and we need to work with unparsable files. fileSet := token.NewFileSet() parserMode := parser.SkipObjectResolution if opt.Comments { diff --git a/event-processor/vendor/golang.org/x/tools/internal/imports/source_modindex.go b/event-processor/vendor/golang.org/x/tools/internal/imports/source_modindex.go index 05229f06..ca745d4a 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/imports/source_modindex.go +++ b/event-processor/vendor/golang.org/x/tools/internal/imports/source_modindex.go @@ -15,6 +15,10 @@ import ( // This code is here rather than in the modindex package // to avoid import loops +// TODO(adonovan): this code is only used by a test in this package. +// Can we delete it? Or is there a plan to call NewIndexSource from +// cmd/goimports? + // implements Source using modindex, so only for module cache. // // this is perhaps over-engineered. A new Index is read at first use. @@ -22,8 +26,8 @@ import ( // is read if the index changed. It is not clear the Mutex is needed. type IndexSource struct { modcachedir string - mutex sync.Mutex - ix *modindex.Index + mu sync.Mutex + index *modindex.Index // (access via getIndex) expires time.Time } @@ -39,13 +43,14 @@ func (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths } func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) { - if err := s.maybeReadIndex(); err != nil { + index, err := s.getIndex() + if err != nil { return nil, err } var cs []modindex.Candidate for pkg, nms := range missing { for nm := range nms { - x := s.ix.Lookup(pkg, nm, false) + x := index.Lookup(pkg, nm, false) cs = append(cs, x...) } } @@ -74,30 +79,22 @@ func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, mi return ans, nil } -func (s *IndexSource) maybeReadIndex() error { - s.mutex.Lock() - defer s.mutex.Unlock() - - var readIndex bool - if time.Now().After(s.expires) { - ok, err := modindex.Update(s.modcachedir) - if err != nil { - return err - } - if ok { - readIndex = true - } - } +func (s *IndexSource) getIndex() (*modindex.Index, error) { + s.mu.Lock() + defer s.mu.Unlock() - if readIndex || s.ix == nil { - ix, err := modindex.ReadIndex(s.modcachedir) + // (s.index = nil => s.expires is zero, + // so the first condition is strictly redundant. + // But it makes the postcondition very clear.) + if s.index == nil || time.Now().After(s.expires) { + index, err := modindex.Update(s.modcachedir) if err != nil { - return err + return nil, err } - s.ix = ix - // for now refresh every 15 minutes - s.expires = time.Now().Add(time.Minute * 15) + s.index = index + s.expires = index.ValidAt.Add(15 * time.Minute) // (refresh period) } + // Inv: s.index != nil - return nil + return s.index, nil } diff --git a/event-processor/vendor/golang.org/x/tools/internal/modindex/directories.go b/event-processor/vendor/golang.org/x/tools/internal/modindex/directories.go index 1e1a02f2..9a963744 100644 --- a/event-processor/vendor/golang.org/x/tools/internal/modindex/directories.go +++ b/event-processor/vendor/golang.org/x/tools/internal/modindex/directories.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "regexp" - "slices" "strings" "sync" "time" @@ -20,50 +19,48 @@ import ( ) type directory struct { - path Relpath + path string // relative to GOMODCACHE importPath string version string // semantic version - syms []symbol } -// filterDirs groups the directories by import path, -// sorting the ones with the same import path by semantic version, -// most recent first. -func byImportPath(dirs []Relpath) (map[string][]*directory, error) { - ans := make(map[string][]*directory) // key is import path - for _, d := range dirs { - ip, sv, err := DirToImportPathVersion(d) +// bestDirByImportPath returns the best directory for each import +// path, where "best" means most recent semantic version. These import +// paths are inferred from the GOMODCACHE-relative dir names in dirs. +func bestDirByImportPath(dirs []string) (map[string]directory, error) { + dirsByPath := make(map[string]directory) + for _, dir := range dirs { + importPath, version, err := dirToImportPathVersion(dir) if err != nil { return nil, err } - ans[ip] = append(ans[ip], &directory{ - path: d, - importPath: ip, - version: sv, - }) - } - for k, v := range ans { - semanticSort(v) - ans[k] = v + new := directory{ + path: dir, + importPath: importPath, + version: version, + } + if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 { + dirsByPath[importPath] = new + } } - return ans, nil + return dirsByPath, nil } -// sort the directories by semantic version, latest first -func semanticSort(v []*directory) { - slices.SortFunc(v, func(l, r *directory) int { - if n := semver.Compare(l.version, r.version); n != 0 { - return -n // latest first - } - return strings.Compare(string(l.path), string(r.path)) - }) +// compareDirectory defines an ordering of path@version directories, +// by descending version, then by ascending path. +func compareDirectory(x, y directory) int { + if sign := -semver.Compare(x.version, y.version); sign != 0 { + return sign // latest first + } + return strings.Compare(string(x.path), string(y.path)) } // modCacheRegexp splits a relpathpath into module, module version, and package. var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`) -// DirToImportPathVersion computes import path and semantic version -func DirToImportPathVersion(dir Relpath) (string, string, error) { +// dirToImportPathVersion computes import path and semantic version +// from a GOMODCACHE-relative directory name. +func dirToImportPathVersion(dir string) (string, string, error) { m := modCacheRegexp.FindStringSubmatch(string(dir)) // m[1] is the module path // m[2] is the version major.minor.patch(-

 that contains the name
+// Package modindex contains code for building and searching an
+// [Index] of the Go module cache.
+package modindex
+
+// The directory containing the index, returned by
+// [IndexDir], contains a file index-name- that contains the name
 // of the current index. We believe writing that short file is atomic.
-// ReadIndex reads that file to get the file name of the index.
+// [Read] reads that file to get the file name of the index.
 // WriteIndex writes an index with a unique name and then
 // writes that name into a new version of index-name-.
 // ( stands for the CurrentVersion of the index format.)
-package modindex
 
 import (
+	"maps"
+	"os"
 	"path/filepath"
 	"slices"
 	"strings"
@@ -21,144 +25,95 @@ import (
 	"golang.org/x/mod/semver"
 )
 
-// Create always creates a new index for the go module cache that is in cachedir.
-func Create(cachedir string) error {
-	_, err := indexModCache(cachedir, true)
-	return err
-}
-
-// Update the index for the go module cache that is in cachedir,
-// If there is no existing index it will build one.
-// If there are changed directories since the last index, it will
-// write a new one and return true. Otherwise it returns false.
-func Update(cachedir string) (bool, error) {
-	return indexModCache(cachedir, false)
+// Update updates the index for the specified Go
+// module cache directory, creating it as needed.
+// On success it returns the current index.
+func Update(gomodcache string) (*Index, error) {
+	prev, err := Read(gomodcache)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return nil, err
+		}
+		prev = nil
+	}
+	return update(gomodcache, prev)
 }
 
-// indexModCache writes an index current as of when it is called.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and the updates to the cache. It returns true if it wrote an index,
-// false otherwise.
-func indexModCache(cachedir string, clear bool) (bool, error) {
-	cachedir, err := filepath.Abs(cachedir)
+// update builds, writes, and returns the current index.
+//
+// If old is nil, the new index is built from all of GOMODCACHE;
+// otherwise it is built from the old index plus cache updates
+// since the previous index's time.
+func update(gomodcache string, old *Index) (*Index, error) {
+	gomodcache, err := filepath.Abs(gomodcache)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	cd := Abspath(cachedir)
-	future := time.Now().Add(24 * time.Hour) // safely in the future
-	ok, err := modindexTimed(future, cd, clear)
+	new, changed, err := build(gomodcache, old)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	return ok, nil
-}
-
-// modindexTimed writes an index current as of onlyBefore.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and all the updates to the cache before onlyBefore.
-// It returns true if it wrote a new index, false if it wrote nothing.
-func modindexTimed(onlyBefore time.Time, cachedir Abspath, clear bool) (bool, error) {
-	var curIndex *Index
-	if !clear {
-		var err error
-		curIndex, err = ReadIndex(string(cachedir))
-		if clear && err != nil {
-			return false, err
+	if old == nil || changed {
+		if err := write(gomodcache, new); err != nil {
+			return nil, err
 		}
-		// TODO(pjw): check that most of those directories still exist
-	}
-	cfg := &work{
-		onlyBefore: onlyBefore,
-		oldIndex:   curIndex,
-		cacheDir:   cachedir,
-	}
-	if curIndex != nil {
-		cfg.onlyAfter = curIndex.Changed
-	}
-	if err := cfg.buildIndex(); err != nil {
-		return false, err
 	}
-	if len(cfg.newIndex.Entries) == 0 && curIndex != nil {
-		// no changes from existing curIndex, don't write a new index
-		return false, nil
-	}
-	if err := cfg.writeIndex(); err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-type work struct {
-	onlyBefore time.Time // do not use directories later than this
-	onlyAfter  time.Time // only interested in directories after this
-	// directories from before onlyAfter come from oldIndex
-	oldIndex *Index
-	newIndex *Index
-	cacheDir Abspath
+	return new, nil
 }
 
-func (w *work) buildIndex() error {
-	// The effective date of the new index should be at least
-	// slightly earlier than when the directories are scanned
-	// so set it now.
-	w.newIndex = &Index{Changed: time.Now(), Cachedir: w.cacheDir}
-	dirs := findDirs(string(w.cacheDir), w.onlyAfter, w.onlyBefore)
-	if len(dirs) == 0 {
-		return nil
+// build returns a new index for the specified Go module cache (an
+// absolute path).
+//
+// If an old index is provided, only directories more recent than it
+// that it are scanned; older directories are provided by the old
+// Index.
+//
+// The boolean result indicates whether new entries were found.
+func build(gomodcache string, old *Index) (*Index, bool, error) {
+	// Set the time window.
+	var start time.Time // = dawn of time
+	if old != nil {
+		start = old.ValidAt
 	}
-	newdirs, err := byImportPath(dirs)
+	now := time.Now()
+	end := now.Add(24 * time.Hour) // safely in the future
+
+	// Enumerate GOMODCACHE package directories.
+	// Choose the best (latest) package for each import path.
+	pkgDirs := findDirs(gomodcache, start, end)
+	dirByPath, err := bestDirByImportPath(pkgDirs)
 	if err != nil {
-		return err
+		return nil, false, err
 	}
-	// for each import path it might occur only in newdirs,
-	// only in w.oldIndex, or in both.
-	// If it occurs in both, use the semantically later one
-	if w.oldIndex != nil {
-		for _, e := range w.oldIndex.Entries {
-			found, ok := newdirs[e.ImportPath]
-			if !ok {
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				continue // use this one, there is no new one
-			}
-			if semver.Compare(found[0].version, e.Version) > 0 {
-				// use the new one
-			} else {
-				// use the old one, forget the new one
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				delete(newdirs, e.ImportPath)
+
+	// For each import path it might occur only in
+	// dirByPath, only in old, or in both.
+	// If both, use the semantically later one.
+	var entries []Entry
+	if old != nil {
+		for _, entry := range old.Entries {
+			dir, ok := dirByPath[entry.ImportPath]
+			if !ok || semver.Compare(dir.version, entry.Version) <= 0 {
+				// New dir is missing or not more recent; use old entry.
+				entries = append(entries, entry)
+				delete(dirByPath, entry.ImportPath)
 			}
 		}
 	}
-	// get symbol information for all the new diredtories
-	getSymbols(w.cacheDir, newdirs)
-	// assemble the new index entries
-	for k, v := range newdirs {
-		d := v[0]
-		pkg, names := processSyms(d.syms)
-		if pkg == "" {
-			continue // PJW: does this ever happen?
-		}
-		entry := Entry{
-			PkgName:    pkg,
-			Dir:        d.path,
-			ImportPath: k,
-			Version:    d.version,
-			Names:      names,
-		}
-		w.newIndex.Entries = append(w.newIndex.Entries, entry)
-	}
-	// sort the entries in the new index
-	slices.SortFunc(w.newIndex.Entries, func(l, r Entry) int {
-		if n := strings.Compare(l.PkgName, r.PkgName); n != 0 {
+
+	// Extract symbol information for all the new directories.
+	newEntries := extractSymbols(gomodcache, maps.Values(dirByPath))
+	entries = append(entries, newEntries...)
+	slices.SortFunc(entries, func(x, y Entry) int {
+		if n := strings.Compare(x.PkgName, y.PkgName); n != 0 {
 			return n
 		}
-		return strings.Compare(l.ImportPath, r.ImportPath)
+		return strings.Compare(x.ImportPath, y.ImportPath)
 	})
-	return nil
-}
 
-func (w *work) writeIndex() error {
-	return writeIndex(w.cacheDir, w.newIndex)
+	return &Index{
+		GOMODCACHE: gomodcache,
+		ValidAt:    now, // time before the directories were scanned
+		Entries:    entries,
+	}, len(newEntries) > 0, nil
 }
diff --git a/event-processor/vendor/golang.org/x/tools/internal/modindex/symbols.go b/event-processor/vendor/golang.org/x/tools/internal/modindex/symbols.go
index b918529d..fe24db9b 100644
--- a/event-processor/vendor/golang.org/x/tools/internal/modindex/symbols.go
+++ b/event-processor/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -10,11 +10,13 @@ import (
 	"go/parser"
 	"go/token"
 	"go/types"
+	"iter"
 	"os"
 	"path/filepath"
 	"runtime"
 	"slices"
 	"strings"
+	"sync"
 
 	"golang.org/x/sync/errgroup"
 )
@@ -30,45 +32,69 @@ import (
 type symbol struct {
 	pkg  string // name of the symbols's package
 	name string // declared name
-	kind string // T, C, V, or F, follwed by D if deprecated
+	kind string // T, C, V, or F, followed by D if deprecated
 	sig  string // signature information, for F
 }
 
-// find the symbols for the best directories
-func getSymbols(cd Abspath, dirs map[string][]*directory) {
+// extractSymbols returns a (new, unordered) array of Entries, one for
+// each provided package directory, describing its exported symbols.
+func extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {
+	var (
+		mu      sync.Mutex
+		entries []Entry
+	)
+
 	var g errgroup.Group
 	g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
-	for _, vv := range dirs {
-		// throttling some day?
-		d := vv[0]
+	for dir := range dirs {
 		g.Go(func() error {
-			thedir := filepath.Join(string(cd), string(d.path))
+			thedir := filepath.Join(cwd, string(dir.path))
 			mode := parser.SkipObjectResolution | parser.ParseComments
 
-			fi, err := os.ReadDir(thedir)
+			// Parse all Go files in dir and extract symbols.
+			dirents, err := os.ReadDir(thedir)
 			if err != nil {
 				return nil // log this someday?
 			}
-			for _, fx := range fi {
-				if !strings.HasSuffix(fx.Name(), ".go") || strings.HasSuffix(fx.Name(), "_test.go") {
+			var syms []symbol
+			for _, dirent := range dirents {
+				if !strings.HasSuffix(dirent.Name(), ".go") ||
+					strings.HasSuffix(dirent.Name(), "_test.go") {
 					continue
 				}
-				fname := filepath.Join(thedir, fx.Name())
+				fname := filepath.Join(thedir, dirent.Name())
 				tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
 				if err != nil {
 					continue // ignore errors, someday log them?
 				}
-				d.syms = append(d.syms, getFileExports(tr)...)
+				syms = append(syms, getFileExports(tr)...)
+			}
+
+			// Create an entry for the package.
+			pkg, names := processSyms(syms)
+			if pkg != "" {
+				mu.Lock()
+				defer mu.Unlock()
+				entries = append(entries, Entry{
+					PkgName:    pkg,
+					Dir:        dir.path,
+					ImportPath: dir.importPath,
+					Version:    dir.version,
+					Names:      names,
+				})
 			}
+
 			return nil
 		})
 	}
-	g.Wait()
+	g.Wait() // ignore error
+
+	return entries
 }
 
 func getFileExports(f *ast.File) []symbol {
 	pkg := f.Name.Name
-	if pkg == "main" {
+	if pkg == "main" || pkg == "" {
 		return nil
 	}
 	var ans []symbol
@@ -110,7 +136,7 @@ func getFileExports(f *ast.File) []symbol {
 				// The only place a $ can occur seems to be in a struct tag, which
 				// can be an arbitrary string literal, and ExprString does not presently
 				// print struct tags. So for this to happen the type of a formal parameter
-				// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
+				// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
 				// would have to show the struct tag. Even testing for this case seems
 				// a waste of effort, but let's remember the possibility
 				if strings.Contains(tp, "$") {
@@ -202,17 +228,18 @@ func processSyms(syms []symbol) (string, []string) {
 	pkg := syms[0].pkg
 	var names []string
 	for _, s := range syms {
+		if s.pkg != pkg {
+			// Symbols came from two files in same dir
+			// with different package declarations.
+			continue
+		}
 		var nx string
-		if s.pkg == pkg {
-			if s.sig != "" {
-				nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
-			} else {
-				nx = fmt.Sprintf("%s %s", s.name, s.kind)
-			}
-			names = append(names, nx)
+		if s.sig != "" {
+			nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
 		} else {
-			continue // PJW: do we want to keep track of these?
+			nx = fmt.Sprintf("%s %s", s.name, s.kind)
 		}
+		names = append(names, nx)
 	}
 	return pkg, names
 }
diff --git a/event-processor/vendor/golang.org/x/tools/internal/modindex/types.go b/event-processor/vendor/golang.org/x/tools/internal/modindex/types.go
deleted file mode 100644
index ece44886..00000000
--- a/event-processor/vendor/golang.org/x/tools/internal/modindex/types.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modindex
-
-import (
-	"strings"
-)
-
-// some special types to avoid confusions
-
-// distinguish various types of directory names. It's easy to get confused.
-type Abspath string // absolute paths
-type Relpath string // paths with GOMODCACHE prefix removed
-
-func toRelpath(cachedir Abspath, s string) Relpath {
-	if strings.HasPrefix(s, string(cachedir)) {
-		if s == string(cachedir) {
-			return Relpath("")
-		}
-		return Relpath(s[len(cachedir)+1:])
-	}
-	return Relpath(s)
-}
diff --git a/event-processor/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/event-processor/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 73eefa2a..929b470b 100644
--- a/event-processor/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/event-processor/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -5,6 +5,8 @@
 // Package packagesinternal exposes internal-only fields from go/packages.
 package packagesinternal
 
+import "fmt"
+
 var GetDepsErrors = func(p any) []*PackageError { return nil }
 
 type PackageError struct {
@@ -13,5 +15,9 @@ type PackageError struct {
 	Err         string   // the error itself
 }
 
+func (err PackageError) String() string {
+	return fmt.Sprintf("%s: %s (import stack: %s)", err.Pos, err.Err, err.ImportStack)
+}
+
 var TypecheckCgo int
 var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
diff --git a/event-processor/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go b/event-processor/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
index 649c82b6..3db2a135 100644
--- a/event-processor/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
+++ b/event-processor/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
@@ -65,14 +65,16 @@ func ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {
 	if info.Types == nil {
 		panic("ClassifyCall: info.Types is nil")
 	}
-	if info.Types[call.Fun].IsType() {
+	tv := info.Types[call.Fun]
+	if tv.IsType() {
 		return CallConversion
 	}
+	if tv.IsBuiltin() {
+		return CallBuiltin
+	}
 	obj := info.Uses[UsedIdent(info, call.Fun)]
 	// Classify the call by the type of the object, if any.
 	switch obj := obj.(type) {
-	case *types.Builtin:
-		return CallBuiltin
 	case *types.Func:
 		if interfaceMethod(obj) {
 			return CallInterface
diff --git a/event-processor/vendor/golang.org/x/tools/internal/typesinternal/types.go b/event-processor/vendor/golang.org/x/tools/internal/typesinternal/types.go
index cc244689..a5cd7e8d 100644
--- a/event-processor/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/event-processor/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -69,6 +69,34 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 	}
 }
 
+// TypeNameFor returns the type name symbol for the specified type, if
+// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a
+// [*types.Basic] representing a type.
+//
+// For all other types, and for Basic types representing a builtin,
+// constant, or nil, it returns nil. Be careful not to convert the
+// resulting nil pointer to a [types.Object]!
+//
+// If t is the type of a constant, it may be an "untyped" type, which
+// has no TypeName. To access the name of such types (e.g. "untyped
+// int"), use [types.Basic.Name].
+func TypeNameFor(t types.Type) *types.TypeName {
+	switch t := t.(type) {
+	case *types.Alias:
+		return t.Obj()
+	case *types.Named:
+		return t.Obj()
+	case *types.TypeParam:
+		return t.Obj()
+	case *types.Basic:
+		// See issues #71886 and #66890 for some history.
+		if tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {
+			return tname
+		}
+	}
+	return nil
+}
+
 // A NamedOrAlias is a [types.Type] that is named (as
 // defined by the spec) and capable of bearing type parameters: it
 // abstracts aliases ([types.Alias]) and defined types
@@ -77,7 +105,7 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 // Every type declared by an explicit "type" declaration is a
 // NamedOrAlias. (Built-in type symbols may additionally
 // have type [types.Basic], which is not a NamedOrAlias,
-// though the spec regards them as "named".)
+// though the spec regards them as "named"; see [TypeNameFor].)
 //
 // NamedOrAlias cannot expose the Origin method, because
 // [types.Alias.Origin] and [types.Named.Origin] have different
@@ -85,32 +113,15 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 type NamedOrAlias interface {
 	types.Type
 	Obj() *types.TypeName
-	// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
-}
-
-// TypeParams is a light shim around t.TypeParams().
-// (go/types.Alias).TypeParams requires >= 1.23.
-func TypeParams(t NamedOrAlias) *types.TypeParamList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeParams(t)
-	case *types.Named:
-		return t.TypeParams()
-	}
-	return nil
+	TypeArgs() *types.TypeList
+	TypeParams() *types.TypeParamList
+	SetTypeParams(tparams []*types.TypeParam)
 }
 
-// TypeArgs is a light shim around t.TypeArgs().
-// (go/types.Alias).TypeArgs requires >= 1.23.
-func TypeArgs(t NamedOrAlias) *types.TypeList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeArgs(t)
-	case *types.Named:
-		return t.TypeArgs()
-	}
-	return nil
-}
+var (
+	_ NamedOrAlias = (*types.Alias)(nil)
+	_ NamedOrAlias = (*types.Named)(nil)
+)
 
 // Origin returns the generic type of the Named or Alias type t if it
 // is instantiated, otherwise it returns t.
diff --git a/event-processor/vendor/golang.org/x/vuln/LICENSE b/event-processor/vendor/golang.org/x/vuln/LICENSE
index 6a66aea5..2a7cf70d 100644
--- a/event-processor/vendor/golang.org/x/vuln/LICENSE
+++ b/event-processor/vendor/golang.org/x/vuln/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
+Copyright 2009 The Go Authors.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
-   * Neither the name of Google Inc. nor the names of its
+   * Neither the name of Google LLC nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.
 
diff --git a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
index b7b16d9f..8de6904a 100644
--- a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
+++ b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
@@ -9,10 +9,10 @@ only those that could affect the application.
 
 By default, govulncheck makes requests to the Go vulnerability database at
 https://vuln.go.dev. Requests to the vulnerability database contain only module
-paths, not code or other properties of your program. See
-https://vuln.go.dev/privacy.html for more. Use the -db flag to specify a
-different database, which must implement the specification at
-https://go.dev/security/vuln/database.
+paths with vulnerabilities already known to the database, not code or other
+properties of your program. See https://vuln.go.dev/privacy.html for more.
+Use the -db flag to specify a different database, which must implement the
+specification at https://go.dev/security/vuln/database.
 
 Govulncheck looks for vulnerabilities in Go programs using a specific build
 configuration. For analyzing source code, that configuration is the Go version
@@ -20,8 +20,6 @@ specified by the “go” command found on the PATH. For binaries, the build
 configuration is the one used to build the binary. Note that different build
 configurations may have different known vulnerabilities.
 
-Govulncheck must be built with Go version 1.18 or later.
-
 # Usage
 
 To analyze source code, run govulncheck from the module directory, using the
@@ -41,44 +39,45 @@ To control which files are processed, use the -tags flag to provide a
 comma-separated list of build tags, and the -test flag to indicate that test
 files should be included.
 
-To run govulncheck on a compiled binary, pass it the path to the binary file
-with the -mode=binary flag:
-
-	$ govulncheck -mode=binary $HOME/go/bin/my-go-program
+To include more detailed stack traces, pass '-show traces', this will cause it to
+print the full call stack for each entry.
 
-Govulncheck uses the binary's symbol information to find mentions of vulnerable
-functions. Its output omits call stacks, which require source code analysis.
+To include progress messages and more details on findings, pass '-show verbose'.
 
-Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
-and exits unsuccessfully if there are. It also exits successfully if -json flag
-is provided, regardless of the number of detected vulnerabilities.
+To run govulncheck on a compiled binary, pass it the path to the binary file
+with the '-mode binary' flag:
 
-# Flags
+	$ govulncheck -mode binary $HOME/go/bin/my-go-program
 
-A few flags control govulncheck's behavior.
+Govulncheck uses the binary's symbol information to find mentions of vulnerable
+functions. These functions can belong to binary's transitive dependencies and
+also the main module of the binary. The latter functions are checked for only
+when the precise version of the binary module is known. Govulncheck output on
+binaries omits call stacks, which require source code analysis.
 
-The -C flag causes govulncheck to change its working directory to the provided
-directory before running. Any patterns or files named on the command line are
-interpreted after changing directories.
+Govulncheck also supports '-mode extract' on a Go binary for extraction of minimal
+information needed to analyze the binary. This will produce a blob, typically much
+smaller than the binary, that can also be passed to govulncheck as an argument with
+'-mode binary'. The users should not rely on the contents or representation of the blob.
 
-The -db flag causes govulncheck to read from the specified database, which must
-implement the specification at https://go.dev/security/vuln/database. By
-default, govulncheck fetches vulnerability data from https://vuln.go.dev.
+# Integrations
 
-The -json flag causes govulncheck to print its output as a JSON object
-corresponding to the type [golang.org/x/vuln/internal/govulncheck.Result]. The
-exit code of govulncheck is 0 when this flag is provided.
+Govulncheck supports streaming JSON. For more details, please see [golang.org/x/vuln/internal/govulncheck].
 
-The -mode flag causes govulncheck to run source or binary analysis. By default,
-govulnchecks runs source analysis.
+Govulncheck also supports Static Analysis Results Interchange Format (SARIF) output
+format, following the specification at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+For more details, please see [golang.org/x/vuln/internal/sarif].
 
-The -tags flag accepts a comma-separated list of build tags to control which
-files should be included in loaded packages for source analysis.
+Govulncheck supports the Vulnerability EXchange (VEX) output format, following
+the specification at https://github.com/openvex/spec.
+For more details, please see [golang.org/x/vuln/internal/openvex].
 
-The -test flag causes govulncheck to include test files in the source analysis.
+# Exit codes
 
-The -v flag causes govulncheck to output more information when run on source.
-It has no effect when run on a binary.
+Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
+and exits unsuccessfully if there are. It also exits successfully if the
+'format -json' ('-json'), '-format sarif', or '-format openvex' is provided,
+regardless of the number of detected vulnerabilities.
 
 # Limitations
 
@@ -88,22 +87,20 @@ Govulncheck has these limitations:
     which may result in false positives or inaccurate call stacks in some cases.
   - Calls to functions made using package reflect are not visible to static
     analysis. Vulnerable code reachable only through those calls will not be
-    reported.
+    reported in source scan mode. Similarly, use of the unsafe package may
+    result in false negatives.
   - Because Go binaries do not contain detailed call information, govulncheck
     cannot show the call graphs for detected vulnerabilities. It may also
     report false positives for code that is in the binary but unreachable.
-  - There is no support for silencing vulnerability findings.
-  - Govulncheck only reads binaries compiled with Go 1.18 and later.
-  - Govulncheck only reports vulnerabilities that apply to the current Go
-    version. For example, a standard library vulnerability that only applies for
-    Go 1.18 will not be reported if the current Go version is 1.19. See
-    https://go.dev/issue/54841 for updates to this limitation.
+  - There is no support for silencing vulnerability findings. See https://go.dev/issue/61211 for
+    updates.
+  - Govulncheck reports only standard library vulnerabilities for binaries
+    built with Go versions prior to Go 1.18.
   - For binaries where the symbol information cannot be extracted, govulncheck
     reports vulnerabilities for all modules on which the binary depends.
 
 # Feedback
 
-Govulncheck is an experimental tool under active development. To share
-feedback, see https://go.dev/security/vuln#feedback.
+To share feedback, see https://go.dev/security/vuln#feedback.
 */
 package main
diff --git a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
new file mode 100644
index 00000000..288c10c2
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
@@ -0,0 +1,12 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.23
+
+//go:debug gotypesalias=1
+
+package main
+
+// Materialize aliases whenever the go toolchain version is after 1.23 (#69772).
+// Remove this file after go.mod >= 1.23 (which implies gotypesalias=1).
diff --git a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/main.go b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
index f6ca253f..73e3370a 100644
--- a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
+++ b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
@@ -9,10 +9,13 @@ import (
 	"fmt"
 	"os"
 
+	"golang.org/x/telemetry"
 	"golang.org/x/vuln/scan"
 )
 
 func main() {
+	telemetry.Start(telemetry.Config{ReportCrashes: true})
+
 	ctx := context.Background()
 
 	cmd := scan.Command(ctx, os.Args[1:]...)
diff --git a/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
new file mode 100644
index 00000000..826d6caf
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
@@ -0,0 +1,128 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"testing"
+)
+
+// copyTestCase copies the test case at dir into a
+// temporary directory. The created files have 0644
+// permission and directories 0755. It does not create
+// symlinks.
+func copyTestCase(dir string, t *testing.T) string {
+	newDir, err := filepath.Abs(t.TempDir())
+	if err != nil {
+		t.Fatalf("failed to copy test case %s: cannot create root %v", dir, err)
+	}
+
+	if err := copyDir(dir, newDir); err != nil {
+		t.Fatalf("failed to copy test case %s: copy failure %v", dir, err)
+	}
+	return newDir
+}
+
+func copyDir(srcDir, destDir string) error {
+	entries, err := os.ReadDir(srcDir)
+	if err != nil {
+		return err
+	}
+	for _, entry := range entries {
+		src := filepath.Join(srcDir, entry.Name())
+		dest := filepath.Join(destDir, entry.Name())
+
+		fileInfo, err := os.Stat(src)
+		if err != nil {
+			return err
+		}
+
+		switch fileInfo.Mode() & os.ModeType {
+		case os.ModeDir:
+			if err := os.MkdirAll(dest, 0755); err != nil {
+				return err
+			}
+			if err := copyDir(src, dest); err != nil {
+				return err
+			}
+		default:
+			if err := copyFile(src, dest); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func copyFile(src, dest string) error {
+	b, err := os.ReadFile(src)
+	if err != nil {
+		return err
+	}
+	return os.WriteFile(dest, b, 0644)
+}
+
+type config struct {
+	// SkipGOOS is a list of GOOS to skip
+	SkipGOOS []string `json:"skipGOOS,omitempty"`
+	// Copy the folder to isolate it
+	Copy bool `json:"copy,omitempty"`
+	// SkipBuild the test case
+	SkipBuild bool `json:"skipBuild,omitempty"`
+	// Strip indicates if binaries should be stripped
+	Strip bool `json:"strip,omitempty"`
+	// EnableSBOM indicates if sbom should be
+	// printed in JSON.
+	EnableSBOM bool `json:"sbom,omitempty"`
+
+	Fixups []fixup `json:"fixups,omitempty"`
+}
+
+func (c *config) skip() bool {
+	for _, sg := range c.SkipGOOS {
+		if runtime.GOOS == sg {
+			return true
+		}
+	}
+	return false
+}
+
+type fixup struct {
+	Pattern     string `json:"pattern,omitempty"`
+	Replace     string `json:"replace,omitempty"`
+	compiled    *regexp.Regexp
+	replaceFunc func(b []byte) []byte
+}
+
+func (f *fixup) init() {
+	f.compiled = regexp.MustCompile(f.Pattern)
+}
+
+func (f *fixup) apply(data []byte) []byte {
+	if f.replaceFunc != nil {
+		return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
+	}
+	return f.compiled.ReplaceAll(data, []byte(f.Replace))
+}
+
+// loadConfig loads and initializes the config from path.
+func loadConfig(path string) (*config, error) {
+	b, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	var cfg config
+	if err := json.Unmarshal(b, &cfg); err != nil {
+		return nil, err
+	}
+	for i := range cfg.Fixups {
+		cfg.Fixups[i].init()
+	}
+	return &cfg, nil
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/README.md
similarity index 100%
rename from event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md
rename to event-processor/vendor/golang.org/x/vuln/internal/buildinfo/README.md
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
new file mode 100644
index 00000000..49869ce3
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
@@ -0,0 +1,257 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// This file adds to buildinfo the functionality for extracting the PCLN table.
+
+import (
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// ErrNoSymbols represents non-existence of symbol
+// table in binaries supported by buildinfo.
+var ErrNoSymbols = errors.New("no symbol section")
+
+// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
+func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil || sym == nil {
+		if errors.Is(err, elf.ErrNoSymbols) {
+			return 0, 0, nil, ErrNoSymbols
+		}
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	prog := x.progContaining(sym.Value)
+	if prog == nil {
+		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
+}
+
+func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		syms, err := x.f.Symbols()
+		if err != nil {
+			x.symbolsErr = err
+			return
+		}
+		x.symbols = make(map[string]*elf.Symbol, len(syms))
+		for _, s := range syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *elfExe) progContaining(addr uint64) *elf.Prog {
+	for _, p := range x.f.Progs {
+		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
+			return p
+		}
+	}
+	return nil
+}
+
+const go12magic = 0xfffffffb
+const go116magic = 0xfffffffa
+
+// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
+func (x *elfExe) PCLNTab() ([]byte, uint64) {
+	var offset uint64
+	text := x.f.Section(".text")
+	if text != nil {
+		offset = text.Offset
+	}
+	pclntab := x.f.Section(".gopclntab")
+	if pclntab == nil {
+		// Addition: this code is added to support some form of stripping.
+		pclntab = x.f.Section(".data.rel.ro.gopclntab")
+		if pclntab == nil {
+			pclntab = x.f.Section(".data.rel.ro")
+			if pclntab == nil {
+				return nil, 0
+			}
+			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
+			// its own section header. We can search for for the start by looking for the four
+			// byte magic and the go magic.
+			b, err := pclntab.Data()
+			if err != nil {
+				return nil, 0
+			}
+			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
+			// actually correct. During testing it worked, but that may be because I got lucky
+			// with the binary I was using, and we need to do four byte jumps to exhaustively
+			// search the section?
+			for i := 0; i < len(b); i += 16 {
+				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
+					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
+					(b[i+7] == 4 || b[i+7] == 8) {
+					// Also check for the go magic
+					leMagic := binary.LittleEndian.Uint32(b[i:])
+					beMagic := binary.BigEndian.Uint32(b[i:])
+					switch {
+					case leMagic == go12magic:
+						fallthrough
+					case beMagic == go12magic:
+						fallthrough
+					case leMagic == go116magic:
+						fallthrough
+					case beMagic == go116magic:
+						return b[i:], offset
+					}
+				}
+			}
+		}
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, offset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
+func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	sect := x.f.Sections[sym.SectionNumber-1]
+	// In PE, the symbol's value is the offset from the section start.
+	return uint64(sym.Value), 0, sect.ReaderAt, nil
+}
+
+func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
+		if len(x.f.Symbols) == 0 {
+			x.symbolsErr = ErrNoSymbols
+			return
+		}
+		for _, s := range x.f.Symbols {
+			x.symbols[s.Name] = s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
+// Assumes that the underlying symbol table exists, otherwise
+// it might panic.
+func (x *peExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	for _, section := range x.f.Sections {
+		if section.Name == ".text" {
+			textOffset = uint64(section.Offset)
+			break
+		}
+	}
+
+	var start, end int64
+	var section int
+	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
+		start = int64(s.Value)
+		section = int(s.SectionNumber - 1)
+	}
+	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
+		end = int64(s.Value)
+	}
+	if start == 0 || end == 0 {
+		return nil, 0
+	}
+	offset := int64(x.f.Sections[section].Offset) + start
+	size := end - start
+
+	pclntab := make([]byte, size)
+	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
+		return nil, 0
+	}
+	return pclntab, textOffset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
+func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	seg := x.segmentContaining(sym.Value)
+	if seg == nil {
+		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, seg.Addr, seg.ReaderAt, nil
+}
+
+func (x *machoExe) lookupSymbol(name string) (*macho.Symbol, error) {
+	const mustExistSymbol = "runtime.main"
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
+		for _, s := range x.f.Symtab.Syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+		// In the presence of stripping, the symbol table for darwin
+		// binaries will not be empty, but the program symbols will
+		// be missing.
+		if _, ok := x.symbols[mustExistSymbol]; !ok {
+			x.symbolsErr = ErrNoSymbols
+		}
+	})
+
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
+			return seg
+		}
+	}
+	return nil
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
+func (x *machoExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	text := x.f.Section("__text")
+	if text != nil {
+		textOffset = uint64(text.Offset)
+	}
+	pclntab := x.f.Section("__gopclntab")
+	if pclntab == nil {
+		return nil, 0
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, textOffset
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
new file mode 100644
index 00000000..ddbdea08
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
@@ -0,0 +1,160 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Code in this package is dervied from src/cmd/go/internal/version/version.go
+// and cmd/go/internal/version/exe.go.
+
+import (
+	"debug/buildinfo"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"runtime/debug"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/gosym"
+	"golang.org/x/vuln/internal/goversion"
+)
+
+func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
+	packagesModules := make([]*packages.Module, len(debugModules))
+	for i, mod := range debugModules {
+		packagesModules[i] = &packages.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+		if mod.Replace != nil {
+			packagesModules[i].Replace = &packages.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+	}
+	return packagesModules
+}
+
+type Symbol struct {
+	Pkg  string `json:"pkg,omitempty"`
+	Name string `json:"name,omitempty"`
+}
+
+// ExtractPackagesAndSymbols extracts symbols, packages, modules from
+// Go binary file as well as bin's metadata.
+//
+// If the symbol table is not available, such as in the case of stripped
+// binaries, returns module and binary info but without the symbol info.
+func ExtractPackagesAndSymbols(file string) ([]*packages.Module, []Symbol, *debug.BuildInfo, error) {
+	bin, err := os.Open(file)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+	defer bin.Close()
+
+	bi, err := buildinfo.Read(bin)
+	if err != nil {
+		// It could be that bin is an ancient Go binary.
+		v, err := goversion.ReadExe(file)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		bi := &debug.BuildInfo{
+			GoVersion: v.Release,
+			Main:      debug.Module{Path: v.ModuleInfo},
+		}
+		// We cannot analyze symbol tables of ancient binaries.
+		return nil, nil, bi, nil
+	}
+
+	funcSymName := gosym.FuncSymName(bi.GoVersion)
+	if funcSymName == "" {
+		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
+	}
+
+	x, err := openExe(bin)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	value, base, r, err := x.SymbolInfo(funcSymName)
+	if err != nil {
+		if errors.Is(err, ErrNoSymbols) {
+			// bin is stripped, so return just module info and metadata.
+			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+		}
+		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
+	}
+
+	pclntab, textOffset := x.PCLNTab()
+	if pclntab == nil {
+		// If we have build information, but not PCLN table, fall
+		// back to much higher granularity vulnerability checking.
+		return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+	}
+	lineTab := gosym.NewLineTable(pclntab, textOffset)
+	if lineTab == nil {
+		return nil, nil, nil, errors.New("invalid line table")
+	}
+	tab, err := gosym.NewTable(nil, lineTab)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	pkgSyms := make(map[Symbol]bool)
+	for _, f := range tab.Funcs {
+		if f.Func == nil {
+			continue
+		}
+		pkgName, symName, err := parseName(f.Func.Sym)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		pkgSyms[Symbol{pkgName, symName}] = true
+
+		// Collect symbols that were inlined in f.
+		it, err := lineTab.InlineTree(&f, value, base, r)
+		if err != nil {
+			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
+		}
+		for _, ic := range it {
+			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
+			if err != nil {
+				return nil, nil, nil, err
+			}
+			pkgSyms[Symbol{pkgName, symName}] = true
+		}
+	}
+
+	var syms []Symbol
+	for ps := range pkgSyms {
+		syms = append(syms, ps)
+	}
+
+	return debugModulesToPackagesModules(bi.Deps), syms, bi, nil
+}
+
+func parseName(s *gosym.Sym) (pkg, sym string, err error) {
+	symName := s.BaseName()
+	if r := s.ReceiverName(); r != "" {
+		if strings.HasPrefix(r, "(*") {
+			r = strings.Trim(r, "(*)")
+		}
+		symName = fmt.Sprintf("%s.%s", r, symName)
+	}
+
+	pkgName := s.PackageName()
+	if pkgName != "" {
+		pkgName, err = url.PathUnescape(pkgName)
+		if err != nil {
+			return "", "", err
+		}
+	}
+	return pkgName, symName, nil
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
new file mode 100644
index 00000000..f29dffa2
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
@@ -0,0 +1,221 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"fmt"
+	"sync"
+
+	// "internal/xcoff"
+	"io"
+)
+
+// Addition: modification of rawBuildInfo in the original file.
+// openExe returns reader r as an exe.
+func openExe(r io.ReaderAt) (exe, error) {
+	data := make([]byte, 16)
+	if _, err := r.ReadAt(data, 0); err != nil {
+		return nil, err
+	}
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &elfExe{f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &peExe{r: r, f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &machoExe{f: e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type exe interface {
+	// ReadData reads and returns up to size byte starting at virtual address addr.
+	ReadData(addr, size uint64) ([]byte, error)
+
+	// DataStart returns the virtual address of the segment or section that
+	// should contain build information. This is either a specially named section
+	// or the first writable non-zero data segment.
+	DataStart() uint64
+
+	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
+
+	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
+}
+
+// elfExe is the ELF implementation of the exe interface.
+type elfExe struct {
+	f *elf.File
+
+	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once              // Addition: for computing symbols
+	symbolsErr  error                  // Addition: error for computing symbols
+}
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *elfExe) DataStart() uint64 {
+	for _, s := range x.f.Sections {
+		if s.Name == ".go.buildinfo" {
+			return s.Addr
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
+			return p.Vaddr
+		}
+	}
+	return 0
+}
+
+// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
+type peExe struct {
+	r io.ReaderAt
+	f *pe.File
+
+	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once             // Addition: for computing symbols
+	symbolsErr  error                 // Addition: error for computing symbols
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
+			n := uint64(sect.VirtualAddress+sect.Size) - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *peExe) DataStart() uint64 {
+	// Assume data is first writable section.
+	const (
+		IMAGE_SCN_CNT_CODE               = 0x00000020
+		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
+		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
+		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
+		IMAGE_SCN_MEM_READ               = 0x40000000
+		IMAGE_SCN_MEM_WRITE              = 0x80000000
+		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
+		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
+		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
+	)
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 &&
+			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
+			return uint64(sect.VirtualAddress) + x.imageBase()
+		}
+	}
+	return 0
+}
+
+// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
+type machoExe struct {
+	f *macho.File
+
+	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once                // Addition: for computing symbols
+	symbolsErr  error                    // Addition: error for computing symbols
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			n := seg.Addr + seg.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *machoExe) DataStart() uint64 {
+	// Look for section named "__go_buildinfo".
+	for _, sec := range x.f.Sections {
+		if sec.Name == "__go_buildinfo" {
+			return sec.Addr
+		}
+	}
+	// Try the first non-empty writable segment.
+	const RW = 3
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
+			return seg.Addr
+		}
+	}
+	return 0
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/client/index.go b/event-processor/vendor/golang.org/x/vuln/internal/client/index.go
index 5f2d0c00..435980c4 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/client/index.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/client/index.go
@@ -96,7 +96,7 @@ func (i *index) add(entry *osv.Entry) {
 		module.Vulns = append(module.Vulns, moduleVuln{
 			ID:       entry.ID,
 			Modified: entry.Modified,
-			Fixed:    isem.LatestFixedVersion(affected.Ranges),
+			Fixed:    isem.NonSupersededFix(affected.Ranges),
 		})
 	}
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/client/source.go b/event-processor/vendor/golang.org/x/vuln/internal/client/source.go
index 3e47b09f..2e848c32 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/client/source.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/client/source.go
@@ -45,8 +45,9 @@ type httpSource struct {
 func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err error) {
 	derrors.Wrap(&err, "get(%s)", endpoint)
 
+	method := http.MethodGet
 	reqURL := fmt.Sprintf("%s/%s", hs.url, endpoint+".json.gz")
-	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
+	req, err := http.NewRequestWithContext(ctx, method, reqURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -56,7 +57,7 @@ func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err e
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
+		return nil, fmt.Errorf("HTTP %s %s returned unexpected status: %s", method, reqURL, resp.Status)
 	}
 
 	// Uncompress the result.
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md b/event-processor/vendor/golang.org/x/vuln/internal/gosym/README.md
similarity index 100%
rename from event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md
rename to event-processor/vendor/golang.org/x/vuln/internal/gosym/README.md
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/gosym/additions.go b/event-processor/vendor/golang.org/x/vuln/internal/gosym/additions.go
new file mode 100644
index 00000000..022cf92e
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/gosym/additions.go
@@ -0,0 +1,184 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gosym
+
+import (
+	"encoding/binary"
+	"io"
+	"strings"
+
+	sv "golang.org/x/mod/semver"
+	"golang.org/x/vuln/internal/semver"
+)
+
+const (
+	funcSymNameGo119Lower string = "go.func.*"
+	funcSymNameGo120      string = "go:func.*"
+)
+
+// FuncSymName returns symbol name for Go functions used in binaries
+// based on Go version. Supported Go versions are 1.18 and greater.
+// If the go version is unreadable it assumes that it is a newer version
+// and returns the symbol name for go version 1.20 or greater.
+func FuncSymName(goVersion string) string {
+	// Support devel goX.Y...
+	v := strings.TrimPrefix(goVersion, "devel ")
+	v = semver.GoTagToSemver(v)
+	mm := sv.MajorMinor(v)
+	if sv.Compare(mm, "v1.20") >= 0 || mm == "" {
+		return funcSymNameGo120
+	} else if sv.Compare(mm, "v1.18") >= 0 {
+		return funcSymNameGo119Lower
+	}
+	return ""
+}
+
+// Additions to the original package from cmd/internal/objabi/funcdata.go
+const (
+	pcdata_InlTreeIndex = 2
+	funcdata_InlTree    = 3
+)
+
+// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
+// goFuncValue is the value of the gosym.FuncSymName symbol.
+// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
+// progReader is a ReaderAt positioned at the start of that region.
+func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
+	if f.inlineTreeCount == 0 {
+		return nil, nil
+	}
+	if f.inlineTreeOffset == ^uint32(0) {
+		return nil, nil
+	}
+	var offset int64
+	if t.version >= ver118 {
+		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
+	} else {
+		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
+	}
+
+	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
+	ics := make([]InlinedCall, 0, f.inlineTreeCount)
+	for i := 0; i < f.inlineTreeCount; i++ {
+		if t.version >= ver120 {
+			var ric rawInlinedCall120
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.NameOff)),
+				ParentPC: ric.ParentPC,
+			})
+		} else {
+			var ric rawInlinedCall112
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.Func_)),
+				ParentPC: ric.ParentPC,
+			})
+		}
+	}
+	return ics, nil
+}
+
+// InlinedCall describes a call to an inlined function.
+type InlinedCall struct {
+	FuncID   uint8  // type of the called function
+	Name     string // name of called function
+	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall112 struct {
+	Parent   int16 // index of parent in the inltree, or < 0
+	FuncID   uint8 // type of the called function
+	_        byte
+	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
+	Line     int32 // line number of the call site
+	Func_    int32 // offset into pclntab for name of called function
+	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.20. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall120 struct {
+	FuncID    uint8 // type of the called function
+	_         [3]byte
+	NameOff   int32 // offset into pclntab for name of called function
+	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
+	StartLine int32 // line number of start of function (func keyword/TEXT directive)
+}
+
+func (f funcData) npcdata() uint32 { return f.field(7) }
+func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
+	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
+}
+
+func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.nfuncdata(numFuncFields) {
+		return ^uint32(0)
+	}
+	var off uint32
+	if f.t.version >= ver118 {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4 + // skip pcdata
+			uint32(i)*4 // index of i'th FUNCDATA
+	} else {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4
+		off += uint32(i) * f.t.ptrsize
+	}
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+func (f funcData) fieldOffset(n uint32) uint32 {
+	// In Go 1.18, the first field of _func changed
+	// from a uintptr entry PC to a uint32 entry offset.
+	sz0 := f.t.ptrsize
+	if f.t.version >= ver118 {
+		sz0 = 4
+	}
+	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
+}
+
+func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.npcdata() {
+		return ^uint32(0)
+	}
+	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
+		uint32(i)*4 // index of i'th PCDATA
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+// maxInlineTreeIndexValue returns the maximum value of the inline tree index
+// pc-value table in info. This is the only way to determine how many
+// IndexedCalls are in an inline tree, since the data of the tree itself is not
+// delimited in any way.
+func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
+	if info.npcdata() <= pcdata_InlTreeIndex {
+		return -1
+	}
+	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
+	p := t.pctab[off:]
+	val := int32(-1)
+	max := int32(-1)
+	var pc uint64
+	for t.step(&p, &pc, &val, pc == 0) {
+		if val > max {
+			max = val
+		}
+	}
+	return int(max)
+}
+
+type inlTree struct {
+	inlineTreeOffset uint32 // offset from go.func.* symbol
+	inlineTreeCount  int    // number of entries in inline tree
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go b/event-processor/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
similarity index 100%
rename from event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go
rename to event-processor/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go b/event-processor/vendor/golang.org/x/vuln/internal/gosym/symtab.go
similarity index 100%
rename from event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go
rename to event-processor/vendor/golang.org/x/vuln/internal/gosym/symtab.go
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/goversion/asm.go b/event-processor/vendor/golang.org/x/vuln/internal/goversion/asm.go
new file mode 100644
index 00000000..1c165e60
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/goversion/asm.go
@@ -0,0 +1,349 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"encoding/binary"
+	"fmt"
+	"os"
+)
+
+type matcher [][]uint32
+
+const (
+	pWild    uint32 = 0xff00
+	pAddr    uint32 = 0x10000
+	pEnd     uint32 = 0x20000
+	pRelAddr uint32 = 0x30000
+
+	opMaybe = 1 + iota
+	opMust
+	opDone
+	opAnchor = 0x100
+	opSub8   = 0x200
+	opFlags  = opAnchor | opSub8
+)
+
+var amd64Matcher = matcher{
+	{opMaybe | opAnchor,
+		// __rt0_amd64_darwin:
+		//	JMP __rt0_amd64
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	lea ADDR(%rip), %rax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24, 0x48,
+		0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	mov $ADDR, %eax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24,
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// __rt0_amd64:
+		//	mov (%rsp), %rdi
+		//	lea 8(%rsp), %rsi
+		//	jmp runtime.rt0_g0
+		0x48, 0x8b, 0x3c, 0x24,
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	lea __libc_csu_fini(%rip), %r8
+		//	lea __libc_csu_init(%rip), %rcx
+		//	lea ADDR(%rip), %rdi # main
+		//	callq *xxx(%rip)
+		0x4c, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x3d, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0x15,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	push %rsp (1)
+		//	mov $__libc_csu_fini, %r8 (7)
+		//	mov $__libc_csu_init, %rcx (7)
+		//	mov $ADDR, %rdi # main (7)
+		//	callq *xxx(%rip)
+		0x54,
+		0x49, 0xc7, 0xc0, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc1, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc7, pAddr | pWild, pWild, pWild, pWild,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	lea ADDR(%rip), %rax # rt0_go
+		//	jmpq *%rax
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	mov $ADDR, %eax
+		//	jmpq *%rax
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	JMP runtime.rt0_go(SB)
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMust | opAnchor,
+		// rt0_go:
+		//	mov %rdi, %rax
+		//	mov %rsi, %rbx
+		//	sub %0x27, %rsp
+		//	and $0xfffffffffffffff0,%rsp
+		//	mov %rax,0x10(%rsp)
+		//	mov %rbx,0x18(%rsp)
+		0x48, 0x89, 0xf8,
+		0x48, 0x89, 0xf3,
+		0x48, 0x83, 0xec, 0x27,
+		0x48, 0x83, 0xe4, 0xf0,
+		0x48, 0x89, 0x44, 0x24, 0x10,
+		0x48, 0x89, 0x5c, 0x24, 0x18,
+	},
+	{opMust,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		//	lea other(%rip), %rdi
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0x8d, 0x05,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.hashinit
+		//	callq runtime.schedinit (ADDR)
+		//	pushq $main.main
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x68,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rax
+		//	test %rax, %rax
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc0,
+		0x75, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rbx
+		//	cmp $0x0, %rbx
+		//	jne 
+		//	lea "unknown"(%rip), %rbx
+		//	mov %rbx, ADDR(%rip)
+		//	movq $7, (ADDR+8)(%rip)
+		0x48, 0x8b, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x83, 0xfb, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	lea "unknown"(%rip), %rax
+		//	mov %rax, ADDR(%rip)
+		//	lea ADDR(%rip), %rax
+		//	movq $7, 8(%rax)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		//	test %eax, %eax
+		//	jne 
+		//	lea "unknown"(RIP), %rax
+		//	mov %rax, ADDR(%rip)
+		0x48, 0x85, 0xc0, 0x75, pWild, 0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild, 0x48, 0x89, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rcx
+		//	test %rcx, %rcx
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc9,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+}
+
+var DebugMatch bool
+
+func (m matcher) match(f exe, addr uint64) (uint64, bool) {
+	data, err := f.ReadData(addr, 512)
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
+	}
+	if err != nil {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "match: %v\n", err)
+		}
+		return 0, false
+	}
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
+	}
+Matchers:
+	for pc, p := range m {
+		op := p[0]
+		p = p[1:]
+	Search:
+		for i := 0; i <= len(data)-len(p); i++ {
+			a := -1
+			e := -1
+			if i > 0 && op&opAnchor != 0 {
+				break
+			}
+			for j := 0; j < len(p); j++ {
+				b := byte(p[j])
+				m := byte(p[j] >> 8)
+				if data[i+j]&^m != b {
+					continue Search
+				}
+				if p[j]&pAddr != 0 {
+					a = j
+				}
+				if p[j]&pEnd != 0 {
+					e = j + 1
+				}
+			}
+			// matched
+			if DebugMatch {
+				fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
+			}
+			if a != -1 {
+				val := uint64(int32(binary.LittleEndian.Uint32(data[i+a:])))
+				if e == -1 {
+					addr = val
+				} else {
+					addr += uint64(i+e) + val
+				}
+				if op&opSub8 != 0 {
+					addr -= 8
+				}
+			}
+			if op&^opFlags == opDone {
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "done %x\n", addr)
+				}
+				return addr, true
+			}
+			if a != -1 {
+				// changed addr, so reload
+				data, err = f.ReadData(addr, 512)
+				if err != nil {
+					return 0, false
+				}
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
+				}
+			}
+			continue Matchers
+		}
+		// not matched
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
+		}
+		if op&^opFlags == opMust {
+			return 0, false
+		}
+	}
+	// ran off end of matcher
+	return 0, false
+}
+
+func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
+	entry := f.Entry()
+	if entry == 0 {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "missing entry!\n")
+		}
+		return
+	}
+	addr, ok := amd64Matcher.match(f, entry)
+	if !ok {
+		return
+	}
+	v, err := readBuildVersion(f, addr, 16)
+	if err != nil {
+		return
+	}
+	return true, v
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/goversion/exe.go b/event-processor/vendor/golang.org/x/vuln/internal/goversion/exe.go
new file mode 100644
index 00000000..d833bfe6
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/goversion/exe.go
@@ -0,0 +1,324 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+type sym struct {
+	Name string
+	Addr uint64
+	Size uint64
+}
+
+type exe interface {
+	AddrSize() int // bytes
+	ReadData(addr, size uint64) ([]byte, error)
+	Symbols() ([]sym, error)
+	SectionNames() []string
+	Close() error
+	ByteOrder() binary.ByteOrder
+	Entry() uint64
+	TextRange() (uint64, uint64)
+	RODataRange() (uint64, uint64)
+}
+
+func openExe(file string) (exe, error) {
+	f, err := os.Open(file)
+	if err != nil {
+		return nil, err
+	}
+	data := make([]byte, 16)
+	if _, err := io.ReadFull(f, data); err != nil {
+		return nil, err
+	}
+	f.Seek(0, 0)
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &elfExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &peExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &machoExe{f, e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type elfExe struct {
+	os *os.File
+	f  *elf.File
+}
+
+func (x *elfExe) AddrSize() int { return 0 }
+
+func (x *elfExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *elfExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *elfExe) Entry() uint64 { return x.f.Entry }
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		// The following line was commented from the original code.
+		//fmt.Printf("%#x %#x %#x\n", addr, prog.Vaddr, prog.Vaddr+prog.Filesz)
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *elfExe) Symbols() ([]sym, error) {
+	syms, err := x.f.Symbols()
+	if err != nil {
+		return nil, err
+	}
+	var out []sym
+	for _, s := range syms {
+		out = append(out, sym{s.Name, s.Value, s.Size})
+	}
+	return out, nil
+}
+
+func (x *elfExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *elfExe) TextRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *elfExe) RODataRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == elf.PF_R {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == (elf.PF_R|elf.PF_X) {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+type peExe struct {
+	os *os.File
+	f  *pe.File
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) AddrSize() int {
+	if x.f.Machine == pe.IMAGE_FILE_MACHINE_AMD64 {
+		return 8
+	}
+	return 4
+}
+
+func (x *peExe) ByteOrder() binary.ByteOrder { return binary.LittleEndian }
+
+func (x *peExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *peExe) Entry() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase + oh.AddressOfEntryPoint)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase + uint64(oh.AddressOfEntryPoint)
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	data := make([]byte, size)
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr+size-1 <= uint64(sect.VirtualAddress+sect.Size-1) {
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *peExe) Symbols() ([]sym, error) {
+	base := x.imageBase()
+	var out []sym
+	for _, s := range x.f.Symbols {
+		if s.SectionNumber <= 0 || int(s.SectionNumber) > len(x.f.Sections) {
+			continue
+		}
+		sect := x.f.Sections[s.SectionNumber-1]
+		out = append(out, sym{s.Name, uint64(s.Value) + base + uint64(sect.VirtualAddress), 0})
+	}
+	return out, nil
+}
+
+func (x *peExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *peExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty section.
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 {
+			return uint64(sect.VirtualAddress) + x.imageBase(), uint64(sect.VirtualAddress+sect.Size) + x.imageBase()
+		}
+	}
+	return 0, 0
+}
+
+func (x *peExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
+
+type machoExe struct {
+	os *os.File
+	f  *macho.File
+}
+
+func (x *machoExe) AddrSize() int {
+	if x.f.Cpu&0x01000000 != 0 {
+		return 8
+	}
+	return 4
+}
+
+func (x *machoExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *machoExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *machoExe) Entry() uint64 {
+	for _, load := range x.f.Loads {
+		b, ok := load.(macho.LoadBytes)
+		if !ok {
+			continue
+		}
+		// TODO: Other thread states.
+		bo := x.f.ByteOrder
+		const x86_THREAD_STATE64 = 4
+		cmd, siz := macho.LoadCmd(bo.Uint32(b[0:4])), bo.Uint32(b[4:8])
+		if cmd == macho.LoadCmdUnixThread && siz == 184 && bo.Uint32(b[8:12]) == x86_THREAD_STATE64 {
+			return bo.Uint64(b[144:])
+		}
+	}
+	return 0
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	data := make([]byte, size)
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr+size-1 <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *machoExe) Symbols() ([]sym, error) {
+	var out []sym
+	for _, s := range x.f.Symtab.Syms {
+		out = append(out, sym{s.Name, s.Value, 0})
+	}
+	return out, nil
+}
+
+func (x *machoExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *machoExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty segment.
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Name != "__PAGEZERO" && seg.Addr != 0 && seg.Filesz != 0 {
+			return seg.Addr, seg.Addr + seg.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *machoExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/goversion/read.go b/event-processor/vendor/golang.org/x/vuln/internal/goversion/read.go
new file mode 100644
index 00000000..f298ef07
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/goversion/read.go
@@ -0,0 +1,246 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package goversion reports the Go version used to build program executables.
+//
+// This is a copy of rsc.io/goversion/version. We renamed the package to goversion
+// to differentiate between version package in standard library that we also use.
+package goversion
+
+import (
+	"bytes"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// Version is the information reported by ReadExe.
+type Version struct {
+	Release        string // Go version (runtime.Version in the program)
+	ModuleInfo     string // program's module information
+	BoringCrypto   bool   // program uses BoringCrypto
+	StandardCrypto bool   // program uses standard crypto (replaced by BoringCrypto)
+	FIPSOnly       bool   // program imports "crypto/tls/fipsonly"
+}
+
+// ReadExe reports information about the Go version used to build
+// the program executable named by file.
+func ReadExe(file string) (Version, error) {
+	var v Version
+	f, err := openExe(file)
+	if err != nil {
+		return v, err
+	}
+	defer f.Close()
+	isGo := false
+	for _, name := range f.SectionNames() {
+		if name == ".note.go.buildid" {
+			isGo = true
+		}
+	}
+	syms, symsErr := f.Symbols()
+	isGccgo := false
+	for _, sym := range syms {
+		name := sym.Name
+		if name == "runtime.main" || name == "main.main" {
+			isGo = true
+		}
+		if strings.HasPrefix(name, "runtime.") && strings.HasSuffix(name, "$descriptor") {
+			isGccgo = true
+		}
+		if name == "runtime.buildVersion" {
+			isGo = true
+			release, err := readBuildVersion(f, sym.Addr, sym.Size)
+			if err != nil {
+				return v, err
+			}
+			v.Release = release
+		}
+		// Note: Using strings.HasPrefix because Go 1.17+ adds ".abi0" to many of these symbols.
+		if strings.Contains(name, "_Cfunc__goboringcrypto_") || strings.HasPrefix(name, "crypto/internal/boring/sig.BoringCrypto") {
+			v.BoringCrypto = true
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.FIPSOnly") {
+			v.FIPSOnly = true
+		}
+		for _, re := range standardCryptoNames {
+			if re.MatchString(name) {
+				v.StandardCrypto = true
+			}
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.StandardCrypto") {
+			v.StandardCrypto = true
+		}
+	}
+
+	if DebugMatch {
+		v.Release = ""
+	}
+	if err := findModuleInfo(&v, f); err != nil {
+		return v, err
+	}
+	if v.Release == "" {
+		g, release := readBuildVersionX86Asm(f)
+		if g {
+			isGo = true
+			v.Release = release
+			if err := findCryptoSigs(&v, f); err != nil {
+				return v, err
+			}
+		}
+	}
+	if isGccgo && v.Release == "" {
+		isGo = true
+		v.Release = "gccgo (version unknown)"
+	}
+	if !isGo && symsErr != nil {
+		return v, symsErr
+	}
+
+	if !isGo {
+		return v, errors.New("not a Go executable")
+	}
+	if v.Release == "" {
+		v.Release = "unknown Go version"
+	}
+	return v, nil
+}
+
+var re = regexp.MustCompile
+
+var standardCryptoNames = []*regexp.Regexp{
+	re(`^crypto/sha1\.\(\*digest\)`),
+	re(`^crypto/sha256\.\(\*digest\)`),
+	re(`^crypto/rand\.\(\*devReader\)`),
+	re(`^crypto/rsa\.encrypt(\.abi.)?$`),
+	re(`^crypto/rsa\.decrypt(\.abi.)?$`),
+}
+
+func readBuildVersion(f exe, addr, size uint64) (string, error) {
+	if size == 0 {
+		size = uint64(f.AddrSize() * 2)
+	}
+	if size != 8 && size != 16 {
+		return "", fmt.Errorf("invalid size for runtime.buildVersion")
+	}
+	data, err := f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion: %v", err)
+	}
+
+	if size == 8 {
+		addr = uint64(f.ByteOrder().Uint32(data))
+		size = uint64(f.ByteOrder().Uint32(data[4:]))
+	} else {
+		addr = f.ByteOrder().Uint64(data)
+		size = f.ByteOrder().Uint64(data[8:])
+	}
+	if size > 1000 {
+		return "", fmt.Errorf("implausible string size %d for runtime.buildVersion", size)
+	}
+
+	data, err = f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion string data: %v", err)
+	}
+	return string(data), nil
+}
+
+// Code signatures that indicate BoringCrypto or crypto/internal/fipsonly.
+// These are not byte literals in order to avoid the actual
+// byte signatures appearing in the goversion binary,
+// because on some systems you can't tell rodata from text.
+var (
+	sigBoringCrypto, _   = hex.DecodeString("EB1DF448F44BF4B332F52813A3B450D441CC2485F001454E92101B1D2F1950C3")
+	sigStandardCrypto, _ = hex.DecodeString("EB1DF448F44BF4BAEE4DFA9851CA56A91145E83E99C59CF911CB8E80DAF12FC3")
+	sigFIPSOnly, _       = hex.DecodeString("EB1DF448F44BF4363CB9CE9D68047D31F28D325D5CA5873F5D80CAF6D6151BC3")
+)
+
+func findCryptoSigs(v *Version, f exe) error {
+	const maxSigLen = 1 << 10
+	start, end := f.TextRange()
+	for addr := start; addr < end; {
+		size := uint64(1 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveSig(data, sigBoringCrypto) {
+			v.BoringCrypto = true
+		}
+		if haveSig(data, sigFIPSOnly) {
+			v.FIPSOnly = true
+		}
+		if haveSig(data, sigStandardCrypto) {
+			v.StandardCrypto = true
+		}
+		if addr+size < end {
+			size -= maxSigLen
+		}
+		addr += size
+	}
+	return nil
+}
+
+func haveSig(data, sig []byte) bool {
+	const align = 16
+	for {
+		i := bytes.Index(data, sig)
+		if i < 0 {
+			return false
+		}
+		if i&(align-1) == 0 {
+			return true
+		}
+		// Found unaligned match; unexpected but
+		// skip to next aligned boundary and keep searching.
+		data = data[(i+align-1)&^(align-1):]
+	}
+}
+
+func findModuleInfo(v *Version, f exe) error {
+	const maxModInfo = 128 << 10
+	start, end := f.RODataRange()
+	for addr := start; addr < end; {
+		size := uint64(4 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveModuleInfo(data, v) {
+			return nil
+		}
+		if addr+size < end {
+			size -= maxModInfo
+		}
+		addr += size
+	}
+	return nil
+}
+
+var (
+	infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+	infoEnd, _   = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func haveModuleInfo(data []byte, v *Version) bool {
+	i := bytes.Index(data, infoStart)
+	if i < 0 {
+		return false
+	}
+	j := bytes.Index(data[i:], infoEnd)
+	if j < 0 {
+		return false
+	}
+	v.ModuleInfo = string(data[i+len(infoStart) : i+j])
+	return true
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
new file mode 100644
index 00000000..377a3787
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
@@ -0,0 +1,241 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package govulncheck contains the JSON output structs for govulncheck.
+//
+// govulncheck supports streaming JSON by emitting a series of Message
+// objects as it analyzes user code and discovers vulnerabilities.
+// Streaming JSON is useful for displaying progress in real-time for
+// large projects where govulncheck execution might take some time.
+//
+// govulncheck JSON emits configuration used to perform the analysis,
+// a user-friendly message about what is being analyzed, and the
+// vulnerability findings. Findings for the same vulnerability can
+// can be emitted several times. For instance, govulncheck JSON will
+// emit a finding when it sees that a vulnerable module is required
+// before proceeding to check if the vulnerability is imported or called.
+// Please see documentation on Message and related types for precise
+// details on the stream encoding.
+//
+// There are no guarantees on the order of messages. The pattern of emitted
+// messages can change in the future. Clients can follow code in handler.go
+// for consuming the streaming JSON programmatically.
+package govulncheck
+
+import (
+	"time"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+const (
+	// ProtocolVersion is the current protocol version this file implements
+	ProtocolVersion = "v1.0.0"
+)
+
+// Message is an entry in the output stream. It will always have exactly one
+// field filled in.
+type Message struct {
+	Config   *Config   `json:"config,omitempty"`
+	Progress *Progress `json:"progress,omitempty"`
+	SBOM     *SBOM     `json:"SBOM,omitempty"`
+	// OSV is emitted for every vulnerability in the current database
+	// that applies to user modules regardless of their version. If a
+	// module is being used at a vulnerable version, the corresponding
+	// OSV will be referenced in Findings depending on the type of usage
+	// and the desired scan level.
+	OSV     *osv.Entry `json:"osv,omitempty"`
+	Finding *Finding   `json:"finding,omitempty"`
+}
+
+// Config must occur as the first message of a stream and informs the client
+// about the information used to generate the findings.
+// The only required field is the protocol version.
+type Config struct {
+	// ProtocolVersion specifies the version of the JSON protocol.
+	ProtocolVersion string `json:"protocol_version"`
+
+	// ScannerName is the name of the tool, for example, govulncheck.
+	//
+	// We expect this JSON format to be used by other tools that wrap
+	// govulncheck, which will have a different name.
+	ScannerName string `json:"scanner_name,omitempty"`
+
+	// ScannerVersion is the version of the tool.
+	ScannerVersion string `json:"scanner_version,omitempty"`
+
+	// DB is the database used by the tool, for example,
+	// vuln.go.dev.
+	DB string `json:"db,omitempty"`
+
+	// LastModified is the last modified time of the data source.
+	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
+
+	// GoVersion is the version of Go used for analyzing standard library
+	// vulnerabilities.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// ScanLevel instructs govulncheck to analyze at a specific level of detail.
+	// Valid values include module, package and symbol.
+	ScanLevel ScanLevel `json:"scan_level,omitempty"`
+
+	// ScanMode instructs govulncheck how to interpret the input and
+	// what to do with it. Valid values are source, binary, query,
+	// and extract.
+	ScanMode ScanMode `json:"scan_mode,omitempty"`
+}
+
+// SBOM contains minimal information about the artifacts govulncheck is scanning.
+type SBOM struct {
+	// The go version used by govulncheck when scanning, which also defines
+	// the version of the standard library used for detecting vulns.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// The set of modules included in the scan.
+	Modules []*Module `json:"modules,omitempty"`
+
+	// The roots of the scan, as package paths.
+	// For binaries, this will be the main package.
+	// For source code, this will be the packages matching the provided package patterns.
+	Roots []string `json:"roots,omitempty"`
+}
+
+type Module struct {
+	// The full module path.
+	Path string `json:"path,omitempty"`
+
+	// The version of the module.
+	Version string `json:"version,omitempty"`
+}
+
+// Progress messages are informational only, intended to allow users to monitor
+// the progress of a long running scan.
+// A stream must remain fully valid and able to be interpreted with all progress
+// messages removed.
+type Progress struct {
+	// A time stamp for the message.
+	Timestamp *time.Time `json:"time,omitempty"`
+
+	// Message is the progress message.
+	Message string `json:"message,omitempty"`
+}
+
+// Finding contains information on a discovered vulnerability. Each vulnerability
+// will likely have multiple findings in JSON mode. This is because govulncheck
+// emits findings as it does work, and therefore could emit one module level,
+// one package level, and potentially multiple symbol level findings depending
+// on scan level.
+// Multiple symbol level findings can be emitted when multiple symbols of the
+// same vuln are called or govulncheck decides to show multiple traces for the
+// same symbol.
+type Finding struct {
+	// OSV is the id of the detected vulnerability.
+	OSV string `json:"osv,omitempty"`
+
+	// FixedVersion is the module version where the vulnerability was
+	// fixed. This is empty if a fix is not available.
+	//
+	// If there are multiple fixed versions in the OSV report, this will
+	// be the fixed version in the latest range event for the OSV report.
+	//
+	// For example, if the range events are
+	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
+	// will be empty.
+	//
+	// For the stdlib, we will show the fixed version closest to the
+	// Go version that is used. For example, if a fix is available in 1.17.5 and
+	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
+	// fixed version.
+	FixedVersion string `json:"fixed_version,omitempty"`
+
+	// Trace contains an entry for each frame in the trace.
+	//
+	// Frames are sorted starting from the imported vulnerable symbol
+	// until the entry point. The first frame in Frames should match
+	// Symbol.
+	//
+	// In binary mode, trace will contain a single-frame with no position
+	// information.
+	//
+	// For module level source findings, the trace will contain a single-frame
+	// with no symbol, position, or package information. For package level source
+	// findings, the trace will contain a single-frame with no symbol or position
+	// information.
+	Trace []*Frame `json:"trace,omitempty"`
+}
+
+// Frame represents an entry in a finding trace.
+type Frame struct {
+	// Module is the module path of the module containing this symbol.
+	//
+	// Importable packages in the standard library will have the path "stdlib".
+	Module string `json:"module"`
+
+	// Version is the module version from the build graph.
+	Version string `json:"version,omitempty"`
+
+	// Package is the import path.
+	Package string `json:"package,omitempty"`
+
+	// Function is the function name.
+	Function string `json:"function,omitempty"`
+
+	// Receiver is the receiver type if the called symbol is a method.
+	//
+	// The client can create the final symbol name by
+	// prepending Receiver to FuncName.
+	Receiver string `json:"receiver,omitempty"`
+
+	// Position describes an arbitrary source position
+	// including the file, line, and column location.
+	// A Position is valid if the line number is > 0.
+	//
+	// The filenames are relative to the directory of
+	// the enclosing module and always use "/" for
+	// portability.
+	Position *Position `json:"position,omitempty"`
+}
+
+// Position represents arbitrary source position.
+type Position struct {
+	Filename string `json:"filename,omitempty"` // filename, if any
+	Offset   int    `json:"offset"`             // byte offset, starting at 0
+	Line     int    `json:"line"`               // line number, starting at 1
+	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
+}
+
+// ScanLevel represents the detail level at which a scan occurred.
+// This can be necessary to correctly interpret the findings, for instance if
+// a scan is at symbol level and a finding does not have a symbol it means the
+// vulnerability was imported but not called. If the scan however was at
+// "package" level, that determination cannot be made.
+type ScanLevel string
+
+const (
+	ScanLevelModule  = "module"
+	ScanLevelPackage = "package"
+	ScanLevelSymbol  = "symbol"
+)
+
+// WantSymbols can be used to check whether the scan level is one that is able
+// to generate symbol-level findings.
+func (l ScanLevel) WantSymbols() bool { return l == ScanLevelSymbol }
+
+// WantPackages can be used to check whether the scan level is one that is able
+// to generate package-level findings.
+func (l ScanLevel) WantPackages() bool { return l == ScanLevelPackage || l == ScanLevelSymbol }
+
+// ScanMode represents the mode in which a scan occurred. This can
+// be necessary to correctly to interpret findings. For instance,
+// a binary can be checked for vulnerabilities or the user just wants
+// to extract minimal data necessary for the vulnerability check.
+type ScanMode string
+
+const (
+	ScanModeSource  = "source"
+	ScanModeBinary  = "binary"
+	ScanModeConvert = "convert"
+	ScanModeQuery   = "query"
+	ScanModeExtract = "extract" // currently, only binary extraction is supported
+)
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/handler.go b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
index 5676ea94..5ce7d532 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
@@ -17,6 +17,9 @@ type Handler interface {
 	// Config communicates introductory message to the user.
 	Config(config *Config) error
 
+	// SBOM shows information about what govulncheck is scanning.
+	SBOM(sbom *SBOM) error
+
 	// Progress is called to display a progress message.
 	Progress(progress *Progress) error
 
@@ -45,6 +48,9 @@ func HandleJSON(from io.Reader, to Handler) error {
 		if msg.Progress != nil {
 			err = to.Progress(msg.Progress)
 		}
+		if msg.SBOM != nil {
+			err = to.SBOM(msg.SBOM)
+		}
 		if msg.OSV != nil {
 			err = to.OSV(msg.OSV)
 		}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/json.go b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/json.go
deleted file mode 100644
index d1ea78af..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/json.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package govulncheck
-
-import (
-	"encoding/json"
-
-	"io"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-type jsonHandler struct {
-	enc *json.Encoder
-}
-
-// NewJSONHandler returns a handler that writes govulncheck output as json.
-func NewJSONHandler(w io.Writer) Handler {
-	enc := json.NewEncoder(w)
-	enc.SetIndent("", "  ")
-	return &jsonHandler{enc: enc}
-}
-
-// Config writes config block in JSON to the underlying writer.
-func (h *jsonHandler) Config(config *Config) error {
-	return h.enc.Encode(Message{Config: config})
-}
-
-// Progress writes a progress message in JSON to the underlying writer.
-func (h *jsonHandler) Progress(progress *Progress) error {
-	return h.enc.Encode(Message{Progress: progress})
-}
-
-// OSV writes an osv entry in JSON to the underlying writer.
-func (h *jsonHandler) OSV(entry *osv.Entry) error {
-	return h.enc.Encode(Message{OSV: entry})
-}
-
-// Finding writes a finding in JSON to the underlying writer.
-func (h *jsonHandler) Finding(finding *Finding) error {
-	return h.enc.Encode(Message{Finding: finding})
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
new file mode 100644
index 00000000..b1586e09
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
@@ -0,0 +1,49 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package govulncheck
+
+import (
+	"encoding/json"
+
+	"io"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+type jsonHandler struct {
+	enc *json.Encoder
+}
+
+// NewJSONHandler returns a handler that writes govulncheck output as json.
+func NewJSONHandler(w io.Writer) Handler {
+	enc := json.NewEncoder(w)
+	enc.SetIndent("", "  ")
+	return &jsonHandler{enc: enc}
+}
+
+// Config writes config block in JSON to the underlying writer.
+func (h *jsonHandler) Config(config *Config) error {
+	return h.enc.Encode(Message{Config: config})
+}
+
+// Progress writes a progress message in JSON to the underlying writer.
+func (h *jsonHandler) Progress(progress *Progress) error {
+	return h.enc.Encode(Message{Progress: progress})
+}
+
+// SBOM writes the SBOM block in JSON to the underlying writer.
+func (h *jsonHandler) SBOM(sbom *SBOM) error {
+	return h.enc.Encode(Message{SBOM: sbom})
+}
+
+// OSV writes an osv entry in JSON to the underlying writer.
+func (h *jsonHandler) OSV(entry *osv.Entry) error {
+	return h.enc.Encode(Message{OSV: entry})
+}
+
+// Finding writes a finding in JSON to the underlying writer.
+func (h *jsonHandler) Finding(finding *Finding) error {
+	return h.enc.Encode(Message{Finding: finding})
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/result.go b/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/result.go
deleted file mode 100644
index 3c1f2bdd..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/govulncheck/result.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package result contains the JSON output structs for govulncheck.
-package govulncheck
-
-import (
-	"time"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-const (
-	// ProtocolVersion is the current protocol version this file implements
-	ProtocolVersion = "v0.1.0"
-)
-
-// Message is an entry in the output stream. It will always have exactly one
-// field filled in.
-type Message struct {
-	Config   *Config    `json:"config,omitempty"`
-	Progress *Progress  `json:"progress,omitempty"`
-	OSV      *osv.Entry `json:"osv,omitempty"`
-	Finding  *Finding   `json:"finding,omitempty"`
-}
-
-type Config struct {
-	// ProtocolVersion specifies the version of the JSON protocol.
-	ProtocolVersion string `json:"protocol_version,omitempty"`
-
-	// ScannerName is the name of the tool, for example, govulncheck.
-	//
-	// We expect this JSON format to be used by other tools that wrap
-	// govulncheck, which will have a different name.
-	ScannerName string `json:"scanner_name,omitempty"`
-
-	// ScannerVersion is the version of the tool.
-	ScannerVersion string `json:"scanner_version,omitempty"`
-
-	// DB is the database used by the tool, for example,
-	// vuln.go.dev.
-	DB string `json:"db,omitempty"`
-
-	// LastModified is the last modified time of the data source.
-	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
-
-	// GoVersion is the version of Go used for analyzing standard library
-	// vulnerabilities.
-	GoVersion string `json:"go_version,omitempty"`
-
-	// ScanLevel instructs vulncheck to analyze at a specific level of detail.
-	// Valid values include module, package and symbol.
-	ScanLevel ScanLevel `json:"scan_level,omitempty"`
-}
-
-type Progress struct {
-	// A time stamp for the message.
-	Timestamp *time.Time `json:"time,omitempty"`
-
-	// Message is the progress message.
-	Message string `json:"message,omitempty"`
-}
-
-// Vuln represents a single OSV entry.
-type Finding struct {
-	// OSV is the id of the detected vulnerability.
-	OSV string `json:"osv,omitempty"`
-
-	// FixedVersion is the module version where the vulnerability was
-	// fixed. This is empty if a fix is not available.
-	//
-	// If there are multiple fixed versions in the OSV report, this will
-	// be the fixed version in the latest range event for the OSV report.
-	//
-	// For example, if the range events are
-	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
-	// will be empty.
-	//
-	// For the stdlib, we will show the fixed version closest to the
-	// Go version that is used. For example, if a fix is available in 1.17.5 and
-	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
-	// fixed version.
-	FixedVersion string `json:"fixed_version,omitempty"`
-
-	// Trace contains an entry for each frame in the trace.
-	//
-	// Frames are sorted starting from the imported vulnerable symbol
-	// until the entry point. The first frame in Frames should match
-	// Symbol.
-	//
-	// In binary mode, trace will contain a single-frame with no position
-	// information.
-	//
-	// When a package is imported but no vulnerable symbol is called, the trace
-	// will contain a single-frame with no symbol or position information.
-	Trace []*Frame `json:"trace,omitempty"`
-}
-
-// Frame represents an entry in a finding trace.
-type Frame struct {
-	// Module is the module path of the module containing this symbol.
-	//
-	// Importable packages in the standard library will have the path "stdlib".
-	Module string `json:"module"`
-
-	// Version is the module version from the build graph.
-	Version string `json:"version,omitempty"`
-
-	// Package is the import path.
-	Package string `json:"package,omitempty"`
-
-	// Function is the function name.
-	Function string `json:"function,omitempty"`
-
-	// Receiver is the receiver type if the called symbol is a method.
-	//
-	// The client can create the final symbol name by
-	// prepending Receiver to FuncName.
-	Receiver string `json:"receiver,omitempty"`
-
-	// Position describes an arbitrary source position
-	// including the file, line, and column location.
-	// A Position is valid if the line number is > 0.
-	Position *Position `json:"position,omitempty"`
-}
-
-// Position is a copy of token.Position used to marshal/unmarshal
-// JSON correctly.
-type Position struct {
-	Filename string `json:"filename,omitempty"` // filename, if any
-	Offset   int    `json:"offset"`             // offset, starting at 0
-	Line     int    `json:"line"`               // line number, starting at 1
-	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
-}
-
-type ScanLevel string
-
-const (
-	scanLevelModule  = "module"
-	scanLevelPackage = "package"
-	scanLevelSymbol  = "symbol"
-)
-
-func (l ScanLevel) WantSymbols() bool { return l == scanLevelSymbol }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/internal.go b/event-processor/vendor/golang.org/x/vuln/internal/internal.go
index 64c5e8d5..8e6b7f5c 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/internal.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/internal.go
@@ -24,5 +24,9 @@ const (
 
 	// UnknownModulePath is a special module path for when we cannot work out
 	// the module for a package.
-	UnknownModulePath = "unknown"
+	UnknownModulePath = "unknown-module"
+
+	// UnknownPackagePath is a special package path for when we cannot work out
+	// the packagUnknownModulePath = "unknown"
+	UnknownPackagePath = "unknown-package"
 )
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/openvex/handler.go b/event-processor/vendor/golang.org/x/vuln/internal/openvex/handler.go
new file mode 100644
index 00000000..a2d32829
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/openvex/handler.go
@@ -0,0 +1,261 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"io"
+	"slices"
+	"time"
+
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+)
+
+type findingLevel int
+
+const (
+	invalid findingLevel = iota
+	required
+	imported
+	called
+)
+
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	sbom *govulncheck.SBOM
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(cfg *govulncheck.Config) error {
+	h.cfg = cfg
+	return nil
+}
+
+func (h *handler) Progress(progress *govulncheck.Progress) error {
+	return nil
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	h.sbom = s
+	return nil
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// foundAtLevel returns the level at which a specific finding is present in the
+// scanned product.
+func foundAtLevel(f *govulncheck.Finding) findingLevel {
+	frame := f.Trace[0]
+	if frame.Function != "" {
+		return called
+	}
+	if frame.Package != "" {
+		return imported
+	}
+	return required
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is at the same level of precision.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print the vex json to w.
+// This is needed as vex is not streamed.
+func (h *handler) Flush() error {
+	doc := toVex(h)
+	out, err := json.MarshalIndent(doc, "", "  ")
+	if err != nil {
+		return err
+	}
+	_, err = h.w.Write(out)
+	return err
+}
+
+func toVex(h *handler) Document {
+	doc := Document{
+		Context:    ContextURI,
+		Author:     DefaultAuthor,
+		Timestamp:  time.Now().UTC(),
+		Version:    1,
+		Tooling:    Tooling,
+		Statements: statements(h),
+	}
+
+	id := hashVex(doc)
+	doc.ID = "govulncheck/vex:" + id
+	return doc
+}
+
+// Given a slice of findings, returns those findings as a set of subcomponents
+// that are unique per the vulnerable artifact's PURL.
+func subcomponentSet(findings []*govulncheck.Finding) []Component {
+	var scs []Component
+	seen := make(map[string]bool)
+	for _, f := range findings {
+		purl := purlFromFinding(f)
+		if !seen[purl] {
+			scs = append(scs, Component{
+				ID: purlFromFinding(f),
+			})
+			seen[purl] = true
+		}
+	}
+	return scs
+}
+
+// statements combines all OSVs found by govulncheck and generates the list of
+// vex statements with the proper affected level and justification to match the
+// openVex specification.
+func statements(h *handler) []Statement {
+	var scanLevel findingLevel
+	switch h.cfg.ScanLevel {
+	case govulncheck.ScanLevelModule:
+		scanLevel = required
+	case govulncheck.ScanLevelPackage:
+		scanLevel = imported
+	case govulncheck.ScanLevelSymbol:
+		scanLevel = called
+	}
+
+	var statements []Statement
+	for id, osv := range h.osvs {
+		// if there are no findings emitted for a given OSV that means that
+		// the vulnerable module is not required at a vulnerable version.
+		if len(h.findings[id]) == 0 {
+			continue
+		}
+		description := osv.Summary
+		if description == "" {
+			description = osv.Details
+		}
+
+		s := Statement{
+			Vulnerability: Vulnerability{
+				ID:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", id),
+				Name:        id,
+				Description: description,
+				Aliases:     osv.Aliases,
+			},
+			Products: []Product{
+				{
+					Component:     Component{ID: DefaultPID},
+					Subcomponents: subcomponentSet(h.findings[id]),
+				},
+			},
+		}
+
+		// Findings are guaranteed to be at the same level, so we can just check the first element
+		fLevel := foundAtLevel(h.findings[id][0])
+		if fLevel >= scanLevel {
+			s.Status = StatusAffected
+		} else {
+			s.Status = StatusNotAffected
+			s.ImpactStatement = Impact
+			s.Justification = JustificationNotPresent
+			// We only reach this case if running in symbol mode
+			if fLevel == imported {
+				s.Justification = JustificationNotExecuted
+			}
+		}
+		statements = append(statements, s)
+	}
+
+	slices.SortFunc(statements, func(a, b Statement) int {
+		if a.Vulnerability.ID > b.Vulnerability.ID {
+			return 1
+		}
+		if a.Vulnerability.ID < b.Vulnerability.ID {
+			return -1
+		}
+		// this should never happen in practice, since statements are being
+		// populated from a map with the vulnerability IDs as keys
+		return 0
+	})
+	return statements
+}
+
+func hashVex(doc Document) string {
+	// json.Marshal should never error here (because of the structure of Document).
+	// If an error does occur, it won't be a jsonerror, but instead a panic
+	d := Document{
+		Context:    doc.Context,
+		ID:         doc.ID,
+		Author:     doc.Author,
+		Version:    doc.Version,
+		Tooling:    doc.Tooling,
+		Statements: doc.Statements,
+	}
+	out, err := json.Marshal(d)
+	if err != nil {
+		panic(err)
+	}
+	return fmt.Sprintf("%x", sha256.Sum256(out))
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/openvex/purl.go b/event-processor/vendor/golang.org/x/vuln/internal/openvex/purl.go
new file mode 100644
index 00000000..fc1cea9c
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/openvex/purl.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"net/url"
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// The PURL is printed as: pkg:golang/MODULE_PATH@VERSION
+// Conceptually there is no namespace and the name is entirely defined by
+// the module path. See https://github.com/package-url/purl-spec/issues/63
+// for further disucssion.
+
+const suffix = "pkg:golang/"
+
+type purl struct {
+	name    string
+	version string
+}
+
+func (p *purl) String() string {
+	var b strings.Builder
+	b.WriteString(suffix)
+	b.WriteString(url.PathEscape(p.name))
+	if p.version != "" {
+		b.WriteString("@")
+		b.WriteString(p.version)
+	}
+	return b.String()
+}
+
+// purlFromFinding takes a govulncheck finding and generates a purl to the
+// vulnerable dependency.
+func purlFromFinding(f *govulncheck.Finding) string {
+	purl := purl{
+		name:    f.Trace[0].Module,
+		version: f.Trace[0].Version,
+	}
+
+	return purl.String()
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/openvex/vex.go b/event-processor/vendor/golang.org/x/vuln/internal/openvex/vex.go
new file mode 100644
index 00000000..18779f70
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/openvex/vex.go
@@ -0,0 +1,113 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vex defines the Vulnerability EXchange Format (VEX) types
+// supported by govulncheck.
+//
+// These types match the OpenVEX standard. See https://github.com/openvex for
+// more information on VEX and OpenVEX.
+//
+// This is intended to be the minimimal amount of information required to output
+// a complete VEX document according to the specification.
+package openvex
+
+import "time"
+
+const (
+	ContextURI = "https://openvex.dev/ns/v0.2.0"
+	Tooling    = "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Impact     = "Govulncheck determined that the vulnerable code isn't called"
+
+	DefaultAuthor = "Unknown Author"
+	DefaultPID    = "Unknown Product"
+
+	// The following are defined by the VEX standard.
+	StatusAffected    = "affected"
+	StatusNotAffected = "not_affected"
+
+	// The following are defined by the VEX standard.
+	JustificationNotExecuted = "vulnerable_code_not_in_execute_path"
+	JustificationNotPresent  = "vulnerable_code_not_present"
+)
+
+// Document is the top-level struct for a VEX document.
+type Document struct {
+	// Context is an IRI pointing to the version of openVEX being used by the doc
+	// For govulncheck, it will always be https://openvex.dev/ns/v0.2.0
+	Context string `json:"@context,omitempty"`
+
+	// ID is the identifying string for the VEX document.
+	// govulncheck/vex-[content-based-hash]
+	ID string `json:"@id,omitempty"`
+
+	// Author is the identifier for the author of the VEX statement.
+	// Govulncheck will leave this field default (Unknown author) to be filled in by the user.
+	Author string `json:"author,omitempty"`
+
+	// Timestamp defines the time at which the document was issued.
+	Timestamp time.Time `json:"timestamp,omitempty"`
+
+	// Version is the document version. For govulncheck's output, this will always be 1.
+	Version int `json:"version,omitempty"`
+
+	// Tooling expresses how the VEX document and contained VEX statements were
+	// generated. In this case, it will always be:
+	// "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Tooling string `json:"tooling,omitempty"`
+
+	// Statements are all statements for a given govulncheck output.
+	// Each OSV emitted by govulncheck will have a corresponding statement.
+	Statements []Statement `json:"statements,omitempty"`
+}
+
+// Statement conveys a single status for a single vulnerability for one or more products.
+type Statement struct {
+	// Vulnerability is the vuln being referenced by the statement.
+	Vulnerability Vulnerability `json:"vulnerability,omitempty"`
+
+	// Products are the products associated with the given vulnerability in the statement.
+	Products []Product `json:"products,omitempty"`
+
+	// The status of the vulnerability. Will be either not_affected or affected for govulncheck.
+	Status string `json:"status,omitempty"`
+
+	// If the status is not_affected, this must be filled. The official VEX justification that
+	// best matches govulncheck's vuln filtering is "vulnerable_code_not_in_execute_path"
+	Justification string `json:"justification,omitempty"`
+
+	// If the status is not_affected, this must be filled. For govulncheck, this will always be:
+	// "Govulncheck determined that the vulnerable code isn't called"
+	ImpactStatement string `json:"impact_statement,omitempty"`
+}
+
+// Vulnerability captures a vulnerability and its identifiers/aliases.
+type Vulnerability struct {
+	// ID is a URI that in govulncheck's case points to the govulndb link for the vulnerability.
+	// I.E. https://pkg.go.dev/vuln/GO-2024-2497
+	ID string `json:"@id,omitempty"`
+
+	// Name is the main identifier for the vulnerability (GO-YYYY-XXXX)
+	Name string `json:"name,omitempty"`
+
+	// Description is a short text description of the vulnerability.
+	// It will be populated from the 'summary' field of the vuln's OSV if it exists,
+	// and the 'description' field of the osv if a summary isn't present.
+	Description string `json:"description,omitempty"`
+
+	// Aliases a list of identifiers that other systems are using to track the vulnerability.
+	// I.E. GHSA or CVE ids.
+	Aliases []string `json:"aliases,omitempty"`
+}
+
+// Product identifies the products associated with the given vuln.
+type Product struct {
+	// The main product ID will remian default for now.
+	Component
+	// The subcomponent ID will be a PURL to the vulnerable dependency.
+	Subcomponents []Component `json:"subcomponents,omitempty"`
+}
+
+type Component struct {
+	ID string `json:"@id,omitempty"`
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/osv/osv.go b/event-processor/vendor/golang.org/x/vuln/internal/osv/osv.go
index 3fa3a086..0bb44b27 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/osv/osv.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/osv/osv.go
@@ -97,7 +97,7 @@ type Range struct {
 	Events []RangeEvent `json:"events"`
 }
 
-// Reference type is a reference (link) type.
+// ReferenceType is a reference (link) type.
 type ReferenceType string
 
 const (
@@ -235,4 +235,6 @@ type DatabaseSpecific struct {
 	// The URL of the Go advisory for this vulnerability, of the form
 	// "https://pkg.go.dev/GO-YYYY-XXXX".
 	URL string `json:"url,omitempty"`
+	// The review status of this report (UNREVIEWED or REVIEWED).
+	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/osv/review_status.go b/event-processor/vendor/golang.org/x/vuln/internal/osv/review_status.go
new file mode 100644
index 00000000..7185e184
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/osv/review_status.go
@@ -0,0 +1,67 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package osv
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type ReviewStatus int
+
+const (
+	ReviewStatusUnknown ReviewStatus = iota
+	ReviewStatusUnreviewed
+	ReviewStatusReviewed
+)
+
+var statusStrs = []string{
+	ReviewStatusUnknown:    "",
+	ReviewStatusUnreviewed: "UNREVIEWED",
+	ReviewStatusReviewed:   "REVIEWED",
+}
+
+func (r ReviewStatus) String() string {
+	if !r.IsValid() {
+		return fmt.Sprintf("INVALID(%d)", r)
+	}
+	return statusStrs[r]
+}
+
+func ReviewStatusValues() []string {
+	return statusStrs[1:]
+}
+
+func (r ReviewStatus) IsValid() bool {
+	return int(r) >= 0 && int(r) < len(statusStrs)
+}
+
+func ToReviewStatus(s string) (ReviewStatus, bool) {
+	for stat, str := range statusStrs {
+		if s == str {
+			return ReviewStatus(stat), true
+		}
+	}
+	return 0, false
+}
+
+func (r ReviewStatus) MarshalJSON() ([]byte, error) {
+	if !r.IsValid() {
+		return nil, fmt.Errorf("MarshalJSON: unrecognized review status: %d", r)
+	}
+	return json.Marshal(r.String())
+}
+
+func (r *ReviewStatus) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if rs, ok := ToReviewStatus(s); ok {
+		*r = rs
+		return nil
+	}
+	return fmt.Errorf("UnmarshalJSON: unrecognized review status: %s", s)
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/sarif/handler.go b/event-processor/vendor/golang.org/x/vuln/internal/sarif/handler.go
new file mode 100644
index 00000000..d9e585b7
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/sarif/handler.go
@@ -0,0 +1,409 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"path/filepath"
+	"sort"
+
+	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
+)
+
+// handler for sarif output.
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(c *govulncheck.Config) error {
+	h.cfg = c
+	return nil
+}
+
+func (h *handler) Progress(p *govulncheck.Progress) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is equal to an existing one and
+			// because of the invariant on h.findings, it is
+			// also equal to all existing ones.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print out to w the sarif json output.
+// This is needed as sarif is not streamed.
+func (h *handler) Flush() error {
+	sLog := toSarif(h)
+	s, err := json.MarshalIndent(sLog, "", "  ")
+	if err != nil {
+		return err
+	}
+	h.w.Write(s)
+	return nil
+}
+
+func toSarif(h *handler) Log {
+	cfg := h.cfg
+	r := Run{
+		Tool: Tool{
+			Driver: Driver{
+				Name:           cfg.ScannerName,
+				Version:        cfg.ScannerVersion,
+				InformationURI: "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
+				Properties:     *cfg,
+				Rules:          rules(h),
+			},
+		},
+		Results: results(h),
+	}
+
+	return Log{
+		Version: "2.1.0",
+		Schema:  "https://json.schemastore.org/sarif-2.1.0.json",
+		Runs:    []Run{r},
+	}
+}
+
+func rules(h *handler) []Rule {
+	rs := make([]Rule, 0, len(h.findings)) // must not be nil
+	for id := range h.findings {
+		osv := h.osvs[id]
+		// s is either summary if it exists, or details
+		// otherwise. Govulncheck text does the same.
+		s := osv.Summary
+		if s == "" {
+			s = osv.Details
+		}
+		rs = append(rs, Rule{
+			ID:               osv.ID,
+			ShortDescription: Description{Text: fmt.Sprintf("[%s] %s", osv.ID, s)},
+			FullDescription:  Description{Text: s},
+			HelpURI:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", osv.ID),
+			Help:             Description{Text: osv.Details},
+			Properties:       RuleTags{Tags: tags(osv)},
+		})
+	}
+	sort.SliceStable(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
+	return rs
+}
+
+// tags returns an slice of zero or
+// more aliases of o.
+func tags(o *osv.Entry) []string {
+	if len(o.Aliases) > 0 {
+		return o.Aliases
+	}
+	return []string{} // must not be nil
+}
+
+func results(h *handler) []Result {
+	results := make([]Result, 0, len(h.findings)) // must not be nil
+	for osv, fs := range h.findings {
+		var locs []Location
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			// Attach result to the go.mod file for source analysis.
+			// But there is no such place for binaries.
+			locs = []Location{{PhysicalLocation: PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       "go.mod",
+					URIBaseID: SrcRootID,
+				},
+				Region: Region{StartLine: 1}, // for now, point to the first line
+			},
+				Message: Description{Text: fmt.Sprintf("Findings for vulnerability %s", osv)}, // not having a message here results in an invalid sarif
+			}}
+		}
+
+		res := Result{
+			RuleID:    osv,
+			Level:     level(fs[0], h.cfg),
+			Message:   Description{Text: resultMessage(fs, h.cfg)},
+			Stacks:    stacks(h, fs),
+			CodeFlows: codeFlows(h, fs),
+			Locations: locs,
+		}
+		results = append(results, res)
+	}
+	sort.SliceStable(results, func(i, j int) bool { return results[i].RuleID < results[j].RuleID }) // for deterministic output
+	return results
+}
+
+func resultMessage(findings []*govulncheck.Finding, cfg *govulncheck.Config) string {
+	// We can infer the findings' level by just looking at the
+	// top trace frame of any finding.
+	frame := findings[0].Trace[0]
+	uniqueElems := make(map[string]bool)
+	if frame.Function == "" && frame.Package == "" { // module level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Module] = true
+		}
+	} else { // symbol and package level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Package] = true
+		}
+	}
+	var elems []string
+	for e := range uniqueElems {
+		elems = append(elems, e)
+	}
+	sort.Strings(elems)
+
+	l := len(elems)
+	elemList := list(elems)
+	main, addition := "", ""
+	const runCallAnalysis = "Run the call-level analysis to understand whether your code actually calls the vulnerabilities."
+	switch {
+	case frame.Function != "":
+		main = fmt.Sprintf("calls vulnerable functions in %d package%s (%s).", l, choose("", "s", l == 1), elemList)
+	case frame.Package != "":
+		main = fmt.Sprintf("imports %d vulnerable package%s (%s)", l, choose("", "s", l == 1), elemList)
+		addition = choose(", but doesn’t appear to call any of the vulnerable symbols.", ". "+runCallAnalysis, cfg.ScanLevel.WantSymbols())
+	default:
+		main = fmt.Sprintf("depends on %d vulnerable module%s (%s)", l, choose("", "s", l == 1), elemList)
+		informational := ", but doesn't appear to " + choose("call", "import", cfg.ScanLevel.WantSymbols()) + " any of the vulnerable symbols."
+		addition = choose(informational, ". "+runCallAnalysis, cfg.ScanLevel.WantPackages())
+	}
+
+	return fmt.Sprintf("Your code %s%s", main, addition)
+}
+
+const (
+	errorLevel         = "error"
+	warningLevel       = "warning"
+	informationalLevel = "note"
+)
+
+func level(f *govulncheck.Finding, cfg *govulncheck.Config) string {
+	fr := f.Trace[0]
+	switch {
+	case cfg.ScanLevel.WantSymbols():
+		if fr.Function != "" {
+			return errorLevel
+		}
+		if fr.Package != "" {
+			return warningLevel
+		}
+		return informationalLevel
+	case cfg.ScanLevel.WantPackages():
+		if fr.Package != "" {
+			return errorLevel
+		}
+		return warningLevel
+	default:
+		return errorLevel
+	}
+}
+
+func stacks(h *handler, fs []*govulncheck.Finding) []Stack {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	var stacks []Stack
+	for _, f := range fs {
+		stacks = append(stacks, stack(h, f))
+	}
+	// Sort stacks for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(stacks, func(i, j int) bool { return stacks[i].Message.Text < stacks[j].Message.Text })
+	return stacks
+}
+
+// stack transforms call stack in f to a sarif stack.
+func stack(h *handler, f *govulncheck.Finding) Stack {
+	trace := f.Trace
+	top := trace[len(trace)-1] // belongs to top level module
+
+	frames := make([]Frame, 0, len(trace)) // must not be nil
+	for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+		frame := trace[i]
+		pos := govulncheck.Position{Line: 1, Column: 1}
+		if frame.Position != nil {
+			pos = *frame.Position
+		}
+
+		sf := Frame{
+			Module:   frame.Module + "@" + frame.Version,
+			Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+		}
+		file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			sf.Location.PhysicalLocation = PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       file,
+					URIBaseID: base,
+				},
+				Region: Region{
+					StartLine:   pos.Line,
+					StartColumn: pos.Column,
+				},
+			}
+		}
+		frames = append(frames, sf)
+	}
+
+	return Stack{
+		Frames:  frames,
+		Message: Description{Text: fmt.Sprintf("A call stack for vulnerable function %s", symbol(trace[0]))},
+	}
+}
+
+func codeFlows(h *handler, fs []*govulncheck.Finding) []CodeFlow {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	// group call stacks per symbol. There should
+	// be one call stack currently per symbol, but
+	// this might change in the future.
+	m := make(map[govulncheck.Frame][]*govulncheck.Finding)
+	for _, f := range fs {
+		// fr.Position is currently the position
+		// of the definition of the vuln symbol
+		fr := *f.Trace[0]
+		m[fr] = append(m[fr], f)
+	}
+
+	var codeFlows []CodeFlow
+	for fr, fs := range m {
+		tfs := threadFlows(h, fs)
+		codeFlows = append(codeFlows, CodeFlow{
+			ThreadFlows: tfs,
+			// TODO: should we instead show the message from govulncheck text output?
+			Message: Description{Text: fmt.Sprintf("A summarized code flow for vulnerable function %s", symbol(&fr))},
+		})
+	}
+	// Sort flows for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(codeFlows, func(i, j int) bool { return codeFlows[i].Message.Text < codeFlows[j].Message.Text })
+	return codeFlows
+}
+
+func threadFlows(h *handler, fs []*govulncheck.Finding) []ThreadFlow {
+	tfs := make([]ThreadFlow, 0, len(fs)) // must not be nil
+	for _, f := range fs {
+		trace := traces.Compact(f)
+		top := trace[len(trace)-1] // belongs to top level module
+
+		var tf []ThreadFlowLocation
+		for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+			// TODO: should we, similar to govulncheck text output, only
+			// mention three elements of the compact trace?
+			frame := trace[i]
+			pos := govulncheck.Position{Line: 1, Column: 1}
+			if frame.Position != nil {
+				pos = *frame.Position
+			}
+
+			tfl := ThreadFlowLocation{
+				Module:   frame.Module + "@" + frame.Version,
+				Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+			}
+			file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+			if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+				tfl.Location.PhysicalLocation = PhysicalLocation{
+					ArtifactLocation: ArtifactLocation{
+						URI:       file,
+						URIBaseID: base,
+					},
+					Region: Region{
+						StartLine:   pos.Line,
+						StartColumn: pos.Column,
+					},
+				}
+			}
+			tf = append(tf, tfl)
+		}
+		tfs = append(tfs, ThreadFlow{Locations: tf})
+	}
+	return tfs
+}
+
+func fileURIInfo(filename, top, module, version string) (string, string) {
+	if top == module {
+		return filename, SrcRootID
+	}
+	if module == internal.GoStdModulePath {
+		return filename, GoRootID
+	}
+	return filepath.ToSlash(filepath.Join(module+"@"+version, filename)), GoModCacheID
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/sarif/sarif.go b/event-processor/vendor/golang.org/x/vuln/internal/sarif/sarif.go
new file mode 100644
index 00000000..934ade8b
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/sarif/sarif.go
@@ -0,0 +1,213 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sarif defines Static Analysis Results Interchange Format
+// (SARIF) types supported by govulncheck.
+//
+// The implementation covers the subset of the specification available
+// at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+//
+// The sarif encoding models govulncheck findings as Results. Each
+// Result encodes findings for a unique OSV entry at the most precise
+// detected level only. CodeFlows summarize call stacks, similar to govulncheck
+// textual output, while Stacks contain call stack information verbatim.
+//
+// The result Levels are defined by the govulncheck.ScanLevel and the most
+// precise level at which the finding was detected. Result error is produced
+// when the finding level matches the user desired level of scan precision;
+// all other finding levels are then classified as progressively weaker.
+// For instance, if the user specified symbol scan level and govulncheck
+// detected a use of a vulnerable symbol, then the Result will have error
+// Level. If the symbol was not used but its package was imported, then the
+// Result Level is warning, and so on.
+//
+// Each Result is attached to the first line of the go.mod file. Other
+// ArtifactLocations are paths relative to their enclosing modules.
+// Similar to JSON output format, this makes govulncheck sarif locations
+// portable.
+//
+// The relative paths in PhysicalLocations also come with a URIBaseID offset.
+// Paths for the source module analyzed, the Go standard library, and third-party
+// dependencies are relative to %SRCROOT%, %GOROOT%, and %GOMODCACHE% offsets,
+// resp. We note that the URIBaseID offsets are not explicitly defined in
+// the sarif output. It is the clients responsibility to set them to resolve
+// paths at their local machines.
+//
+// All paths use "/" delimiter for portability.
+//
+// Properties field of a Tool.Driver is a govulncheck.Config used for the
+// invocation of govulncheck producing the Results. Properties field of
+// a Rule contains information on CVE and GHSA aliases for the corresponding
+// rule OSV. Clients can use this information to, say, suppress and filter
+// vulnerabilities.
+//
+// Please see the definition of types below for more information.
+package sarif
+
+import "golang.org/x/vuln/internal/govulncheck"
+
+// Log is the top-level SARIF object encoded in UTF-8.
+type Log struct {
+	// Version should always be "2.1.0"
+	Version string `json:"version,omitempty"`
+
+	// Schema should always be "https://json.schemastore.org/sarif-2.1.0.json"
+	Schema string `json:"$schema,omitempty"`
+
+	// Runs describes executions of static analysis tools. For govulncheck,
+	// there will be only one run object.
+	Runs []Run `json:"runs,omitempty"`
+}
+
+// Run summarizes results of a single invocation of a static analysis tool,
+// in this case govulncheck.
+type Run struct {
+	Tool Tool `json:"tool,omitempty"`
+	// Results contain govulncheck findings. There should be exactly one
+	// Result per a detected use of an OSV.
+	Results []Result `json:"results"`
+}
+
+// Tool captures information about govulncheck analysis that was run.
+type Tool struct {
+	Driver Driver `json:"driver,omitempty"`
+}
+
+// Driver provides details about the govulncheck binary being executed.
+type Driver struct {
+	// Name is "govulncheck"
+	Name string `json:"name,omitempty"`
+	// Version is the govulncheck version
+	Version string `json:"semanticVersion,omitempty"`
+	// InformationURI points to the description of govulncheck tool
+	InformationURI string `json:"informationUri,omitempty"`
+	// Properties are govulncheck run metadata, such as vuln db, Go version, etc.
+	Properties govulncheck.Config `json:"properties,omitempty"`
+
+	Rules []Rule `json:"rules"`
+}
+
+// Rule corresponds to the static analysis rule/analyzer that
+// produces findings. For govulncheck, rules are OSVs.
+type Rule struct {
+	// ID is OSV.ID
+	ID               string      `json:"id,omitempty"`
+	ShortDescription Description `json:"shortDescription,omitempty"`
+	FullDescription  Description `json:"fullDescription,omitempty"`
+	Help             Description `json:"help,omitempty"`
+	HelpURI          string      `json:"helpUri,omitempty"`
+	// Properties contain OSV.Aliases (CVEs and GHSAs) as tags.
+	// Consumers of govulncheck SARIF can use these tags to filter
+	// results.
+	Properties RuleTags `json:"properties,omitempty"`
+}
+
+// RuleTags defines properties.tags.
+type RuleTags struct {
+	Tags []string `json:"tags"`
+}
+
+// Description is a text in its raw or markdown form.
+type Description struct {
+	Text     string `json:"text,omitempty"`
+	Markdown string `json:"markdown,omitempty"`
+}
+
+// Result is a set of govulncheck findings for an OSV. For call stack
+// mode, it will contain call stacks for the OSV. There is exactly
+// one Result per detected OSV. Only findings at the most precise
+// detected level appear in the Result. For instance, if there are
+// symbol findings for an OSV, those findings will be in the Result,
+// but not the package and module level findings for the same OSV.
+type Result struct {
+	// RuleID is the Rule.ID/OSV producing the finding.
+	RuleID string `json:"ruleId,omitempty"`
+	// Level is one of "error", "warning", and "note".
+	Level string `json:"level,omitempty"`
+	// Message explains the overall findings.
+	Message Description `json:"message,omitempty"`
+	// Locations to which the findings are associated. Always
+	// a single location pointing to the first line of the go.mod
+	// file. The path to the file is "go.mod".
+	Locations []Location `json:"locations,omitempty"`
+	// CodeFlows summarize call stacks produced by govulncheck.
+	CodeFlows []CodeFlow `json:"codeFlows,omitempty"`
+	// Stacks encode call stacks produced by govulncheck.
+	Stacks []Stack `json:"stacks,omitempty"`
+}
+
+// CodeFlow summarizes a detected offending flow of information in terms of
+// code locations. More precisely, it can contain several related information
+// flows, keeping them together. In govulncheck, those can be all call stacks
+// for, say, a particular symbol or package.
+type CodeFlow struct {
+	// ThreadFlows is effectively a set of related information flows.
+	ThreadFlows []ThreadFlow `json:"threadFlows"`
+	Message     Description  `json:"message,omitempty"`
+}
+
+// ThreadFlow encodes an information flow as a sequence of locations.
+// For govulncheck, it can encode a call stack.
+type ThreadFlow struct {
+	Locations []ThreadFlowLocation `json:"locations,omitempty"`
+}
+
+type ThreadFlowLocation struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module string `json:"module,omitempty"`
+	// Location also contains a Message field.
+	Location Location `json:"location,omitempty"`
+}
+
+// Stack is a sequence of frames and can encode a govulncheck call stack.
+type Stack struct {
+	Message Description `json:"message,omitempty"`
+	Frames  []Frame     `json:"frames"`
+}
+
+// Frame is effectively a module location. It can also contain thread and
+// parameter info, but those are not needed for govulncheck.
+type Frame struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module   string   `json:"module,omitempty"`
+	Location Location `json:"location,omitempty"`
+}
+
+// Location is currently a physical location annotated with a message.
+type Location struct {
+	PhysicalLocation PhysicalLocation `json:"physicalLocation,omitempty"`
+	Message          Description      `json:"message,omitempty"`
+}
+
+type PhysicalLocation struct {
+	ArtifactLocation ArtifactLocation `json:"artifactLocation,omitempty"`
+	Region           Region           `json:"region,omitempty"`
+}
+
+const (
+	SrcRootID    = "%SRCROOT%"
+	GoRootID     = "%GOROOT%"
+	GoModCacheID = "%GOMODCACHE%"
+)
+
+// ArtifactLocation is a path to an offending file.
+type ArtifactLocation struct {
+	// URI is a path relative to URIBaseID.
+	URI string `json:"uri,omitempty"`
+	// URIBaseID is offset for URI, one of %SRCROOT%, %GOROOT%,
+	// and %GOMODCACHE%.
+	URIBaseID string `json:"uriBaseId,omitempty"`
+}
+
+// Region is a target region within a file.
+type Region struct {
+	StartLine   int `json:"startLine,omitempty"`
+	StartColumn int `json:"startColumn,omitempty"`
+	EndLine     int `json:"endLine,omitempty"`
+	EndColumn   int `json:"endColumn,omitempty"`
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/sarif/utils.go b/event-processor/vendor/golang.org/x/vuln/internal/sarif/utils.go
new file mode 100644
index 00000000..045cac76
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/sarif/utils.go
@@ -0,0 +1,46 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+func choose(s1, s2 string, cond bool) string {
+	if cond {
+		return s1
+	}
+	return s2
+}
+
+func list(elems []string) string {
+	l := len(elems)
+	if l == 0 {
+		return ""
+	}
+	if l == 1 {
+		return elems[0]
+	}
+
+	cList := strings.Join(elems[:l-1], ", ")
+	return cList + choose("", ",", l == 2) + " and " + elems[l-1]
+}
+
+// symbol is simplified adaptation of internal/scan/symbol.
+func symbol(fr *govulncheck.Frame) string {
+	if fr.Function == "" {
+		return ""
+	}
+	sym := strings.Split(fr.Function, "$")[0]
+	if fr.Receiver != "" {
+		sym = fr.Receiver + "." + sym
+	}
+	if fr.Package != "" {
+		sym = fr.Package + "." + sym
+	}
+	return sym
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/binary.go
index 76b17f75..5cc8f6ba 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/binary.go
@@ -2,93 +2,109 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package scan
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
+	"errors"
 	"os"
-	"strings"
-	"unicode"
+	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
-// runBinary detects presence of vulnerable symbols in an executable.
-func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) error {
-	var exe *os.File
-	exe, err := os.Open(cfg.patterns[0])
+// runBinary detects presence of vulnerable symbols in an executable or its minimal blob representation.
+func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
 	if err != nil {
 		return err
 	}
-	defer exe.Close()
 
 	p := &govulncheck.Progress{Message: binaryProgressMessage}
 	if err := handler.Progress(p); err != nil {
 		return err
 	}
-	vr, err := binary(ctx, exe, &cfg.Config, client)
-	if err != nil {
-		return fmt.Errorf("govulncheck: %v", err)
-	}
-	callstacks := binaryCallstacks(vr)
-	return emitResult(handler, vr, callstacks)
+	return vulncheck.Binary(ctx, handler, bin, &cfg.Config, client)
 }
 
-func binaryCallstacks(vr *vulncheck.Result) map[*vulncheck.Vuln]vulncheck.CallStack {
-	callstacks := map[*vulncheck.Vuln]vulncheck.CallStack{}
-	for _, vv := range uniqueVulns(vr.Vulns) {
-		f := &vulncheck.FuncNode{Package: vv.ImportSink, Name: vv.Symbol}
-		parts := strings.Split(vv.Symbol, ".")
-		if len(parts) != 1 {
-			f.RecvType = parts[0]
-			f.Name = parts[1]
+func createBin(path string) (*vulncheck.Bin, error) {
+	// First check if the path points to a Go binary. Otherwise, blob
+	// parsing might json decode a Go binary which takes time.
+	//
+	// TODO(#64716): use fingerprinting to make this precise, clean, and fast.
+	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(path)
+	if err == nil {
+		var main *packages.Module
+		if bi.Main.Path != "" {
+			main = &packages.Module{
+				Path:    bi.Main.Path,
+				Version: bi.Main.Version,
+			}
 		}
-		callstacks[vv] = vulncheck.CallStack{vulncheck.StackEntry{Function: f}}
+
+		return &vulncheck.Bin{
+			Path:       bi.Path,
+			Main:       main,
+			Modules:    mods,
+			PkgSymbols: packageSymbols,
+			GoVersion:  bi.GoVersion,
+			GOOS:       findSetting("GOOS", bi),
+			GOARCH:     findSetting("GOARCH", bi),
+		}, nil
+	}
+
+	// Otherwise, see if the path points to a valid blob.
+	bin := parseBlob(path)
+	if bin != nil {
+		return bin, nil
 	}
-	return callstacks
+
+	return nil, errors.New("unrecognized binary format")
 }
 
-// uniqueVulns does for binary mode what uniqueCallStack does for source mode.
-// It tries not to report redundant symbols. Since there are no call stacks in
-// binary mode, the following approximate approach is used. Do not report unexported
-// symbols for a  triple if there are some exported symbols.
-// Otherwise, report all unexported symbols to avoid not reporting anything.
-func uniqueVulns(vulns []*vulncheck.Vuln) []*vulncheck.Vuln {
-	type key struct {
-		id  string
-		pkg string
-		mod string
+// parseBlob extracts vulncheck.Bin from a valid blob at path.
+// If it cannot recognize a valid blob, returns nil.
+func parseBlob(path string) *vulncheck.Bin {
+	from, err := os.Open(path)
+	if err != nil {
+		return nil
 	}
-	hasExported := make(map[key]bool)
-	for _, v := range vulns {
-		if isExported(v.Symbol) {
-			k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-			hasExported[k] = true
-		}
+	defer from.Close()
+
+	dec := json.NewDecoder(from)
+
+	var h header
+	if err := dec.Decode(&h); err != nil {
+		return nil // no header
+	} else if h.Name != extractModeID || h.Version != extractModeVersion {
+		return nil // invalid header
 	}
 
-	var uniques []*vulncheck.Vuln
-	for _, v := range vulns {
-		k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-		if isExported(v.Symbol) || !hasExported[k] {
-			uniques = append(uniques, v)
-		}
+	var b vulncheck.Bin
+	if err := dec.Decode(&b); err != nil {
+		return nil // no body
+	}
+	if dec.More() {
+		return nil // we want just header and body, nothing else
 	}
-	return uniques
+	return &b
 }
 
-// isExported checks if the symbol is exported. Assumes that the
-// symbol is of the form "identifier" or "identifier1.identifier2".
-func isExported(symbol string) bool {
-	parts := strings.Split(symbol, ".")
-	if len(parts) == 1 {
-		return unicode.IsUpper(rune(symbol[0]))
+// findSetting returns value of setting from bi if present.
+// Otherwise, returns "".
+func findSetting(setting string, bi *debug.BuildInfo) string {
+	for _, s := range bi.Settings {
+		if s.Key == setting {
+			return s.Value
+		}
 	}
-	return unicode.IsUpper(rune(parts[1][0]))
+	return ""
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_118.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_118.go
deleted file mode 100644
index d4345f3b..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_118.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package scan
-
-import (
-	"context"
-	"io"
-
-	"golang.org/x/vuln/internal/client"
-	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *vulncheck.Result, err error) {
-	return vulncheck.Binary(ctx, exe, cfg, client)
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_not118.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
deleted file mode 100644
index 0f66a02c..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package scan
-
-import (
-	"context"
-	"errors"
-	"io"
-
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *vulncheck.Config) (_ *vulncheck.Result, err error) {
-	return nil, errors.New("compile with Go 1.18 or higher to analyze binary files")
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/errors.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/errors.go
index 920edd4c..c28e3c5a 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/errors.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/errors.go
@@ -22,7 +22,7 @@ var (
 	// errUsage indicates that there was a usage error on the command line.
 	//
 	// In this case, we assume that the user does not know how to run
-	// govulncheck, and print the usage message with exit status 2.
+	// govulncheck and exit with status 2.
 	errUsage = &exitCodeError{message: "invalid usage", code: 2}
 
 	// errGoVersionMismatch is used to indicate that there is a mismatch between
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/extract.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/extract.go
new file mode 100644
index 00000000..58a3f673
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/extract.go
@@ -0,0 +1,60 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scan
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"sort"
+
+	"golang.org/x/vuln/internal/derrors"
+	"golang.org/x/vuln/internal/vulncheck"
+)
+
+const (
+	// extractModeID is the unique name of the extract mode protocol
+	extractModeID      = "govulncheck-extract"
+	extractModeVersion = "0.1.0"
+)
+
+// header information for the blob output.
+type header struct {
+	Name    string `json:"name"`
+	Version string `json:"version"`
+}
+
+// runExtract dumps the extracted abstraction of binary at cfg.patterns to out.
+// It prints out exactly two blob messages, one with the header and one with
+// the vulncheck.Bin as the body.
+func runExtract(cfg *config, out io.Writer) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
+	if err != nil {
+		return err
+	}
+	sortBin(bin) // sort for easier testing and validation
+	header := header{
+		Name:    extractModeID,
+		Version: extractModeVersion,
+	}
+
+	enc := json.NewEncoder(out)
+
+	if err := enc.Encode(header); err != nil {
+		return fmt.Errorf("marshaling blob header: %v", err)
+	}
+	if err := enc.Encode(bin); err != nil {
+		return fmt.Errorf("marshaling blob body: %v", err)
+	}
+	return nil
+}
+
+func sortBin(bin *vulncheck.Bin) {
+	sort.SliceStable(bin.PkgSymbols, func(i, j int) bool {
+		return bin.PkgSymbols[i].Pkg+"."+bin.PkgSymbols[i].Name < bin.PkgSymbols[j].Pkg+"."+bin.PkgSymbols[j].Name
+	})
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/flags.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/flags.go
index 1e581102..5512540f 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/flags.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/flags.go
@@ -19,37 +19,37 @@ import (
 type config struct {
 	govulncheck.Config
 	patterns []string
-	mode     string
 	db       string
-	json     bool
 	dir      string
-	tags     []string
+	tags     buildutil.TagsFlag
 	test     bool
-	show     []string
+	show     ShowFlag
+	format   FormatFlag
 	env      []string
 }
 
-const (
-	modeBinary  = "binary"
-	modeSource  = "source"
-	modeConvert = "convert" // only intended for use by gopls
-	modeQuery   = "query"   // only intended for use by gopls
-)
-
 func parseFlags(cfg *config, stderr io.Writer, args []string) error {
-	var tagsFlag buildutil.TagsFlag
-	var showFlag showFlag
+	var version bool
+	var json bool
+	var scanFlag ScanFlag
+	var modeFlag ModeFlag
 	flags := flag.NewFlagSet("", flag.ContinueOnError)
 	flags.SetOutput(stderr)
-	flags.BoolVar(&cfg.json, "json", false, "output JSON")
-	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode)")
+	flags.BoolVar(&json, "json", false, "output JSON (Go compatible legacy flag, see format flag)")
+	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode, default false)")
 	flags.StringVar(&cfg.dir, "C", "", "change to `dir` before running govulncheck")
 	flags.StringVar(&cfg.db, "db", "https://vuln.go.dev", "vulnerability database `url`")
-	flags.StringVar(&cfg.mode, "mode", modeSource, "supports source or binary")
-	flags.Var(&tagsFlag, "tags", "comma-separated `list` of build tags")
-	flags.Var(&showFlag, "show", "enable display of additional information specified by `list`")
-	scanLevel := flags.String("scan-level", "symbol", "set the scanning level desired, one of module, package or symbol")
-	flags.Usage = func() {
+	flags.Var(&modeFlag, "mode", "supports 'source', 'binary', and 'extract' (default 'source')")
+	flags.Var(&cfg.tags, "tags", "comma-separated `list` of build tags")
+	flags.Var(&cfg.show, "show", "enable display of additional information specified by the comma separated `list`\nThe supported values are 'traces','color', 'version', and 'verbose'")
+	flags.Var(&cfg.format, "format", "specify format output\nThe supported values are 'text', 'json', 'sarif', and 'openvex' (default 'text')")
+	flags.BoolVar(&version, "version", false, "print the version information")
+	flags.Var(&scanFlag, "scan", "set the scanning level desired, one of 'module', 'package', or 'symbol' (default 'symbol')")
+
+	// We don't want to print the whole usage message on each flags
+	// error, so we set to a no-op and do the printing ourselves.
+	flags.Usage = func() {}
+	usage := func() {
 		fmt.Fprint(flags.Output(), `Govulncheck reports known vulnerabilities in dependencies.
 
 Usage:
@@ -61,44 +61,60 @@ Usage:
 		flags.PrintDefaults()
 		fmt.Fprintf(flags.Output(), "\n%s\n", detailsMessage)
 	}
+
 	if err := flags.Parse(args); err != nil {
 		if err == flag.ErrHelp {
+			usage() // print usage only on help
 			return errHelp
 		}
-		return err
+		return errUsage
 	}
 	cfg.patterns = flags.Args()
-	if cfg.mode != modeConvert && len(cfg.patterns) == 0 {
-		flags.Usage()
-		return errUsage
+	if version {
+		cfg.show = append(cfg.show, "version")
 	}
-	cfg.tags = tagsFlag
-	cfg.show = showFlag
-	cfg.ScanLevel = govulncheck.ScanLevel(*scanLevel)
-	if err := validateConfig(cfg); err != nil {
+	cfg.ScanLevel = govulncheck.ScanLevel(scanFlag)
+	cfg.ScanMode = govulncheck.ScanMode(modeFlag)
+	if err := validateConfig(cfg, json); err != nil {
 		fmt.Fprintln(flags.Output(), err)
 		return errUsage
 	}
 	return nil
 }
 
-var supportedModes = map[string]bool{
-	modeSource:  true,
-	modeBinary:  true,
-	modeConvert: true,
-	modeQuery:   true,
-}
+func validateConfig(cfg *config, json bool) error {
+	// take care of default values
+	if cfg.ScanMode == "" {
+		cfg.ScanMode = govulncheck.ScanModeSource
+	}
+	if cfg.ScanLevel == "" {
+		cfg.ScanLevel = govulncheck.ScanLevelSymbol
+	}
+	if json {
+		if cfg.format != formatUnset {
+			return fmt.Errorf("the -json flag cannot be used with -format flag")
+		}
+		cfg.format = formatJSON
+	} else {
+		if cfg.format == formatUnset {
+			cfg.format = formatText
+		}
+	}
 
-func validateConfig(cfg *config) error {
-	if _, ok := supportedModes[cfg.mode]; !ok {
-		return fmt.Errorf("%q is not a valid mode", cfg.mode)
+	// show flag is only supported with text output
+	if cfg.format != formatText && len(cfg.show) > 0 {
+		return fmt.Errorf("the -show flag is not supported for %s output", cfg.format)
 	}
-	switch cfg.mode {
-	case modeSource:
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		if len(cfg.patterns) == 1 && isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is a file.\n\n%v", cfg.patterns[0], errNoBinaryFlag)
 		}
-	case modeBinary:
+		if cfg.ScanLevel == govulncheck.ScanLevelModule && len(cfg.patterns) != 0 {
+			return fmt.Errorf("patterns are not accepted for module only scanning")
+		}
+	case govulncheck.ScanModeBinary:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in binary mode")
 		}
@@ -111,7 +127,23 @@ func validateConfig(cfg *config) error {
 		if !isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is not a file", cfg.patterns[0])
 		}
-	case modeConvert:
+	case govulncheck.ScanModeExtract:
+		if cfg.test {
+			return fmt.Errorf("the -test flag is not supported in extract mode")
+		}
+		if len(cfg.tags) > 0 {
+			return fmt.Errorf("the -tags flag is not supported in extract mode")
+		}
+		if len(cfg.patterns) != 1 {
+			return fmt.Errorf("only 1 binary can be extracted at a time")
+		}
+		if cfg.format == formatJSON {
+			return fmt.Errorf("the json format must be off in extract mode")
+		}
+		if !isFile(cfg.patterns[0]) {
+			return fmt.Errorf("%q is not a file (source extraction is not supported)", cfg.patterns[0])
+		}
+	case govulncheck.ScanModeConvert:
 		if len(cfg.patterns) != 0 {
 			return fmt.Errorf("patterns are not accepted in convert mode")
 		}
@@ -124,15 +156,15 @@ func validateConfig(cfg *config) error {
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in convert mode")
 		}
-	case modeQuery:
+	case govulncheck.ScanModeQuery:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in query mode")
 		}
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in query mode")
 		}
-		if !cfg.json {
-			return fmt.Errorf("the -json flag must be set in query mode")
+		if cfg.format != formatJSON {
+			return fmt.Errorf("the json format must be set in query mode")
 		}
 		for _, pattern := range cfg.patterns {
 			// Parse the input here so that we can catch errors before
@@ -142,9 +174,6 @@ func validateConfig(cfg *config) error {
 			}
 		}
 	}
-	if cfg.json && len(cfg.show) > 0 {
-		return fmt.Errorf("the -show flag is not supported for JSON output")
-	}
 	return nil
 }
 
@@ -156,26 +185,119 @@ func isFile(path string) bool {
 	return !s.IsDir()
 }
 
-// fileExists checks if file path exists. Returns true
-// if the file exists or it cannot prove that it does
-// not exist. Otherwise, returns false.
-func fileExists(path string) bool {
-	if _, err := os.Stat(path); err == nil {
-		return true
-	} else if errors.Is(err, os.ErrNotExist) {
-		return false
+var errFlagParse = errors.New("see -help for details")
+
+// ShowFlag is used for parsing and validation of
+// govulncheck -show flag.
+type ShowFlag []string
+
+var supportedShows = map[string]bool{
+	"traces":  true,
+	"color":   true,
+	"verbose": true,
+	"version": true,
+}
+
+func (v *ShowFlag) Set(s string) error {
+	if s == "" {
+		return nil
+	}
+	for _, show := range strings.Split(s, ",") {
+		sh := strings.TrimSpace(show)
+		if _, ok := supportedShows[sh]; !ok {
+			return errFlagParse
+		}
+		*v = append(*v, sh)
 	}
-	// Conservatively return true if os.Stat fails
-	// for some other reason.
-	return true
+	return nil
 }
 
-type showFlag []string
+func (v *ShowFlag) Get() interface{} { return *v }
+func (v *ShowFlag) String() string   { return "" }
+
+// Update the text handler h with values of the flag.
+func (v ShowFlag) Update(h *TextHandler) {
+	for _, show := range v {
+		switch show {
+		case "traces":
+			h.showTraces = true
+		case "color":
+			h.showColor = true
+		case "version":
+			h.showVersion = true
+		case "verbose":
+			h.showVerbose = true
+		}
+	}
+}
 
-func (v *showFlag) Set(s string) error {
-	*v = append(*v, strings.Split(s, ",")...)
+// FormatFlag is used for parsing and validation of
+// govulncheck -format flag.
+type FormatFlag string
+
+const (
+	formatUnset   = ""
+	formatJSON    = "json"
+	formatText    = "text"
+	formatSarif   = "sarif"
+	formatOpenVEX = "openvex"
+)
+
+var supportedFormats = map[string]bool{
+	formatJSON:    true,
+	formatText:    true,
+	formatSarif:   true,
+	formatOpenVEX: true,
+}
+
+func (f *FormatFlag) Get() interface{} { return *f }
+func (f *FormatFlag) Set(s string) error {
+	if _, ok := supportedFormats[s]; !ok {
+		return errFlagParse
+	}
+	*f = FormatFlag(s)
 	return nil
 }
+func (f *FormatFlag) String() string { return "" }
 
-func (f *showFlag) Get() interface{} { return *f }
-func (f *showFlag) String() string   { return "" }
+// ModeFlag is used for parsing and validation of
+// govulncheck -mode flag.
+type ModeFlag string
+
+var supportedModes = map[string]bool{
+	govulncheck.ScanModeSource:  true,
+	govulncheck.ScanModeBinary:  true,
+	govulncheck.ScanModeConvert: true,
+	govulncheck.ScanModeQuery:   true,
+	govulncheck.ScanModeExtract: true,
+}
+
+func (f *ModeFlag) Get() interface{} { return *f }
+func (f *ModeFlag) Set(s string) error {
+	if _, ok := supportedModes[s]; !ok {
+		return errFlagParse
+	}
+	*f = ModeFlag(s)
+	return nil
+}
+func (f *ModeFlag) String() string { return "" }
+
+// ScanFlag is used for parsing and validation of
+// govulncheck -scan flag.
+type ScanFlag string
+
+var supportedLevels = map[string]bool{
+	govulncheck.ScanLevelModule:  true,
+	govulncheck.ScanLevelPackage: true,
+	govulncheck.ScanLevelSymbol:  true,
+}
+
+func (f *ScanFlag) Get() interface{} { return *f }
+func (f *ScanFlag) Set(s string) error {
+	if _, ok := supportedLevels[s]; !ok {
+		return errFlagParse
+	}
+	*f = ScanFlag(s)
+	return nil
+}
+func (f *ScanFlag) String() string { return "" }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/run.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/run.go
index fe452cfa..f29b9d31 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/run.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/run.go
@@ -15,8 +15,11 @@ import (
 	"strings"
 	"time"
 
+	"golang.org/x/telemetry/counter"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/openvex"
+	"golang.org/x/vuln/internal/sarif"
 )
 
 // RunGovulncheck performs main govulncheck functionality and exits the
@@ -27,9 +30,6 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 	if err := parseFlags(cfg, stderr, args); err != nil {
 		return err
 	}
-	if cfg.mode == modeConvert {
-		return convertJSONToText(r, stdout)
-	}
 
 	client, err := client.NewClient(cfg.db, nil)
 	if err != nil {
@@ -38,42 +38,48 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 
 	prepareConfig(ctx, cfg, client)
 	var handler govulncheck.Handler
-	switch {
-	case cfg.json:
+	switch cfg.format {
+	case formatJSON:
 		handler = govulncheck.NewJSONHandler(stdout)
+	case formatSarif:
+		handler = sarif.NewHandler(stdout)
+	case formatOpenVEX:
+		handler = openvex.NewHandler(stdout)
 	default:
 		th := NewTextHandler(stdout)
-		th.Show(cfg.show)
+		cfg.show.Update(th)
 		handler = th
 	}
 
-	// Write the introductory message to the user.
 	if err := handler.Config(&cfg.Config); err != nil {
 		return err
 	}
 
-	switch cfg.mode {
-	case modeSource:
+	incTelemetryFlagCounters(cfg)
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		dir := filepath.FromSlash(cfg.dir)
 		err = runSource(ctx, handler, cfg, client, dir)
-	case modeBinary:
+	case govulncheck.ScanModeBinary:
 		err = runBinary(ctx, handler, cfg, client)
-	case modeQuery:
+	case govulncheck.ScanModeExtract:
+		return runExtract(cfg, stdout)
+	case govulncheck.ScanModeQuery:
 		err = runQuery(ctx, handler, cfg, client)
+	case govulncheck.ScanModeConvert:
+		err = govulncheck.HandleJSON(r, handler)
 	}
 	if err != nil {
 		return err
 	}
-	if err := Flush(handler); err != nil {
-		return err
-	}
-	return nil
+	return Flush(handler)
 }
 
 func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 	cfg.ProtocolVersion = govulncheck.ProtocolVersion
 	cfg.DB = cfg.db
-	if cfg.mode == modeSource && cfg.GoVersion == "" {
+	if cfg.ScanMode == govulncheck.ScanModeSource && cfg.GoVersion == "" {
 		const goverPrefix = "GOVERSION="
 		for _, env := range cfg.env {
 			if val := strings.TrimPrefix(env, goverPrefix); val != env {
@@ -82,7 +88,7 @@ func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 		}
 		if cfg.GoVersion == "" {
 			if out, err := exec.Command("go", "env", "GOVERSION").Output(); err == nil {
-				cfg.GoVersion = string(out)
+				cfg.GoVersion = strings.TrimSpace(string(out))
 			}
 		}
 	}
@@ -133,13 +139,22 @@ func scannerVersion(cfg *config, bi *debug.BuildInfo) {
 	cfg.ScannerVersion = buf.String()
 }
 
-// convertJSONToText converts r, which is expected to be the JSON output of govulncheck,
-// into the text output, and writes the output to w.
-func convertJSONToText(r io.Reader, w io.Writer) error {
-	h := NewTextHandler(w)
-	if err := govulncheck.HandleJSON(r, h); err != nil {
-		return err
+func incTelemetryFlagCounters(cfg *config) {
+	counter.Inc(fmt.Sprintf("govulncheck/mode:%s", cfg.ScanMode))
+	counter.Inc(fmt.Sprintf("govulncheck/scan:%s", cfg.ScanLevel))
+	counter.Inc(fmt.Sprintf("govulncheck/format:%s", cfg.format))
+
+	if len(cfg.show) == 0 {
+		counter.Inc("govulncheck/show:none")
+	}
+	for _, s := range cfg.show {
+		counter.Inc(fmt.Sprintf("govulncheck/show:%s", s))
+	}
+}
+
+func Flush(h govulncheck.Handler) error {
+	if th, ok := h.(interface{ Flush() error }); ok {
+		return th.Flush()
 	}
-	Flush(h)
 	return nil
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/source.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/source.go
index cfdc1227..e9232112 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/source.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/source.go
@@ -7,13 +7,11 @@ package scan
 import (
 	"context"
 	"fmt"
-	"path/filepath"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
@@ -22,189 +20,30 @@ import (
 // Vulnerabilities can be called (affecting the package, because a vulnerable
 // symbol is actually exercised) or just imported by the package
 // (likely having a non-affecting outcome).
-func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) error {
-	var pkgs []*packages.Package
+func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	if cfg.ScanLevel.WantPackages() && len(cfg.patterns) == 0 {
+		return nil // don't throw an error here
+	}
+	if !gomodExists(dir) {
+		return errNoGoMod
+	}
 	graph := vulncheck.NewPackageGraph(cfg.GoVersion)
 	pkgConfig := &packages.Config{
 		Dir:   dir,
 		Tests: cfg.test,
 		Env:   cfg.env,
 	}
-	pkgs, err := graph.LoadPackages(pkgConfig, cfg.tags, cfg.patterns)
-	if err != nil {
-		// Try to provide a meaningful and actionable error message.
-		if !fileExists(filepath.Join(dir, "go.mod")) {
-			return fmt.Errorf("govulncheck: %v", errNoGoMod)
-		}
+	if err := graph.LoadPackagesAndMods(pkgConfig, cfg.tags, cfg.patterns, cfg.ScanLevel == govulncheck.ScanLevelSymbol); err != nil {
 		if isGoVersionMismatchError(err) {
-			return fmt.Errorf("govulncheck: %v\n\n%v", errGoVersionMismatch, err)
-		}
-		return fmt.Errorf("govulncheck: loading packages: %w", err)
-	}
-	if err := handler.Progress(sourceProgressMessage(pkgs)); err != nil {
-		return err
-	}
-	vr, err := vulncheck.Source(ctx, pkgs, &cfg.Config, client, graph)
-	if err != nil {
-		return err
-	}
-	callStacks := vulncheck.CallStacks(vr)
-	return emitResult(handler, vr, callStacks)
-}
-
-func emitResult(handler govulncheck.Handler, vr *vulncheck.Result, callstacks map[*vulncheck.Vuln]vulncheck.CallStack) error {
-	osvs := map[string]*osv.Entry{}
-	// first deal with all the affected vulnerabilities
-	emitted := map[string]bool{}
-	seen := map[string]bool{}
-	for _, vv := range vr.Vulns {
-		osvs[vv.OSV.ID] = vv.OSV
-		fixed := fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected)
-		stack := callstacks[vv]
-		if stack == nil {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixed,
-			Trace:        tracefromEntries(stack),
-		})
-	}
-	for _, vv := range vr.Vulns {
-		if emitted[vv.OSV.ID] {
-			continue
+			return fmt.Errorf("%v\n\n%v", errGoVersionMismatch, err)
 		}
-		stacks := callstacks[vv]
-		if len(stacks) != 0 {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected),
-			Trace:        []*govulncheck.Frame{frameFromPackage(vv.ImportSink)},
-		})
-	}
-	return nil
-}
-
-func emitFinding(handler govulncheck.Handler, osvs map[string]*osv.Entry, seen map[string]bool, finding *govulncheck.Finding) error {
-	if !seen[finding.OSV] {
-		seen[finding.OSV] = true
-		if err := handler.OSV(osvs[finding.OSV]); err != nil {
-			return err
-		}
-	}
-	return handler.Finding(finding)
-}
-
-// tracefromEntries creates a sequence of
-// frames from vcs. Position of a Frame is the
-// call position of the corresponding stack entry.
-func tracefromEntries(vcs vulncheck.CallStack) []*govulncheck.Frame {
-	var frames []*govulncheck.Frame
-	for i := len(vcs) - 1; i >= 0; i-- {
-		e := vcs[i]
-		fr := frameFromPackage(e.Function.Package)
-		fr.Function = e.Function.Name
-		fr.Receiver = e.Function.Receiver()
-		if e.Call == nil || e.Call.Pos == nil {
-			fr.Position = nil
-		} else {
-			fr.Position = &govulncheck.Position{
-				Filename: e.Call.Pos.Filename,
-				Offset:   e.Call.Pos.Offset,
-				Line:     e.Call.Pos.Line,
-				Column:   e.Call.Pos.Column,
-			}
-		}
-		frames = append(frames, fr)
+		return fmt.Errorf("loading packages: %w", err)
 	}
-	return frames
-}
 
-func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
-	fr := &govulncheck.Frame{}
-	if pkg != nil {
-		fr.Module = pkg.Module.Path
-		fr.Version = pkg.Module.Version
-		fr.Package = pkg.PkgPath
-	}
-	if pkg.Module.Replace != nil {
-		fr.Module = pkg.Module.Replace.Path
-		fr.Version = pkg.Module.Replace.Version
+	if cfg.ScanLevel.WantPackages() && len(graph.TopPkgs()) == 0 {
+		return nil // early exit
 	}
-	return fr
-}
-
-// sourceProgressMessage returns a string of the form
-//
-//	"Scanning your code and P packages across M dependent modules for known vulnerabilities..."
-//
-// P is the number of strictly dependent packages of
-// topPkgs and Y is the number of their modules.
-func sourceProgressMessage(topPkgs []*packages.Package) *govulncheck.Progress {
-	pkgs, mods := depPkgsAndMods(topPkgs)
-
-	pkgsPhrase := fmt.Sprintf("%d package", pkgs)
-	if pkgs != 1 {
-		pkgsPhrase += "s"
-	}
-
-	modsPhrase := fmt.Sprintf("%d dependent module", mods)
-	if mods != 1 {
-		modsPhrase += "s"
-	}
-
-	msg := fmt.Sprintf("Scanning your code and %s across %s for known vulnerabilities...", pkgsPhrase, modsPhrase)
-	return &govulncheck.Progress{Message: msg}
-}
-
-// depPkgsAndMods returns the number of packages that
-// topPkgs depend on and the number of their modules.
-func depPkgsAndMods(topPkgs []*packages.Package) (int, int) {
-	tops := make(map[string]bool)
-	depPkgs := make(map[string]bool)
-	depMods := make(map[string]bool)
-
-	for _, t := range topPkgs {
-		tops[t.PkgPath] = true
-	}
-
-	var visit func(*packages.Package, bool)
-	visit = func(p *packages.Package, top bool) {
-		path := p.PkgPath
-		if depPkgs[path] {
-			return
-		}
-		if tops[path] && !top {
-			// A top package that is a dependency
-			// will not be in depPkgs, so we skip
-			// reiterating on it here.
-			return
-		}
-
-		// We don't count a top-level package as
-		// a dependency even when they are used
-		// as a dependent package.
-		if !tops[path] {
-			depPkgs[path] = true
-			if p.Module != nil &&
-				p.Module.Path != internal.GoStdModulePath && // no module for stdlib
-				p.Module.Path != internal.UnknownModulePath { // no module for unknown
-				depMods[p.Module.Path] = true
-			}
-		}
-
-		for _, d := range p.Imports {
-			visit(d, false)
-		}
-	}
-
-	for _, t := range topPkgs {
-		visit(t, true)
-	}
-
-	return len(depPkgs), len(depMods)
+	return vulncheck.Source(ctx, handler, &cfg.Config, client, graph)
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/template.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/template.go
index 953fbaeb..5c1a4a75 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/template.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/template.go
@@ -14,9 +14,9 @@ import (
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
 )
 
 type findingSummary struct {
@@ -26,9 +26,11 @@ type findingSummary struct {
 }
 
 type summaryCounters struct {
-	VulnerabilitiesCalled int
-	ModulesCalled         int
-	StdlibCalled          bool
+	VulnerabilitiesCalled   int
+	ModulesCalled           int
+	VulnerabilitiesImported int
+	VulnerabilitiesRequired int
+	StdlibCalled            bool
 }
 
 func fixupFindings(osvs []*osv.Entry, findings []*findingSummary) {
@@ -74,27 +76,22 @@ func groupBy(findings []*findingSummary, compare func(left, right *findingSummar
 	return result
 }
 
-func counters(findings []*findingSummary) summaryCounters {
-	vulns := map[string]struct{}{}
-	modules := map[string]struct{}{}
+func isRequired(findings []*findingSummary) bool {
 	for _, f := range findings {
-		if f.Trace[0].Function == "" {
-			continue
+		if f.Trace[0].Module != "" {
+			return true
 		}
-		id := f.OSV.ID
-		vulns[id] = struct{}{}
-		mod := f.Trace[0].Module
-		modules[mod] = struct{}{}
-	}
-	result := summaryCounters{
-		VulnerabilitiesCalled: len(vulns),
-		ModulesCalled:         len(modules),
 	}
-	if _, found := modules[internal.GoStdModulePath]; found {
-		result.StdlibCalled = true
-		result.ModulesCalled--
+	return false
+}
+
+func isImported(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if f.Trace[0].Package != "" {
+			return true
+		}
 	}
-	return result
+	return false
 }
 
 func isCalled(findings []*findingSummary) bool {
@@ -105,6 +102,7 @@ func isCalled(findings []*findingSummary) bool {
 	}
 	return false
 }
+
 func getOSV(osvs []*osv.Entry, id string) *osv.Entry {
 	for _, entry := range osvs {
 		if entry.ID == id {
@@ -184,7 +182,13 @@ func posToString(p *govulncheck.Position) string {
 
 func symbol(frame *govulncheck.Frame, short bool) string {
 	buf := &strings.Builder{}
-	addSymbolName(buf, frame, short)
+	addSymbol(buf, frame, short)
+	return buf.String()
+}
+
+func symbolName(frame *govulncheck.Frame) string {
+	buf := &strings.Builder{}
+	addSymbolName(buf, frame)
 	return buf.String()
 }
 
@@ -196,44 +200,36 @@ func symbol(frame *govulncheck.Frame, short bool) string {
 // If the vulnerable symbol is in the users code, it will show the entry point
 // and the vulnerable symbol.
 func compactTrace(finding *govulncheck.Finding) string {
-	if len(finding.Trace) < 1 {
+	compact := traces.Compact(finding)
+	if len(compact) == 0 {
 		return ""
 	}
-	iTop := len(finding.Trace) - 1
-	topModule := finding.Trace[iTop].Module
-	// search for the exit point of the top module
-	for i, frame := range finding.Trace {
-		if frame.Module == topModule {
-			iTop = i
-			break
-		}
-	}
-
-	if iTop == 0 {
-		// all in one module, reset to the end
-		iTop = len(finding.Trace) - 1
-	}
 
+	l := len(compact)
+	iTop := l - 1
 	buf := &strings.Builder{}
-	topPos := posToString(finding.Trace[iTop].Position)
+	topPos := posToString(compact[iTop].Position)
 	if topPos != "" {
 		buf.WriteString(topPos)
 		buf.WriteString(": ")
 	}
 
-	if iTop > 0 {
-		addSymbolName(buf, finding.Trace[iTop], true)
+	if l > 1 {
+		// print the root of the compact trace
+		addSymbol(buf, compact[iTop], true)
 		buf.WriteString(" calls ")
 	}
-	if iTop > 1 {
-		addSymbolName(buf, finding.Trace[iTop-1], true)
+	if l > 2 {
+		// print next element of the trace, if any
+		addSymbol(buf, compact[iTop-1], true)
 		buf.WriteString(", which")
-		if iTop > 2 {
+		if l > 3 {
+			// don't print the third element, just acknowledge it
 			buf.WriteString(" eventually")
 		}
 		buf.WriteString(" calls ")
 	}
-	addSymbolName(buf, finding.Trace[0], true)
+	addSymbol(buf, compact[0], true) // print the vulnerable symbol
 	return buf.String()
 }
 
@@ -265,7 +261,7 @@ func importPathToAssumedName(importPath string) string {
 	return base
 }
 
-func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
+func addSymbol(w io.Writer, frame *govulncheck.Frame, short bool) {
 	if frame.Function == "" {
 		return
 	}
@@ -277,6 +273,10 @@ func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
 		io.WriteString(w, pkg)
 		io.WriteString(w, ".")
 	}
+	addSymbolName(w, frame)
+}
+
+func addSymbolName(w io.Writer, frame *govulncheck.Frame) {
 	if frame.Receiver != "" {
 		if frame.Receiver[0] == '*' {
 			io.WriteString(w, frame.Receiver[1:])
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/text.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/text.go
index 845054b9..ab49bdd1 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/text.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/text.go
@@ -7,19 +7,19 @@ package scan
 import (
 	"fmt"
 	"io"
+	"sort"
 	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/vulncheck"
 )
 
 type style int
 
 const (
 	defaultStyle = style(iota)
-	goStyle
-	scannerStyle
 	osvCalledStyle
 	osvImportedStyle
 	detailsStyle
@@ -34,81 +34,143 @@ func NewTextHandler(w io.Writer) *TextHandler {
 }
 
 type TextHandler struct {
-	w        io.Writer
-	osvs     []*osv.Entry
-	findings []*findingSummary
+	w         io.Writer
+	sbom      *govulncheck.SBOM
+	osvs      []*osv.Entry
+	findings  []*findingSummary
+	scanLevel govulncheck.ScanLevel
+	scanMode  govulncheck.ScanMode
 
 	err error
 
-	showColor  bool
-	showTraces bool
+	showColor   bool
+	showTraces  bool
+	showVersion bool
+	showVerbose bool
 }
 
 const (
 	detailsMessage = `For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.`
 
 	binaryProgressMessage = `Scanning your binary for known vulnerabilities...`
-)
 
-func (h *TextHandler) Show(show []string) {
-	for _, show := range show {
-		switch show {
-		case "traces":
-			h.showTraces = true
-		case "color":
-			h.showColor = true
-		}
-	}
-}
+	noVulnsMessage = `No vulnerabilities found.`
 
-func Flush(h govulncheck.Handler) error {
-	if th, ok := h.(interface{ Flush() error }); ok {
-		return th.Flush()
-	}
-	return nil
-}
+	noOtherVulnsMessage = `No other vulnerabilities found.`
+
+	verboseMessage = `'-show verbose' for more details`
+
+	symbolMessage = `'-scan symbol' for more fine grained vulnerability detection`
+)
 
 func (h *TextHandler) Flush() error {
+	if h.showVerbose {
+		h.printSBOM()
+	}
 	if len(h.findings) == 0 {
-		return nil
+		h.print(noVulnsMessage + "\n")
+	} else {
+		fixupFindings(h.osvs, h.findings)
+		counters := h.allVulns(h.findings)
+		h.summary(counters)
 	}
-	fixupFindings(h.osvs, h.findings)
-	h.byVulnerability(h.findings)
-	h.summary(h.findings)
 	if h.err != nil {
 		return h.err
 	}
-	if isCalled(h.findings) {
+	// We found vulnerabilities when the findings' level matches the scan level.
+	if (isCalled(h.findings) && h.scanLevel == govulncheck.ScanLevelSymbol) ||
+		(isImported(h.findings) && h.scanLevel == govulncheck.ScanLevelPackage) ||
+		(isRequired(h.findings) && h.scanLevel == govulncheck.ScanLevelModule) {
 		return errVulnerabilitiesFound
 	}
+
 	return nil
 }
 
-// Config writes text output formatted according to govulncheck-intro.tmpl.
+// Config writes version information only if --version was set.
 func (h *TextHandler) Config(config *govulncheck.Config) error {
-	h.print("govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.\n\nUsing ")
+	h.scanLevel = config.ScanLevel
+	h.scanMode = config.ScanMode
+
+	if !h.showVersion {
+		return nil
+	}
 	if config.GoVersion != "" {
-		h.style(goStyle, config.GoVersion)
-		h.print(` and `)
+		h.style(keyStyle, "Go: ")
+		h.print(config.GoVersion, "\n")
 	}
 	if config.ScannerName != "" {
-		h.style(scannerStyle, config.ScannerName)
+		h.style(keyStyle, "Scanner: ")
+		h.print(config.ScannerName)
 		if config.ScannerVersion != "" {
 			h.print(`@`, config.ScannerVersion)
 		}
-		h.print(` with `)
+		h.print("\n")
 	}
-	h.print(`vulnerability data from `, config.DB)
-	if config.DBLastModified != nil {
-		h.print(` (last modified `, *config.DBLastModified, `)`)
+	if config.DB != "" {
+		h.style(keyStyle, "DB: ")
+		h.print(config.DB, "\n")
+		if config.DBLastModified != nil {
+			h.style(keyStyle, "DB updated: ")
+			h.print(*config.DBLastModified, "\n")
+		}
 	}
-	h.print(".\n\n")
+	h.print("\n")
 	return h.err
 }
 
-// Progress writes progress updates during govulncheck execution..
+func (h *TextHandler) SBOM(sbom *govulncheck.SBOM) error {
+	h.sbom = sbom
+	return nil
+}
+
+func (h *TextHandler) printSBOM() error {
+	if h.sbom == nil {
+		h.print("No packages matched the provided pattern.\n")
+		return nil
+	}
+
+	printed := false
+
+	for i, root := range h.sbom.Roots {
+		if i == 0 {
+			if len(h.sbom.Roots) > 1 {
+				h.print("The package pattern matched the following ", len(h.sbom.Roots), " root packages:\n")
+			} else {
+				h.print("The package pattern matched the following root package:\n")
+			}
+		}
+
+		h.print("  ", root, "\n")
+		printed = true
+	}
+	for i, mod := range h.sbom.Modules {
+		if i == 0 && mod.Path != "stdlib" {
+			h.print("Govulncheck scanned the following ", len(h.sbom.Modules)-1, " modules and the ", h.sbom.GoVersion, " standard library:\n")
+		}
+
+		if mod.Path == "stdlib" {
+			continue
+		}
+
+		h.print("  ", mod.Path)
+		if mod.Version != "" {
+			h.print("@", mod.Version)
+		}
+		h.print("\n")
+		printed = true
+	}
+	if printed {
+		h.print("\n")
+	}
+	return nil
+}
+
+// Progress writes progress updates during govulncheck execution.
 func (h *TextHandler) Progress(progress *govulncheck.Progress) error {
-	h.print(progress.Message, "\n\n")
+	if h.showVerbose {
+		h.print(progress.Message, "\n\n")
+	}
 	return h.err
 }
 
@@ -127,39 +189,64 @@ func (h *TextHandler) Finding(finding *govulncheck.Finding) error {
 	return nil
 }
 
-func (h *TextHandler) byVulnerability(findings []*findingSummary) {
+func (h *TextHandler) allVulns(findings []*findingSummary) summaryCounters {
 	byVuln := groupByVuln(findings)
-	called := 0
+	var called, imported, required [][]*findingSummary
+	mods := map[string]struct{}{}
+	stdlibCalled := false
 	for _, findings := range byVuln {
-		if isCalled(findings) {
-			if called > 0 {
-				h.print("\n")
+		switch {
+		case isCalled(findings):
+			called = append(called, findings)
+			if isStdFindings(findings) {
+				stdlibCalled = true
+			} else {
+				mods[findings[0].Trace[0].Module] = struct{}{}
 			}
-			h.vulnerability(called, findings)
-			called++
+		case isImported(findings):
+			imported = append(imported, findings)
+		default:
+			required = append(required, findings)
 		}
 	}
-	unCalled := len(byVuln) - called
-	if unCalled == 0 {
-		return
+
+	if h.scanLevel.WantSymbols() {
+		h.style(sectionStyle, "=== Symbol Results ===\n\n")
+		if len(called) == 0 {
+			h.print(noVulnsMessage, "\n\n")
+		}
+		for index, findings := range called {
+			h.vulnerability(index, findings)
+		}
 	}
-	h.print("\n")
-	h.style(sectionStyle, "=== Informational ===\n")
-	h.print("\nFound ", unCalled)
-	h.print(choose(unCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(" in packages that you import, but there are no call\nstacks leading to the use of ")
-	h.print(choose(unCalled == 1, `this vulnerability`, `these vulnerabilities`))
-	h.print(". You may not need to\ntake any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck\nfor details.\n\n")
-	index := 0
-	for _, findings := range byVuln {
-		if !isCalled(findings) {
-			if index > 0 {
-				h.print("\n")
-			}
+
+	if h.scanLevel == govulncheck.ScanLevelPackage || (h.scanLevel.WantPackages() && h.showVerbose) {
+		h.style(sectionStyle, "=== Package Results ===\n\n")
+		if len(imported) == 0 {
+			h.print(choose(!h.scanLevel.WantSymbols(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range imported {
 			h.vulnerability(index, findings)
-			index++
 		}
 	}
+
+	if h.showVerbose || h.scanLevel == govulncheck.ScanLevelModule {
+		h.style(sectionStyle, "=== Module Results ===\n\n")
+		if len(required) == 0 {
+			h.print(choose(!h.scanLevel.WantPackages(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range required {
+			h.vulnerability(index, findings)
+		}
+	}
+
+	return summaryCounters{
+		VulnerabilitiesCalled:   len(called),
+		VulnerabilitiesImported: len(imported),
+		VulnerabilitiesRequired: len(required),
+		ModulesCalled:           len(mods),
+		StdlibCalled:            stdlibCalled,
+	}
 }
 
 func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
@@ -185,13 +272,20 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 	byModule := groupByModule(findings)
 	first := true
 	for _, module := range byModule {
-		//TODO: this assumes all traces on a module are found and fixed at the same versions
+		// Note: there can be several findingSummaries for the same vulnerability
+		// emitted during streaming for different scan levels.
+
+		// The module is same for all finding summaries.
 		lastFrame := module[0].Trace[0]
 		mod := lastFrame.Module
+		// For stdlib, try to show package path as module name where
+		// the scan level allows it.
+		// TODO: should this be done in byModule as well?
 		path := lastFrame.Module
-		if path == internal.GoStdModulePath {
-			path = lastFrame.Package
+		if stdPkg := h.pkg(module); path == internal.GoStdModulePath && stdPkg != "" {
+			path = stdPkg
 		}
+		// All findings on a module are found and fixed at the same version
 		foundVersion := moduleVersionString(lastFrame.Module, lastFrame.Version)
 		fixedVersion := moduleVersionString(lastFrame.Module, module[0].FixedVersion)
 		if !first {
@@ -228,59 +322,180 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 		}
 		h.traces(module)
 	}
+	h.print("\n")
+}
+
+// pkg gives the package information for findings summaries
+// if one exists. This is only used to print package path
+// instead of a module for stdlib vulnerabilities at symbol
+// and package scan level.
+func (h *TextHandler) pkg(summaries []*findingSummary) string {
+	for _, f := range summaries {
+		if pkg := f.Trace[0].Package; pkg != "" {
+			return pkg
+		}
+	}
+	return ""
 }
 
+// traces prints out the most precise trace information
+// found in the given summaries.
 func (h *TextHandler) traces(traces []*findingSummary) {
-	first := true
-	for i, entry := range traces {
-		if entry.Compact == "" {
-			continue
+	// Sort the traces by the vulnerable symbol. This
+	// guarantees determinism since we are currently
+	// showing only one trace per symbol.
+	sort.SliceStable(traces, func(i, j int) bool {
+		return symbol(traces[i].Trace[0], true) < symbol(traces[j].Trace[0], true)
+	})
+
+	// compacts are finding summaries with compact traces
+	// suitable for non-verbose textual output. Currently,
+	// only traces produced by symbol analysis.
+	var compacts []*findingSummary
+	for _, t := range traces {
+		if t.Compact != "" {
+			compacts = append(compacts, t)
 		}
-		if first {
-			h.style(keyStyle, "    Example traces found:\n")
+	}
+
+	// binLimit is a limit on the number of binary traces
+	// to show. Traces for binaries are less interesting
+	// as users cannot act on them and they can hence
+	// spam users.
+	const binLimit = 5
+	binary := h.scanMode == govulncheck.ScanModeBinary
+	for i, entry := range compacts {
+		if i == 0 {
+			if binary {
+				h.style(keyStyle, "    Vulnerable symbols found:\n")
+			} else {
+				h.style(keyStyle, "    Example traces found:\n")
+			}
+		}
+
+		// skip showing all symbols in binary mode unless '-show traces' is on.
+		if binary && (i+1) > binLimit && !h.showTraces {
+			h.print("      Use '-show traces' to see the other ", len(compacts)-binLimit, " found symbols\n")
+			break
 		}
-		first = false
 
 		h.print("      #", i+1, ": ")
-		if !h.showTraces {
+
+		if !h.showTraces { // show summarized traces
 			h.print(entry.Compact, "\n")
+			continue
+		}
+
+		if binary {
+			// There are no call stacks in binary mode
+			// so just show the full symbol name.
+			h.print(symbol(entry.Trace[0], false), "\n")
 		} else {
 			h.print("for function ", symbol(entry.Trace[0], false), "\n")
 			for i := len(entry.Trace) - 1; i >= 0; i-- {
 				t := entry.Trace[i]
 				h.print("        ")
+				h.print(symbolName(t))
 				if t.Position != nil {
-					h.print(posToString(t.Position), ": ")
+					h.print(" @ ", symbolPath(t))
 				}
-				h.print(symbol(t, false), "\n")
+				h.print("\n")
 			}
 		}
 	}
 }
 
-func (h *TextHandler) summary(findings []*findingSummary) {
-	counters := counters(findings)
-	h.print("\n")
-	if counters.VulnerabilitiesCalled == 0 {
-		h.print("No vulnerabilities found.\n")
-		return
-	}
-	h.print(`Your code is affected by `)
-	h.style(valueStyle, counters.VulnerabilitiesCalled)
-	h.print(choose(counters.VulnerabilitiesCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(` from`)
-	if counters.ModulesCalled > 0 {
-		h.print(` `)
-		h.style(valueStyle, counters.ModulesCalled)
-		h.print(choose(counters.ModulesCalled == 1, ` module`, ` modules`))
+// symbolPath returns a user-friendly path to a symbol.
+func symbolPath(t *govulncheck.Frame) string {
+	// Add module path prefix to symbol paths to be more
+	// explicit to which module the symbols belong to.
+	return t.Module + "/" + posToString(t.Position)
+}
+
+func (h *TextHandler) summary(c summaryCounters) {
+	// print short summary of findings identified at the desired level of scan precision
+	var vulnCount int
+	h.print("Your code ", choose(h.scanLevel.WantSymbols(), "is", "may be"), " affected by ")
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		vulnCount = c.VulnerabilitiesCalled
+	case govulncheck.ScanLevelPackage:
+		vulnCount = c.VulnerabilitiesImported
+	case govulncheck.ScanLevelModule:
+		vulnCount = c.VulnerabilitiesRequired
 	}
-	if counters.StdlibCalled {
-		if counters.ModulesCalled != 0 {
-			h.print(` and`)
+	h.style(valueStyle, vulnCount)
+	h.print(choose(vulnCount == 1, ` vulnerability`, ` vulnerabilities`))
+	if h.scanLevel.WantSymbols() {
+		h.print(choose(c.ModulesCalled > 0 || c.StdlibCalled, ` from `, ``))
+		if c.ModulesCalled > 0 {
+			h.style(valueStyle, c.ModulesCalled)
+			h.print(choose(c.ModulesCalled == 1, ` module`, ` modules`))
+		}
+		if c.StdlibCalled {
+			if c.ModulesCalled != 0 {
+				h.print(` and `)
+			}
+			h.print(`the Go standard library`)
 		}
-		h.print(` the Go standard library`)
 	}
 	h.print(".\n")
+
+	// print summary for vulnerabilities found at other levels of scan precision
+	if other := h.summaryOtherVulns(c); other != "" {
+		h.wrap("", other, 80)
+		h.print("\n")
+	}
+
+	// print suggested flags for more/better info depending on scan level and if in verbose mode
+	if sugg := h.summarySuggestion(); sugg != "" {
+		h.wrap("", sugg, 80)
+		h.print("\n")
+	}
+}
+
+func (h *TextHandler) summaryOtherVulns(c summaryCounters) string {
+	var summary strings.Builder
+	if c.VulnerabilitiesRequired+c.VulnerabilitiesImported == 0 {
+		summary.WriteString("This scan found no other vulnerabilities in ")
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString("packages you import or ")
+		}
+		summary.WriteString("modules you require.")
+	} else {
+		summary.WriteString(choose(h.scanLevel.WantPackages(), "This scan also found ", ""))
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesImported))
+			summary.WriteString(choose(c.VulnerabilitiesImported == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in packages you import and ")
+		}
+		if h.scanLevel.WantPackages() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesRequired))
+			summary.WriteString(choose(c.VulnerabilitiesRequired == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in modules you require")
+			summary.WriteString(choose(h.scanLevel.WantSymbols(), ", but your code doesn't appear to call these vulnerabilities.", "."))
+		}
+	}
+	return summary.String()
+}
+
+func (h *TextHandler) summarySuggestion() string {
+	var sugg strings.Builder
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		if !h.showVerbose {
+			sugg.WriteString("Use " + verboseMessage + ".")
+		}
+	case govulncheck.ScanLevelPackage:
+		sugg.WriteString("Use " + symbolMessage)
+		if !h.showVerbose {
+			sugg.WriteString(" and " + verboseMessage)
+		}
+		sugg.WriteString(".")
+	case govulncheck.ScanLevelModule:
+		sugg.WriteString("Use " + symbolMessage + ".")
+	}
+	return sugg.String()
 }
 
 func (h *TextHandler) style(style style, values ...any) {
@@ -288,10 +503,6 @@ func (h *TextHandler) style(style style, values ...any) {
 		switch style {
 		default:
 			h.print(colorReset)
-		case goStyle:
-			h.print(colorBold)
-		case scannerStyle:
-			h.print(colorBold)
 		case osvCalledStyle:
 			h.print(colorBold, fgRed)
 		case osvImportedStyle:
@@ -347,9 +558,18 @@ func (h *TextHandler) wrap(indent string, s string, maxWidth int) {
 	}
 }
 
-func choose(b bool, yes, no any) any {
+func choose[t any](b bool, yes, no t) t {
 	if b {
 		return yes
 	}
 	return no
 }
+
+func isStdFindings(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if vulncheck.IsStdPackage(f.Trace[0].Package) || f.Trace[0].Module == internal.GoStdModulePath {
+			return true
+		}
+	}
+	return false
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/scan/util.go b/event-processor/vendor/golang.org/x/vuln/internal/scan/util.go
index ce5500bb..0d82ca82 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/scan/util.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/scan/util.go
@@ -6,11 +6,12 @@ package scan
 
 import (
 	"fmt"
+	"os"
+	"os/exec"
+	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	isem "golang.org/x/vuln/internal/semver"
 )
 
 // validateFindings checks that the supplied findings all obey the protocol
@@ -25,48 +26,19 @@ func validateFindings(findings ...*govulncheck.Finding) error {
 		}
 		for _, frame := range f.Trace {
 			if frame.Version != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Version is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Version (%s) is set, Frame.Module must also be", frame.Version)
 			}
 			if frame.Package != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Package is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Package (%s) is set, Frame.Module must also be", frame.Package)
 			}
 			if frame.Function != "" && frame.Package == "" {
-				return fmt.Errorf("invalid finding: if Frame.Function is set, Frame.Package must also be")
+				return fmt.Errorf("invalid finding: if Frame.Function (%s) is set, Frame.Package must also be", frame.Function)
 			}
 		}
 	}
 	return nil
 }
 
-// latestFixed returns the latest fixed version in the list of affected ranges,
-// or the empty string if there are no fixed versions.
-func latestFixed(modulePath string, as []osv.Affected) string {
-	v := ""
-	for _, a := range as {
-		if modulePath != a.Module.Path {
-			continue
-		}
-		fixed := isem.LatestFixedVersion(a.Ranges)
-		// Special case: if there is any affected block for this module
-		// with no fix, the module is considered unfixed.
-		if fixed == "" {
-			return ""
-		}
-		if isem.Less(v, fixed) {
-			v = fixed
-		}
-	}
-	return v
-}
-
-func fixedVersion(modulePath string, affected []osv.Affected) string {
-	fixed := latestFixed(modulePath, affected)
-	if fixed != "" {
-		fixed = "v" + fixed
-	}
-	return fixed
-}
-
 func moduleVersionString(modulePath, version string) string {
 	if version == "" {
 		return ""
@@ -76,3 +48,13 @@ func moduleVersionString(modulePath, version string) string {
 	}
 	return version
 }
+
+func gomodExists(dir string) bool {
+	cmd := exec.Command("go", "env", "GOMOD")
+	cmd.Dir = dir
+	out, err := cmd.Output()
+	output := strings.TrimSpace(string(out))
+	// If module-aware mode is enabled, but there is no go.mod, GOMOD will be os.DevNull
+	// If module-aware mode is disabled, GOMOD will be the empty string.
+	return err == nil && !(output == os.DevNull || output == "")
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/semver/affects.go b/event-processor/vendor/golang.org/x/vuln/internal/semver/affects.go
index 603d8277..03ea6fd7 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/semver/affects.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/semver/affects.go
@@ -21,7 +21,7 @@ func Affects(a []osv.Range, v string) bool {
 			continue
 		}
 		semverRangePresent = true
-		if containsSemver(r, v) {
+		if ContainsSemver(r, v) {
 			return true
 		}
 	}
@@ -32,9 +32,10 @@ func Affects(a []osv.Range, v string) bool {
 	return !semverRangePresent
 }
 
-// containsSemver checks if semver version v is in the
+// ContainsSemver checks if semver version v is in the
 // range encoded by ar. If ar is not a semver range,
-// returns false.
+// returns false. A range is interpreted as a left-closed
+// and right-open interval.
 //
 // Assumes that
 //   - exactly one of Introduced or Fixed fields is set
@@ -42,7 +43,7 @@ func Affects(a []osv.Range, v string) bool {
 //   - beginning of time is encoded with .Introduced="0"
 //   - no-fix is not an event, as opposed to being an
 //     event where Introduced="" and Fixed=""
-func containsSemver(ar osv.Range, v string) bool {
+func ContainsSemver(ar osv.Range, v string) bool {
 	if ar.Type != osv.RangeTypeSemver {
 		return false
 	}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/semver/fixed.go b/event-processor/vendor/golang.org/x/vuln/internal/semver/fixed.go
index 152fc1de..bd29c407 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/semver/fixed.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/semver/fixed.go
@@ -6,7 +6,11 @@ package semver
 
 import "golang.org/x/vuln/internal/osv"
 
-func LatestFixedVersion(ranges []osv.Range) string {
+// NonSupersededFix returns a fixed version from ranges
+// that is not superseded by any other fix or any other
+// introduction of a vulnerability. Returns "" in case
+// there is no such fixed version.
+func NonSupersededFix(ranges []osv.Range) string {
 	var latestFixed string
 	for _, r := range ranges {
 		if r.Type == "SEMVER" {
@@ -16,6 +20,7 @@ func LatestFixedVersion(ranges []osv.Range) string {
 					latestFixed = fixed
 				}
 			}
+
 			// If the vulnerability was re-introduced after the latest fix
 			// we found, there is no latest fix for this range.
 			for _, e := range r.Events {
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/semver/semver.go b/event-processor/vendor/golang.org/x/vuln/internal/semver/semver.go
index fe0f701b..efe1e006 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/semver/semver.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/semver/semver.go
@@ -7,6 +7,7 @@
 package semver
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -93,3 +94,47 @@ func GoTagToSemver(tag string) string {
 	}
 	return version
 }
+
+// This is a modified copy of pkgsite/internal/stlib:TagForVersion
+func SemverToGoTag(v string) string {
+	// Special case: v1.0.0 => go1.
+	if v == "v1.0.0" {
+		return "go1"
+	}
+
+	goVersion := semver.Canonical(v)
+	prerelease := semver.Prerelease(goVersion)
+	versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)
+	patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".")
+	if patch == "0" && (semver.Compare(v, "v1.21.0") < 0 || prerelease != "") {
+		// Starting with go1.21.0, the first patch version includes .0.
+		// Prereleases do not include .0 (we don't do prereleases for other patch releases).
+		versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0")
+	}
+	goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v"))
+	if prerelease != "" {
+		i := finalDigitsIndex(prerelease)
+		if i >= 1 {
+			// Remove the dot.
+			prerelease = prerelease[:i-1] + prerelease[i:]
+		}
+		goVersion += prerelease
+	}
+	return goVersion
+}
+
+// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.
+// If s doesn't end in digits, it returns -1.
+func finalDigitsIndex(s string) int {
+	// Assume ASCII (since the semver package does anyway).
+	var i int
+	for i = len(s) - 1; i >= 0; i-- {
+		if s[i] < '0' || s[i] > '9' {
+			break
+		}
+	}
+	if i == len(s)-1 {
+		return -1
+	}
+	return i + 1
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/traces/traces.go b/event-processor/vendor/golang.org/x/vuln/internal/traces/traces.go
new file mode 100644
index 00000000..e413ae7d
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/traces/traces.go
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package traces
+
+import (
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// Compact returns a summarization of finding.Trace. The first
+// returned element is the vulnerable symbol and the last element
+// is the exit point of the user module. There can also be two
+// elements in between, if applicable, which are the two elements
+// preceding the user module exit point.
+func Compact(finding *govulncheck.Finding) []*govulncheck.Frame {
+	if len(finding.Trace) < 1 {
+		return nil
+	}
+	iTop := len(finding.Trace) - 1
+	topModule := finding.Trace[iTop].Module
+	// search for the exit point of the top module
+	for i, frame := range finding.Trace {
+		if frame.Module == topModule {
+			iTop = i
+			break
+		}
+	}
+
+	if iTop == 0 {
+		// all in one module, reset to the end
+		iTop = len(finding.Trace) - 1
+	}
+
+	compact := []*govulncheck.Frame{finding.Trace[0]}
+	if iTop > 1 {
+		if iTop > 2 {
+			compact = append(compact, finding.Trace[iTop-2])
+		}
+		compact = append(compact, finding.Trace[iTop-1])
+	}
+	if iTop > 0 {
+		compact = append(compact, finding.Trace[iTop])
+	}
+	return compact
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/binary.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
index a35a3a0a..d78af3ff 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
@@ -2,120 +2,184 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package vulncheck
 
 import (
 	"context"
 	"fmt"
-	"io"
-	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	"golang.org/x/vuln/internal/vulncheck/internal/buildinfo"
+	"golang.org/x/vuln/internal/semver"
 )
 
-// Binary detects presence of vulnerable symbols in exe.
-// The Calls, Imports, and Requires fields on Result will be empty.
-func Binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *Result, err error) {
-	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(exe)
+// Bin is an abstraction of Go binary containing
+// minimal information needed by govulncheck.
+type Bin struct {
+	// Path of the main package.
+	Path string `json:"path,omitempty"`
+	// Main module. When present, it never has empty information.
+	Main       *packages.Module   `json:"main,omitempty"`
+	Modules    []*packages.Module `json:"modules,omitempty"`
+	PkgSymbols []buildinfo.Symbol `json:"pkgSymbols,omitempty"`
+	GoVersion  string             `json:"goVersion,omitempty"`
+	GOOS       string             `json:"goos,omitempty"`
+	GOARCH     string             `json:"goarch,omitempty"`
+}
+
+// Binary detects presence of vulnerable symbols in bin and
+// emits findings to handler.
+func Binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) error {
+	vr, err := binary(ctx, handler, bin, cfg, client)
 	if err != nil {
-		return nil, fmt.Errorf("could not parse provided binary: %v", err)
+		return err
+	}
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, binaryCallstacks(vr))
+	}
+	return nil
+}
+
+// binary detects presence of vulnerable symbols in bin.
+// It does not compute call graphs so the corresponding
+// info in Result will be empty.
+func binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) (*Result, error) {
+	graph := NewPackageGraph(bin.GoVersion)
+	mods := append(bin.Modules, graph.GetModule(internal.GoStdModulePath))
+
+	if bin.Main != nil {
+		mods = append(mods, bin.Main)
 	}
 
-	graph := NewPackageGraph(bi.GoVersion)
 	graph.AddModules(mods...)
-	mods = append(mods, graph.GetModule(internal.GoStdModulePath))
+
+	if err := handler.SBOM(bin.SBOM()); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
+	}
 
 	mv, err := FetchVulnerabilities(ctx, client, mods)
 	if err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
 
-	goos := findSetting("GOOS", bi)
-	goarch := findSetting("GOARCH", bi)
-	if goos == "" || goarch == "" {
-		fmt.Printf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", goos, goarch)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingBinVulnsMessage}); err != nil {
+		return nil, err
+	}
+
+	// Emit warning message for ancient Go binaries, defined as binaries
+	// built with Go version without support for debug.BuildInfo (< go1.18).
+	if semver.Valid(bin.GoVersion) && semver.Less(bin.GoVersion, "go1.18") {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: binary built with Go version %s, only standard library vulnerabilities will be checked", bin.GoVersion)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+
+	if bin.GOOS == "" || bin.GOARCH == "" {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", bin.GOOS, bin.GOARCH)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+	affVulns := affectingVulnerabilities(mv, bin.GOOS, bin.GOARCH)
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
 
-	modVulns = modVulns.filter(goos, goarch)
-	result := &Result{}
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
+	}
 
-	if packageSymbols == nil {
+	// Group symbols per package to avoid querying affVulns all over again.
+	var pkgSymbols map[string][]string
+	if len(bin.PkgSymbols) == 0 {
 		// The binary exe is stripped. We currently cannot detect inlined
 		// symbols for stripped binaries (see #57764), so we report
 		// vulnerabilities at the go.mod-level precision.
-		addRequiresOnlyVulns(result, graph, modVulns)
+		pkgSymbols = allKnownVulnerableSymbols(affVulns)
 	} else {
-		for pkg, symbols := range packageSymbols {
-			if !cfg.ScanLevel.WantSymbols() {
-				addImportsOnlyVulns(result, graph, pkg, symbols, modVulns)
-			} else {
-				addSymbolVulns(result, graph, pkg, symbols, modVulns)
-			}
-		}
+		pkgSymbols = packagesAndSymbols(bin)
 	}
-	return result, nil
-}
 
-// addImportsOnlyVulns adds Vuln entries to result in imports only mode, i.e., for each vulnerable symbol
-// of pkg.
-func addImportsOnlyVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, osv := range modVulns.vulnsForPackage(pkg) {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg {
-					continue
-				}
-				syms := p.Symbols
-				if len(syms) == 0 {
-					// If every symbol of pkg is vulnerable, we would ideally
-					// compute every symbol mentioned in the pkg and then add
-					// Vuln entry for it, just as we do in Source. However,
-					// we don't have code of pkg here so we have to do best
-					// we can, which is the symbols of pkg actually appearing
-					// in the binary.
-					syms = symbols
-				}
+	impVulns := binImportedVulnPackages(graph, pkgSymbols, affVulns)
+	// Emit information on imported vulnerable packages now to
+	// mimic behavior of source.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
+	}
 
-				for _, symbol := range syms {
-					addVuln(result, graph, osv, symbol, pkg)
-				}
-			}
+	// Return result immediately if not in symbol mode to mimic the
+	// behavior of source.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
+
+	symVulns := binVulnSymbols(graph, pkgSymbols, affVulns)
+	return &Result{Vulns: symVulns}, nil
+}
+
+func packagesAndSymbols(bin *Bin) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, sym := range bin.PkgSymbols {
+		// If the name of the package is main, we need to expand
+		// it to its full path as that is what vuln db uses.
+		if sym.Pkg == "main" && bin.Path != "" {
+			pkgSymbols[bin.Path] = append(pkgSymbols[bin.Path], sym.Name)
+		} else {
+			pkgSymbols[sym.Pkg] = append(pkgSymbols[sym.Pkg], sym.Name)
 		}
 	}
+	return pkgSymbols
 }
 
-// addSymbolVulns adds Vuln entries to result for every symbol of pkg in the binary that is vulnerable.
-func addSymbolVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, symbol := range symbols {
-		for _, osv := range modVulns.vulnsForSymbol(pkg, symbol) {
-			addVuln(result, graph, osv, symbol, pkg)
+func binImportedVulnPackages(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg := range pkgSymbols {
+		for _, osv := range affVulns.ForPackage(internal.UnknownModulePath, pkg) {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg),
+			}
+			vulns = append(vulns, vuln)
 		}
 	}
+	return vulns
 }
 
-// findSetting returns value of setting from bi if present.
-// Otherwise, returns "".
-func findSetting(setting string, bi *debug.BuildInfo) string {
-	for _, s := range bi.Settings {
-		if s.Key == setting {
-			return s.Value
+func binVulnSymbols(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg, symbols := range pkgSymbols {
+		for _, symbol := range symbols {
+			for _, osv := range affVulns.ForSymbol(internal.UnknownModulePath, pkg, symbol) {
+				vuln := &Vuln{
+					OSV:     osv,
+					Symbol:  symbol,
+					Package: graph.GetPackage(pkg),
+				}
+				vulns = append(vulns, vuln)
+			}
 		}
 	}
-	return ""
+	return vulns
 }
 
-// addRequiresOnlyVulns adds to result all vulnerabilities in modVulns.
-// Used when the binary under analysis is stripped.
-func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVulnerabilities) {
-	for _, mv := range modVulns {
+// allKnownVulnerableSymbols returns all known vulnerable symbols for packages in graph.
+// If all symbols of a package are vulnerable, that is modeled as a wild car symbol "/*".
+func allKnownVulnerableSymbols(affVulns affectingVulns) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, mv := range affVulns {
 		for _, osv := range mv.Vulns {
 			for _, affected := range osv.Affected {
 				for _, p := range affected.EcosystemSpecific.Packages {
@@ -134,19 +198,40 @@ func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVu
 						syms = []string{fmt.Sprintf("%s/*", p.Path)}
 					}
 
-					for _, symbol := range syms {
-						addVuln(result, graph, osv, symbol, p.Path)
-					}
+					pkgSymbols[p.Path] = append(pkgSymbols[p.Path], syms...)
 				}
 			}
 		}
 	}
+	return pkgSymbols
 }
 
-func addVuln(result *Result, graph *PackageGraph, osv *osv.Entry, symbol string, pkgPath string) {
-	result.Vulns = append(result.Vulns, &Vuln{
-		OSV:        osv,
-		Symbol:     symbol,
-		ImportSink: graph.GetPackage(pkgPath),
+func (bin *Bin) SBOM() (sbom *govulncheck.SBOM) {
+	sbom = &govulncheck.SBOM{}
+	if bin.Main != nil {
+		sbom.Roots = []string{bin.Main.Path}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    bin.Main.Path,
+			Version: bin.Main.Version,
+		})
+	}
+
+	sbom.GoVersion = bin.GoVersion
+	for _, mod := range bin.Modules {
+		if mod.Replace != nil {
+			mod = mod.Replace
+		}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		})
+	}
+
+	// add stdlib to mirror source mode output
+	sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+		Path:    internal.GoStdModulePath,
+		Version: bin.GoVersion,
 	})
+
+	return sbom
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/doc.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
index 3f19e299..e56cdfbc 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
@@ -24,8 +24,7 @@ detection in Go source code and binaries, respectively.
 
 [Source] accepts a list of [Package] objects, which
 are a trimmed version of [golang.org/x/tools/go/packages.Package] objects to
-reduce memory consumption. [Binary] accepts a path to a Go binary file that
-must have been compiled with Go 1.18 or greater.
+reduce memory consumption. [Binary] accepts a path to a Go binary file.
 
 Both [Source] and [Binary] require information about known
 vulnerabilities in the form of a vulnerability database,
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/emit.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
new file mode 100644
index 00000000..fc9b2d7a
--- /dev/null
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
@@ -0,0 +1,198 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vulncheck
+
+import (
+	"go/token"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// emitOSVs emits all OSV vuln entries in modVulns to handler.
+func emitOSVs(handler govulncheck.Handler, modVulns []*ModVulns) error {
+	for _, mv := range modVulns {
+		for _, v := range mv.Vulns {
+			if err := handler.OSV(v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitModuleFindings emits module-level findings for vulnerabilities in modVulns.
+func emitModuleFindings(handler govulncheck.Handler, affVulns affectingVulns) error {
+	for _, vuln := range affVulns {
+		for _, osv := range vuln.Vulns {
+			if err := handler.Finding(&govulncheck.Finding{
+				OSV:          osv.ID,
+				FixedVersion: FixedVersion(modPath(vuln.Module), modVersion(vuln.Module), osv.Affected),
+				Trace:        []*govulncheck.Frame{frameFromModule(vuln.Module)},
+			}); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitPackageFinding emits package-level findings fod vulnerabilities in vulns.
+func emitPackageFindings(handler govulncheck.Handler, vulns []*Vuln) error {
+	for _, v := range vulns {
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          v.OSV.ID,
+			FixedVersion: FixedVersion(modPath(v.Package.Module), modVersion(v.Package.Module), v.OSV.Affected),
+			Trace:        []*govulncheck.Frame{frameFromPackage(v.Package)},
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// emitCallFindings emits call-level findings for vulnerabilities
+// that have a call stack in callstacks.
+func emitCallFindings(handler govulncheck.Handler, callstacks map[*Vuln]CallStack) error {
+	var vulns []*Vuln
+	for v := range callstacks {
+		vulns = append(vulns, v)
+	}
+
+	for _, vuln := range vulns {
+		stack := callstacks[vuln]
+		if stack == nil {
+			continue
+		}
+		fixed := FixedVersion(modPath(vuln.Package.Module), modVersion(vuln.Package.Module), vuln.OSV.Affected)
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          vuln.OSV.ID,
+			FixedVersion: fixed,
+			Trace:        traceFromEntries(stack),
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// traceFromEntries creates a sequence of
+// frames from vcs. Position of a Frame is the
+// call position of the corresponding stack entry.
+func traceFromEntries(vcs CallStack) []*govulncheck.Frame {
+	var frames []*govulncheck.Frame
+	for i := len(vcs) - 1; i >= 0; i-- {
+		e := vcs[i]
+		fr := frameFromPackage(e.Function.Package)
+		fr.Function = e.Function.Name
+		fr.Receiver = e.Function.Receiver()
+		isSink := i == (len(vcs) - 1)
+		fr.Position = posFromStackEntry(e, isSink)
+		frames = append(frames, fr)
+	}
+	return frames
+}
+
+func posFromStackEntry(e StackEntry, sink bool) *govulncheck.Position {
+	var p *token.Position
+	var f *FuncNode
+	if sink && e.Function != nil && e.Function.Pos != nil {
+		// For sinks, i.e., vulns we take the position
+		// of the symbol.
+		p = e.Function.Pos
+		f = e.Function
+	} else if e.Call != nil && e.Call.Pos != nil {
+		// Otherwise, we take the position of
+		// the call statement.
+		p = e.Call.Pos
+		f = e.Call.Parent
+	}
+
+	if p == nil {
+		return nil
+	}
+	return &govulncheck.Position{
+		Filename: pathRelativeToMod(p.Filename, f),
+		Offset:   p.Offset,
+		Line:     p.Line,
+		Column:   p.Column,
+	}
+}
+
+// pathRelativeToMod computes a version of path
+// relative to the module of f. If it does not
+// have all the necessary information, returns
+// an empty string.
+//
+// The returned paths always use slash as separator
+// so they can work across different platforms.
+func pathRelativeToMod(path string, f *FuncNode) string {
+	if path == "" || f == nil || f.Package == nil { // sanity
+		return ""
+	}
+
+	mod := f.Package.Module
+	if mod.Replace != nil {
+		mod = mod.Replace // for replace directive
+	}
+
+	modDir := modDirWithVendor(mod.Dir, path, mod.Path)
+	p, err := filepath.Rel(modDir, path)
+	if err != nil {
+		return ""
+	}
+	// make sure paths are portable.
+	return filepath.ToSlash(p)
+}
+
+// modDirWithVendor returns modDir if modDir is not empty.
+// Otherwise, the module might be located in the vendor
+// directory. This function attempts to reconstruct the
+// vendored module directory from path and module. It
+// returns an empty string if reconstruction fails.
+func modDirWithVendor(modDir, path, module string) string {
+	if modDir != "" {
+		return modDir
+	}
+
+	sep := string(os.PathSeparator)
+	vendor := sep + "vendor" + sep
+	vendorIndex := strings.Index(path, vendor)
+	if vendorIndex == -1 {
+		return ""
+	}
+	return filepath.Join(path[:vendorIndex], "vendor", filepath.FromSlash(module))
+}
+
+func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
+	fr := &govulncheck.Frame{}
+	if pkg != nil {
+		fr.Module = pkg.Module.Path
+		fr.Version = pkg.Module.Version
+		fr.Package = pkg.PkgPath
+	}
+	if pkg.Module.Replace != nil {
+		fr.Module = pkg.Module.Replace.Path
+		fr.Version = pkg.Module.Replace.Version
+	}
+	return fr
+}
+
+func frameFromModule(mod *packages.Module) *govulncheck.Frame {
+	fr := &govulncheck.Frame{
+		Module:  mod.Path,
+		Version: mod.Version,
+	}
+
+	if mod.Replace != nil {
+		fr.Module = mod.Replace.Path
+		fr.Version = mod.Replace.Version
+	}
+
+	return fr
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/entries.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
index 834d5901..3d46f6ca 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
@@ -10,6 +10,12 @@ import (
 	"golang.org/x/tools/go/ssa"
 )
 
+// entryPoints returns functions of topPackages considered entry
+// points of govulncheck analysis: main, inits, and exported methods
+// and functions.
+//
+// TODO(https://go.dev/issue/57221): currently, entry functions
+// that are generics are not considered an entry point.
 func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
 	var entries []*ssa.Function
 	for _, pkg := range topPackages {
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
index ef0c7ca9..700a7f99 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
@@ -6,6 +6,7 @@ package vulncheck
 
 import (
 	"context"
+	"fmt"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal/client"
@@ -25,7 +26,7 @@ func FetchVulnerabilities(ctx context.Context, c *client.Client, modules []*pack
 	}
 	resps, err := c.ByModules(ctx, mreqs)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("fetching vulnerabilities: %v", err)
 	}
 	var mv []*ModVulns
 	for i, resp := range resps {
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
deleted file mode 100644
index 1bdd38c7..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// This file adds to buildinfo the functionality for extracting the PCLN table.
-
-import (
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-)
-
-// ErrNoSymbols represents non-existence of symbol
-// table in binaries supported by buildinfo.
-var ErrNoSymbols = errors.New("no symbol section")
-
-// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
-func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		if errors.Is(err, elf.ErrNoSymbols) {
-			return 0, 0, nil, ErrNoSymbols
-		}
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	prog := x.progContaining(sym.Value)
-	if prog == nil {
-		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
-}
-
-func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		syms, err := x.f.Symbols()
-		if err != nil {
-			x.symbolsErr = err
-			return
-		}
-		x.symbols = make(map[string]*elf.Symbol, len(syms))
-		for _, s := range syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-func (x *elfExe) progContaining(addr uint64) *elf.Prog {
-	for _, p := range x.f.Progs {
-		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
-			return p
-		}
-	}
-	return nil
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
-	var offset uint64
-	text := x.f.Section(".text")
-	if text != nil {
-		offset = text.Offset
-	}
-	pclntab := x.f.Section(".gopclntab")
-	if pclntab == nil {
-		// Addition: this code is added to support some form of stripping.
-		pclntab = x.f.Section(".data.rel.ro.gopclntab")
-		if pclntab == nil {
-			pclntab = x.f.Section(".data.rel.ro")
-			if pclntab == nil {
-				return nil, 0
-			}
-			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
-			// its own section header. We can search for for the start by looking for the four
-			// byte magic and the go magic.
-			b, err := pclntab.Data()
-			if err != nil {
-				return nil, 0
-			}
-			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
-			// actually correct. During testing it worked, but that may be because I got lucky
-			// with the binary I was using, and we need to do four byte jumps to exhaustively
-			// search the section?
-			for i := 0; i < len(b); i += 16 {
-				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
-					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
-					(b[i+7] == 4 || b[i+7] == 8) {
-					// Also check for the go magic
-					leMagic := binary.LittleEndian.Uint32(b[i:])
-					beMagic := binary.BigEndian.Uint32(b[i:])
-					switch {
-					case leMagic == go12magic:
-						fallthrough
-					case beMagic == go12magic:
-						fallthrough
-					case leMagic == go116magic:
-						fallthrough
-					case beMagic == go116magic:
-						return b[i:], offset
-					}
-				}
-			}
-		}
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, offset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
-func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		return 0, 0, nil, err
-	}
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	sect := x.f.Sections[sym.SectionNumber-1]
-	// In PE, the symbol's value is the offset from the section start.
-	return uint64(sym.Value), 0, sect.ReaderAt, nil
-}
-
-func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
-		if len(x.f.Symbols) == 0 {
-			x.symbolsErr = ErrNoSymbols
-			return
-		}
-		for _, s := range x.f.Symbols {
-			x.symbols[s.Name] = s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
-// Assumes that the underlying symbol table exists, otherwise
-// it might panic.
-func (x *peExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	for _, section := range x.f.Sections {
-		if section.Name == ".text" {
-			textOffset = uint64(section.Offset)
-			break
-		}
-	}
-
-	var start, end int64
-	var section int
-	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
-		start = int64(s.Value)
-		section = int(s.SectionNumber - 1)
-	}
-	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
-		end = int64(s.Value)
-	}
-	if start == 0 || end == 0 {
-		return nil, 0
-	}
-	offset := int64(x.f.Sections[section].Offset) + start
-	size := end - start
-
-	pclntab := make([]byte, size)
-	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
-		return nil, 0
-	}
-	return pclntab, textOffset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
-func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym := x.lookupSymbol(name)
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	seg := x.segmentContaining(sym.Value)
-	if seg == nil {
-		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, seg.Addr, seg.ReaderAt, nil
-}
-
-func (x *machoExe) lookupSymbol(name string) *macho.Symbol {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
-		for _, s := range x.f.Symtab.Syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	return x.symbols[name]
-}
-
-func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
-			return seg
-		}
-	}
-	return nil
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	text := x.f.Section("__text")
-	if text != nil {
-		textOffset = uint64(text.Offset)
-	}
-	pclntab := x.f.Section("__gopclntab")
-	if pclntab == nil {
-		return nil, 0
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, textOffset
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
deleted file mode 100644
index 9790cfa9..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
-	"debug/buildinfo"
-	"errors"
-	"fmt"
-	"io"
-	"net/url"
-	"runtime/debug"
-	"sort"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal/vulncheck/internal/gosym"
-)
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
-	packagesModules := make([]*packages.Module, len(debugModules))
-	for i, mod := range debugModules {
-		packagesModules[i] = &packages.Module{
-			Path:    mod.Path,
-			Version: mod.Version,
-		}
-		if mod.Replace != nil {
-			packagesModules[i].Replace = &packages.Module{
-				Path:    mod.Replace.Path,
-				Version: mod.Replace.Version,
-			}
-		}
-	}
-	return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts symbols, packages, modules from
-// bin as well as bin's metadata.
-//
-// If the symbol table is not available, such as in the case of stripped
-// binaries, returns module and binary info but without the symbol info.
-func ExtractPackagesAndSymbols(bin io.ReaderAt) ([]*packages.Module, map[string][]string, *debug.BuildInfo, error) {
-	bi, err := buildinfo.Read(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	funcSymName := gosym.FuncSymName(bi.GoVersion)
-	if funcSymName == "" {
-		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
-	}
-
-	x, err := openExe(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	value, base, r, err := x.SymbolInfo(funcSymName)
-	if err != nil {
-		if errors.Is(err, ErrNoSymbols) {
-			// bin is stripped, so return just module info and metadata.
-			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
-		}
-		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
-	}
-
-	pclntab, textOffset := x.PCLNTab()
-	if pclntab == nil {
-		// TODO(https://go.dev/issue/59731): if we have build information, but
-		// not PCLN table, we should be able to fall back to much higher
-		// granularity vulnerability checking.
-		return nil, nil, nil, errors.New("unable to load the PCLN table")
-	}
-	lineTab := gosym.NewLineTable(pclntab, textOffset)
-	if lineTab == nil {
-		return nil, nil, nil, errors.New("invalid line table")
-	}
-	tab, err := gosym.NewTable(nil, lineTab)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	type pkgSymbol struct {
-		pkg string
-		sym string
-	}
-	pkgSyms := make(map[pkgSymbol]bool)
-	for _, f := range tab.Funcs {
-		if f.Func == nil {
-			continue
-		}
-		pkgName, symName, err := parseName(f.Func.Sym)
-		if err != nil {
-			return nil, nil, nil, err
-		}
-		pkgSyms[pkgSymbol{pkgName, symName}] = true
-
-		// Collect symbols that were inlined in f.
-		it, err := lineTab.InlineTree(&f, value, base, r)
-		if err != nil {
-			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
-		}
-		for _, ic := range it {
-			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
-			if err != nil {
-				return nil, nil, nil, err
-			}
-			pkgSyms[pkgSymbol{pkgName, symName}] = true
-		}
-	}
-
-	packageSymbols := make(map[string][]string)
-	for p := range pkgSyms {
-		packageSymbols[p.pkg] = append(packageSymbols[p.pkg], p.sym)
-	}
-	// Sort symbols per pkg for deterministic results.
-	for _, syms := range packageSymbols {
-		sort.Strings(syms)
-	}
-
-	return debugModulesToPackagesModules(bi.Deps), packageSymbols, bi, nil
-}
-
-func parseName(s *gosym.Sym) (pkg, sym string, err error) {
-	symName := s.BaseName()
-	if r := s.ReceiverName(); r != "" {
-		if strings.HasPrefix(r, "(*") {
-			r = strings.Trim(r, "(*)")
-		}
-		symName = fmt.Sprintf("%s.%s", r, symName)
-	}
-
-	pkgName := s.PackageName()
-	if pkgName != "" {
-		pkgName, err = url.PathUnescape(pkgName)
-		if err != nil {
-			return "", "", err
-		}
-	}
-	return pkgName, symName, nil
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
deleted file mode 100644
index 1be795ee..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
-
-import (
-	"bytes"
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"fmt"
-	"sync"
-
-	// "internal/xcoff"
-	"io"
-)
-
-// Addition: modification of rawBuildInfo in the original file.
-// openExe returns reader r as an exe.
-func openExe(r io.ReaderAt) (exe, error) {
-	data := make([]byte, 16)
-	if _, err := r.ReadAt(data, 0); err != nil {
-		return nil, err
-	}
-	if bytes.HasPrefix(data, []byte("\x7FELF")) {
-		e, err := elf.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &elfExe{f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("MZ")) {
-		e, err := pe.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &peExe{r: r, f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
-		e, err := macho.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &machoExe{f: e}, nil
-	}
-	return nil, fmt.Errorf("unrecognized executable format")
-}
-
-type exe interface {
-	// ReadData reads and returns up to size byte starting at virtual address addr.
-	ReadData(addr, size uint64) ([]byte, error)
-
-	// DataStart returns the virtual address of the segment or section that
-	// should contain build information. This is either a specially named section
-	// or the first writable non-zero data segment.
-	DataStart() uint64
-
-	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
-
-	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
-	f *elf.File
-
-	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once              // Addition: for computing symbols
-	symbolsErr  error                  // Addition: error for computing symbols
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, prog := range x.f.Progs {
-		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
-			n := prog.Vaddr + prog.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *elfExe) DataStart() uint64 {
-	for _, s := range x.f.Sections {
-		if s.Name == ".go.buildinfo" {
-			return s.Addr
-		}
-	}
-	for _, p := range x.f.Progs {
-		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
-			return p.Vaddr
-		}
-	}
-	return 0
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
-	r io.ReaderAt
-	f *pe.File
-
-	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once             // Addition: for computing symbols
-	symbolsErr  error                 // Addition: error for computing symbols
-}
-
-func (x *peExe) imageBase() uint64 {
-	switch oh := x.f.OptionalHeader.(type) {
-	case *pe.OptionalHeader32:
-		return uint64(oh.ImageBase)
-	case *pe.OptionalHeader64:
-		return oh.ImageBase
-	}
-	return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
-	addr -= x.imageBase()
-	for _, sect := range x.f.Sections {
-		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-			n := uint64(sect.VirtualAddress+sect.Size) - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *peExe) DataStart() uint64 {
-	// Assume data is first writable section.
-	const (
-		IMAGE_SCN_CNT_CODE               = 0x00000020
-		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-		IMAGE_SCN_MEM_READ               = 0x40000000
-		IMAGE_SCN_MEM_WRITE              = 0x80000000
-		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-	)
-	for _, sect := range x.f.Sections {
-		if sect.VirtualAddress != 0 && sect.Size != 0 &&
-			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
-			return uint64(sect.VirtualAddress) + x.imageBase()
-		}
-	}
-	return 0
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
-	f *macho.File
-
-	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once                // Addition: for computing symbols
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if !ok {
-			continue
-		}
-		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
-			if seg.Name == "__PAGEZERO" {
-				continue
-			}
-			n := seg.Addr + seg.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *machoExe) DataStart() uint64 {
-	// Look for section named "__go_buildinfo".
-	for _, sec := range x.f.Sections {
-		if sec.Name == "__go_buildinfo" {
-			return sec.Addr
-		}
-	}
-	// Try the first non-empty writable segment.
-	const RW = 3
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
-			return seg.Addr
-		}
-	}
-	return 0
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
deleted file mode 100644
index f608c151..00000000
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gosym
-
-import (
-	"encoding/binary"
-	"io"
-	"strings"
-
-	sv "golang.org/x/mod/semver"
-	"golang.org/x/vuln/internal/semver"
-)
-
-const (
-	funcSymNameGo119Lower string = "go.func.*"
-	funcSymNameGo120      string = "go:func.*"
-)
-
-// FuncSymName returns symbol name for Go functions
-// used in binaries based on Go version. Supported
-// Go versions are 1.18, 1.19, and 1.20. Otherwise,
-// returns an empty string.
-func FuncSymName(goVersion string) string {
-	// Support devel goX.Y...
-	v := strings.TrimPrefix(goVersion, "devel ")
-	v = semver.GoTagToSemver(v)
-	mm := sv.MajorMinor(v)
-	if mm == "v1.18" || mm == "v1.19" {
-		return funcSymNameGo119Lower
-	} else if mm == "v1.20" {
-		return funcSymNameGo120
-	} else if v == "" && strings.HasPrefix(goVersion, "devel") {
-		// We currently don't have a direct way of mapping
-		// Go versions of the form devel  to semver,
-		// so we map it to the most recent supported major
-		// Go version, which is currently go1.20.
-		return funcSymNameGo120
-	}
-	return ""
-}
-
-// Additions to the original package from cmd/internal/objabi/funcdata.go
-const (
-	pcdata_InlTreeIndex = 2
-	funcdata_InlTree    = 3
-)
-
-// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
-// goFuncValue is the value of the gosym.FuncSymName symbol.
-// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
-// progReader is a ReaderAt positioned at the start of that region.
-func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
-	if f.inlineTreeCount == 0 {
-		return nil, nil
-	}
-	if f.inlineTreeOffset == ^uint32(0) {
-		return nil, nil
-	}
-	var offset int64
-	if t.version >= ver118 {
-		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
-	} else {
-		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
-	}
-
-	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
-	var ics []InlinedCall
-	for i := 0; i < f.inlineTreeCount; i++ {
-		if t.version >= ver120 {
-			var ric rawInlinedCall120
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.NameOff)),
-				ParentPC: ric.ParentPC,
-			})
-		} else {
-			var ric rawInlinedCall112
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.Func_)),
-				ParentPC: ric.ParentPC,
-			})
-		}
-	}
-	return ics, nil
-}
-
-// InlinedCall describes a call to an inlined function.
-type InlinedCall struct {
-	FuncID   uint8  // type of the called function
-	Name     string // name of called function
-	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall112 struct {
-	Parent   int16 // index of parent in the inltree, or < 0
-	FuncID   uint8 // type of the called function
-	_        byte
-	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
-	Line     int32 // line number of the call site
-	Func_    int32 // offset into pclntab for name of called function
-	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.20. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall120 struct {
-	FuncID    uint8 // type of the called function
-	_         [3]byte
-	NameOff   int32 // offset into pclntab for name of called function
-	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
-	StartLine int32 // line number of start of function (func keyword/TEXT directive)
-}
-
-func (f funcData) npcdata() uint32 { return f.field(7) }
-func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
-	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
-}
-
-func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.nfuncdata(numFuncFields) {
-		return ^uint32(0)
-	}
-	var off uint32
-	if f.t.version >= ver118 {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4 + // skip pcdata
-			uint32(i)*4 // index of i'th FUNCDATA
-	} else {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4
-		off += uint32(i) * f.t.ptrsize
-	}
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-func (f funcData) fieldOffset(n uint32) uint32 {
-	// In Go 1.18, the first field of _func changed
-	// from a uintptr entry PC to a uint32 entry offset.
-	sz0 := f.t.ptrsize
-	if f.t.version >= ver118 {
-		sz0 = 4
-	}
-	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
-}
-
-func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.npcdata() {
-		return ^uint32(0)
-	}
-	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
-		uint32(i)*4 // index of i'th PCDATA
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-// maxInlineTreeIndexValue returns the maximum value of the inline tree index
-// pc-value table in info. This is the only way to determine how many
-// IndexedCalls are in an inline tree, since the data of the tree itself is not
-// delimited in any way.
-func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
-	if info.npcdata() <= pcdata_InlTreeIndex {
-		return -1
-	}
-	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
-	p := t.pctab[off:]
-	val := int32(-1)
-	max := int32(-1)
-	var pc uint64
-	for t.step(&p, &pc, &val, pc == 0) {
-		if val > max {
-			max = val
-		}
-	}
-	return int(max)
-}
-
-type inlTree struct {
-	inlineTreeOffset uint32 // offset from go.func.* symbol
-	inlineTreeCount  int    // number of entries in inline tree
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/packages.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
index 124a9a50..484e5494 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
@@ -6,18 +6,25 @@ package vulncheck
 
 import (
 	"fmt"
+	"os/exec"
+	"slices"
 	"strings"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/semver"
 )
 
 // PackageGraph holds a complete module and package graph.
-// Its primary purpose is to allow fast access to the nodes by path.
+// Its primary purpose is to allow fast access to the nodes
+// by path and make sure all(stdlib)  packages have a module.
 type PackageGraph struct {
-	modules  map[string]*packages.Module
-	packages map[string]*packages.Package
+	// topPkgs are top-level packages specified by the user.
+	// Empty in binary mode.
+	topPkgs  []*packages.Package
+	modules  map[string]*packages.Module  // all modules (even replacing ones)
+	packages map[string]*packages.Package // all packages (even dependencies)
 }
 
 func NewPackageGraph(goVersion string) *PackageGraph {
@@ -25,15 +32,83 @@ func NewPackageGraph(goVersion string) *PackageGraph {
 		modules:  map[string]*packages.Module{},
 		packages: map[string]*packages.Package{},
 	}
-	graph.AddModules(&packages.Module{
+
+	goRoot := ""
+	if out, err := exec.Command("go", "env", "GOROOT").Output(); err == nil {
+		goRoot = strings.TrimSpace(string(out))
+	}
+	stdlibModule := &packages.Module{
 		Path:    internal.GoStdModulePath,
 		Version: semver.GoTagToSemver(goVersion),
-	})
+		Dir:     goRoot,
+	}
+	graph.AddModules(stdlibModule)
 	return graph
 }
 
+func (g *PackageGraph) TopPkgs() []*packages.Package {
+	return g.topPkgs
+}
+
+// DepPkgs returns the number of packages that graph.TopPkgs()
+// strictly depend on. This does not include topPkgs even if
+// they are dependency of each other.
+func (g *PackageGraph) DepPkgs() []*packages.Package {
+	topPkgs := g.TopPkgs()
+	tops := make(map[string]bool)
+	depPkgs := make(map[string]*packages.Package)
+
+	for _, t := range topPkgs {
+		tops[t.PkgPath] = true
+	}
+
+	var visit func(*packages.Package, bool)
+	visit = func(p *packages.Package, top bool) {
+		path := p.PkgPath
+		if _, ok := depPkgs[path]; ok {
+			return
+		}
+		if tops[path] && !top {
+			// A top package that is a dependency
+			// will not be in depPkgs, so we skip
+			// reiterating on it here.
+			return
+		}
+
+		// We don't count a top-level package as
+		// a dependency even when they are used
+		// as a dependent package.
+		if !tops[path] {
+			depPkgs[path] = p
+		}
+
+		for _, d := range p.Imports {
+			visit(d, false)
+		}
+	}
+
+	for _, t := range topPkgs {
+		visit(t, true)
+	}
+
+	var deps []*packages.Package
+	for _, d := range depPkgs {
+		deps = append(deps, g.GetPackage(d.PkgPath))
+	}
+	return deps
+}
+
+func (g *PackageGraph) Modules() []*packages.Module {
+	var mods []*packages.Module
+	for _, m := range g.modules {
+		mods = append(mods, m)
+	}
+	return mods
+}
+
 // AddModules adds the modules and any replace modules provided.
-// It will ignore modules that have duplicate paths to ones the graph already holds.
+// It will ignore modules that have duplicate paths to ones the
+// graph already holds.
 func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	for _, mod := range mods {
 		if _, found := g.modules[mod.Path]; found {
@@ -47,7 +122,8 @@ func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	}
 }
 
-// .
+// GetModule gets module at path if one exists. Otherwise,
+// it creates a module and returns it.
 func (g *PackageGraph) GetModule(path string) *packages.Module {
 	if mod, ok := g.modules[path]; ok {
 		return mod
@@ -60,8 +136,9 @@ func (g *PackageGraph) GetModule(path string) *packages.Module {
 	return mod
 }
 
-// AddPackages adds the packages and the full graph of imported packages.
-// It will ignore packages that have duplicate paths to ones the graph already holds.
+// AddPackages adds the packages and their full graph of imported packages.
+// It also adds the modules of the added packages. It will ignore packages
+// that have duplicate paths to ones the graph already holds.
 func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	for _, pkg := range pkgs {
 		if _, found := g.packages[pkg.PkgPath]; found {
@@ -76,6 +153,9 @@ func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	}
 }
 
+// fixupPackage adds the module of pkg, if any, to the set
+// of all modules in g. If packages is not assigned a module
+// (likely stdlib package), a module set for pkg.
 func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 	if pkg.Module != nil {
 		g.AddModules(pkg.Module)
@@ -89,7 +169,7 @@ func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 // not find anything, it returns the "unknown" module.
 func (g *PackageGraph) findModule(pkgPath string) *packages.Module {
 	//TODO: better stdlib test
-	if !strings.Contains(pkgPath, ".") {
+	if IsStdPackage(pkgPath) {
 		return g.GetModule(internal.GoStdModulePath)
 	}
 	for _, m := range g.modules {
@@ -116,22 +196,16 @@ func (g *PackageGraph) GetPackage(path string) *packages.Package {
 
 // LoadPackages loads the packages specified by the patterns into the graph.
 // See golang.org/x/tools/go/packages.Load for details of how it works.
-func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, patterns []string) ([]*packages.Package, error) {
+func (g *PackageGraph) LoadPackagesAndMods(cfg *packages.Config, tags []string, patterns []string, wantSymbols bool) error {
 	if len(tags) > 0 {
 		cfg.BuildFlags = []string{fmt.Sprintf("-tags=%s", strings.Join(tags, ","))}
 	}
-	cfg.Mode |=
-		packages.NeedDeps |
-			packages.NeedImports |
-			packages.NeedModule |
-			packages.NeedSyntax |
-			packages.NeedTypes |
-			packages.NeedTypesInfo |
-			packages.NeedName
+
+	addLoadMode(cfg, wantSymbols)
 
 	pkgs, err := packages.Load(cfg, patterns...)
 	if err != nil {
-		return nil, err
+		return err
 	}
 	var perrs []packages.Error
 	packages.Visit(pkgs, nil, func(p *packages.Package) {
@@ -140,8 +214,27 @@ func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, pattern
 	if len(perrs) > 0 {
 		err = &packageError{perrs}
 	}
+
+	// Add all packages, top-level ones and their imports.
+	// This will also add their respective modules.
 	g.AddPackages(pkgs...)
-	return pkgs, err
+
+	// save top-level packages
+	for _, p := range pkgs {
+		g.topPkgs = append(g.topPkgs, g.GetPackage(p.PkgPath))
+	}
+	return err
+}
+
+func addLoadMode(cfg *packages.Config, wantSymbols bool) {
+	cfg.Mode |=
+		packages.NeedModule |
+			packages.NeedName |
+			packages.NeedDeps |
+			packages.NeedImports
+	if wantSymbols {
+		cfg.Mode |= packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo
+	}
 }
 
 // packageError contains errors from loading a set of packages.
@@ -159,3 +252,67 @@ func (e *packageError) Error() string {
 	fmt.Fprintln(&b, "\nFor details on package patterns, see https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.")
 	return b.String()
 }
+
+func (g *PackageGraph) SBOM() *govulncheck.SBOM {
+	getMod := func(mod *packages.Module) *govulncheck.Module {
+		if mod.Replace != nil {
+			return &govulncheck.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+
+		return &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+	}
+
+	var roots []string
+	rootMods := make(map[string]*govulncheck.Module)
+	for _, pkg := range g.TopPkgs() {
+		roots = append(roots, pkg.PkgPath)
+		mod := getMod(pkg.Module)
+		rootMods[mod.Path] = mod
+	}
+
+	// Govulncheck attempts to put the modules that correspond to the matched package patterns (i.e. the root modules)
+	// at the beginning of the SBOM.Modules message.
+	// Note: This does not guarantee that the first element is the root module.
+	var topMods, depMods []*govulncheck.Module
+	var goVersion string
+	for _, mod := range g.Modules() {
+		mod := getMod(mod)
+
+		if mod.Path == internal.GoStdModulePath {
+			goVersion = semver.SemverToGoTag(mod.Version)
+		}
+
+		// if the mod is not associated with a root package, add it to depMods
+		if rootMods[mod.Path] == nil {
+			depMods = append(depMods, mod)
+		}
+	}
+
+	for _, mod := range rootMods {
+		topMods = append(topMods, mod)
+	}
+	// Sort for deterministic output
+	sortMods(topMods)
+	sortMods(depMods)
+
+	mods := append(topMods, depMods...)
+
+	return &govulncheck.SBOM{
+		GoVersion: goVersion,
+		Modules:   mods,
+		Roots:     roots,
+	}
+}
+
+// Sorts modules alphabetically by path.
+func sortMods(mods []*govulncheck.Module) {
+	slices.SortFunc(mods, func(a, b *govulncheck.Module) int {
+		return strings.Compare(a.Path, b.Path)
+	})
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
index 71fffc41..0bfa1603 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
@@ -44,12 +44,3 @@ func forwardSlice(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.
 	}
 	return seen
 }
-
-// pruneSet removes functions in `set` that are in `toPrune`.
-func pruneSet(set, toPrune map[*ssa.Function]bool) {
-	for f := range set {
-		if !toPrune[f] {
-			delete(set, f)
-		}
-	}
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/source.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/source.go
index 2119c70d..348c3b96 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/source.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/source.go
@@ -6,8 +6,6 @@ package vulncheck
 
 import (
 	"context"
-	"fmt"
-	"go/token"
 	"sync"
 
 	"golang.org/x/tools/go/callgraph"
@@ -18,32 +16,24 @@ import (
 	"golang.org/x/vuln/internal/osv"
 )
 
-// Source detects vulnerabilities in packages. The result will contain:
-//
-// 1) An ImportGraph related to an import of a package with some known
-// vulnerabilities.
-//
-// 2) A RequireGraph related to a require of a module with a package that has
-// some known vulnerabilities.
-//
-// 3) A CallGraph leading to the use of a known vulnerable function or method.
-func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (_ *Result, err error) {
-	// buildSSA builds a whole program that assumes all packages use the same FileSet.
-	// Check all packages in pkgs are using the same FileSet.
-	// TODO(https://go.dev/issue/59729): take FileSet out of Package and
-	// let Source take a single FileSet. That will make the enforcement
-	// clearer from the API level.
-	var fset *token.FileSet
-	for _, p := range pkgs {
-		if fset == nil {
-			fset = p.Fset
-		} else {
-			if fset != p.Fset {
-				return nil, fmt.Errorf("[]*Package must have created with the same FileSet")
-			}
-		}
+// Source detects vulnerabilities in pkgs and emits the findings to handler.
+func Source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) error {
+	vr, err := source(ctx, handler, cfg, client, graph)
+	if err != nil {
+		return err
+	}
+
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, sourceCallstacks(vr))
 	}
+	return nil
+}
 
+// source detects vulnerabilities in packages. It emits findings to handler
+// and produces a Result that contains info on detected vulnerabilities.
+//
+// Assumes that pkgs are non-empty and belong to the same program.
+func source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (*Result, error) {
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
@@ -57,118 +47,109 @@ func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Conf
 		buildErr error
 	)
 	if cfg.ScanLevel.WantSymbols() {
+		fset := graph.TopPkgs()[0].Fset
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			prog, ssaPkgs := buildSSA(pkgs, fset)
+			prog, ssaPkgs := buildSSA(graph.TopPkgs(), fset)
 			entries = entryPoints(ssaPkgs)
 			cg, buildErr = callGraph(ctx, prog, entries)
 		}()
 	}
 
-	mods := extractModules(pkgs)
-	mv, err := FetchVulnerabilities(ctx, client, mods)
-	if err != nil {
+	if err := handler.SBOM(graph.SBOM()); err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
-	modVulns = modVulns.filter("", "")
-	result := &Result{}
 
-	vulnPkgModSlice(pkgs, modVulns, result)
-	// Return result immediately if not in symbol mode or
-	// if there are no vulnerable packages.
-	if !cfg.ScanLevel.WantSymbols() || len(result.EntryPackages) == 0 {
-		return result, nil
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
 	}
 
-	wg.Wait() // wait for build to finish
-	if buildErr != nil {
+	mv, err := FetchVulnerabilities(ctx, client, graph.Modules())
+	if err != nil {
 		return nil, err
 	}
 
-	vulnCallGraphSlice(entries, modVulns, cg, result, graph)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
 
-	return result, nil
-}
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingSrcVulnsMessage}); err != nil {
+		return nil, err
+	}
 
-// vulnPkgModSlice computes the slice of pkgs imports and requires graph
-// leading to imports/requires of vulnerable packages/modules in modVulns
-// and stores the computed slices to result.
-func vulnPkgModSlice(pkgs []*packages.Package, modVulns moduleVulnerabilities, result *Result) {
-	// analyzedPkgs contains information on packages analyzed thus far.
-	// If a package is mapped to false, this means it has been visited
-	// but it does not lead to a vulnerable imports. Otherwise, a
-	// visited package is mapped to true.
-	analyzedPkgs := make(map[*packages.Package]bool)
-	for _, pkg := range pkgs {
-		// Top level packages that lead to vulnerable imports are
-		// stored as result.EntryPackages graph entry points.
-		if vulnerable := vulnImportSlice(pkg, modVulns, result, analyzedPkgs); vulnerable {
-			result.EntryPackages = append(result.EntryPackages, pkg)
-		}
+	affVulns := affectingVulnerabilities(mv, "", "")
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
-}
 
-// vulnImportSlice checks if pkg has some vulnerabilities or transitively imports
-// a package with known vulnerabilities. If that is the case, populates result.Imports
-// graph with this reachability information and returns the result.Imports package
-// node for pkg. Otherwise, returns nil.
-func vulnImportSlice(pkg *packages.Package, modVulns moduleVulnerabilities, result *Result, analyzed map[*packages.Package]bool) bool {
-	if vulnerable, ok := analyzed[pkg]; ok {
-		return vulnerable
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
 	}
-	analyzed[pkg] = false
-	// Recursively compute which direct dependencies lead to an import of
-	// a vulnerable package and remember the nodes of such dependencies.
-	transitiveVulnerable := false
-	for _, imp := range pkg.Imports {
-		if impVulnerable := vulnImportSlice(imp, modVulns, result, analyzed); impVulnerable {
-			transitiveVulnerable = true
-		}
+
+	impVulns := importedVulnPackages(affVulns, graph)
+	// Emit information on imported vulnerable packages now as
+	// call graph computation might take a while.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
 	}
 
-	// Check if pkg has known vulnerabilities.
-	vulns := modVulns.vulnsForPackage(pkg.PkgPath)
+	// Return result immediately if not in symbol mode or
+	// if there are no vulnerabilities imported.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
 
-	// If pkg is not vulnerable nor it transitively leads
-	// to vulnerabilities, jump out.
-	if !transitiveVulnerable && len(vulns) == 0 {
-		return false
+	wg.Wait() // wait for build to finish
+	if buildErr != nil {
+		return nil, err
 	}
 
-	// Create Vuln entry for each symbol of known OSV entries for pkg.
-	for _, osv := range vulns {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg.PkgPath {
-					continue
-				}
-
-				symbols := p.Symbols
-				if len(symbols) == 0 {
-					symbols = allSymbols(pkg.Types)
-				}
-
-				for _, symbol := range symbols {
-					vuln := &Vuln{
-						OSV:        osv,
-						Symbol:     symbol,
-						ImportSink: pkg,
-					}
-					result.Vulns = append(result.Vulns, vuln)
-				}
+	entryFuncs, callVulns := calledVulnSymbols(entries, affVulns, cg, graph)
+	return &Result{EntryFunctions: entryFuncs, Vulns: callVulns}, nil
+}
+
+// importedVulnPackages detects imported vulnerable packages.
+func importedVulnPackages(affVulns affectingVulns, graph *PackageGraph) []*Vuln {
+	var vulns []*Vuln
+	analyzed := make(map[*packages.Package]bool) // skip analyzing the same package multiple times
+	var vulnImports func(pkg *packages.Package)
+	vulnImports = func(pkg *packages.Package) {
+		if analyzed[pkg] {
+			return
+		}
+
+		osvs := affVulns.ForPackage(pkgModPath(pkg), pkg.PkgPath)
+		// Create Vuln entry for each OSV entry for pkg.
+		for _, osv := range osvs {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg.PkgPath),
 			}
+			vulns = append(vulns, vuln)
+		}
+
+		analyzed[pkg] = true
+		for _, imp := range pkg.Imports {
+			vulnImports(imp)
 		}
 	}
-	analyzed[pkg] = true
-	return true
+
+	for _, pkg := range graph.TopPkgs() {
+		vulnImports(pkg)
+	}
+	return vulns
 }
 
-// vulnCallGraphSlice checks if known vulnerabilities are transitively reachable from sources
-// via call graph cg. If so, populates result.Calls graph with this reachability information.
-func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result, graph *PackageGraph) {
-	sinksWithVulns := vulnFuncs(cg, modVulns)
+// calledVulnSymbols detects vuln symbols transitively reachable from sources
+// via call graph cg.
+//
+// A slice of call graph is computed related to the reachable vulnerabilities. Each
+// reachable Vuln has attached FuncNode that can be upward traversed to the entry points.
+// Entry points that reach the vulnerable symbols are also returned.
+func calledVulnSymbols(sources []*ssa.Function, affVulns affectingVulns, cg *callgraph.Graph, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	sinksWithVulns := vulnFuncs(cg, affVulns, graph)
 
 	// Compute call graph backwards reachable
 	// from vulnerable functions and methods.
@@ -197,8 +178,8 @@ func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities,
 	}
 
 	// Transform the resulting call graph slice into
-	// vulncheck representation and store it to result.
-	vulnCallGraph(filteredSources, filteredSinks, result, graph)
+	// vulncheck representation.
+	return vulnCallGraph(filteredSources, filteredSinks, graph)
 }
 
 // callGraphSlice computes a slice of callgraph beginning at starts
@@ -240,25 +221,25 @@ func callGraphSlice(starts []*callgraph.Node, forward bool) *callgraph.Graph {
 	return g
 }
 
-// vulnCallGraph creates vulnerability call graph from sources -> sinks reachability info.
-func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, result *Result, graph *PackageGraph) {
+// vulnCallGraph creates vulnerability call graph in terms of sources and sinks.
+func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	var entries []*FuncNode
+	var vulns []*Vuln
 	nodes := make(map[*ssa.Function]*FuncNode)
 
 	// First create entries and sinks and store relevant information.
 	for _, s := range sources {
 		fn := createNode(nodes, s.Func, graph)
-		result.EntryFunctions = append(result.EntryFunctions, fn)
+		entries = append(entries, fn)
 	}
 
-	for s, vulns := range sinks {
+	for s, osvs := range sinks {
 		f := s.Func
 		funNode := createNode(nodes, s.Func, graph)
 
 		// Populate CallSink field for each detected vuln symbol.
-		for _, osv := range vulns {
-			if vulnMatchesPackage(osv, funNode.Package.PkgPath) {
-				addCallSinkForVuln(funNode, osv, dbFuncName(f), funNode.Package.PkgPath, result)
-			}
+		for _, osv := range osvs {
+			vulns = append(vulns, calledVuln(funNode, osv, dbFuncName(f), funNode.Package))
 		}
 	}
 
@@ -291,13 +272,15 @@ func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.E
 	for s := range sinks {
 		visit(s)
 	}
+	return entries, vulns
 }
 
 // vulnFuncs returns vulnerability information for vulnerable functions in cg.
-func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgraph.Node][]*osv.Entry {
+func vulnFuncs(cg *callgraph.Graph, affVulns affectingVulns, graph *PackageGraph) map[*callgraph.Node][]*osv.Entry {
 	m := make(map[*callgraph.Node][]*osv.Entry)
 	for f, n := range cg.Nodes {
-		vulns := modVulns.vulnsForSymbol(pkgPath(f), dbFuncName(f))
+		p := pkgPath(f)
+		vulns := affVulns.ForSymbol(pkgModPath(graph.GetPackage(p)), p, dbFuncName(f))
 		if len(vulns) > 0 {
 			m[n] = vulns
 		}
@@ -305,15 +288,6 @@ func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgra
 	return m
 }
 
-// pkgPath returns the path of the f's enclosing package, if any.
-// Otherwise, returns "".
-func pkgPath(f *ssa.Function) string {
-	if f.Package() != nil && f.Package().Pkg != nil {
-		return f.Package().Pkg.Path()
-	}
-	return ""
-}
-
 func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *PackageGraph) *FuncNode {
 	if fn, ok := nodes[f]; ok {
 		return fn
@@ -328,46 +302,11 @@ func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *Packa
 	return fn
 }
 
-// addCallSinkForVuln adds callID as call sink to vuln of result.Vulns
-// identified with .
-func addCallSinkForVuln(call *FuncNode, osv *osv.Entry, symbol, pkg string, result *Result) {
-	for _, vuln := range result.Vulns {
-		if vuln.OSV == osv && vuln.Symbol == symbol && vuln.ImportSink.PkgPath == pkg {
-			vuln.CallSink = call
-			return
-		}
-	}
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*packages.Package) []*packages.Module {
-	modMap := map[string]*packages.Module{}
-	seen := map[*packages.Package]bool{}
-	var extract func(*packages.Package, map[string]*packages.Module)
-	extract = func(pkg *packages.Package, modMap map[string]*packages.Module) {
-		if pkg == nil || seen[pkg] {
-			return
-		}
-		if pkg.Module != nil {
-			if pkg.Module.Replace != nil {
-				modMap[pkg.Module.Replace.Path] = pkg.Module
-			} else {
-				modMap[pkg.Module.Path] = pkg.Module
-			}
-		}
-		seen[pkg] = true
-		for _, imp := range pkg.Imports {
-			extract(imp, modMap)
-		}
-	}
-	for _, pkg := range pkgs {
-		extract(pkg, modMap)
-	}
-
-	modules := []*packages.Module{}
-	for _, mod := range modMap {
-		modules = append(modules, mod)
+func calledVuln(call *FuncNode, osv *osv.Entry, symbol string, pkg *packages.Package) *Vuln {
+	return &Vuln{
+		Symbol:   symbol,
+		Package:  pkg,
+		OSV:      osv,
+		CallSink: call,
 	}
-	return modules
 }
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/utils.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
index 4fa9c69a..e752f4a0 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
@@ -9,15 +9,17 @@ import (
 	"context"
 	"go/token"
 	"go/types"
+	"sort"
 	"strings"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/callgraph/cha"
 	"golang.org/x/tools/go/callgraph/vta"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa/ssautil"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/semver"
 
 	"golang.org/x/tools/go/ssa"
 )
@@ -26,7 +28,6 @@ import (
 // the ssa program encapsulating the packages and top level
 // ssa packages corresponding to pkgs.
 func buildSSA(pkgs []*packages.Package, fset *token.FileSet) (*ssa.Program, []*ssa.Package) {
-	// TODO(https://go.dev/issue/57221): what about entry functions that are generics?
 	prog := ssa.NewProgram(fset, ssa.InstantiateGenerics)
 
 	imports := make(map[*packages.Package]*ssa.Package)
@@ -69,12 +70,8 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 		return nil, err
 	}
 	initial := cha.CallGraph(prog)
-	allFuncs := ssautil.AllFunctions(prog)
 
 	fslice := forwardSlice(entrySlice, initial)
-	// Keep only actually linked functions.
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -83,8 +80,6 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 	// Repeat the process once more, this time using
 	// the produced VTA call graph as the base graph.
 	fslice = forwardSlice(entrySlice, vtaCg)
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -110,15 +105,17 @@ func dbTypeFormat(t types.Type) string {
 
 // dbFuncName computes a function name consistent with the namings used in vulnerability
 // databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
+// If a receiver is a pointer, this information is not encoded in the resulting name. If
+// a function has type argument/parameter, this information is omitted. The name of
+// anonymous functions is simply "". The function names are unique subject to the enclosing
+// package, but not globally.
 //
 // Examples:
 //
 //	func (a A) foo (...) {...}  -> A.foo
 //	func foo(...) {...}         -> foo
 //	func (b *B) bar (...) {...} -> B.bar
+//	func (c C[T]) do(...) {...} -> C.do
 func dbFuncName(f *ssa.Function) string {
 	selectBound := func(f *ssa.Function) types.Type {
 		// If f is a "bound" function introduced by ssa for a given type, return the type.
@@ -151,18 +148,17 @@ func dbFuncName(f *ssa.Function) string {
 	}
 
 	if qprefix == "" {
-		return f.Name()
+		return funcName(f)
 	}
-	return qprefix + "." + f.Name()
+	return qprefix + "." + funcName(f)
 }
 
-// dbTypesFuncName is dbFuncName defined over *types.Func.
-func dbTypesFuncName(f *types.Func) string {
-	sig := f.Type().(*types.Signature)
-	if sig.Recv() == nil {
-		return f.Name()
-	}
-	return dbTypeFormat(sig.Recv().Type()) + "." + f.Name()
+// funcName returns the name of the ssa function f.
+// It is f.Name() without additional type argument
+// information in case of generics.
+func funcName(f *ssa.Function) string {
+	n, _, _ := strings.Cut(f.Name(), "[")
+	return n
 }
 
 // memberFuncs returns functions associated with the `member`:
@@ -227,35 +223,124 @@ func funcRecvType(f *ssa.Function) string {
 	return buf.String()
 }
 
-// allSymbols returns all top-level functions and methods defined in pkg.
-func allSymbols(pkg *types.Package) []string {
-	var names []string
-	scope := pkg.Scope()
-	for _, name := range scope.Names() {
-		o := scope.Lookup(name)
-		switch o := o.(type) {
-		case *types.Func:
-			names = append(names, dbTypesFuncName(o))
-		case *types.TypeName:
-			ms := types.NewMethodSet(types.NewPointer(o.Type()))
-			for i := 0; i < ms.Len(); i++ {
-				if f, ok := ms.At(i).Obj().(*types.Func); ok {
-					names = append(names, dbTypesFuncName(f))
+func FixedVersion(modulePath, version string, affected []osv.Affected) string {
+	fixed := earliestValidFix(modulePath, version, affected)
+	// Add "v" prefix if one does not exist. moduleVersionString
+	// will later on replace it with "go" if needed.
+	if fixed != "" && !strings.HasPrefix(fixed, "v") {
+		fixed = "v" + fixed
+	}
+	return fixed
+}
+
+// earliestValidFix returns the earliest fix for version of modulePath that
+// itself is not vulnerable in affected.
+//
+// Suppose we have a version "v1.0.0" and we use {...} to denote different
+// affected regions. Assume for simplicity that all affected apply to the
+// same input modulePath.
+//
+//	{[v0.1.0, v0.1.9), [v1.0.0, v2.0.0)} -> v2.0.0
+//	{[v1.0.0, v1.5.0), [v2.0.0, v2.1.0}, {[v1.4.0, v1.6.0)} -> v2.1.0
+func earliestValidFix(modulePath, version string, affected []osv.Affected) string {
+	var moduleAffected []osv.Affected
+	for _, a := range affected {
+		if a.Module.Path == modulePath {
+			moduleAffected = append(moduleAffected, a)
+		}
+	}
+
+	vFixes := validFixes(version, moduleAffected)
+	for _, fix := range vFixes {
+		if !fixNegated(fix, moduleAffected) {
+			return fix
+		}
+	}
+	return ""
+
+}
+
+// validFixes computes all fixes for version in affected and
+// returns them sorted increasingly. Assumes that all affected
+// apply to the same module.
+func validFixes(version string, affected []osv.Affected) []string {
+	var fixes []string
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if r.Type != osv.RangeTypeSemver {
+				continue
+			}
+			for _, e := range r.Events {
+				fix := e.Fixed
+				if fix != "" && semver.Less(version, fix) {
+					fixes = append(fixes, fix)
 				}
 			}
 		}
 	}
-	return names
+	sort.SliceStable(fixes, func(i, j int) bool { return semver.Less(fixes[i], fixes[j]) })
+	return fixes
 }
 
-// vulnMatchesPackage reports whether an entry applies to pkg (an import path).
-func vulnMatchesPackage(v *osv.Entry, pkg string) bool {
-	for _, a := range v.Affected {
-		for _, p := range a.EcosystemSpecific.Packages {
-			if p.Path == pkg {
+// fixNegated checks if fix is negated to by a re-introduction
+// of a vulnerability in affected. Assumes that all affected apply
+// to the same module.
+func fixNegated(fix string, affected []osv.Affected) bool {
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if semver.ContainsSemver(r, fix) {
 				return true
 			}
 		}
 	}
 	return false
 }
+
+func modPath(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Path
+	}
+	return mod.Path
+}
+
+func modVersion(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Version
+	}
+	return mod.Version
+}
+
+// pkgPath returns the path of the f's enclosing package, if any.
+// Otherwise, returns internal.UnknownPackagePath.
+func pkgPath(f *ssa.Function) string {
+	g := f
+	if f.Origin() != nil {
+		// Instantiations of generics do not have
+		// an associated package. We hence look up
+		// the original function for the package.
+		g = f.Origin()
+	}
+	if g.Package() != nil && g.Package().Pkg != nil {
+		return g.Package().Pkg.Path()
+	}
+	return internal.UnknownPackagePath
+}
+
+func pkgModPath(pkg *packages.Package) string {
+	if pkg != nil && pkg.Module != nil {
+		return pkg.Module.Path
+	}
+	return internal.UnknownModulePath
+}
+
+func IsStdPackage(pkg string) bool {
+	if pkg == "" || pkg == internal.UnknownPackagePath {
+		return false
+	}
+	// std packages do not have a "." in their path. For instance, see
+	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
+	if i := strings.IndexByte(pkg, '/'); i != -1 {
+		pkg = pkg[:i]
+	}
+	return !strings.Contains(pkg, ".")
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
index 7786695c..198fffe0 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
@@ -16,31 +16,31 @@ import (
 	"golang.org/x/vuln/internal/semver"
 )
 
-// Result contains information on how known vulnerabilities are reachable
-// in the call graph, package imports graph, and module requires graph of
-// the user code.
+const (
+	fetchingVulnsMessage    = "Fetching vulnerabilities from the database..."
+	checkingSrcVulnsMessage = "Checking the code against the vulnerabilities..."
+	checkingBinVulnsMessage = "Checking the binary against the vulnerabilities..."
+)
+
+// Result contains information on detected vulnerabilities.
+// For call graph analysis, it provides information on reachability
+// of vulnerable symbols through entry points of the program.
 type Result struct {
 	// EntryFunctions are a subset of Functions representing vulncheck entry points.
 	EntryFunctions []*FuncNode
 
-	// EntryPackages are a subset of Packages representing packages of vulncheck entry points.
-	EntryPackages []*packages.Package
-
-	// Vulns contains information on detected vulnerabilities and their place in
-	// the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
-	// or whose packages are imported in Imports, or whose modules are required in
-	// Requires, have an entry in Vulns.
+	// Vulns contains information on detected vulnerabilities.
 	Vulns []*Vuln
 }
 
-// Vuln provides information on how a vulnerability is affecting user code by
-// connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities
-// detected in Go binaries do not appear in the Result graphs.
+// Vuln provides information on a detected vulnerability. For call
+// graph mode, Vuln will also contain the information on how the
+// vulnerability is reachable in the user call graph.
 type Vuln struct {
 	// OSV contains information on the detected vulnerability in the shared
 	// vulnerability format.
 	//
-	// OSV, Symbol, PkgPath, and ModPath identify a vulnerability.
+	// OSV, Symbol, and Package identify a vulnerability.
 	//
 	// Note that *osv.Entry may describe multiple symbols from multiple
 	// packages.
@@ -49,17 +49,17 @@ type Vuln struct {
 	// Symbol is the name of the detected vulnerable function or method.
 	Symbol string
 
-	// CallSink is the FuncNode in Result.Calls corresponding to Symbol.
+	// CallSink is the FuncNode corresponding to Symbol.
 	//
 	// When analyzing binaries, Symbol is not reachable, or cfg.ScanLevel
-	// is symbol, CallSink will be unavailable and set to 0.
+	// is symbol, CallSink will be unavailable and set to nil.
 	CallSink *FuncNode
 
-	// ImportSink is the PkgNode in Result.Imports corresponding to PkgPath.
+	// Package of Symbol.
 	//
-	// When analyzing binaries or PkgPath is not imported, ImportSink will be
-	// unavailable and set to 0.
-	ImportSink *packages.Package
+	// When the package of symbol is not imported, Package will be
+	// unavailable and set to nil.
+	Package *packages.Package
 }
 
 // A FuncNode describes a function in the call graph.
@@ -111,10 +111,10 @@ type CallSite struct {
 	Resolved bool
 }
 
-// moduleVulnerabilities is an internal structure for
-// holding and querying vulnerabilities provided by a
-// vulnerability database client.
-type moduleVulnerabilities []*ModVulns
+// affectingVulns is an internal structure for querying
+// vulnerabilities that apply to the current program
+// and platform under consideration.
+type affectingVulns []*ModVulns
 
 // ModVulns groups vulnerabilities per module.
 type ModVulns struct {
@@ -122,10 +122,10 @@ type ModVulns struct {
 	Vulns  []*osv.Entry
 }
 
-func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
+func affectingVulnerabilities(vulns []*ModVulns, os, arch string) affectingVulns {
 	now := time.Now()
-	var filteredMod moduleVulnerabilities
-	for _, mod := range mv {
+	var filtered affectingVulns
+	for _, mod := range vulns {
 		module := mod.Module
 		modVersion := module.Version
 		if module.Replace != nil {
@@ -150,24 +150,20 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 				if a.Module.Path != module.Path {
 					continue
 				}
-
-				// A module version is affected if
-				//  - it is included in one of the affected version ranges
-				//  - and module version is not ""
-				if modVersion == "" {
-					// Module version of "" means the module version is not available,
-					// and so we don't want to spam users with potential false alarms.
-					continue
-				}
-				if !semver.Affects(a.Ranges, modVersion) {
+				if !affected(modVersion, a) {
 					continue
 				}
+
 				var filteredImports []osv.Package
 				for _, p := range a.EcosystemSpecific.Packages {
 					if matchesPlatform(os, arch, p) {
 						filteredImports = append(filteredImports, p)
 					}
 				}
+				// If we pruned all existing Packages, then the affected is
+				// empty and we can filter it out. Note that Packages can
+				// be empty for vulnerabilities that have no package or
+				// symbol information available.
 				if len(a.EcosystemSpecific.Packages) != 0 && len(filteredImports) == 0 {
 					continue
 				}
@@ -183,12 +179,28 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 			newV.Affected = filteredAffected
 			filteredVulns = append(filteredVulns, &newV)
 		}
-		filteredMod = append(filteredMod, &ModVulns{
+
+		filtered = append(filtered, &ModVulns{
 			Module: module,
 			Vulns:  filteredVulns,
 		})
 	}
-	return filteredMod
+	return filtered
+}
+
+// affected checks if modVersion is affected by a:
+//   - it is included in one of the affected version ranges
+//   - and module version is not "" and "(devel)"
+func affected(modVersion string, a osv.Affected) bool {
+	const devel = "(devel)"
+	if modVersion == "" || modVersion == devel {
+		// Module version of "" means the module version is not available
+		// and devel means it is in development stage. Either way, we don't
+		// know the exact version so we don't want to spam users with
+		// potential false alarms.
+		return false
+	}
+	return semver.Affects(a.Ranges, modVersion)
 }
 
 func matchesPlatform(os, arch string, e osv.Package) bool {
@@ -211,37 +223,66 @@ func matchesPlatformComponent(s string, ps []string) bool {
 	return false
 }
 
-// vulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv moduleVulnerabilities) vulnsForPackage(importPath string) []*osv.Entry {
-	isStd := isStdPackage(importPath)
-	var mostSpecificMod *ModVulns
-	for _, mod := range mv {
+// moduleVulns return vulnerabilities for module. If module is unknown,
+// it figures the module from package importPath. It returns the module
+// whose path is the longest prefix of importPath.
+func (aff affectingVulns) moduleVulns(module, importPath string) *ModVulns {
+	moduleKnown := module != "" && module != internal.UnknownModulePath
+
+	isStd := IsStdPackage(importPath)
+	var mostSpecificMod *ModVulns // for the case where !moduleKnown
+	for _, mod := range aff {
 		md := mod
 		if isStd && mod.Module.Path == internal.GoStdModulePath {
-			// standard library packages do not have an associated module,
+			// Standard library packages do not have an associated module,
 			// so we relate them to the artificial stdlib module.
-			mostSpecificMod = md
+			return md
+		}
+
+		if moduleKnown {
+			if mod.Module.Path == module {
+				// If we know exactly which module we need,
+				// return its vulnerabilities.
+				return md
+			}
 		} else if strings.HasPrefix(importPath, md.Module.Path) {
+			// If module is unknown, we try to figure it out from importPath.
+			// We take the module whose path has the longest match to importPath.
+			// TODO: do matching based on path components.
 			if mostSpecificMod == nil || len(mostSpecificMod.Module.Path) < len(md.Module.Path) {
 				mostSpecificMod = md
 			}
 		}
 	}
-	if mostSpecificMod == nil {
+	return mostSpecificMod
+}
+
+// ForPackage returns the vulnerabilities for the importPath belonging to
+// module.
+//
+// If module is unknown, ForPackage will resolve it as the most specific
+// prefix of importPath.
+func (aff affectingVulns) ForPackage(module, importPath string) []*osv.Entry {
+	mod := aff.moduleVulns(module, importPath)
+	if mod == nil {
 		return nil
 	}
 
-	if mostSpecificMod.Module.Replace != nil {
+	if mod.Module.Replace != nil {
 		// standard libraries do not have a module nor replace module
-		importPath = fmt.Sprintf("%s%s", mostSpecificMod.Module.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.Module.Path))
+		importPath = fmt.Sprintf("%s%s", mod.Module.Replace.Path, strings.TrimPrefix(importPath, mod.Module.Path))
 	}
-	vulns := mostSpecificMod.Vulns
+	vulns := mod.Vulns
 	packageVulns := []*osv.Entry{}
 Vuln:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all packages are vulnerable
+				packageVulns = append(packageVulns, v)
+				continue Vuln
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path == importPath {
 					packageVulns = append(packageVulns, v)
@@ -253,9 +294,9 @@ Vuln:
 	return packageVulns
 }
 
-// vulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv.Entry {
-	vulns := mv.vulnsForPackage(importPath)
+// ForSymbol returns vulnerabilities for symbol in aff.ForPackage(module, importPath).
+func (aff affectingVulns) ForSymbol(module, importPath, symbol string) []*osv.Entry {
+	vulns := aff.ForPackage(module, importPath)
 	if vulns == nil {
 		return nil
 	}
@@ -264,6 +305,12 @@ func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv
 vulnLoop:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all symbols of all packages are vulnerable
+				symbolVulns = append(symbolVulns, v)
+				continue vulnLoop
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path != importPath {
 					continue
@@ -287,15 +334,3 @@ func contains(symbols []string, target string) bool {
 	}
 	return false
 }
-
-func isStdPackage(pkg string) bool {
-	if pkg == "" {
-		return false
-	}
-	// std packages do not have a "." in their path. For instance, see
-	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
-	if i := strings.IndexByte(pkg, '/'); i != -1 {
-		pkg = pkg[:i]
-	}
-	return !strings.Contains(pkg, ".")
-}
diff --git a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/witness.go b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
index 7de37587..7bc18581 100644
--- a/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
+++ b/event-processor/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
@@ -13,6 +13,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"unicode"
 
 	"golang.org/x/tools/go/packages"
 )
@@ -32,18 +33,18 @@ type StackEntry struct {
 	Call *CallSite
 }
 
-// CallStacks returns representative call stacks for each
+// sourceCallstacks returns representative call stacks for each
 // vulnerability in res. The returned call stacks are heuristically
 // ordered by how seemingly easy is to understand them: shorter
 // call stacks with less dynamic call sites appear earlier in the
 // returned slices.
 //
-// CallStacks performs a breadth-first search of res.CallGraph starting
-// at the vulnerable symbol and going up until reaching an entry
+// sourceCallstacks performs a breadth-first search of res.CallGraph
+// starting at the vulnerable symbol and going up until reaching an entry
 // function or method in res.CallGraph.Entries. During this search,
 // each function is visited at most once to avoid potential
 // exponential explosion. Hence, not all call stacks are analyzed.
-func CallStacks(res *Result) map[*Vuln]CallStack {
+func sourceCallstacks(res *Result) map[*Vuln]CallStack {
 	var (
 		wg sync.WaitGroup
 		mu sync.Mutex
@@ -53,7 +54,7 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 		vuln := vuln
 		wg.Add(1)
 		go func() {
-			cs := callStack(vuln, res)
+			cs := sourceCallstack(vuln, res)
 			mu.Lock()
 			stackPerVuln[vuln] = cs
 			mu.Unlock()
@@ -66,10 +67,10 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 	return stackPerVuln
 }
 
-// callStack finds a representative call stack for vuln.
+// sourceCallstack finds a representative call stack for vuln.
 // This is a shortest unique call stack with the least
 // number of dynamic call sites.
-func callStack(vuln *Vuln, res *Result) CallStack {
+func sourceCallstack(vuln *Vuln, res *Result) CallStack {
 	vulnSink := vuln.CallSink
 	if vulnSink == nil {
 		return nil
@@ -100,7 +101,7 @@ func callStack(vuln *Vuln, res *Result) CallStack {
 	skipSymbols := make(map[*FuncNode]bool)
 	for _, v := range res.Vulns {
 		if v.CallSink != nil && v != vuln &&
-			v.OSV == vuln.OSV && v.ImportSink == vuln.ImportSink {
+			v.OSV == vuln.OSV && v.Package == vuln.Package {
 			skipSymbols[v.CallSink] = true
 		}
 	}
@@ -390,3 +391,59 @@ func isInit(f *FuncNode) bool {
 	// positive integer. Implicit inits are named simply "init".
 	return f.Name == "init" || strings.HasPrefix(f.Name, "init#")
 }
+
+// binaryCallstacks computes representative call stacks for binary results.
+func binaryCallstacks(vr *Result) map[*Vuln]CallStack {
+	callstacks := map[*Vuln]CallStack{}
+	for _, vv := range uniqueVulns(vr.Vulns) {
+		f := &FuncNode{Package: vv.Package, Name: vv.Symbol}
+		parts := strings.Split(vv.Symbol, ".")
+		if len(parts) != 1 {
+			f.RecvType = parts[0]
+			f.Name = parts[1]
+		}
+		callstacks[vv] = CallStack{StackEntry{Function: f}}
+	}
+	return callstacks
+}
+
+// uniqueVulns does for binary mode what sourceCallstacks does for source mode.
+// It tries not to report redundant symbols. Since there are no call stacks in
+// binary mode, the following approximate approach is used. Do not report unexported
+// symbols for a  triple if there are some exported symbols.
+// Otherwise, report all unexported symbols to avoid not reporting anything.
+func uniqueVulns(vulns []*Vuln) []*Vuln {
+	type key struct {
+		id  string
+		pkg string
+		mod string
+	}
+	hasExported := make(map[key]bool)
+	for _, v := range vulns {
+		if isExported(v.Symbol) {
+			k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+			hasExported[k] = true
+		}
+	}
+
+	var uniques []*Vuln
+	for _, v := range vulns {
+		k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+		if isExported(v.Symbol) || !hasExported[k] {
+			uniques = append(uniques, v)
+		}
+	}
+	return uniques
+}
+
+// isExported checks if the symbol is exported. Assumes that the
+// symbol is of the form "identifier", "identifier1.identifier2",
+// or "identifier.".
+func isExported(symbol string) bool {
+	parts := strings.Split(symbol, ".")
+	last := parts[len(parts)-1]
+	if last == "" { // case for "identifier."
+		return false
+	}
+	return unicode.IsUpper(rune(last[0]))
+}
diff --git a/event-processor/vendor/golang.org/x/vuln/scan/scan.go b/event-processor/vendor/golang.org/x/vuln/scan/scan.go
index 83ed75a9..0aa9975e 100644
--- a/event-processor/vendor/golang.org/x/vuln/scan/scan.go
+++ b/event-processor/vendor/golang.org/x/vuln/scan/scan.go
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+/*
+Package scan provides functionality for running govulncheck.
+
+See [cmd/govulncheck/main.go] as a usage example.
+
+[cmd/govulncheck/main.go]: https://go.googlesource.com/vuln/+/master/cmd/govulncheck/main.go
+*/
 package scan
 
 import (
diff --git a/event-processor/vendor/google.golang.org/grpc/MAINTAINERS.md b/event-processor/vendor/google.golang.org/grpc/MAINTAINERS.md
index 5d4096d4..df35bb9a 100644
--- a/event-processor/vendor/google.golang.org/grpc/MAINTAINERS.md
+++ b/event-processor/vendor/google.golang.org/grpc/MAINTAINERS.md
@@ -9,21 +9,19 @@ for general contribution guidelines.
 
 ## Maintainers (in alphabetical order)
 
-- [aranjans](https://github.com/aranjans), Google LLC
 - [arjan-bal](https://github.com/arjan-bal), Google LLC
 - [arvindbr8](https://github.com/arvindbr8), Google LLC
 - [atollena](https://github.com/atollena), Datadog, Inc.
 - [dfawley](https://github.com/dfawley), Google LLC
 - [easwars](https://github.com/easwars), Google LLC
-- [erm-g](https://github.com/erm-g), Google LLC
 - [gtcooke94](https://github.com/gtcooke94), Google LLC
-- [purnesh42h](https://github.com/purnesh42h), Google LLC
-- [zasweq](https://github.com/zasweq), Google LLC
 
 ## Emeritus Maintainers (in alphabetical order)
 - [adelez](https://github.com/adelez)
+- [aranjans](https://github.com/aranjans)
 - [canguler](https://github.com/canguler)
 - [cesarghali](https://github.com/cesarghali)
+- [erm-g](https://github.com/erm-g)
 - [iamqizhao](https://github.com/iamqizhao)
 - [jeanbza](https://github.com/jeanbza)
 - [jtattermusch](https://github.com/jtattermusch)
@@ -32,5 +30,7 @@ for general contribution guidelines.
 - [matt-kwong](https://github.com/matt-kwong)
 - [menghanl](https://github.com/menghanl)
 - [nicolasnoble](https://github.com/nicolasnoble)
+- [purnesh42h](https://github.com/purnesh42h)
 - [srini100](https://github.com/srini100)
 - [yongni](https://github.com/yongni)
+- [zasweq](https://github.com/zasweq)
diff --git a/event-processor/vendor/google.golang.org/grpc/balancer/balancer.go b/event-processor/vendor/google.golang.org/grpc/balancer/balancer.go
index c9b343c7..b1264017 100644
--- a/event-processor/vendor/google.golang.org/grpc/balancer/balancer.go
+++ b/event-processor/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -360,6 +360,10 @@ type Balancer interface {
 	// call SubConn.Shutdown for its existing SubConns; however, this will be
 	// required in a future release, so it is recommended.
 	Close()
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // ExitIdler is an optional interface for balancers to implement.  If
@@ -367,8 +371,8 @@ type Balancer interface {
 // the ClientConn is idle.  If unimplemented, ClientConn.Connect will cause
 // all SubConns to connect.
 //
-// Notice: it will be required for all balancers to implement this in a future
-// release.
+// Deprecated: All balancers must implement this interface. This interface will
+// be removed in a future release.
 type ExitIdler interface {
 	// ExitIdle instructs the LB policy to reconnect to backends / exit the
 	// IDLE state, if appropriate and possible.  Note that SubConns that enter
diff --git a/event-processor/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/event-processor/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
index cc606f4d..360db08e 100644
--- a/event-processor/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
+++ b/event-processor/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
@@ -37,6 +37,8 @@ import (
 	"google.golang.org/grpc/resolver"
 )
 
+var randIntN = rand.IntN
+
 // ChildState is the balancer state of a child along with the endpoint which
 // identifies the child balancer.
 type ChildState struct {
@@ -45,7 +47,15 @@ type ChildState struct {
 
 	// Balancer exposes only the ExitIdler interface of the child LB policy.
 	// Other methods of the child policy are called only by endpointsharding.
-	Balancer balancer.ExitIdler
+	Balancer ExitIdler
+}
+
+// ExitIdler provides access to only the ExitIdle method of the child balancer.
+type ExitIdler interface {
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // Options are the options to configure the behaviour of the
@@ -104,6 +114,21 @@ type endpointSharding struct {
 	mu sync.Mutex
 }
 
+// rotateEndpoints returns a slice of all the input endpoints rotated a random
+// amount.
+func rotateEndpoints(es []resolver.Endpoint) []resolver.Endpoint {
+	les := len(es)
+	if les == 0 {
+		return es
+	}
+	r := randIntN(les)
+	// Make a copy to avoid mutating data beyond the end of es.
+	ret := make([]resolver.Endpoint, les)
+	copy(ret, es[r:])
+	copy(ret[les-r:], es[:r])
+	return ret
+}
+
 // UpdateClientConnState creates a child for new endpoints and deletes children
 // for endpoints that are no longer present. It also updates all the children,
 // and sends a single synchronous update of the childrens' aggregated state at
@@ -125,7 +150,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
 	newChildren := resolver.NewEndpointMap[*balancerWrapper]()
 
 	// Update/Create new children.
-	for _, endpoint := range state.ResolverState.Endpoints {
+	for _, endpoint := range rotateEndpoints(state.ResolverState.Endpoints) {
 		if _, ok := newChildren.Get(endpoint); ok {
 			// Endpoint child was already created, continue to avoid duplicate
 			// update.
@@ -205,6 +230,16 @@ func (es *endpointSharding) Close() {
 	}
 }
 
+func (es *endpointSharding) ExitIdle() {
+	es.childMu.Lock()
+	defer es.childMu.Unlock()
+	for _, bw := range es.children.Load().Values() {
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+	}
+}
+
 // updateState updates this component's state. It sends the aggregated state,
 // and a picker with round robin behavior with all the child states present if
 // needed.
@@ -261,7 +296,7 @@ func (es *endpointSharding) updateState() {
 	p := &pickerWithChildStates{
 		pickers:     pickers,
 		childStates: childStates,
-		next:        uint32(rand.IntN(len(pickers))),
+		next:        uint32(randIntN(len(pickers))),
 	}
 	es.cc.UpdateState(balancer.State{
 		ConnectivityState: aggState,
@@ -326,15 +361,13 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) {
 // ExitIdle pings an IDLE child balancer to exit idle in a new goroutine to
 // avoid deadlocks due to synchronous balancer state updates.
 func (bw *balancerWrapper) ExitIdle() {
-	if ei, ok := bw.child.(balancer.ExitIdler); ok {
-		go func() {
-			bw.es.childMu.Lock()
-			if !bw.isClosed {
-				ei.ExitIdle()
-			}
-			bw.es.childMu.Unlock()
-		}()
-	}
+	go func() {
+		bw.es.childMu.Lock()
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+		bw.es.childMu.Unlock()
+	}()
 }
 
 // updateClientConnStateLocked delivers the ClientConnState to the child
diff --git a/event-processor/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/event-processor/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
index 494314f2..67f315a0 100644
--- a/event-processor/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
+++ b/event-processor/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
@@ -54,18 +54,9 @@ func init() {
 	balancer.Register(pickfirstBuilder{})
 }
 
-type (
-	// enableHealthListenerKeyType is a unique key type used in resolver
-	// attributes to indicate whether the health listener usage is enabled.
-	enableHealthListenerKeyType struct{}
-	// managedByPickfirstKeyType is an attribute key type to inform Outlier
-	// Detection that the generic health listener is being used.
-	// TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when
-	// implementing the dualstack design. This is a hack. Once Dualstack is
-	// completed, outlier detection will stop sending ejection updates through
-	// the connectivity listener.
-	managedByPickfirstKeyType struct{}
-)
+// enableHealthListenerKeyType is a unique key type used in resolver
+// attributes to indicate whether the health listener usage is enabled.
+type enableHealthListenerKeyType struct{}
 
 var (
 	logger = grpclog.Component("pick-first-leaf-lb")
@@ -76,21 +67,21 @@ var (
 	disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.disconnections",
 		Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
-		Unit:        "disconnection",
+		Unit:        "{disconnection}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_succeeded",
 		Description: "EXPERIMENTAL. Number of successful connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_failed",
 		Description: "EXPERIMENTAL. Number of failed connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
@@ -149,17 +140,6 @@ func EnableHealthListener(state resolver.State) resolver.State {
 	return state
 }
 
-// IsManagedByPickfirst returns whether an address belongs to a SubConn
-// managed by the pickfirst LB policy.
-// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable
-// outlier_detection via the with connectivity listener when using pick_first.
-// Once Dualstack changes are complete, all SubConns will be created by
-// pick_first and outlier detection will only use the health listener for
-// ejection. This hack can then be removed.
-func IsManagedByPickfirst(addr resolver.Address) bool {
-	return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil
-}
-
 type pfConfig struct {
 	serviceconfig.LoadBalancingConfig `json:"-"`
 
@@ -186,7 +166,6 @@ type scData struct {
 }
 
 func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) {
-	addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true)
 	sd := &scData{
 		rawConnectivityState: connectivity.Idle,
 		effectiveState:       connectivity.Idle,
diff --git a/event-processor/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/event-processor/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
index 35da5d1e..22045bf3 100644
--- a/event-processor/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
+++ b/event-processor/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -70,10 +70,3 @@ func (b *rrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
 		ResolverState: pickfirstleaf.EnableHealthListener(ccs.ResolverState),
 	})
 }
-
-func (b *rrBalancer) ExitIdle() {
-	// Should always be ok, as child is endpoint sharding.
-	if ei, ok := b.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-	}
-}
diff --git a/event-processor/vendor/google.golang.org/grpc/clientconn.go b/event-processor/vendor/google.golang.org/grpc/clientconn.go
index cd3eaf8d..3f762285 100644
--- a/event-processor/vendor/google.golang.org/grpc/clientconn.go
+++ b/event-processor/vendor/google.golang.org/grpc/clientconn.go
@@ -208,7 +208,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error)
 	channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority)
 
 	cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz)
-	cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers)
+	cc.pickerWrapper = newPickerWrapper()
 
 	cc.metricsRecorderList = stats.NewMetricsRecorderList(cc.dopts.copts.StatsHandlers)
 
@@ -1076,13 +1076,6 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
 	return cc.sc.healthCheckConfig
 }
 
-func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
-	return cc.pickerWrapper.pick(ctx, failfast, balancer.PickInfo{
-		Ctx:            ctx,
-		FullMethodName: method,
-	})
-}
-
 func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSelector iresolver.ConfigSelector) {
 	if sc == nil {
 		// should never reach here.
@@ -1831,7 +1824,7 @@ func (cc *ClientConn) initAuthority() error {
 	} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
 		cc.authority = auth.OverrideAuthority(cc.parsedTarget)
 	} else if strings.HasPrefix(endpoint, ":") {
-		cc.authority = "localhost" + endpoint
+		cc.authority = "localhost" + encodeAuthority(endpoint)
 	} else {
 		cc.authority = encodeAuthority(endpoint)
 	}
diff --git a/event-processor/vendor/google.golang.org/grpc/credentials/credentials.go b/event-processor/vendor/google.golang.org/grpc/credentials/credentials.go
index a63ab606..c8e337cd 100644
--- a/event-processor/vendor/google.golang.org/grpc/credentials/credentials.go
+++ b/event-processor/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -96,10 +96,11 @@ func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
 	return c
 }
 
-// ProtocolInfo provides information regarding the gRPC wire protocol version,
-// security protocol, security protocol version in use, server name, etc.
+// ProtocolInfo provides static information regarding transport credentials.
 type ProtocolInfo struct {
 	// ProtocolVersion is the gRPC wire protocol version.
+	//
+	// Deprecated: this is unused by gRPC.
 	ProtocolVersion string
 	// SecurityProtocol is the security protocol in use.
 	SecurityProtocol string
@@ -109,7 +110,16 @@ type ProtocolInfo struct {
 	//
 	// Deprecated: please use Peer.AuthInfo.
 	SecurityVersion string
-	// ServerName is the user-configured server name.
+	// ServerName is the user-configured server name.  If set, this overrides
+	// the default :authority header used for all RPCs on the channel using the
+	// containing credentials, unless grpc.WithAuthority is set on the channel,
+	// in which case that setting will take precedence.
+	//
+	// This must be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: Users should use grpc.WithAuthority to override the authority
+	// on a channel instead of configuring the credentials.
 	ServerName string
 }
 
@@ -173,12 +183,17 @@ type TransportCredentials interface {
 	// Clone makes a copy of this TransportCredentials.
 	Clone() TransportCredentials
 	// OverrideServerName specifies the value used for the following:
+	//
 	// - verifying the hostname on the returned certificates
 	// - as SNI in the client's handshake to support virtual hosting
 	// - as the value for `:authority` header at stream creation time
 	//
-	// Deprecated: use grpc.WithAuthority instead. Will be supported
-	// throughout 1.x.
+	// The provided string should be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: this method is unused by gRPC.  Users should use
+	// grpc.WithAuthority to override the authority on a channel instead of
+	// configuring the credentials.
 	OverrideServerName(string) error
 }
 
diff --git a/event-processor/vendor/google.golang.org/grpc/credentials/tls.go b/event-processor/vendor/google.golang.org/grpc/credentials/tls.go
index 20f65f7b..8277be7d 100644
--- a/event-processor/vendor/google.golang.org/grpc/credentials/tls.go
+++ b/event-processor/vendor/google.golang.org/grpc/credentials/tls.go
@@ -110,14 +110,14 @@ func (c tlsCreds) Info() ProtocolInfo {
 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
 	// use local cfg to avoid clobbering ServerName if using multiple endpoints
 	cfg := credinternal.CloneTLSConfig(c.config)
-	if cfg.ServerName == "" {
-		serverName, _, err := net.SplitHostPort(authority)
-		if err != nil {
-			// If the authority had no host port or if the authority cannot be parsed, use it as-is.
-			serverName = authority
-		}
-		cfg.ServerName = serverName
+
+	serverName, _, err := net.SplitHostPort(authority)
+	if err != nil {
+		// If the authority had no host port or if the authority cannot be parsed, use it as-is.
+		serverName = authority
 	}
+	cfg.ServerName = serverName
+
 	conn := tls.Client(rawConn, cfg)
 	errChannel := make(chan error, 1)
 	go func() {
@@ -259,9 +259,11 @@ func applyDefaults(c *tls.Config) *tls.Config {
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
 }
@@ -271,9 +273,11 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
 	b, err := os.ReadFile(certFile)
 	if err != nil {
diff --git a/event-processor/vendor/google.golang.org/grpc/dialoptions.go b/event-processor/vendor/google.golang.org/grpc/dialoptions.go
index 050ba0f1..7a5ac2e7 100644
--- a/event-processor/vendor/google.golang.org/grpc/dialoptions.go
+++ b/event-processor/vendor/google.golang.org/grpc/dialoptions.go
@@ -213,6 +213,7 @@ func WithReadBufferSize(s int) DialOption {
 func WithInitialWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -222,6 +223,26 @@ func WithInitialWindowSize(s int32) DialOption {
 func WithInitialConnWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticStreamWindowSize returns a DialOption which sets the initial
+// stream window size to the value provided and disables dynamic flow control.
+func WithStaticStreamWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticConnWindowSize returns a DialOption which sets the initial
+// connection window size to the value provided and disables dynamic flow
+// control.
+func WithStaticConnWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -587,6 +608,8 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
 
 // WithAuthority returns a DialOption that specifies the value to be used as the
 // :authority pseudo-header and as the server name in authentication handshake.
+// This overrides all other ways of setting authority on the channel, but can be
+// overridden per-call by using grpc.CallAuthority.
 func WithAuthority(a string) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.authority = a
diff --git a/event-processor/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go b/event-processor/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
index 93136610..f2c01f29 100644
--- a/event-processor/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
+++ b/event-processor/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
@@ -188,13 +188,13 @@ type HealthServer interface {
 type UnimplementedHealthServer struct{}
 
 func (UnimplementedHealthServer) Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
+	return nil, status.Error(codes.Unimplemented, "method Check not implemented")
 }
 func (UnimplementedHealthServer) List(context.Context, *HealthListRequest) (*HealthListResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+	return nil, status.Error(codes.Unimplemented, "method List not implemented")
 }
 func (UnimplementedHealthServer) Watch(*HealthCheckRequest, grpc.ServerStreamingServer[HealthCheckResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method Watch not implemented")
+	return status.Error(codes.Unimplemented, "method Watch not implemented")
 }
 func (UnimplementedHealthServer) testEmbeddedByValue() {}
 
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/event-processor/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
index fbc1ca35..ba25b898 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
@@ -223,15 +223,7 @@ func (gsb *Balancer) ExitIdle() {
 	// There is no need to protect this read with a mutex, as the write to the
 	// Balancer field happens in SwitchTo, which completes before this can be
 	// called.
-	if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-		return
-	}
-	gsb.mu.Lock()
-	defer gsb.mu.Unlock()
-	for sc := range balToUpdate.subconns {
-		sc.Connect()
-	}
+	balToUpdate.ExitIdle()
 }
 
 // updateSubConnState forwards the update to the appropriate child.
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/event-processor/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
index f5f2bdeb..7e060f5e 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -26,30 +26,32 @@ import (
 )
 
 var (
-	// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
+	// EnableTXTServiceConfig is set if the DNS resolver should perform TXT
+	// lookups for service config ("GRPC_ENABLE_TXT_SERVICE_CONFIG" is not
+	// "false").
+	EnableTXTServiceConfig = boolFromEnv("GRPC_ENABLE_TXT_SERVICE_CONFIG", true)
+
+	// TXTErrIgnore is set if TXT errors should be ignored
+	// ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
 	TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
+
 	// RingHashCap indicates the maximum ring size which defaults to 4096
 	// entries but may be overridden by setting the environment variable
 	// "GRPC_RING_HASH_CAP".  This does not override the default bounds
 	// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
 	RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
-	// LeastRequestLB is set if we should support the least_request_experimental
-	// LB policy, which can be enabled by setting the environment variable
-	// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
-	LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", true)
+
 	// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
 	// handshakes that can be performed.
 	ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
+
 	// EnforceALPNEnabled is set if TLS connections to servers with ALPN disabled
 	// should be rejected. The HTTP/2 protocol requires ALPN to be enabled, this
 	// option is present for backward compatibility. This option may be overridden
 	// by setting the environment variable "GRPC_ENFORCE_ALPN_ENABLED" to "true"
 	// or "false".
 	EnforceALPNEnabled = boolFromEnv("GRPC_ENFORCE_ALPN_ENABLED", true)
-	// XDSFallbackSupport is the env variable that controls whether support for
-	// xDS fallback is turned on. If this is unset or is false, only the first
-	// xDS server in the list of server configs will be used.
-	XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true)
+
 	// NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used
 	// instead of the exiting pickfirst implementation. This can be disabled by
 	// setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST"
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/internal.go b/event-processor/vendor/google.golang.org/grpc/internal/internal.go
index 3ac798e8..2699223a 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/internal.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/internal.go
@@ -182,35 +182,6 @@ var (
 	// other features, including the CSDS service.
 	NewXDSResolverWithClientForTesting any // func(xdsclient.XDSClient) (resolver.Builder, error)
 
-	// RegisterRLSClusterSpecifierPluginForTesting registers the RLS Cluster
-	// Specifier Plugin for testing purposes, regardless of the XDSRLS environment
-	// variable.
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	RegisterRLSClusterSpecifierPluginForTesting func()
-
-	// UnregisterRLSClusterSpecifierPluginForTesting unregisters the RLS Cluster
-	// Specifier Plugin for testing purposes. This is needed because there is no way
-	// to unregister the RLS Cluster Specifier Plugin after registering it solely
-	// for testing purposes using RegisterRLSClusterSpecifierPluginForTesting().
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	UnregisterRLSClusterSpecifierPluginForTesting func()
-
-	// RegisterRBACHTTPFilterForTesting registers the RBAC HTTP Filter for testing
-	// purposes, regardless of the RBAC environment variable.
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	RegisterRBACHTTPFilterForTesting func()
-
-	// UnregisterRBACHTTPFilterForTesting unregisters the RBAC HTTP Filter for
-	// testing purposes. This is needed because there is no way to unregister the
-	// HTTP Filter after registering it solely for testing purposes using
-	// RegisterRBACHTTPFilterForTesting().
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	UnregisterRBACHTTPFilterForTesting func()
-
 	// ORCAAllowAnyMinReportingInterval is for examples/orca use ONLY.
 	ORCAAllowAnyMinReportingInterval any // func(so *orca.ServiceOptions)
 
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/event-processor/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
index ba5c5a95..ada5251c 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
@@ -132,13 +132,13 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
 	// DNS address (non-IP).
 	ctx, cancel := context.WithCancel(context.Background())
 	d := &dnsResolver{
-		host:                 host,
-		port:                 port,
-		ctx:                  ctx,
-		cancel:               cancel,
-		cc:                   cc,
-		rn:                   make(chan struct{}, 1),
-		disableServiceConfig: opts.DisableServiceConfig,
+		host:                host,
+		port:                port,
+		ctx:                 ctx,
+		cancel:              cancel,
+		cc:                  cc,
+		rn:                  make(chan struct{}, 1),
+		enableServiceConfig: envconfig.EnableTXTServiceConfig && !opts.DisableServiceConfig,
 	}
 
 	d.resolver, err = internal.NewNetResolver(target.URL.Host)
@@ -181,8 +181,8 @@ type dnsResolver struct {
 	// finishes, race detector sometimes will warn lookup (READ the lookup
 	// function pointers) inside watcher() goroutine has data race with
 	// replaceNetFunc (WRITE the lookup function pointers).
-	wg                   sync.WaitGroup
-	disableServiceConfig bool
+	wg                  sync.WaitGroup
+	enableServiceConfig bool
 }
 
 // ResolveNow invoke an immediate resolution of the target that this
@@ -346,7 +346,7 @@ func (d *dnsResolver) lookup() (*resolver.State, error) {
 	if len(srv) > 0 {
 		state = grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: srv})
 	}
-	if !d.disableServiceConfig {
+	if d.enableServiceConfig {
 		state.ServiceConfig = d.lookupTXT(ctx)
 	}
 	return &state, nil
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
index ef72fbb3..a2831e5d 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -40,6 +40,13 @@ var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
 	e.SetMaxDynamicTableSizeLimit(v)
 }
 
+// itemNodePool is used to reduce heap allocations.
+var itemNodePool = sync.Pool{
+	New: func() any {
+		return &itemNode{}
+	},
+}
+
 type itemNode struct {
 	it   any
 	next *itemNode
@@ -51,7 +58,9 @@ type itemList struct {
 }
 
 func (il *itemList) enqueue(i any) {
-	n := &itemNode{it: i}
+	n := itemNodePool.Get().(*itemNode)
+	n.next = nil
+	n.it = i
 	if il.tail == nil {
 		il.head, il.tail = n, n
 		return
@@ -71,7 +80,9 @@ func (il *itemList) dequeue() any {
 		return nil
 	}
 	i := il.head.it
+	temp := il.head
 	il.head = il.head.next
+	itemNodePool.Put(temp)
 	if il.head == nil {
 		il.tail = nil
 	}
@@ -146,10 +157,11 @@ type earlyAbortStream struct {
 func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
 
 type dataFrame struct {
-	streamID  uint32
-	endStream bool
-	h         []byte
-	reader    mem.Reader
+	streamID   uint32
+	endStream  bool
+	h          []byte
+	data       mem.BufferSlice
+	processing bool
 	// onEachWrite is called every time
 	// a part of data is written out.
 	onEachWrite func()
@@ -234,6 +246,7 @@ type outStream struct {
 	itl              *itemList
 	bytesOutStanding int
 	wq               *writeQuota
+	reader           mem.Reader
 
 	next *outStream
 	prev *outStream
@@ -461,7 +474,9 @@ func (c *controlBuffer) finish() {
 				v.onOrphaned(ErrConnClosing)
 			}
 		case *dataFrame:
-			_ = v.reader.Close()
+			if !v.processing {
+				v.data.Free()
+			}
 		}
 	}
 
@@ -650,10 +665,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
 
 func (l *loopyWriter) registerStreamHandler(h *registerStream) {
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	l.estdStreams[h.streamID] = str
 }
@@ -685,10 +701,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
 	}
 	// Case 2: Client wants to originate stream.
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	return l.originateStream(str, h)
 }
@@ -790,10 +807,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
 		// a RST_STREAM before stream initialization thus the stream might
 		// not be established yet.
 		delete(l.estdStreams, c.streamID)
+		str.reader.Close()
 		str.deleteSelf()
 		for head := str.itl.dequeueAll(); head != nil; head = head.next {
 			if df, ok := head.it.(*dataFrame); ok {
-				_ = df.reader.Close()
+				if !df.processing {
+					df.data.Free()
+				}
 			}
 		}
 	}
@@ -928,7 +948,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	if str == nil {
 		return true, nil
 	}
+	reader := str.reader
 	dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
+	if !dataItem.processing {
+		dataItem.processing = true
+		str.reader.Reset(dataItem.data)
+		dataItem.data.Free()
+	}
 	// A data item is represented by a dataFrame, since it later translates into
 	// multiple HTTP2 data frames.
 	// Every dataFrame has two buffers; h that keeps grpc-message header and data
@@ -936,13 +962,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	// from data is copied to h to make as big as the maximum possible HTTP2 frame
 	// size.
 
-	if len(dataItem.h) == 0 && dataItem.reader.Remaining() == 0 { // Empty data frame
+	if len(dataItem.h) == 0 && reader.Remaining() == 0 { // Empty data frame
 		// Client sends out empty data frame with endStream = true
 		if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
 			return false, err
 		}
 		str.itl.dequeue() // remove the empty data item from stream
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		if str.itl.isEmpty() {
 			str.state = empty
 		} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
@@ -971,8 +997,8 @@ func (l *loopyWriter) processData() (bool, error) {
 	}
 	// Compute how much of the header and data we can send within quota and max frame length
 	hSize := min(maxSize, len(dataItem.h))
-	dSize := min(maxSize-hSize, dataItem.reader.Remaining())
-	remainingBytes := len(dataItem.h) + dataItem.reader.Remaining() - hSize - dSize
+	dSize := min(maxSize-hSize, reader.Remaining())
+	remainingBytes := len(dataItem.h) + reader.Remaining() - hSize - dSize
 	size := hSize + dSize
 
 	var buf *[]byte
@@ -993,7 +1019,7 @@ func (l *loopyWriter) processData() (bool, error) {
 		defer pool.Put(buf)
 
 		copy((*buf)[:hSize], dataItem.h)
-		_, _ = dataItem.reader.Read((*buf)[hSize:])
+		_, _ = reader.Read((*buf)[hSize:])
 	}
 
 	// Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1014,7 +1040,7 @@ func (l *loopyWriter) processData() (bool, error) {
 	dataItem.h = dataItem.h[hSize:]
 
 	if remainingBytes == 0 { // All the data from that message was written out.
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		str.itl.dequeue()
 	}
 	if str.itl.isEmpty() {
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 3dea2357..d954a64c 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -277,11 +277,13 @@ func (ht *serverHandlerTransport) writeStatus(s *ServerStream, st *status.Status
 	if err == nil { // transport has not been closed
 		// Note: The trailer fields are compressed with hpack after this call returns.
 		// No WireLength field is set here.
+		s.hdrMu.Lock()
 		for _, sh := range ht.stats {
 			sh.HandleRPC(s.Context(), &stats.OutTrailer{
 				Trailer: s.trailer.Copy(),
 			})
 		}
+		s.hdrMu.Unlock()
 	}
 	ht.Close(errors.New("finished writing status"))
 	return err
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index ef56592b..5467fe97 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -309,11 +309,9 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 			scheme = "https"
 		}
 	}
-	dynamicWindow := true
 	icwz := int32(initialWindowSize)
 	if opts.InitialConnWindowSize >= defaultWindowSize {
 		icwz = opts.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	writeBufSize := opts.WriteBufferSize
 	readBufSize := opts.ReadBufferSize
@@ -381,9 +379,8 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 	t.controlBuf = newControlBuffer(t.ctxDone)
 	if opts.InitialWindowSize >= defaultWindowSize {
 		t.initialWindowSize = opts.InitialWindowSize
-		dynamicWindow = false
 	}
-	if dynamicWindow {
+	if !opts.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -1091,32 +1088,29 @@ func (t *http2Client) GracefulClose() {
 // Write formats the data into HTTP2 data frame(s) and sends it out. The caller
 // should proceed only if Write returns nil.
 func (t *http2Client) write(s *ClientStream, hdr []byte, data mem.BufferSlice, opts *WriteOptions) error {
-	reader := data.Reader()
-
 	if opts.Last {
 		// If it's the last message, update stream state.
 		if !s.compareAndSwapState(streamActive, streamWriteDone) {
-			_ = reader.Close()
 			return errStreamDone
 		}
 	} else if s.getState() != streamActive {
-		_ = reader.Close()
 		return errStreamDone
 	}
 	df := &dataFrame{
 		streamID:  s.id,
 		endStream: opts.Last,
 		h:         hdr,
-		reader:    reader,
+		data:      data,
 	}
-	if hdr != nil || df.reader.Remaining() != 0 { // If it's not an empty data frame, check quota.
-		if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-			_ = reader.Close()
+	dataLen := data.Len()
+	if hdr != nil || dataLen != 0 { // If it's not an empty data frame, check quota.
+		if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 			return err
 		}
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index e4c3731b..83cee314 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -132,6 +132,10 @@ type http2Server struct {
 	maxStreamID uint32 // max stream ID ever seen
 
 	logger *grpclog.PrefixLogger
+	// setResetPingStrikes is stored as a closure instead of making this a
+	// method on http2Server to avoid a heap allocation when converting a method
+	// to a closure for passing to frames objects.
+	setResetPingStrikes func()
 }
 
 // NewServerTransport creates a http2 transport with conn and configuration
@@ -176,16 +180,13 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 			Val: config.MaxStreams,
 		})
 	}
-	dynamicWindow := true
 	iwz := int32(initialWindowSize)
 	if config.InitialWindowSize >= defaultWindowSize {
 		iwz = config.InitialWindowSize
-		dynamicWindow = false
 	}
 	icwz := int32(initialWindowSize)
 	if config.InitialConnWindowSize >= defaultWindowSize {
 		icwz = config.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	if iwz != defaultWindowSize {
 		isettings = append(isettings, http2.Setting{
@@ -266,6 +267,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		initialWindowSize: iwz,
 		bufferPool:        config.BufferPool,
 	}
+	t.setResetPingStrikes = func() {
+		atomic.StoreUint32(&t.resetPingStrikes, 1)
+	}
 	var czSecurity credentials.ChannelzSecurityValue
 	if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok {
 		czSecurity = au.GetSecurityValue()
@@ -285,7 +289,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 	t.logger = prefixLoggerForServerTransport(t)
 
 	t.controlBuf = newControlBuffer(t.done)
-	if dynamicWindow {
+	if !config.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -596,10 +600,25 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
 			return nil
 		}
 	}
+
+	if s.ctx.Err() != nil {
+		t.mu.Unlock()
+		// Early abort in case the timeout was zero or so low it already fired.
+		t.controlBuf.put(&earlyAbortStream{
+			httpStatus:     http.StatusOK,
+			streamID:       s.id,
+			contentSubtype: s.contentSubtype,
+			status:         status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()),
+			rst:            !frame.StreamEnded(),
+		})
+		return nil
+	}
+
 	t.activeStreams[streamID] = s
 	if len(t.activeStreams) == 1 {
 		t.idle = time.Time{}
 	}
+
 	// Start a timer to close the stream on reaching the deadline.
 	if timeoutSet {
 		// We need to wait for s.cancel to be updated before calling
@@ -1016,10 +1035,6 @@ func (t *http2Server) writeHeader(s *ServerStream, md metadata.MD) error {
 	return nil
 }
 
-func (t *http2Server) setResetPingStrikes() {
-	atomic.StoreUint32(&t.resetPingStrikes, 1)
-}
-
 func (t *http2Server) writeHeaderLocked(s *ServerStream) error {
 	// TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
 	// first and create a slice of that exact size.
@@ -1132,17 +1147,13 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error {
 // Write converts the data into HTTP2 data frame and sends it out. Non-nil error
 // is returns if it fails (e.g., framing error, transport error).
 func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _ *WriteOptions) error {
-	reader := data.Reader()
-
 	if !s.isHeaderSent() { // Headers haven't been written yet.
 		if err := t.writeHeader(s, nil); err != nil {
-			_ = reader.Close()
 			return err
 		}
 	} else {
 		// Writing headers checks for this condition.
 		if s.getState() == streamDone {
-			_ = reader.Close()
 			return t.streamContextErr(s)
 		}
 	}
@@ -1150,15 +1161,16 @@ func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _
 	df := &dataFrame{
 		streamID:    s.id,
 		h:           hdr,
-		reader:      reader,
+		data:        data,
 		onEachWrite: t.setResetPingStrikes,
 	}
-	if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-		_ = reader.Close()
+	dataLen := data.Len()
+	if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 		return t.streamContextErr(s)
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
@@ -1341,10 +1353,10 @@ func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCo
 	// called to interrupt the potential blocking on other goroutines.
 	s.cancel()
 
-	oldState := s.swapState(streamDone)
-	if oldState == streamDone {
-		return
-	}
+	// We can't return early even if the stream's state is "done" as the state
+	// might have been set by the `finishStream` method. Deleting the stream via
+	// `finishStream` can get blocked on flow control.
+	s.swapState(streamDone)
 	t.deleteStream(s, eosReceived)
 
 	t.controlBuf.put(&cleanupStream{
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/http_util.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 607d2c4c..e3663f87 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/http_util.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -200,9 +200,6 @@ func decodeTimeout(s string) (time.Duration, error) {
 	if err != nil {
 		return 0, err
 	}
-	if t == 0 {
-		return 0, fmt.Errorf("transport: timeout must be positive: %q", s)
-	}
 	const maxHours = math.MaxInt64 / uint64(time.Hour)
 	if d == time.Hour && t > maxHours {
 		// This timeout would overflow math.MaxInt64; clamp it.
diff --git a/event-processor/vendor/google.golang.org/grpc/internal/transport/transport.go b/event-processor/vendor/google.golang.org/grpc/internal/transport/transport.go
index 1730a639..7dd53e80 100644
--- a/event-processor/vendor/google.golang.org/grpc/internal/transport/transport.go
+++ b/event-processor/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -466,6 +466,7 @@ type ServerConfig struct {
 	MaxHeaderListSize     *uint32
 	HeaderTableSize       *uint32
 	BufferPool            mem.BufferPool
+	StaticWindowSize      bool
 }
 
 // ConnectOptions covers all relevant options for communicating with the server.
@@ -504,6 +505,8 @@ type ConnectOptions struct {
 	MaxHeaderListSize *uint32
 	// The mem.BufferPool to use when reading/writing to the wire.
 	BufferPool mem.BufferPool
+	// StaticWindowSize controls whether dynamic window sizing is enabled.
+	StaticWindowSize bool
 }
 
 // WriteOptions provides additional hints and information for message
diff --git a/event-processor/vendor/google.golang.org/grpc/mem/buffer_slice.go b/event-processor/vendor/google.golang.org/grpc/mem/buffer_slice.go
index 65002e2c..af510d20 100644
--- a/event-processor/vendor/google.golang.org/grpc/mem/buffer_slice.go
+++ b/event-processor/vendor/google.golang.org/grpc/mem/buffer_slice.go
@@ -137,6 +137,9 @@ type Reader interface {
 	Close() error
 	// Remaining returns the number of unread bytes remaining in the slice.
 	Remaining() int
+	// Reset frees the currently held buffer slice and starts reading from the
+	// provided slice. This allows reusing the reader object.
+	Reset(s BufferSlice)
 }
 
 type sliceReader struct {
@@ -150,6 +153,14 @@ func (r *sliceReader) Remaining() int {
 	return r.len
 }
 
+func (r *sliceReader) Reset(s BufferSlice) {
+	r.data.Free()
+	s.Ref()
+	r.data = s
+	r.len = s.Len()
+	r.bufferIdx = 0
+}
+
 func (r *sliceReader) Close() error {
 	r.data.Free()
 	r.data = nil
diff --git a/event-processor/vendor/google.golang.org/grpc/picker_wrapper.go b/event-processor/vendor/google.golang.org/grpc/picker_wrapper.go
index a2d2a798..aa52bfe9 100644
--- a/event-processor/vendor/google.golang.org/grpc/picker_wrapper.go
+++ b/event-processor/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -29,7 +29,6 @@ import (
 	"google.golang.org/grpc/internal/channelz"
 	istatus "google.golang.org/grpc/internal/status"
 	"google.golang.org/grpc/internal/transport"
-	"google.golang.org/grpc/stats"
 	"google.golang.org/grpc/status"
 )
 
@@ -48,14 +47,11 @@ type pickerGeneration struct {
 // actions and unblock when there's a picker update.
 type pickerWrapper struct {
 	// If pickerGen holds a nil pointer, the pickerWrapper is closed.
-	pickerGen     atomic.Pointer[pickerGeneration]
-	statsHandlers []stats.Handler // to record blocking picker calls
+	pickerGen atomic.Pointer[pickerGeneration]
 }
 
-func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
-	pw := &pickerWrapper{
-		statsHandlers: statsHandlers,
-	}
+func newPickerWrapper() *pickerWrapper {
+	pw := &pickerWrapper{}
 	pw.pickerGen.Store(&pickerGeneration{
 		blockingCh: make(chan struct{}),
 	})
@@ -93,6 +89,12 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 	}
 }
 
+type pick struct {
+	transport transport.ClientTransport // the selected transport
+	result    balancer.PickResult       // the contents of the pick from the LB policy
+	blocked   bool                      // set if a picker call queued for a new picker
+}
+
 // pick returns the transport that will be used for the RPC.
 // It may block in the following cases:
 // - there's no picker
@@ -100,15 +102,16 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 // - the current picker returns other errors and failfast is false.
 // - the subConn returned by the current picker is not READY
 // When one of these situations happens, pick blocks until the picker gets updated.
-func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
+func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (pick, error) {
 	var ch chan struct{}
 
 	var lastPickErr error
+	pickBlocked := false
 
 	for {
 		pg := pw.pickerGen.Load()
 		if pg == nil {
-			return nil, balancer.PickResult{}, ErrClientConnClosing
+			return pick{}, ErrClientConnClosing
 		}
 		if pg.picker == nil {
 			ch = pg.blockingCh
@@ -127,9 +130,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				}
 				switch ctx.Err() {
 				case context.DeadlineExceeded:
-					return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
+					return pick{}, status.Error(codes.DeadlineExceeded, errStr)
 				case context.Canceled:
-					return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
+					return pick{}, status.Error(codes.Canceled, errStr)
 				}
 			case <-ch:
 			}
@@ -145,9 +148,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		// In the second case, the only way it will get to this conditional is
 		// if there is a new picker.
 		if ch != nil {
-			for _, sh := range pw.statsHandlers {
-				sh.HandleRPC(ctx, &stats.PickerUpdated{})
-			}
+			pickBlocked = true
 		}
 
 		ch = pg.blockingCh
@@ -164,7 +165,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				if istatus.IsRestrictedControlPlaneCode(st) {
 					err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
 				}
-				return nil, balancer.PickResult{}, dropError{error: err}
+				return pick{}, dropError{error: err}
 			}
 			// For all other errors, wait for ready RPCs should block and other
 			// RPCs should fail with unavailable.
@@ -172,7 +173,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				lastPickErr = err
 				continue
 			}
-			return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
+			return pick{}, status.Error(codes.Unavailable, err.Error())
 		}
 
 		acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
@@ -183,9 +184,8 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		if t := acbw.ac.getReadyTransport(); t != nil {
 			if channelz.IsOn() {
 				doneChannelzWrapper(acbw, &pickResult)
-				return t, pickResult, nil
 			}
-			return t, pickResult, nil
+			return pick{transport: t, result: pickResult, blocked: pickBlocked}, nil
 		}
 		if pickResult.Done != nil {
 			// Calling done with nil error, no bytes sent and no bytes received.
diff --git a/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
index 03108280..f4a361c6 100644
--- a/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
+++ b/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
@@ -90,7 +90,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
index 80755d74..0a43b521 100644
--- a/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
+++ b/event-processor/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
@@ -87,7 +87,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/event-processor/vendor/google.golang.org/grpc/resolver/resolver.go b/event-processor/vendor/google.golang.org/grpc/resolver/resolver.go
index b84ef26d..8e6af951 100644
--- a/event-processor/vendor/google.golang.org/grpc/resolver/resolver.go
+++ b/event-processor/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -332,6 +332,11 @@ type AuthorityOverrider interface {
 	// OverrideAuthority returns the authority to use for a ClientConn with the
 	// given target. The implementation must generate it without blocking,
 	// typically in line, and must keep it unchanged.
+	//
+	// The returned string must be a valid ":authority" header value, i.e. be
+	// encoded according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
+	// necessary.
 	OverrideAuthority(Target) string
 }
 
diff --git a/event-processor/vendor/google.golang.org/grpc/server.go b/event-processor/vendor/google.golang.org/grpc/server.go
index 976e70ae..1da2a542 100644
--- a/event-processor/vendor/google.golang.org/grpc/server.go
+++ b/event-processor/vendor/google.golang.org/grpc/server.go
@@ -179,6 +179,7 @@ type serverOptions struct {
 	numServerWorkers      uint32
 	bufferPool            mem.BufferPool
 	waitForHandlers       bool
+	staticWindowSize      bool
 }
 
 var defaultServerOptions = serverOptions{
@@ -279,6 +280,7 @@ func ReadBufferSize(s int) ServerOption {
 func InitialWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -287,6 +289,29 @@ func InitialWindowSize(s int32) ServerOption {
 func InitialConnWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialConnWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticStreamWindowSize returns a ServerOption to set the initial stream
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticStreamWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticConnWindowSize returns a ServerOption to set the initial connection
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticConnWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialConnWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -986,6 +1011,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
 		MaxHeaderListSize:     s.opts.maxHeaderListSize,
 		HeaderTableSize:       s.opts.headerTableSize,
 		BufferPool:            s.opts.bufferPool,
+		StaticWindowSize:      s.opts.staticWindowSize,
 	}
 	st, err := transport.NewServerTransport(c, config)
 	if err != nil {
@@ -1572,6 +1598,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv
 		s:                     stream,
 		p:                     &parser{r: stream, bufferPool: s.opts.bufferPool},
 		codec:                 s.getCodec(stream.ContentSubtype()),
+		desc:                  sd,
 		maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
 		maxSendMessageSize:    s.opts.maxSendMessageSize,
 		trInfo:                trInfo,
diff --git a/event-processor/vendor/google.golang.org/grpc/stats/stats.go b/event-processor/vendor/google.golang.org/grpc/stats/stats.go
index baf7740e..10bf998a 100644
--- a/event-processor/vendor/google.golang.org/grpc/stats/stats.go
+++ b/event-processor/vendor/google.golang.org/grpc/stats/stats.go
@@ -64,15 +64,21 @@ func (s *Begin) IsClient() bool { return s.Client }
 
 func (s *Begin) isRPCStats() {}
 
-// PickerUpdated indicates that the LB policy provided a new picker while the
-// RPC was waiting for one.
-type PickerUpdated struct{}
+// DelayedPickComplete indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+type DelayedPickComplete struct{}
 
-// IsClient indicates if the stats information is from client side. Only Client
-// Side interfaces with a Picker, thus always returns true.
-func (*PickerUpdated) IsClient() bool { return true }
+// IsClient indicates DelayedPickComplete is available on the client.
+func (*DelayedPickComplete) IsClient() bool { return true }
 
-func (*PickerUpdated) isRPCStats() {}
+func (*DelayedPickComplete) isRPCStats() {}
+
+// PickerUpdated indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+//
+// Deprecated: will be removed in a future release; use DelayedPickComplete
+// instead.
+type PickerUpdated = DelayedPickComplete
 
 // InPayload contains stats about an incoming payload.
 type InPayload struct {
diff --git a/event-processor/vendor/google.golang.org/grpc/stream.go b/event-processor/vendor/google.golang.org/grpc/stream.go
index d58bb647..d9bbd4c5 100644
--- a/event-processor/vendor/google.golang.org/grpc/stream.go
+++ b/event-processor/vendor/google.golang.org/grpc/stream.go
@@ -469,8 +469,9 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error)
 func (a *csAttempt) getTransport() error {
 	cs := a.cs
 
-	var err error
-	a.transport, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method)
+	pickInfo := balancer.PickInfo{Ctx: a.ctx, FullMethodName: cs.callHdr.Method}
+	pick, err := cs.cc.pickerWrapper.pick(a.ctx, cs.callInfo.failFast, pickInfo)
+	a.transport, a.pickResult = pick.transport, pick.result
 	if err != nil {
 		if de, ok := err.(dropError); ok {
 			err = de.error
@@ -481,6 +482,11 @@ func (a *csAttempt) getTransport() error {
 	if a.trInfo != nil {
 		a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr())
 	}
+	if pick.blocked {
+		for _, sh := range a.statsHandlers {
+			sh.HandleRPC(a.ctx, &stats.DelayedPickComplete{})
+		}
+	}
 	return nil
 }
 
@@ -1171,7 +1177,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (a *csAttempt) finish(err error) {
@@ -1495,7 +1501,7 @@ func (as *addrConnStream) RecvMsg(m any) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (as *addrConnStream) finish(err error) {
@@ -1580,6 +1586,7 @@ type serverStream struct {
 	s     *transport.ServerStream
 	p     *parser
 	codec baseCodec
+	desc  *StreamDesc
 
 	compressorV0   Compressor
 	compressorV1   encoding.Compressor
@@ -1588,6 +1595,8 @@ type serverStream struct {
 
 	sendCompressorName string
 
+	recvFirstMsg bool // set after the first message is received
+
 	maxReceiveMessageSize int
 	maxSendMessageSize    int
 	trInfo                *traceInfo
@@ -1774,6 +1783,10 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 					binlog.Log(ss.ctx, chc)
 				}
 			}
+			// Received no request msg for non-client streaming rpcs.
+			if !ss.desc.ClientStreams && !ss.recvFirstMsg {
+				return status.Error(codes.Internal, "cardinality violation: received no request message from non-client-streaming RPC")
+			}
 			return err
 		}
 		if err == io.ErrUnexpectedEOF {
@@ -1781,6 +1794,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 		}
 		return toRPCErr(err)
 	}
+	ss.recvFirstMsg = true
 	if len(ss.statsHandler) != 0 {
 		for _, sh := range ss.statsHandler {
 			sh.HandleRPC(ss.s.Context(), &stats.InPayload{
@@ -1800,7 +1814,19 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 			binlog.Log(ss.ctx, cm)
 		}
 	}
-	return nil
+
+	if ss.desc.ClientStreams {
+		// Subsequent messages should be received by subsequent RecvMsg calls.
+		return nil
+	}
+	// Special handling for non-client-stream rpcs.
+	// This recv expects EOF or errors, so we don't collect inPayload.
+	if err := recv(ss.p, ss.codec, ss.s, ss.decompressorV0, m, ss.maxReceiveMessageSize, nil, ss.decompressorV1, true); err == io.EOF {
+		return nil
+	} else if err != nil {
+		return err
+	}
+	return status.Error(codes.Internal, "cardinality violation: received multiple request messages for non-client-streaming RPC")
 }
 
 // MethodFromServerStream returns the method string for the input stream.
diff --git a/event-processor/vendor/google.golang.org/grpc/version.go b/event-processor/vendor/google.golang.org/grpc/version.go
index bd82673d..468f1106 100644
--- a/event-processor/vendor/google.golang.org/grpc/version.go
+++ b/event-processor/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.73.0"
+const Version = "1.75.1"
diff --git a/event-processor/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go b/event-processor/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
index 999a2515..45749edd 100644
--- a/event-processor/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
+++ b/event-processor/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
@@ -11,6 +11,7 @@ import (
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/reflect/protoreflect"
 
@@ -279,8 +280,7 @@ func isLazy(field *protogen.Field) bool {
 	}
 
 	// Was the field marked as [lazy = true] in the .proto file?
-	fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
-	return fopts.GetLazy()
+	return field.Desc.(interface{ IsLazy() bool }).IsLazy()
 }
 
 // opaqueGenGet generates a Get method for a field.
@@ -573,16 +573,8 @@ func usePresence(message *messageInfo, field *protogen.Field) bool {
 	if !message.isOpaque() {
 		return false
 	}
-	return opaqueFieldNeedsPresenceArray(message, field)
-}
-
-func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
-	// Non optional fields need presence if truly lazy field, i.e. are message fields.
-	if isLazy(field) {
-		return true
-	}
-	isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
-	return field.Desc.HasPresence() && field.Message == nil && isNotOneof
+	usePresence, _ := filedesc.UsePresenceForField(field.Desc)
+	return usePresence
 }
 
 // opaqueGenHas generates a Has method for a field.
@@ -832,7 +824,7 @@ func opaqueNeedsPresenceArray(message *messageInfo) bool {
 		return false
 	}
 	for _, field := range message.Fields {
-		if opaqueFieldNeedsPresenceArray(message, field) {
+		if usePresence, _ := filedesc.UsePresenceForField(field.Desc); usePresence {
 			return true
 		}
 	}
diff --git a/event-processor/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/event-processor/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
index e942bc98..743bfb81 100644
--- a/event-processor/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
+++ b/event-processor/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
@@ -371,7 +371,31 @@ func ConsumeVarint(b []byte) (v uint64, n int) {
 func SizeVarint(v uint64) int {
 	// This computes 1 + (bits.Len64(v)-1)/7.
 	// 9/64 is a good enough approximation of 1/7
-	return int(9*uint32(bits.Len64(v))+64) / 64
+	//
+	// The Go compiler can translate the bits.LeadingZeros64 call into the LZCNT
+	// instruction, which is very fast on CPUs from the last few years. The
+	// specific way of expressing the calculation matches C++ Protobuf, see
+	// https://godbolt.org/z/4P3h53oM4 for the C++ code and how gcc/clang
+	// optimize that function for GOAMD64=v1 and GOAMD64=v3 (-march=haswell).
+
+	// By OR'ing v with 1, we guarantee that v is never 0, without changing the
+	// result of SizeVarint. LZCNT is not defined for 0, meaning the compiler
+	// needs to add extra instructions to handle that case.
+	//
+	// The Go compiler currently (go1.24.4) does not make use of this knowledge.
+	// This opportunity (removing the XOR instruction, which handles the 0 case)
+	// results in a small (1%) performance win across CPU architectures.
+	//
+	// Independently of avoiding the 0 case, we need the v |= 1 line because
+	// it allows the Go compiler to eliminate an extra XCHGL barrier.
+	v |= 1
+
+	// It would be clearer to write log2value := 63 - uint32(...), but
+	// writing uint32(...) ^ 63 is much more efficient (-14% ARM, -20% Intel).
+	// Proof of identity for our value range [0..63]:
+	// https://go.dev/play/p/Pdn9hEWYakX
+	log2value := uint32(bits.LeadingZeros64(v)) ^ 63
+	return int((log2value*9 + (64 + 9)) / 64)
 }
 
 // AppendFixed32 appends v to b as a little-endian uint32.
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/event-processor/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb
index 323829da..04696351 100644
Binary files a/event-processor/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb and b/event-processor/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb differ
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/event-processor/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
index bf1aba0e..7b9f01af 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
@@ -9,7 +9,7 @@ import "google.golang.org/protobuf/types/descriptorpb"
 
 const (
 	Minimum = descriptorpb.Edition_EDITION_PROTO2
-	Maximum = descriptorpb.Edition_EDITION_2023
+	Maximum = descriptorpb.Edition_EDITION_2024
 
 	// MaximumKnown is the maximum edition that is known to Go Protobuf, but not
 	// declared as supported. In other words: end users cannot use it, but
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 688aabe4..dbcf90b8 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -72,9 +72,10 @@ type (
 		EditionFeatures EditionFeatures
 	}
 	FileL2 struct {
-		Options   func() protoreflect.ProtoMessage
-		Imports   FileImports
-		Locations SourceLocations
+		Options       func() protoreflect.ProtoMessage
+		Imports       FileImports
+		OptionImports func() protoreflect.FileImports
+		Locations     SourceLocations
 	}
 
 	// EditionFeatures is a frequently-instantiated struct, so please take care
@@ -126,12 +127,9 @@ func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
 func (fd *File) Parent() protoreflect.Descriptor         { return nil }
 func (fd *File) Index() int                              { return 0 }
 func (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }
-
-// Not exported and just used to reconstruct the original FileDescriptor proto
-func (fd *File) Edition() int32                  { return int32(fd.L1.Edition) }
-func (fd *File) Name() protoreflect.Name         { return fd.L1.Package.Name() }
-func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
-func (fd *File) IsPlaceholder() bool             { return false }
+func (fd *File) Name() protoreflect.Name                 { return fd.L1.Package.Name() }
+func (fd *File) FullName() protoreflect.FullName         { return fd.L1.Package }
+func (fd *File) IsPlaceholder() bool                     { return false }
 func (fd *File) Options() protoreflect.ProtoMessage {
 	if f := fd.lazyInit().Options; f != nil {
 		return f()
@@ -150,6 +148,16 @@ func (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatD
 func (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
 func (fd *File) ProtoInternal(pragma.DoNotImplement)           {}
 
+// The next two are not part of the FileDescriptor interface. They are just used to reconstruct
+// the original FileDescriptor proto.
+func (fd *File) Edition() int32 { return int32(fd.L1.Edition) }
+func (fd *File) OptionImports() protoreflect.FileImports {
+	if f := fd.lazyInit().OptionImports; f != nil {
+		return f()
+	}
+	return emptyFiles
+}
+
 func (fd *File) lazyInit() *FileL2 {
 	if atomic.LoadUint32(&fd.once) == 0 {
 		fd.lazyInitOnce()
@@ -182,9 +190,9 @@ type (
 		L2 *EnumL2 // protected by fileDesc.once
 	}
 	EnumL1 struct {
-		eagerValues bool // controls whether EnumL2.Values is already populated
-
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		eagerValues     bool // controls whether EnumL2.Values is already populated
 	}
 	EnumL2 struct {
 		Options        func() protoreflect.ProtoMessage
@@ -219,6 +227,11 @@ func (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit()
 func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
 func (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
 func (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
+
+// This is not part of the EnumDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (ed *Enum) Visibility() int32 { return ed.L1.Visibility }
+
 func (ed *Enum) lazyInit() *EnumL2 {
 	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return ed.L2
@@ -244,13 +257,13 @@ type (
 		L2 *MessageL2 // protected by fileDesc.once
 	}
 	MessageL1 struct {
-		Enums        Enums
-		Messages     Messages
-		Extensions   Extensions
-		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
-		IsMessageSet bool // promoted from google.protobuf.MessageOptions
-
+		Enums           Enums
+		Messages        Messages
+		Extensions      Extensions
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		IsMapEntry      bool // promoted from google.protobuf.MessageOptions
+		IsMessageSet    bool // promoted from google.protobuf.MessageOptions
 	}
 	MessageL2 struct {
 		Options               func() protoreflect.ProtoMessage
@@ -319,6 +332,11 @@ func (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L
 func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
 func (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
 func (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
+
+// This is not part of the MessageDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (md *Message) Visibility() int32 { return md.L1.Visibility }
+
 func (md *Message) lazyInit() *MessageL2 {
 	md.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return md.L2
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
index d2f54949..e91860f5 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
@@ -284,6 +284,13 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protorefl
 			case genid.EnumDescriptorProto_Value_field_number:
 				numValues++
 			}
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.EnumDescriptorProto_Visibility_field_number:
+				ed.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
@@ -365,6 +372,13 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
 				md.unmarshalSeedOptions(v)
 			}
 			prevField = num
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.DescriptorProto_Visibility_field_number:
+				md.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index d4c94458..dd31faae 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -134,6 +134,7 @@ func (fd *File) unmarshalFull(b []byte) {
 
 	var enumIdx, messageIdx, extensionIdx, serviceIdx int
 	var rawOptions []byte
+	var optionImports []string
 	fd.L2 = new(FileL2)
 	for len(b) > 0 {
 		num, typ, n := protowire.ConsumeTag(b)
@@ -157,6 +158,8 @@ func (fd *File) unmarshalFull(b []byte) {
 					imp = PlaceholderFile(path)
 				}
 				fd.L2.Imports = append(fd.L2.Imports, protoreflect.FileImport{FileDescriptor: imp})
+			case genid.FileDescriptorProto_OptionDependency_field_number:
+				optionImports = append(optionImports, sb.MakeString(v))
 			case genid.FileDescriptorProto_EnumType_field_number:
 				fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
 				enumIdx++
@@ -178,6 +181,23 @@ func (fd *File) unmarshalFull(b []byte) {
 		}
 	}
 	fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
+	if len(optionImports) > 0 {
+		var imps FileImports
+		var once sync.Once
+		fd.L2.OptionImports = func() protoreflect.FileImports {
+			once.Do(func() {
+				imps = make(FileImports, len(optionImports))
+				for i, path := range optionImports {
+					imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
+					if imp == nil {
+						imp = PlaceholderFile(path)
+					}
+					imps[i] = protoreflect.FileImport{FileDescriptor: imp}
+				}
+			})
+			return &imps
+		}
+	}
 }
 
 func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
index b08b7183..66ba9068 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
@@ -13,8 +13,10 @@ import (
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
-var defaultsCache = make(map[Edition]EditionFeatures)
-var defaultsKeys = []Edition{}
+var (
+	defaultsCache = make(map[Edition]EditionFeatures)
+	defaultsKeys  = []Edition{}
+)
 
 func init() {
 	unmarshalEditionDefaults(editiondefaults.Defaults)
@@ -41,7 +43,7 @@ func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
 			b = b[m:]
 			parent.StripEnumPrefix = int(v)
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling GoFeatures", num))
 		}
 	}
 	return parent
@@ -72,8 +74,11 @@ func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
 			case genid.FeatureSet_EnforceNamingStyle_field_number:
 				// EnforceNamingStyle is enforced in protoc, languages other than C++
 				// are not supposed to do anything with this feature.
+			case genid.FeatureSet_DefaultSymbolVisibility_field_number:
+				// DefaultSymbolVisibility is enforced in protoc, runtimes should not
+				// inspect this value.
 			default:
-				panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
+				panic(fmt.Sprintf("unknown field number %d while unmarshalling FeatureSet", num))
 			}
 		case protowire.BytesType:
 			v, m := protowire.ConsumeBytes(b)
@@ -147,7 +152,7 @@ func unmarshalEditionDefaults(b []byte) {
 			_, m := protowire.ConsumeVarint(b)
 			b = b[m:]
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling EditionDefault", num))
 		}
 	}
 }
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/presence.go b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
new file mode 100644
index 00000000..a12ec979
--- /dev/null
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
@@ -0,0 +1,33 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package filedesc
+
+import "google.golang.org/protobuf/reflect/protoreflect"
+
+// UsePresenceForField reports whether the presence bitmap should be used for
+// the specified field.
+func UsePresenceForField(fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
+	switch {
+	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
+		// Oneof fields never use the presence bitmap.
+		//
+		// Synthetic oneofs are an exception: Those are used to implement proto3
+		// optional fields and hence should follow non-oneof field semantics.
+		return false, false
+
+	case fd.IsMap():
+		// Map-typed fields never use the presence bitmap.
+		return false, false
+
+	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
+		// Lazy fields always use the presence bitmap (only messages can be lazy).
+		isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
+		return isLazy, isLazy
+
+	default:
+		// If the field has presence, use the presence bitmap.
+		return fd.HasPresence(), false
+	}
+}
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/genid/api_gen.go b/event-processor/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
index df8f9185..3ceb6fa7 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
@@ -27,6 +27,7 @@ const (
 	Api_SourceContext_field_name protoreflect.Name = "source_context"
 	Api_Mixins_field_name        protoreflect.Name = "mixins"
 	Api_Syntax_field_name        protoreflect.Name = "syntax"
+	Api_Edition_field_name       protoreflect.Name = "edition"
 
 	Api_Name_field_fullname          protoreflect.FullName = "google.protobuf.Api.name"
 	Api_Methods_field_fullname       protoreflect.FullName = "google.protobuf.Api.methods"
@@ -35,6 +36,7 @@ const (
 	Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context"
 	Api_Mixins_field_fullname        protoreflect.FullName = "google.protobuf.Api.mixins"
 	Api_Syntax_field_fullname        protoreflect.FullName = "google.protobuf.Api.syntax"
+	Api_Edition_field_fullname       protoreflect.FullName = "google.protobuf.Api.edition"
 )
 
 // Field numbers for google.protobuf.Api.
@@ -46,6 +48,7 @@ const (
 	Api_SourceContext_field_number protoreflect.FieldNumber = 5
 	Api_Mixins_field_number        protoreflect.FieldNumber = 6
 	Api_Syntax_field_number        protoreflect.FieldNumber = 7
+	Api_Edition_field_number       protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Method.
@@ -63,6 +66,7 @@ const (
 	Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming"
 	Method_Options_field_name           protoreflect.Name = "options"
 	Method_Syntax_field_name            protoreflect.Name = "syntax"
+	Method_Edition_field_name           protoreflect.Name = "edition"
 
 	Method_Name_field_fullname              protoreflect.FullName = "google.protobuf.Method.name"
 	Method_RequestTypeUrl_field_fullname    protoreflect.FullName = "google.protobuf.Method.request_type_url"
@@ -71,6 +75,7 @@ const (
 	Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming"
 	Method_Options_field_fullname           protoreflect.FullName = "google.protobuf.Method.options"
 	Method_Syntax_field_fullname            protoreflect.FullName = "google.protobuf.Method.syntax"
+	Method_Edition_field_fullname           protoreflect.FullName = "google.protobuf.Method.edition"
 )
 
 // Field numbers for google.protobuf.Method.
@@ -82,6 +87,7 @@ const (
 	Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5
 	Method_Options_field_number           protoreflect.FieldNumber = 6
 	Method_Syntax_field_number            protoreflect.FieldNumber = 7
+	Method_Edition_field_number           protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Mixin.
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/event-processor/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
index 39524782..950a6a32 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
@@ -34,6 +34,19 @@ const (
 	Edition_EDITION_MAX_enum_value             = 2147483647
 )
 
+// Full and short names for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_enum_fullname = "google.protobuf.SymbolVisibility"
+	SymbolVisibility_enum_name     = "SymbolVisibility"
+)
+
+// Enum values for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_VISIBILITY_UNSET_enum_value  = 0
+	SymbolVisibility_VISIBILITY_LOCAL_enum_value  = 1
+	SymbolVisibility_VISIBILITY_EXPORT_enum_value = 2
+)
+
 // Names for google.protobuf.FileDescriptorSet.
 const (
 	FileDescriptorSet_message_name     protoreflect.Name     = "FileDescriptorSet"
@@ -65,6 +78,7 @@ const (
 	FileDescriptorProto_Dependency_field_name       protoreflect.Name = "dependency"
 	FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency"
 	FileDescriptorProto_WeakDependency_field_name   protoreflect.Name = "weak_dependency"
+	FileDescriptorProto_OptionDependency_field_name protoreflect.Name = "option_dependency"
 	FileDescriptorProto_MessageType_field_name      protoreflect.Name = "message_type"
 	FileDescriptorProto_EnumType_field_name         protoreflect.Name = "enum_type"
 	FileDescriptorProto_Service_field_name          protoreflect.Name = "service"
@@ -79,6 +93,7 @@ const (
 	FileDescriptorProto_Dependency_field_fullname       protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency"
 	FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency"
 	FileDescriptorProto_WeakDependency_field_fullname   protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency"
+	FileDescriptorProto_OptionDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.option_dependency"
 	FileDescriptorProto_MessageType_field_fullname      protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type"
 	FileDescriptorProto_EnumType_field_fullname         protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type"
 	FileDescriptorProto_Service_field_fullname          protoreflect.FullName = "google.protobuf.FileDescriptorProto.service"
@@ -96,6 +111,7 @@ const (
 	FileDescriptorProto_Dependency_field_number       protoreflect.FieldNumber = 3
 	FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10
 	FileDescriptorProto_WeakDependency_field_number   protoreflect.FieldNumber = 11
+	FileDescriptorProto_OptionDependency_field_number protoreflect.FieldNumber = 15
 	FileDescriptorProto_MessageType_field_number      protoreflect.FieldNumber = 4
 	FileDescriptorProto_EnumType_field_number         protoreflect.FieldNumber = 5
 	FileDescriptorProto_Service_field_number          protoreflect.FieldNumber = 6
@@ -124,6 +140,7 @@ const (
 	DescriptorProto_Options_field_name        protoreflect.Name = "options"
 	DescriptorProto_ReservedRange_field_name  protoreflect.Name = "reserved_range"
 	DescriptorProto_ReservedName_field_name   protoreflect.Name = "reserved_name"
+	DescriptorProto_Visibility_field_name     protoreflect.Name = "visibility"
 
 	DescriptorProto_Name_field_fullname           protoreflect.FullName = "google.protobuf.DescriptorProto.name"
 	DescriptorProto_Field_field_fullname          protoreflect.FullName = "google.protobuf.DescriptorProto.field"
@@ -135,6 +152,7 @@ const (
 	DescriptorProto_Options_field_fullname        protoreflect.FullName = "google.protobuf.DescriptorProto.options"
 	DescriptorProto_ReservedRange_field_fullname  protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range"
 	DescriptorProto_ReservedName_field_fullname   protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name"
+	DescriptorProto_Visibility_field_fullname     protoreflect.FullName = "google.protobuf.DescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.DescriptorProto.
@@ -149,6 +167,7 @@ const (
 	DescriptorProto_Options_field_number        protoreflect.FieldNumber = 7
 	DescriptorProto_ReservedRange_field_number  protoreflect.FieldNumber = 9
 	DescriptorProto_ReservedName_field_number   protoreflect.FieldNumber = 10
+	DescriptorProto_Visibility_field_number     protoreflect.FieldNumber = 11
 )
 
 // Names for google.protobuf.DescriptorProto.ExtensionRange.
@@ -388,12 +407,14 @@ const (
 	EnumDescriptorProto_Options_field_name       protoreflect.Name = "options"
 	EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
 	EnumDescriptorProto_ReservedName_field_name  protoreflect.Name = "reserved_name"
+	EnumDescriptorProto_Visibility_field_name    protoreflect.Name = "visibility"
 
 	EnumDescriptorProto_Name_field_fullname          protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name"
 	EnumDescriptorProto_Value_field_fullname         protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value"
 	EnumDescriptorProto_Options_field_fullname       protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options"
 	EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range"
 	EnumDescriptorProto_ReservedName_field_fullname  protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name"
+	EnumDescriptorProto_Visibility_field_fullname    protoreflect.FullName = "google.protobuf.EnumDescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.EnumDescriptorProto.
@@ -403,6 +424,7 @@ const (
 	EnumDescriptorProto_Options_field_number       protoreflect.FieldNumber = 3
 	EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4
 	EnumDescriptorProto_ReservedName_field_number  protoreflect.FieldNumber = 5
+	EnumDescriptorProto_Visibility_field_number    protoreflect.FieldNumber = 6
 )
 
 // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
@@ -1008,32 +1030,35 @@ const (
 
 // Field names for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_name         protoreflect.Name = "field_presence"
-	FeatureSet_EnumType_field_name              protoreflect.Name = "enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_name        protoreflect.Name = "utf8_validation"
-	FeatureSet_MessageEncoding_field_name       protoreflect.Name = "message_encoding"
-	FeatureSet_JsonFormat_field_name            protoreflect.Name = "json_format"
-	FeatureSet_EnforceNamingStyle_field_name    protoreflect.Name = "enforce_naming_style"
-
-	FeatureSet_FieldPresence_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
-	FeatureSet_EnumType_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_fullname        protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
-	FeatureSet_MessageEncoding_field_fullname       protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
-	FeatureSet_JsonFormat_field_fullname            protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
-	FeatureSet_EnforceNamingStyle_field_fullname    protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_FieldPresence_field_name           protoreflect.Name = "field_presence"
+	FeatureSet_EnumType_field_name                protoreflect.Name = "enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_name   protoreflect.Name = "repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_name          protoreflect.Name = "utf8_validation"
+	FeatureSet_MessageEncoding_field_name         protoreflect.Name = "message_encoding"
+	FeatureSet_JsonFormat_field_name              protoreflect.Name = "json_format"
+	FeatureSet_EnforceNamingStyle_field_name      protoreflect.Name = "enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_name protoreflect.Name = "default_symbol_visibility"
+
+	FeatureSet_FieldPresence_field_fullname           protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
+	FeatureSet_EnumType_field_fullname                protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_fullname   protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_fullname          protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
+	FeatureSet_MessageEncoding_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
+	FeatureSet_JsonFormat_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
+	FeatureSet_EnforceNamingStyle_field_fullname      protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.default_symbol_visibility"
 )
 
 // Field numbers for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_number         protoreflect.FieldNumber = 1
-	FeatureSet_EnumType_field_number              protoreflect.FieldNumber = 2
-	FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
-	FeatureSet_Utf8Validation_field_number        protoreflect.FieldNumber = 4
-	FeatureSet_MessageEncoding_field_number       protoreflect.FieldNumber = 5
-	FeatureSet_JsonFormat_field_number            protoreflect.FieldNumber = 6
-	FeatureSet_EnforceNamingStyle_field_number    protoreflect.FieldNumber = 7
+	FeatureSet_FieldPresence_field_number           protoreflect.FieldNumber = 1
+	FeatureSet_EnumType_field_number                protoreflect.FieldNumber = 2
+	FeatureSet_RepeatedFieldEncoding_field_number   protoreflect.FieldNumber = 3
+	FeatureSet_Utf8Validation_field_number          protoreflect.FieldNumber = 4
+	FeatureSet_MessageEncoding_field_number         protoreflect.FieldNumber = 5
+	FeatureSet_JsonFormat_field_number              protoreflect.FieldNumber = 6
+	FeatureSet_EnforceNamingStyle_field_number      protoreflect.FieldNumber = 7
+	FeatureSet_DefaultSymbolVisibility_field_number protoreflect.FieldNumber = 8
 )
 
 // Full and short names for google.protobuf.FeatureSet.FieldPresence.
@@ -1128,6 +1153,27 @@ const (
 	FeatureSet_STYLE_LEGACY_enum_value                 = 2
 )
 
+// Names for google.protobuf.FeatureSet.VisibilityFeature.
+const (
+	FeatureSet_VisibilityFeature_message_name     protoreflect.Name     = "VisibilityFeature"
+	FeatureSet_VisibilityFeature_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet.VisibilityFeature"
+)
+
+// Full and short names for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_fullname = "google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility"
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_name     = "DefaultSymbolVisibility"
+)
+
+// Enum values for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN_enum_value = 0
+	FeatureSet_VisibilityFeature_EXPORT_ALL_enum_value                        = 1
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL_enum_value                  = 2
+	FeatureSet_VisibilityFeature_LOCAL_ALL_enum_value                         = 3
+	FeatureSet_VisibilityFeature_STRICT_enum_value                            = 4
+)
+
 // Names for google.protobuf.FeatureSetDefaults.
 const (
 	FeatureSetDefaults_message_name     protoreflect.Name     = "FeatureSetDefaults"
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/event-processor/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
index 41c1f74e..bdad12a9 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
@@ -11,6 +11,7 @@ import (
 
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/encoding/messageset"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/order"
 	"google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -80,7 +81,7 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
 		// permit us to skip over definitely-unset fields at marshal time.
 
 		var hasPresence bool
-		hasPresence, cf.isLazy = usePresenceForField(si, fd)
+		hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
 
 		if hasPresence {
 			cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/event-processor/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
index dd55e8e0..5a439daa 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"sync/atomic"
 
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
@@ -53,7 +54,7 @@ func opaqueInitHook(mi *MessageInfo) bool {
 		fd := fds.Get(i)
 		fs := si.fieldsByNumber[fd.Number()]
 		var fi fieldInfo
-		usePresence, _ := usePresenceForField(si, fd)
+		usePresence, _ := filedesc.UsePresenceForField(fd)
 
 		switch {
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
@@ -343,17 +344,15 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return false
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return false
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			return rv.Elem().Len() > 0
 		},
 		clear: func(p pointer) {
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if !sp.IsNil() {
-				rv := sp.AsValueOf(fs.Type.Elem())
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if !rv.IsNil() {
 				rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
 			}
 		},
@@ -361,11 +360,10 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return conv.Zero()
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return conv.Zero()
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			if rv.Elem().Len() == 0 {
 				return conv.Zero()
 			}
@@ -598,30 +596,3 @@ func (mi *MessageInfo) clearPresent(p pointer, index uint32) {
 func (mi *MessageInfo) present(p pointer, index uint32) bool {
 	return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
 }
-
-// usePresenceForField implements the somewhat intricate logic of when
-// the presence bitmap is used for a field.  The main logic is that a
-// field that is optional or that can be lazy will use the presence
-// bit, but for proto2, also maps have a presence bit. It also records
-// if the field can ever be lazy, which is true if we have a
-// lazyOffset and the field is a message or a slice of messages. A
-// field that is lazy will always need a presence bit.  Oneofs are not
-// lazy and do not use presence, unless they are a synthetic oneof,
-// which is a proto3 optional field. For proto3 optionals, we use the
-// presence and they can also be lazy when applicable (a message).
-func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
-	hasLazyField := fd.(interface{ IsLazy() bool }).IsLazy()
-
-	// Non-oneof scalar fields with explicit field presence use the presence array.
-	usesPresenceArray := fd.HasPresence() && fd.Message() == nil && (fd.ContainingOneof() == nil || fd.ContainingOneof().IsSynthetic())
-	switch {
-	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
-		return false, false
-	case fd.IsMap():
-		return false, false
-	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
-		return hasLazyField, hasLazyField
-	default:
-		return usesPresenceArray || (hasLazyField && fd.HasPresence()), false
-	}
-}
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/impl/presence.go b/event-processor/vendor/google.golang.org/protobuf/internal/impl/presence.go
index 914cb1de..443afe81 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/impl/presence.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/impl/presence.go
@@ -32,9 +32,6 @@ func (p presence) toElem(num uint32) (ret *uint32) {
 
 // Present checks for the presence of a specific field number in a presence set.
 func (p presence) Present(num uint32) bool {
-	if p.P == nil {
-		return false
-	}
 	return Export{}.Present(p.toElem(num), num)
 }
 
diff --git a/event-processor/vendor/google.golang.org/protobuf/internal/version/version.go b/event-processor/vendor/google.golang.org/protobuf/internal/version/version.go
index aac1cb18..77de0f23 100644
--- a/event-processor/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/event-processor/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -52,7 +52,7 @@ import (
 const (
 	Major      = 1
 	Minor      = 36
-	Patch      = 6
+	Patch      = 10
 	PreRelease = ""
 )
 
diff --git a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
index 823dbf3b..9196288e 100644
--- a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
+++ b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
@@ -152,6 +152,28 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
 		imp := &f.L2.Imports[i]
 		imps.importPublic(imp.Imports())
 	}
+	if len(fd.GetOptionDependency()) > 0 {
+		optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency()))
+		for i, path := range fd.GetOptionDependency() {
+			imp := &optionImports[i]
+			f, err := r.FindFileByPath(path)
+			if err == protoregistry.NotFound {
+				// We always allow option imports to be unresolvable.
+				f = filedesc.PlaceholderFile(path)
+			} else if err != nil {
+				return nil, errors.New("could not resolve import %q: %v", path, err)
+			}
+			imp.FileDescriptor = f
+
+			if imps[imp.Path()] {
+				return nil, errors.New("already imported %q", path)
+			}
+			imps[imp.Path()] = true
+		}
+		f.L2.OptionImports = func() protoreflect.FileImports {
+			return &optionImports
+		}
+	}
 
 	// Handle source locations.
 	f.L2.Locations.File = f
diff --git a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
index 9da34998..c826ad04 100644
--- a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
+++ b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
@@ -29,6 +29,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
 			e.L2.Options = func() protoreflect.ProtoMessage { return opts }
 		}
 		e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
+		e.L1.Visibility = int32(ed.GetVisibility())
 		for _, s := range ed.GetReservedName() {
 			e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
 		}
@@ -70,6 +71,7 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
 			return nil, err
 		}
 		m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
+		m.L1.Visibility = int32(md.GetVisibility())
 		if opts := md.GetOptions(); opts != nil {
 			opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
 			m.L2.Options = func() protoreflect.ProtoMessage { return opts }
diff --git a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
index 9b880aa8..6f91074e 100644
--- a/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
+++ b/event-processor/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
@@ -70,16 +70,27 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
 	if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
 		p.Syntax = proto.String(file.Syntax().String())
 	}
+	desc := file
+	if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
+		desc = fileImportDesc.FileDescriptor
+	}
 	if file.Syntax() == protoreflect.Editions {
-		desc := file
-		if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
-			desc = fileImportDesc.FileDescriptor
-		}
-
 		if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok {
 			p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum()
 		}
 	}
+	type hasOptionImports interface {
+		OptionImports() protoreflect.FileImports
+	}
+	if opts, ok := desc.(hasOptionImports); ok {
+		if optionImports := opts.OptionImports(); optionImports.Len() > 0 {
+			optionDeps := make([]string, optionImports.Len())
+			for i := range optionImports.Len() {
+				optionDeps[i] = optionImports.Get(i).Path()
+			}
+			p.OptionDependency = optionDeps
+		}
+	}
 	return p
 }
 
@@ -123,6 +134,14 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
 	for i, names := 0, message.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := message.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
@@ -216,6 +235,14 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
 	for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := enum.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
diff --git a/event-processor/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/event-processor/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
index a4a0a297..730331e6 100644
--- a/event-processor/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
+++ b/event-processor/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
@@ -21,6 +21,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "public_dependency", nil)
 	case 11:
 		b = p.appendRepeatedField(b, "weak_dependency", nil)
+	case 15:
+		b = p.appendRepeatedField(b, "option_dependency", nil)
 	case 4:
 		b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto)
 	case 5:
@@ -66,6 +68,8 @@ func (p *SourcePath) appendDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange)
 	case 10:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 11:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -85,6 +89,8 @@ func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange)
 	case 5:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 6:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -400,6 +406,8 @@ func (p *SourcePath) appendFeatureSet(b []byte) []byte {
 		b = p.appendSingularField(b, "json_format", nil)
 	case 7:
 		b = p.appendSingularField(b, "enforce_naming_style", nil)
+	case 8:
+		b = p.appendSingularField(b, "default_symbol_visibility", nil)
 	}
 	return b
 }
diff --git a/event-processor/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/event-processor/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
index 7fe280f1..4eacb523 100644
--- a/event-processor/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
+++ b/event-processor/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
@@ -151,6 +151,70 @@ func (Edition) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0}
 }
 
+// Describes the 'visibility' of a symbol with respect to the proto import
+// system. Symbols can only be imported when the visibility rules do not prevent
+// it (ex: local symbols cannot be imported).  Visibility modifiers can only set
+// on `message` and `enum` as they are the only types available to be referenced
+// from other files.
+type SymbolVisibility int32
+
+const (
+	SymbolVisibility_VISIBILITY_UNSET  SymbolVisibility = 0
+	SymbolVisibility_VISIBILITY_LOCAL  SymbolVisibility = 1
+	SymbolVisibility_VISIBILITY_EXPORT SymbolVisibility = 2
+)
+
+// Enum value maps for SymbolVisibility.
+var (
+	SymbolVisibility_name = map[int32]string{
+		0: "VISIBILITY_UNSET",
+		1: "VISIBILITY_LOCAL",
+		2: "VISIBILITY_EXPORT",
+	}
+	SymbolVisibility_value = map[string]int32{
+		"VISIBILITY_UNSET":  0,
+		"VISIBILITY_LOCAL":  1,
+		"VISIBILITY_EXPORT": 2,
+	}
+)
+
+func (x SymbolVisibility) Enum() *SymbolVisibility {
+	p := new(SymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x SymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+}
+
+func (SymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+}
+
+func (x SymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *SymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = SymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use SymbolVisibility.Descriptor instead.
+func (SymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1}
+}
+
 // The verification state of the extension range.
 type ExtensionRangeOptions_VerificationState int32
 
@@ -183,11 +247,11 @@ func (x ExtensionRangeOptions_VerificationState) String() string {
 }
 
 func (ExtensionRangeOptions_VerificationState) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
 }
 
 func (ExtensionRangeOptions_VerificationState) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+	return &file_google_protobuf_descriptor_proto_enumTypes[2]
 }
 
 func (x ExtensionRangeOptions_VerificationState) Number() protoreflect.EnumNumber {
@@ -299,11 +363,11 @@ func (x FieldDescriptorProto_Type) String() string {
 }
 
 func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
 }
 
 func (FieldDescriptorProto_Type) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[2]
+	return &file_google_protobuf_descriptor_proto_enumTypes[3]
 }
 
 func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber {
@@ -362,11 +426,11 @@ func (x FieldDescriptorProto_Label) String() string {
 }
 
 func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
 }
 
 func (FieldDescriptorProto_Label) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[3]
+	return &file_google_protobuf_descriptor_proto_enumTypes[4]
 }
 
 func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber {
@@ -423,11 +487,11 @@ func (x FileOptions_OptimizeMode) String() string {
 }
 
 func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
 }
 
 func (FileOptions_OptimizeMode) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[4]
+	return &file_google_protobuf_descriptor_proto_enumTypes[5]
 }
 
 func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber {
@@ -489,11 +553,11 @@ func (x FieldOptions_CType) String() string {
 }
 
 func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
 }
 
 func (FieldOptions_CType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[5]
+	return &file_google_protobuf_descriptor_proto_enumTypes[6]
 }
 
 func (x FieldOptions_CType) Number() protoreflect.EnumNumber {
@@ -551,11 +615,11 @@ func (x FieldOptions_JSType) String() string {
 }
 
 func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
 }
 
 func (FieldOptions_JSType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[6]
+	return &file_google_protobuf_descriptor_proto_enumTypes[7]
 }
 
 func (x FieldOptions_JSType) Number() protoreflect.EnumNumber {
@@ -611,11 +675,11 @@ func (x FieldOptions_OptionRetention) String() string {
 }
 
 func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
 }
 
 func (FieldOptions_OptionRetention) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[7]
+	return &file_google_protobuf_descriptor_proto_enumTypes[8]
 }
 
 func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber {
@@ -694,11 +758,11 @@ func (x FieldOptions_OptionTargetType) String() string {
 }
 
 func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
 }
 
 func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[8]
+	return &file_google_protobuf_descriptor_proto_enumTypes[9]
 }
 
 func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber {
@@ -756,11 +820,11 @@ func (x MethodOptions_IdempotencyLevel) String() string {
 }
 
 func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
 }
 
 func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[9]
+	return &file_google_protobuf_descriptor_proto_enumTypes[10]
 }
 
 func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber {
@@ -818,11 +882,11 @@ func (x FeatureSet_FieldPresence) String() string {
 }
 
 func (FeatureSet_FieldPresence) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
 }
 
 func (FeatureSet_FieldPresence) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[10]
+	return &file_google_protobuf_descriptor_proto_enumTypes[11]
 }
 
 func (x FeatureSet_FieldPresence) Number() protoreflect.EnumNumber {
@@ -877,11 +941,11 @@ func (x FeatureSet_EnumType) String() string {
 }
 
 func (FeatureSet_EnumType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
 }
 
 func (FeatureSet_EnumType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[11]
+	return &file_google_protobuf_descriptor_proto_enumTypes[12]
 }
 
 func (x FeatureSet_EnumType) Number() protoreflect.EnumNumber {
@@ -936,11 +1000,11 @@ func (x FeatureSet_RepeatedFieldEncoding) String() string {
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[12]
+	return &file_google_protobuf_descriptor_proto_enumTypes[13]
 }
 
 func (x FeatureSet_RepeatedFieldEncoding) Number() protoreflect.EnumNumber {
@@ -995,11 +1059,11 @@ func (x FeatureSet_Utf8Validation) String() string {
 }
 
 func (FeatureSet_Utf8Validation) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
 }
 
 func (FeatureSet_Utf8Validation) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[13]
+	return &file_google_protobuf_descriptor_proto_enumTypes[14]
 }
 
 func (x FeatureSet_Utf8Validation) Number() protoreflect.EnumNumber {
@@ -1054,11 +1118,11 @@ func (x FeatureSet_MessageEncoding) String() string {
 }
 
 func (FeatureSet_MessageEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
 }
 
 func (FeatureSet_MessageEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[14]
+	return &file_google_protobuf_descriptor_proto_enumTypes[15]
 }
 
 func (x FeatureSet_MessageEncoding) Number() protoreflect.EnumNumber {
@@ -1113,11 +1177,11 @@ func (x FeatureSet_JsonFormat) String() string {
 }
 
 func (FeatureSet_JsonFormat) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
 }
 
 func (FeatureSet_JsonFormat) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[15]
+	return &file_google_protobuf_descriptor_proto_enumTypes[16]
 }
 
 func (x FeatureSet_JsonFormat) Number() protoreflect.EnumNumber {
@@ -1172,11 +1236,11 @@ func (x FeatureSet_EnforceNamingStyle) String() string {
 }
 
 func (FeatureSet_EnforceNamingStyle) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
 }
 
 func (FeatureSet_EnforceNamingStyle) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[16]
+	return &file_google_protobuf_descriptor_proto_enumTypes[17]
 }
 
 func (x FeatureSet_EnforceNamingStyle) Number() protoreflect.EnumNumber {
@@ -1198,6 +1262,77 @@ func (FeatureSet_EnforceNamingStyle) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 6}
 }
 
+type FeatureSet_VisibilityFeature_DefaultSymbolVisibility int32
+
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 0
+	// Default pre-EDITION_2024, all UNSET visibility are export.
+	FeatureSet_VisibilityFeature_EXPORT_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 1
+	// All top-level symbols default to export, nested default to local.
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 2
+	// All symbols default to local.
+	FeatureSet_VisibilityFeature_LOCAL_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 3
+	// All symbols local by default. Nested types cannot be exported.
+	// With special case caveat for message { enum {} reserved 1 to max; }
+	// This is the recommended setting for new protos.
+	FeatureSet_VisibilityFeature_STRICT FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 4
+)
+
+// Enum value maps for FeatureSet_VisibilityFeature_DefaultSymbolVisibility.
+var (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_name = map[int32]string{
+		0: "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN",
+		1: "EXPORT_ALL",
+		2: "EXPORT_TOP_LEVEL",
+		3: "LOCAL_ALL",
+		4: "STRICT",
+	}
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_value = map[string]int32{
+		"DEFAULT_SYMBOL_VISIBILITY_UNKNOWN": 0,
+		"EXPORT_ALL":                        1,
+		"EXPORT_TOP_LEVEL":                  2,
+		"LOCAL_ALL":                         3,
+		"STRICT":                            4,
+	}
+)
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Enum() *FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	p := new(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[18].Descriptor()
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[18]
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_VisibilityFeature_DefaultSymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = FeatureSet_VisibilityFeature_DefaultSymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature_DefaultSymbolVisibility.Descriptor instead.
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0, 0}
+}
+
 // Represents the identified object's effect on the element in the original
 // .proto file.
 type GeneratedCodeInfo_Annotation_Semantic int32
@@ -1236,11 +1371,11 @@ func (x GeneratedCodeInfo_Annotation_Semantic) String() string {
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[19].Descriptor()
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[17]
+	return &file_google_protobuf_descriptor_proto_enumTypes[19]
 }
 
 func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber {
@@ -1321,6 +1456,9 @@ type FileDescriptorProto struct {
 	// Indexes of the weak imported files in the dependency list.
 	// For Google-internal migration only. Do not use.
 	WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+	// Names of files imported by this file purely for the purpose of providing
+	// option extensions. These are excluded from the dependency list above.
+	OptionDependency []string `protobuf:"bytes,15,rep,name=option_dependency,json=optionDependency" json:"option_dependency,omitempty"`
 	// All top-level definitions in this file.
 	MessageType []*DescriptorProto        `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
 	EnumType    []*EnumDescriptorProto    `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
@@ -1414,6 +1552,13 @@ func (x *FileDescriptorProto) GetWeakDependency() []int32 {
 	return nil
 }
 
+func (x *FileDescriptorProto) GetOptionDependency() []string {
+	if x != nil {
+		return x.OptionDependency
+	}
+	return nil
+}
+
 func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto {
 	if x != nil {
 		return x.MessageType
@@ -1484,7 +1629,9 @@ type DescriptorProto struct {
 	ReservedRange  []*DescriptorProto_ReservedRange  `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved field names, which may not be used by fields in the same message.
 	// A given name may only be reserved once.
-	ReservedName  []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,11,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1589,6 +1736,13 @@ func (x *DescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *DescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 type ExtensionRangeOptions struct {
 	state protoimpl.MessageState `protogen:"open.v1"`
 	// The parser stores options it doesn't recognize here. See above.
@@ -1901,7 +2055,9 @@ type EnumDescriptorProto struct {
 	ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved enum value names, which may not be reused. A given name may only
 	// be reserved once.
-	ReservedName  []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,6,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1971,6 +2127,13 @@ func (x *EnumDescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *EnumDescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 // Describes a value within an enum.
 type EnumValueDescriptorProto struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
@@ -2710,7 +2873,10 @@ type FieldOptions struct {
 	// for accessors, or it will be completely ignored; in the very least, this
 	// is a formalization for deprecating fields.
 	Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+	// DEPRECATED. DO NOT USE!
 	// For Google-internal migration only. Do not use.
+	//
+	// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 	Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
 	// Indicate that the field value should not be printed out when using debug
 	// formats, e.g. when the field contains sensitive credentials.
@@ -2814,6 +2980,7 @@ func (x *FieldOptions) GetDeprecated() bool {
 	return Default_FieldOptions_Deprecated
 }
 
+// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 func (x *FieldOptions) GetWeak() bool {
 	if x != nil && x.Weak != nil {
 		return *x.Weak
@@ -3392,17 +3559,18 @@ func (x *UninterpretedOption) GetAggregateValue() string {
 // be designed and implemented to handle this, hopefully before we ever hit a
 // conflict here.
 type FeatureSet struct {
-	state                 protoimpl.MessageState            `protogen:"open.v1"`
-	FieldPresence         *FeatureSet_FieldPresence         `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
-	EnumType              *FeatureSet_EnumType              `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
-	RepeatedFieldEncoding *FeatureSet_RepeatedFieldEncoding `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
-	Utf8Validation        *FeatureSet_Utf8Validation        `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
-	MessageEncoding       *FeatureSet_MessageEncoding       `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
-	JsonFormat            *FeatureSet_JsonFormat            `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
-	EnforceNamingStyle    *FeatureSet_EnforceNamingStyle    `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
-	extensionFields       protoimpl.ExtensionFields
-	unknownFields         protoimpl.UnknownFields
-	sizeCache             protoimpl.SizeCache
+	state                   protoimpl.MessageState                                `protogen:"open.v1"`
+	FieldPresence           *FeatureSet_FieldPresence                             `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
+	EnumType                *FeatureSet_EnumType                                  `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
+	RepeatedFieldEncoding   *FeatureSet_RepeatedFieldEncoding                     `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
+	Utf8Validation          *FeatureSet_Utf8Validation                            `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
+	MessageEncoding         *FeatureSet_MessageEncoding                           `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
+	JsonFormat              *FeatureSet_JsonFormat                                `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
+	EnforceNamingStyle      *FeatureSet_EnforceNamingStyle                        `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
+	DefaultSymbolVisibility *FeatureSet_VisibilityFeature_DefaultSymbolVisibility `protobuf:"varint,8,opt,name=default_symbol_visibility,json=defaultSymbolVisibility,enum=google.protobuf.FeatureSet_VisibilityFeature_DefaultSymbolVisibility" json:"default_symbol_visibility,omitempty"`
+	extensionFields         protoimpl.ExtensionFields
+	unknownFields           protoimpl.UnknownFields
+	sizeCache               protoimpl.SizeCache
 }
 
 func (x *FeatureSet) Reset() {
@@ -3484,6 +3652,13 @@ func (x *FeatureSet) GetEnforceNamingStyle() FeatureSet_EnforceNamingStyle {
 	return FeatureSet_ENFORCE_NAMING_STYLE_UNKNOWN
 }
 
+func (x *FeatureSet) GetDefaultSymbolVisibility() FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	if x != nil && x.DefaultSymbolVisibility != nil {
+		return *x.DefaultSymbolVisibility
+	}
+	return FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN
+}
+
 // A compiled specification for the defaults of a set of features.  These
 // messages are generated from FeatureSet extensions and can be used to seed
 // feature resolution. The resolution with this object becomes a simple search
@@ -4144,6 +4319,42 @@ func (x *UninterpretedOption_NamePart) GetIsExtension() bool {
 	return false
 }
 
+type FeatureSet_VisibilityFeature struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *FeatureSet_VisibilityFeature) Reset() {
+	*x = FeatureSet_VisibilityFeature{}
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *FeatureSet_VisibilityFeature) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSet_VisibilityFeature) ProtoMessage() {}
+
+func (x *FeatureSet_VisibilityFeature) ProtoReflect() protoreflect.Message {
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature.ProtoReflect.Descriptor instead.
+func (*FeatureSet_VisibilityFeature) Descriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+}
+
 // A map from every known edition with a unique set of defaults to its
 // defaults. Not all editions may be contained here.  For a given edition,
 // the defaults at the closest matching edition ordered at or before it should
@@ -4161,7 +4372,7 @@ type FeatureSetDefaults_FeatureSetEditionDefault struct {
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() {
 	*x = FeatureSetDefaults_FeatureSetEditionDefault{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4173,7 +4384,7 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string {
 func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {}
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4309,7 +4520,7 @@ type SourceCodeInfo_Location struct {
 
 func (x *SourceCodeInfo_Location) Reset() {
 	*x = SourceCodeInfo_Location{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4321,7 +4532,7 @@ func (x *SourceCodeInfo_Location) String() string {
 func (*SourceCodeInfo_Location) ProtoMessage() {}
 
 func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4393,7 +4604,7 @@ type GeneratedCodeInfo_Annotation struct {
 
 func (x *GeneratedCodeInfo_Annotation) Reset() {
 	*x = GeneratedCodeInfo_Annotation{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4405,7 +4616,7 @@ func (x *GeneratedCodeInfo_Annotation) String() string {
 func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
 
 func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4462,7 +4673,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\n" +
 	" google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"[\n" +
 	"\x11FileDescriptorSet\x128\n" +
-	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\x98\x05\n" +
+	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\xc5\x05\n" +
 	"\x13FileDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
 	"\apackage\x18\x02 \x01(\tR\apackage\x12\x1e\n" +
@@ -4471,7 +4682,8 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"dependency\x12+\n" +
 	"\x11public_dependency\x18\n" +
 	" \x03(\x05R\x10publicDependency\x12'\n" +
-	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12C\n" +
+	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12+\n" +
+	"\x11option_dependency\x18\x0f \x03(\tR\x10optionDependency\x12C\n" +
 	"\fmessage_type\x18\x04 \x03(\v2 .google.protobuf.DescriptorProtoR\vmessageType\x12A\n" +
 	"\tenum_type\x18\x05 \x03(\v2$.google.protobuf.EnumDescriptorProtoR\benumType\x12A\n" +
 	"\aservice\x18\x06 \x03(\v2'.google.protobuf.ServiceDescriptorProtoR\aservice\x12C\n" +
@@ -4479,7 +4691,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\b \x01(\v2\x1c.google.protobuf.FileOptionsR\aoptions\x12I\n" +
 	"\x10source_code_info\x18\t \x01(\v2\x1f.google.protobuf.SourceCodeInfoR\x0esourceCodeInfo\x12\x16\n" +
 	"\x06syntax\x18\f \x01(\tR\x06syntax\x122\n" +
-	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xb9\x06\n" +
+	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xfc\x06\n" +
 	"\x0fDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12;\n" +
 	"\x05field\x18\x02 \x03(\v2%.google.protobuf.FieldDescriptorProtoR\x05field\x12C\n" +
@@ -4493,7 +4705,10 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\a \x01(\v2\x1f.google.protobuf.MessageOptionsR\aoptions\x12U\n" +
 	"\x0ereserved_range\x18\t \x03(\v2..google.protobuf.DescriptorProto.ReservedRangeR\rreservedRange\x12#\n" +
 	"\rreserved_name\x18\n" +
-	" \x03(\tR\freservedName\x1az\n" +
+	" \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\v \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1az\n" +
 	"\x0eExtensionRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\x12@\n" +
@@ -4562,13 +4777,16 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0eLABEL_REQUIRED\x10\x02\"c\n" +
 	"\x14OneofDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x127\n" +
-	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xe3\x02\n" +
+	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xa6\x03\n" +
 	"\x13EnumDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12?\n" +
 	"\x05value\x18\x02 \x03(\v2).google.protobuf.EnumValueDescriptorProtoR\x05value\x126\n" +
 	"\aoptions\x18\x03 \x01(\v2\x1c.google.protobuf.EnumOptionsR\aoptions\x12]\n" +
 	"\x0ereserved_range\x18\x04 \x03(\v26.google.protobuf.EnumDescriptorProto.EnumReservedRangeR\rreservedRange\x12#\n" +
-	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x1a;\n" +
+	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\x06 \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1a;\n" +
 	"\x11EnumReservedRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\"\x83\x01\n" +
@@ -4629,7 +4847,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"&deprecated_legacy_json_field_conflicts\x18\v \x01(\bB\x02\x18\x01R\"deprecatedLegacyJsonFieldConflicts\x127\n" +
 	"\bfeatures\x18\f \x01(\v2\x1b.google.protobuf.FeatureSetR\bfeatures\x12X\n" +
 	"\x14uninterpreted_option\x18\xe7\a \x03(\v2$.google.protobuf.UninterpretedOptionR\x13uninterpretedOption*\t\b\xe8\a\x10\x80\x80\x80\x80\x02J\x04\b\x04\x10\x05J\x04\b\x05\x10\x06J\x04\b\x06\x10\aJ\x04\b\b\x10\tJ\x04\b\t\x10\n" +
-	"\"\x9d\r\n" +
+	"\"\xa1\r\n" +
 	"\fFieldOptions\x12A\n" +
 	"\x05ctype\x18\x01 \x01(\x0e2#.google.protobuf.FieldOptions.CType:\x06STRINGR\x05ctype\x12\x16\n" +
 	"\x06packed\x18\x02 \x01(\bR\x06packed\x12G\n" +
@@ -4638,9 +4856,9 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0funverified_lazy\x18\x0f \x01(\b:\x05falseR\x0eunverifiedLazy\x12%\n" +
 	"\n" +
 	"deprecated\x18\x03 \x01(\b:\x05falseR\n" +
-	"deprecated\x12\x19\n" +
+	"deprecated\x12\x1d\n" +
 	"\x04weak\x18\n" +
-	" \x01(\b:\x05falseR\x04weak\x12(\n" +
+	" \x01(\b:\x05falseB\x02\x18\x01R\x04weak\x12(\n" +
 	"\fdebug_redact\x18\x10 \x01(\b:\x05falseR\vdebugRedact\x12K\n" +
 	"\tretention\x18\x11 \x01(\x0e2-.google.protobuf.FieldOptions.OptionRetentionR\tretention\x12H\n" +
 	"\atargets\x18\x13 \x03(\x0e2..google.protobuf.FieldOptions.OptionTargetTypeR\atargets\x12W\n" +
@@ -4728,7 +4946,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0faggregate_value\x18\b \x01(\tR\x0eaggregateValue\x1aJ\n" +
 	"\bNamePart\x12\x1b\n" +
 	"\tname_part\x18\x01 \x02(\tR\bnamePart\x12!\n" +
-	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\xae\f\n" +
+	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\x8e\x0f\n" +
 	"\n" +
 	"FeatureSet\x12\x91\x01\n" +
 	"\x0efield_presence\x18\x01 \x01(\x0e2).google.protobuf.FeatureSet.FieldPresenceB?\x88\x01\x01\x98\x01\x04\x98\x01\x01\xa2\x01\r\x12\bEXPLICIT\x18\x84\a\xa2\x01\r\x12\bIMPLICIT\x18\xe7\a\xa2\x01\r\x12\bEXPLICIT\x18\xe8\a\xb2\x01\x03\b\xe8\aR\rfieldPresence\x12l\n" +
@@ -4739,7 +4957,18 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\vjson_format\x18\x06 \x01(\x0e2&.google.protobuf.FeatureSet.JsonFormatB9\x88\x01\x01\x98\x01\x03\x98\x01\x06\x98\x01\x01\xa2\x01\x17\x12\x12LEGACY_BEST_EFFORT\x18\x84\a\xa2\x01\n" +
 	"\x12\x05ALLOW\x18\xe7\a\xb2\x01\x03\b\xe8\aR\n" +
 	"jsonFormat\x12\xab\x01\n" +
-	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\"\\\n" +
+	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\x12\xb9\x01\n" +
+	"\x19default_symbol_visibility\x18\b \x01(\x0e2E.google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibilityB6\x88\x01\x02\x98\x01\x01\xa2\x01\x0f\x12\n" +
+	"EXPORT_ALL\x18\x84\a\xa2\x01\x15\x12\x10EXPORT_TOP_LEVEL\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x17defaultSymbolVisibility\x1a\xa1\x01\n" +
+	"\x11VisibilityFeature\"\x81\x01\n" +
+	"\x17DefaultSymbolVisibility\x12%\n" +
+	"!DEFAULT_SYMBOL_VISIBILITY_UNKNOWN\x10\x00\x12\x0e\n" +
+	"\n" +
+	"EXPORT_ALL\x10\x01\x12\x14\n" +
+	"\x10EXPORT_TOP_LEVEL\x10\x02\x12\r\n" +
+	"\tLOCAL_ALL\x10\x03\x12\n" +
+	"\n" +
+	"\x06STRICT\x10\x04J\b\b\x01\x10\x80\x80\x80\x80\x02\"\\\n" +
 	"\rFieldPresence\x12\x1a\n" +
 	"\x16FIELD_PRESENCE_UNKNOWN\x10\x00\x12\f\n" +
 	"\bEXPLICIT\x10\x01\x12\f\n" +
@@ -4817,7 +5046,11 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99998_TEST_ONLY\x10\x9e\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99999_TEST_ONLY\x10\x9f\x8d\x06\x12\x13\n" +
-	"\vEDITION_MAX\x10\xff\xff\xff\xff\aB~\n" +
+	"\vEDITION_MAX\x10\xff\xff\xff\xff\a*U\n" +
+	"\x10SymbolVisibility\x12\x14\n" +
+	"\x10VISIBILITY_UNSET\x10\x00\x12\x14\n" +
+	"\x10VISIBILITY_LOCAL\x10\x01\x12\x15\n" +
+	"\x11VISIBILITY_EXPORT\x10\x02B~\n" +
 	"\x13com.google.protobufB\x10DescriptorProtosH\x01Z-google.golang.org/protobuf/types/descriptorpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection"
 
 var (
@@ -4832,145 +5065,151 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte {
 	return file_google_protobuf_descriptor_proto_rawDescData
 }
 
-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 18)
-var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 20)
+var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
 var file_google_protobuf_descriptor_proto_goTypes = []any{
-	(Edition)(0), // 0: google.protobuf.Edition
-	(ExtensionRangeOptions_VerificationState)(0),        // 1: google.protobuf.ExtensionRangeOptions.VerificationState
-	(FieldDescriptorProto_Type)(0),                      // 2: google.protobuf.FieldDescriptorProto.Type
-	(FieldDescriptorProto_Label)(0),                     // 3: google.protobuf.FieldDescriptorProto.Label
-	(FileOptions_OptimizeMode)(0),                       // 4: google.protobuf.FileOptions.OptimizeMode
-	(FieldOptions_CType)(0),                             // 5: google.protobuf.FieldOptions.CType
-	(FieldOptions_JSType)(0),                            // 6: google.protobuf.FieldOptions.JSType
-	(FieldOptions_OptionRetention)(0),                   // 7: google.protobuf.FieldOptions.OptionRetention
-	(FieldOptions_OptionTargetType)(0),                  // 8: google.protobuf.FieldOptions.OptionTargetType
-	(MethodOptions_IdempotencyLevel)(0),                 // 9: google.protobuf.MethodOptions.IdempotencyLevel
-	(FeatureSet_FieldPresence)(0),                       // 10: google.protobuf.FeatureSet.FieldPresence
-	(FeatureSet_EnumType)(0),                            // 11: google.protobuf.FeatureSet.EnumType
-	(FeatureSet_RepeatedFieldEncoding)(0),               // 12: google.protobuf.FeatureSet.RepeatedFieldEncoding
-	(FeatureSet_Utf8Validation)(0),                      // 13: google.protobuf.FeatureSet.Utf8Validation
-	(FeatureSet_MessageEncoding)(0),                     // 14: google.protobuf.FeatureSet.MessageEncoding
-	(FeatureSet_JsonFormat)(0),                          // 15: google.protobuf.FeatureSet.JsonFormat
-	(FeatureSet_EnforceNamingStyle)(0),                  // 16: google.protobuf.FeatureSet.EnforceNamingStyle
-	(GeneratedCodeInfo_Annotation_Semantic)(0),          // 17: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	(*FileDescriptorSet)(nil),                           // 18: google.protobuf.FileDescriptorSet
-	(*FileDescriptorProto)(nil),                         // 19: google.protobuf.FileDescriptorProto
-	(*DescriptorProto)(nil),                             // 20: google.protobuf.DescriptorProto
-	(*ExtensionRangeOptions)(nil),                       // 21: google.protobuf.ExtensionRangeOptions
-	(*FieldDescriptorProto)(nil),                        // 22: google.protobuf.FieldDescriptorProto
-	(*OneofDescriptorProto)(nil),                        // 23: google.protobuf.OneofDescriptorProto
-	(*EnumDescriptorProto)(nil),                         // 24: google.protobuf.EnumDescriptorProto
-	(*EnumValueDescriptorProto)(nil),                    // 25: google.protobuf.EnumValueDescriptorProto
-	(*ServiceDescriptorProto)(nil),                      // 26: google.protobuf.ServiceDescriptorProto
-	(*MethodDescriptorProto)(nil),                       // 27: google.protobuf.MethodDescriptorProto
-	(*FileOptions)(nil),                                 // 28: google.protobuf.FileOptions
-	(*MessageOptions)(nil),                              // 29: google.protobuf.MessageOptions
-	(*FieldOptions)(nil),                                // 30: google.protobuf.FieldOptions
-	(*OneofOptions)(nil),                                // 31: google.protobuf.OneofOptions
-	(*EnumOptions)(nil),                                 // 32: google.protobuf.EnumOptions
-	(*EnumValueOptions)(nil),                            // 33: google.protobuf.EnumValueOptions
-	(*ServiceOptions)(nil),                              // 34: google.protobuf.ServiceOptions
-	(*MethodOptions)(nil),                               // 35: google.protobuf.MethodOptions
-	(*UninterpretedOption)(nil),                         // 36: google.protobuf.UninterpretedOption
-	(*FeatureSet)(nil),                                  // 37: google.protobuf.FeatureSet
-	(*FeatureSetDefaults)(nil),                          // 38: google.protobuf.FeatureSetDefaults
-	(*SourceCodeInfo)(nil),                              // 39: google.protobuf.SourceCodeInfo
-	(*GeneratedCodeInfo)(nil),                           // 40: google.protobuf.GeneratedCodeInfo
-	(*DescriptorProto_ExtensionRange)(nil),              // 41: google.protobuf.DescriptorProto.ExtensionRange
-	(*DescriptorProto_ReservedRange)(nil),               // 42: google.protobuf.DescriptorProto.ReservedRange
-	(*ExtensionRangeOptions_Declaration)(nil),           // 43: google.protobuf.ExtensionRangeOptions.Declaration
-	(*EnumDescriptorProto_EnumReservedRange)(nil),       // 44: google.protobuf.EnumDescriptorProto.EnumReservedRange
-	(*FieldOptions_EditionDefault)(nil),                 // 45: google.protobuf.FieldOptions.EditionDefault
-	(*FieldOptions_FeatureSupport)(nil),                 // 46: google.protobuf.FieldOptions.FeatureSupport
-	(*UninterpretedOption_NamePart)(nil),                // 47: google.protobuf.UninterpretedOption.NamePart
-	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 48: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	(*SourceCodeInfo_Location)(nil),                     // 49: google.protobuf.SourceCodeInfo.Location
-	(*GeneratedCodeInfo_Annotation)(nil),                // 50: google.protobuf.GeneratedCodeInfo.Annotation
+	(Edition)(0),          // 0: google.protobuf.Edition
+	(SymbolVisibility)(0), // 1: google.protobuf.SymbolVisibility
+	(ExtensionRangeOptions_VerificationState)(0),              // 2: google.protobuf.ExtensionRangeOptions.VerificationState
+	(FieldDescriptorProto_Type)(0),                            // 3: google.protobuf.FieldDescriptorProto.Type
+	(FieldDescriptorProto_Label)(0),                           // 4: google.protobuf.FieldDescriptorProto.Label
+	(FileOptions_OptimizeMode)(0),                             // 5: google.protobuf.FileOptions.OptimizeMode
+	(FieldOptions_CType)(0),                                   // 6: google.protobuf.FieldOptions.CType
+	(FieldOptions_JSType)(0),                                  // 7: google.protobuf.FieldOptions.JSType
+	(FieldOptions_OptionRetention)(0),                         // 8: google.protobuf.FieldOptions.OptionRetention
+	(FieldOptions_OptionTargetType)(0),                        // 9: google.protobuf.FieldOptions.OptionTargetType
+	(MethodOptions_IdempotencyLevel)(0),                       // 10: google.protobuf.MethodOptions.IdempotencyLevel
+	(FeatureSet_FieldPresence)(0),                             // 11: google.protobuf.FeatureSet.FieldPresence
+	(FeatureSet_EnumType)(0),                                  // 12: google.protobuf.FeatureSet.EnumType
+	(FeatureSet_RepeatedFieldEncoding)(0),                     // 13: google.protobuf.FeatureSet.RepeatedFieldEncoding
+	(FeatureSet_Utf8Validation)(0),                            // 14: google.protobuf.FeatureSet.Utf8Validation
+	(FeatureSet_MessageEncoding)(0),                           // 15: google.protobuf.FeatureSet.MessageEncoding
+	(FeatureSet_JsonFormat)(0),                                // 16: google.protobuf.FeatureSet.JsonFormat
+	(FeatureSet_EnforceNamingStyle)(0),                        // 17: google.protobuf.FeatureSet.EnforceNamingStyle
+	(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)(0), // 18: google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	(GeneratedCodeInfo_Annotation_Semantic)(0),                // 19: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	(*FileDescriptorSet)(nil),                                 // 20: google.protobuf.FileDescriptorSet
+	(*FileDescriptorProto)(nil),                               // 21: google.protobuf.FileDescriptorProto
+	(*DescriptorProto)(nil),                                   // 22: google.protobuf.DescriptorProto
+	(*ExtensionRangeOptions)(nil),                             // 23: google.protobuf.ExtensionRangeOptions
+	(*FieldDescriptorProto)(nil),                              // 24: google.protobuf.FieldDescriptorProto
+	(*OneofDescriptorProto)(nil),                              // 25: google.protobuf.OneofDescriptorProto
+	(*EnumDescriptorProto)(nil),                               // 26: google.protobuf.EnumDescriptorProto
+	(*EnumValueDescriptorProto)(nil),                          // 27: google.protobuf.EnumValueDescriptorProto
+	(*ServiceDescriptorProto)(nil),                            // 28: google.protobuf.ServiceDescriptorProto
+	(*MethodDescriptorProto)(nil),                             // 29: google.protobuf.MethodDescriptorProto
+	(*FileOptions)(nil),                                       // 30: google.protobuf.FileOptions
+	(*MessageOptions)(nil),                                    // 31: google.protobuf.MessageOptions
+	(*FieldOptions)(nil),                                      // 32: google.protobuf.FieldOptions
+	(*OneofOptions)(nil),                                      // 33: google.protobuf.OneofOptions
+	(*EnumOptions)(nil),                                       // 34: google.protobuf.EnumOptions
+	(*EnumValueOptions)(nil),                                  // 35: google.protobuf.EnumValueOptions
+	(*ServiceOptions)(nil),                                    // 36: google.protobuf.ServiceOptions
+	(*MethodOptions)(nil),                                     // 37: google.protobuf.MethodOptions
+	(*UninterpretedOption)(nil),                               // 38: google.protobuf.UninterpretedOption
+	(*FeatureSet)(nil),                                        // 39: google.protobuf.FeatureSet
+	(*FeatureSetDefaults)(nil),                                // 40: google.protobuf.FeatureSetDefaults
+	(*SourceCodeInfo)(nil),                                    // 41: google.protobuf.SourceCodeInfo
+	(*GeneratedCodeInfo)(nil),                                 // 42: google.protobuf.GeneratedCodeInfo
+	(*DescriptorProto_ExtensionRange)(nil),                    // 43: google.protobuf.DescriptorProto.ExtensionRange
+	(*DescriptorProto_ReservedRange)(nil),                     // 44: google.protobuf.DescriptorProto.ReservedRange
+	(*ExtensionRangeOptions_Declaration)(nil),                 // 45: google.protobuf.ExtensionRangeOptions.Declaration
+	(*EnumDescriptorProto_EnumReservedRange)(nil),             // 46: google.protobuf.EnumDescriptorProto.EnumReservedRange
+	(*FieldOptions_EditionDefault)(nil),                       // 47: google.protobuf.FieldOptions.EditionDefault
+	(*FieldOptions_FeatureSupport)(nil),                       // 48: google.protobuf.FieldOptions.FeatureSupport
+	(*UninterpretedOption_NamePart)(nil),                      // 49: google.protobuf.UninterpretedOption.NamePart
+	(*FeatureSet_VisibilityFeature)(nil),                      // 50: google.protobuf.FeatureSet.VisibilityFeature
+	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil),       // 51: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	(*SourceCodeInfo_Location)(nil),                           // 52: google.protobuf.SourceCodeInfo.Location
+	(*GeneratedCodeInfo_Annotation)(nil),                      // 53: google.protobuf.GeneratedCodeInfo.Annotation
 }
 var file_google_protobuf_descriptor_proto_depIdxs = []int32{
-	19, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
-	20, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
-	24, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	26, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
-	22, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	28, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
-	39, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
+	21, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
+	22, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
+	26, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	28, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
+	24, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	30, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
+	41, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
 	0,  // 7: google.protobuf.FileDescriptorProto.edition:type_name -> google.protobuf.Edition
-	22, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
-	22, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	20, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
-	24, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	41, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
-	23, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
-	29, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
-	42, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
-	36, // 16: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	43, // 17: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
-	37, // 18: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
-	1,  // 19: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
-	3,  // 20: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
-	2,  // 21: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
-	30, // 22: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
-	31, // 23: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
-	25, // 24: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
-	32, // 25: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
-	44, // 26: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
-	33, // 27: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
-	27, // 28: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
-	34, // 29: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
-	35, // 30: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
-	4,  // 31: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
-	37, // 32: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 33: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 34: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 35: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	5,  // 36: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
-	6,  // 37: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
-	7,  // 38: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
-	8,  // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
-	45, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
-	37, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	9,  // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
-	37, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	47, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
-	10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
-	11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
-	12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
-	13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
-	14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
-	15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
-	16, // 63: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
-	48, // 64: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	0,  // 65: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
-	0,  // 66: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
-	49, // 67: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
-	50, // 68: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
-	21, // 69: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
-	0,  // 70: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
-	0,  // 71: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
-	0,  // 72: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
-	0,  // 73: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
-	0,  // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
-	37, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
-	37, // 76: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
-	17, // 77: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	78, // [78:78] is the sub-list for method output_type
-	78, // [78:78] is the sub-list for method input_type
-	78, // [78:78] is the sub-list for extension type_name
-	78, // [78:78] is the sub-list for extension extendee
-	0,  // [0:78] is the sub-list for field type_name
+	24, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
+	24, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	22, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
+	26, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	43, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
+	25, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
+	31, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
+	44, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
+	1,  // 16: google.protobuf.DescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	38, // 17: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	45, // 18: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
+	39, // 19: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
+	2,  // 20: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
+	4,  // 21: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
+	3,  // 22: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
+	32, // 23: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
+	33, // 24: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
+	27, // 25: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
+	34, // 26: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
+	46, // 27: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
+	1,  // 28: google.protobuf.EnumDescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	35, // 29: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
+	29, // 30: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
+	36, // 31: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
+	37, // 32: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
+	5,  // 33: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
+	39, // 34: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 35: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 36: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 37: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	6,  // 38: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
+	7,  // 39: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
+	8,  // 40: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
+	9,  // 41: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
+	47, // 42: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
+	39, // 43: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 44: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 45: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 46: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 47: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 48: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 49: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 50: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 51: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 52: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 53: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 54: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	10, // 55: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
+	39, // 56: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 57: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	49, // 58: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
+	11, // 59: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
+	12, // 60: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
+	13, // 61: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
+	14, // 62: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
+	15, // 63: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
+	16, // 64: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
+	17, // 65: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
+	18, // 66: google.protobuf.FeatureSet.default_symbol_visibility:type_name -> google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	51, // 67: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	0,  // 68: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
+	0,  // 69: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
+	52, // 70: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
+	53, // 71: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
+	23, // 72: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
+	0,  // 73: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
+	0,  // 74: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
+	0,  // 75: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
+	0,  // 76: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
+	0,  // 77: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
+	39, // 78: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
+	39, // 79: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
+	19, // 80: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	81, // [81:81] is the sub-list for method output_type
+	81, // [81:81] is the sub-list for method input_type
+	81, // [81:81] is the sub-list for extension type_name
+	81, // [81:81] is the sub-list for extension extendee
+	0,  // [0:81] is the sub-list for field type_name
 }
 
 func init() { file_google_protobuf_descriptor_proto_init() }
@@ -4983,8 +5222,8 @@ func file_google_protobuf_descriptor_proto_init() {
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_protobuf_descriptor_proto_rawDesc), len(file_google_protobuf_descriptor_proto_rawDesc)),
-			NumEnums:      18,
-			NumMessages:   33,
+			NumEnums:      20,
+			NumMessages:   34,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/event-processor/vendor/gopkg.in/ini.v1/.editorconfig b/event-processor/vendor/gopkg.in/ini.v1/.editorconfig
deleted file mode 100644
index 4a2d9180..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# http://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*_test.go]
-trim_trailing_whitespace = false
diff --git a/event-processor/vendor/gopkg.in/ini.v1/.gitignore b/event-processor/vendor/gopkg.in/ini.v1/.gitignore
deleted file mode 100644
index 588388bd..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-testdata/conf_out.ini
-ini.sublime-project
-ini.sublime-workspace
-testdata/conf_reflect.ini
-.idea
-/.vscode
-.DS_Store
diff --git a/event-processor/vendor/gopkg.in/ini.v1/.golangci.yml b/event-processor/vendor/gopkg.in/ini.v1/.golangci.yml
deleted file mode 100644
index 631e3692..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/.golangci.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-linters-settings:
-  staticcheck:
-    checks: [
-      "all",
-      "-SA1019" # There are valid use cases of strings.Title
-    ]
-  nakedret:
-    max-func-lines: 0 # Disallow any unnamed return statement
-
-linters:
-  enable:
-    - deadcode
-    - errcheck
-    - gosimple
-    - govet
-    - ineffassign
-    - staticcheck
-    - structcheck
-    - typecheck
-    - unused
-    - varcheck
-    - nakedret
-    - gofmt
-    - rowserrcheck
-    - unconvert
-    - goimports
-    - unparam
diff --git a/event-processor/vendor/gopkg.in/ini.v1/LICENSE b/event-processor/vendor/gopkg.in/ini.v1/LICENSE
deleted file mode 100644
index d361bbcd..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the Work and such
-Derivative Works in Source or Object form.
-
-3. Grant of Patent License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable (except as stated in this section) patent license to make, have
-made, use, offer to sell, sell, import, and otherwise transfer the Work, where
-such license applies only to those patent claims licensable by such Contributor
-that are necessarily infringed by their Contribution(s) alone or by combination
-of their Contribution(s) with the Work to which such Contribution(s) was
-submitted. If You institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work or a
-Contribution incorporated within the Work constitutes direct or contributory
-patent infringement, then any patent licenses granted to You under this License
-for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.
-
-You may reproduce and distribute copies of the Work or Derivative Works thereof
-in any medium, with or without modifications, and in Source or Object form,
-provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of
-this License; and
-You must cause any modified files to carry prominent notices stating that You
-changed the files; and
-You must retain, in the Source form of any Derivative Works that You distribute,
-all copyright, patent, trademark, and attribution notices from the Source form
-of the Work, excluding those notices that do not pertain to any part of the
-Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any
-Derivative Works that You distribute must include a readable copy of the
-attribution notices contained within such NOTICE file, excluding those notices
-that do not pertain to any part of the Derivative Works, in at least one of the
-following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions.
-
-Unless You explicitly state otherwise, any Contribution intentionally submitted
-for inclusion in the Work by You to the Licensor shall be under the terms and
-conditions of this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify the terms of
-any separate license agreement you may have executed with Licensor regarding
-such Contributions.
-
-6. Trademarks.
-
-This License does not grant permission to use the trade names, trademarks,
-service marks, or product names of the Licensor, except as required for
-reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty.
-
-Unless required by applicable law or agreed to in writing, Licensor provides the
-Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
-including, without limitation, any warranties or conditions of TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
-solely responsible for determining the appropriateness of using or
-redistributing the Work and assume any risks associated with Your exercise of
-permissions under this License.
-
-8. Limitation of Liability.
-
-In no event and under no legal theory, whether in tort (including negligence),
-contract, or otherwise, unless required by applicable law (such as deliberate
-and grossly negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special, incidental,
-or consequential damages of any character arising as a result of this License or
-out of the use or inability to use the Work (including but not limited to
-damages for loss of goodwill, work stoppage, computer failure or malfunction, or
-any and all other commercial damages or losses), even if such Contributor has
-been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability.
-
-While redistributing the Work or Derivative Works thereof, You may choose to
-offer, and charge a fee for, acceptance of support, warranty, indemnity, or
-other liability obligations and/or rights consistent with this License. However,
-in accepting such obligations, You may act only on Your own behalf and on Your
-sole responsibility, not on behalf of any other Contributor, and only if You
-agree to indemnify, defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason of your
-accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work
-
-To apply the Apache License to your work, attach the following boilerplate
-notice, with the fields enclosed by brackets "[]" replaced with your own
-identifying information. (Don't include the brackets!) The text should be
-enclosed in the appropriate comment syntax for the file format. We also
-recommend that a file or class name and description of purpose be included on
-the same "printed page" as the copyright notice for easier identification within
-third-party archives.
-
-   Copyright 2014 Unknwon
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/event-processor/vendor/gopkg.in/ini.v1/Makefile b/event-processor/vendor/gopkg.in/ini.v1/Makefile
deleted file mode 100644
index f3b0dae2..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-.PHONY: build test bench vet coverage
-
-build: vet bench
-
-test:
-	go test -v -cover -race
-
-bench:
-	go test -v -cover -test.bench=. -test.benchmem
-
-vet:
-	go vet
-
-coverage:
-	go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
diff --git a/event-processor/vendor/gopkg.in/ini.v1/README.md b/event-processor/vendor/gopkg.in/ini.v1/README.md
deleted file mode 100644
index 30606d97..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# INI
-
-[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain)
-[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini)
-[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc)
-[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini)
-
-![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
-
-Package ini provides INI file read and write functionality in Go.
-
-## Features
-
-- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites.
-- Read with recursion values.
-- Read with parent-child sections.
-- Read with auto-increment key names.
-- Read with multiple-line values.
-- Read with tons of helper methods.
-- Read and convert values to Go types.
-- Read and **WRITE** comments of sections and keys.
-- Manipulate sections, keys and comments with ease.
-- Keep sections and keys in order as you parse and save.
-
-## Installation
-
-The minimum requirement of Go is **1.13**.
-
-```sh
-$ go get gopkg.in/ini.v1
-```
-
-Please add `-u` flag to update in the future.
-
-## Getting Help
-
-- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started)
-- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
-- 中国大陆镜像:https://ini.unknwon.cn
-
-## License
-
-This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
diff --git a/event-processor/vendor/gopkg.in/ini.v1/codecov.yml b/event-processor/vendor/gopkg.in/ini.v1/codecov.yml
deleted file mode 100644
index e02ec84b..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/codecov.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-coverage:
-  range: "60...95"
-  status:
-    project:
-      default:
-        threshold: 1%
-        informational: true
-    patch:
-      defualt:
-        only_pulls: true
-        informational: true
-
-comment:
-  layout: 'diff'
-
-github_checks: false
diff --git a/event-processor/vendor/gopkg.in/ini.v1/data_source.go b/event-processor/vendor/gopkg.in/ini.v1/data_source.go
deleted file mode 100644
index c3a541f1..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/data_source.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-)
-
-var (
-	_ dataSource = (*sourceFile)(nil)
-	_ dataSource = (*sourceData)(nil)
-	_ dataSource = (*sourceReadCloser)(nil)
-)
-
-// dataSource is an interface that returns object which can be read and closed.
-type dataSource interface {
-	ReadCloser() (io.ReadCloser, error)
-}
-
-// sourceFile represents an object that contains content on the local file system.
-type sourceFile struct {
-	name string
-}
-
-func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
-	return os.Open(s.name)
-}
-
-// sourceData represents an object that contains content in memory.
-type sourceData struct {
-	data []byte
-}
-
-func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewReader(s.data)), nil
-}
-
-// sourceReadCloser represents an input stream with Close method.
-type sourceReadCloser struct {
-	reader io.ReadCloser
-}
-
-func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
-	return s.reader, nil
-}
-
-func parseDataSource(source interface{}) (dataSource, error) {
-	switch s := source.(type) {
-	case string:
-		return sourceFile{s}, nil
-	case []byte:
-		return &sourceData{s}, nil
-	case io.ReadCloser:
-		return &sourceReadCloser{s}, nil
-	case io.Reader:
-		return &sourceReadCloser{ioutil.NopCloser(s)}, nil
-	default:
-		return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
-	}
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/deprecated.go b/event-processor/vendor/gopkg.in/ini.v1/deprecated.go
deleted file mode 100644
index 48b8e66d..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/deprecated.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-var (
-	// Deprecated: Use "DefaultSection" instead.
-	DEFAULT_SECTION = DefaultSection
-	// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
-	AllCapsUnderscore = SnackCase
-)
diff --git a/event-processor/vendor/gopkg.in/ini.v1/error.go b/event-processor/vendor/gopkg.in/ini.v1/error.go
deleted file mode 100644
index f66bc94b..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/error.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"fmt"
-)
-
-// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
-type ErrDelimiterNotFound struct {
-	Line string
-}
-
-// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
-func IsErrDelimiterNotFound(err error) bool {
-	_, ok := err.(ErrDelimiterNotFound)
-	return ok
-}
-
-func (err ErrDelimiterNotFound) Error() string {
-	return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
-}
-
-// ErrEmptyKeyName indicates the error type of no key name is found which there should be one.
-type ErrEmptyKeyName struct {
-	Line string
-}
-
-// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName.
-func IsErrEmptyKeyName(err error) bool {
-	_, ok := err.(ErrEmptyKeyName)
-	return ok
-}
-
-func (err ErrEmptyKeyName) Error() string {
-	return fmt.Sprintf("empty key name: %s", err.Line)
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/file.go b/event-processor/vendor/gopkg.in/ini.v1/file.go
deleted file mode 100644
index f8b22408..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/file.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2017 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"sync"
-)
-
-// File represents a combination of one or more INI files in memory.
-type File struct {
-	options     LoadOptions
-	dataSources []dataSource
-
-	// Should make things safe, but sometimes doesn't matter.
-	BlockMode bool
-	lock      sync.RWMutex
-
-	// To keep data in order.
-	sectionList []string
-	// To keep track of the index of a section with same name.
-	// This meta list is only used with non-unique section names are allowed.
-	sectionIndexes []int
-
-	// Actual data is stored here.
-	sections map[string][]*Section
-
-	NameMapper
-	ValueMapper
-}
-
-// newFile initializes File object with given data sources.
-func newFile(dataSources []dataSource, opts LoadOptions) *File {
-	if len(opts.KeyValueDelimiters) == 0 {
-		opts.KeyValueDelimiters = "=:"
-	}
-	if len(opts.KeyValueDelimiterOnWrite) == 0 {
-		opts.KeyValueDelimiterOnWrite = "="
-	}
-	if len(opts.ChildSectionDelimiter) == 0 {
-		opts.ChildSectionDelimiter = "."
-	}
-
-	return &File{
-		BlockMode:   true,
-		dataSources: dataSources,
-		sections:    make(map[string][]*Section),
-		options:     opts,
-	}
-}
-
-// Empty returns an empty file object.
-func Empty(opts ...LoadOptions) *File {
-	var opt LoadOptions
-	if len(opts) > 0 {
-		opt = opts[0]
-	}
-
-	// Ignore error here, we are sure our data is good.
-	f, _ := LoadSources(opt, []byte(""))
-	return f
-}
-
-// NewSection creates a new section.
-func (f *File) NewSection(name string) (*Section, error) {
-	if len(name) == 0 {
-		return nil, errors.New("empty section name")
-	}
-
-	if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) {
-		return f.sections[name][0], nil
-	}
-
-	f.sectionList = append(f.sectionList, name)
-
-	// NOTE: Append to indexes must happen before appending to sections,
-	// otherwise index will have off-by-one problem.
-	f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name]))
-
-	sec := newSection(f, name)
-	f.sections[name] = append(f.sections[name], sec)
-
-	return sec, nil
-}
-
-// NewRawSection creates a new section with an unparseable body.
-func (f *File) NewRawSection(name, body string) (*Section, error) {
-	section, err := f.NewSection(name)
-	if err != nil {
-		return nil, err
-	}
-
-	section.isRawSection = true
-	section.rawBody = body
-	return section, nil
-}
-
-// NewSections creates a list of sections.
-func (f *File) NewSections(names ...string) (err error) {
-	for _, name := range names {
-		if _, err = f.NewSection(name); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// GetSection returns section by given name.
-func (f *File) GetSection(name string) (*Section, error) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return nil, err
-	}
-
-	return secs[0], err
-}
-
-// HasSection returns true if the file contains a section with given name.
-func (f *File) HasSection(name string) bool {
-	section, _ := f.GetSection(name)
-	return section != nil
-}
-
-// SectionsByName returns all sections with given name.
-func (f *File) SectionsByName(name string) ([]*Section, error) {
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	secs := f.sections[name]
-	if len(secs) == 0 {
-		return nil, fmt.Errorf("section %q does not exist", name)
-	}
-
-	return secs, nil
-}
-
-// Section assumes named section exists and returns a zero-value when not.
-func (f *File) Section(name string) *Section {
-	sec, err := f.GetSection(name)
-	if err != nil {
-		if name == "" {
-			name = DefaultSection
-		}
-		sec, _ = f.NewSection(name)
-		return sec
-	}
-	return sec
-}
-
-// SectionWithIndex assumes named section exists and returns a new section when not.
-func (f *File) SectionWithIndex(name string, index int) *Section {
-	secs, err := f.SectionsByName(name)
-	if err != nil || len(secs) <= index {
-		// NOTE: It's OK here because the only possible error is empty section name,
-		// but if it's empty, this piece of code won't be executed.
-		newSec, _ := f.NewSection(name)
-		return newSec
-	}
-
-	return secs[index]
-}
-
-// Sections returns a list of Section stored in the current instance.
-func (f *File) Sections() []*Section {
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	sections := make([]*Section, len(f.sectionList))
-	for i, name := range f.sectionList {
-		sections[i] = f.sections[name][f.sectionIndexes[i]]
-	}
-	return sections
-}
-
-// ChildSections returns a list of child sections of given section name.
-func (f *File) ChildSections(name string) []*Section {
-	return f.Section(name).ChildSections()
-}
-
-// SectionStrings returns list of section names.
-func (f *File) SectionStrings() []string {
-	list := make([]string, len(f.sectionList))
-	copy(list, f.sectionList)
-	return list
-}
-
-// DeleteSection deletes a section or all sections with given name.
-func (f *File) DeleteSection(name string) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(secs); i++ {
-		// For non-unique sections, it is always needed to remove the first one so
-		// in the next iteration, the subsequent section continue having index 0.
-		// Ignoring the error as index 0 never returns an error.
-		_ = f.DeleteSectionWithIndex(name, 0)
-	}
-}
-
-// DeleteSectionWithIndex deletes a section with given name and index.
-func (f *File) DeleteSectionWithIndex(name string, index int) error {
-	if !f.options.AllowNonUniqueSections && index != 0 {
-		return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled")
-	}
-
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	// Count occurrences of the sections
-	occurrences := 0
-
-	sectionListCopy := make([]string, len(f.sectionList))
-	copy(sectionListCopy, f.sectionList)
-
-	for i, s := range sectionListCopy {
-		if s != name {
-			continue
-		}
-
-		if occurrences == index {
-			if len(f.sections[name]) <= 1 {
-				delete(f.sections, name) // The last one in the map
-			} else {
-				f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...)
-			}
-
-			// Fix section lists
-			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
-			f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...)
-
-		} else if occurrences > index {
-			// Fix the indices of all following sections with this name.
-			f.sectionIndexes[i-1]--
-		}
-
-		occurrences++
-	}
-
-	return nil
-}
-
-func (f *File) reload(s dataSource) error {
-	r, err := s.ReadCloser()
-	if err != nil {
-		return err
-	}
-	defer r.Close()
-
-	return f.parse(r)
-}
-
-// Reload reloads and parses all data sources.
-func (f *File) Reload() (err error) {
-	for _, s := range f.dataSources {
-		if err = f.reload(s); err != nil {
-			// In loose mode, we create an empty default section for nonexistent files.
-			if os.IsNotExist(err) && f.options.Loose {
-				_ = f.parse(bytes.NewBuffer(nil))
-				continue
-			}
-			return err
-		}
-		if f.options.ShortCircuit {
-			return nil
-		}
-	}
-	return nil
-}
-
-// Append appends one or more data sources and reloads automatically.
-func (f *File) Append(source interface{}, others ...interface{}) error {
-	ds, err := parseDataSource(source)
-	if err != nil {
-		return err
-	}
-	f.dataSources = append(f.dataSources, ds)
-	for _, s := range others {
-		ds, err = parseDataSource(s)
-		if err != nil {
-			return err
-		}
-		f.dataSources = append(f.dataSources, ds)
-	}
-	return f.Reload()
-}
-
-func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
-	equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight
-
-	if PrettyFormat || PrettyEqual {
-		equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite)
-	}
-
-	// Use buffer to make sure target is safe until finish encoding.
-	buf := bytes.NewBuffer(nil)
-	lastSectionIdx := len(f.sectionList) - 1
-	for i, sname := range f.sectionList {
-		sec := f.SectionWithIndex(sname, f.sectionIndexes[i])
-		if len(sec.Comment) > 0 {
-			// Support multiline comments
-			lines := strings.Split(sec.Comment, LineBreak)
-			for i := range lines {
-				if lines[i][0] != '#' && lines[i][0] != ';' {
-					lines[i] = "; " + lines[i]
-				} else {
-					lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-				}
-
-				if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) {
-			if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
-				return nil, err
-			}
-		} else {
-			// Write nothing if default section is empty
-			if len(sec.keyList) == 0 {
-				continue
-			}
-		}
-
-		isLastSection := i == lastSectionIdx
-		if sec.isRawSection {
-			if _, err := buf.WriteString(sec.rawBody); err != nil {
-				return nil, err
-			}
-
-			if PrettySection && !isLastSection {
-				// Put a line between sections
-				if _, err := buf.WriteString(LineBreak); err != nil {
-					return nil, err
-				}
-			}
-			continue
-		}
-
-		// Count and generate alignment length and buffer spaces using the
-		// longest key. Keys may be modified if they contain certain characters so
-		// we need to take that into account in our calculation.
-		alignLength := 0
-		if PrettyFormat {
-			for _, kname := range sec.keyList {
-				keyLength := len(kname)
-				// First case will surround key by ` and second by """
-				if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) {
-					keyLength += 2
-				} else if strings.Contains(kname, "`") {
-					keyLength += 6
-				}
-
-				if keyLength > alignLength {
-					alignLength = keyLength
-				}
-			}
-		}
-		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
-
-	KeyList:
-		for _, kname := range sec.keyList {
-			key := sec.Key(kname)
-			if len(key.Comment) > 0 {
-				if len(indent) > 0 && sname != DefaultSection {
-					buf.WriteString(indent)
-				}
-
-				// Support multiline comments
-				lines := strings.Split(key.Comment, LineBreak)
-				for i := range lines {
-					if lines[i][0] != '#' && lines[i][0] != ';' {
-						lines[i] = "; " + strings.TrimSpace(lines[i])
-					} else {
-						lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-					}
-
-					if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-						return nil, err
-					}
-				}
-			}
-
-			if len(indent) > 0 && sname != DefaultSection {
-				buf.WriteString(indent)
-			}
-
-			switch {
-			case key.isAutoIncrement:
-				kname = "-"
-			case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters):
-				kname = "`" + kname + "`"
-			case strings.Contains(kname, "`"):
-				kname = `"""` + kname + `"""`
-			}
-
-			writeKeyValue := func(val string) (bool, error) {
-				if _, err := buf.WriteString(kname); err != nil {
-					return false, err
-				}
-
-				if key.isBooleanType {
-					buf.WriteString(LineBreak)
-					return true, nil
-				}
-
-				// Write out alignment spaces before "=" sign
-				if PrettyFormat {
-					buf.Write(alignSpaces[:alignLength-len(kname)])
-				}
-
-				// In case key value contains "\n", "`", "\"", "#" or ";"
-				if strings.ContainsAny(val, "\n`") {
-					val = `"""` + val + `"""`
-				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
-					val = "`" + val + "`"
-				} else if len(strings.TrimSpace(val)) != len(val) {
-					val = `"` + val + `"`
-				}
-				if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
-					return false, err
-				}
-				return false, nil
-			}
-
-			shadows := key.ValueWithShadows()
-			if len(shadows) == 0 {
-				if _, err := writeKeyValue(""); err != nil {
-					return nil, err
-				}
-			}
-
-			for _, val := range shadows {
-				exitLoop, err := writeKeyValue(val)
-				if err != nil {
-					return nil, err
-				} else if exitLoop {
-					continue KeyList
-				}
-			}
-
-			for _, val := range key.nestedValues {
-				if _, err := buf.WriteString(indent + "  " + val + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if PrettySection && !isLastSection {
-			// Put a line between sections
-			if _, err := buf.WriteString(LineBreak); err != nil {
-				return nil, err
-			}
-		}
-	}
-
-	return buf, nil
-}
-
-// WriteToIndent writes content into io.Writer with given indention.
-// If PrettyFormat has been set to be true,
-// it will align "=" sign with spaces under each section.
-func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return 0, err
-	}
-	return buf.WriteTo(w)
-}
-
-// WriteTo writes file content into io.Writer.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
-	return f.WriteToIndent(w, "")
-}
-
-// SaveToIndent writes content to file system with given value indention.
-func (f *File) SaveToIndent(filename, indent string) error {
-	// Note: Because we are truncating with os.Create,
-	// 	so it's safer to save to a temporary file location and rename after done.
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return err
-	}
-
-	return ioutil.WriteFile(filename, buf.Bytes(), 0666)
-}
-
-// SaveTo writes content to file system.
-func (f *File) SaveTo(filename string) error {
-	return f.SaveToIndent(filename, "")
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/helper.go b/event-processor/vendor/gopkg.in/ini.v1/helper.go
deleted file mode 100644
index f9d80a68..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/helper.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-func inSlice(str string, s []string) bool {
-	for _, v := range s {
-		if str == v {
-			return true
-		}
-	}
-	return false
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/ini.go b/event-processor/vendor/gopkg.in/ini.v1/ini.go
deleted file mode 100644
index 99e7f865..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/ini.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-// Package ini provides INI file read and write functionality in Go.
-package ini
-
-import (
-	"os"
-	"regexp"
-	"runtime"
-	"strings"
-)
-
-const (
-	// Maximum allowed depth when recursively substituing variable names.
-	depthValues = 99
-)
-
-var (
-	// DefaultSection is the name of default section. You can use this var or the string literal.
-	// In most of cases, an empty string is all you need to access the section.
-	DefaultSection = "DEFAULT"
-
-	// LineBreak is the delimiter to determine or compose a new line.
-	// This variable will be changed to "\r\n" automatically on Windows at package init time.
-	LineBreak = "\n"
-
-	// Variable regexp pattern: %(variable)s
-	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)
-
-	// DefaultHeader explicitly writes default section header.
-	DefaultHeader = false
-
-	// PrettySection indicates whether to put a line between sections.
-	PrettySection = true
-	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
-	// or reduce all possible spaces for compact format.
-	PrettyFormat = true
-	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
-	PrettyEqual = false
-	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatLeft = ""
-	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatRight = ""
-)
-
-var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
-
-func init() {
-	if runtime.GOOS == "windows" && !inTest {
-		LineBreak = "\r\n"
-	}
-}
-
-// LoadOptions contains all customized options used for load data source(s).
-type LoadOptions struct {
-	// Loose indicates whether the parser should ignore nonexistent files or return error.
-	Loose bool
-	// Insensitive indicates whether the parser forces all section and key names to lowercase.
-	Insensitive bool
-	// InsensitiveSections indicates whether the parser forces all section to lowercase.
-	InsensitiveSections bool
-	// InsensitiveKeys indicates whether the parser forces all key names to lowercase.
-	InsensitiveKeys bool
-	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
-	IgnoreContinuation bool
-	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
-	IgnoreInlineComment bool
-	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs.
-	SkipUnrecognizableLines bool
-	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source.
-	ShortCircuit bool
-	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
-	// This type of keys are mostly used in my.cnf.
-	AllowBooleanKeys bool
-	// AllowShadows indicates whether to keep track of keys with same name under same section.
-	AllowShadows bool
-	// AllowNestedValues indicates whether to allow AWS-like nested values.
-	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
-	AllowNestedValues bool
-	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values.
-	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
-	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper
-	// than the first line of the value.
-	AllowPythonMultilineValues bool
-	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
-	// Docs: https://docs.python.org/2/library/configparser.html
-	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
-	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
-	SpaceBeforeInlineComment bool
-	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
-	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
-	UnescapeValueDoubleQuotes bool
-	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
-	// when value is NOT surrounded by any quotes.
-	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
-	UnescapeValueCommentSymbols bool
-	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
-	// conform to key/value pairs. Specify the names of those blocks here.
-	UnparseableSections []string
-	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
-	KeyValueDelimiters string
-	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=".
-	KeyValueDelimiterOnWrite string
-	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
-	ChildSectionDelimiter string
-	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
-	PreserveSurroundedQuote bool
-	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
-	DebugFunc DebugFunc
-	// ReaderBufferSize is the buffer size of the reader in bytes.
-	ReaderBufferSize int
-	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
-	AllowNonUniqueSections bool
-	// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated.
-	AllowDuplicateShadowValues bool
-}
-
-// DebugFunc is the type of function called to log parse events.
-type DebugFunc func(message string)
-
-// LoadSources allows caller to apply customized options for loading from data source(s).
-func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
-	sources := make([]dataSource, len(others)+1)
-	sources[0], err = parseDataSource(source)
-	if err != nil {
-		return nil, err
-	}
-	for i := range others {
-		sources[i+1], err = parseDataSource(others[i])
-		if err != nil {
-			return nil, err
-		}
-	}
-	f := newFile(sources, opts)
-	if err = f.Reload(); err != nil {
-		return nil, err
-	}
-	return f, nil
-}
-
-// Load loads and parses from INI data sources.
-// Arguments can be mixed of file name with string type, or raw data in []byte.
-// It will return error if list contains nonexistent files.
-func Load(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{}, source, others...)
-}
-
-// LooseLoad has exactly same functionality as Load function
-// except it ignores nonexistent files instead of returning error.
-func LooseLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Loose: true}, source, others...)
-}
-
-// InsensitiveLoad has exactly same functionality as Load function
-// except it forces all section and key names to be lowercased.
-func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
-}
-
-// ShadowLoad has exactly same functionality as Load function
-// except it allows have shadow keys.
-func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/key.go b/event-processor/vendor/gopkg.in/ini.v1/key.go
deleted file mode 100644
index a19d9f38..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/key.go
+++ /dev/null
@@ -1,837 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Key represents a key under a section.
-type Key struct {
-	s               *Section
-	Comment         string
-	name            string
-	value           string
-	isAutoIncrement bool
-	isBooleanType   bool
-
-	isShadow bool
-	shadows  []*Key
-
-	nestedValues []string
-}
-
-// newKey simply return a key object with given values.
-func newKey(s *Section, name, val string) *Key {
-	return &Key{
-		s:     s,
-		name:  name,
-		value: val,
-	}
-}
-
-func (k *Key) addShadow(val string) error {
-	if k.isShadow {
-		return errors.New("cannot add shadow to another shadow key")
-	} else if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add shadow to auto-increment or boolean key")
-	}
-
-	if !k.s.f.options.AllowDuplicateShadowValues {
-		// Deduplicate shadows based on their values.
-		if k.value == val {
-			return nil
-		}
-		for i := range k.shadows {
-			if k.shadows[i].value == val {
-				return nil
-			}
-		}
-	}
-
-	shadow := newKey(k.s, k.name, val)
-	shadow.isShadow = true
-	k.shadows = append(k.shadows, shadow)
-	return nil
-}
-
-// AddShadow adds a new shadow key to itself.
-func (k *Key) AddShadow(val string) error {
-	if !k.s.f.options.AllowShadows {
-		return errors.New("shadow key is not allowed")
-	}
-	return k.addShadow(val)
-}
-
-func (k *Key) addNestedValue(val string) error {
-	if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add nested value to auto-increment or boolean key")
-	}
-
-	k.nestedValues = append(k.nestedValues, val)
-	return nil
-}
-
-// AddNestedValue adds a nested value to the key.
-func (k *Key) AddNestedValue(val string) error {
-	if !k.s.f.options.AllowNestedValues {
-		return errors.New("nested value is not allowed")
-	}
-	return k.addNestedValue(val)
-}
-
-// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
-type ValueMapper func(string) string
-
-// Name returns name of key.
-func (k *Key) Name() string {
-	return k.name
-}
-
-// Value returns raw value of key for performance purpose.
-func (k *Key) Value() string {
-	return k.value
-}
-
-// ValueWithShadows returns raw values of key and its shadows if any. Shadow
-// keys with empty values are ignored from the returned list.
-func (k *Key) ValueWithShadows() []string {
-	if len(k.shadows) == 0 {
-		if k.value == "" {
-			return []string{}
-		}
-		return []string{k.value}
-	}
-
-	vals := make([]string, 0, len(k.shadows)+1)
-	if k.value != "" {
-		vals = append(vals, k.value)
-	}
-	for _, s := range k.shadows {
-		if s.value != "" {
-			vals = append(vals, s.value)
-		}
-	}
-	return vals
-}
-
-// NestedValues returns nested values stored in the key.
-// It is possible returned value is nil if no nested values stored in the key.
-func (k *Key) NestedValues() []string {
-	return k.nestedValues
-}
-
-// transformValue takes a raw value and transforms to its final string.
-func (k *Key) transformValue(val string) string {
-	if k.s.f.ValueMapper != nil {
-		val = k.s.f.ValueMapper(val)
-	}
-
-	// Fail-fast if no indicate char found for recursive value
-	if !strings.Contains(val, "%") {
-		return val
-	}
-	for i := 0; i < depthValues; i++ {
-		vr := varPattern.FindString(val)
-		if len(vr) == 0 {
-			break
-		}
-
-		// Take off leading '%(' and trailing ')s'.
-		noption := vr[2 : len(vr)-2]
-
-		// Search in the same section.
-		// If not found or found the key itself, then search again in default section.
-		nk, err := k.s.GetKey(noption)
-		if err != nil || k == nk {
-			nk, _ = k.s.f.Section("").GetKey(noption)
-			if nk == nil {
-				// Stop when no results found in the default section,
-				// and returns the value as-is.
-				break
-			}
-		}
-
-		// Substitute by new value and take off leading '%(' and trailing ')s'.
-		val = strings.Replace(val, vr, nk.value, -1)
-	}
-	return val
-}
-
-// String returns string representation of value.
-func (k *Key) String() string {
-	return k.transformValue(k.value)
-}
-
-// Validate accepts a validate function which can
-// return modifed result as key value.
-func (k *Key) Validate(fn func(string) string) string {
-	return fn(k.String())
-}
-
-// parseBool returns the boolean value represented by the string.
-//
-// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
-// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
-// Any other value returns an error.
-func parseBool(str string) (value bool, err error) {
-	switch str {
-	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
-		return true, nil
-	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
-		return false, nil
-	}
-	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
-}
-
-// Bool returns bool type value.
-func (k *Key) Bool() (bool, error) {
-	return parseBool(k.String())
-}
-
-// Float64 returns float64 type value.
-func (k *Key) Float64() (float64, error) {
-	return strconv.ParseFloat(k.String(), 64)
-}
-
-// Int returns int type value.
-func (k *Key) Int() (int, error) {
-	v, err := strconv.ParseInt(k.String(), 0, 64)
-	return int(v), err
-}
-
-// Int64 returns int64 type value.
-func (k *Key) Int64() (int64, error) {
-	return strconv.ParseInt(k.String(), 0, 64)
-}
-
-// Uint returns uint type valued.
-func (k *Key) Uint() (uint, error) {
-	u, e := strconv.ParseUint(k.String(), 0, 64)
-	return uint(u), e
-}
-
-// Uint64 returns uint64 type value.
-func (k *Key) Uint64() (uint64, error) {
-	return strconv.ParseUint(k.String(), 0, 64)
-}
-
-// Duration returns time.Duration type value.
-func (k *Key) Duration() (time.Duration, error) {
-	return time.ParseDuration(k.String())
-}
-
-// TimeFormat parses with given format and returns time.Time type value.
-func (k *Key) TimeFormat(format string) (time.Time, error) {
-	return time.Parse(format, k.String())
-}
-
-// Time parses with RFC3339 format and returns time.Time type value.
-func (k *Key) Time() (time.Time, error) {
-	return k.TimeFormat(time.RFC3339)
-}
-
-// MustString returns default value if key value is empty.
-func (k *Key) MustString(defaultVal string) string {
-	val := k.String()
-	if len(val) == 0 {
-		k.value = defaultVal
-		return defaultVal
-	}
-	return val
-}
-
-// MustBool always returns value without error,
-// it returns false if error occurs.
-func (k *Key) MustBool(defaultVal ...bool) bool {
-	val, err := k.Bool()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatBool(defaultVal[0])
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustFloat64 always returns value without error,
-// it returns 0.0 if error occurs.
-func (k *Key) MustFloat64(defaultVal ...float64) float64 {
-	val, err := k.Float64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt(defaultVal ...int) int {
-	val, err := k.Int()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt64(defaultVal ...int64) int64 {
-	val, err := k.Int64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint(defaultVal ...uint) uint {
-	val, err := k.Uint()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
-	val, err := k.Uint64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustDuration always returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
-	val, err := k.Duration()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].String()
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTimeFormat always parses with given format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
-	val, err := k.TimeFormat(format)
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].Format(format)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTime always parses with RFC3339 format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
-	return k.MustTimeFormat(time.RFC3339, defaultVal...)
-}
-
-// In always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) In(defaultVal string, candidates []string) string {
-	val := k.String()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InFloat64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
-	val := k.MustFloat64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt(defaultVal int, candidates []int) int {
-	val := k.MustInt()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
-	val := k.MustInt64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
-	val := k.MustUint()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
-	val := k.MustUint64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTimeFormat always parses with given format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTime always parses with RFC3339 format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
-	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
-}
-
-// RangeFloat64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
-	val := k.MustFloat64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt(defaultVal, min, max int) int {
-	val := k.MustInt()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
-	val := k.MustInt64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTimeFormat checks if value with given format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTime checks if value with RFC3339 format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
-	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
-}
-
-// Strings returns list of string divided by given delimiter.
-func (k *Key) Strings(delim string) []string {
-	str := k.String()
-	if len(str) == 0 {
-		return []string{}
-	}
-
-	runes := []rune(str)
-	vals := make([]string, 0, 2)
-	var buf bytes.Buffer
-	escape := false
-	idx := 0
-	for {
-		if escape {
-			escape = false
-			if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
-				buf.WriteRune('\\')
-			}
-			buf.WriteRune(runes[idx])
-		} else {
-			if runes[idx] == '\\' {
-				escape = true
-			} else if strings.HasPrefix(string(runes[idx:]), delim) {
-				idx += len(delim) - 1
-				vals = append(vals, strings.TrimSpace(buf.String()))
-				buf.Reset()
-			} else {
-				buf.WriteRune(runes[idx])
-			}
-		}
-		idx++
-		if idx == len(runes) {
-			break
-		}
-	}
-
-	if buf.Len() > 0 {
-		vals = append(vals, strings.TrimSpace(buf.String()))
-	}
-
-	return vals
-}
-
-// StringsWithShadows returns list of string divided by given delimiter.
-// Shadows will also be appended if any.
-func (k *Key) StringsWithShadows(delim string) []string {
-	vals := k.ValueWithShadows()
-	results := make([]string, 0, len(vals)*2)
-	for i := range vals {
-		if len(vals) == 0 {
-			continue
-		}
-
-		results = append(results, strings.Split(vals[i], delim)...)
-	}
-
-	for i := range results {
-		results[i] = k.transformValue(strings.TrimSpace(results[i]))
-	}
-	return results
-}
-
-// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Float64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Ints(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), true, false)
-	return vals
-}
-
-// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Int64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Bools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), true, false)
-	return vals
-}
-
-// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) TimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
-	return vals
-}
-
-// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) Times(delim string) []time.Time {
-	return k.TimesFormat(time.RFC3339, delim)
-}
-
-// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
-// it will not be included to result list.
-func (k *Key) ValidFloat64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
-// not be included to result list.
-func (k *Key) ValidInts(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
-// then it will not be included to result list.
-func (k *Key) ValidInt64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
-// then it will not be included to result list.
-func (k *Key) ValidUints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidUint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidBools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimes(delim string) []time.Time {
-	return k.ValidTimesFormat(time.RFC3339, delim)
-}
-
-// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
-	return k.parseFloat64s(k.Strings(delim), false, true)
-}
-
-// StrictInts returns list of int divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInts(delim string) ([]int, error) {
-	return k.parseInts(k.Strings(delim), false, true)
-}
-
-// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInt64s(delim string) ([]int64, error) {
-	return k.parseInt64s(k.Strings(delim), false, true)
-}
-
-// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUints(delim string) ([]uint, error) {
-	return k.parseUints(k.Strings(delim), false, true)
-}
-
-// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
-	return k.parseUint64s(k.Strings(delim), false, true)
-}
-
-// StrictBools returns list of bool divided by given delimiter or error on first invalid input.
-func (k *Key) StrictBools(delim string) ([]bool, error) {
-	return k.parseBools(k.Strings(delim), false, true)
-}
-
-// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
-	return k.parseTimesFormat(format, k.Strings(delim), false, true)
-}
-
-// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
-	return k.StrictTimesFormat(time.RFC3339, delim)
-}
-
-// parseBools transforms strings to bools.
-func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) {
-	vals := make([]bool, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := parseBool(str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(bool))
-		}
-	}
-	return vals, err
-}
-
-// parseFloat64s transforms strings to float64s.
-func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
-	vals := make([]float64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseFloat(str, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(float64))
-		}
-	}
-	return vals, err
-}
-
-// parseInts transforms strings to ints.
-func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
-	vals := make([]int, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, int(val.(int64)))
-		}
-	}
-	return vals, err
-}
-
-// parseInt64s transforms strings to int64s.
-func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
-	vals := make([]int64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(int64))
-		}
-	}
-	return vals, err
-}
-
-// parseUints transforms strings to uints.
-func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
-	vals := make([]uint, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, uint(val.(uint64)))
-		}
-	}
-	return vals, err
-}
-
-// parseUint64s transforms strings to uint64s.
-func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
-	vals := make([]uint64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(uint64))
-		}
-	}
-	return vals, err
-}
-
-type Parser func(str string) (interface{}, error)
-
-// parseTimesFormat transforms strings to times in given format.
-func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
-	vals := make([]time.Time, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := time.Parse(format, str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(time.Time))
-		}
-	}
-	return vals, err
-}
-
-// doParse transforms strings to different types
-func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) {
-	vals := make([]interface{}, 0, len(strs))
-	for _, str := range strs {
-		val, err := parser(str)
-		if err != nil && returnOnInvalid {
-			return nil, err
-		}
-		if err == nil || addInvalid {
-			vals = append(vals, val)
-		}
-	}
-	return vals, nil
-}
-
-// SetValue changes key value.
-func (k *Key) SetValue(v string) {
-	if k.s.f.BlockMode {
-		k.s.f.lock.Lock()
-		defer k.s.f.lock.Unlock()
-	}
-
-	k.value = v
-	k.s.keysHash[k.name] = v
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/parser.go b/event-processor/vendor/gopkg.in/ini.v1/parser.go
deleted file mode 100644
index 44fc526c..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/parser.go
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2015 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"regexp"
-	"strconv"
-	"strings"
-	"unicode"
-)
-
-const minReaderBufferSize = 4096
-
-var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`)
-
-type parserOptions struct {
-	IgnoreContinuation          bool
-	IgnoreInlineComment         bool
-	AllowPythonMultilineValues  bool
-	SpaceBeforeInlineComment    bool
-	UnescapeValueDoubleQuotes   bool
-	UnescapeValueCommentSymbols bool
-	PreserveSurroundedQuote     bool
-	DebugFunc                   DebugFunc
-	ReaderBufferSize            int
-}
-
-type parser struct {
-	buf     *bufio.Reader
-	options parserOptions
-
-	isEOF   bool
-	count   int
-	comment *bytes.Buffer
-}
-
-func (p *parser) debug(format string, args ...interface{}) {
-	if p.options.DebugFunc != nil {
-		p.options.DebugFunc(fmt.Sprintf(format, args...))
-	}
-}
-
-func newParser(r io.Reader, opts parserOptions) *parser {
-	size := opts.ReaderBufferSize
-	if size < minReaderBufferSize {
-		size = minReaderBufferSize
-	}
-
-	return &parser{
-		buf:     bufio.NewReaderSize(r, size),
-		options: opts,
-		count:   1,
-		comment: &bytes.Buffer{},
-	}
-}
-
-// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
-// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
-func (p *parser) BOM() error {
-	mask, err := p.buf.Peek(2)
-	if err != nil && err != io.EOF {
-		return err
-	} else if len(mask) < 2 {
-		return nil
-	}
-
-	switch {
-	case mask[0] == 254 && mask[1] == 255:
-		fallthrough
-	case mask[0] == 255 && mask[1] == 254:
-		_, err = p.buf.Read(mask)
-		if err != nil {
-			return err
-		}
-	case mask[0] == 239 && mask[1] == 187:
-		mask, err := p.buf.Peek(3)
-		if err != nil && err != io.EOF {
-			return err
-		} else if len(mask) < 3 {
-			return nil
-		}
-		if mask[2] == 191 {
-			_, err = p.buf.Read(mask)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func (p *parser) readUntil(delim byte) ([]byte, error) {
-	data, err := p.buf.ReadBytes(delim)
-	if err != nil {
-		if err == io.EOF {
-			p.isEOF = true
-		} else {
-			return nil, err
-		}
-	}
-	return data, nil
-}
-
-func cleanComment(in []byte) ([]byte, bool) {
-	i := bytes.IndexAny(in, "#;")
-	if i == -1 {
-		return nil, false
-	}
-	return in[i:], true
-}
-
-func readKeyName(delimiters string, in []byte) (string, int, error) {
-	line := string(in)
-
-	// Check if key name surrounded by quotes.
-	var keyQuote string
-	if line[0] == '"' {
-		if len(line) > 6 && line[0:3] == `"""` {
-			keyQuote = `"""`
-		} else {
-			keyQuote = `"`
-		}
-	} else if line[0] == '`' {
-		keyQuote = "`"
-	}
-
-	// Get out key name
-	var endIdx int
-	if len(keyQuote) > 0 {
-		startIdx := len(keyQuote)
-		// FIXME: fail case -> """"""name"""=value
-		pos := strings.Index(line[startIdx:], keyQuote)
-		if pos == -1 {
-			return "", -1, fmt.Errorf("missing closing key quote: %s", line)
-		}
-		pos += startIdx
-
-		// Find key-value delimiter
-		i := strings.IndexAny(line[pos+startIdx:], delimiters)
-		if i < 0 {
-			return "", -1, ErrDelimiterNotFound{line}
-		}
-		endIdx = pos + i
-		return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
-	}
-
-	endIdx = strings.IndexAny(line, delimiters)
-	if endIdx < 0 {
-		return "", -1, ErrDelimiterNotFound{line}
-	}
-	if endIdx == 0 {
-		return "", -1, ErrEmptyKeyName{line}
-	}
-
-	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
-}
-
-func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := string(data)
-
-		pos := strings.LastIndex(next, valQuote)
-		if pos > -1 {
-			val += next[:pos]
-
-			comment, has := cleanComment([]byte(next[pos:]))
-			if has {
-				p.comment.Write(bytes.TrimSpace(comment))
-			}
-			break
-		}
-		val += next
-		if p.isEOF {
-			return "", fmt.Errorf("missing closing key quote from %q to %q", line, next)
-		}
-	}
-	return val, nil
-}
-
-func (p *parser) readContinuationLines(val string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := strings.TrimSpace(string(data))
-
-		if len(next) == 0 {
-			break
-		}
-		val += next
-		if val[len(val)-1] != '\\' {
-			break
-		}
-		val = val[:len(val)-1]
-	}
-	return val, nil
-}
-
-// hasSurroundedQuote check if and only if the first and last characters
-// are quotes \" or \'.
-// It returns false if any other parts also contain same kind of quotes.
-func hasSurroundedQuote(in string, quote byte) bool {
-	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
-		strings.IndexByte(in[1:], quote) == len(in)-2
-}
-
-func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
-
-	line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
-	if len(line) == 0 {
-		if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
-			return p.readPythonMultilines(line, bufferSize)
-		}
-		return "", nil
-	}
-
-	var valQuote string
-	if len(line) > 3 && line[0:3] == `"""` {
-		valQuote = `"""`
-	} else if line[0] == '`' {
-		valQuote = "`"
-	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
-		valQuote = `"`
-	}
-
-	if len(valQuote) > 0 {
-		startIdx := len(valQuote)
-		pos := strings.LastIndex(line[startIdx:], valQuote)
-		// Check for multi-line value
-		if pos == -1 {
-			return p.readMultilines(line, line[startIdx:], valQuote)
-		}
-
-		if p.options.UnescapeValueDoubleQuotes && valQuote == `"` {
-			return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
-		}
-		return line[startIdx : pos+startIdx], nil
-	}
-
-	lastChar := line[len(line)-1]
-	// Won't be able to reach here if value only contains whitespace
-	line = strings.TrimSpace(line)
-	trimmedLastChar := line[len(line)-1]
-
-	// Check continuation lines when desired
-	if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
-		return p.readContinuationLines(line[:len(line)-1])
-	}
-
-	// Check if ignore inline comment
-	if !p.options.IgnoreInlineComment {
-		var i int
-		if p.options.SpaceBeforeInlineComment {
-			i = strings.Index(line, " #")
-			if i == -1 {
-				i = strings.Index(line, " ;")
-			}
-
-		} else {
-			i = strings.IndexAny(line, "#;")
-		}
-
-		if i > -1 {
-			p.comment.WriteString(line[i:])
-			line = strings.TrimSpace(line[:i])
-		}
-
-	}
-
-	// Trim single and double quotes
-	if (hasSurroundedQuote(line, '\'') ||
-		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
-		line = line[1 : len(line)-1]
-	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
-		line = strings.ReplaceAll(line, `\;`, ";")
-		line = strings.ReplaceAll(line, `\#`, "#")
-	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
-		return p.readPythonMultilines(line, bufferSize)
-	}
-
-	return line, nil
-}
-
-func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
-	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
-	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
-
-	for {
-		peekData, peekErr := peekBuffer.ReadBytes('\n')
-		if peekErr != nil && peekErr != io.EOF {
-			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
-			return "", peekErr
-		}
-
-		p.debug("readPythonMultilines: parsing %q", string(peekData))
-
-		peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
-		p.debug("readPythonMultilines: matched %d parts", len(peekMatches))
-		for n, v := range peekMatches {
-			p.debug("   %d: %q", n, v)
-		}
-
-		// Return if not a Python multiline value.
-		if len(peekMatches) != 3 {
-			p.debug("readPythonMultilines: end of value, got: %q", line)
-			return line, nil
-		}
-
-		// Advance the parser reader (buffer) in-sync with the peek buffer.
-		_, err := p.buf.Discard(len(peekData))
-		if err != nil {
-			p.debug("readPythonMultilines: failed to skip to the end, returning error")
-			return "", err
-		}
-
-		line += "\n" + peekMatches[0]
-	}
-}
-
-// parse parses data through an io.Reader.
-func (f *File) parse(reader io.Reader) (err error) {
-	p := newParser(reader, parserOptions{
-		IgnoreContinuation:          f.options.IgnoreContinuation,
-		IgnoreInlineComment:         f.options.IgnoreInlineComment,
-		AllowPythonMultilineValues:  f.options.AllowPythonMultilineValues,
-		SpaceBeforeInlineComment:    f.options.SpaceBeforeInlineComment,
-		UnescapeValueDoubleQuotes:   f.options.UnescapeValueDoubleQuotes,
-		UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols,
-		PreserveSurroundedQuote:     f.options.PreserveSurroundedQuote,
-		DebugFunc:                   f.options.DebugFunc,
-		ReaderBufferSize:            f.options.ReaderBufferSize,
-	})
-	if err = p.BOM(); err != nil {
-		return fmt.Errorf("BOM: %v", err)
-	}
-
-	// Ignore error because default section name is never empty string.
-	name := DefaultSection
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(DefaultSection)
-	}
-	section, _ := f.NewSection(name)
-
-	// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
-	var isLastValueEmpty bool
-	var lastRegularKey *Key
-
-	var line []byte
-	var inUnparseableSection bool
-
-	// NOTE: Iterate and increase `currentPeekSize` until
-	// the size of the parser buffer is found.
-	// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`.
-	parserBufferSize := 0
-	// NOTE: Peek 4kb at a time.
-	currentPeekSize := minReaderBufferSize
-
-	if f.options.AllowPythonMultilineValues {
-		for {
-			peekBytes, _ := p.buf.Peek(currentPeekSize)
-			peekBytesLength := len(peekBytes)
-
-			if parserBufferSize >= peekBytesLength {
-				break
-			}
-
-			currentPeekSize *= 2
-			parserBufferSize = peekBytesLength
-		}
-	}
-
-	for !p.isEOF {
-		line, err = p.readUntil('\n')
-		if err != nil {
-			return err
-		}
-
-		if f.options.AllowNestedValues &&
-			isLastValueEmpty && len(line) > 0 {
-			if line[0] == ' ' || line[0] == '\t' {
-				err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
-				if err != nil {
-					return err
-				}
-				continue
-			}
-		}
-
-		line = bytes.TrimLeftFunc(line, unicode.IsSpace)
-		if len(line) == 0 {
-			continue
-		}
-
-		// Comments
-		if line[0] == '#' || line[0] == ';' {
-			// Note: we do not care ending line break,
-			// it is needed for adding second line,
-			// so just clean it once at the end when set to value.
-			p.comment.Write(line)
-			continue
-		}
-
-		// Section
-		if line[0] == '[' {
-			// Read to the next ']' (TODO: support quoted strings)
-			closeIdx := bytes.LastIndexByte(line, ']')
-			if closeIdx == -1 {
-				return fmt.Errorf("unclosed section: %s", line)
-			}
-
-			name := string(line[1:closeIdx])
-			section, err = f.NewSection(name)
-			if err != nil {
-				return err
-			}
-
-			comment, has := cleanComment(line[closeIdx+1:])
-			if has {
-				p.comment.Write(comment)
-			}
-
-			section.Comment = strings.TrimSpace(p.comment.String())
-
-			// Reset auto-counter and comments
-			p.comment.Reset()
-			p.count = 1
-			// Nested values can't span sections
-			isLastValueEmpty = false
-
-			inUnparseableSection = false
-			for i := range f.options.UnparseableSections {
-				if f.options.UnparseableSections[i] == name ||
-					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
-					inUnparseableSection = true
-					continue
-				}
-			}
-			continue
-		}
-
-		if inUnparseableSection {
-			section.isRawSection = true
-			section.rawBody += string(line)
-			continue
-		}
-
-		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
-		if err != nil {
-			switch {
-			// Treat as boolean key when desired, and whole line is key name.
-			case IsErrDelimiterNotFound(err):
-				switch {
-				case f.options.AllowBooleanKeys:
-					kname, err := p.readValue(line, parserBufferSize)
-					if err != nil {
-						return err
-					}
-					key, err := section.NewBooleanKey(kname)
-					if err != nil {
-						return err
-					}
-					key.Comment = strings.TrimSpace(p.comment.String())
-					p.comment.Reset()
-					continue
-
-				case f.options.SkipUnrecognizableLines:
-					continue
-				}
-			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines:
-				continue
-			}
-			return err
-		}
-
-		// Auto increment.
-		isAutoIncr := false
-		if kname == "-" {
-			isAutoIncr = true
-			kname = "#" + strconv.Itoa(p.count)
-			p.count++
-		}
-
-		value, err := p.readValue(line[offset:], parserBufferSize)
-		if err != nil {
-			return err
-		}
-		isLastValueEmpty = len(value) == 0
-
-		key, err := section.NewKey(kname, value)
-		if err != nil {
-			return err
-		}
-		key.isAutoIncrement = isAutoIncr
-		key.Comment = strings.TrimSpace(p.comment.String())
-		p.comment.Reset()
-		lastRegularKey = key
-	}
-	return nil
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/section.go b/event-processor/vendor/gopkg.in/ini.v1/section.go
deleted file mode 100644
index a3615d82..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/section.go
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"errors"
-	"fmt"
-	"strings"
-)
-
-// Section represents a config section.
-type Section struct {
-	f        *File
-	Comment  string
-	name     string
-	keys     map[string]*Key
-	keyList  []string
-	keysHash map[string]string
-
-	isRawSection bool
-	rawBody      string
-}
-
-func newSection(f *File, name string) *Section {
-	return &Section{
-		f:        f,
-		name:     name,
-		keys:     make(map[string]*Key),
-		keyList:  make([]string, 0, 10),
-		keysHash: make(map[string]string),
-	}
-}
-
-// Name returns name of Section.
-func (s *Section) Name() string {
-	return s.name
-}
-
-// Body returns rawBody of Section if the section was marked as unparseable.
-// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
-func (s *Section) Body() string {
-	return strings.TrimSpace(s.rawBody)
-}
-
-// SetBody updates body content only if section is raw.
-func (s *Section) SetBody(body string) {
-	if !s.isRawSection {
-		return
-	}
-	s.rawBody = body
-}
-
-// NewKey creates a new key to given section.
-func (s *Section) NewKey(name, val string) (*Key, error) {
-	if len(name) == 0 {
-		return nil, errors.New("error creating new key: empty key name")
-	} else if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	if inSlice(name, s.keyList) {
-		if s.f.options.AllowShadows {
-			if err := s.keys[name].addShadow(val); err != nil {
-				return nil, err
-			}
-		} else {
-			s.keys[name].value = val
-			s.keysHash[name] = val
-		}
-		return s.keys[name], nil
-	}
-
-	s.keyList = append(s.keyList, name)
-	s.keys[name] = newKey(s, name, val)
-	s.keysHash[name] = val
-	return s.keys[name], nil
-}
-
-// NewBooleanKey creates a new boolean type key to given section.
-func (s *Section) NewBooleanKey(name string) (*Key, error) {
-	key, err := s.NewKey(name, "true")
-	if err != nil {
-		return nil, err
-	}
-
-	key.isBooleanType = true
-	return key, nil
-}
-
-// GetKey returns key in section by given name.
-func (s *Section) GetKey(name string) (*Key, error) {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-	}
-	if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-	key := s.keys[name]
-	if s.f.BlockMode {
-		s.f.lock.RUnlock()
-	}
-
-	if key == nil {
-		// Check if it is a child-section.
-		sname := s.name
-		for {
-			if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-				sname = sname[:i]
-				sec, err := s.f.GetSection(sname)
-				if err != nil {
-					continue
-				}
-				return sec.GetKey(name)
-			}
-			break
-		}
-		return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name)
-	}
-	return key, nil
-}
-
-// HasKey returns true if section contains a key with given name.
-func (s *Section) HasKey(name string) bool {
-	key, _ := s.GetKey(name)
-	return key != nil
-}
-
-// Deprecated: Use "HasKey" instead.
-func (s *Section) Haskey(name string) bool {
-	return s.HasKey(name)
-}
-
-// HasValue returns true if section contains given raw value.
-func (s *Section) HasValue(value string) bool {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	for _, k := range s.keys {
-		if value == k.value {
-			return true
-		}
-	}
-	return false
-}
-
-// Key assumes named Key exists in section and returns a zero-value when not.
-func (s *Section) Key(name string) *Key {
-	key, err := s.GetKey(name)
-	if err != nil {
-		// It's OK here because the only possible error is empty key name,
-		// but if it's empty, this piece of code won't be executed.
-		key, _ = s.NewKey(name, "")
-		return key
-	}
-	return key
-}
-
-// Keys returns list of keys of section.
-func (s *Section) Keys() []*Key {
-	keys := make([]*Key, len(s.keyList))
-	for i := range s.keyList {
-		keys[i] = s.Key(s.keyList[i])
-	}
-	return keys
-}
-
-// ParentKeys returns list of keys of parent section.
-func (s *Section) ParentKeys() []*Key {
-	var parentKeys []*Key
-	sname := s.name
-	for {
-		if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-			sname = sname[:i]
-			sec, err := s.f.GetSection(sname)
-			if err != nil {
-				continue
-			}
-			parentKeys = append(parentKeys, sec.Keys()...)
-		} else {
-			break
-		}
-
-	}
-	return parentKeys
-}
-
-// KeyStrings returns list of key names of section.
-func (s *Section) KeyStrings() []string {
-	list := make([]string, len(s.keyList))
-	copy(list, s.keyList)
-	return list
-}
-
-// KeysHash returns keys hash consisting of names and values.
-func (s *Section) KeysHash() map[string]string {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	hash := make(map[string]string, len(s.keysHash))
-	for key, value := range s.keysHash {
-		hash[key] = value
-	}
-	return hash
-}
-
-// DeleteKey deletes a key from section.
-func (s *Section) DeleteKey(name string) {
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	for i, k := range s.keyList {
-		if k == name {
-			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
-			delete(s.keys, name)
-			delete(s.keysHash, name)
-			return
-		}
-	}
-}
-
-// ChildSections returns a list of child sections of current section.
-// For example, "[parent.child1]" and "[parent.child12]" are child sections
-// of section "[parent]".
-func (s *Section) ChildSections() []*Section {
-	prefix := s.name + s.f.options.ChildSectionDelimiter
-	children := make([]*Section, 0, 3)
-	for _, name := range s.f.sectionList {
-		if strings.HasPrefix(name, prefix) {
-			children = append(children, s.f.sections[name]...)
-		}
-	}
-	return children
-}
diff --git a/event-processor/vendor/gopkg.in/ini.v1/struct.go b/event-processor/vendor/gopkg.in/ini.v1/struct.go
deleted file mode 100644
index a486b2fe..00000000
--- a/event-processor/vendor/gopkg.in/ini.v1/struct.go
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"reflect"
-	"strings"
-	"time"
-	"unicode"
-)
-
-// NameMapper represents a ini tag name mapper.
-type NameMapper func(string) string
-
-// Built-in name getters.
-var (
-	// SnackCase converts to format SNACK_CASE.
-	SnackCase NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-			}
-			newstr = append(newstr, unicode.ToUpper(chr))
-		}
-		return string(newstr)
-	}
-	// TitleUnderscore converts to format title_underscore.
-	TitleUnderscore NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-				chr -= 'A' - 'a'
-			}
-			newstr = append(newstr, chr)
-		}
-		return string(newstr)
-	}
-)
-
-func (s *Section) parseFieldName(raw, actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	if s.f.NameMapper != nil {
-		return s.f.NameMapper(raw)
-	}
-	return raw
-}
-
-func parseDelim(actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	return ","
-}
-
-var reflectTime = reflect.TypeOf(time.Now()).Kind()
-
-// setSliceWithProperType sets proper values to slice based on its type.
-func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	var strs []string
-	if allowShadow {
-		strs = key.StringsWithShadows(delim)
-	} else {
-		strs = key.Strings(delim)
-	}
-
-	numVals := len(strs)
-	if numVals == 0 {
-		return nil
-	}
-
-	var vals interface{}
-	var err error
-
-	sliceOf := field.Type().Elem().Kind()
-	switch sliceOf {
-	case reflect.String:
-		vals = strs
-	case reflect.Int:
-		vals, err = key.parseInts(strs, true, false)
-	case reflect.Int64:
-		vals, err = key.parseInt64s(strs, true, false)
-	case reflect.Uint:
-		vals, err = key.parseUints(strs, true, false)
-	case reflect.Uint64:
-		vals, err = key.parseUint64s(strs, true, false)
-	case reflect.Float64:
-		vals, err = key.parseFloat64s(strs, true, false)
-	case reflect.Bool:
-		vals, err = key.parseBools(strs, true, false)
-	case reflectTime:
-		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
-	default:
-		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-	}
-	if err != nil && isStrict {
-		return err
-	}
-
-	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
-	for i := 0; i < numVals; i++ {
-		switch sliceOf {
-		case reflect.String:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
-		case reflect.Int:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
-		case reflect.Int64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
-		case reflect.Uint:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
-		case reflect.Uint64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
-		case reflect.Float64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
-		case reflect.Bool:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i]))
-		case reflectTime:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
-		}
-	}
-	field.Set(slice)
-	return nil
-}
-
-func wrapStrictError(err error, isStrict bool) error {
-	if isStrict {
-		return err
-	}
-	return nil
-}
-
-// setWithProperType sets proper value to field based on its type,
-// but it does not return error for failing parsing,
-// because we want to use default value that is already assigned to struct.
-func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	vt := t
-	isPtr := t.Kind() == reflect.Ptr
-	if isPtr {
-		vt = t.Elem()
-	}
-	switch vt.Kind() {
-	case reflect.String:
-		stringVal := key.String()
-		if isPtr {
-			field.Set(reflect.ValueOf(&stringVal))
-		} else if len(stringVal) > 0 {
-			field.SetString(key.String())
-		}
-	case reflect.Bool:
-		boolVal, err := key.Bool()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&boolVal))
-		} else {
-			field.SetBool(boolVal)
-		}
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		// ParseDuration will not return err for `0`, so check the type name
-		if vt.Name() == "Duration" {
-			durationVal, err := key.Duration()
-			if err != nil {
-				if intVal, err := key.Int64(); err == nil {
-					field.SetInt(intVal)
-					return nil
-				}
-				return wrapStrictError(err, isStrict)
-			}
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else if int64(durationVal) > 0 {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		intVal, err := key.Int64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetInt(intVal)
-			field.Set(pv)
-		} else {
-			field.SetInt(intVal)
-		}
-	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
-	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		durationVal, err := key.Duration()
-		// Skip zero value
-		if err == nil && uint64(durationVal) > 0 {
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		uintVal, err := key.Uint64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetUint(uintVal)
-			field.Set(pv)
-		} else {
-			field.SetUint(uintVal)
-		}
-
-	case reflect.Float32, reflect.Float64:
-		floatVal, err := key.Float64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetFloat(floatVal)
-			field.Set(pv)
-		} else {
-			field.SetFloat(floatVal)
-		}
-	case reflectTime:
-		timeVal, err := key.Time()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&timeVal))
-		} else {
-			field.Set(reflect.ValueOf(timeVal))
-		}
-	case reflect.Slice:
-		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) {
-	opts := strings.SplitN(tag, ",", 5)
-	rawName = opts[0]
-	for _, opt := range opts[1:] {
-		omitEmpty = omitEmpty || (opt == "omitempty")
-		allowShadow = allowShadow || (opt == "allowshadow")
-		allowNonUnique = allowNonUnique || (opt == "nonunique")
-		extends = extends || (opt == "extends")
-	}
-	return rawName, omitEmpty, allowShadow, allowNonUnique, extends
-}
-
-// mapToField maps the given value to the matching field of the given section.
-// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
-func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		isStruct := tpField.Type.Kind() == reflect.Struct
-		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
-		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
-		if isAnonymousPtr {
-			field.Set(reflect.New(tpField.Type.Elem()))
-		}
-
-		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) {
-			if isStructPtr && field.IsNil() {
-				field.Set(reflect.New(tpField.Type.Elem()))
-			}
-			fieldSection := s
-			if rawName != "" {
-				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName
-				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) {
-					fieldSection = secs[sectionIndex]
-				}
-			}
-			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil {
-				return fmt.Errorf("map to field %q: %v", fieldName, err)
-			}
-		} else if isAnonymousPtr || isStruct || isStructPtr {
-			if secs, err := s.f.SectionsByName(fieldName); err == nil {
-				if len(secs) <= sectionIndex {
-					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
-				}
-				// Only set the field to non-nil struct value if we have a section for it.
-				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
-				if isStructPtr && field.IsNil() {
-					field.Set(reflect.New(tpField.Type.Elem()))
-				}
-				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil {
-					return fmt.Errorf("map to field %q: %v", fieldName, err)
-				}
-				continue
-			}
-		}
-
-		// Map non-unique sections
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			newField, err := s.mapToSlice(fieldName, field, isStrict)
-			if err != nil {
-				return fmt.Errorf("map to slice %q: %v", fieldName, err)
-			}
-
-			field.Set(newField)
-			continue
-		}
-
-		if key, err := s.GetKey(fieldName); err == nil {
-			delim := parseDelim(tpField.Tag.Get("delim"))
-			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
-				return fmt.Errorf("set field %q: %v", fieldName, err)
-			}
-		}
-	}
-	return nil
-}
-
-// mapToSlice maps all sections with the same name and returns the new value.
-// The type of the Value must be a slice.
-func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
-	secs, err := s.f.SectionsByName(secName)
-	if err != nil {
-		return reflect.Value{}, err
-	}
-
-	typ := val.Type().Elem()
-	for i, sec := range secs {
-		elem := reflect.New(typ)
-		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
-			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
-		}
-
-		val = reflect.Append(val, elem.Elem())
-	}
-	return val, nil
-}
-
-// mapTo maps a section to object v.
-func (s *Section) mapTo(v interface{}, isStrict bool) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-	if typ.Kind() == reflect.Ptr {
-		typ = typ.Elem()
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	if typ.Kind() == reflect.Slice {
-		newField, err := s.mapToSlice(s.name, val, isStrict)
-		if err != nil {
-			return err
-		}
-
-		val.Set(newField)
-		return nil
-	}
-
-	return s.mapToField(val, isStrict, 0, s.name)
-}
-
-// MapTo maps section to given struct.
-func (s *Section) MapTo(v interface{}) error {
-	return s.mapTo(v, false)
-}
-
-// StrictMapTo maps section to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (s *Section) StrictMapTo(v interface{}) error {
-	return s.mapTo(v, true)
-}
-
-// MapTo maps file to given struct.
-func (f *File) MapTo(v interface{}) error {
-	return f.Section("").MapTo(v)
-}
-
-// StrictMapTo maps file to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (f *File) StrictMapTo(v interface{}) error {
-	return f.Section("").StrictMapTo(v)
-}
-
-// MapToWithMapper maps data sources to given struct with name mapper.
-func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.MapTo(v)
-}
-
-// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.StrictMapTo(v)
-}
-
-// MapTo maps data sources to given struct.
-func MapTo(v, source interface{}, others ...interface{}) error {
-	return MapToWithMapper(v, nil, source, others...)
-}
-
-// StrictMapTo maps data sources to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapTo(v, source interface{}, others ...interface{}) error {
-	return StrictMapToWithMapper(v, nil, source, others...)
-}
-
-// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
-func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	slice := field.Slice(0, field.Len())
-	if field.Len() == 0 {
-		return nil
-	}
-	sliceOf := field.Type().Elem().Kind()
-
-	if allowShadow {
-		var keyWithShadows *Key
-		for i := 0; i < field.Len(); i++ {
-			var val string
-			switch sliceOf {
-			case reflect.String:
-				val = slice.Index(i).String()
-			case reflect.Int, reflect.Int64:
-				val = fmt.Sprint(slice.Index(i).Int())
-			case reflect.Uint, reflect.Uint64:
-				val = fmt.Sprint(slice.Index(i).Uint())
-			case reflect.Float64:
-				val = fmt.Sprint(slice.Index(i).Float())
-			case reflect.Bool:
-				val = fmt.Sprint(slice.Index(i).Bool())
-			case reflectTime:
-				val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
-			default:
-				return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-			}
-
-			if i == 0 {
-				keyWithShadows = newKey(key.s, key.name, val)
-			} else {
-				_ = keyWithShadows.AddShadow(val)
-			}
-		}
-		*key = *keyWithShadows
-		return nil
-	}
-
-	var buf bytes.Buffer
-	for i := 0; i < field.Len(); i++ {
-		switch sliceOf {
-		case reflect.String:
-			buf.WriteString(slice.Index(i).String())
-		case reflect.Int, reflect.Int64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
-		case reflect.Uint, reflect.Uint64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
-		case reflect.Float64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
-		case reflect.Bool:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
-		case reflectTime:
-			buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
-		default:
-			return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-		}
-		buf.WriteString(delim)
-	}
-	key.SetValue(buf.String()[:buf.Len()-len(delim)])
-	return nil
-}
-
-// reflectWithProperType does the opposite thing as setWithProperType.
-func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	switch t.Kind() {
-	case reflect.String:
-		key.SetValue(field.String())
-	case reflect.Bool:
-		key.SetValue(fmt.Sprint(field.Bool()))
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		key.SetValue(fmt.Sprint(field.Int()))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		key.SetValue(fmt.Sprint(field.Uint()))
-	case reflect.Float32, reflect.Float64:
-		key.SetValue(fmt.Sprint(field.Float()))
-	case reflectTime:
-		key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
-	case reflect.Slice:
-		return reflectSliceWithProperType(key, field, delim, allowShadow)
-	case reflect.Ptr:
-		if !field.IsNil() {
-			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
-		}
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-// CR: copied from encoding/json/encode.go with modifications of time.Time support.
-// TODO: add more test coverage.
-func isEmptyValue(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	case reflectTime:
-		t, ok := v.Interface().(time.Time)
-		return ok && t.IsZero()
-	}
-	return false
-}
-
-// StructReflector is the interface implemented by struct types that can extract themselves into INI objects.
-type StructReflector interface {
-	ReflectINIStruct(*File) error
-}
-
-func (s *Section) reflectFrom(val reflect.Value) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		if !val.Field(i).CanInterface() {
-			continue
-		}
-
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		if omitEmpty && isEmptyValue(field) {
-			continue
-		}
-
-		if r, ok := field.Interface().(StructReflector); ok {
-			return r.ReflectINIStruct(s.f)
-		}
-
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
-			if err := s.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
-			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
-			// Note: The only error here is section doesn't exist.
-			sec, err := s.f.GetSection(fieldName)
-			if err != nil {
-				// Note: fieldName can never be empty here, ignore error.
-				sec, _ = s.f.NewSection(fieldName)
-			}
-
-			// Add comment from comment tag
-			if len(sec.Comment) == 0 {
-				sec.Comment = tpField.Tag.Get("comment")
-			}
-
-			if err = sec.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			slice := field.Slice(0, field.Len())
-			if field.Len() == 0 {
-				return nil
-			}
-			sliceOf := field.Type().Elem().Kind()
-
-			for i := 0; i < field.Len(); i++ {
-				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
-					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
-				}
-
-				sec, err := s.f.NewSection(fieldName)
-				if err != nil {
-					return err
-				}
-
-				// Add comment from comment tag
-				if len(sec.Comment) == 0 {
-					sec.Comment = tpField.Tag.Get("comment")
-				}
-
-				if err := sec.reflectFrom(slice.Index(i)); err != nil {
-					return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-				}
-			}
-			continue
-		}
-
-		// Note: Same reason as section.
-		key, err := s.GetKey(fieldName)
-		if err != nil {
-			key, _ = s.NewKey(fieldName, "")
-		}
-
-		// Add comment from comment tag
-		if len(key.Comment) == 0 {
-			key.Comment = tpField.Tag.Get("comment")
-		}
-
-		delim := parseDelim(tpField.Tag.Get("delim"))
-		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
-			return fmt.Errorf("reflect field %q: %v", fieldName, err)
-		}
-
-	}
-	return nil
-}
-
-// ReflectFrom reflects section from given struct. It overwrites existing ones.
-func (s *Section) ReflectFrom(v interface{}) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-
-	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
-		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
-		// Clear sections to make sure none exists before adding the new ones
-		s.f.DeleteSection(s.name)
-
-		if typ.Kind() == reflect.Ptr {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-			return sec.reflectFrom(val.Elem())
-		}
-
-		slice := val.Slice(0, val.Len())
-		sliceOf := val.Type().Elem().Kind()
-		if sliceOf != reflect.Ptr {
-			return fmt.Errorf("not a slice of pointers")
-		}
-
-		for i := 0; i < slice.Len(); i++ {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-
-			err = sec.reflectFrom(slice.Index(i))
-			if err != nil {
-				return fmt.Errorf("reflect from %dth field: %v", i, err)
-			}
-		}
-
-		return nil
-	}
-
-	if typ.Kind() == reflect.Ptr {
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	return s.reflectFrom(val)
-}
-
-// ReflectFrom reflects file from given struct.
-func (f *File) ReflectFrom(v interface{}) error {
-	return f.Section("").ReflectFrom(v)
-}
-
-// ReflectFromWithMapper reflects data sources from given struct with name mapper.
-func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
-	cfg.NameMapper = mapper
-	return cfg.ReflectFrom(v)
-}
-
-// ReflectFrom reflects data sources from given struct.
-func ReflectFrom(cfg *File, v interface{}) error {
-	return ReflectFromWithMapper(cfg, v, nil)
-}
diff --git a/event-processor/vendor/gorm.io/gorm/association.go b/event-processor/vendor/gorm.io/gorm/association.go
index e3f51d17..f210ca0a 100644
--- a/event-processor/vendor/gorm.io/gorm/association.go
+++ b/event-processor/vendor/gorm.io/gorm/association.go
@@ -19,10 +19,10 @@ type Association struct {
 }
 
 func (db *DB) Association(column string) *Association {
-	association := &Association{DB: db}
+	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
 	table := db.Statement.Table
 
-	if err := db.Statement.Parse(db.Statement.Model); err == nil {
+	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
 		db.Statement.Table = table
 		association.Relationship = db.Statement.Schema.Relationships.Relations[column]
 
@@ -34,8 +34,6 @@ func (db *DB) Association(column string) *Association {
 		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
 			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
 		}
-	} else {
-		association.Error = err
 	}
 
 	return association
@@ -58,6 +56,8 @@ func (association *Association) Find(out interface{}, conds ...interface{}) erro
 }
 
 func (association *Association) Append(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		switch association.Relationship.Type {
 		case schema.HasOne, schema.BelongsTo:
@@ -73,6 +73,8 @@ func (association *Association) Append(values ...interface{}) error {
 }
 
 func (association *Association) Replace(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		reflectValue := association.DB.Statement.ReflectValue
 		rel := association.Relationship
@@ -195,6 +197,8 @@ func (association *Association) Replace(values ...interface{}) error {
 }
 
 func (association *Association) Delete(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		var (
 			reflectValue  = association.DB.Statement.ReflectValue
@@ -431,10 +435,49 @@ func (association *Association) saveAssociation(clear bool, values ...interface{
 				}
 			}
 
+			processMap := func(mapv reflect.Value) {
+				child := reflect.New(association.Relationship.FieldSchema.ModelType)
+
+				switch association.Relationship.Type {
+				case schema.HasMany:
+					for _, ref := range association.Relationship.References {
+						key := reflect.ValueOf(ref.ForeignKey.DBName)
+						if ref.OwnPrimaryKey {
+							v := ref.PrimaryKey.ReflectValueOf(association.DB.Statement.Context, source)
+							mapv.SetMapIndex(key, v)
+						} else if ref.PrimaryValue != "" {
+							mapv.SetMapIndex(key, reflect.ValueOf(ref.PrimaryValue))
+						}
+					}
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+				case schema.Many2Many:
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+
+					for _, key := range mapv.MapKeys() {
+						k := strings.ToLower(key.String())
+						if f, ok := association.Relationship.FieldSchema.FieldsByDBName[k]; ok {
+							_ = f.Set(association.DB.Statement.Context, child, mapv.MapIndex(key).Interface())
+						}
+					}
+					appendToFieldValues(child)
+				}
+			}
+
 			switch rv.Kind() {
+			case reflect.Map:
+				processMap(rv)
 			case reflect.Slice, reflect.Array:
 				for i := 0; i < rv.Len(); i++ {
-					appendToFieldValues(reflect.Indirect(rv.Index(i)).Addr())
+					elem := reflect.Indirect(rv.Index(i))
+					if elem.Kind() == reflect.Map {
+						processMap(elem)
+						continue
+					}
+					appendToFieldValues(elem.Addr())
 				}
 			case reflect.Struct:
 				if !rv.CanAddr() {
@@ -591,3 +634,32 @@ func (association *Association) buildCondition() *DB {
 
 	return tx
 }
+
+func expandValues(values ...any) (results []any) {
+	appendToResult := func(rv reflect.Value) {
+		// unwrap interface
+		if rv.IsValid() && rv.Kind() == reflect.Interface {
+			rv = rv.Elem()
+		}
+		if rv.IsValid() && rv.Kind() == reflect.Struct {
+			p := reflect.New(rv.Type())
+			p.Elem().Set(rv)
+			results = append(results, p.Interface())
+		} else if rv.IsValid() {
+			results = append(results, rv.Interface())
+		}
+	}
+
+	// Process each argument; if an argument is a slice/array, expand its elements
+	for _, value := range values {
+		rv := reflect.ValueOf(value)
+		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
+			for i := 0; i < rv.Len(); i++ {
+				appendToResult(rv.Index(i))
+			}
+		} else {
+			appendToResult(rv)
+		}
+	}
+	return
+}
diff --git a/event-processor/vendor/gorm.io/gorm/callbacks.go b/event-processor/vendor/gorm.io/gorm/callbacks.go
index 50b5b0e9..bd97f040 100644
--- a/event-processor/vendor/gorm.io/gorm/callbacks.go
+++ b/event-processor/vendor/gorm.io/gorm/callbacks.go
@@ -89,10 +89,16 @@ func (p *processor) Execute(db *DB) *DB {
 		resetBuildClauses = true
 	}
 
-	if optimizer, ok := db.Statement.Dest.(StatementModifier); ok {
+	if optimizer, ok := stmt.Dest.(StatementModifier); ok {
 		optimizer.ModifyStatement(stmt)
 	}
 
+	if db.DefaultContextTimeout > 0 {
+		if _, ok := stmt.Context.Deadline(); !ok {
+			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
+		}
+	}
+
 	// assign model values
 	if stmt.Model == nil {
 		stmt.Model = stmt.Dest
diff --git a/event-processor/vendor/gorm.io/gorm/callbacks/create.go b/event-processor/vendor/gorm.io/gorm/callbacks/create.go
index d8701f51..e5929adb 100644
--- a/event-processor/vendor/gorm.io/gorm/callbacks/create.go
+++ b/event-processor/vendor/gorm.io/gorm/callbacks/create.go
@@ -53,9 +53,13 @@ func Create(config *Config) func(db *gorm.DB) {
 				if _, ok := db.Statement.Clauses["RETURNING"]; !ok {
 					fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue))
 					for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue {
-						fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						if field.Readable {
+							fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						}
+					}
+					if len(fromColumns) > 0 {
+						db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 					}
-					db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 				}
 			}
 		}
@@ -76,8 +80,11 @@ func Create(config *Config) func(db *gorm.DB) {
 		ok, mode := hasReturning(db, supportReturning)
 		if ok {
 			if c, ok := db.Statement.Clauses["ON CONFLICT"]; ok {
-				if onConflict, _ := c.Expression.(clause.OnConflict); onConflict.DoNothing {
+				onConflict, _ := c.Expression.(clause.OnConflict)
+				if onConflict.DoNothing {
 					mode |= gorm.ScanOnConflictDoNothing
+				} else if len(onConflict.DoUpdates) > 0 || onConflict.UpdateAll {
+					mode |= gorm.ScanUpdate
 				}
 			}
 
@@ -122,6 +129,16 @@ func Create(config *Config) func(db *gorm.DB) {
 			pkFieldName = "@id"
 		)
 
+		if db.Statement.Schema != nil {
+			if db.Statement.Schema.PrioritizedPrimaryField == nil ||
+				!db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue ||
+				!db.Statement.Schema.PrioritizedPrimaryField.Readable {
+				return
+			}
+			pkField = db.Statement.Schema.PrioritizedPrimaryField
+			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
+		}
+
 		insertID, err := result.LastInsertId()
 		insertOk := err == nil && insertID > 0
 
@@ -132,14 +149,6 @@ func Create(config *Config) func(db *gorm.DB) {
 			return
 		}
 
-		if db.Statement.Schema != nil {
-			if db.Statement.Schema.PrioritizedPrimaryField == nil || !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue {
-				return
-			}
-			pkField = db.Statement.Schema.PrioritizedPrimaryField
-			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
-		}
-
 		// append @id column with value for auto-increment primary key
 		// the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1
 		switch values := db.Statement.Dest.(type) {
diff --git a/event-processor/vendor/gorm.io/gorm/clause/association.go b/event-processor/vendor/gorm.io/gorm/clause/association.go
new file mode 100644
index 00000000..a9bf7eb0
--- /dev/null
+++ b/event-processor/vendor/gorm.io/gorm/clause/association.go
@@ -0,0 +1,35 @@
+package clause
+
+// AssociationOpType represents association operation types
+type AssociationOpType int
+
+const (
+	OpUnlink AssociationOpType = iota // Unlink association
+	OpDelete                          // Delete association records
+	OpUpdate                          // Update association records
+	OpCreate                          // Create association records with assignments
+)
+
+// Association represents an association operation
+type Association struct {
+	Association string            // Association name
+	Type        AssociationOpType // Operation type
+	Conditions  []Expression      // Filter conditions
+	Set         []Assignment      // Assignment operations (for Update and Create)
+	Values      []interface{}     // Values for Create operation
+}
+
+// AssociationAssigner is an interface for association operation providers
+type AssociationAssigner interface {
+	AssociationAssignments() []Association
+}
+
+// Assignments implements the Assigner interface so that AssociationOperation can be used as a Set method parameter
+func (ao Association) Assignments() []Assignment {
+	return []Assignment{}
+}
+
+// AssociationAssignments implements the AssociationAssigner interface
+func (ao Association) AssociationAssignments() []Association {
+	return []Association{ao}
+}
diff --git a/event-processor/vendor/gorm.io/gorm/clause/set.go b/event-processor/vendor/gorm.io/gorm/clause/set.go
index 75eb6bdd..cb5f36a0 100644
--- a/event-processor/vendor/gorm.io/gorm/clause/set.go
+++ b/event-processor/vendor/gorm.io/gorm/clause/set.go
@@ -9,6 +9,11 @@ type Assignment struct {
 	Value  interface{}
 }
 
+// Assigner assignments provider interface
+type Assigner interface {
+	Assignments() []Assignment
+}
+
 func (set Set) Name() string {
 	return "SET"
 }
@@ -37,6 +42,9 @@ func (set Set) MergeClause(clause *Clause) {
 	clause.Expression = Set(copiedAssignments)
 }
 
+// Assignments implements Assigner for Set.
+func (set Set) Assignments() []Assignment { return []Assignment(set) }
+
 func Assignments(values map[string]interface{}) Set {
 	keys := make([]string, 0, len(values))
 	for key := range values {
@@ -58,3 +66,6 @@ func AssignmentColumns(values []string) Set {
 	}
 	return assignments
 }
+
+// Assignments implements Assigner for a single Assignment.
+func (a Assignment) Assignments() []Assignment { return []Assignment{a} }
diff --git a/event-processor/vendor/gorm.io/gorm/finisher_api.go b/event-processor/vendor/gorm.io/gorm/finisher_api.go
index 57809d17..e601fe66 100644
--- a/event-processor/vendor/gorm.io/gorm/finisher_api.go
+++ b/event-processor/vendor/gorm.io/gorm/finisher_api.go
@@ -675,9 +675,9 @@ func (db *DB) Begin(opts ...*sql.TxOptions) *DB {
 	}
 
 	ctx := tx.Statement.Context
-	if _, ok := ctx.Deadline(); !ok {
-		if db.Config.DefaultTransactionTimeout > 0 {
-			ctx, _ = context.WithTimeout(ctx, db.Config.DefaultTransactionTimeout)
+	if db.DefaultTransactionTimeout > 0 {
+		if _, ok := ctx.Deadline(); !ok {
+			ctx, _ = context.WithTimeout(ctx, db.DefaultTransactionTimeout)
 		}
 	}
 
diff --git a/event-processor/vendor/gorm.io/gorm/generics.go b/event-processor/vendor/gorm.io/gorm/generics.go
index ad2d063f..79238d5f 100644
--- a/event-processor/vendor/gorm.io/gorm/generics.go
+++ b/event-processor/vendor/gorm.io/gorm/generics.go
@@ -3,12 +3,15 @@ package gorm
 import (
 	"context"
 	"database/sql"
+	"errors"
 	"fmt"
+	"reflect"
 	"sort"
 	"strings"
 
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/logger"
+	"gorm.io/gorm/schema"
 )
 
 type result struct {
@@ -35,10 +38,34 @@ type Interface[T any] interface {
 }
 
 type CreateInterface[T any] interface {
-	ChainInterface[T]
+	ExecInterface[T]
+	// chain methods available at start; return ChainInterface
+	Scopes(scopes ...func(db *Statement)) ChainInterface[T]
+	Where(query interface{}, args ...interface{}) ChainInterface[T]
+	Not(query interface{}, args ...interface{}) ChainInterface[T]
+	Or(query interface{}, args ...interface{}) ChainInterface[T]
+	Limit(offset int) ChainInterface[T]
+	Offset(offset int) ChainInterface[T]
+	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[T]
+	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[T]
+	Select(query string, args ...interface{}) ChainInterface[T]
+	Omit(columns ...string) ChainInterface[T]
+	MapColumns(m map[string]string) ChainInterface[T]
+	Distinct(args ...interface{}) ChainInterface[T]
+	Group(name string) ChainInterface[T]
+	Having(query interface{}, args ...interface{}) ChainInterface[T]
+	Order(value interface{}) ChainInterface[T]
+	Build(builder clause.Builder)
+
+	Delete(ctx context.Context) (rowsAffected int, err error)
+	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
+	Updates(ctx context.Context, t T) (rowsAffected int, err error)
+	Count(ctx context.Context, column string) (result int64, err error)
+
 	Table(name string, args ...interface{}) CreateInterface[T]
 	Create(ctx context.Context, r *T) error
 	CreateInBatches(ctx context.Context, r *[]T, batchSize int) error
+	Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T]
 }
 
 type ChainInterface[T any] interface {
@@ -58,15 +85,28 @@ type ChainInterface[T any] interface {
 	Group(name string) ChainInterface[T]
 	Having(query interface{}, args ...interface{}) ChainInterface[T]
 	Order(value interface{}) ChainInterface[T]
+	Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T]
 
 	Build(builder clause.Builder)
 
+	Table(name string, args ...interface{}) ChainInterface[T]
 	Delete(ctx context.Context) (rowsAffected int, err error)
 	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
 	Updates(ctx context.Context, t T) (rowsAffected int, err error)
 	Count(ctx context.Context, column string) (result int64, err error)
 }
 
+// SetUpdateOnlyInterface is returned by Set after chaining; only Update is allowed
+type SetUpdateOnlyInterface[T any] interface {
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
+// SetCreateOrUpdateInterface is returned by Set at start; Create or Update are allowed
+type SetCreateOrUpdateInterface[T any] interface {
+	Create(ctx context.Context) error
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
 type ExecInterface[T any] interface {
 	Scan(ctx context.Context, r interface{}) error
 	First(context.Context) (T, error)
@@ -142,13 +182,15 @@ func (c *g[T]) Raw(sql string, values ...interface{}) ExecInterface[T] {
 	return execG[T]{g: &g[T]{
 		db: c.db,
 		ops: append(c.ops, func(db *DB) *DB {
-			return db.Raw(sql, values...)
+			var r T
+			return db.Model(r).Raw(sql, values...)
 		}),
 	}}
 }
 
 func (c *g[T]) Exec(ctx context.Context, sql string, values ...interface{}) error {
-	return c.apply(ctx).Exec(sql, values...).Error
+	var r T
+	return c.apply(ctx).Model(r).Exec(sql, values...).Error
 }
 
 type createG[T any] struct {
@@ -161,6 +203,10 @@ func (c createG[T]) Table(name string, args ...interface{}) CreateInterface[T] {
 	})}
 }
 
+func (c createG[T]) Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c createG[T]) Create(ctx context.Context, r *T) error {
 	return c.g.apply(ctx).Create(r).Error
 }
@@ -187,6 +233,12 @@ func (c chainG[T]) with(v op) chainG[T] {
 	}
 }
 
+func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
+	return c.with(func(db *DB) *DB {
+		return db.Table(name, args...)
+	})
+}
+
 func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		for _, fc := range scopes {
@@ -196,12 +248,6 @@ func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	})
 }
 
-func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
-	return c.with(func(db *DB) *DB {
-		return db.Table(name, args...)
-	})
-}
-
 func (c chainG[T]) Where(query interface{}, args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Where(query, args...)
@@ -388,6 +434,10 @@ func (c chainG[T]) MapColumns(m map[string]string) ChainInterface[T] {
 	})
 }
 
+func (c chainG[T]) Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c chainG[T]) Distinct(args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Distinct(args...)
@@ -425,12 +475,12 @@ func (c chainG[T]) Preload(association string, query func(db PreloadBuilder) err
 			relation, ok := db.Statement.Schema.Relationships.Relations[association]
 			if !ok {
 				if preloadFields := strings.Split(association, "."); len(preloadFields) > 1 {
-					relationships := db.Statement.Schema.Relationships
+					relationships := &db.Statement.Schema.Relationships
 					for _, field := range preloadFields {
 						var ok bool
 						relation, ok = relationships.Relations[field]
 						if ok {
-							relationships = relation.FieldSchema.Relationships
+							relationships = &relation.FieldSchema.Relationships
 						} else {
 							db.AddError(fmt.Errorf("relation %s not found", association))
 							return nil
@@ -567,7 +617,7 @@ func (g execG[T]) First(ctx context.Context) (T, error) {
 
 func (g execG[T]) Scan(ctx context.Context, result interface{}) error {
 	var r T
-	err := g.g.apply(ctx).Model(r).Find(&result).Error
+	err := g.g.apply(ctx).Model(r).Find(result).Error
 	return err
 }
 
@@ -603,3 +653,242 @@ func (g execG[T]) Row(ctx context.Context) *sql.Row {
 func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) {
 	return g.g.apply(ctx).Rows()
 }
+
+func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdateG[T] {
+	var (
+		assigns  []clause.Assignment
+		assocOps []clause.Association
+	)
+
+	for _, item := range items {
+		// Check if it's an AssociationAssigner
+		if assocAssigner, ok := item.(clause.AssociationAssigner); ok {
+			assocOps = append(assocOps, assocAssigner.AssociationAssignments()...)
+		} else {
+			assigns = append(assigns, item.Assignments()...)
+		}
+	}
+
+	return setCreateOrUpdateG[T]{
+		c:        c,
+		assigns:  assigns,
+		assocOps: assocOps,
+	}
+}
+
+// setCreateOrUpdateG[T] is a struct that holds operations to be executed in a batch.
+// It supports regular assignments and association operations.
+type setCreateOrUpdateG[T any] struct {
+	c        chainG[T]
+	assigns  []clause.Assignment
+	assocOps []clause.Association
+}
+
+func (s setCreateOrUpdateG[T]) Update(ctx context.Context) (rowsAffected int, err error) {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return 0, err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		var r T
+		res := s.c.g.apply(ctx).Model(r).Clauses(clause.Set(s.assigns)).Updates(map[string]interface{}{})
+		return int(res.RowsAffected), res.Error
+	}
+
+	return 0, nil
+}
+
+func (s setCreateOrUpdateG[T]) Create(ctx context.Context) error {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		data := make(map[string]interface{}, len(s.assigns))
+		for _, a := range s.assigns {
+			data[a.Column.Name] = a.Value
+		}
+		var r T
+		return s.c.g.apply(ctx).Model(r).Create(data).Error
+	}
+
+	return nil
+}
+
+// executeAssociationOperation executes an association operation
+func (s setCreateOrUpdateG[T]) executeAssociationOperation(ctx context.Context, op clause.Association) error {
+	var r T
+	base := s.c.g.apply(ctx).Model(r)
+
+	switch op.Type {
+	case clause.OpCreate:
+		return s.handleAssociationCreate(ctx, base, op)
+	case clause.OpUnlink, clause.OpDelete, clause.OpUpdate:
+		return s.handleAssociation(ctx, base, op)
+	default:
+		return fmt.Errorf("unknown association operation type: %v", op.Type)
+	}
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociationCreate(ctx context.Context, base *DB, op clause.Association) error {
+	if len(op.Set) > 0 {
+		return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+			data := make(map[string]interface{}, len(op.Set))
+			for _, a := range op.Set {
+				data[a.Column.Name] = a.Value
+			}
+			return assoc.Append(data)
+		}, op.Association)
+	}
+
+	return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+		return assoc.Append(op.Values...)
+	}, op.Association)
+}
+
+// handleAssociationForOwners is a helper function that handles associations for all owners
+func (s setCreateOrUpdateG[T]) handleAssociationForOwners(base *DB, ctx context.Context, handler func(owner T, association *Association) error, associationName string) error {
+	var owners []T
+	if err := base.Find(&owners).Error; err != nil {
+		return err
+	}
+
+	for _, owner := range owners {
+		assoc := base.Session(&Session{NewDB: true, Context: ctx}).Model(&owner).Association(associationName)
+		if assoc.Error != nil {
+			return assoc.Error
+		}
+
+		if err := handler(owner, assoc); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, base *DB, op clause.Association) error {
+	assoc := base.Association(op.Association)
+	if assoc.Error != nil {
+		return assoc.Error
+	}
+
+	var (
+		rel            = assoc.Relationship
+		assocModel     = reflect.New(rel.FieldSchema.ModelType).Interface()
+		fkNil          = map[string]any{}
+		setMap         = make(map[string]any, len(op.Set))
+		ownerPKNames   []string
+		ownerFKNames   []string
+		primaryColumns []any
+		foreignColumns []any
+	)
+
+	for _, a := range op.Set {
+		setMap[a.Column.Name] = a.Value
+	}
+
+	for _, ref := range rel.References {
+		fkNil[ref.ForeignKey.DBName] = nil
+
+		if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerPKNames = append(ownerPKNames, ref.PrimaryKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+			foreignColumns = append(foreignColumns, clause.Column{Name: ref.ForeignKey.DBName})
+		} else if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerFKNames = append(ownerFKNames, ref.ForeignKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+		}
+	}
+
+	assocDB := s.c.g.db.Session(&Session{NewDB: true, Context: ctx}).Model(assocModel).Where(op.Conditions)
+
+	switch rel.Type {
+	case schema.HasOne, schema.HasMany:
+		assocDB = assocDB.Where("? IN (?)", foreignColumns, base.Select(ownerPKNames))
+		switch op.Type {
+		case clause.OpUnlink:
+			return assocDB.Updates(fkNil).Error
+		case clause.OpDelete:
+			return assocDB.Delete(assocModel).Error
+		case clause.OpUpdate:
+			return assocDB.Updates(setMap).Error
+		}
+	case schema.BelongsTo:
+		switch op.Type {
+		case clause.OpDelete:
+			return base.Transaction(func(tx *DB) error {
+				assocDB.Statement.ConnPool = tx.Statement.ConnPool
+				base.Statement.ConnPool = tx.Statement.ConnPool
+
+				if err := assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Delete(assocModel).Error; err != nil {
+					return err
+				}
+				return base.Updates(fkNil).Error
+			})
+		case clause.OpUnlink:
+			return base.Updates(fkNil).Error
+		case clause.OpUpdate:
+			return assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Updates(setMap).Error
+		}
+	case schema.Many2Many:
+		joinModel := reflect.New(rel.JoinTable.ModelType).Interface()
+		joinDB := base.Session(&Session{NewDB: true, Context: ctx}).Model(joinModel)
+
+		// EXISTS owners: owners.pk = join.owner_fk for all owner refs
+		ownersExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.Schema.Table).Select("1")
+		for _, ref := range rel.References {
+			if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				ownersExists = ownersExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.Schema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+
+		// EXISTS related: related.pk = join.rel_fk for all related refs, plus optional conditions
+		relatedExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Select("1")
+		for _, ref := range rel.References {
+			if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				relatedExists = relatedExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+		relatedExists = relatedExists.Where(op.Conditions)
+
+		switch op.Type {
+		case clause.OpUnlink, clause.OpDelete:
+			joinDB = joinDB.Where("EXISTS (?)", ownersExists)
+			if len(op.Conditions) > 0 {
+				joinDB = joinDB.Where("EXISTS (?)", relatedExists)
+			}
+			return joinDB.Delete(nil).Error
+		case clause.OpUpdate:
+			// Update related table rows that have join rows matching owners
+			relatedDB := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Where(op.Conditions)
+
+			// correlated join subquery: join.rel_fk = related.pk AND EXISTS owners
+			joinSub := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.JoinTable.Table).Select("1")
+			for _, ref := range rel.References {
+				if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+					joinSub = joinSub.Where(clause.Eq{
+						Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+						Value:  clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					})
+				}
+			}
+			joinSub = joinSub.Where("EXISTS (?)", ownersExists)
+			return relatedDB.Where("EXISTS (?)", joinSub).Updates(setMap).Error
+		}
+	}
+	return errors.New("unsupported relationship")
+}
diff --git a/event-processor/vendor/gorm.io/gorm/gorm.go b/event-processor/vendor/gorm.io/gorm/gorm.go
index 67889262..a209bb09 100644
--- a/event-processor/vendor/gorm.io/gorm/gorm.go
+++ b/event-processor/vendor/gorm.io/gorm/gorm.go
@@ -23,6 +23,7 @@ type Config struct {
 	// You can disable it by setting `SkipDefaultTransaction` to true
 	SkipDefaultTransaction    bool
 	DefaultTransactionTimeout time.Duration
+	DefaultContextTimeout     time.Duration
 
 	// NamingStrategy tables, columns naming strategy
 	NamingStrategy schema.Namer
@@ -137,6 +138,14 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
 		return isConfig && !isConfig2
 	})
 
+	if len(opts) > 0 {
+		if c, ok := opts[0].(*Config); ok {
+			config = c
+		} else {
+			opts = append([]Option{config}, opts...)
+		}
+	}
+
 	var skipAfterInitialize bool
 	for _, opt := range opts {
 		if opt != nil {
diff --git a/event-processor/vendor/gorm.io/gorm/logger/slog.go b/event-processor/vendor/gorm.io/gorm/logger/slog.go
new file mode 100644
index 00000000..613234ca
--- /dev/null
+++ b/event-processor/vendor/gorm.io/gorm/logger/slog.go
@@ -0,0 +1,100 @@
+//go:build go1.21
+
+package logger
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"log/slog"
+	"time"
+)
+
+type slogLogger struct {
+	Logger                    *slog.Logger
+	LogLevel                  LogLevel
+	SlowThreshold             time.Duration
+	Parameterized             bool
+	Colorful                  bool // Ignored in slog
+	IgnoreRecordNotFoundError bool
+}
+
+func NewSlogLogger(logger *slog.Logger, config Config) Interface {
+	return &slogLogger{
+		Logger:                    logger,
+		LogLevel:                  config.LogLevel,
+		SlowThreshold:             config.SlowThreshold,
+		Parameterized:             config.ParameterizedQueries,
+		IgnoreRecordNotFoundError: config.IgnoreRecordNotFoundError,
+	}
+}
+
+func (l *slogLogger) LogMode(level LogLevel) Interface {
+	newLogger := *l
+	newLogger.LogLevel = level
+	return &newLogger
+}
+
+func (l *slogLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Info {
+		l.Logger.InfoContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Warn {
+		l.Logger.WarnContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Error {
+		l.Logger.ErrorContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	if l.LogLevel <= Silent {
+		return
+	}
+
+	elapsed := time.Since(begin)
+	sql, rows := fc()
+	fields := []slog.Attr{
+		slog.String("duration", fmt.Sprintf("%.3fms", float64(elapsed.Nanoseconds())/1e6)),
+		slog.String("sql", sql),
+	}
+
+	if rows != -1 {
+		fields = append(fields, slog.Int64("rows", rows))
+	}
+
+	switch {
+	case err != nil && (!l.IgnoreRecordNotFoundError || !errors.Is(err, ErrRecordNotFound)):
+		fields = append(fields, slog.String("error", err.Error()))
+		l.Logger.ErrorContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.SlowThreshold != 0 && elapsed > l.SlowThreshold:
+		l.Logger.WarnContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.LogLevel >= Info:
+		l.Logger.InfoContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+	}
+}
+
+// ParamsFilter filter params
+func (l *slogLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) {
+	if l.Parameterized {
+		return sql, nil
+	}
+	return sql, params
+}
diff --git a/event-processor/vendor/gorm.io/gorm/migrator/migrator.go b/event-processor/vendor/gorm.io/gorm/migrator/migrator.go
index cec4e30f..50a36d10 100644
--- a/event-processor/vendor/gorm.io/gorm/migrator/migrator.go
+++ b/event-processor/vendor/gorm.io/gorm/migrator/migrator.go
@@ -474,7 +474,6 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 	// found, smart migrate
 	fullDataType := strings.TrimSpace(strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL))
 	realDataType := strings.ToLower(columnType.DatabaseTypeName())
-
 	var (
 		alterColumn bool
 		isSameType  = fullDataType == realDataType
@@ -513,8 +512,19 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 				}
 			}
 		}
+	}
 
-		// check precision
+	// check precision
+	if realDataType == "decimal" || realDataType == "numeric" &&
+		regexp.MustCompile(realDataType+`\(.*\)`).FindString(fullDataType) != "" { // if realDataType has no precision,ignore
+		precision, scale, ok := columnType.DecimalSize()
+		if ok {
+			if !strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d,%d)", realDataType, precision, scale)) &&
+				!strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d)", realDataType, precision)) {
+				alterColumn = true
+			}
+		}
+	} else {
 		if precision, _, ok := columnType.DecimalSize(); ok && int64(field.Precision) != precision {
 			if regexp.MustCompile(fmt.Sprintf("[^0-9]%d[^0-9]", field.Precision)).MatchString(m.DataTypeOf(field)) {
 				alterColumn = true
diff --git a/event-processor/vendor/gorm.io/gorm/schema/field.go b/event-processor/vendor/gorm.io/gorm/schema/field.go
index a6ff1a72..de797402 100644
--- a/event-processor/vendor/gorm.io/gorm/schema/field.go
+++ b/event-processor/vendor/gorm.io/gorm/schema/field.go
@@ -448,16 +448,17 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 }
 
 // create valuer, setter when parse struct
-func (field *Field) setupValuerAndSetter() {
+func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
 	// Setup NewValuePool
 	field.setupNewValuePool()
 
 	// ValueOf returns field's value and if it is zero
 	fieldIndex := field.StructField.Index[0]
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
-			fieldValue := reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
+			v = reflect.Indirect(v)
+			fieldValue := v.Field(fieldIndex)
 			return fieldValue.Interface(), fieldValue.IsZero()
 		}
 	default:
@@ -504,9 +505,10 @@ func (field *Field) setupValuerAndSetter() {
 
 	// ReflectValueOf returns field's reflect value
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
-			return reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
+			v = reflect.Indirect(v)
+			return v.Field(fieldIndex)
 		}
 	default:
 		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
diff --git a/event-processor/vendor/gorm.io/gorm/schema/relationship.go b/event-processor/vendor/gorm.io/gorm/schema/relationship.go
index f1ace924..0535bba4 100644
--- a/event-processor/vendor/gorm.io/gorm/schema/relationship.go
+++ b/event-processor/vendor/gorm.io/gorm/schema/relationship.go
@@ -75,9 +75,7 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
 		}
 	)
 
-	cacheStore := schema.cacheStore
-
-	if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
+	if relation.FieldSchema, err = getOrParse(fieldValue, schema.cacheStore, schema.namer); err != nil {
 		schema.err = fmt.Errorf("failed to parse field: %s, error: %w", field.Name, err)
 		return nil
 	}
@@ -147,6 +145,9 @@ func hasPolymorphicRelation(tagSettings map[string]string) bool {
 }
 
 func (schema *Schema) setRelation(relation *Relationship) {
+	schema.Relationships.Mux.Lock()
+	defer schema.Relationships.Mux.Unlock()
+
 	// set non-embedded relation
 	if rel := schema.Relationships.Relations[relation.Name]; rel != nil {
 		if len(rel.Field.BindNames) > 1 {
@@ -590,6 +591,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 	// build references
 	for idx, foreignField := range foreignFields {
 		// use same data type for foreign keys
+		schema.Relationships.Mux.Lock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Lock()
+		}
 		if copyableDataType(primaryFields[idx].DataType) {
 			foreignField.DataType = primaryFields[idx].DataType
 		}
@@ -597,6 +602,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 		if foreignField.Size == 0 {
 			foreignField.Size = primaryFields[idx].Size
 		}
+		schema.Relationships.Mux.Unlock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Unlock()
+		}
 
 		relation.References = append(relation.References, &Reference{
 			PrimaryKey:    primaryFields[idx],
diff --git a/event-processor/vendor/gorm.io/gorm/schema/schema.go b/event-processor/vendor/gorm.io/gorm/schema/schema.go
index db236797..9419846b 100644
--- a/event-processor/vendor/gorm.io/gorm/schema/schema.go
+++ b/event-processor/vendor/gorm.io/gorm/schema/schema.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"go/ast"
+	"path"
 	"reflect"
 	"strings"
 	"sync"
@@ -59,14 +60,14 @@ type Schema struct {
 	cacheStore                *sync.Map
 }
 
-func (schema Schema) String() string {
+func (schema *Schema) String() string {
 	if schema.ModelType.Name() == "" {
 		return fmt.Sprintf("%s(%s)", schema.Name, schema.Table)
 	}
 	return fmt.Sprintf("%s.%s", schema.ModelType.PkgPath(), schema.ModelType.Name())
 }
 
-func (schema Schema) MakeSlice() reflect.Value {
+func (schema *Schema) MakeSlice() reflect.Value {
 	slice := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(schema.ModelType)), 0, 20)
 	results := reflect.New(slice.Type())
 	results.Elem().Set(slice)
@@ -74,7 +75,7 @@ func (schema Schema) MakeSlice() reflect.Value {
 	return results
 }
 
-func (schema Schema) LookUpField(name string) *Field {
+func (schema *Schema) LookUpField(name string) *Field {
 	if field, ok := schema.FieldsByDBName[name]; ok {
 		return field
 	}
@@ -92,10 +93,7 @@ func (schema Schema) LookUpField(name string) *Field {
 //		}
 //		ID string // is selected by LookUpFieldByBindName([]string{"ID"}, "ID")
 //	}
-func (schema Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
-	if len(bindNames) == 0 {
-		return nil
-	}
+func (schema *Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
 	for i := len(bindNames) - 1; i >= 0; i-- {
 		find := strings.Join(bindNames[:i], ".") + "." + name
 		if field, ok := schema.FieldsByBindName[find]; ok {
@@ -113,6 +111,14 @@ type TablerWithNamer interface {
 	TableName(Namer) string
 }
 
+var callbackTypes = []callbackType{
+	callbackTypeBeforeCreate, callbackTypeAfterCreate,
+	callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
+	callbackTypeBeforeSave, callbackTypeAfterSave,
+	callbackTypeBeforeDelete, callbackTypeAfterDelete,
+	callbackTypeAfterFind,
+}
+
 // Parse get data type from dialector
 func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	return ParseWithSpecialTableName(dest, cacheStore, namer, "")
@@ -124,34 +130,33 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
 	}
 
-	value := reflect.ValueOf(dest)
-	if value.Kind() == reflect.Ptr && value.IsNil() {
-		value = reflect.New(value.Type().Elem())
-	}
-	modelType := reflect.Indirect(value).Type()
-
-	if modelType.Kind() == reflect.Interface {
-		modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
-	}
-
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+	modelType := reflect.ValueOf(dest).Type()
+	if modelType.Kind() == reflect.Ptr {
 		modelType = modelType.Elem()
 	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		if modelType.Kind() == reflect.Interface {
+			modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
+		}
+
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	// Cache the Schema for performance,
 	// Use the modelType or modelType + schemaTable (if it present) as cache key.
-	var schemaCacheKey interface{}
+	var schemaCacheKey interface{} = modelType
 	if specialTableName != "" {
 		schemaCacheKey = fmt.Sprintf("%p-%s", modelType, specialTableName)
-	} else {
-		schemaCacheKey = modelType
 	}
 
 	// Load exist schema cache, return if exists
@@ -162,28 +167,29 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return s, s.err
 	}
 
+	var tableName string
 	modelValue := reflect.New(modelType)
-	tableName := namer.TableName(modelType.Name())
-	if tabler, ok := modelValue.Interface().(Tabler); ok {
+	if specialTableName != "" {
+		tableName = specialTableName
+	} else if en, ok := namer.(embeddedNamer); ok {
+		tableName = en.Table
+	} else if tabler, ok := modelValue.Interface().(Tabler); ok {
 		tableName = tabler.TableName()
-	}
-	if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
+	} else if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
 		tableName = tabler.TableName(namer)
-	}
-	if en, ok := namer.(embeddedNamer); ok {
-		tableName = en.Table
-	}
-	if specialTableName != "" && specialTableName != tableName {
-		tableName = specialTableName
+	} else {
+		tableName = namer.TableName(modelType.Name())
 	}
 
 	schema := &Schema{
 		Name:             modelType.Name(),
 		ModelType:        modelType,
 		Table:            tableName,
-		FieldsByName:     map[string]*Field{},
-		FieldsByBindName: map[string]*Field{},
-		FieldsByDBName:   map[string]*Field{},
+		DBNames:          make([]string, 0, 10),
+		Fields:           make([]*Field, 0, 10),
+		FieldsByName:     make(map[string]*Field, 10),
+		FieldsByBindName: make(map[string]*Field, 10),
+		FieldsByDBName:   make(map[string]*Field, 10),
 		Relationships:    Relationships{Relations: map[string]*Relationship{}},
 		cacheStore:       cacheStore,
 		namer:            namer,
@@ -227,8 +233,9 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 				schema.FieldsByBindName[bindName] = field
 
 				if v != nil && v.PrimaryKey {
+					// remove the existing primary key field
 					for idx, f := range schema.PrimaryFields {
-						if f == v {
+						if f.DBName == v.DBName {
 							schema.PrimaryFields = append(schema.PrimaryFields[0:idx], schema.PrimaryFields[idx+1:]...)
 						}
 					}
@@ -247,7 +254,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 			schema.FieldsByBindName[bindName] = field
 		}
 
-		field.setupValuerAndSetter()
+		field.setupValuerAndSetter(modelType)
 	}
 
 	prioritizedPrimaryField := schema.LookUpField("id")
@@ -283,10 +290,37 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		schema.PrimaryFieldDBNames = append(schema.PrimaryFieldDBNames, field.DBName)
 	}
 
+	_, embedded := schema.cacheStore.Load(embeddedCacheKey)
+	relationshipFields := []*Field{}
 	for _, field := range schema.Fields {
 		if field.DataType != "" && field.HasDefaultValue && field.DefaultValueInterface == nil {
 			schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field)
 		}
+
+		if !embedded {
+			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
+				relationshipFields = append(relationshipFields, field)
+				schema.FieldsByName[field.Name] = field
+				schema.FieldsByBindName[field.BindName()] = field
+			}
+
+			fieldValue := reflect.New(field.IndirectFieldType).Interface()
+			if fc, ok := fieldValue.(CreateClausesInterface); ok {
+				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(QueryClausesInterface); ok {
+				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(UpdateClausesInterface); ok {
+				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(DeleteClausesInterface); ok {
+				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
+			}
+		}
 	}
 
 	if field := schema.PrioritizedPrimaryField; field != nil {
@@ -303,24 +337,6 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}
 
-	callbackTypes := []callbackType{
-		callbackTypeBeforeCreate, callbackTypeAfterCreate,
-		callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
-		callbackTypeBeforeSave, callbackTypeAfterSave,
-		callbackTypeBeforeDelete, callbackTypeAfterDelete,
-		callbackTypeAfterFind,
-	}
-	for _, cbName := range callbackTypes {
-		if methodValue := callBackToMethodValue(modelValue, cbName); methodValue.IsValid() {
-			switch methodValue.Type().String() {
-			case "func(*gorm.DB) error": // TODO hack
-				reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
-			default:
-				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
-			}
-		}
-	}
-
 	// Cache the schema
 	if v, loaded := cacheStore.LoadOrStore(schemaCacheKey, schema); loaded {
 		s := v.(*Schema)
@@ -336,84 +352,47 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}()
 
-	if _, embedded := schema.cacheStore.Load(embeddedCacheKey); !embedded {
-		for _, field := range schema.Fields {
-			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
-				if schema.parseRelation(field); schema.err != nil {
-					return schema, schema.err
+	for _, cbName := range callbackTypes {
+		if methodValue := modelValue.MethodByName(string(cbName)); methodValue.IsValid() {
+			switch methodValue.Type().String() {
+			case "func(*gorm.DB) error":
+				expectedPkgPath := path.Dir(reflect.TypeOf(schema).Elem().PkgPath())
+				if inVarPkg := methodValue.Type().In(0).Elem().PkgPath(); inVarPkg == expectedPkgPath {
+					reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
 				} else {
-					schema.FieldsByName[field.Name] = field
-					schema.FieldsByBindName[field.BindName()] = field
+					logger.Default.Warn(context.Background(), "In model %v, the hook function `%v(*gorm.DB) error` has an incorrect parameter type. The expected parameter type is `%v`, but the provided type is `%v`.", schema, cbName, expectedPkgPath, inVarPkg)
+					// PASS
 				}
+			default:
+				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
 			}
+		}
+	}
 
-			fieldValue := reflect.New(field.IndirectFieldType)
-			fieldInterface := fieldValue.Interface()
-			if fc, ok := fieldInterface.(CreateClausesInterface); ok {
-				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(QueryClausesInterface); ok {
-				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(UpdateClausesInterface); ok {
-				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(DeleteClausesInterface); ok {
-				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
-			}
+	// parse relationships
+	for _, field := range relationshipFields {
+		if schema.parseRelation(field); schema.err != nil {
+			return schema, schema.err
 		}
 	}
 
 	return schema, schema.err
 }
 
-// This unrolling is needed to show to the compiler the exact set of methods
-// that can be used on the modelType.
-// Prior to go1.22 any use of MethodByName would cause the linker to
-// abandon dead code elimination for the entire binary.
-// As of go1.22 the compiler supports one special case of a string constant
-// being passed to MethodByName. For enterprise customers or those building
-// large binaries, this gives a significant reduction in binary size.
-// https://github.com/golang/go/issues/62257
-func callBackToMethodValue(modelType reflect.Value, cbType callbackType) reflect.Value {
-	switch cbType {
-	case callbackTypeBeforeCreate:
-		return modelType.MethodByName(string(callbackTypeBeforeCreate))
-	case callbackTypeAfterCreate:
-		return modelType.MethodByName(string(callbackTypeAfterCreate))
-	case callbackTypeBeforeUpdate:
-		return modelType.MethodByName(string(callbackTypeBeforeUpdate))
-	case callbackTypeAfterUpdate:
-		return modelType.MethodByName(string(callbackTypeAfterUpdate))
-	case callbackTypeBeforeSave:
-		return modelType.MethodByName(string(callbackTypeBeforeSave))
-	case callbackTypeAfterSave:
-		return modelType.MethodByName(string(callbackTypeAfterSave))
-	case callbackTypeBeforeDelete:
-		return modelType.MethodByName(string(callbackTypeBeforeDelete))
-	case callbackTypeAfterDelete:
-		return modelType.MethodByName(string(callbackTypeAfterDelete))
-	case callbackTypeAfterFind:
-		return modelType.MethodByName(string(callbackTypeAfterFind))
-	default:
-		return reflect.ValueOf(nil)
-	}
-}
-
 func getOrParse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	modelType := reflect.ValueOf(dest).Type()
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
-		modelType = modelType.Elem()
-	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	if v, ok := cacheStore.Load(modelType); ok {
diff --git a/event-processor/vendor/gorm.io/gorm/schema/utils.go b/event-processor/vendor/gorm.io/gorm/schema/utils.go
index fa1c65d4..d4fe252e 100644
--- a/event-processor/vendor/gorm.io/gorm/schema/utils.go
+++ b/event-processor/vendor/gorm.io/gorm/schema/utils.go
@@ -121,6 +121,17 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
 	}
 
 	switch reflectValue.Kind() {
+	case reflect.Map:
+		results = [][]interface{}{make([]interface{}, len(fields))}
+		for idx, field := range fields {
+			mapValue := reflectValue.MapIndex(reflect.ValueOf(field.DBName))
+			if mapValue.IsZero() {
+				mapValue = reflectValue.MapIndex(reflect.ValueOf(field.Name))
+			}
+			results[0][idx] = mapValue.Interface()
+		}
+
+		dataResults[utils.ToStringKey(results[0]...)] = []reflect.Value{reflectValue}
 	case reflect.Struct:
 		results = [][]interface{}{make([]interface{}, len(fields))}
 
diff --git a/event-processor/vendor/gorm.io/gorm/statement.go b/event-processor/vendor/gorm.io/gorm/statement.go
index c6183724..736087d7 100644
--- a/event-processor/vendor/gorm.io/gorm/statement.go
+++ b/event-processor/vendor/gorm.io/gorm/statement.go
@@ -96,7 +96,9 @@ func (stmt *Statement) QuoteTo(writer clause.Writer, field interface{}) {
 		if v.Name == clause.CurrentTable {
 			if stmt.TableExpr != nil {
 				stmt.TableExpr.Build(stmt)
-			} else {
+			} else if stmt.Table != "" {
+				write(v.Raw, stmt.Table)
+			} else if stmt.AddError(stmt.Parse(stmt.Model)) == nil {
 				write(v.Raw, stmt.Table)
 			}
 		} else {
@@ -334,6 +336,8 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 		switch v := arg.(type) {
 		case clause.Expression:
 			conds = append(conds, v)
+		case []clause.Expression:
+			conds = append(conds, v...)
 		case *DB:
 			v.executeScopes()
 
@@ -341,7 +345,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 				if where, ok := cs.Expression.(clause.Where); ok {
 					if len(where.Exprs) == 1 {
 						if orConds, ok := where.Exprs[0].(clause.OrConditions); ok {
-							where.Exprs[0] = clause.AndConditions(orConds)
+							if len(orConds.Exprs) == 1 {
+								where.Exprs[0] = clause.AndConditions(orConds)
+							}
 						}
 					}
 					conds = append(conds, clause.And(where.Exprs...))
@@ -362,6 +368,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 
 			for _, key := range keys {
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				conds = append(conds, clause.Eq{Column: column, Value: v[key]})
 			}
 		case map[string]interface{}:
@@ -374,6 +383,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 			for _, key := range keys {
 				reflectValue := reflect.Indirect(reflect.ValueOf(v[key]))
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				switch reflectValue.Kind() {
 				case reflect.Slice, reflect.Array:
 					if _, ok := v[key].(driver.Valuer); ok {
@@ -650,12 +662,15 @@ func (stmt *Statement) Changed(fields ...string) bool {
 				for destValue.Kind() == reflect.Ptr {
 					destValue = destValue.Elem()
 				}
-
-				changedValue, zero := field.ValueOf(stmt.Context, destValue)
-				if v {
-					return !utils.AssertEqual(changedValue, fieldValue)
+				if descSchema, err := schema.Parse(stmt.Dest, stmt.DB.cacheStore, stmt.DB.NamingStrategy); err == nil {
+					if destField := descSchema.LookUpField(field.DBName); destField != nil {
+						changedValue, zero := destField.ValueOf(stmt.Context, destValue)
+						if v {
+							return !utils.AssertEqual(changedValue, fieldValue)
+						}
+						return !zero && !utils.AssertEqual(changedValue, fieldValue)
+					}
 				}
-				return !zero && !utils.AssertEqual(changedValue, fieldValue)
 			}
 		}
 		return false
diff --git a/event-processor/vendor/modules.txt b/event-processor/vendor/modules.txt
index 302d7e06..b34ed1e8 100644
--- a/event-processor/vendor/modules.txt
+++ b/event-processor/vendor/modules.txt
@@ -119,6 +119,9 @@ github.com/charithe/durationcheck
 # github.com/chavacava/garif v0.1.0
 ## explicit; go 1.16
 github.com/chavacava/garif
+# github.com/cilium/tetragon v1.3.0
+## explicit; go 1.23.0
+github.com/cilium/tetragon/pkg/arch
 # github.com/cilium/tetragon/api v1.3.0
 ## explicit; go 1.23.0
 github.com/cilium/tetragon/api/v1/tetragon
@@ -164,9 +167,10 @@ github.com/felixge/httpsnoop
 # github.com/firefart/nonamedreturns v1.0.5
 ## explicit; go 1.18
 github.com/firefart/nonamedreturns/analyzer
-# github.com/fsnotify/fsnotify v1.6.0
-## explicit; go 1.16
+# github.com/fsnotify/fsnotify v1.8.0
+## explicit; go 1.17
 github.com/fsnotify/fsnotify
+github.com/fsnotify/fsnotify/internal
 # github.com/fzipp/gocyclo v0.6.0
 ## explicit; go 1.18
 github.com/fzipp/gocyclo
@@ -205,7 +209,7 @@ github.com/go-toolsmith/strparse
 # github.com/go-toolsmith/typep v1.1.0
 ## explicit; go 1.16
 github.com/go-toolsmith/typep
-# github.com/go-viper/mapstructure/v2 v2.2.1
+# github.com/go-viper/mapstructure/v2 v2.4.0
 ## explicit; go 1.18
 github.com/go-viper/mapstructure/v2
 github.com/go-viper/mapstructure/v2/internal/errors
@@ -441,8 +445,8 @@ github.com/gostaticanalysis/forcetypeassert
 # github.com/gostaticanalysis/nilerr v0.1.1
 ## explicit; go 1.15
 github.com/gostaticanalysis/nilerr
-# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
-## explicit; go 1.23.0
+# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
+## explicit; go 1.24.0
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/casing
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor
@@ -467,18 +471,6 @@ github.com/hashicorp/go-version
 ## explicit; go 1.18
 github.com/hashicorp/golang-lru/v2/internal
 github.com/hashicorp/golang-lru/v2/simplelru
-# github.com/hashicorp/hcl v1.0.0
-## explicit
-github.com/hashicorp/hcl
-github.com/hashicorp/hcl/hcl/ast
-github.com/hashicorp/hcl/hcl/parser
-github.com/hashicorp/hcl/hcl/printer
-github.com/hashicorp/hcl/hcl/scanner
-github.com/hashicorp/hcl/hcl/strconv
-github.com/hashicorp/hcl/hcl/token
-github.com/hashicorp/hcl/json/parser
-github.com/hashicorp/hcl/json/scanner
-github.com/hashicorp/hcl/json/token
 # github.com/hexops/gotextdiff v1.0.3
 ## explicit; go 1.16
 github.com/hexops/gotextdiff
@@ -493,8 +485,8 @@ github.com/jackc/pgpassfile
 # github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
 ## explicit; go 1.14
 github.com/jackc/pgservicefile
-# github.com/jackc/pgx/v5 v5.7.1
-## explicit; go 1.21
+# github.com/jackc/pgx/v5 v5.7.6
+## explicit; go 1.23.0
 github.com/jackc/pgx/v5
 github.com/jackc/pgx/v5/internal/iobufpool
 github.com/jackc/pgx/v5/internal/pgio
@@ -541,8 +533,8 @@ github.com/kisielk/errcheck/errcheck
 # github.com/kkHAIKE/contextcheck v1.1.6
 ## explicit; go 1.23.0
 github.com/kkHAIKE/contextcheck
-# github.com/knqyf263/go-plugin v0.8.1-0.20241107183803-4626258850e7
-## explicit; go 1.22
+# github.com/knqyf263/go-plugin v0.9.0
+## explicit; go 1.24.0
 github.com/knqyf263/go-plugin/cmd/protoc-gen-go-plugin
 github.com/knqyf263/go-plugin/encoding/defval
 github.com/knqyf263/go-plugin/encoding/tag
@@ -592,9 +584,6 @@ github.com/lufia/plan9stats
 # github.com/macabu/inamedparam v0.1.3
 ## explicit; go 1.20
 github.com/macabu/inamedparam
-# github.com/magiconair/properties v1.8.7
-## explicit; go 1.19
-github.com/magiconair/properties
 # github.com/maratori/testableexamples v1.0.0
 ## explicit; go 1.19
 github.com/maratori/testableexamples/pkg/testableexamples
@@ -625,9 +614,6 @@ github.com/mgechev/revive/rule
 # github.com/mitchellh/go-homedir v1.1.0
 ## explicit
 github.com/mitchellh/go-homedir
-# github.com/mitchellh/mapstructure v1.5.0
-## explicit; go 1.14
-github.com/mitchellh/mapstructure
 # github.com/moricho/tparallel v0.3.2
 ## explicit; go 1.20
 github.com/moricho/tparallel
@@ -707,8 +693,8 @@ github.com/prometheus/client_model/go
 ## explicit; go 1.21
 github.com/prometheus/common/expfmt
 github.com/prometheus/common/model
-# github.com/prometheus/procfs v0.15.1
-## explicit; go 1.20
+# github.com/prometheus/procfs v0.17.0
+## explicit; go 1.23.0
 github.com/prometheus/procfs
 github.com/prometheus/procfs/internal/fs
 github.com/prometheus/procfs/internal/util
@@ -760,21 +746,21 @@ github.com/rogpeppe/go-internal/internal/syscall/windows
 github.com/rogpeppe/go-internal/internal/syscall/windows/sysdll
 github.com/rogpeppe/go-internal/lockedfile
 github.com/rogpeppe/go-internal/lockedfile/internal/filelock
-# github.com/rs/cors v1.11.0
+# github.com/rs/cors v1.11.1
 ## explicit; go 1.13
 github.com/rs/cors
 github.com/rs/cors/internal
-# github.com/rs/zerolog v1.33.0
+# github.com/rs/zerolog v1.34.0
 ## explicit; go 1.15
 github.com/rs/zerolog
 github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000 => ../history-api
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/history-api/pkg/model
 # github.com/runtime-radar/runtime-radar/lib v0.0.24 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/docker
 github.com/runtime-radar/runtime-radar/lib/errcommon
@@ -787,10 +773,10 @@ github.com/runtime-radar/runtime-radar/lib/server/healthcheck
 github.com/runtime-radar/runtime-radar/lib/server/interceptor
 github.com/runtime-radar/runtime-radar/lib/server/middleware
 # github.com/runtime-radar/runtime-radar/notifier v0.0.0-00010101000000-000000000000 => ../notifier
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/notifier/api
 # github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8 => ../policy-enforcer
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/policy-enforcer/api
 github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model
 # github.com/ryancurrah/gomodguard v1.3.5
@@ -799,12 +785,9 @@ github.com/ryancurrah/gomodguard
 # github.com/ryanrolds/sqlclosecheck v0.5.1
 ## explicit; go 1.20
 github.com/ryanrolds/sqlclosecheck/pkg/analyzer
-# github.com/sagikazarmark/locafero v0.3.0
-## explicit; go 1.20
+# github.com/sagikazarmark/locafero v0.7.0
+## explicit; go 1.21
 github.com/sagikazarmark/locafero
-# github.com/sagikazarmark/slog-shim v0.1.0
-## explicit; go 1.20
-github.com/sagikazarmark/slog-shim
 # github.com/sanposhiho/wastedassign/v2 v2.1.0
 ## explicit; go 1.18
 github.com/sanposhiho/wastedassign/v2
@@ -865,26 +848,23 @@ github.com/sourcegraph/go-diff/diff
 github.com/spf13/afero
 github.com/spf13/afero/internal/common
 github.com/spf13/afero/mem
-# github.com/spf13/cast v1.5.1
-## explicit; go 1.18
+# github.com/spf13/cast v1.7.1
+## explicit; go 1.19
 github.com/spf13/cast
 # github.com/spf13/cobra v1.9.1
 ## explicit; go 1.15
 github.com/spf13/cobra
-# github.com/spf13/pflag v1.0.6
+# github.com/spf13/pflag v1.0.7
 ## explicit; go 1.12
 github.com/spf13/pflag
-# github.com/spf13/viper v1.17.0
-## explicit; go 1.18
+# github.com/spf13/viper v1.20.1
+## explicit; go 1.21.0
 github.com/spf13/viper
-github.com/spf13/viper/internal/encoding
 github.com/spf13/viper/internal/encoding/dotenv
-github.com/spf13/viper/internal/encoding/hcl
-github.com/spf13/viper/internal/encoding/ini
-github.com/spf13/viper/internal/encoding/javaproperties
 github.com/spf13/viper/internal/encoding/json
 github.com/spf13/viper/internal/encoding/toml
 github.com/spf13/viper/internal/encoding/yaml
+github.com/spf13/viper/internal/features
 # github.com/ssgreg/nlreturn/v2 v2.2.1
 ## explicit; go 1.13
 github.com/ssgreg/nlreturn/v2/pkg/nlreturn
@@ -1033,26 +1013,22 @@ go.uber.org/zap/internal/exit
 go.uber.org/zap/internal/pool
 go.uber.org/zap/internal/stacktrace
 go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.38.0
+# go.yaml.in/yaml/v3 v3.0.4
+## explicit; go 1.16
+go.yaml.in/yaml/v3
+# golang.org/x/crypto v0.41.0
 ## explicit; go 1.23.0
 golang.org/x/crypto/pbkdf2
-# golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
-## explicit; go 1.22.0
-golang.org/x/exp/constraints
-golang.org/x/exp/slices
-golang.org/x/exp/slog
-golang.org/x/exp/slog/internal
-golang.org/x/exp/slog/internal/buffer
 # golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac
 ## explicit; go 1.18
 golang.org/x/exp/typeparams
-# golang.org/x/mod v0.25.0
+# golang.org/x/mod v0.27.0
 ## explicit; go 1.23.0
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.40.0
+# golang.org/x/net v0.43.0
 ## explicit; go 1.23.0
 golang.org/x/net/http/httpguts
 golang.org/x/net/http2
@@ -1061,16 +1037,27 @@ golang.org/x/net/idna
 golang.org/x/net/internal/httpcommon
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
-# golang.org/x/sync v0.15.0
-## explicit; go 1.23.0
+# golang.org/x/sync v0.17.0
+## explicit; go 1.24.0
 golang.org/x/sync/errgroup
 golang.org/x/sync/semaphore
-# golang.org/x/sys v0.33.0
+# golang.org/x/sys v0.35.0
 ## explicit; go 1.23.0
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/text v0.26.0
+# golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
 ## explicit; go 1.23.0
+golang.org/x/telemetry
+golang.org/x/telemetry/counter
+golang.org/x/telemetry/internal/config
+golang.org/x/telemetry/internal/configstore
+golang.org/x/telemetry/internal/counter
+golang.org/x/telemetry/internal/crashmonitor
+golang.org/x/telemetry/internal/mmap
+golang.org/x/telemetry/internal/telemetry
+golang.org/x/telemetry/internal/upload
+# golang.org/x/text v0.29.0
+## explicit; go 1.24.0
 golang.org/x/text/cases
 golang.org/x/text/encoding
 golang.org/x/text/encoding/internal
@@ -1096,7 +1083,7 @@ golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
-# golang.org/x/tools v0.33.0
+# golang.org/x/tools v0.36.0
 ## explicit; go 1.23.0
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/passes/appends
@@ -1148,6 +1135,7 @@ golang.org/x/tools/go/analysis/passes/unusedresult
 golang.org/x/tools/go/analysis/passes/unusedwrite
 golang.org/x/tools/go/analysis/passes/waitgroup
 golang.org/x/tools/go/ast/astutil
+golang.org/x/tools/go/ast/edge
 golang.org/x/tools/go/ast/inspector
 golang.org/x/tools/go/buildutil
 golang.org/x/tools/go/callgraph
@@ -1168,8 +1156,6 @@ golang.org/x/tools/imports
 golang.org/x/tools/internal/aliases
 golang.org/x/tools/internal/analysisinternal
 golang.org/x/tools/internal/astutil
-golang.org/x/tools/internal/astutil/cursor
-golang.org/x/tools/internal/astutil/edge
 golang.org/x/tools/internal/event
 golang.org/x/tools/internal/event/core
 golang.org/x/tools/internal/event/keys
@@ -1186,32 +1172,40 @@ golang.org/x/tools/internal/stdlib
 golang.org/x/tools/internal/typeparams
 golang.org/x/tools/internal/typesinternal
 golang.org/x/tools/internal/versions
-# golang.org/x/vuln v0.2.0
-## explicit; go 1.18
+# golang.org/x/tools/go/expect v0.1.1-deprecated
+## explicit; go 1.23.0
+# golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated
+## explicit; go 1.23.0
+# golang.org/x/vuln v1.1.4
+## explicit; go 1.22.0
 golang.org/x/vuln/cmd/govulncheck
 golang.org/x/vuln/internal
+golang.org/x/vuln/internal/buildinfo
 golang.org/x/vuln/internal/client
 golang.org/x/vuln/internal/derrors
+golang.org/x/vuln/internal/gosym
+golang.org/x/vuln/internal/goversion
 golang.org/x/vuln/internal/govulncheck
+golang.org/x/vuln/internal/openvex
 golang.org/x/vuln/internal/osv
+golang.org/x/vuln/internal/sarif
 golang.org/x/vuln/internal/scan
 golang.org/x/vuln/internal/semver
+golang.org/x/vuln/internal/traces
 golang.org/x/vuln/internal/vulncheck
-golang.org/x/vuln/internal/vulncheck/internal/buildinfo
-golang.org/x/vuln/internal/vulncheck/internal/gosym
 golang.org/x/vuln/internal/web
 golang.org/x/vuln/scan
-# google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/api
 google.golang.org/genproto/googleapis/api/annotations
 google.golang.org/genproto/googleapis/api/httpbody
 google.golang.org/genproto/googleapis/api/visibility
-# google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/rpc/errdetails
 google.golang.org/genproto/googleapis/rpc/status
-# google.golang.org/grpc v1.73.0
+# google.golang.org/grpc v1.75.1
 ## explicit; go 1.23.0
 google.golang.org/grpc
 google.golang.org/grpc/attributes
@@ -1281,8 +1275,8 @@ google.golang.org/grpc/tap
 # google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
 ## explicit; go 1.21
 google.golang.org/grpc/cmd/protoc-gen-go-grpc
-# google.golang.org/protobuf v1.36.6
-## explicit; go 1.22
+# google.golang.org/protobuf v1.36.10
+## explicit; go 1.23
 google.golang.org/protobuf/cmd/protoc-gen-go
 google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo
 google.golang.org/protobuf/compiler/protogen
@@ -1334,9 +1328,6 @@ google.golang.org/protobuf/types/known/structpb
 google.golang.org/protobuf/types/known/timestamppb
 google.golang.org/protobuf/types/known/wrapperspb
 google.golang.org/protobuf/types/pluginpb
-# gopkg.in/ini.v1 v1.67.0
-## explicit
-gopkg.in/ini.v1
 # gopkg.in/yaml.v2 v2.4.0
 ## explicit; go 1.15
 gopkg.in/yaml.v2
@@ -1346,7 +1337,7 @@ gopkg.in/yaml.v3
 # gorm.io/driver/postgres v1.6.0
 ## explicit; go 1.20
 gorm.io/driver/postgres
-# gorm.io/gorm v1.30.0
+# gorm.io/gorm v1.31.0
 ## explicit; go 1.18
 gorm.io/gorm
 gorm.io/gorm/callbacks
diff --git a/go.mod b/go.mod
index 794fa16b..9d420ba0 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/runtime-radar/runtime-radar
 
-go 1.24
+go 1.25
 
 require (
 	github.com/golangci/golangci-lint v1.64.8
diff --git a/history-api/Dockerfile b/history-api/Dockerfile
index 88a010cc..7459b199 100644
--- a/history-api/Dockerfile
+++ b/history-api/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 ARG BUILD_RELEASE
 ARG BUILD_BRANCH
diff --git a/history-api/docker-compose.test.yml b/history-api/docker-compose.test.yml
index 3126a730..c59784f0 100644
--- a/history-api/docker-compose.test.yml
+++ b/history-api/docker-compose.test.yml
@@ -1,6 +1,6 @@
 services:
   test:
-      image: golang:1.24
+      image: golang:1.25
       working_dir: /go/src/repo
       volumes:
         - .:/go/src/repo
diff --git a/history-api/go.mod b/history-api/go.mod
index a816ec3b..fb790952 100644
--- a/history-api/go.mod
+++ b/history-api/go.mod
@@ -1,27 +1,27 @@
 module github.com/runtime-radar/runtime-radar/history-api
 
-go 1.23.0
+go 1.25
 
 require (
 	github.com/cilium/tetragon/api v1.3.0
 	github.com/golangci/golangci-lint v1.64.8
 	github.com/google/gops v0.3.28
 	github.com/google/uuid v1.6.0
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
 	github.com/justinas/alice v1.2.0
-	github.com/rs/cors v1.11.0
-	github.com/rs/zerolog v1.33.0
+	github.com/rs/cors v1.11.1
+	github.com/rs/zerolog v1.34.0
 	github.com/runtime-radar/runtime-radar/event-processor v0.0.0-00010101000000-000000000000
 	github.com/runtime-radar/runtime-radar/lib v0.0.24
 	github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8
 	go.uber.org/automaxprocs v1.6.0
-	golang.org/x/vuln v0.2.0
-	google.golang.org/grpc v1.73.0
+	golang.org/x/vuln v1.1.4
+	google.golang.org/grpc v1.75.1
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
-	google.golang.org/protobuf v1.36.6
+	google.golang.org/protobuf v1.36.10
 	gorm.io/driver/clickhouse v0.6.1
 	gorm.io/driver/postgres v1.6.0
-	gorm.io/gorm v1.30.0
+	gorm.io/gorm v1.31.0
 )
 
 require (
@@ -31,8 +31,8 @@ require (
 )
 
 require (
-	google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect
 )
 
 require (
@@ -80,7 +80,7 @@ require (
 	github.com/fatih/color v1.18.0 // indirect
 	github.com/fatih/structtag v1.2.0 // indirect
 	github.com/firefart/nonamedreturns v1.0.5 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/fsnotify/fsnotify v1.8.0 // indirect
 	github.com/fzipp/gocyclo v0.6.0 // indirect
 	github.com/ghostiam/protogetter v0.3.9 // indirect
 	github.com/go-critic/go-critic v0.12.0 // indirect
@@ -94,7 +94,7 @@ require (
 	github.com/go-toolsmith/astp v1.1.0 // indirect
 	github.com/go-toolsmith/strparse v1.1.0 // indirect
 	github.com/go-toolsmith/typep v1.1.0 // indirect
-	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
+	github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
 	github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
 	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
@@ -115,12 +115,11 @@ require (
 	github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
 	github.com/hashicorp/go-version v1.7.0 // indirect
 	github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
-	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/hexops/gotextdiff v1.0.3 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
-	github.com/jackc/pgx/v5 v5.7.1 // indirect
+	github.com/jackc/pgx/v5 v5.7.6 // indirect
 	github.com/jackc/puddle/v2 v2.2.2 // indirect
 	github.com/jgautheron/goconst v1.7.1 // indirect
 	github.com/jingyugao/rowserrcheck v1.1.1 // indirect
@@ -143,7 +142,6 @@ require (
 	github.com/leonklingele/grouper v1.1.2 // indirect
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/macabu/inamedparam v0.1.3 // indirect
-	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/maratori/testableexamples v1.0.0 // indirect
 	github.com/maratori/testpackage v1.1.1 // indirect
 	github.com/matoous/godox v1.1.0 // indirect
@@ -152,7 +150,6 @@ require (
 	github.com/mattn/go-runewidth v0.0.16 // indirect
 	github.com/mgechev/revive v1.7.0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
-	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/moricho/tparallel v0.3.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/nakabonne/nestif v0.3.1 // indirect
@@ -169,7 +166,7 @@ require (
 	github.com/prometheus/client_golang v1.22.0 // indirect
 	github.com/prometheus/client_model v0.6.2 // indirect
 	github.com/prometheus/common v0.62.0 // indirect
-	github.com/prometheus/procfs v0.15.1 // indirect
+	github.com/prometheus/procfs v0.17.0 // indirect
 	github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
 	github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
 	github.com/quasilyte/gogrep v0.5.0 // indirect
@@ -181,8 +178,7 @@ require (
 	github.com/rogpeppe/go-internal v1.14.1 // indirect
 	github.com/ryancurrah/gomodguard v1.3.5 // indirect
 	github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
-	github.com/sagikazarmark/locafero v0.3.0 // indirect
-	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+	github.com/sagikazarmark/locafero v0.7.0 // indirect
 	github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
 	github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
 	github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
@@ -199,10 +195,10 @@ require (
 	github.com/sourcegraph/conc v0.3.0 // indirect
 	github.com/sourcegraph/go-diff v0.7.0 // indirect
 	github.com/spf13/afero v1.12.0 // indirect
-	github.com/spf13/cast v1.5.1 // indirect
+	github.com/spf13/cast v1.7.1 // indirect
 	github.com/spf13/cobra v1.9.1 // indirect
-	github.com/spf13/pflag v1.0.6 // indirect
-	github.com/spf13/viper v1.17.0 // indirect
+	github.com/spf13/pflag v1.0.7 // indirect
+	github.com/spf13/viper v1.20.1 // indirect
 	github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
 	github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
@@ -229,20 +225,20 @@ require (
 	gitlab.com/bosi/decorder v0.4.2 // indirect
 	go-simpler.org/musttag v0.13.0 // indirect
 	go-simpler.org/sloglint v0.9.0 // indirect
-	go.opentelemetry.io/otel v1.35.0 // indirect
-	go.opentelemetry.io/otel/trace v1.35.0 // indirect
+	go.opentelemetry.io/otel v1.37.0 // indirect
+	go.opentelemetry.io/otel/trace v1.37.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.38.0 // indirect
-	golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
+	go.yaml.in/yaml/v3 v3.0.4 // indirect
+	golang.org/x/crypto v0.41.0 // indirect
 	golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
-	golang.org/x/mod v0.25.0 // indirect
-	golang.org/x/net v0.40.0 // indirect
-	golang.org/x/sync v0.15.0 // indirect
-	golang.org/x/sys v0.33.0 // indirect
-	golang.org/x/text v0.26.0 // indirect
-	golang.org/x/tools v0.33.0 // indirect
-	gopkg.in/ini.v1 v1.67.0 // indirect
+	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/net v0.43.0 // indirect
+	golang.org/x/sync v0.17.0 // indirect
+	golang.org/x/sys v0.35.0 // indirect
+	golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 // indirect
+	golang.org/x/text v0.29.0 // indirect
+	golang.org/x/tools v0.36.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	honnef.co/go/tools v0.6.1 // indirect
diff --git a/history-api/go.sum b/history-api/go.sum
index 4fb6da98..b47fad38 100644
--- a/history-api/go.sum
+++ b/history-api/go.sum
@@ -102,10 +102,10 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
 github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
 github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
 github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ=
@@ -116,8 +116,8 @@ github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
 github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
 github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
 github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@@ -146,8 +146,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi
 github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ=
 github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
 github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
-github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
-github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY=
 github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
@@ -213,8 +213,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW
 github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
 github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8=
 github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
 github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
@@ -224,8 +224,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe
 github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -234,8 +232,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
-github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
-github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
+github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
+github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
 github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
 github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
@@ -292,8 +290,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
 github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
 github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE=
 github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04=
@@ -316,8 +312,6 @@ github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY=
 github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
 github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
@@ -369,8 +363,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
 github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
 github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
 github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
@@ -390,20 +384,18 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
 github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
-github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
-github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
-github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
+github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
+github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU=
 github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE=
 github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
 github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
-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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
+github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
 github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
 github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
 github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
@@ -440,15 +432,16 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp
 github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
 github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
 github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
-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/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
 github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
-github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
+github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
 github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0=
 github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
 github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4=
@@ -534,16 +527,16 @@ go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+f
 go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
-go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
-go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
-go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
-go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
-go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
-go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
-go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
-go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
-go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
+go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
+go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
 go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -552,6 +545,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
 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=
@@ -559,8 +554,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
-golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
+golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
+golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
@@ -578,8 +573,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
-golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
 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=
@@ -596,8 +591,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
-golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
 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-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -607,8 +602,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -627,7 +622,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -636,8 +630,10 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -656,8 +652,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
-golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
 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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
@@ -678,32 +674,36 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
-golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
-golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
-golang.org/x/vuln v0.2.0 h1:Dlz47lW0pvPHU7tnb10S8vbMn9GnV2B6eyT7Tem5XBI=
-golang.org/x/vuln v0.2.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
+golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
+golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
+golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
 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/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
-google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
-google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f h1:OiFuztEyBivVKDvguQJYWq1yDcfAHIID/FVrPR4oiI0=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f/go.mod h1:kprOiu9Tr0JYyD6DORrc4Hfyk3RFXqkQ3ctHEum3ZbM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
+google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
+google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
-google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-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.2/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=
@@ -714,8 +714,8 @@ gorm.io/driver/clickhouse v0.6.1 h1:t7JMB6sLBXxN8hEO6RdzCbJCwq/jAEVZdwXlmQs1Sd4=
 gorm.io/driver/clickhouse v0.6.1/go.mod h1:riMYpJcGZ3sJ/OAZZ1rEP1j/Y0H6cByOAnwz7fo2AyM=
 gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
 gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
-gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
-gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
+gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
+gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
 honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
 honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
 mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/history-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
new file mode 100644
index 00000000..f4e7dbf3
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
@@ -0,0 +1,14 @@
+freebsd_task:
+  name: 'FreeBSD'
+  freebsd_instance:
+    image_family: freebsd-14-1
+  install_script:
+    - pkg update -f
+    - pkg install -y go
+  test_script:
+      # run tests as user "cirrus" instead of root
+    - pw useradd cirrus -m
+    - chown -R cirrus:cirrus .
+    - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    -                      sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    - FSNOTIFY_DEBUG=1     sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/.editorconfig b/history-api/vendor/github.com/fsnotify/fsnotify/.editorconfig
deleted file mode 100644
index fad89585..00000000
--- a/history-api/vendor/github.com/fsnotify/fsnotify/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-root = true
-
-[*.go]
-indent_style = tab
-indent_size = 4
-insert_final_newline = true
-
-[*.{yml,yaml}]
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/.gitattributes b/history-api/vendor/github.com/fsnotify/fsnotify/.gitattributes
deleted file mode 100644
index 32f1001b..00000000
--- a/history-api/vendor/github.com/fsnotify/fsnotify/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-go.sum linguist-generated
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/.gitignore b/history-api/vendor/github.com/fsnotify/fsnotify/.gitignore
index 1d89d85c..daea9dd6 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/.gitignore
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/.gitignore
@@ -4,3 +4,7 @@
 
 # Output of go build ./cmd/fsnotify
 /fsnotify
+/fsnotify.exe
+
+/test/kqueue
+/test/a.out
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/history-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
index 77f9593b..fa854785 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
@@ -1,16 +1,115 @@
 # Changelog
 
-All notable changes to this project will be documented in this file.
+1.8.0 2023-10-31
+----------------
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+### Additions
+
+- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
+
+### Changes and fixes
+
+- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610])
+
+- kqueue: ignore events with Ident=0 ([#590])
+
+- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617])
+
+- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625])
+
+- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620])
+
+- inotify: fix panic when calling Remove() in a goroutine ([#650])
+
+- fen: allow watching subdirectories of watched directories ([#621])
+
+[#590]: https://github.com/fsnotify/fsnotify/pull/590
+[#610]: https://github.com/fsnotify/fsnotify/pull/610
+[#617]: https://github.com/fsnotify/fsnotify/pull/617
+[#619]: https://github.com/fsnotify/fsnotify/pull/619
+[#620]: https://github.com/fsnotify/fsnotify/pull/620
+[#621]: https://github.com/fsnotify/fsnotify/pull/621
+[#625]: https://github.com/fsnotify/fsnotify/pull/625
+[#650]: https://github.com/fsnotify/fsnotify/pull/650
+
+1.7.0 - 2023-10-22
+------------------
+This version of fsnotify needs Go 1.17.
+
+### Additions
+
+- illumos: add FEN backend to support illumos and Solaris. ([#371])
+
+- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful
+  in cases where you can't control the kernel buffer and receive a large number
+  of events in bursts. ([#550], [#572])
+
+- all: add `AddWith()`, which is identical to `Add()` but allows passing
+  options. ([#521])
+
+- windows: allow setting the ReadDirectoryChangesW() buffer size with
+  `fsnotify.WithBufferSize()`; the default of 64K is the highest value that
+  works on all platforms and is enough for most purposes, but in some cases a
+  highest buffer is needed. ([#521])
+
+### Changes and fixes
+
+- inotify: remove watcher if a watched path is renamed ([#518])
+
+  After a rename the reported name wasn't updated, or even an empty string.
+  Inotify doesn't provide any good facilities to update it, so just remove the
+  watcher. This is already how it worked on kqueue and FEN.
+
+  On Windows this does work, and remains working.
+
+- windows: don't listen for file attribute changes ([#520])
+
+  File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API,
+  with no way to see if they're a file write or attribute change, so would show
+  up as a fsnotify.Write event. This is never useful, and could result in many
+  spurious Write events.
+
+- windows: return `ErrEventOverflow` if the buffer is full ([#525])
+
+  Before it would merely return "short read", making it hard to detect this
+  error.
+
+- kqueue: make sure events for all files are delivered properly when removing a
+  watched directory ([#526])
+
+  Previously they would get sent with `""` (empty string) or `"."` as the path
+  name.
+
+- kqueue: don't emit spurious Create events for symbolic links ([#524])
+
+  The link would get resolved but kqueue would "forget" it already saw the link
+  itself, resulting on a Create for every Write event for the directory.
+
+- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516])
 
-## [Unreleased]
+- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in
+  `backend_other.go`, making it easier to use on unsupported platforms such as
+  WASM, AIX, etc. ([#528])
 
-Nothing yet.
+- other: use the `backend_other.go` no-op if the `appengine` build tag is set;
+  Google AppEngine forbids usage of the unsafe package so the inotify backend
+  won't compile there.
 
-## [1.6.0] - 2022-10-13
+[#371]: https://github.com/fsnotify/fsnotify/pull/371
+[#516]: https://github.com/fsnotify/fsnotify/pull/516
+[#518]: https://github.com/fsnotify/fsnotify/pull/518
+[#520]: https://github.com/fsnotify/fsnotify/pull/520
+[#521]: https://github.com/fsnotify/fsnotify/pull/521
+[#524]: https://github.com/fsnotify/fsnotify/pull/524
+[#525]: https://github.com/fsnotify/fsnotify/pull/525
+[#526]: https://github.com/fsnotify/fsnotify/pull/526
+[#528]: https://github.com/fsnotify/fsnotify/pull/528
+[#537]: https://github.com/fsnotify/fsnotify/pull/537
+[#550]: https://github.com/fsnotify/fsnotify/pull/550
+[#572]: https://github.com/fsnotify/fsnotify/pull/572
 
+1.6.0 - 2022-10-13
+------------------
 This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1,
 but not documented). It also increases the minimum Linux version to 2.6.32.
 
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/history-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
index ea379759..e4ac2a2f 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
@@ -1,7 +1,7 @@
 Thank you for your interest in contributing to fsnotify! We try to review and
 merge PRs in a reasonable timeframe, but please be aware that:
 
-- To avoid "wasted" work, please discus changes on the issue tracker first. You
+- To avoid "wasted" work, please discuss changes on the issue tracker first. You
   can just send PRs, but they may end up being rejected for one reason or the
   other.
 
@@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like
 
 Use the `-short` flag to make the "stress test" run faster.
 
+Writing new tests
+-----------------
+Scripts in the testdata directory allow creating test cases in a "shell-like"
+syntax. The basic format is:
+
+    script
+
+    Output:
+    desired output
+
+For example:
+
+    # Create a new empty file with some data.
+    watch /
+    echo data >/file
+
+    Output:
+        create  /file
+        write   /file
+
+Just create a new file to add a new test; select which tests to run with
+`-run TestScript/[path]`.
+
+script
+------
+The script is a "shell-like" script:
+
+    cmd arg arg
+
+Comments are supported with `#`:
+
+    # Comment
+    cmd arg arg  # Comment
+
+All operations are done in a temp directory; a path like "/foo" is rewritten to
+"/tmp/TestFoo/foo".
+
+Arguments can be quoted with `"` or `'`; there are no escapes and they're
+functionally identical right now, but this may change in the future, so best to
+assume shell-like rules.
+
+    touch "/file with spaces"
+
+End-of-line escapes with `\` are not supported.
+
+### Supported commands
+
+    watch path [ops]    # Watch the path, reporting events for it. Nothing is
+                        # watched by default. Optionally a list of ops can be
+                        # given, as with AddWith(path, WithOps(...)).
+    unwatch path        # Stop watching the path.
+    watchlist n         # Assert watchlist length.
+
+    stop                # Stop running the script; for debugging.
+    debug [yes/no]      # Enable/disable FSNOTIFY_DEBUG (tests are run in
+                          parallel by default, so -parallel=1 is probably a good
+                          idea).
+
+    touch path
+    mkdir [-p] dir
+    ln -s target link   # Only ln -s supported.
+    mkfifo path
+    mknod dev path
+    mv src dst
+    rm [-r] path
+    chmod mode path     # Octal only
+    sleep time-in-ms
+
+    cat path            # Read path (does nothing with the data; just reads it).
+    echo str >>path     # Append "str" to "path".
+    echo str >path      # Truncate "path" and write "str".
+
+    require reason      # Skip the test if "reason" is true; "skip" and
+    skip reason         # "require" behave identical; it supports both for
+                        # readability. Possible reasons are:
+                        #
+                        #   always    Always skip this test.
+                        #   symlink   Symlinks are supported (requires admin
+                        #             permissions on Windows).
+                        #   mkfifo    Platform doesn't support FIFO named sockets.
+                        #   mknod     Platform doesn't support device nodes.
+
+
+output
+------
+After `Output:` the desired output is given; this is indented by convention, but
+that's not required.
+
+The format of that is:
+
+    # Comment
+    event  path  # Comment
+
+    system:
+        event  path
+    system2:
+        event  path
+
+Every event is one line, and any whitespace between the event and path are
+ignored. The path can optionally be surrounded in ". Anything after a "#" is
+ignored.
+
+Platform-specific tests can be added after GOOS; for example:
+
+    watch /
+    touch /file
+
+    Output:
+        # Tested if nothing else matches
+        create    /file
+
+        # Windows-specific test.
+        windows:
+            write  /file
+
+You can specify multiple platforms with a comma (e.g. "windows, linux:").
+"kqueue" is a shortcut for all kqueue systems (BSD, macOS).
+
 
 [goon]: https://github.com/arp242/goon
 [Vagrant]: https://www.vagrantup.com/
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/README.md b/history-api/vendor/github.com/fsnotify/fsnotify/README.md
index d4e6080f..e480733d 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/README.md
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/README.md
@@ -1,29 +1,31 @@
 fsnotify is a Go library to provide cross-platform filesystem notifications on
-Windows, Linux, macOS, and BSD systems.
+Windows, Linux, macOS, BSD, and illumos.
 
-Go 1.16 or newer is required; the full documentation is at
+Go 1.17 or newer is required; the full documentation is at
 https://pkg.go.dev/github.com/fsnotify/fsnotify
 
-**It's best to read the documentation at pkg.go.dev, as it's pinned to the last
-released version, whereas this README is for the last development version which
-may include additions/changes.**
-
 ---
 
 Platform support:
 
-| Adapter               | OS             | Status                                                       |
-| --------------------- | ---------------| -------------------------------------------------------------|
-| inotify               | Linux 2.6.32+  | Supported                                                    |
-| kqueue                | BSD, macOS     | Supported                                                    |
-| ReadDirectoryChangesW | Windows        | Supported                                                    |
-| FSEvents              | macOS          | [Planned](https://github.com/fsnotify/fsnotify/issues/11)    |
-| FEN                   | Solaris 11     | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) |
-| fanotify              | Linux 5.9+     | [Maybe](https://github.com/fsnotify/fsnotify/issues/114)     |
-| USN Journals          | Windows        | [Maybe](https://github.com/fsnotify/fsnotify/issues/53)      |
-| Polling               | *All*          | [Maybe](https://github.com/fsnotify/fsnotify/issues/9)       |
-
-Linux and macOS should include Android and iOS, but these are currently untested.
+| Backend               | OS         | Status                                                                    |
+| :-------------------- | :--------- | :------------------------------------------------------------------------ |
+| inotify               | Linux      | Supported                                                                 |
+| kqueue                | BSD, macOS | Supported                                                                 |
+| ReadDirectoryChangesW | Windows    | Supported                                                                 |
+| FEN                   | illumos    | Supported                                                                 |
+| fanotify              | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114)                |
+| AHAFS                 | AIX        | [aix branch]; experimental due to lack of maintainer and test environment |
+| FSEvents              | macOS      | [Needs support in x/sys/unix][fsevents]                                   |
+| USN Journals          | Windows    | [Needs support in x/sys/windows][usn]                                     |
+| Polling               | *All*      | [Not yet](https://github.com/fsnotify/fsnotify/issues/9)                  |
+
+Linux and illumos should include Android and Solaris, but these are currently
+untested.
+
+[fsevents]:   https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
+[usn]:        https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
+[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
 
 Usage
 -----
@@ -83,20 +85,23 @@ run with:
 
     % go run ./cmd/fsnotify
 
+Further detailed documentation can be found in godoc:
+https://pkg.go.dev/github.com/fsnotify/fsnotify
+
 FAQ
 ---
 ### Will a file still be watched when it's moved to another directory?
 No, not unless you are watching the location it was moved to.
 
-### Are subdirectories watched too?
+### Are subdirectories watched?
 No, you must add watches for any directory you want to watch (a recursive
 watcher is on the roadmap: [#18]).
 
 [#18]: https://github.com/fsnotify/fsnotify/issues/18
 
 ### Do I have to watch the Error and Event channels in a goroutine?
-As of now, yes (you can read both channels in the same goroutine using `select`,
-you don't need a separate goroutine for both channels; see the example).
+Yes. You can read both channels in the same goroutine using `select` (you don't
+need a separate goroutine for both channels; see the example).
 
 ### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys?
 fsnotify requires support from underlying OS to work. The current NFS and SMB
@@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented.
 
 [#9]: https://github.com/fsnotify/fsnotify/issues/9
 
+### Why do I get many Chmod events?
+Some programs may generate a lot of attribute changes; for example Spotlight on
+macOS, anti-virus programs, backup applications, and some others are known to do
+this. As a rule, it's typically best to ignore Chmod events. They're often not
+useful, and tend to cause problems.
+
+Spotlight indexing on macOS can result in multiple events (see [#15]). A
+temporary workaround is to add your folder(s) to the *Spotlight Privacy
+settings* until we have a native FSEvents implementation (see [#11]).
+
+[#11]: https://github.com/fsnotify/fsnotify/issues/11
+[#15]: https://github.com/fsnotify/fsnotify/issues/15
+
+### Watching a file doesn't work well
+Watching individual files (rather than directories) is generally not recommended
+as many programs (especially editors) update files atomically: it will write to
+a temporary file which is then moved to to destination, overwriting the original
+(or some variant thereof). The watcher on the original file is now lost, as that
+no longer exists.
+
+The upshot of this is that a power failure or crash won't leave a half-written
+file.
+
+Watch the parent directory and use `Event.Name` to filter out files you're not
+interested in. There is an example of this in `cmd/fsnotify/file.go`.
+
 Platform-specific notes
 -----------------------
 ### Linux
@@ -151,11 +182,3 @@ these platforms.
 
 The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to
 control the maximum number of open files.
-
-### macOS
-Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary
-workaround is to add your folder(s) to the *Spotlight Privacy settings* until we
-have a native FSEvents implementation (see [#11]).
-
-[#11]: https://github.com/fsnotify/fsnotify/issues/11
-[#15]: https://github.com/fsnotify/fsnotify/issues/15
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/history-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
index 1a95ad8e..c349c326 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
@@ -1,162 +1,484 @@
 //go:build solaris
-// +build solaris
+
+// FEN backend for illumos (supported) and Solaris (untested, but should work).
+//
+// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create
 
 package fsnotify
 
 import (
 	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"sync"
+	"time"
+
+	"github.com/fsnotify/fsnotify/internal"
+	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type fen struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
+
+	mu      sync.Mutex
+	port    *unix.EventPort
+	done    chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	dirs    map[string]Op // Explicitly watched directories
+	watches map[string]Op // Explicitly watched non-directories
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, errors.New("FEN based watcher not yet supported for fsnotify\n")
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	w := &fen{
+		Events:  ev,
+		Errors:  errs,
+		dirs:    make(map[string]Op),
+		watches: make(map[string]Op),
+		done:    make(chan struct{}),
+	}
+
+	var err error
+	w.port, err = unix.NewEventPort()
+	if err != nil {
+		return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err)
+	}
+
+	go w.readEvents()
+	return w, nil
+}
+
+// sendEvent attempts to send an event to the user, returning true if the event
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendEvent(name string, op Op) (sent bool) {
+	select {
+	case <-w.done:
+		return false
+	case w.Events <- Event{Name: name, Op: op}:
+		return true
+	}
+}
+
+// sendError attempts to send an error to the user, returning true if the error
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendError(err error) (sent bool) {
+	if err == nil {
+		return true
+	}
+	select {
+	case <-w.done:
+		return false
+	case w.Errors <- err:
+		return true
+	}
+}
+
+func (w *fen) isClosed() bool {
+	select {
+	case <-w.done:
+		return true
+	default:
+		return false
+	}
+}
+
+func (w *fen) Close() error {
+	// Take the lock used by associateFile to prevent lingering events from
+	// being processed after the close
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if w.isClosed() {
+		return nil
+	}
+	close(w.done)
+	return w.port.Close()
+}
+
+func (w *fen) Add(name string) error { return w.AddWith(name) }
+
+func (w *fen) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
+	// Currently we resolve symlinks that were explicitly requested to be
+	// watched. Otherwise we would use LStat here.
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Associate all files in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, true, w.associateFile)
+		if err != nil {
+			return err
+		}
+
+		w.mu.Lock()
+		w.dirs[name] = with.op
+		w.mu.Unlock()
+		return nil
+	}
+
+	err = w.associateFile(name, stat, true)
+	if err != nil {
+		return err
+	}
+
+	w.mu.Lock()
+	w.watches[name] = with.op
+	w.mu.Unlock()
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
+func (w *fen) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if !w.port.PathIsWatched(name) {
+		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	// The user has expressed an intent. Immediately remove this name from
+	// whichever watch list it might be in. If it's not in there the delete
+	// doesn't cause harm.
+	w.mu.Lock()
+	delete(w.watches, name)
+	delete(w.dirs, name)
+	w.mu.Unlock()
+
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Remove associations for every file in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, false, w.dissociateFile)
+		if err != nil {
+			return err
+		}
+		return nil
+	}
+
+	err = w.port.DissociatePath(name)
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+// readEvents contains the main loop that runs in a goroutine watching for events.
+func (w *fen) readEvents() {
+	// If this function returns, the watcher has been closed and we can close
+	// these channels
+	defer func() {
+		close(w.Errors)
+		close(w.Events)
+	}()
+
+	pevents := make([]unix.PortEvent, 8)
+	for {
+		count, err := w.port.Get(pevents, 1, nil)
+		if err != nil && err != unix.ETIME {
+			// Interrupted system call (count should be 0) ignore and continue
+			if errors.Is(err, unix.EINTR) && count == 0 {
+				continue
+			}
+			// Get failed because we called w.Close()
+			if errors.Is(err, unix.EBADF) && w.isClosed() {
+				return
+			}
+			// There was an error not caused by calling w.Close()
+			if !w.sendError(err) {
+				return
+			}
+		}
+
+		p := pevents[:count]
+		for _, pevent := range p {
+			if pevent.Source != unix.PORT_SOURCE_FILE {
+				// Event from unexpected source received; should never happen.
+				if !w.sendError(errors.New("Event from unexpected source received")) {
+					return
+				}
+				continue
+			}
+
+			if debug {
+				internal.Debug(pevent.Path, pevent.Events)
+			}
+
+			err = w.handleEvent(&pevent)
+			if !w.sendError(err) {
+				return
+			}
+		}
+	}
+}
+
+func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	// Handle all children of the directory.
+	for _, entry := range files {
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = handler(filepath.Join(path, finfo.Name()), finfo, false)
+		if err != nil {
+			return err
+		}
+	}
+
+	// And finally handle the directory itself.
+	return handler(path, stat, follow)
+}
+
+// handleEvent might need to emit more than one fsnotify event if the events
+// bitmap matches more than one event type (e.g. the file was both modified and
+// had the attributes changed between when the association was created and the
+// when event was returned)
+func (w *fen) handleEvent(event *unix.PortEvent) error {
+	var (
+		events     = event.Events
+		path       = event.Path
+		fmode      = event.Cookie.(os.FileMode)
+		reRegister = true
+	)
+
+	w.mu.Lock()
+	_, watchedDir := w.dirs[path]
+	_, watchedPath := w.watches[path]
+	w.mu.Unlock()
+	isWatched := watchedDir || watchedPath
+
+	if events&unix.FILE_DELETE != 0 {
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_FROM != 0 {
+		if !w.sendEvent(path, Rename) {
+			return nil
+		}
+		// Don't keep watching the new file name
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_TO != 0 {
+		// We don't report a Rename event for this case, because Rename events
+		// are interpreted as referring to the _old_ name of the file, and in
+		// this case the event would refer to the new name of the file. This
+		// type of rename event is not supported by fsnotify.
+
+		// inotify reports a Remove event in this case, so we simulate this
+		// here.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Don't keep watching the file that was removed
+		reRegister = false
+	}
+
+	// The file is gone, nothing left to do.
+	if !reRegister {
+		if watchedDir {
+			w.mu.Lock()
+			delete(w.dirs, path)
+			w.mu.Unlock()
+		}
+		if watchedPath {
+			w.mu.Lock()
+			delete(w.watches, path)
+			w.mu.Unlock()
+		}
+		return nil
+	}
+
+	// If we didn't get a deletion the file still exists and we're going to have
+	// to watch it again. Let's Stat it now so that we can compare permissions
+	// and have what we need to continue watching the file
+
+	stat, err := os.Lstat(path)
+	if err != nil {
+		// This is unexpected, but we should still emit an event. This happens
+		// most often on "rm -r" of a subdirectory inside a watched directory We
+		// get a modify event of something happening inside, but by the time we
+		// get here, the sudirectory is already gone. Clearly we were watching
+		// this path but now it is gone. Let's tell the user that it was
+		// removed.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Suppress extra write events on removed directories; they are not
+		// informative and can be confusing.
+		return nil
+	}
+
+	// resolve symlinks that were explicitly watched as we would have at Add()
+	// time. this helps suppress spurious Chmod events on watched symlinks
+	if isWatched {
+		stat, err = os.Stat(path)
+		if err != nil {
+			// The symlink still exists, but the target is gone. Report the
+			// Remove similar to above.
+			if !w.sendEvent(path, Remove) {
+				return nil
+			}
+			// Don't return the error
+		}
+	}
+
+	if events&unix.FILE_MODIFIED != 0 {
+		if fmode.IsDir() && watchedDir {
+			if err := w.updateDirectory(path); err != nil {
+				return err
+			}
+		} else {
+			if !w.sendEvent(path, Write) {
+				return nil
+			}
+		}
+	}
+	if events&unix.FILE_ATTRIB != 0 && stat != nil {
+		// Only send Chmod if perms changed
+		if stat.Mode().Perm() != fmode.Perm() {
+			if !w.sendEvent(path, Chmod) {
+				return nil
+			}
+		}
+	}
+
+	if stat != nil {
+		// If we get here, it means we've hit an event above that requires us to
+		// continue watching the file or directory
+		return w.associateFile(path, stat, isWatched)
+	}
+	return nil
+}
+
+func (w *fen) updateDirectory(path string) error {
+	// The directory was modified, so we must find unwatched entities and watch
+	// them. If something was removed from the directory, nothing will happen,
+	// as everything else should still be watched.
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	for _, entry := range files {
+		path := filepath.Join(path, entry.Name())
+		if w.port.PathIsWatched(path) {
+			continue
+		}
+
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = w.associateFile(path, finfo, false)
+		if !w.sendError(err) {
+			return nil
+		}
+		if !w.sendEvent(path, Create) {
+			return nil
+		}
+	}
 	return nil
 }
+
+func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	// This is primarily protecting the call to AssociatePath but it is
+	// important and intentional that the call to PathIsWatched is also
+	// protected by this mutex. Without this mutex, AssociatePath has been seen
+	// to error out that the path is already associated.
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.port.PathIsWatched(path) {
+		// Remove the old association in favor of this one If we get ENOENT,
+		// then while the x/sys/unix wrapper still thought that this path was
+		// associated, the underlying event port did not. This call will have
+		// cleared up that discrepancy. The most likely cause is that the event
+		// has fired but we haven't processed it yet.
+		err := w.port.DissociatePath(path)
+		if err != nil && !errors.Is(err, unix.ENOENT) {
+			return err
+		}
+	}
+
+	var events int
+	if !follow {
+		// Watch symlinks themselves rather than their targets unless this entry
+		// is explicitly watched.
+		events |= unix.FILE_NOFOLLOW
+	}
+	if true { // TODO: implement withOps()
+		events |= unix.FILE_MODIFIED
+	}
+	if true {
+		events |= unix.FILE_ATTRIB
+	}
+	return w.port.AssociatePath(path, stat, events, stat.Mode())
+}
+
+func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
+	if !w.port.PathIsWatched(path) {
+		return nil
+	}
+	return w.port.DissociatePath(path)
+}
+
+func (w *fen) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	entries := make([]string, 0, len(w.watches)+len(w.dirs))
+	for pathname := range w.dirs {
+		entries = append(entries, pathname)
+	}
+	for pathname := range w.watches {
+		entries = append(entries, pathname)
+	}
+
+	return entries
+}
+
+func (w *fen) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/history-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
index 54c77fbb..36c31169 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
@@ -1,5 +1,4 @@
-//go:build linux
-// +build linux
+//go:build linux && !appengine
 
 package fsnotify
 
@@ -7,142 +6,188 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/fs"
 	"os"
 	"path/filepath"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type inotify struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	// Store fd here as os.File.Read() will no longer return on close after
 	// calling Fd(). See: https://github.com/golang/go/issues/26439
 	fd          int
-	mu          sync.Mutex // Map access
 	inotifyFile *os.File
-	watches     map[string]*watch // Map of inotify watches (key: path)
-	paths       map[int]string    // Map of watched paths (key: watch descriptor)
-	done        chan struct{}     // Channel for sending a "quit message" to the reader goroutine
-	doneResp    chan struct{}     // Channel to respond to Close
+	watches     *watches
+	done        chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	doneMu      sync.Mutex
+	doneResp    chan struct{} // Channel to respond to Close
+
+	// Store rename cookies in an array, with the index wrapping to 0. Almost
+	// all of the time what we get is a MOVED_FROM to set the cookie and the
+	// next event inotify sends will be MOVED_TO to read it. However, this is
+	// not guaranteed – as described in inotify(7) – and we may get other events
+	// between the two MOVED_* events (including other MOVED_* ones).
+	//
+	// A second issue is that moving a file outside the watched directory will
+	// trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to
+	// read and delete it. So just storing it in a map would slowly leak memory.
+	//
+	// Doing it like this gives us a simple fast LRU-cache that won't allocate.
+	// Ten items should be more than enough for our purpose, and a loop over
+	// such a short array is faster than a map access anyway (not that it hugely
+	// matters since we're talking about hundreds of ns at the most, but still).
+	cookies     [10]koekje
+	cookieIndex uint8
+	cookiesMu   sync.Mutex
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	// Create inotify fd
-	// Need to set the FD to nonblocking mode in order for SetDeadline methods to work
-	// Otherwise, blocking i/o operations won't terminate on close
+type (
+	watches struct {
+		mu   sync.RWMutex
+		wd   map[uint32]*watch // wd → watch
+		path map[string]uint32 // pathname → wd
+	}
+	watch struct {
+		wd      uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+		flags   uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+		path    string // Watch path.
+		recurse bool   // Recursion with ./...?
+	}
+	koekje struct {
+		cookie uint32
+		path   string
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:   make(map[uint32]*watch),
+		path: make(map[string]uint32),
+	}
+}
+
+func (w *watches) len() int {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return len(w.wd)
+}
+
+func (w *watches) add(ww *watch) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.wd[ww.wd] = ww
+	w.path[ww.path] = ww.wd
+}
+
+func (w *watches) remove(wd uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	watch := w.wd[wd] // Could have had Remove() called. See #616.
+	if watch == nil {
+		return
+	}
+	delete(w.path, watch.path)
+	delete(w.wd, wd)
+}
+
+func (w *watches) removePath(path string) ([]uint32, error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	path, recurse := recursivePath(path)
+	wd, ok := w.path[path]
+	if !ok {
+		return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path)
+	}
+
+	watch := w.wd[wd]
+	if recurse && !watch.recurse {
+		return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path)
+	}
+
+	delete(w.path, path)
+	delete(w.wd, wd)
+	if !watch.recurse {
+		return []uint32{wd}, nil
+	}
+
+	wds := make([]uint32, 0, 8)
+	wds = append(wds, wd)
+	for p, rwd := range w.path {
+		if filepath.HasPrefix(p, path) {
+			delete(w.path, p)
+			delete(w.wd, rwd)
+			wds = append(wds, rwd)
+		}
+	}
+	return wds, nil
+}
+
+func (w *watches) byPath(path string) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[w.path[path]]
+}
+
+func (w *watches) byWd(wd uint32) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[wd]
+}
+
+func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	var existing *watch
+	wd, ok := w.path[path]
+	if ok {
+		existing = w.wd[wd]
+	}
+
+	upd, err := f(existing)
+	if err != nil {
+		return err
+	}
+	if upd != nil {
+		w.wd[upd.wd] = upd
+		w.path[upd.path] = upd.wd
+
+		if upd.wd != wd {
+			delete(w.wd, wd)
+		}
+	}
+
+	return nil
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
+	// I/O operations won't terminate on close.
 	fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
 	if fd == -1 {
 		return nil, errno
 	}
 
-	w := &Watcher{
+	w := &inotify{
+		Events:      ev,
+		Errors:      errs,
 		fd:          fd,
 		inotifyFile: os.NewFile(uintptr(fd), ""),
-		watches:     make(map[string]*watch),
-		paths:       make(map[int]string),
-		Events:      make(chan Event),
-		Errors:      make(chan error),
+		watches:     newWatches(),
 		done:        make(chan struct{}),
 		doneResp:    make(chan struct{}),
 	}
@@ -152,26 +197,29 @@ func NewWatcher() (*Watcher, error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *inotify) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
-	select {
-	case w.Errors <- err:
+func (w *inotify) sendError(err error) bool {
+	if err == nil {
 		return true
+	}
+	select {
 	case <-w.done:
 		return false
+	case w.Errors <- err:
+		return true
 	}
 }
 
-func (w *Watcher) isClosed() bool {
+func (w *inotify) isClosed() bool {
 	select {
 	case <-w.done:
 		return true
@@ -180,17 +228,14 @@ func (w *Watcher) isClosed() bool {
 	}
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
+func (w *inotify) Close() error {
+	w.doneMu.Lock()
 	if w.isClosed() {
-		w.mu.Unlock()
+		w.doneMu.Unlock()
 		return nil
 	}
-
-	// Send 'close' signal to goroutine, and set the Watcher to closed.
 	close(w.done)
-	w.mu.Unlock()
+	w.doneMu.Unlock()
 
 	// Causes any blocking reads to return with an error, provided the file
 	// still supports deadline operations.
@@ -205,138 +250,168 @@ func (w *Watcher) Close() error {
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) Add(name string) error { return w.AddWith(name) }
+
+func (w *inotify) AddWith(path string, opts ...addOpt) error {
 	if w.isClosed() {
-		return errors.New("inotify instance already closed")
+		return ErrClosed
 	}
-
-	var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
-		unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
-		unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
-
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watchEntry := w.watches[name]
-	if watchEntry != nil {
-		flags |= watchEntry.flags | unix.IN_MASK_ADD
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), path)
 	}
-	wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
-	if wd == -1 {
-		return errno
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
 	}
 
-	if watchEntry == nil {
-		w.watches[name] = &watch{wd: uint32(wd), flags: flags}
-		w.paths[wd] = name
-	} else {
-		watchEntry.wd = uint32(wd)
-		watchEntry.flags = flags
+	path, recurse := recursivePath(path)
+	if recurse {
+		return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
+			if err != nil {
+				return err
+			}
+			if !d.IsDir() {
+				if root == path {
+					return fmt.Errorf("fsnotify: not a directory: %q", path)
+				}
+				return nil
+			}
+
+			// Send a Create event when adding new directory from a recursive
+			// watch; this is for "mkdir -p one/two/three". Usually all those
+			// directories will be created before we can set up watchers on the
+			// subdirectories, so only "one" would be sent as a Create event and
+			// not "one/two" and "one/two/three" (inotifywait -r has the same
+			// problem).
+			if with.sendCreate && root != path {
+				w.sendEvent(Event{Name: root, Op: Create})
+			}
+
+			return w.add(root, with, true)
+		})
 	}
 
-	return nil
+	return w.add(path, with, false)
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) add(path string, with withOpts, recurse bool) error {
+	var flags uint32
+	if with.noFollow {
+		flags |= unix.IN_DONT_FOLLOW
+	}
+	if with.op.Has(Create) {
+		flags |= unix.IN_CREATE
+	}
+	if with.op.Has(Write) {
+		flags |= unix.IN_MODIFY
+	}
+	if with.op.Has(Remove) {
+		flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
+	}
+	if with.op.Has(Rename) {
+		flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
+	}
+	if with.op.Has(Chmod) {
+		flags |= unix.IN_ATTRIB
+	}
+	if with.op.Has(xUnportableOpen) {
+		flags |= unix.IN_OPEN
+	}
+	if with.op.Has(xUnportableRead) {
+		flags |= unix.IN_ACCESS
+	}
+	if with.op.Has(xUnportableCloseWrite) {
+		flags |= unix.IN_CLOSE_WRITE
+	}
+	if with.op.Has(xUnportableCloseRead) {
+		flags |= unix.IN_CLOSE_NOWRITE
+	}
+	return w.register(path, flags, recurse)
+}
 
-	// Fetch the watch.
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watch, ok := w.watches[name]
+func (w *inotify) register(path string, flags uint32, recurse bool) error {
+	return w.watches.updatePath(path, func(existing *watch) (*watch, error) {
+		if existing != nil {
+			flags |= existing.flags | unix.IN_MASK_ADD
+		}
 
-	// Remove it from inotify.
-	if !ok {
-		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
-	}
-
-	// We successfully removed the watch if InotifyRmWatch doesn't return an
-	// error, we need to clean up our internal state to ensure it matches
-	// inotify's kernel state.
-	delete(w.paths, int(watch.wd))
-	delete(w.watches, name)
-
-	// inotify_rm_watch will return EINVAL if the file has been deleted;
-	// the inotify will already have been removed.
-	// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
-	// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
-	// so that EINVAL means that the wd is being rm_watch()ed or its file removed
-	// by another thread and we have not received IN_IGNORE event.
-	success, errno := unix.InotifyRmWatch(w.fd, watch.wd)
-	if success == -1 {
-		// TODO: Perhaps it's not helpful to return an error here in every case;
-		//       The only two possible errors are:
-		//
-		//       - EBADF, which happens when w.fd is not a valid file descriptor
-		//         of any kind.
-		//       - EINVAL, which is when fd is not an inotify descriptor or wd
-		//         is not a valid watch descriptor. Watch descriptors are
-		//         invalidated when they are removed explicitly or implicitly;
-		//         explicitly by inotify_rm_watch, implicitly when the file they
-		//         are watching is deleted.
-		return errno
+		wd, err := unix.InotifyAddWatch(w.fd, path, flags)
+		if wd == -1 {
+			return nil, err
+		}
+
+		if existing == nil {
+			return &watch{
+				wd:      uint32(wd),
+				path:    path,
+				flags:   flags,
+				recurse: recurse,
+			}, nil
+		}
+
+		existing.wd = uint32(wd)
+		existing.flags = flags
+		return existing, nil
+	})
+}
+
+func (w *inotify) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(filepath.Clean(name))
+}
+
+func (w *inotify) remove(name string) error {
+	wds, err := w.watches.removePath(name)
+	if err != nil {
+		return err
 	}
 
+	for _, wd := range wds {
+		_, err := unix.InotifyRmWatch(w.fd, wd)
+		if err != nil {
+			// TODO: Perhaps it's not helpful to return an error here in every
+			// case; the only two possible errors are:
+			//
+			// EBADF, which happens when w.fd is not a valid file descriptor of
+			// any kind.
+			//
+			// EINVAL, which is when fd is not an inotify descriptor or wd is
+			// not a valid watch descriptor. Watch descriptors are invalidated
+			// when they are removed explicitly or implicitly; explicitly by
+			// inotify_rm_watch, implicitly when the file they are watching is
+			// deleted.
+			return err
+		}
+	}
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
+func (w *inotify) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
 
-	entries := make([]string, 0, len(w.watches))
-	for pathname := range w.watches {
+	entries := make([]string, 0, w.watches.len())
+	w.watches.mu.RLock()
+	for pathname := range w.watches.path {
 		entries = append(entries, pathname)
 	}
+	w.watches.mu.RUnlock()
 
 	return entries
 }
 
-type watch struct {
-	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
-	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
-}
-
 // readEvents reads from the inotify file descriptor, converts the
 // received events into Event objects and sends them via the Events channel
-func (w *Watcher) readEvents() {
+func (w *inotify) readEvents() {
 	defer func() {
 		close(w.doneResp)
 		close(w.Errors)
@@ -367,14 +442,11 @@ func (w *Watcher) readEvents() {
 		if n < unix.SizeofInotifyEvent {
 			var err error
 			if n == 0 {
-				// If EOF is received. This should really never happen.
-				err = io.EOF
+				err = io.EOF // If EOF is received. This should really never happen.
 			} else if n < 0 {
-				// If an error occurred while reading.
-				err = errno
+				err = errno // If an error occurred while reading.
 			} else {
-				// Read was too short.
-				err = errors.New("notify: short read in readEvents()")
+				err = errors.New("notify: short read in readEvents()") // Read was too short.
 			}
 			if !w.sendError(err) {
 				return
@@ -382,15 +454,17 @@ func (w *Watcher) readEvents() {
 			continue
 		}
 
-		var offset uint32
 		// We don't know how many events we just read into the buffer
 		// While the offset points to at least one whole event...
+		var offset uint32
 		for offset <= uint32(n-unix.SizeofInotifyEvent) {
 			var (
 				// Point "raw" to the event in the buffer
 				raw     = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
 				mask    = uint32(raw.Mask)
 				nameLen = uint32(raw.Len)
+				// Move to the next event in the buffer
+				next = func() { offset += unix.SizeofInotifyEvent + nameLen }
 			)
 
 			if mask&unix.IN_Q_OVERFLOW != 0 {
@@ -399,46 +473,124 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			// If the event happened to the watched directory or the watched file, the kernel
-			// doesn't append the filename to the event, but we would like to always fill the
-			// the "Name" field with a valid filename. We retrieve the path of the watch from
-			// the "paths" map.
-			w.mu.Lock()
-			name, ok := w.paths[int(raw.Wd)]
-			// IN_DELETE_SELF occurs when the file/directory being watched is removed.
-			// This is a sign to clean up the maps, otherwise we are no longer in sync
-			// with the inotify kernel state which has already deleted the watch
-			// automatically.
-			if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
-				delete(w.paths, int(raw.Wd))
-				delete(w.watches, name)
+			/// If the event happened to the watched directory or the watched
+			/// file, the kernel doesn't append the filename to the event, but
+			/// we would like to always fill the the "Name" field with a valid
+			/// filename. We retrieve the path of the watch from the "paths"
+			/// map.
+			watch := w.watches.byWd(uint32(raw.Wd))
+			/// Can be nil if Remove() was called in another goroutine for this
+			/// path inbetween reading the events from the kernel and reading
+			/// the internal state. Not much we can do about it, so just skip.
+			/// See #616.
+			if watch == nil {
+				next()
+				continue
 			}
-			w.mu.Unlock()
 
+			name := watch.path
 			if nameLen > 0 {
-				// Point "bytes" at the first byte of the filename
+				/// Point "bytes" at the first byte of the filename
 				bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
-				// The filename is padded with NULL bytes. TrimRight() gets rid of those.
+				/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
 				name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
 			}
 
-			event := w.newEvent(name, mask)
+			if debug {
+				internal.Debug(name, raw.Mask, raw.Cookie)
+			}
 
-			// Send the events that are not ignored on the events channel
-			if mask&unix.IN_IGNORED == 0 {
-				if !w.sendEvent(event) {
-					return
+			if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
+				next()
+				continue
+			}
+
+			// inotify will automatically remove the watch on deletes; just need
+			// to clean our state here.
+			if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
+				w.watches.remove(watch.wd)
+			}
+
+			// We can't really update the state when a watched path is moved;
+			// only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
+			// the watch.
+			if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
+				if watch.recurse {
+					next() // Do nothing
+					continue
+				}
+
+				err := w.remove(watch.path)
+				if err != nil && !errors.Is(err, ErrNonExistentWatch) {
+					if !w.sendError(err) {
+						return
+					}
+				}
+			}
+
+			/// Skip if we're watching both this path and the parent; the parent
+			/// will already send a delete so no need to do it twice.
+			if mask&unix.IN_DELETE_SELF != 0 {
+				if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok {
+					next()
+					continue
+				}
+			}
+
+			ev := w.newEvent(name, mask, raw.Cookie)
+			// Need to update watch path for recurse.
+			if watch.recurse {
+				isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR
+				/// New directory created: set up watch on it.
+				if isDir && ev.Has(Create) {
+					err := w.register(ev.Name, watch.flags, true)
+					if !w.sendError(err) {
+						return
+					}
+
+					// This was a directory rename, so we need to update all
+					// the children.
+					//
+					// TODO: this is of course pretty slow; we should use a
+					// better data structure for storing all of this, e.g. store
+					// children in the watch. I have some code for this in my
+					// kqueue refactor we can use in the future. For now I'm
+					// okay with this as it's not publicly available.
+					// Correctness first, performance second.
+					if ev.renamedFrom != "" {
+						w.watches.mu.Lock()
+						for k, ww := range w.watches.wd {
+							if k == watch.wd || ww.path == ev.Name {
+								continue
+							}
+							if strings.HasPrefix(ww.path, ev.renamedFrom) {
+								ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
+								w.watches.wd[k] = ww
+							}
+						}
+						w.watches.mu.Unlock()
+					}
 				}
 			}
 
-			// Move to the next event in the buffer
-			offset += unix.SizeofInotifyEvent + nameLen
+			/// Send the events that are not ignored on the events channel
+			if !w.sendEvent(ev) {
+				return
+			}
+			next()
 		}
 	}
 }
 
-// newEvent returns an platform-independent Event based on an inotify mask.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *inotify) isRecursive(path string) bool {
+	ww := w.watches.byPath(path)
+	if ww == nil { // path could be a file, so also check the Dir.
+		ww = w.watches.byPath(filepath.Dir(path))
+	}
+	return ww != nil && ww.recurse
+}
+
+func (w *inotify) newEvent(name string, mask, cookie uint32) Event {
 	e := Event{Name: name}
 	if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
 		e.Op |= Create
@@ -449,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.IN_MODIFY == unix.IN_MODIFY {
 		e.Op |= Write
 	}
+	if mask&unix.IN_OPEN == unix.IN_OPEN {
+		e.Op |= xUnportableOpen
+	}
+	if mask&unix.IN_ACCESS == unix.IN_ACCESS {
+		e.Op |= xUnportableRead
+	}
+	if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE {
+		e.Op |= xUnportableCloseWrite
+	}
+	if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE {
+		e.Op |= xUnportableCloseRead
+	}
 	if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
 		e.Op |= Rename
 	}
 	if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
 		e.Op |= Chmod
 	}
+
+	if cookie != 0 {
+		if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
+			w.cookiesMu.Lock()
+			w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name}
+			w.cookieIndex++
+			if w.cookieIndex > 9 {
+				w.cookieIndex = 0
+			}
+			w.cookiesMu.Unlock()
+		} else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
+			w.cookiesMu.Lock()
+			var prev string
+			for _, c := range w.cookies {
+				if c.cookie == cookie {
+					prev = c.path
+					break
+				}
+			}
+			w.cookiesMu.Unlock()
+			e.renamedFrom = prev
+		}
+	}
 	return e
 }
+
+func (w *inotify) xSupports(op Op) bool {
+	return true // Supports everything.
+}
+
+func (w *inotify) state() {
+	w.watches.mu.Lock()
+	defer w.watches.mu.Unlock()
+	for wd, ww := range w.watches.wd {
+		fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
+	}
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/history-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
index 29087469..d8de5ab7 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
@@ -1,155 +1,201 @@
 //go:build freebsd || openbsd || netbsd || dragonfly || darwin
-// +build freebsd openbsd netbsd dragonfly darwin
 
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
+	"runtime"
 	"sync"
+	"time"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type kqueue struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
-	done         chan struct{}
-	kq           int                         // File descriptor (as returned by the kqueue() syscall).
-	closepipe    [2]int                      // Pipe used for closing.
-	mu           sync.Mutex                  // Protects access to watcher data
-	watches      map[string]int              // Watched file descriptors (key: path).
-	watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)).
-	userWatches  map[string]struct{}         // Watches added with Watcher.Add()
-	dirFlags     map[string]uint32           // Watched directories to fflags used in kqueue.
-	paths        map[int]pathInfo            // File descriptors to path names for processing kqueue events.
-	fileExists   map[string]struct{}         // Keep track of if we know this file exists (to stop duplicate create events).
-	isClosed     bool                        // Set to true when Close() is first called
+	kq        int    // File descriptor (as returned by the kqueue() syscall).
+	closepipe [2]int // Pipe used for closing kq.
+	watches   *watches
+	done      chan struct{}
+	doneMu    sync.Mutex
 }
 
-type pathInfo struct {
-	name  string
-	isDir bool
+type (
+	watches struct {
+		mu     sync.RWMutex
+		wd     map[int]watch               // wd → watch
+		path   map[string]int              // pathname → wd
+		byDir  map[string]map[int]struct{} // dirname(path) → wd
+		seen   map[string]struct{}         // Keep track of if we know this file exists.
+		byUser map[string]struct{}         // Watches added with Watcher.Add()
+	}
+	watch struct {
+		wd       int
+		name     string
+		linkName string // In case of links; name is the target, and this is the link.
+		isDir    bool
+		dirFlags uint32
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:     make(map[int]watch),
+		path:   make(map[string]int),
+		byDir:  make(map[string]map[int]struct{}),
+		seen:   make(map[string]struct{}),
+		byUser: make(map[string]struct{}),
+	}
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func (w *watches) listPaths(userOnly bool) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	if userOnly {
+		l := make([]string, 0, len(w.byUser))
+		for p := range w.byUser {
+			l = append(l, p)
+		}
+		return l
+	}
+
+	l := make([]string, 0, len(w.path))
+	for p := range w.path {
+		l = append(l, p)
+	}
+	return l
+}
+
+func (w *watches) watchesInDir(path string) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	l := make([]string, 0, 4)
+	for fd := range w.byDir[path] {
+		info := w.wd[fd]
+		if _, ok := w.byUser[info.name]; !ok {
+			l = append(l, info.name)
+		}
+	}
+	return l
+}
+
+// Mark path as added by the user.
+func (w *watches) addUserWatch(path string) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.byUser[path] = struct{}{}
+}
+
+func (w *watches) addLink(path string, fd int) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.seen[path] = struct{}{}
+}
+
+func (w *watches) add(path, linkPath string, fd int, isDir bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir}
+
+	parent := filepath.Dir(path)
+	byDir, ok := w.byDir[parent]
+	if !ok {
+		byDir = make(map[int]struct{}, 1)
+		w.byDir[parent] = byDir
+	}
+	byDir[fd] = struct{}{}
+}
+
+func (w *watches) byWd(fd int) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[fd]
+	return info, ok
+}
+
+func (w *watches) byPath(path string) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[w.path[path]]
+	return info, ok
+}
+
+func (w *watches) updateDirFlags(path string, flags uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	fd := w.path[path]
+	info := w.wd[fd]
+	info.dirFlags = flags
+	w.wd[fd] = info
+}
+
+func (w *watches) remove(fd int, path string) bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	isDir := w.wd[fd].isDir
+	delete(w.path, path)
+	delete(w.byUser, path)
+
+	parent := filepath.Dir(path)
+	delete(w.byDir[parent], fd)
+
+	if len(w.byDir[parent]) == 0 {
+		delete(w.byDir, parent)
+	}
+
+	delete(w.wd, fd)
+	delete(w.seen, path)
+	return isDir
+}
+
+func (w *watches) markSeen(path string, exists bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if exists {
+		w.seen[path] = struct{}{}
+	} else {
+		delete(w.seen, path)
+	}
+}
+
+func (w *watches) seenBefore(path string) bool {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	_, ok := w.seen[path]
+	return ok
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	kq, closepipe, err := newKqueue()
 	if err != nil {
 		return nil, err
 	}
 
-	w := &Watcher{
-		kq:           kq,
-		closepipe:    closepipe,
-		watches:      make(map[string]int),
-		watchesByDir: make(map[string]map[int]struct{}),
-		dirFlags:     make(map[string]uint32),
-		paths:        make(map[int]pathInfo),
-		fileExists:   make(map[string]struct{}),
-		userWatches:  make(map[string]struct{}),
-		Events:       make(chan Event),
-		Errors:       make(chan error),
-		done:         make(chan struct{}),
+	w := &kqueue{
+		Events:    ev,
+		Errors:    errs,
+		kq:        kq,
+		closepipe: closepipe,
+		done:      make(chan struct{}),
+		watches:   newWatches(),
 	}
 
 	go w.readEvents()
@@ -174,6 +220,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 		unix.Close(kq)
 		return kq, closepipe, err
 	}
+	unix.CloseOnExec(closepipe[0])
+	unix.CloseOnExec(closepipe[1])
 
 	// Register changes to listen on the closepipe.
 	changes := make([]unix.Kevent_t, 1)
@@ -192,218 +240,172 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *kqueue) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *kqueue) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
+	case <-w.done:
+		return false
 	case w.Errors <- err:
 		return true
+	}
+}
+
+func (w *kqueue) isClosed() bool {
+	select {
 	case <-w.done:
+		return true
+	default:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *kqueue) Close() error {
+	w.doneMu.Lock()
+	if w.isClosed() {
+		w.doneMu.Unlock()
 		return nil
 	}
-	w.isClosed = true
+	close(w.done)
+	w.doneMu.Unlock()
 
-	// copy paths to remove while locked
-	pathsToRemove := make([]string, 0, len(w.watches))
-	for name := range w.watches {
-		pathsToRemove = append(pathsToRemove, name)
-	}
-	w.mu.Unlock() // Unlock before calling Remove, which also locks
+	pathsToRemove := w.watches.listPaths(false)
 	for _, name := range pathsToRemove {
 		w.Remove(name)
 	}
 
 	// Send "quit" message to the reader goroutine.
 	unix.Close(w.closepipe[1])
-	close(w.done)
-
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	w.userWatches[name] = struct{}{}
-	w.mu.Unlock()
+func (w *kqueue) Add(name string) error { return w.AddWith(name) }
+
+func (w *kqueue) AddWith(name string, opts ...addOpt) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
 	_, err := w.addWatch(name, noteAllEvents)
-	return err
+	if err != nil {
+		return err
+	}
+	w.watches.addUserWatch(name)
+	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *kqueue) Remove(name string) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(name, true)
+}
+
+func (w *kqueue) remove(name string, unwatchFiles bool) error {
+	if w.isClosed() {
+		return nil
+	}
+
 	name = filepath.Clean(name)
-	w.mu.Lock()
-	watchfd, ok := w.watches[name]
-	w.mu.Unlock()
+	info, ok := w.watches.byPath(name)
 	if !ok {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_DELETE, 0)
+	err := w.register([]int{info.wd}, unix.EV_DELETE, 0)
 	if err != nil {
 		return err
 	}
 
-	unix.Close(watchfd)
-
-	w.mu.Lock()
-	isDir := w.paths[watchfd].isDir
-	delete(w.watches, name)
-	delete(w.userWatches, name)
-
-	parentName := filepath.Dir(name)
-	delete(w.watchesByDir[parentName], watchfd)
-
-	if len(w.watchesByDir[parentName]) == 0 {
-		delete(w.watchesByDir, parentName)
-	}
+	unix.Close(info.wd)
 
-	delete(w.paths, watchfd)
-	delete(w.dirFlags, name)
-	delete(w.fileExists, name)
-	w.mu.Unlock()
+	isDir := w.watches.remove(info.wd, name)
 
 	// Find all watched paths that are in this directory that are not external.
-	if isDir {
-		var pathsToRemove []string
-		w.mu.Lock()
-		for fd := range w.watchesByDir[name] {
-			path := w.paths[fd]
-			if _, ok := w.userWatches[path.name]; !ok {
-				pathsToRemove = append(pathsToRemove, path.name)
-			}
-		}
-		w.mu.Unlock()
+	if unwatchFiles && isDir {
+		pathsToRemove := w.watches.watchesInDir(name)
 		for _, name := range pathsToRemove {
-			// Since these are internal, not much sense in propagating error
-			// to the user, as that will just confuse them with an error about
-			// a path they did not explicitly watch themselves.
+			// Since these are internal, not much sense in propagating error to
+			// the user, as that will just confuse them with an error about a
+			// path they did not explicitly watch themselves.
 			w.Remove(name)
 		}
 	}
-
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-
-	entries := make([]string, 0, len(w.userWatches))
-	for pathname := range w.userWatches {
-		entries = append(entries, pathname)
+func (w *kqueue) WatchList() []string {
+	if w.isClosed() {
+		return nil
 	}
-
-	return entries
+	return w.watches.listPaths(true)
 }
 
 // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
 const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
 
-// addWatch adds name to the watched file set.
-// The flags are interpreted as described in kevent(2).
-// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
-func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
-	var isDir bool
-	// Make ./name and name equivalent
-	name = filepath.Clean(name)
-
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return "", errors.New("kevent instance already closed")
-	}
-	watchfd, alreadyWatching := w.watches[name]
-	// We already have a watch, but we can still override flags.
-	if alreadyWatching {
-		isDir = w.paths[watchfd].isDir
+// addWatch adds name to the watched file set; the flags are interpreted as
+// described in kevent(2).
+//
+// Returns the real path to the file which was added, with symlinks resolved.
+func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
+	if w.isClosed() {
+		return "", ErrClosed
 	}
-	w.mu.Unlock()
 
+	name = filepath.Clean(name)
+
+	info, alreadyWatching := w.watches.byPath(name)
 	if !alreadyWatching {
 		fi, err := os.Lstat(name)
 		if err != nil {
 			return "", err
 		}
 
-		// Don't watch sockets or named pipes
+		// Don't watch sockets or named pipes.
 		if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) {
 			return "", nil
 		}
 
-		// Follow Symlinks
-		//
-		// Linux can add unresolvable symlinks to the watch list without issue,
-		// and Windows can't do symlinks period. To maintain consistency, we
-		// will act like everything is fine if the link can't be resolved.
-		// There will simply be no file events for broken symlinks. Hence the
-		// returns of nil on errors.
+		// Follow symlinks.
 		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
-			name, err = filepath.EvalSymlinks(name)
+			link, err := os.Readlink(name)
 			if err != nil {
+				// Return nil because Linux can add unresolvable symlinks to the
+				// watch list without problems, so maintain consistency with
+				// that. There will be no file events for broken symlinks.
+				// TODO: more specific check; returns os.PathError; ENOENT?
 				return "", nil
 			}
 
-			w.mu.Lock()
-			_, alreadyWatching = w.watches[name]
-			w.mu.Unlock()
-
+			_, alreadyWatching = w.watches.byPath(link)
 			if alreadyWatching {
-				return name, nil
+				// Add to watches so we don't get spurious Create events later
+				// on when we diff the directories.
+				w.watches.addLink(name, 0)
+				return link, nil
 			}
 
+			info.linkName = name
+			name = link
 			fi, err = os.Lstat(name)
 			if err != nil {
 				return "", nil
@@ -411,9 +413,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 		}
 
 		// Retry on EINTR; open() can return EINTR in practice on macOS.
-		// See #354, and go issues 11180 and 39237.
+		// See #354, and Go issues 11180 and 39237.
 		for {
-			watchfd, err = unix.Open(name, openMode, 0)
+			info.wd, err = unix.Open(name, openMode, 0)
 			if err == nil {
 				break
 			}
@@ -424,41 +426,25 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 			return "", err
 		}
 
-		isDir = fi.IsDir()
+		info.isDir = fi.IsDir()
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
+	err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
 	if err != nil {
-		unix.Close(watchfd)
+		unix.Close(info.wd)
 		return "", err
 	}
 
 	if !alreadyWatching {
-		w.mu.Lock()
-		parentName := filepath.Dir(name)
-		w.watches[name] = watchfd
-
-		watchesByDir, ok := w.watchesByDir[parentName]
-		if !ok {
-			watchesByDir = make(map[int]struct{}, 1)
-			w.watchesByDir[parentName] = watchesByDir
-		}
-		watchesByDir[watchfd] = struct{}{}
-
-		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
-		w.mu.Unlock()
+		w.watches.add(name, info.linkName, info.wd, info.isDir)
 	}
 
-	if isDir {
-		// Watch the directory if it has not been watched before,
-		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
-		w.mu.Lock()
-
+	// Watch the directory if it has not been watched before, or if it was
+	// watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
+	if info.isDir {
 		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
-			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
-		// Store flags so this watch can be updated later
-		w.dirFlags[name] = flags
-		w.mu.Unlock()
+			(!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
+		w.watches.updateDirFlags(name, flags)
 
 		if watchDir {
 			if err := w.watchDirectoryFiles(name); err != nil {
@@ -471,95 +457,110 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 
 // readEvents reads from kqueue and converts the received kevents into
 // Event values that it sends down the Events channel.
-func (w *Watcher) readEvents() {
+func (w *kqueue) readEvents() {
 	defer func() {
-		err := unix.Close(w.kq)
-		if err != nil {
-			w.Errors <- err
-		}
-		unix.Close(w.closepipe[0])
 		close(w.Events)
 		close(w.Errors)
+		_ = unix.Close(w.kq)
+		unix.Close(w.closepipe[0])
 	}()
 
 	eventBuffer := make([]unix.Kevent_t, 10)
-	for closed := false; !closed; {
+	for {
 		kevents, err := w.read(eventBuffer)
 		// EINTR is okay, the syscall was interrupted before timeout expired.
 		if err != nil && err != unix.EINTR {
 			if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) {
-				closed = true
+				return
 			}
-			continue
 		}
 
-		// Flush the events we received to the Events channel
 		for _, kevent := range kevents {
 			var (
-				watchfd = int(kevent.Ident)
-				mask    = uint32(kevent.Fflags)
+				wd   = int(kevent.Ident)
+				mask = uint32(kevent.Fflags)
 			)
 
 			// Shut down the loop when the pipe is closed, but only after all
 			// other events have been processed.
-			if watchfd == w.closepipe[0] {
-				closed = true
-				continue
+			if wd == w.closepipe[0] {
+				return
 			}
 
-			w.mu.Lock()
-			path := w.paths[watchfd]
-			w.mu.Unlock()
-
-			event := w.newEvent(path.name, mask)
+			path, ok := w.watches.byWd(wd)
+			if debug {
+				internal.Debug(path.name, &kevent)
+			}
 
-			if path.isDir && !event.Has(Remove) {
-				// Double check to make sure the directory exists. This can
-				// happen when we do a rm -fr on a recursively watched folders
-				// and we receive a modification event first but the folder has
-				// been deleted and later receive the delete event.
-				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
-					event.Op |= Remove
-				}
+			// On macOS it seems that sometimes an event with Ident=0 is
+			// delivered, and no other flags/information beyond that, even
+			// though we never saw such a file descriptor. For example in
+			// TestWatchSymlink/277 (usually at the end, but sometimes sooner):
+			//
+			// fmt.Printf("READ: %2d  %#v\n", kevent.Ident, kevent)
+			// unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			// unix.Kevent_t{Ident:0x0,  Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			//
+			// The first is a normal event, the second with Ident 0. No error
+			// flag, no data, no ... nothing.
+			//
+			// I read a bit through bsd/kern_event.c from the xnu source, but I
+			// don't really see an obvious location where this is triggered –
+			// this doesn't seem intentional, but idk...
+			//
+			// Technically fd 0 is a valid descriptor, so only skip it if
+			// there's no path, and if we're on macOS.
+			if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" {
+				continue
 			}
 
+			event := w.newEvent(path.name, path.linkName, mask)
+
 			if event.Has(Rename) || event.Has(Remove) {
-				w.Remove(event.Name)
-				w.mu.Lock()
-				delete(w.fileExists, event.Name)
-				w.mu.Unlock()
+				w.remove(event.Name, false)
+				w.watches.markSeen(event.Name, false)
 			}
 
 			if path.isDir && event.Has(Write) && !event.Has(Remove) {
-				w.sendDirectoryChangeEvents(event.Name)
-			} else {
-				if !w.sendEvent(event) {
-					closed = true
-					continue
-				}
+				w.dirChange(event.Name)
+			} else if !w.sendEvent(event) {
+				return
 			}
 
 			if event.Has(Remove) {
-				// Look for a file that may have overwritten this.
-				// For example, mv f1 f2 will delete f2, then create f2.
+				// Look for a file that may have overwritten this; for example,
+				// mv f1 f2 will delete f2, then create f2.
 				if path.isDir {
 					fileDir := filepath.Clean(event.Name)
-					w.mu.Lock()
-					_, found := w.watches[fileDir]
-					w.mu.Unlock()
+					_, found := w.watches.byPath(fileDir)
 					if found {
-						// make sure the directory exists before we watch for changes. When we
-						// do a recursive watch and perform rm -fr, the parent directory might
-						// have gone missing, ignore the missing directory and let the
-						// upcoming delete event remove the watch from the parent directory.
-						if _, err := os.Lstat(fileDir); err == nil {
-							w.sendDirectoryChangeEvents(fileDir)
+						// TODO: this branch is never triggered in any test.
+						// Added in d6220df (2012).
+						// isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111
+						//
+						// I don't really get how this can be triggered either.
+						// And it wasn't triggered in the patch that added it,
+						// either.
+						//
+						// Original also had a comment:
+						//   make sure the directory exists before we watch for
+						//   changes. When we do a recursive watch and perform
+						//   rm -rf, the parent directory might have gone
+						//   missing, ignore the missing directory and let the
+						//   upcoming delete event remove the watch from the
+						//   parent directory.
+						err := w.dirChange(fileDir)
+						if !w.sendError(err) {
+							return
 						}
 					}
 				} else {
-					filePath := filepath.Clean(event.Name)
-					if fileInfo, err := os.Lstat(filePath); err == nil {
-						w.sendFileCreatedEventIfNew(filePath, fileInfo)
+					path := filepath.Clean(event.Name)
+					if fi, err := os.Lstat(path); err == nil {
+						err := w.sendCreateIfNew(path, fi)
+						if !w.sendError(err) {
+							return
+						}
 					}
 				}
 			}
@@ -568,8 +569,14 @@ func (w *Watcher) readEvents() {
 }
 
 // newEvent returns an platform-independent Event based on kqueue Fflags.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *kqueue) newEvent(name, linkName string, mask uint32) Event {
 	e := Event{Name: name}
+	if linkName != "" {
+		// If the user watched "/path/link" then emit events as "/path/link"
+		// rather than "/path/target".
+		e.Name = linkName
+	}
+
 	if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
 		e.Op |= Remove
 	}
@@ -582,21 +589,30 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
 		e.Op |= Chmod
 	}
+	// No point sending a write and delete event at the same time: if it's gone,
+	// then it's gone.
+	if e.Op.Has(Write) && e.Op.Has(Remove) {
+		e.Op &^= Write
+	}
 	return e
 }
 
 // watchDirectoryFiles to mimic inotify when adding a watch on a directory
-func (w *Watcher) watchDirectoryFiles(dirPath string) error {
-	// Get all files
-	files, err := ioutil.ReadDir(dirPath)
+func (w *kqueue) watchDirectoryFiles(dirPath string) error {
+	files, err := os.ReadDir(dirPath)
 	if err != nil {
 		return err
 	}
 
-	for _, fileInfo := range files {
-		path := filepath.Join(dirPath, fileInfo.Name())
+	for _, f := range files {
+		path := filepath.Join(dirPath, f.Name())
 
-		cleanPath, err := w.internalWatch(path, fileInfo)
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("%q: %w", path, err)
+		}
+
+		cleanPath, err := w.internalWatch(path, fi)
 		if err != nil {
 			// No permission to read the file; that's not a problem: just skip.
 			// But do add it to w.fileExists to prevent it from being picked up
@@ -606,13 +622,11 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 			case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM):
 				cleanPath = filepath.Clean(path)
 			default:
-				return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err)
+				return fmt.Errorf("%q: %w", path, err)
 			}
 		}
 
-		w.mu.Lock()
-		w.fileExists[cleanPath] = struct{}{}
-		w.mu.Unlock()
+		w.watches.markSeen(cleanPath, true)
 	}
 
 	return nil
@@ -622,58 +636,59 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 //
 // This functionality is to have the BSD watcher match the inotify, which sends
 // a create event for files created in a watched directory.
-func (w *Watcher) sendDirectoryChangeEvents(dir string) {
-	// Get all files
-	files, err := ioutil.ReadDir(dir)
+func (w *kqueue) dirChange(dir string) error {
+	files, err := os.ReadDir(dir)
 	if err != nil {
-		if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) {
-			return
+		// Directory no longer exists: we can ignore this safely. kqueue will
+		// still give us the correct events.
+		if errors.Is(err, os.ErrNotExist) {
+			return nil
 		}
+		return fmt.Errorf("fsnotify.dirChange: %w", err)
 	}
 
-	// Search for new files
-	for _, fi := range files {
-		err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi)
+	for _, f := range files {
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
+		}
+
+		err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
 		if err != nil {
-			return
+			// Don't need to send an error if this file isn't readable.
+			if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) {
+				return nil
+			}
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
 		}
 	}
+	return nil
 }
 
-// sendFileCreatedEvent sends a create event if the file isn't already being tracked.
-func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) {
-	w.mu.Lock()
-	_, doesExist := w.fileExists[filePath]
-	w.mu.Unlock()
-	if !doesExist {
-		if !w.sendEvent(Event{Name: filePath, Op: Create}) {
-			return
+// Send a create event if the file isn't already being tracked, and start
+// watching this file.
+func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error {
+	if !w.watches.seenBefore(path) {
+		if !w.sendEvent(Event{Name: path, Op: Create}) {
+			return nil
 		}
 	}
 
-	// like watchDirectoryFiles (but without doing another ReadDir)
-	filePath, err = w.internalWatch(filePath, fileInfo)
+	// Like watchDirectoryFiles, but without doing another ReadDir.
+	path, err := w.internalWatch(path, fi)
 	if err != nil {
 		return err
 	}
-
-	w.mu.Lock()
-	w.fileExists[filePath] = struct{}{}
-	w.mu.Unlock()
-
+	w.watches.markSeen(path, true)
 	return nil
 }
 
-func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) {
-	if fileInfo.IsDir() {
-		// mimic Linux providing delete events for subdirectories
-		// but preserve the flags used if currently watching subdirectory
-		w.mu.Lock()
-		flags := w.dirFlags[name]
-		w.mu.Unlock()
-
-		flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
-		return w.addWatch(name, flags)
+func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) {
+	if fi.IsDir() {
+		// mimic Linux providing delete events for subdirectories, but preserve
+		// the flags used if currently watching subdirectory
+		info, _ := w.watches.byPath(name)
+		return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME)
 	}
 
 	// watch file to mimic Linux inotify
@@ -681,7 +696,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro
 }
 
 // Register events with the queue.
-func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
+func (w *kqueue) register(fds []int, flags int, fflags uint32) error {
 	changes := make([]unix.Kevent_t, len(fds))
 	for i, fd := range fds {
 		// SetKevent converts int to the platform-specific types.
@@ -698,10 +713,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
 }
 
 // read retrieves pending events, or waits until an event occurs.
-func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
+func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
 	n, err := unix.Kevent(w.kq, nil, events, nil)
 	if err != nil {
 		return nil, err
 	}
 	return events[0:n], nil
 }
+
+func (w *kqueue) xSupports(op Op) bool {
+	if runtime.GOOS == "freebsd" {
+		//return true // Supports everything.
+	}
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/backend_other.go b/history-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
index a9bb1c3c..5eb5dbc6 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
@@ -1,66 +1,23 @@
-//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows
-// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
+//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
 
 package fsnotify
 
-import (
-	"fmt"
-	"runtime"
-)
+import "errors"
 
-// Watcher watches a set of files, delivering events to a channel.
-type Watcher struct{}
-
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	return nil
+type other struct {
+	Events chan Event
+	Errors chan error
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	return nil
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return nil, errors.New("fsnotify not supported on the current platform")
 }
-
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	return nil
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	return newBackend(ev, errs)
 }
+func (w *other) Close() error                              { return nil }
+func (w *other) WatchList() []string                       { return nil }
+func (w *other) Add(name string) error                     { return nil }
+func (w *other) AddWith(name string, opts ...addOpt) error { return nil }
+func (w *other) Remove(name string) error                  { return nil }
+func (w *other) xSupports(op Op) bool                      { return false }
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/history-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
index ae392867..c54a6308 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
@@ -1,5 +1,8 @@
 //go:build windows
-// +build windows
+
+// Windows backend based on ReadDirectoryChangesW()
+//
+// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
 
 package fsnotify
 
@@ -12,143 +15,60 @@ import (
 	"runtime"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/windows"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type readDirChangesW struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	port  windows.Handle // Handle to completion port
 	input chan *input    // Inputs to the reader are sent on this channel
 	quit  chan chan<- error
 
-	mu       sync.Mutex // Protects access to watches, isClosed
-	watches  watchMap   // Map of watches (key: i-number)
-	isClosed bool       // Set to true when Close() is first called
+	mu      sync.Mutex // Protects access to watches, closed
+	watches watchMap   // Map of watches (key: i-number)
+	closed  bool       // Set to true when Close() is first called
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(50, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
 	if err != nil {
 		return nil, os.NewSyscallError("CreateIoCompletionPort", err)
 	}
-	w := &Watcher{
+	w := &readDirChangesW{
+		Events:  ev,
+		Errors:  errs,
 		port:    port,
 		watches: make(watchMap),
 		input:   make(chan *input, 1),
-		Events:  make(chan Event, 50),
-		Errors:  make(chan error),
 		quit:    make(chan chan<- error, 1),
 	}
 	go w.readEvents()
 	return w, nil
 }
 
-func (w *Watcher) sendEvent(name string, mask uint64) bool {
+func (w *readDirChangesW) isClosed() bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	return w.closed
+}
+
+func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
 	if mask == 0 {
 		return false
 	}
 
 	event := w.newEvent(name, uint32(mask))
+	event.renamedFrom = renamedFrom
 	select {
 	case ch := <-w.quit:
 		w.quit <- ch
@@ -158,23 +78,25 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *readDirChangesW) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
 	case w.Errors <- err:
 		return true
 	case <-w.quit:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *readDirChangesW) Close() error {
+	if w.isClosed() {
 		return nil
 	}
-	w.isClosed = true
+
+	w.mu.Lock()
+	w.closed = true
 	w.mu.Unlock()
 
 	// Send "quit" message to the reader goroutine
@@ -186,49 +108,31 @@ func (w *Watcher) Close() error {
 	return <-ch
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return errors.New("watcher already closed")
+func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
+
+func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+	if with.bufsize < 4096 {
+		return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
 	}
-	w.mu.Unlock()
 
 	in := &input{
-		op:    opAddWatch,
-		path:  filepath.Clean(name),
-		flags: sysFSALLEVENTS,
-		reply: make(chan error),
+		op:      opAddWatch,
+		path:    filepath.Clean(name),
+		flags:   sysFSALLEVENTS,
+		reply:   make(chan error),
+		bufsize: with.bufsize,
 	}
 	w.input <- in
 	if err := w.wakeupReader(); err != nil {
@@ -237,13 +141,15 @@ func (w *Watcher) Add(name string) error {
 	return <-in.reply
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *readDirChangesW) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
 	in := &input{
 		op:    opRemoveWatch,
 		path:  filepath.Clean(name),
@@ -256,15 +162,24 @@ func (w *Watcher) Remove(name string) error {
 	return <-in.reply
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
+func (w *readDirChangesW) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
 	w.mu.Lock()
 	defer w.mu.Unlock()
 
 	entries := make([]string, 0, len(w.watches))
 	for _, entry := range w.watches {
 		for _, watchEntry := range entry {
-			entries = append(entries, watchEntry.path)
+			for name := range watchEntry.names {
+				entries = append(entries, filepath.Join(watchEntry.path, name))
+			}
+			// the directory itself is being watched
+			if watchEntry.mask != 0 {
+				entries = append(entries, watchEntry.path)
+			}
 		}
 	}
 
@@ -279,7 +194,6 @@ func (w *Watcher) WatchList() []string {
 // This should all be removed at some point, and just use windows.FILE_NOTIFY_*
 const (
 	sysFSALLEVENTS  = 0xfff
-	sysFSATTRIB     = 0x4
 	sysFSCREATE     = 0x100
 	sysFSDELETE     = 0x200
 	sysFSDELETESELF = 0x400
@@ -291,7 +205,7 @@ const (
 	sysFSIGNORED    = 0x8000
 )
 
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
 	e := Event{Name: name}
 	if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
 		e.Op |= Create
@@ -305,9 +219,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
 		e.Op |= Rename
 	}
-	if mask&sysFSATTRIB == sysFSATTRIB {
-		e.Op |= Chmod
-	}
 	return e
 }
 
@@ -321,10 +232,11 @@ const (
 )
 
 type input struct {
-	op    int
-	path  string
-	flags uint32
-	reply chan error
+	op      int
+	path    string
+	flags   uint32
+	bufsize int
+	reply   chan error
 }
 
 type inode struct {
@@ -334,13 +246,14 @@ type inode struct {
 }
 
 type watch struct {
-	ov     windows.Overlapped
-	ino    *inode            // i-number
-	path   string            // Directory path
-	mask   uint64            // Directory itself is being watched with these notify flags
-	names  map[string]uint64 // Map of names being watched and their notify flags
-	rename string            // Remembers the old name while renaming a file
-	buf    [65536]byte       // 64K buffer
+	ov      windows.Overlapped
+	ino     *inode            // i-number
+	recurse bool              // Recursive watch?
+	path    string            // Directory path
+	mask    uint64            // Directory itself is being watched with these notify flags
+	names   map[string]uint64 // Map of names being watched and their notify flags
+	rename  string            // Remembers the old name while renaming a file
+	buf     []byte            // buffer, allocated later
 }
 
 type (
@@ -348,7 +261,7 @@ type (
 	watchMap map[uint32]indexMap
 )
 
-func (w *Watcher) wakeupReader() error {
+func (w *readDirChangesW) wakeupReader() error {
 	err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
 	if err != nil {
 		return os.NewSyscallError("PostQueuedCompletionStatus", err)
@@ -356,7 +269,7 @@ func (w *Watcher) wakeupReader() error {
 	return nil
 }
 
-func (w *Watcher) getDir(pathname string) (dir string, err error) {
+func (w *readDirChangesW) getDir(pathname string) (dir string, err error) {
 	attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
 	if err != nil {
 		return "", os.NewSyscallError("GetFileAttributes", err)
@@ -370,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
 	return
 }
 
-func (w *Watcher) getIno(path string) (ino *inode, err error) {
+func (w *readDirChangesW) getIno(path string) (ino *inode, err error) {
 	h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
 		windows.FILE_LIST_DIRECTORY,
 		windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
@@ -413,7 +326,9 @@ func (m watchMap) set(ino *inode, watch *watch) {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) addWatch(pathname string, flags uint64) error {
+func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -433,9 +348,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 			return os.NewSyscallError("CreateIoCompletionPort", err)
 		}
 		watchEntry = &watch{
-			ino:   ino,
-			path:  dir,
-			names: make(map[string]uint64),
+			ino:     ino,
+			path:    dir,
+			names:   make(map[string]uint64),
+			recurse: recurse,
+			buf:     make([]byte, bufsize),
 		}
 		w.mu.Lock()
 		w.watches.set(ino, watchEntry)
@@ -464,7 +381,9 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) remWatch(pathname string) error {
+func (w *readDirChangesW) remWatch(pathname string) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -478,6 +397,10 @@ func (w *Watcher) remWatch(pathname string) error {
 	watch := w.watches.get(ino)
 	w.mu.Unlock()
 
+	if recurse && !watch.recurse {
+		return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname)
+	}
+
 	err = windows.CloseHandle(ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CloseHandle", err))
@@ -486,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
 	}
 	if pathname == dir {
-		w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+		w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		watch.mask = 0
 	} else {
 		name := filepath.Base(pathname)
-		w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
+		w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED)
 		delete(watch.names, name)
 	}
 
@@ -498,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) deleteWatch(watch *watch) {
+func (w *readDirChangesW) deleteWatch(watch *watch) {
 	for name, mask := range watch.names {
 		if mask&provisional == 0 {
-			w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
+			w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED)
 		}
 		delete(watch.names, name)
 	}
 	if watch.mask != 0 {
 		if watch.mask&provisional == 0 {
-			w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+			w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		}
 		watch.mask = 0
 	}
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) startRead(watch *watch) error {
+func (w *readDirChangesW) startRead(watch *watch) error {
 	err := windows.CancelIo(watch.ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CancelIo", err))
@@ -535,13 +458,16 @@ func (w *Watcher) startRead(watch *watch) error {
 		return nil
 	}
 
-	rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
-		uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+	// We need to pass the array, rather than the slice.
+	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf))
+	rdErr := windows.ReadDirectoryChanges(watch.ino.handle,
+		(*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len),
+		watch.recurse, mask, nil, &watch.ov, 0)
 	if rdErr != nil {
 		err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
 		if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			err = nil
 		}
 		w.deleteWatch(watch)
@@ -554,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error {
 // readEvents reads from the I/O completion port, converts the
 // received events into Event objects and sends them via the Events channel.
 // Entry point to the I/O thread.
-func (w *Watcher) readEvents() {
+func (w *readDirChangesW) readEvents() {
 	var (
 		n   uint32
 		key uintptr
@@ -563,9 +489,8 @@ func (w *Watcher) readEvents() {
 	runtime.LockOSThread()
 
 	for {
+		// This error is handled after the watch == nil check below.
 		qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE)
-		// This error is handled after the watch == nil check below. NOTE: this
-		// seems odd, note sure if it's correct.
 
 		watch := (*watch)(unsafe.Pointer(ov))
 		if watch == nil {
@@ -595,7 +520,7 @@ func (w *Watcher) readEvents() {
 			case in := <-w.input:
 				switch in.op {
 				case opAddWatch:
-					in.reply <- w.addWatch(in.path, uint64(in.flags))
+					in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize)
 				case opRemoveWatch:
 					in.reply <- w.remWatch(in.path)
 				}
@@ -605,6 +530,8 @@ func (w *Watcher) readEvents() {
 		}
 
 		switch qErr {
+		case nil:
+			// No error
 		case windows.ERROR_MORE_DATA:
 			if watch == nil {
 				w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer"))
@@ -616,7 +543,7 @@ func (w *Watcher) readEvents() {
 			}
 		case windows.ERROR_ACCESS_DENIED:
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			w.deleteWatch(watch)
 			w.startRead(watch)
 			continue
@@ -626,13 +553,12 @@ func (w *Watcher) readEvents() {
 		default:
 			w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr))
 			continue
-		case nil:
 		}
 
 		var offset uint32
 		for {
 			if n == 0 {
-				w.sendError(errors.New("short read in readEvents()"))
+				w.sendError(ErrEventOverflow)
 				break
 			}
 
@@ -650,6 +576,10 @@ func (w *Watcher) readEvents() {
 			name := windows.UTF16ToString(buf)
 			fullname := filepath.Join(watch.path, name)
 
+			if debug {
+				internal.Debug(fullname, raw.Action)
+			}
+
 			var mask uint64
 			switch raw.Action {
 			case windows.FILE_ACTION_REMOVED:
@@ -678,21 +608,22 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			sendNameEvent := func() {
-				w.sendEvent(fullname, watch.names[name]&mask)
-			}
 			if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
-				sendNameEvent()
+				w.sendEvent(fullname, "", watch.names[name]&mask)
 			}
 			if raw.Action == windows.FILE_ACTION_REMOVED {
-				w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
+				w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED)
 				delete(watch.names, name)
 			}
 
-			w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action))
+			if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
+				w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action))
+			} else {
+				w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action))
+			}
+
 			if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
-				fullname = filepath.Join(watch.path, watch.rename)
-				sendNameEvent()
+				w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
 			}
 
 			// Move to the next event in the buffer
@@ -703,8 +634,8 @@ func (w *Watcher) readEvents() {
 
 			// Error!
 			if offset >= n {
-				w.sendError(errors.New(
-					"Windows system assumed buffer larger than it is, events have likely been missed."))
+				//lint:ignore ST1005 Windows should be capitalized
+				w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed"))
 				break
 			}
 		}
@@ -715,21 +646,18 @@ func (w *Watcher) readEvents() {
 	}
 }
 
-func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
+func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
 	var m uint32
 	if mask&sysFSMODIFY != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
 	}
-	if mask&sysFSATTRIB != 0 {
-		m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES
-	}
 	if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
 	}
 	return m
 }
 
-func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
+func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
 	switch action {
 	case windows.FILE_ACTION_ADDED:
 		return sysFSCREATE
@@ -744,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
 	}
 	return 0
 }
+
+func (w *readDirChangesW) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/history-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
index 30a5bf0f..0760efe9 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
@@ -1,16 +1,148 @@
-//go:build !plan9
-// +build !plan9
-
 // Package fsnotify provides a cross-platform interface for file system
 // notifications.
+//
+// Currently supported systems:
+//
+//   - Linux      via inotify
+//   - BSD, macOS via kqueue
+//   - Windows    via ReadDirectoryChangesW
+//   - illumos    via FEN
+//
+// # FSNOTIFY_DEBUG
+//
+// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to
+// stderr. This can be useful to track down some problems, especially in cases
+// where fsnotify is used as an indirect dependency.
+//
+// Every event will be printed as soon as there's something useful to print,
+// with as little processing from fsnotify.
+//
+// Example output:
+//
+//	FSNOTIFY_DEBUG: 11:34:23.633087586   256:IN_CREATE            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:23.633202319     4:IN_ATTRIB            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:28.989728764   512:IN_DELETE            → "/tmp/file-1"
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
+	"os"
+	"path/filepath"
 	"strings"
 )
 
+// Watcher watches a set of paths, delivering events on a channel.
+//
+// A watcher should not be copied (e.g. pass it by pointer, rather than by
+// value).
+//
+// # Linux notes
+//
+// When a file is removed a Remove event won't be emitted until all file
+// descriptors are closed, and deletes will always emit a Chmod. For example:
+//
+//	fp := os.Open("file")
+//	os.Remove("file")        // Triggers Chmod
+//	fp.Close()               // Triggers Remove
+//
+// This is the event that inotify sends, so not much can be changed about this.
+//
+// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
+// for the number of watches per user, and fs.inotify.max_user_instances
+// specifies the maximum number of inotify instances per user. Every Watcher you
+// create is an "instance", and every path you add is a "watch".
+//
+// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
+// /proc/sys/fs/inotify/max_user_instances
+//
+// To increase them you can use sysctl or write the value to the /proc file:
+//
+//	# Default values on Linux 5.18
+//	sysctl fs.inotify.max_user_watches=124983
+//	sysctl fs.inotify.max_user_instances=128
+//
+// To make the changes persist on reboot edit /etc/sysctl.conf or
+// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
+// your distro's documentation):
+//
+//	fs.inotify.max_user_watches=124983
+//	fs.inotify.max_user_instances=128
+//
+// Reaching the limit will result in a "no space left on device" or "too many open
+// files" error.
+//
+// # kqueue notes (macOS, BSD)
+//
+// kqueue requires opening a file descriptor for every file that's being watched;
+// so if you're watching a directory with five files then that's six file
+// descriptors. You will run in to your system's "max open files" limit faster on
+// these platforms.
+//
+// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
+// control the maximum number of open files, as well as /etc/login.conf on BSD
+// systems.
+//
+// # Windows notes
+//
+// Paths can be added as "C:\\path\\to\\dir", but forward slashes
+// ("C:/path/to/dir") will also work.
+//
+// When a watched directory is removed it will always send an event for the
+// directory itself, but may not send events for all files in that directory.
+// Sometimes it will send events for all files, sometimes it will send no
+// events, and often only for some files.
+//
+// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest
+// value that is guaranteed to work with SMB filesystems. If you have many
+// events in quick succession this may not be enough, and you will have to use
+// [WithBufferSize] to increase the value.
+type Watcher struct {
+	b backend
+
+	// Events sends the filesystem change events.
+	//
+	// fsnotify can send the following events; a "path" here can refer to a
+	// file, directory, symbolic link, or special file like a FIFO.
+	//
+	//   fsnotify.Create    A new path was created; this may be followed by one
+	//                      or more Write events if data also gets written to a
+	//                      file.
+	//
+	//   fsnotify.Remove    A path was removed.
+	//
+	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
+	//                      old path as Event.Name, and a Create event will be
+	//                      sent with the new name. Renames are only sent for
+	//                      paths that are currently watched; e.g. moving an
+	//                      unmonitored file into a monitored directory will
+	//                      show up as just a Create. Similarly, renaming a file
+	//                      to outside a monitored directory will show up as
+	//                      only a Rename.
+	//
+	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
+	//                      also trigger a Write. A single "write action"
+	//                      initiated by the user may show up as one or multiple
+	//                      writes, depending on when the system syncs things to
+	//                      disk. For example when compiling a large Go program
+	//                      you may get hundreds of Write events, and you may
+	//                      want to wait until you've stopped receiving them
+	//                      (see the dedup example in cmd/fsnotify).
+	//
+	//                      Some systems may send Write event for directories
+	//                      when the directory content changes.
+	//
+	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
+	//                      when a file is removed (or more accurately, when a
+	//                      link to an inode is removed). On kqueue it's sent
+	//                      when a file is truncated. On Windows it's never
+	//                      sent.
+	Events chan Event
+
+	// Errors sends any errors.
+	Errors chan error
+}
+
 // Event represents a file system notification.
 type Event struct {
 	// Path to the file or directory.
@@ -25,6 +157,16 @@ type Event struct {
 	// This is a bitmask and some systems may send multiple operations at once.
 	// Use the Event.Has() method instead of comparing with ==.
 	Op Op
+
+	// Create events will have this set to the old path if it's a rename. This
+	// only works when both the source and destination are watched. It's not
+	// reliable when watching individual files, only directories.
+	//
+	// For example "mv /tmp/file /tmp/rename" will emit:
+	//
+	//   Event{Op: Rename, Name: "/tmp/file"}
+	//   Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"}
+	renamedFrom string
 }
 
 // Op describes a set of file operations.
@@ -33,34 +175,204 @@ type Op uint32
 // The operations fsnotify can trigger; see the documentation on [Watcher] for a
 // full description, and check them with [Event.Has].
 const (
+	// A new pathname was created.
 	Create Op = 1 << iota
+
+	// The pathname was written to; this does *not* mean the write has finished,
+	// and a write can be followed by more writes.
 	Write
+
+	// The path was removed; any watches on it will be removed. Some "remove"
+	// operations may trigger a Rename if the file is actually moved (for
+	// example "remove to trash" is often a rename).
 	Remove
+
+	// The path was renamed to something else; any watches on it will be
+	// removed.
 	Rename
+
+	// File attributes were changed.
+	//
+	// It's generally not recommended to take action on this event, as it may
+	// get triggered very frequently by some software. For example, Spotlight
+	// indexing on macOS, anti-virus software, backup software, etc.
 	Chmod
+
+	// File descriptor was opened.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableOpen
+
+	// File was read from.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableRead
+
+	// File opened for writing was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	//
+	// The advantage of using this over Write is that it's more reliable than
+	// waiting for Write events to stop. It's also faster (if you're not
+	// listening to Write events): copying a file of a few GB can easily
+	// generate tens of thousands of Write events in a short span of time.
+	xUnportableCloseWrite
+
+	// File opened for reading was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableCloseRead
 )
 
-// Common errors that can be reported by a watcher
 var (
-	ErrNonExistentWatch = errors.New("can't remove non-existent watcher")
-	ErrEventOverflow    = errors.New("fsnotify queue overflow")
+	// ErrNonExistentWatch is used when Remove() is called on a path that's not
+	// added.
+	ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
+
+	// ErrClosed is used when trying to operate on a closed Watcher.
+	ErrClosed = errors.New("fsnotify: watcher already closed")
+
+	// ErrEventOverflow is reported from the Errors channel when there are too
+	// many events:
+	//
+	//  - inotify:      inotify returns IN_Q_OVERFLOW – because there are too
+	//                  many queued events (the fs.inotify.max_queued_events
+	//                  sysctl can be used to increase this).
+	//  - windows:      The buffer size is too small; WithBufferSize() can be used to increase it.
+	//  - kqueue, fen:  Not used.
+	ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
+
+	// ErrUnsupported is returned by AddWith() when WithOps() specified an
+	// Unportable event that's not supported on this platform.
+	xErrUnsupported = errors.New("fsnotify: not supported with this backend")
 )
 
-func (op Op) String() string {
+// NewWatcher creates a new Watcher.
+func NewWatcher() (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBackend(ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
+// channel.
+//
+// The main use case for this is situations with a very large number of events
+// where the kernel buffer size can't be increased (e.g. due to lack of
+// permissions). An unbuffered Watcher will perform better for almost all use
+// cases, and whenever possible you will be better off increasing the kernel
+// buffers instead of adding a large userspace buffer.
+func NewBufferedWatcher(sz uint) (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBufferedBackend(sz, ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// Add starts monitoring the path for changes.
+//
+// A path can only be watched once; watching it more than once is a no-op and will
+// not return an error. Paths that do not yet exist on the filesystem cannot be
+// watched.
+//
+// A watch will be automatically removed if the watched path is deleted or
+// renamed. The exception is the Windows backend, which doesn't remove the
+// watcher on renames.
+//
+// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
+// filesystems (/proc, /sys, etc.) generally don't work.
+//
+// Returns [ErrClosed] if [Watcher.Close] was called.
+//
+// See [Watcher.AddWith] for a version that allows adding options.
+//
+// # Watching directories
+//
+// All files in a directory are monitored, including new files that are created
+// after the watcher is started. Subdirectories are not watched (i.e. it's
+// non-recursive).
+//
+// # Watching files
+//
+// Watching individual files (rather than directories) is generally not
+// recommended as many programs (especially editors) update files atomically: it
+// will write to a temporary file which is then moved to destination,
+// overwriting the original (or some variant thereof). The watcher on the
+// original file is now lost, as that no longer exists.
+//
+// The upshot of this is that a power failure or crash won't leave a
+// half-written file.
+//
+// Watch the parent directory and use Event.Name to filter out files you're not
+// interested in. There is an example of this in cmd/fsnotify/file.go.
+func (w *Watcher) Add(path string) error { return w.b.Add(path) }
+
+// AddWith is like [Watcher.Add], but allows adding options. When using Add()
+// the defaults described below are used.
+//
+// Possible options are:
+//
+//   - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
+//     other platforms. The default is 64K (65536 bytes).
+func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) }
+
+// Remove stops monitoring the path for changes.
+//
+// Directories are always removed non-recursively. For example, if you added
+// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
+//
+// Removing a path that has not yet been added returns [ErrNonExistentWatch].
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) Remove(path string) error { return w.b.Remove(path) }
+
+// Close removes all watches and closes the Events channel.
+func (w *Watcher) Close() error { return w.b.Close() }
+
+// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
+// yet removed).
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) WatchList() []string { return w.b.WatchList() }
+
+// Supports reports if all the listed operations are supported by this platform.
+//
+// Create, Write, Remove, Rename, and Chmod are always supported. It can only
+// return false for an Op starting with Unportable.
+func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) }
+
+func (o Op) String() string {
 	var b strings.Builder
-	if op.Has(Create) {
+	if o.Has(Create) {
 		b.WriteString("|CREATE")
 	}
-	if op.Has(Remove) {
+	if o.Has(Remove) {
 		b.WriteString("|REMOVE")
 	}
-	if op.Has(Write) {
+	if o.Has(Write) {
 		b.WriteString("|WRITE")
 	}
-	if op.Has(Rename) {
+	if o.Has(xUnportableOpen) {
+		b.WriteString("|OPEN")
+	}
+	if o.Has(xUnportableRead) {
+		b.WriteString("|READ")
+	}
+	if o.Has(xUnportableCloseWrite) {
+		b.WriteString("|CLOSE_WRITE")
+	}
+	if o.Has(xUnportableCloseRead) {
+		b.WriteString("|CLOSE_READ")
+	}
+	if o.Has(Rename) {
 		b.WriteString("|RENAME")
 	}
-	if op.Has(Chmod) {
+	if o.Has(Chmod) {
 		b.WriteString("|CHMOD")
 	}
 	if b.Len() == 0 {
@@ -70,12 +382,113 @@ func (op Op) String() string {
 }
 
 // Has reports if this operation has the given operation.
-func (o Op) Has(h Op) bool { return o&h == h }
+func (o Op) Has(h Op) bool { return o&h != 0 }
 
 // Has reports if this event has the given operation.
 func (e Event) Has(op Op) bool { return e.Op.Has(op) }
 
 // String returns a string representation of the event with their path.
 func (e Event) String() string {
+	if e.renamedFrom != "" {
+		return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom)
+	}
 	return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
 }
+
+type (
+	backend interface {
+		Add(string) error
+		AddWith(string, ...addOpt) error
+		Remove(string) error
+		WatchList() []string
+		Close() error
+		xSupports(Op) bool
+	}
+	addOpt   func(opt *withOpts)
+	withOpts struct {
+		bufsize    int
+		op         Op
+		noFollow   bool
+		sendCreate bool
+	}
+)
+
+var debug = func() bool {
+	// Check for exactly "1" (rather than mere existence) so we can add
+	// options/flags in the future. I don't know if we ever want that, but it's
+	// nice to leave the option open.
+	return os.Getenv("FSNOTIFY_DEBUG") == "1"
+}()
+
+var defaultOpts = withOpts{
+	bufsize: 65536, // 64K
+	op:      Create | Write | Remove | Rename | Chmod,
+}
+
+func getOptions(opts ...addOpt) withOpts {
+	with := defaultOpts
+	for _, o := range opts {
+		if o != nil {
+			o(&with)
+		}
+	}
+	return with
+}
+
+// WithBufferSize sets the [ReadDirectoryChangesW] buffer size.
+//
+// This only has effect on Windows systems, and is a no-op for other backends.
+//
+// The default value is 64K (65536 bytes) which is the highest value that works
+// on all filesystems and should be enough for most applications, but if you
+// have a large burst of events it may not be enough. You can increase it if
+// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]).
+//
+// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
+func WithBufferSize(bytes int) addOpt {
+	return func(opt *withOpts) { opt.bufsize = bytes }
+}
+
+// WithOps sets which operations to listen for. The default is [Create],
+// [Write], [Remove], [Rename], and [Chmod].
+//
+// Excluding operations you're not interested in can save quite a bit of CPU
+// time; in some use cases there may be hundreds of thousands of useless Write
+// or Chmod operations per second.
+//
+// This can also be used to add unportable operations not supported by all
+// platforms; unportable operations all start with "Unportable":
+// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and
+// [UnportableCloseRead].
+//
+// AddWith returns an error when using an unportable operation that's not
+// supported. Use [Watcher.Support] to check for support.
+func withOps(op Op) addOpt {
+	return func(opt *withOpts) { opt.op = op }
+}
+
+// WithNoFollow disables following symlinks, so the symlinks themselves are
+// watched.
+func withNoFollow() addOpt {
+	return func(opt *withOpts) { opt.noFollow = true }
+}
+
+// "Internal" option for recursive watches on inotify.
+func withCreate() addOpt {
+	return func(opt *withOpts) { opt.sendCreate = true }
+}
+
+var enableRecurse = false
+
+// Check if this path is recursive (ends with "/..." or "\..."), and return the
+// path with the /... stripped.
+func recursivePath(path string) (string, bool) {
+	path = filepath.Clean(path)
+	if !enableRecurse { // Only enabled in tests for now.
+		return path, false
+	}
+	if filepath.Base(path) == "..." {
+		return filepath.Dir(path), true
+	}
+	return path, false
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
new file mode 100644
index 00000000..b0eab100
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
@@ -0,0 +1,39 @@
+//go:build darwin
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+func SetRlimit() {
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = l.Cur
+
+	if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+
+	if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
new file mode 100644
index 00000000..928319fb
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
@@ -0,0 +1,57 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_BACKGROUND", unix.NOTE_BACKGROUND},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CRITICAL", unix.NOTE_CRITICAL},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS},
+	{"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR},
+	{"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL},
+	{"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL},
+	{"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK},
+	{"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY},
+	{"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_FUNLOCK", unix.NOTE_FUNLOCK},
+	{"NOTE_LEEWAY", unix.NOTE_LEEWAY},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MACHTIME", unix.NOTE_MACHTIME},
+	{"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME},
+	{"NOTE_NONE", unix.NOTE_NONE},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	//{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!)
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_REAP", unix.NOTE_REAP},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_SIGNAL", unix.NOTE_SIGNAL},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_VM_ERROR", unix.NOTE_VM_ERROR},
+	{"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE},
+	{"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE},
+	{"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
new file mode 100644
index 00000000..3186b0c3
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
@@ -0,0 +1,33 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
new file mode 100644
index 00000000..f69fdb93
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
@@ -0,0 +1,42 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSTIME", unix.NOTE_ABSTIME},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CLOSE", unix.NOTE_CLOSE},
+	{"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FILE_POLL", unix.NOTE_FILE_POLL},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MSECONDS", unix.NOTE_MSECONDS},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OPEN", unix.NOTE_OPEN},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_READ", unix.NOTE_READ},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
new file mode 100644
index 00000000..607e683b
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
@@ -0,0 +1,32 @@
+//go:build freebsd || openbsd || netbsd || dragonfly || darwin
+
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, kevent *unix.Kevent_t) {
+	mask := uint32(kevent.Fflags)
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-60s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
new file mode 100644
index 00000000..35c734be
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
@@ -0,0 +1,56 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask, cookie uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"IN_ACCESS", unix.IN_ACCESS},
+		{"IN_ATTRIB", unix.IN_ATTRIB},
+		{"IN_CLOSE", unix.IN_CLOSE},
+		{"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE},
+		{"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE},
+		{"IN_CREATE", unix.IN_CREATE},
+		{"IN_DELETE", unix.IN_DELETE},
+		{"IN_DELETE_SELF", unix.IN_DELETE_SELF},
+		{"IN_IGNORED", unix.IN_IGNORED},
+		{"IN_ISDIR", unix.IN_ISDIR},
+		{"IN_MODIFY", unix.IN_MODIFY},
+		{"IN_MOVE", unix.IN_MOVE},
+		{"IN_MOVED_FROM", unix.IN_MOVED_FROM},
+		{"IN_MOVED_TO", unix.IN_MOVED_TO},
+		{"IN_MOVE_SELF", unix.IN_MOVE_SELF},
+		{"IN_OPEN", unix.IN_OPEN},
+		{"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW},
+		{"IN_UNMOUNT", unix.IN_UNMOUNT},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	var c string
+	if cookie > 0 {
+		c = fmt.Sprintf("(cookie: %d) ", cookie)
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-30s → %s%q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name)
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
new file mode 100644
index 00000000..e5b3b6f6
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
@@ -0,0 +1,25 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
new file mode 100644
index 00000000..1dd455bc
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
@@ -0,0 +1,28 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	// {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386?
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EOF", unix.NOTE_EOF},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRUNCATE", unix.NOTE_TRUNCATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
new file mode 100644
index 00000000..f1b2e73b
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask int32) {
+	names := []struct {
+		n string
+		m int32
+	}{
+		{"FILE_ACCESS", unix.FILE_ACCESS},
+		{"FILE_MODIFIED", unix.FILE_MODIFIED},
+		{"FILE_ATTRIB", unix.FILE_ATTRIB},
+		{"FILE_TRUNC", unix.FILE_TRUNC},
+		{"FILE_NOFOLLOW", unix.FILE_NOFOLLOW},
+		{"FILE_DELETE", unix.FILE_DELETE},
+		{"FILE_RENAME_TO", unix.FILE_RENAME_TO},
+		{"FILE_RENAME_FROM", unix.FILE_RENAME_FROM},
+		{"UNMOUNTED", unix.UNMOUNTED},
+		{"MOUNTEDOVER", unix.MOUNTEDOVER},
+		{"FILE_EXCEPTION", unix.FILE_EXCEPTION},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-30s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
new file mode 100644
index 00000000..52bf4ce5
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
@@ -0,0 +1,40 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/windows"
+)
+
+func Debug(name string, mask uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED},
+		{"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED},
+		{"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED},
+		{"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME},
+		{"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-65s → %q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name))
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
new file mode 100644
index 00000000..547df1df
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
@@ -0,0 +1,31 @@
+//go:build freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) }
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go
new file mode 100644
index 00000000..7daa45e1
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go
@@ -0,0 +1,2 @@
+// Package internal contains some helpers.
+package internal
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go
new file mode 100644
index 00000000..30976ce9
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go
@@ -0,0 +1,31 @@
+//go:build !windows && !darwin && !freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
new file mode 100644
index 00000000..37dfeddc
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
@@ -0,0 +1,7 @@
+//go:build !windows
+
+package internal
+
+func HasPrivilegesForSymlink() bool {
+	return true
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/history-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go
new file mode 100644
index 00000000..a72c6495
--- /dev/null
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go
@@ -0,0 +1,41 @@
+//go:build windows
+
+package internal
+
+import (
+	"errors"
+
+	"golang.org/x/sys/windows"
+)
+
+// Just a dummy.
+var (
+	SyscallEACCES = errors.New("dummy")
+	UnixEACCES    = errors.New("dummy")
+)
+
+func SetRlimit()                                    {}
+func Maxfiles() uint64                              { return 1<<64 - 1 }
+func Mkfifo(path string, mode uint32) error         { return errors.New("no FIFOs on Windows") }
+func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") }
+
+func HasPrivilegesForSymlink() bool {
+	var sid *windows.SID
+	err := windows.AllocateAndInitializeSid(
+		&windows.SECURITY_NT_AUTHORITY,
+		2,
+		windows.SECURITY_BUILTIN_DOMAIN_RID,
+		windows.DOMAIN_ALIAS_RID_ADMINS,
+		0, 0, 0, 0, 0, 0,
+		&sid)
+	if err != nil {
+		return false
+	}
+	defer windows.FreeSid(sid)
+	token := windows.Token(0)
+	member, err := token.IsMember(sid)
+	if err != nil {
+		return false
+	}
+	return member || token.IsElevated()
+}
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/history-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
deleted file mode 100644
index b09ef768..00000000
--- a/history-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env zsh
-[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1
-setopt err_exit no_unset pipefail extended_glob
-
-# Simple script to update the godoc comments on all watchers. Probably took me
-# more time to write this than doing it manually, but ah well 🙃
-
-watcher=$(</tmp/x
-		print -r -- $cmt                >>/tmp/x
-		tail -n+$(( end + 1 ))   $file  >>/tmp/x
-		mv /tmp/x $file
-	done
-}
-
-set-cmt '^type Watcher struct '             $watcher
-set-cmt '^func NewWatcher('                 $new
-set-cmt '^func (w \*Watcher) Add('          $add
-set-cmt '^func (w \*Watcher) Remove('       $remove
-set-cmt '^func (w \*Watcher) Close('        $close
-set-cmt '^func (w \*Watcher) WatchList('    $watchlist
-set-cmt '^[[:space:]]*Events *chan Event$'  $events
-set-cmt '^[[:space:]]*Errors *chan error$'  $errors
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/history-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
index 4322b0b8..f65e8fe3 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd || openbsd || netbsd || dragonfly
-// +build freebsd openbsd netbsd dragonfly
 
 package fsnotify
 
diff --git a/history-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/history-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
index 5da5ffa7..a29fc7aa 100644
--- a/history-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
+++ b/history-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
@@ -1,5 +1,4 @@
 //go:build darwin
-// +build darwin
 
 package fsnotify
 
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/history-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
index 1f664d13..faef0c91 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
@@ -16,3 +16,6 @@ indent_style = tab
 
 [*.nix]
 indent_size = 2
+
+[.golangci.yaml]
+indent_size = 2
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/history-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
index 763143aa..bda96256 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
@@ -1,23 +1,48 @@
-run:
-  timeout: 5m
+version: "2"
 
-linters-settings:
-  gci:
-    sections:
-      - standard
-      - default
-      - prefix(github.com/go-viper/mapstructure)
-  golint:
-    min-confidence: 0
-  goimports:
-    local-prefixes: github.com/go-viper/maptstructure
+run:
+  timeout: 10m
 
 linters:
-  disable-all: true
+  enable:
+    - govet
+    - ineffassign
+    # - misspell
+    - nolintlint
+    # - revive
+
+  disable:
+    - errcheck
+    - staticcheck
+    - unused
+
+  settings:
+    misspell:
+      locale: US
+    nolintlint:
+      allow-unused: false # report any unused nolint directives
+      require-specific: false # don't require nolint directives to be specific about which linter is being skipped
+
+formatters:
   enable:
     - gci
     - gofmt
     - gofumpt
     - goimports
-    - staticcheck
-    # - stylecheck
+    # - golines
+
+  settings:
+    gci:
+      sections:
+        - standard
+        - default
+        - localmodule
+    gofmt:
+      simplify: true
+      rewrite-rules:
+        - pattern: interface{}
+          replacement: any
+
+  exclusions:
+    paths:
+      - internal/
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/README.md b/history-api/vendor/github.com/go-viper/mapstructure/v2/README.md
index dd5ec69d..45db7197 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/README.md
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/README.md
@@ -1,8 +1,9 @@
 # mapstructure
 
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
 [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square)
+![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)
 
 mapstructure is a Go library for decoding generic map values to structures
 and vice versa, while providing helpful error handling.
@@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else.
 Here is a script that can help you with the migration:
 
 ```shell
-sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go')
+sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go')
 ```
 
 If you need more time to migrate your code, that is absolutely fine.
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/history-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
index 1f3c69d4..a852a0a0 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
@@ -13,7 +13,7 @@ import (
 	"time"
 )
 
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
 func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	// Create variables here so we can reference them with the reflect pkg
@@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 
 	// Fill in the variables into this interface and the rest is done
 	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
+	potential := []any{f1, f2, f3}
 
 	v := reflect.ValueOf(h)
 	vt := v.Type()
@@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	return nil
 }
 
-// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into a closure to be used directly
 // if the type fails to convert we return a closure always erroring to keep the previous behaviour
-func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) {
+func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Type(), to.Type(), from.Interface())
 		}
 	case DecodeHookFuncKind:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Kind(), to.Kind(), from.Interface())
 		}
 	case DecodeHookFuncValue:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from, to)
 		}
 	default:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return nil, errors.New("invalid decode hook signature")
 		}
 	}
@@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
 func DecodeHookExec(
 	raw DecodeHookFunc,
 	from reflect.Value, to reflect.Value,
-) (interface{}, error) {
+) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
 		return f(from.Type(), to.Type(), from.Interface())
@@ -86,11 +86,11 @@ func DecodeHookExec(
 // The composed funcs are called in order, with the result of the
 // previous transformation.
 func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs))
 	for _, f := range fs {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		var err error
 		data := f.Interface()
 
@@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 			if err != nil {
 				return nil, err
 			}
-			newFrom = reflect.ValueOf(data)
+			if v, ok := data.(reflect.Value); ok {
+				newFrom = v
+			} else {
+				newFrom = reflect.ValueOf(data)
+			}
 		}
 
 		return data, nil
@@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
 // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
 func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff))
 	for _, f := range ff {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(a, b reflect.Value) (interface{}, error) {
+	return func(a, b reflect.Value) (any, error) {
 		var allErrs string
-		var out interface{}
+		var out any
 		var err error
 
 		for _, c := range cached {
@@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	}
 }
 
+// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
+//
+// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
+// This function removes that check.
+func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
 // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
 // strings to time.Duration.
 func StringToTimeDurationHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.ParseDuration(data.(string))
+		d, err := time.ParseDuration(data.(string))
+
+		return d, wrapTimeParseDurationError(err)
+	}
+}
+
+// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
+// strings to *time.Location.
+func StringToTimeLocationHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(time.Local) {
+			return data, nil
+		}
+		d, err := time.LoadLocation(data.(string))
+
+		return d, wrapTimeParseLocationError(err)
 	}
 }
 
@@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return url.Parse(data.(string))
+		u, err := url.Parse(data.(string))
+
+		return u, wrapUrlError(err)
 	}
 }
 
@@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc {
 		// Convert it by parsing
 		ip := net.ParseIP(data.(string))
 		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
+			return net.IP{}, fmt.Errorf("failed parsing ip")
 		}
 
 		return ip, nil
@@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 
 		// Convert it by parsing
 		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
+		return net, wrapNetParseError(err)
 	}
 }
 
@@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.Parse(layout, data.(string))
+		ti, err := time.Parse(layout, data.(string))
+
+		return ti, wrapTimeParseError(err)
 	}
 }
 
@@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 func WeaklyTypedHook(
 	f reflect.Kind,
 	t reflect.Kind,
-	data interface{},
-) (interface{}, error) {
+	data any,
+) (any, error) {
 	dataVal := reflect.ValueOf(data)
 	switch t {
 	case reflect.String:
@@ -301,17 +354,17 @@ func WeaklyTypedHook(
 }
 
 func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		if f.Kind() != reflect.Struct {
 			return f.Interface(), nil
 		}
 
-		var i interface{} = struct{}{}
+		var i any = struct{}{}
 		if t.Type() != reflect.TypeOf(&i).Elem() {
 			return f.Interface(), nil
 		}
 
-		m := make(map[string]interface{})
+		m := make(map[string]any)
 		t.Set(reflect.ValueOf(m))
 
 		return f.Interface(), nil
@@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddr(data.(string))
+		addr, err := netip.ParseAddr(data.(string))
+
+		return addr, wrapNetIPParseAddrError(err)
 	}
 }
 
@@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddrPort(data.(string))
+		addrPort, err := netip.ParseAddrPort(data.(string))
+
+		return addrPort, wrapNetIPParseAddrPortError(err)
+	}
+}
+
+// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts
+// strings to netip.Prefix.
+func StringToNetIPPrefixHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(netip.Prefix{}) {
+			return data, nil
+		}
+
+		// Convert it by parsing
+		prefix, err := netip.ParsePrefix(data.(string))
+
+		return prefix, wrapNetIPParsePrefixError(err)
 	}
 }
 
@@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc {
 // StringToInt8HookFunc returns a DecodeHookFunc that converts
 // strings to int8.
 func StringToInt8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 8)
-		return int8(i64), err
+		return int8(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint8HookFunc returns a DecodeHookFunc that converts
 // strings to uint8.
 func StringToUint8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 8)
-		return uint8(u64), err
+		return uint8(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt16HookFunc returns a DecodeHookFunc that converts
 // strings to int16.
 func StringToInt16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 16)
-		return int16(i64), err
+		return int16(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint16HookFunc returns a DecodeHookFunc that converts
 // strings to uint16.
 func StringToUint16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 16)
-		return uint16(u64), err
+		return uint16(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt32HookFunc returns a DecodeHookFunc that converts
 // strings to int32.
 func StringToInt32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 32)
-		return int32(i64), err
+		return int32(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint32HookFunc returns a DecodeHookFunc that converts
 // strings to uint32.
 func StringToUint32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 32)
-		return uint32(u64), err
+		return uint32(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt64HookFunc returns a DecodeHookFunc that converts
 // strings to int64.
 func StringToInt64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseInt(data.(string), 0, 64)
+		i64, err := strconv.ParseInt(data.(string), 0, 64)
+		return int64(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint64HookFunc returns a DecodeHookFunc that converts
 // strings to uint64.
 func StringToUint64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseUint(data.(string), 0, 64)
+		u64, err := strconv.ParseUint(data.(string), 0, 64)
+		return uint64(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToIntHookFunc returns a DecodeHookFunc that converts
 // strings to int.
 func StringToIntHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 0)
-		return int(i64), err
+		return int(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUintHookFunc returns a DecodeHookFunc that converts
 // strings to uint.
 func StringToUintHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 0)
-		return uint(u64), err
+		return uint(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat32HookFunc returns a DecodeHookFunc that converts
 // strings to float32.
 func StringToFloat32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		f64, err := strconv.ParseFloat(data.(string), 32)
-		return float32(f64), err
+		return float32(f64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat64HookFunc returns a DecodeHookFunc that converts
 // strings to float64.
 func StringToFloat64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseFloat(data.(string), 64)
+		f64, err := strconv.ParseFloat(data.(string), 64)
+		return f64, wrapStrconvNumError(err)
 	}
 }
 
 // StringToBoolHookFunc returns a DecodeHookFunc that converts
 // strings to bool.
 func StringToBoolHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseBool(data.(string))
+		b, err := strconv.ParseBool(data.(string))
+		return b, wrapStrconvNumError(err)
 	}
 }
 
@@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc {
 // StringToComplex64HookFunc returns a DecodeHookFunc that converts
 // strings to complex64.
 func StringToComplex64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		c128, err := strconv.ParseComplex(data.(string), 64)
-		return complex64(c128), err
+		return complex64(c128), wrapStrconvNumError(err)
 	}
 }
 
 // StringToComplex128HookFunc returns a DecodeHookFunc that converts
 // strings to complex128.
 func StringToComplex128HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseComplex(data.(string), 128)
+		c128, err := strconv.ParseComplex(data.(string), 128)
+		return c128, wrapStrconvNumError(err)
 	}
 }
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/errors.go b/history-api/vendor/github.com/go-viper/mapstructure/v2/errors.go
new file mode 100644
index 00000000..07d31c22
--- /dev/null
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/errors.go
@@ -0,0 +1,244 @@
+package mapstructure
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// Error interface is implemented by all errors emitted by mapstructure.
+//
+// Use [errors.As] to check if an error implements this interface.
+type Error interface {
+	error
+
+	mapstructure()
+}
+
+// DecodeError is a generic error type that holds information about
+// a decoding error together with the name of the field that caused the error.
+type DecodeError struct {
+	name string
+	err  error
+}
+
+func newDecodeError(name string, err error) *DecodeError {
+	return &DecodeError{
+		name: name,
+		err:  err,
+	}
+}
+
+func (e *DecodeError) Name() string {
+	return e.name
+}
+
+func (e *DecodeError) Unwrap() error {
+	return e.err
+}
+
+func (e *DecodeError) Error() string {
+	return fmt.Sprintf("'%s' %s", e.name, e.err)
+}
+
+func (*DecodeError) mapstructure() {}
+
+// ParseError is an error type that indicates a value could not be parsed
+// into the expected type.
+type ParseError struct {
+	Expected reflect.Value
+	Value    any
+	Err      error
+}
+
+func (e *ParseError) Error() string {
+	return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err)
+}
+
+func (*ParseError) mapstructure() {}
+
+// UnconvertibleTypeError is an error type that indicates a value could not be
+// converted to the expected type.
+type UnconvertibleTypeError struct {
+	Expected reflect.Value
+	Value    any
+}
+
+func (e *UnconvertibleTypeError) Error() string {
+	return fmt.Sprintf(
+		"expected type '%s', got unconvertible type '%s'",
+		e.Expected.Type(),
+		reflect.TypeOf(e.Value),
+	)
+}
+
+func (*UnconvertibleTypeError) mapstructure() {}
+
+func wrapStrconvNumError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*strconv.NumError); ok {
+		return &strconvNumError{Err: err}
+	}
+
+	return err
+}
+
+type strconvNumError struct {
+	Err *strconv.NumError
+}
+
+func (e *strconvNumError) Error() string {
+	return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
+}
+
+func (e *strconvNumError) Unwrap() error { return e.Err }
+
+func wrapUrlError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*url.Error); ok {
+		return &urlError{Err: err}
+	}
+
+	return err
+}
+
+type urlError struct {
+	Err *url.Error
+}
+
+func (e *urlError) Error() string {
+	return fmt.Sprintf("%s", e.Err.Err)
+}
+
+func (e *urlError) Unwrap() error { return e.Err }
+
+func wrapNetParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*net.ParseError); ok {
+		return &netParseError{Err: err}
+	}
+
+	return err
+}
+
+type netParseError struct {
+	Err *net.ParseError
+}
+
+func (e *netParseError) Error() string {
+	return "invalid " + e.Err.Type
+}
+
+func (e *netParseError) Unwrap() error { return e.Err }
+
+func wrapTimeParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*time.ParseError); ok {
+		return &timeParseError{Err: err}
+	}
+
+	return err
+}
+
+type timeParseError struct {
+	Err *time.ParseError
+}
+
+func (e *timeParseError) Error() string {
+	if e.Err.Message == "" {
+		return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
+	}
+
+	return "parsing time " + e.Err.Message
+}
+
+func (e *timeParseError) Unwrap() error { return e.Err }
+
+func wrapNetIPParseAddrError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapNetIPParseAddrPortError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "invalid port ") {
+		return errors.New("invalid port")
+	} else if strings.HasPrefix(errMsg, "invalid ip:port ") {
+		return errors.New("invalid ip:port")
+	}
+
+	return err
+}
+
+func wrapNetIPParsePrefixError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapTimeParseDurationError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "time: unknown unit ") {
+		return errors.New("time: unknown unit")
+	} else if strings.HasPrefix(errMsg, "time: ") {
+		idx := strings.LastIndex(errMsg, " ")
+
+		return errors.New(errMsg[:idx])
+	}
+
+	return err
+}
+
+func wrapTimeParseLocationError(err error) error {
+	if err == nil {
+		return nil
+	}
+	errMsg := err.Error()
+	if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
+		return fmt.Errorf("invalid time zone format: %w", err)
+	}
+
+	return err
+}
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
index 4bea8154..5e67bdd6 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
@@ -2,30 +2,28 @@
   "nodes": {
     "cachix": {
       "inputs": {
-        "devenv": "devenv_2",
+        "devenv": [
+          "devenv"
+        ],
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "git-hooks": [
+          "devenv"
         ],
-        "pre-commit-hooks": [
-          "devenv",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs"
       },
       "locked": {
-        "lastModified": 1712055811,
-        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "lastModified": 1742042642,
+        "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
         "owner": "cachix",
         "repo": "cachix",
-        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "latest",
         "repo": "cachix",
         "type": "github"
       }
@@ -33,52 +31,21 @@
     "devenv": {
       "inputs": {
         "cachix": "cachix",
-        "flake-compat": "flake-compat_2",
-        "nix": "nix_2",
-        "nixpkgs": "nixpkgs_2",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1717245169,
-        "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "devenv_2": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "cachix",
-          "flake-compat"
-        ],
+        "flake-compat": "flake-compat",
+        "git-hooks": "git-hooks",
         "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "poetry2nix": "poetry2nix",
-        "pre-commit-hooks": [
-          "devenv",
-          "cachix",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs_3"
       },
       "locked": {
-        "lastModified": 1708704632,
-        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
+        "lastModified": 1744876578,
+        "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
+        "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
-        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -86,27 +53,11 @@
     "flake-compat": {
       "flake": false,
       "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-compat_2": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "lastModified": 1733328505,
+        "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
         "type": "github"
       },
       "original": {
@@ -117,14 +68,18 @@
     },
     "flake-parts": {
       "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
+        "nixpkgs-lib": [
+          "devenv",
+          "nix",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1717285511,
-        "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
+        "lastModified": 1712014858,
+        "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
+        "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
         "type": "github"
       },
       "original": {
@@ -133,39 +88,46 @@
         "type": "github"
       }
     },
-    "flake-utils": {
+    "flake-parts_2": {
       "inputs": {
-        "systems": "systems"
+        "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1689068808,
-        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "lastModified": 1743550720,
+        "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "c621e8422220273271f52058f618c94e405bb0f5",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
         "type": "github"
       }
     },
-    "flake-utils_2": {
+    "git-hooks": {
       "inputs": {
-        "systems": "systems_2"
+        "flake-compat": [
+          "devenv"
+        ],
+        "gitignore": "gitignore",
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1710146030,
-        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "lastModified": 1742649964,
+        "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
         "type": "github"
       }
     },
@@ -173,7 +135,7 @@
       "inputs": {
         "nixpkgs": [
           "devenv",
-          "pre-commit-hooks",
+          "git-hooks",
           "nixpkgs"
         ]
       },
@@ -191,166 +153,109 @@
         "type": "github"
       }
     },
-    "nix": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "devenv-2.21",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nix-github-actions": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "poetry2nix",
-          "nixpkgs"
-        ]
-      },
+    "libgit2": {
+      "flake": false,
       "locked": {
-        "lastModified": 1688870561,
-        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
-        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "lastModified": 1697646580,
+        "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
+        "owner": "libgit2",
+        "repo": "libgit2",
+        "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
         "type": "github"
       },
       "original": {
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
+        "owner": "libgit2",
+        "repo": "libgit2",
         "type": "github"
       }
     },
-    "nix_2": {
+    "nix": {
       "inputs": {
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "flake-parts": "flake-parts",
+        "libgit2": "libgit2",
+        "nixpkgs": "nixpkgs_2",
+        "nixpkgs-23-11": [
+          "devenv"
+        ],
+        "nixpkgs-regression": [
+          "devenv"
         ],
-        "nixpkgs-regression": "nixpkgs-regression_2"
+        "pre-commit-hooks": [
+          "devenv"
+        ]
       },
       "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "lastModified": 1741798497,
+        "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
+        "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "devenv-2.21",
+        "ref": "devenv-2.24",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1692808169,
-        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
+        "lastModified": 1733212471,
+        "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
+        "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
+        "ref": "nixos-unstable",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs-lib": {
       "locked": {
-        "lastModified": 1717284937,
-        "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      },
-      "original": {
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression_2": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "lastModified": 1743296961,
+        "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
+        "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
         "type": "github"
       },
       "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
         "type": "github"
       }
     },
-    "nixpkgs-stable": {
+    "nixpkgs_2": {
       "locked": {
-        "lastModified": 1710695816,
-        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
+        "lastModified": 1717432640,
+        "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
+        "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.11",
+        "ref": "release-24.05",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "nixpkgs_2": {
+    "nixpkgs_3": {
       "locked": {
-        "lastModified": 1713361204,
-        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "lastModified": 1733477122,
+        "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
         "owner": "cachix",
         "repo": "devenv-nixpkgs",
-        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
         "type": "github"
       },
       "original": {
@@ -360,13 +265,13 @@
         "type": "github"
       }
     },
-    "nixpkgs_3": {
+    "nixpkgs_4": {
       "locked": {
-        "lastModified": 1717112898,
-        "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=",
+        "lastModified": 1744536153,
+        "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0",
+        "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
         "type": "github"
       },
       "original": {
@@ -376,94 +281,11 @@
         "type": "github"
       }
     },
-    "poetry2nix": {
-      "inputs": {
-        "flake-utils": "flake-utils",
-        "nix-github-actions": "nix-github-actions",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1692876271,
-        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils_2",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1713775815,
-        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
     "root": {
       "inputs": {
         "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_3"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
+        "flake-parts": "flake-parts_2",
+        "nixpkgs": "nixpkgs_4"
       }
     }
   },
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
index 4ed0f533..3b116f42 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
@@ -5,35 +5,42 @@
     devenv.url = "github:cachix/devenv";
   };
 
-  outputs = inputs@{ flake-parts, ... }:
+  outputs =
+    inputs@{ flake-parts, ... }:
     flake-parts.lib.mkFlake { inherit inputs; } {
       imports = [
         inputs.devenv.flakeModule
       ];
 
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
+      systems = [
+        "x86_64-linux"
+        "x86_64-darwin"
+        "aarch64-darwin"
+      ];
 
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-            };
+      perSystem =
+        { pkgs, ... }:
+        rec {
+          devenv.shells = {
+            default = {
+              languages = {
+                go.enable = true;
+              };
 
-            pre-commit.hooks = {
-              nixpkgs-fmt.enable = true;
-            };
+              pre-commit.hooks = {
+                nixpkgs-fmt.enable = true;
+              };
 
-            packages = with pkgs; [
-              golangci-lint
-            ];
+              packages = with pkgs; [
+                golangci-lint
+              ];
 
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
+              # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
+              containers = pkgs.lib.mkForce { };
+            };
 
-          ci = devenv.shells.default;
+            ci = devenv.shells.default;
+          };
         };
-      };
     };
 }
diff --git a/history-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/history-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
index e77e63ba..7c35bce0 100644
--- a/history-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
+++ b/history-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
@@ -1,5 +1,5 @@
 // Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
+// Go type into another, typically to convert a map[string]any
 // into a native Go structure.
 //
 // The Go structure can be arbitrarily complex, containing slices,
@@ -54,8 +54,8 @@
 //
 // This would require an input that looks like below:
 //
-//	map[string]interface{}{
-//	    "person": map[string]interface{}{"name": "alice"},
+//	map[string]any{
+//	    "person": map[string]any{"name": "alice"},
 //	}
 //
 // If your "person" value is NOT nested, then you can append ",squash" to
@@ -68,7 +68,7 @@
 //
 // Now the following input would be accepted:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -79,7 +79,7 @@
 //
 // Will be decoded into a map:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -95,18 +95,18 @@
 //
 // You can also use the ",remain" suffix on your tag to collect all unused
 // values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
+// probably be a "map[string]any" or "map[any]any".
 // See example below:
 //
 //	type Friend struct {
 //	    Name  string
-//	    Other map[string]interface{} `mapstructure:",remain"`
+//	    Other map[string]any `mapstructure:",remain"`
 //	}
 //
 // Given the input below, Other would be populated with the other
 // values that weren't used (everything but "name"):
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name":    "bob",
 //	    "address": "123 Maple St.",
 //	}
@@ -115,15 +115,36 @@
 //
 // When decoding from a struct to any other value, you may use the
 // ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
+// the zero value, or a zero-length element. The zero value of all types is
+// specified in the Go specification.
 //
 // For example, the zero type of a numeric type is zero ("0"). If the struct
 // field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil or empty, it won't be encoded into the destination type.
 //
 //	type Source struct {
-//	    Age int `mapstructure:",omitempty"`
+//	    Age  int      `mapstructure:",omitempty"`
+//	    URLs []string `mapstructure:",omitempty"`
+//	}
+//
+// # Omit Zero Values
+//
+// When decoding from a struct to any other value, you may use the
+// ",omitzero" suffix on your tag to omit that value if it equates to the zero
+// value. The zero value of all types is specified in the Go specification.
+//
+// For example, the zero type of a numeric type is zero ("0"). If the struct
+// field value is zero and a numeric type, the field is empty, and it won't
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil, it won't be encoded into the destination type.
+//
+// Note that if the field is a slice, and it is empty but not nil, it will
+// still be encoded into the destination type.
+//
+//	type Source struct {
+//	    Age  int      `mapstructure:",omitzero"`
+//	    URLs []string `mapstructure:",omitzero"`
 //	}
 //
 // # Unexported fields
@@ -140,7 +161,7 @@
 //
 // Using this map as input:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "private": "I will be ignored",
 //	    "Public":  "I made it through!",
 //	}
@@ -183,19 +204,19 @@ import (
 // we started with Kinds and then realized Types were the better solution,
 // but have a promise to not break backwards compat so we now support
 // both.
-type DecodeHookFunc interface{}
+type DecodeHookFunc any
 
 // DecodeHookFuncType is a DecodeHookFunc which has complete information about
 // the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
+type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
 
 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
 // source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
+type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
 
 // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
 // values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
+type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
 
 // DecoderConfig is the configuration that is used to create a new decoder
 // and allows customization of various aspects of decoding.
@@ -222,6 +243,12 @@ type DecoderConfig struct {
 	// will affect all nested structs as well.
 	ErrorUnset bool
 
+	// AllowUnsetPointer, if set to true, will prevent fields with pointer types
+	// from being reported as unset, even if ErrorUnset is true and the field was
+	// not present in the input data. This allows pointer fields to be optional
+	// without triggering an error when they are missing.
+	AllowUnsetPointer bool
+
 	// ZeroFields, if set to true, will zero fields before writing them.
 	// For example, a map will be emptied before decoded values are put in
 	// it. If this is false, a map will be merged.
@@ -260,7 +287,7 @@ type DecoderConfig struct {
 
 	// Result is a pointer to the struct that will contain the decoded
 	// value.
-	Result interface{}
+	Result any
 
 	// The tag name that mapstructure reads for field names. This
 	// defaults to "mapstructure"
@@ -292,7 +319,7 @@ type DecoderConfig struct {
 // up the most basic Decoder.
 type Decoder struct {
 	config           *DecoderConfig
-	cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
+	cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
 }
 
 // Metadata contains information about decoding a structure that
@@ -313,7 +340,7 @@ type Metadata struct {
 
 // Decode takes an input structure and uses reflection to translate it to
 // the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
+func Decode(input any, output any) error {
 	config := &DecoderConfig{
 		Metadata: nil,
 		Result:   output,
@@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error {
 
 // WeakDecode is the same as Decode but is shorthand to enable
 // WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
+func WeakDecode(input, output any) error {
 	config := &DecoderConfig{
 		Metadata:         nil,
 		Result:           output,
@@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error {
 
 // DecodeMetadata is the same as Decode, but is shorthand to
 // enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func DecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata: metadata,
 		Result:   output,
@@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e
 // WeakDecodeMetadata is the same as Decode, but is shorthand to
 // enable both WeaklyTypedInput and metadata collection. See
 // DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata:         metadata,
 		Result:           output,
@@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
 
 // Decode decodes the given raw interface to the target pointer specified
 // by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
+func (d *Decoder) Decode(input any) error {
 	err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
 
 	// Retain some of the original behavior when multiple errors ocurr
@@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error {
 }
 
 // isNil returns true if the input is nil or a typed nil pointer.
-func isNil(input interface{}) bool {
+func isNil(input any) bool {
 	if input == nil {
 		return true
 	}
@@ -452,7 +479,7 @@ func isNil(input interface{}) bool {
 }
 
 // Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
+func (d *Decoder) decode(name string, input any, outVal reflect.Value) error {
 	var (
 		inputVal   = reflect.ValueOf(input)
 		outputKind = getKind(outVal)
@@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		// Hooks need a valid inputVal, so reset it to zero value of outVal type.
 		switch outputKind {
 		case reflect.Struct, reflect.Map:
-			var mapVal map[string]interface{}
+			var mapVal map[string]any
 			inputVal = reflect.ValueOf(mapVal) // create nil map pointer
 		case reflect.Slice, reflect.Array:
-			var sliceVal []interface{}
+			var sliceVal []any
 			inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
 		default:
 			inputVal = reflect.Zero(outVal.Type())
@@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		var err error
 		input, err = d.cachedDecodeHook(inputVal, outVal)
 		if err != nil {
-			return fmt.Errorf("error decoding '%s': %w", name, err)
+			return newDecodeError(name, err)
 		}
 	}
 	if isNil(input) {
@@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		err = d.decodeFunc(name, input, outVal)
 	default:
 		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
+		return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind))
 	}
 
 	// If we reached here, then we successfully decoded SOMETHING, so
@@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 
 // This decodes a basic type (bool, int, string, etc.) and sets the
 // value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
 	if val.IsValid() && val.Elem().IsValid() {
 		elem := val.Elem()
 
@@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value)
 
 	dataValType := dataVal.Type()
 	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
 	}
 
 	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
 		if err == nil {
 			val.SetInt(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Int64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetInt(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Int:
 		i := dataVal.Int()
 		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%d overflows uint", i),
+			})
 		}
 		val.SetUint(uint64(i))
 	case dataKind == reflect.Uint:
@@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Float32:
 		f := dataVal.Float()
 		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%f overflows uint", f),
+			})
 		}
 		val.SetUint(uint64(f))
 	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
@@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		if err == nil {
 			val.SetUint(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := strconv.ParseUint(string(jn), 0, 64)
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 		val.SetUint(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
 		} else if dataVal.String() == "" {
 			val.SetBool(false)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'",
-			name, val, dataVal, data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
 		if err == nil {
 			val.SetFloat(f)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Float64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetFloat(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value
 	case dataKind == reflect.Complex64:
 		val.SetComplex(dataVal.Complex())
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
 	valType := val.Type()
 	valKeyType := valType.Key()
 	valElemType := valType.Elem()
@@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
 		fallthrough
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 }
 
@@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 		// to the map value.
 		v := dataVal.Field(i)
 		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
+			return newDecodeError(
+				name+"."+f.Name,
+				fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()),
+			)
 		}
 
 		tagValue := f.Tag.Get(d.config.TagName)
@@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 				continue
 			}
 
+			// If "omitzero" is specified in the tag, it ignores zero values.
+			if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() {
+				continue
+			}
+
 			// If "squash" is specified in the tag, we squash the field down.
 			squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
 			if squash {
@@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 
 				// The final type must be a struct
 				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
+					return newDecodeError(
+						name+"."+f.Name,
+						fmt.Errorf("cannot squash non-struct type %q", v.Type()),
+					)
 				}
 			} else {
 				if strings.Index(tagValue[index+1:], "remain") != -1 {
 					if v.Kind() != reflect.Map {
-						return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type())
+						return newDecodeError(
+							name+"."+f.Name,
+							fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()),
+						)
 					}
 
 					ptr := v.MapRange()
@@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 	return nil
 }
 
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
+func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
 	// If the input data is nil, then we want to just set the output
 	// pointer to be nil as well.
 	isNil := data == nil
@@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
 	return false, nil
 }
 
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error {
 	// Create an element of the concrete (non pointer) type and decode
 	// into that. Then set the value of the pointer to this type.
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 					return nil
 				}
 				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 
 			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
 				return d.decodeSlice(name, []byte(dataVal.String()), val)
@@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 			// and "lift" it into it. i.e. a string becomes a string slice.
 			default:
 				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 			}
 		}
 
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
+		return newDecodeError(name,
+			fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 	}
 
 	// If the input value is nil, then don't allocate since empty != nil
@@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 				// and "lift" it into it. i.e. a string becomes a string array.
 				default:
 					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
+					return d.decodeArray(name, []any{data}, val)
 				}
 			}
 
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
+			return newDecodeError(name,
+				fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 
 		}
 		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
+			return newDecodeError(name,
+				fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len()))
 		}
 
 		// Make a new array to hold our result, same size as the original data.
@@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 
 	// If the type of the value to write to and the data match directly,
@@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		// as an intermediary.
 
 		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
+		mapType := reflect.TypeOf((map[string]any)(nil))
 		mval := reflect.MakeMap(mapType)
 
 		// Creating a pointer to a map so that other methods can completely
@@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		return result
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name,
+			fmt.Errorf("expected a map or struct, got %q", dataValKind))
 	}
 }
 
 func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
 	dataValType := dataVal.Type()
 	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
+		return newDecodeError(name,
+			fmt.Errorf("needs a map with string keys, has %q keys", kind))
 	}
 
 	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
+	dataValKeysUnused := make(map[any]struct{})
 	for _, dataValKey := range dataVal.MapKeys() {
 		dataValKeys[dataValKey] = struct{}{}
 		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
 	}
 
-	targetValKeysUnused := make(map[interface{}]struct{})
+	targetValKeysUnused := make(map[any]struct{})
 
 	var errs []error
 
@@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 						structs = append(structs, fieldVal.Elem().Elem())
 					}
 				default:
-					errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
+					errs = append(errs, newDecodeError(
+						name+"."+fieldType.Name,
+						fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()),
+					))
 				}
 				continue
 			}
@@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 			if !rawMapVal.IsValid() {
 				// There was no matching key in the map for the value in
 				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
+				if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) {
+					targetValKeysUnused[fieldName] = struct{}{}
+				}
 				continue
 			}
 		}
@@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 	// we put the unused keys directly into the remain field.
 	if remainField != nil && len(dataValKeysUnused) > 0 {
 		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
+		remain := map[any]any{}
 		for key := range dataValKeysUnused {
 			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
 		}
@@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
@@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if err := errors.Join(errs...); err != nil {
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
index 8766d38f..475699b5 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
@@ -13,6 +13,7 @@ go_library(
     deps = [
         "@org_golang_google_protobuf//compiler/protogen",
         "@org_golang_google_protobuf//proto",
+        "@org_golang_google_protobuf//types/descriptorpb",
         "@org_golang_google_protobuf//types/pluginpb",
     ],
 )
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
index 18c6cf07..dd476abf 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
@@ -2,18 +2,25 @@ package codegenerator
 
 import (
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/types/descriptorpb"
 	"google.golang.org/protobuf/types/pluginpb"
 )
 
 func supportedCodeGeneratorFeatures() uint64 {
-	// Enable support for optional keyword in proto3.
-	return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
+	// Enable support for Protobuf Editions
+	return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS)
+}
+
+func supportedEditions() (descriptorpb.Edition, descriptorpb.Edition) {
+	// Declare support for edition 2023 only
+	return descriptorpb.Edition_EDITION_2023, descriptorpb.Edition_EDITION_2023
 }
 
 // SetSupportedFeaturesOnPluginGen sets supported proto3 features
 // on protogen.Plugin.
 func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) {
 	gen.SupportedFeatures = supportedCodeGeneratorFeatures()
+	gen.SupportedEditionsMinimum, gen.SupportedEditionsMaximum = supportedEditions()
 }
 
 // SetSupportedFeaturesOnCodeGeneratorResponse sets supported proto3 features
@@ -21,4 +28,7 @@ func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) {
 func SetSupportedFeaturesOnCodeGeneratorResponse(resp *pluginpb.CodeGeneratorResponse) {
 	sf := supportedCodeGeneratorFeatures()
 	resp.SupportedFeatures = &sf
+	minE, maxE := supportedEditions()
+	minEN, maxEN := int32(minE.Number()), int32(maxE.Number())
+	resp.MinimumEdition, resp.MaximumEdition = &minEN, &maxEN
 }
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
index 28b6e258..84b73d08 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
@@ -19,7 +19,7 @@ go_library(
         "//internal/descriptor/openapiconfig",
         "//internal/httprule",
         "//protoc-gen-openapiv2/options",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_grpc//grpclog",
         "@org_golang_google_protobuf//compiler/protogen",
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
index 4f4a31c1..dea0605c 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
@@ -7,8 +7,8 @@ import (
 	"strings"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/apiconfig"
+	"go.yaml.in/yaml/v3"
 	"google.golang.org/protobuf/encoding/protojson"
-	"gopkg.in/yaml.v3"
 )
 
 func loadGrpcAPIServiceFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*apiconfig.GrpcAPIService, error) {
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
index d48a7c81..8b540165 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
@@ -6,8 +6,8 @@ import (
 	"os"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapiconfig"
+	"go.yaml.in/yaml/v3"
 	"google.golang.org/protobuf/encoding/protojson"
-	"gopkg.in/yaml.v3"
 )
 
 func loadOpenAPIConfigFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*openapiconfig.OpenAPIConfig, error) {
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
index 06537035..e6e48130 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
@@ -34,3 +34,20 @@ go_proto_compiler(
         "@org_golang_google_grpc//metadata:go_default_library",
     ],
 )
+
+go_proto_compiler(
+    name = "go_gen_grpc_gateway_opaque",
+    options = [
+        "paths=source_relative",
+        "use_opaque_api=true",
+    ],
+    plugin = ":protoc-gen-grpc-gateway",
+    suffix = ".pb.gw.go",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//runtime:go_default_library",
+        "//utilities:go_default_library",
+        "@org_golang_google_grpc//grpclog:go_default_library",
+        "@org_golang_google_grpc//metadata:go_default_library",
+    ],
+)
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
index 819cbf55..5a58625c 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
@@ -22,11 +22,12 @@ type generator struct {
 	registerFuncSuffix string
 	allowPatchFeature  bool
 	standalone         bool
+	useOpaqueAPI       bool
 }
 
 // New returns a new generator which generates grpc gateway files.
 func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix string,
-	allowPatchFeature, standalone bool) gen.Generator {
+	allowPatchFeature, standalone bool, useOpaqueAPI bool) gen.Generator {
 	var imports []descriptor.GoPackage
 	for _, pkgpath := range []string{
 		"context",
@@ -66,6 +67,7 @@ func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix st
 		registerFuncSuffix: registerFuncSuffix,
 		allowPatchFeature:  allowPatchFeature,
 		standalone:         standalone,
+		useOpaqueAPI:       useOpaqueAPI,
 	}
 }
 
@@ -132,6 +134,7 @@ func (g *generator) generate(file *descriptor.File) (string, error) {
 		UseRequestContext:  g.useRequestContext,
 		RegisterFuncSuffix: g.registerFuncSuffix,
 		AllowPatchFeature:  g.allowPatchFeature,
+		UseOpaqueAPI:       g.useOpaqueAPI,
 	}
 	if g.reg != nil {
 		params.OmitPackageDoc = g.reg.GetOmitPackageDoc()
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
index 80df6a0b..b647e1df 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
@@ -21,12 +21,14 @@ type param struct {
 	RegisterFuncSuffix string
 	AllowPatchFeature  bool
 	OmitPackageDoc     bool
+	UseOpaqueAPI       bool
 }
 
 type binding struct {
 	*descriptor.Binding
 	Registry          *descriptor.Registry
 	AllowPatchFeature bool
+	UseOpaqueAPI      bool
 }
 
 // GetBodyFieldPath returns the binding body's field path.
@@ -147,6 +149,7 @@ type trailerParams struct {
 	Services           []*descriptor.Service
 	UseRequestContext  bool
 	RegisterFuncSuffix string
+	UseOpaqueAPI       bool
 }
 
 func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
@@ -182,6 +185,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 					Binding:           b,
 					Registry:          reg,
 					AllowPatchFeature: p.AllowPatchFeature,
+					UseOpaqueAPI:      p.UseOpaqueAPI,
 				}); err != nil {
 					return "", err
 				}
@@ -191,6 +195,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 					Binding:           b,
 					Registry:          reg,
 					AllowPatchFeature: p.AllowPatchFeature,
+					UseOpaqueAPI:      p.UseOpaqueAPI,
 				}); err != nil {
 					return "", err
 				}
@@ -208,6 +213,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 		Services:           targetServices,
 		UseRequestContext:  p.UseRequestContext,
 		RegisterFuncSuffix: p.RegisterFuncSuffix,
+		UseOpaqueAPI:       p.UseOpaqueAPI,
 	}
 	// Local
 	if err := localTrailerTemplate.Execute(w, tp); err != nil {
@@ -335,6 +341,7 @@ func request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }}(ct
 
 	_ = template.Must(handlerTemplate.New("client-rpc-request-func").Funcs(funcMap).Parse(`
 {{ $AllowPatchFeature := .AllowPatchFeature }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{ if .HasQueryParam }}
 var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ .QueryParamFilter }}
 {{ end }}
@@ -365,20 +372,53 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 	{{printf "%s" $protoReq }}
 	{{- end }}
 	{{- if not $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(req.Body).Decode(&{{.Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path}}); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
 	}
 	{{- end }}
 	{{- if $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
 	}
+	{{- if $UseOpaqueAPI }}
+	if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 {
+			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil {
+				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+			} else {
+				protoReq.Set{{ .FieldMaskField }}(fieldMask)
+			}
+	}
+	{{- else }}
 	if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 {
 			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil {
 				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
@@ -387,6 +427,7 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 			}
 	}
 	{{- end }}
+	{{- end }}
 {{- else }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
@@ -421,19 +462,35 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 	{{- if ne "" $protoReq }}
 	{{ printf "%s" $protoReq }}
 	{{- end}}
+	{{- if $UseOpaqueAPI }}
+	converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
+	}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }})
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
 	}
+	{{- end }}
 {{- end}}
 {{- if and $enum $param.IsRepeated }}
 	s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es))
 	for i, v := range es {
 		s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path}}(v)
 	}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s)
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s
+	{{- end }}
 {{- else if $enum}}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e))
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)
+	{{- end }}
 {{- end}}
 	{{- end }}
 {{- end }}
@@ -524,6 +581,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 
 	_ = template.Must(localHandlerTemplate.New("local-client-rpc-request-func").Funcs(funcMap).Parse(`
 {{ $AllowPatchFeature := .AllowPatchFeature }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{ template "local-request-func-signature" . }} {
 	var (
 		protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
@@ -551,14 +609,47 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 	{{ printf "%s" $protoReq }}
 	{{- end }}
 	{{- if not $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(req.Body).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF)  {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	{{- end }}
+	{{- end }}
 	{{- if $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF)  {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
+	{{- if $UseOpaqueAPI }}
+	if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 {
+			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil {
+				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+			} else {
+				protoReq.Set{{ .FieldMaskField }}(fieldMask)
+			}
+	}
+	{{- else }}
 	if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 {
 			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil {
 				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
@@ -567,6 +658,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 			}
 	}
 	{{- end }}
+	{{- end }}
 {{- end }}
 {{- if .PathParams}}
 	{{- $binding := .}}
@@ -596,20 +688,36 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 	{{- $protoReq := $param.AssignableExprPrep "protoReq" $binding.Method.Service.File.GoPkg.Path -}}
 	{{- if ne "" $protoReq }}
 	{{ printf "%s" $protoReq }}
-	{{- end }}
+	{{- end}}
+	{{- if $UseOpaqueAPI }}
+	converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
+	}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }})
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q" }}, err)
 	}
+	{{- end }}
 {{- end}}
 {{- if and $enum $param.IsRepeated }}
 	s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es))
 	for i, v := range es {
 		s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}(v)
 	}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s)
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s
+	{{- end }}
 {{- else if $enum }}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e))
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)
+	{{- end }}
 {{- end }}
 	{{- end }}
 {{- end }}
@@ -689,6 +797,7 @@ func Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}Server(ctx context.Cont
 
 	trailerTemplate = template.Must(template.New("trailer").Funcs(funcMap).Parse(`
 {{ $UseRequestContext := .UseRequestContext }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{range $svc := .Services}}
 // Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}FromEndpoint is same as Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }} but
 // automatically dials to "endpoint" and closes the connection when "ctx" gets done.
@@ -782,7 +891,15 @@ type response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }} struct {
 
 func (m response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }}) XXX_ResponseBody() interface{} {
 	response := m.{{ $m.ResponseType.GetName }}
+	{{- if $UseOpaqueAPI }}
+	{{- if eq "*" $b.ResponseBody.FieldPath.String }}
+	return response
+	{{- else }}
+	return response.Get{{ $b.ResponseBody.FieldPath.String | camelIdentifier }}()
+	{{- end }}
+	{{- else }}
 	return {{ $b.ResponseBody.AssignableExpr "response" $m.Service.File.GoPkg.Path }}
+	{{- end }}
 }
 {{ end }}
 {{ end }}
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
index 086a4624..862a8fc0 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
@@ -36,6 +36,7 @@ var (
 	versionFlag                = flag.Bool("version", false, "print the current version")
 	warnOnUnboundMethods       = flag.Bool("warn_on_unbound_methods", false, "emit a warning message if an RPC method has no HttpRule annotation")
 	generateUnboundMethods     = flag.Bool("generate_unbound_methods", false, "generate proxy methods even for RPC methods that have no HttpRule annotation")
+	useOpaqueAPI               = flag.Bool("use_opaque_api", false, "generate code compatible with the new Opaque API instead of the older Open Struct API")
 
 	_ = flag.Bool("logtostderr", false, "Legacy glog compatibility. This flag is a no-op, you can safely remove it")
 )
@@ -80,7 +81,7 @@ func main() {
 
 		codegenerator.SetSupportedFeaturesOnPluginGen(gen)
 
-		generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone)
+		generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone, *useOpaqueAPI)
 
 		if grpclog.V(1) {
 			grpclog.Infof("Parsing code generator request")
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
index 7be6a90e..cef5f808 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
@@ -20,7 +20,7 @@ go_library(
         "//internal/descriptor",
         "//internal/generator",
         "//protoc-gen-openapiv2/options",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_genproto_googleapis_api//visibility",
         "@org_golang_google_genproto_googleapis_rpc//status",
@@ -59,7 +59,7 @@ go_test(
         "//protoc-gen-openapiv2/options",
         "//runtime",
         "@com_github_google_go_cmp//cmp",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_genproto_googleapis_api//visibility",
         "@org_golang_google_protobuf//encoding/protojson",
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
index 6f0faa8e..30cf7dac 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
@@ -5,7 +5,7 @@ import (
 	"errors"
 	"io"
 
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 type Format string
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
index 6795cf71..69f69b9a 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
@@ -13,6 +13,7 @@ import (
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
 	gen "github.com/grpc-ecosystem/grpc-gateway/v2/internal/generator"
 	openapioptions "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
+	"go.yaml.in/yaml/v3"
 	statuspb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/protobuf/proto"
@@ -20,7 +21,6 @@ import (
 	"google.golang.org/protobuf/types/descriptorpb"
 	"google.golang.org/protobuf/types/known/anypb"
 	"google.golang.org/protobuf/types/pluginpb"
-	"gopkg.in/yaml.v3"
 )
 
 var errNoTargetService = errors.New("no target service defined in the file")
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
index 84831c28..6265da8f 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
@@ -771,8 +771,8 @@ func filterOutExcludedFields(fields []string, excluded []descriptor.Parameter) [
 	return filtered
 }
 
-// schemaOfField returns a OpenAPI Schema Object for a protobuf field.
-func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
+// schemaOfFieldBase returns a base Schema Object for a protobuf field.
+func schemaOfFieldBase(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
 	const (
 		singular = 0
 		array    = 1
@@ -828,7 +828,7 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o
 		}
 	}
 
-	ret := openapiSchemaObject{}
+	var ret openapiSchemaObject
 
 	switch aggregate {
 	case array:
@@ -854,6 +854,12 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o
 			Properties: props,
 		}
 	}
+	return ret
+}
+
+// schemaOfField returns a OpenAPI Schema Object for a protobuf field.
+func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
+	ret := schemaOfFieldBase(f, reg, refs)
 
 	if j, err := getFieldOpenAPIOption(reg, f); err == nil {
 		updateswaggerObjectFromJSONSchema(&ret, j, reg, f)
@@ -1037,7 +1043,7 @@ func resolveFullyQualifiedNameToOpenAPINames(messages []string, namingStrategy s
 	return strategyFn(messages)
 }
 
-var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.]*)([^}]*)}")
+var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.-]*)([^}]*)}")
 
 // templateToParts splits a URL template into path segments for use by `partsToOpenAPIPath` and `partsToRegexpMap`.
 //
@@ -1534,10 +1540,17 @@ func renderServices(services []*descriptor.Service, paths *openapiPathsObject, r
 						}
 						// Align pathParams with body field path.
 						pathParams := subPathParams(bodyField.Name, b.PathParams)
-						var err error
-						schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams)
-						if err != nil {
-							return err
+
+						if len(pathParams) == 0 {
+							// When there are no path parameters, we only need the base schema of the field.
+							// https://github.com/grpc-ecosystem/grpc-gateway/issues/3058
+							schema = schemaOfFieldBase(bodyField.Target, reg, customRefs)
+						} else {
+							var err error
+							schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams)
+							if err != nil {
+								return err
+							}
 						}
 						if schema.Title != "" {
 							desc = mergeDescription(schema)
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
index 02c85784..db9be4de 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
@@ -6,7 +6,7 @@ import (
 	"fmt"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 type param struct {
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
index a65d88eb..04b4bebf 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
@@ -27,6 +27,7 @@ go_library(
         "//internal/httprule",
         "//utilities",
         "@org_golang_google_genproto_googleapis_api//httpbody",
+        "@org_golang_google_grpc//:grpc",
         "@org_golang_google_grpc//codes",
         "@org_golang_google_grpc//grpclog",
         "@org_golang_google_grpc//health/grpc_health_v1",
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
index 2f2b3424..00b2228a 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
@@ -201,13 +201,13 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
 	if timeout != 0 {
 		ctx, _ = context.WithTimeout(ctx, timeout)
 	}
-	if len(pairs) == 0 {
-		return ctx, nil, nil
-	}
 	md := metadata.Pairs(pairs...)
 	for _, mda := range mux.metadataAnnotators {
 		md = metadata.Join(md, mda(ctx, req))
 	}
+	if len(md) == 0 {
+		return ctx, nil, nil
+	}
 	return ctx, md, nil
 }
 
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
index 8376d1e0..3d070630 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
@@ -66,7 +66,7 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
 
 var (
 	// protoMessageType is stored to prevent constant lookup of the same type at runtime.
-	protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
+	protoMessageType = reflect.TypeFor[proto.Message]()
 )
 
 // marshalNonProto marshals a non-message field of a protobuf message.
@@ -325,9 +325,9 @@ type protoEnum interface {
 	EnumDescriptor() ([]byte, []int)
 }
 
-var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem()
+var typeProtoEnum = reflect.TypeFor[protoEnum]()
 
-var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
+var typeProtoMessage = reflect.TypeFor[proto.Message]()
 
 // Delimiter for newline encoded JSON streams.
 func (j *JSONPb) Delimiter() []byte {
diff --git a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
index 19255ec4..3eb16167 100644
--- a/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
+++ b/history-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule"
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/health/grpc_health_v1"
@@ -281,12 +282,19 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 			http.MethodGet, endpointPath, func(w http.ResponseWriter, r *http.Request, _ map[string]string,
 			) {
 				_, outboundMarshaler := MarshalerForRequest(s, r)
+				annotatedContext, err := AnnotateContext(r.Context(), s, r, grpc_health_v1.Health_Check_FullMethodName, WithHTTPPathPattern(endpointPath))
+				if err != nil {
+					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					return
+				}
 
-				resp, err := healthCheckClient.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{
+				var md ServerMetadata
+				resp, err := healthCheckClient.Check(annotatedContext, &grpc_health_v1.HealthCheckRequest{
 					Service: r.URL.Query().Get("service"),
-				})
+				}, grpc.Header(&md.HeaderMD), grpc.Trailer(&md.TrailerMD))
+				annotatedContext = NewServerMetadataContext(annotatedContext, md)
 				if err != nil {
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
@@ -300,7 +308,7 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 						err = status.Error(codes.NotFound, resp.String())
 					}
 
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
diff --git a/history-api/vendor/github.com/hashicorp/hcl/.gitignore b/history-api/vendor/github.com/hashicorp/hcl/.gitignore
deleted file mode 100644
index 15586a2b..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-y.output
-
-# ignore intellij files
-.idea
-*.iml
-*.ipr
-*.iws
-
-*.test
diff --git a/history-api/vendor/github.com/hashicorp/hcl/.travis.yml b/history-api/vendor/github.com/hashicorp/hcl/.travis.yml
deleted file mode 100644
index cb63a321..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-sudo: false
-
-language: go
-
-go:
-  - 1.x
-  - tip
-
-branches:
-  only:
-    - master
-
-script: make test
diff --git a/history-api/vendor/github.com/hashicorp/hcl/LICENSE b/history-api/vendor/github.com/hashicorp/hcl/LICENSE
deleted file mode 100644
index c33dcc7c..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/LICENSE
+++ /dev/null
@@ -1,354 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. “Contributor”
-
-     means each individual or legal entity that creates, contributes to the
-     creation of, or owns Covered Software.
-
-1.2. “Contributor Version”
-
-     means the combination of the Contributions of others (if any) used by a
-     Contributor and that particular Contributor’s Contribution.
-
-1.3. “Contribution”
-
-     means Covered Software of a particular Contributor.
-
-1.4. “Covered Software”
-
-     means Source Code Form to which the initial Contributor has attached the
-     notice in Exhibit A, the Executable Form of such Source Code Form, and
-     Modifications of such Source Code Form, in each case including portions
-     thereof.
-
-1.5. “Incompatible With Secondary Licenses”
-     means
-
-     a. that the initial Contributor has attached the notice described in
-        Exhibit B to the Covered Software; or
-
-     b. that the Covered Software was made available under the terms of version
-        1.1 or earlier of the License, but not also under the terms of a
-        Secondary License.
-
-1.6. “Executable Form”
-
-     means any form of the work other than Source Code Form.
-
-1.7. “Larger Work”
-
-     means a work that combines Covered Software with other material, in a separate
-     file or files, that is not Covered Software.
-
-1.8. “License”
-
-     means this document.
-
-1.9. “Licensable”
-
-     means having the right to grant, to the maximum extent possible, whether at the
-     time of the initial grant or subsequently, any and all of the rights conveyed by
-     this License.
-
-1.10. “Modifications”
-
-     means any of the following:
-
-     a. any file in Source Code Form that results from an addition to, deletion
-        from, or modification of the contents of Covered Software; or
-
-     b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. “Patent Claims” of a Contributor
-
-      means any patent claim(s), including without limitation, method, process,
-      and apparatus claims, in any patent Licensable by such Contributor that
-      would be infringed, but for the grant of the License, by the making,
-      using, selling, offering for sale, having made, import, or transfer of
-      either its Contributions or its Contributor Version.
-
-1.12. “Secondary License”
-
-      means either the GNU General Public License, Version 2.0, the GNU Lesser
-      General Public License, Version 2.1, the GNU Affero General Public
-      License, Version 3.0, or any later versions of those licenses.
-
-1.13. “Source Code Form”
-
-      means the form of the work preferred for making modifications.
-
-1.14. “You” (or “Your”)
-
-      means an individual or a legal entity exercising rights under this
-      License. For legal entities, “You” includes any entity that controls, is
-      controlled by, or is under common control with You. For purposes of this
-      definition, “control” means (a) the power, direct or indirect, to cause
-      the direction or management of such entity, whether by contract or
-      otherwise, or (b) ownership of more than fifty percent (50%) of the
-      outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
-     Each Contributor hereby grants You a world-wide, royalty-free,
-     non-exclusive license:
-
-     a. under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or as
-        part of a Larger Work; and
-
-     b. under Patent Claims of such Contributor to make, use, sell, offer for
-        sale, have made, import, and otherwise transfer either its Contributions
-        or its Contributor Version.
-
-2.2. Effective Date
-
-     The licenses granted in Section 2.1 with respect to any Contribution become
-     effective for each Contribution on the date the Contributor first distributes
-     such Contribution.
-
-2.3. Limitations on Grant Scope
-
-     The licenses granted in this Section 2 are the only rights granted under this
-     License. No additional rights or licenses will be implied from the distribution
-     or licensing of Covered Software under this License. Notwithstanding Section
-     2.1(b) above, no patent license is granted by a Contributor:
-
-     a. for any code that a Contributor has removed from Covered Software; or
-
-     b. for infringements caused by: (i) Your and any other third party’s
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-     c. under Patent Claims infringed by Covered Software in the absence of its
-        Contributions.
-
-     This License does not grant any rights in the trademarks, service marks, or
-     logos of any Contributor (except as may be necessary to comply with the
-     notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-     No Contributor makes additional grants as a result of Your choice to
-     distribute the Covered Software under a subsequent version of this License
-     (see Section 10.2) or under the terms of a Secondary License (if permitted
-     under the terms of Section 3.3).
-
-2.5. Representation
-
-     Each Contributor represents that the Contributor believes its Contributions
-     are its original creation(s) or it has sufficient rights to grant the
-     rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-     This License is not intended to limit any rights You have under applicable
-     copyright doctrines of fair use, fair dealing, or other equivalents.
-
-2.7. Conditions
-
-     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
-     Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
-     All distribution of Covered Software in Source Code Form, including any
-     Modifications that You create or to which You contribute, must be under the
-     terms of this License. You must inform recipients that the Source Code Form
-     of the Covered Software is governed by the terms of this License, and how
-     they can obtain a copy of this License. You may not attempt to alter or
-     restrict the recipients’ rights in the Source Code Form.
-
-3.2. Distribution of Executable Form
-
-     If You distribute Covered Software in Executable Form then:
-
-     a. such Covered Software must also be made available in Source Code Form,
-        as described in Section 3.1, and You must inform recipients of the
-        Executable Form how they can obtain a copy of such Source Code Form by
-        reasonable means in a timely manner, at a charge no more than the cost
-        of distribution to the recipient; and
-
-     b. You may distribute such Executable Form under the terms of this License,
-        or sublicense it under different terms, provided that the license for
-        the Executable Form does not attempt to limit or alter the recipients’
-        rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-     You may create and distribute a Larger Work under terms of Your choice,
-     provided that You also comply with the requirements of this License for the
-     Covered Software. If the Larger Work is a combination of Covered Software
-     with a work governed by one or more Secondary Licenses, and the Covered
-     Software is not Incompatible With Secondary Licenses, this License permits
-     You to additionally distribute such Covered Software under the terms of
-     such Secondary License(s), so that the recipient of the Larger Work may, at
-     their option, further distribute the Covered Software under the terms of
-     either this License or such Secondary License(s).
-
-3.4. Notices
-
-     You may not remove or alter the substance of any license notices (including
-     copyright notices, patent notices, disclaimers of warranty, or limitations
-     of liability) contained within the Source Code Form of the Covered
-     Software, except that You may alter any license notices to the extent
-     required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-     You may choose to offer, and to charge a fee for, warranty, support,
-     indemnity or liability obligations to one or more recipients of Covered
-     Software. However, You may do so only on Your own behalf, and not on behalf
-     of any Contributor. You must make it absolutely clear that any such
-     warranty, support, indemnity, or liability obligation is offered by You
-     alone, and You hereby agree to indemnify every Contributor for any
-     liability incurred by such Contributor as a result of warranty, support,
-     indemnity or liability terms You offer. You may include additional
-     disclaimers of warranty and limitations of liability specific to any
-     jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
-   If it is impossible for You to comply with any of the terms of this License
-   with respect to some or all of the Covered Software due to statute, judicial
-   order, or regulation then You must: (a) comply with the terms of this License
-   to the maximum extent possible; and (b) describe the limitations and the code
-   they affect. Such description must be placed in a text file included with all
-   distributions of the Covered Software under this License. Except to the
-   extent prohibited by statute or regulation, such description must be
-   sufficiently detailed for a recipient of ordinary skill to be able to
-   understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
-     fail to comply with any of its terms. However, if You become compliant,
-     then the rights granted under this License from a particular Contributor
-     are reinstated (a) provisionally, unless and until such Contributor
-     explicitly and finally terminates Your grants, and (b) on an ongoing basis,
-     if such Contributor fails to notify You of the non-compliance by some
-     reasonable means prior to 60 days after You have come back into compliance.
-     Moreover, Your grants from a particular Contributor are reinstated on an
-     ongoing basis if such Contributor notifies You of the non-compliance by
-     some reasonable means, this is the first time You have received notice of
-     non-compliance with this License from such Contributor, and You become
-     compliant prior to 30 days after Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-     infringement claim (excluding declaratory judgment actions, counter-claims,
-     and cross-claims) alleging that a Contributor Version directly or
-     indirectly infringes any patent, then the rights granted to You by any and
-     all Contributors for the Covered Software under Section 2.1 of this License
-     shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
-     license agreements (excluding distributors and resellers) which have been
-     validly granted by You or Your distributors under this License prior to
-     termination shall survive termination.
-
-6. Disclaimer of Warranty
-
-   Covered Software is provided under this License on an “as is” basis, without
-   warranty of any kind, either expressed, implied, or statutory, including,
-   without limitation, warranties that the Covered Software is free of defects,
-   merchantable, fit for a particular purpose or non-infringing. The entire
-   risk as to the quality and performance of the Covered Software is with You.
-   Should any Covered Software prove defective in any respect, You (not any
-   Contributor) assume the cost of any necessary servicing, repair, or
-   correction. This disclaimer of warranty constitutes an essential part of this
-   License. No use of  any Covered Software is authorized under this License
-   except under this disclaimer.
-
-7. Limitation of Liability
-
-   Under no circumstances and under no legal theory, whether tort (including
-   negligence), contract, or otherwise, shall any Contributor, or anyone who
-   distributes Covered Software as permitted above, be liable to You for any
-   direct, indirect, special, incidental, or consequential damages of any
-   character including, without limitation, damages for lost profits, loss of
-   goodwill, work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses, even if such party shall have been
-   informed of the possibility of such damages. This limitation of liability
-   shall not apply to liability for death or personal injury resulting from such
-   party’s negligence to the extent applicable law prohibits such limitation.
-   Some jurisdictions do not allow the exclusion or limitation of incidental or
-   consequential damages, so this exclusion and limitation may not apply to You.
-
-8. Litigation
-
-   Any litigation relating to this License may be brought only in the courts of
-   a jurisdiction where the defendant maintains its principal place of business
-   and such litigation shall be governed by laws of that jurisdiction, without
-   reference to its conflict-of-law provisions. Nothing in this Section shall
-   prevent a party’s ability to bring cross-claims or counter-claims.
-
-9. Miscellaneous
-
-   This License represents the complete agreement concerning the subject matter
-   hereof. If any provision of this License is held to be unenforceable, such
-   provision shall be reformed only to the extent necessary to make it
-   enforceable. Any law or regulation which provides that the language of a
-   contract shall be construed against the drafter shall not be used to construe
-   this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
-      Mozilla Foundation is the license steward. Except as provided in Section
-      10.3, no one other than the license steward has the right to modify or
-      publish new versions of this License. Each version will be given a
-      distinguishing version number.
-
-10.2. Effect of New Versions
-
-      You may distribute the Covered Software under the terms of the version of
-      the License under which You originally received the Covered Software, or
-      under the terms of any subsequent version published by the license
-      steward.
-
-10.3. Modified Versions
-
-      If you create software not governed by this License, and you want to
-      create a new license for such software, you may create and use a modified
-      version of this License if you rename the license and remove any
-      references to the name of the license steward (except to note that such
-      modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
-      If You choose to distribute Source Code Form that is Incompatible With
-      Secondary Licenses under the terms of this version of the License, the
-      notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
-
-      This Source Code Form is subject to the
-      terms of the Mozilla Public License, v.
-      2.0. If a copy of the MPL was not
-      distributed with this file, You can
-      obtain one at
-      http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file, then
-You may include the notice in a location (such as a LICENSE file in a relevant
-directory) where a recipient would be likely to look for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - “Incompatible With Secondary Licenses” Notice
-
-      This Source Code Form is “Incompatible
-      With Secondary Licenses”, as defined by
-      the Mozilla Public License, v. 2.0.
-
diff --git a/history-api/vendor/github.com/hashicorp/hcl/Makefile b/history-api/vendor/github.com/hashicorp/hcl/Makefile
deleted file mode 100644
index 84fd743f..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TEST?=./...
-
-default: test
-
-fmt: generate
-	go fmt ./...
-
-test: generate
-	go get -t ./...
-	go test $(TEST) $(TESTARGS)
-
-generate:
-	go generate ./...
-
-updatedeps:
-	go get -u golang.org/x/tools/cmd/stringer
-
-.PHONY: default generate test updatedeps
diff --git a/history-api/vendor/github.com/hashicorp/hcl/README.md b/history-api/vendor/github.com/hashicorp/hcl/README.md
deleted file mode 100644
index c8223326..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/README.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# HCL
-
-[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl)
-
-HCL (HashiCorp Configuration Language) is a configuration language built
-by HashiCorp. The goal of HCL is to build a structured configuration language
-that is both human and machine friendly for use with command-line tools, but
-specifically targeted towards DevOps tools, servers, etc.
-
-HCL is also fully JSON compatible. That is, JSON can be used as completely
-valid input to a system expecting HCL. This helps makes systems
-interoperable with other systems.
-
-HCL is heavily inspired by
-[libucl](https://github.com/vstakhov/libucl),
-nginx configuration, and others similar.
-
-## Why?
-
-A common question when viewing HCL is to ask the question: why not
-JSON, YAML, etc.?
-
-Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com)
-used a variety of configuration languages from full programming languages
-such as Ruby to complete data structure languages such as JSON. What we
-learned is that some people wanted human-friendly configuration languages
-and some people wanted machine-friendly languages.
-
-JSON fits a nice balance in this, but is fairly verbose and most
-importantly doesn't support comments. With YAML, we found that beginners
-had a really hard time determining what the actual structure was, and
-ended up guessing more often than not whether to use a hyphen, colon, etc.
-in order to represent some configuration key.
-
-Full programming languages such as Ruby enable complex behavior
-a configuration language shouldn't usually allow, and also forces
-people to learn some set of Ruby.
-
-Because of this, we decided to create our own configuration language
-that is JSON-compatible. Our configuration language (HCL) is designed
-to be written and modified by humans. The API for HCL allows JSON
-as an input so that it is also machine-friendly (machines can generate
-JSON instead of trying to generate HCL).
-
-Our goal with HCL is not to alienate other configuration languages.
-It is instead to provide HCL as a specialized language for our tools,
-and JSON as the interoperability layer.
-
-## Syntax
-
-For a complete grammar, please see the parser itself. A high-level overview
-of the syntax and grammar is listed here.
-
-  * Single line comments start with `#` or `//`
-
-  * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments
-    are not allowed. A multi-line comment (also known as a block comment)
-    terminates at the first `*/` found.
-
-  * Values are assigned with the syntax `key = value` (whitespace doesn't
-    matter). The value can be any primitive: a string, number, boolean,
-    object, or list.
-
-  * Strings are double-quoted and can contain any UTF-8 characters.
-    Example: `"Hello, World"`
-
-  * Multi-line strings start with `<-
-    echo %Path%
-
-    go version
-
-    go env
-
-    go get -t ./...
-
-build_script:
-- cmd: go test -v ./...
diff --git a/history-api/vendor/github.com/hashicorp/hcl/decoder.go b/history-api/vendor/github.com/hashicorp/hcl/decoder.go
deleted file mode 100644
index bed9ebbe..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/decoder.go
+++ /dev/null
@@ -1,729 +0,0 @@
-package hcl
-
-import (
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// This is the tag to use with structures to have settings for HCL
-const tagName = "hcl"
-
-var (
-	// nodeType holds a reference to the type of ast.Node
-	nodeType reflect.Type = findNodeType()
-)
-
-// Unmarshal accepts a byte slice as input and writes the
-// data to the value pointed to by v.
-func Unmarshal(bs []byte, v interface{}) error {
-	root, err := parse(bs)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(v, root)
-}
-
-// Decode reads the given input and decodes it into the structure
-// given by `out`.
-func Decode(out interface{}, in string) error {
-	obj, err := Parse(in)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(out, obj)
-}
-
-// DecodeObject is a lower-level version of Decode. It decodes a
-// raw Object into the given output.
-func DecodeObject(out interface{}, n ast.Node) error {
-	val := reflect.ValueOf(out)
-	if val.Kind() != reflect.Ptr {
-		return errors.New("result must be a pointer")
-	}
-
-	// If we have the file, we really decode the root node
-	if f, ok := n.(*ast.File); ok {
-		n = f.Node
-	}
-
-	var d decoder
-	return d.decode("root", n, val.Elem())
-}
-
-type decoder struct {
-	stack []reflect.Kind
-}
-
-func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
-	k := result
-
-	// If we have an interface with a valid value, we use that
-	// for the check.
-	if result.Kind() == reflect.Interface {
-		elem := result.Elem()
-		if elem.IsValid() {
-			k = elem
-		}
-	}
-
-	// Push current onto stack unless it is an interface.
-	if k.Kind() != reflect.Interface {
-		d.stack = append(d.stack, k.Kind())
-
-		// Schedule a pop
-		defer func() {
-			d.stack = d.stack[:len(d.stack)-1]
-		}()
-	}
-
-	switch k.Kind() {
-	case reflect.Bool:
-		return d.decodeBool(name, node, result)
-	case reflect.Float32, reflect.Float64:
-		return d.decodeFloat(name, node, result)
-	case reflect.Int, reflect.Int32, reflect.Int64:
-		return d.decodeInt(name, node, result)
-	case reflect.Interface:
-		// When we see an interface, we make our own thing
-		return d.decodeInterface(name, node, result)
-	case reflect.Map:
-		return d.decodeMap(name, node, result)
-	case reflect.Ptr:
-		return d.decodePtr(name, node, result)
-	case reflect.Slice:
-		return d.decodeSlice(name, node, result)
-	case reflect.String:
-		return d.decodeString(name, node, result)
-	case reflect.Struct:
-		return d.decodeStruct(name, node, result)
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
-		}
-	}
-}
-
-func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.BOOL {
-			v, err := strconv.ParseBool(n.Token.Text)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
-			v, err := strconv.ParseFloat(n.Token.Text, 64)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			v, err := strconv.ParseInt(n.Token.Text, 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		case token.STRING:
-			v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
-	// When we see an ast.Node, we retain the value to enable deferred decoding.
-	// Very useful in situations where we want to preserve ast.Node information
-	// like Pos
-	if result.Type() == nodeType && result.CanSet() {
-		result.Set(reflect.ValueOf(node))
-		return nil
-	}
-
-	var set reflect.Value
-	redecode := true
-
-	// For testing types, ObjectType should just be treated as a list. We
-	// set this to a temporary var because we want to pass in the real node.
-	testNode := node
-	if ot, ok := node.(*ast.ObjectType); ok {
-		testNode = ot.List
-	}
-
-	switch n := testNode.(type) {
-	case *ast.ObjectList:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
-			set = result
-		}
-	case *ast.ObjectType:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
-			set = result
-		}
-	case *ast.ListType:
-		var temp []interface{}
-		tempVal := reflect.ValueOf(temp)
-		result := reflect.MakeSlice(
-			reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
-		set = result
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.BOOL:
-			var result bool
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.FLOAT:
-			var result float64
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.NUMBER:
-			var result int
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.STRING, token.HEREDOC:
-			set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
-		default:
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
-			}
-		}
-	default:
-		return fmt.Errorf(
-			"%s: cannot decode into interface: %T",
-			name, node)
-	}
-
-	// Set the result to what its supposed to be, then reset
-	// result so we don't reflect into this method anymore.
-	result.Set(set)
-
-	if redecode {
-		// Revisit the node so that we can use the newly instantiated
-		// thing and populate it.
-		if err := d.decode(name, node, result); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
-	if item, ok := node.(*ast.ObjectItem); ok {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	n, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
-		}
-	}
-
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	resultKeyType := resultType.Key()
-	if resultKeyType.Kind() != reflect.String {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: map must have string keys", name),
-		}
-	}
-
-	// Make a map if it is nil
-	resultMap := result
-	if result.IsNil() {
-		resultMap = reflect.MakeMap(
-			reflect.MapOf(resultKeyType, resultElemType))
-	}
-
-	// Go through each element and decode it.
-	done := make(map[string]struct{})
-	for _, item := range n.Items {
-		if item.Val == nil {
-			continue
-		}
-
-		// github.com/hashicorp/terraform/issue/5740
-		if len(item.Keys) == 0 {
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: map must have string keys", name),
-			}
-		}
-
-		// Get the key we're dealing with, which is the first item
-		keyStr := item.Keys[0].Token.Value().(string)
-
-		// If we've already processed this key, then ignore it
-		if _, ok := done[keyStr]; ok {
-			continue
-		}
-
-		// Determine the value. If we have more than one key, then we
-		// get the objectlist of only these keys.
-		itemVal := item.Val
-		if len(item.Keys) > 1 {
-			itemVal = n.Filter(keyStr)
-			done[keyStr] = struct{}{}
-		}
-
-		// Make the field name
-		fieldName := fmt.Sprintf("%s.%s", name, keyStr)
-
-		// Get the key/value as reflection values
-		key := reflect.ValueOf(keyStr)
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// If we have a pre-existing value in the map, use that
-		oldVal := resultMap.MapIndex(key)
-		if oldVal.IsValid() {
-			val.Set(oldVal)
-		}
-
-		// Decode!
-		if err := d.decode(fieldName, itemVal, val); err != nil {
-			return err
-		}
-
-		// Set the value on the map
-		resultMap.SetMapIndex(key, val)
-	}
-
-	// Set the final map if we can
-	set.Set(resultMap)
-	return nil
-}
-
-func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	val := reflect.New(resultElemType)
-	if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
-		return err
-	}
-
-	result.Set(val)
-	return nil
-}
-
-func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-	// Create the slice if it isn't nil
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	if result.IsNil() {
-		resultSliceType := reflect.SliceOf(resultElemType)
-		result = reflect.MakeSlice(
-			resultSliceType, 0, 0)
-	}
-
-	// Figure out the items we'll be copying into the slice
-	var items []ast.Node
-	switch n := node.(type) {
-	case *ast.ObjectList:
-		items = make([]ast.Node, len(n.Items))
-		for i, item := range n.Items {
-			items[i] = item
-		}
-	case *ast.ObjectType:
-		items = []ast.Node{n}
-	case *ast.ListType:
-		items = n.List
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("unknown slice type: %T", node),
-		}
-	}
-
-	for i, item := range items {
-		fieldName := fmt.Sprintf("%s[%d]", name, i)
-
-		// Decode
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// if item is an object that was decoded from ambiguous JSON and
-		// flattened, make sure it's expanded if it needs to decode into a
-		// defined structure.
-		item := expandObject(item, val)
-
-		if err := d.decode(fieldName, item, val); err != nil {
-			return err
-		}
-
-		// Append it onto the slice
-		result = reflect.Append(result, val)
-	}
-
-	set.Set(result)
-	return nil
-}
-
-// expandObject detects if an ambiguous JSON object was flattened to a List which
-// should be decoded into a struct, and expands the ast to properly deocode.
-func expandObject(node ast.Node, result reflect.Value) ast.Node {
-	item, ok := node.(*ast.ObjectItem)
-	if !ok {
-		return node
-	}
-
-	elemType := result.Type()
-
-	// our target type must be a struct
-	switch elemType.Kind() {
-	case reflect.Ptr:
-		switch elemType.Elem().Kind() {
-		case reflect.Struct:
-			//OK
-		default:
-			return node
-		}
-	case reflect.Struct:
-		//OK
-	default:
-		return node
-	}
-
-	// A list value will have a key and field name. If it had more fields,
-	// it wouldn't have been flattened.
-	if len(item.Keys) != 2 {
-		return node
-	}
-
-	keyToken := item.Keys[0].Token
-	item.Keys = item.Keys[1:]
-
-	// we need to un-flatten the ast enough to decode
-	newNode := &ast.ObjectItem{
-		Keys: []*ast.ObjectKey{
-			&ast.ObjectKey{
-				Token: keyToken,
-			},
-		},
-		Val: &ast.ObjectType{
-			List: &ast.ObjectList{
-				Items: []*ast.ObjectItem{item},
-			},
-		},
-	}
-
-	return newNode
-}
-
-func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
-			return nil
-		case token.STRING, token.HEREDOC:
-			result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type for string %T", name, node),
-	}
-}
-
-func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
-	var item *ast.ObjectItem
-	if it, ok := node.(*ast.ObjectItem); ok {
-		item = it
-		node = it.Val
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	// Handle the special case where the object itself is a literal. Previously
-	// the yacc parser would always ensure top-level elements were arrays. The new
-	// parser does not make the same guarantees, thus we need to convert any
-	// top-level literal elements into a list.
-	if _, ok := node.(*ast.LiteralType); ok && item != nil {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	list, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
-		}
-	}
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = result
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
-
-			// Ignore fields with tag name "-"
-			if tagParts[0] == "-" {
-				continue
-			}
-
-			if fieldType.Anonymous {
-				fieldKind := fieldType.Type.Kind()
-				if fieldKind != reflect.Struct {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: unsupported type to struct: %s",
-							fieldType.Name, fieldKind),
-					}
-				}
-
-				// We have an embedded field. We "squash" the fields down
-				// if specified in the tag.
-				squash := false
-				for _, tag := range tagParts[1:] {
-					if tag == "squash" {
-						squash = true
-						break
-					}
-				}
-
-				if squash {
-					structs = append(
-						structs, result.FieldByName(fieldType.Name))
-					continue
-				}
-			}
-
-			// Normal struct field, store it away
-			fields = append(fields, field{fieldType, structVal.Field(i)})
-		}
-	}
-
-	usedKeys := make(map[string]struct{})
-	decodedFields := make([]string, 0, len(fields))
-	decodedFieldsVal := make([]reflect.Value, 0)
-	unusedKeysVal := make([]reflect.Value, 0)
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(tagName)
-		tagParts := strings.SplitN(tagValue, ",", 2)
-		if len(tagParts) >= 2 {
-			switch tagParts[1] {
-			case "decodedFields":
-				decodedFieldsVal = append(decodedFieldsVal, fieldValue)
-				continue
-			case "key":
-				if item == nil {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: %s asked for 'key', impossible",
-							name, fieldName),
-					}
-				}
-
-				fieldValue.SetString(item.Keys[0].Token.Value().(string))
-				continue
-			case "unusedKeys":
-				unusedKeysVal = append(unusedKeysVal, fieldValue)
-				continue
-			}
-		}
-
-		if tagParts[0] != "" {
-			fieldName = tagParts[0]
-		}
-
-		// Determine the element we'll use to decode. If it is a single
-		// match (only object with the field), then we decode it exactly.
-		// If it is a prefix match, then we decode the matches.
-		filter := list.Filter(fieldName)
-
-		prefixMatches := filter.Children()
-		matches := filter.Elem()
-		if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
-			continue
-		}
-
-		// Track the used key
-		usedKeys[fieldName] = struct{}{}
-
-		// Create the field name and decode. We range over the elements
-		// because we actually want the value.
-		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
-		if len(prefixMatches.Items) > 0 {
-			if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
-				return err
-			}
-		}
-		for _, match := range matches.Items {
-			var decodeNode ast.Node = match.Val
-			if ot, ok := decodeNode.(*ast.ObjectType); ok {
-				decodeNode = &ast.ObjectList{Items: ot.List.Items}
-			}
-
-			if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
-				return err
-			}
-		}
-
-		decodedFields = append(decodedFields, field.Name)
-	}
-
-	if len(decodedFieldsVal) > 0 {
-		// Sort it so that it is deterministic
-		sort.Strings(decodedFields)
-
-		for _, v := range decodedFieldsVal {
-			v.Set(reflect.ValueOf(decodedFields))
-		}
-	}
-
-	return nil
-}
-
-// findNodeType returns the type of ast.Node
-func findNodeType() reflect.Type {
-	var nodeContainer struct {
-		Node ast.Node
-	}
-	value := reflect.ValueOf(nodeContainer).FieldByName("Node")
-	return value.Type()
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl.go b/history-api/vendor/github.com/hashicorp/hcl/hcl.go
deleted file mode 100644
index 575a20b5..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Package hcl decodes HCL into usable Go structures.
-//
-// hcl input can come in either pure HCL format or JSON format.
-// It can be parsed into an AST, and then decoded into a structure,
-// or it can be decoded directly from a string into a structure.
-//
-// If you choose to parse HCL into a raw AST, the benefit is that you
-// can write custom visitor implementations to implement custom
-// semantic checks. By default, HCL does not perform any semantic
-// checks.
-package hcl
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
deleted file mode 100644
index 6e5ef654..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package ast declares the types used to represent syntax trees for HCL
-// (HashiCorp Configuration Language)
-package ast
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// Node is an element in the abstract syntax tree.
-type Node interface {
-	node()
-	Pos() token.Pos
-}
-
-func (File) node()         {}
-func (ObjectList) node()   {}
-func (ObjectKey) node()    {}
-func (ObjectItem) node()   {}
-func (Comment) node()      {}
-func (CommentGroup) node() {}
-func (ObjectType) node()   {}
-func (LiteralType) node()  {}
-func (ListType) node()     {}
-
-// File represents a single HCL file
-type File struct {
-	Node     Node            // usually a *ObjectList
-	Comments []*CommentGroup // list of all comments in the source
-}
-
-func (f *File) Pos() token.Pos {
-	return f.Node.Pos()
-}
-
-// ObjectList represents a list of ObjectItems. An HCL file itself is an
-// ObjectList.
-type ObjectList struct {
-	Items []*ObjectItem
-}
-
-func (o *ObjectList) Add(item *ObjectItem) {
-	o.Items = append(o.Items, item)
-}
-
-// Filter filters out the objects with the given key list as a prefix.
-//
-// The returned list of objects contain ObjectItems where the keys have
-// this prefix already stripped off. This might result in objects with
-// zero-length key lists if they have no children.
-//
-// If no matches are found, an empty ObjectList (non-nil) is returned.
-func (o *ObjectList) Filter(keys ...string) *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		// If there aren't enough keys, then ignore this
-		if len(item.Keys) < len(keys) {
-			continue
-		}
-
-		match := true
-		for i, key := range item.Keys[:len(keys)] {
-			key := key.Token.Value().(string)
-			if key != keys[i] && !strings.EqualFold(key, keys[i]) {
-				match = false
-				break
-			}
-		}
-		if !match {
-			continue
-		}
-
-		// Strip off the prefix from the children
-		newItem := *item
-		newItem.Keys = newItem.Keys[len(keys):]
-		result.Add(&newItem)
-	}
-
-	return &result
-}
-
-// Children returns further nested objects (key length > 0) within this
-// ObjectList. This should be used with Filter to get at child items.
-func (o *ObjectList) Children() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) > 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-// Elem returns items in the list that are direct element assignments
-// (key length == 0). This should be used with Filter to get at elements.
-func (o *ObjectList) Elem() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) == 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-func (o *ObjectList) Pos() token.Pos {
-	// always returns the uninitiliazed position
-	return o.Items[0].Pos()
-}
-
-// ObjectItem represents a HCL Object Item. An item is represented with a key
-// (or keys). It can be an assignment or an object (both normal and nested)
-type ObjectItem struct {
-	// keys is only one length long if it's of type assignment. If it's a
-	// nested object it can be larger than one. In that case "assign" is
-	// invalid as there is no assignments for a nested object.
-	Keys []*ObjectKey
-
-	// assign contains the position of "=", if any
-	Assign token.Pos
-
-	// val is the item itself. It can be an object,list, number, bool or a
-	// string. If key length is larger than one, val can be only of type
-	// Object.
-	Val Node
-
-	LeadComment *CommentGroup // associated lead comment
-	LineComment *CommentGroup // associated line comment
-}
-
-func (o *ObjectItem) Pos() token.Pos {
-	// I'm not entirely sure what causes this, but removing this causes
-	// a test failure. We should investigate at some point.
-	if len(o.Keys) == 0 {
-		return token.Pos{}
-	}
-
-	return o.Keys[0].Pos()
-}
-
-// ObjectKeys are either an identifier or of type string.
-type ObjectKey struct {
-	Token token.Token
-}
-
-func (o *ObjectKey) Pos() token.Pos {
-	return o.Token.Pos
-}
-
-// LiteralType represents a literal of basic type. Valid types are:
-// token.NUMBER, token.FLOAT, token.BOOL and token.STRING
-type LiteralType struct {
-	Token token.Token
-
-	// comment types, only used when in a list
-	LeadComment *CommentGroup
-	LineComment *CommentGroup
-}
-
-func (l *LiteralType) Pos() token.Pos {
-	return l.Token.Pos
-}
-
-// ListStatement represents a HCL List type
-type ListType struct {
-	Lbrack token.Pos // position of "["
-	Rbrack token.Pos // position of "]"
-	List   []Node    // the elements in lexical order
-}
-
-func (l *ListType) Pos() token.Pos {
-	return l.Lbrack
-}
-
-func (l *ListType) Add(node Node) {
-	l.List = append(l.List, node)
-}
-
-// ObjectType represents a HCL Object Type
-type ObjectType struct {
-	Lbrace token.Pos   // position of "{"
-	Rbrace token.Pos   // position of "}"
-	List   *ObjectList // the nodes in lexical order
-}
-
-func (o *ObjectType) Pos() token.Pos {
-	return o.Lbrace
-}
-
-// Comment node represents a single //, # style or /*- style commment
-type Comment struct {
-	Start token.Pos // position of / or #
-	Text  string
-}
-
-func (c *Comment) Pos() token.Pos {
-	return c.Start
-}
-
-// CommentGroup node represents a sequence of comments with no other tokens and
-// no empty lines between.
-type CommentGroup struct {
-	List []*Comment // len(List) > 0
-}
-
-func (c *CommentGroup) Pos() token.Pos {
-	return c.List[0].Pos()
-}
-
-//-------------------------------------------------------------------
-// GoStringer
-//-------------------------------------------------------------------
-
-func (o *ObjectKey) GoString() string  { return fmt.Sprintf("*%#v", *o) }
-func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) }
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
deleted file mode 100644
index ba07ad42..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package ast
-
-import "fmt"
-
-// WalkFunc describes a function to be called for each node during a Walk. The
-// returned node can be used to rewrite the AST. Walking stops the returned
-// bool is false.
-type WalkFunc func(Node) (Node, bool)
-
-// Walk traverses an AST in depth-first order: It starts by calling fn(node);
-// node must not be nil. If fn returns true, Walk invokes fn recursively for
-// each of the non-nil children of node, followed by a call of fn(nil). The
-// returned node of fn can be used to rewrite the passed node to fn.
-func Walk(node Node, fn WalkFunc) Node {
-	rewritten, ok := fn(node)
-	if !ok {
-		return rewritten
-	}
-
-	switch n := node.(type) {
-	case *File:
-		n.Node = Walk(n.Node, fn)
-	case *ObjectList:
-		for i, item := range n.Items {
-			n.Items[i] = Walk(item, fn).(*ObjectItem)
-		}
-	case *ObjectKey:
-		// nothing to do
-	case *ObjectItem:
-		for i, k := range n.Keys {
-			n.Keys[i] = Walk(k, fn).(*ObjectKey)
-		}
-
-		if n.Val != nil {
-			n.Val = Walk(n.Val, fn)
-		}
-	case *LiteralType:
-		// nothing to do
-	case *ListType:
-		for i, l := range n.List {
-			n.List[i] = Walk(l, fn)
-		}
-	case *ObjectType:
-		n.List = Walk(n.List, fn).(*ObjectList)
-	default:
-		// should we panic here?
-		fmt.Printf("unknown type: %T\n", n)
-	}
-
-	fn(nil)
-	return rewritten
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
deleted file mode 100644
index 5c99381d..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package parser
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// PosError is a parse error that contains a position.
-type PosError struct {
-	Pos token.Pos
-	Err error
-}
-
-func (e *PosError) Error() string {
-	return fmt.Sprintf("At %s: %s", e.Pos, e.Err)
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
deleted file mode 100644
index 64c83bcf..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
+++ /dev/null
@@ -1,532 +0,0 @@
-// Package parser implements a parser for HCL (HashiCorp Configuration
-// Language)
-package parser
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/scanner"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	comments    []*ast.CommentGroup
-	leadComment *ast.CommentGroup // last lead comment
-	lineComment *ast.CommentGroup // last line comment
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	// normalize all line endings
-	// since the scanner and output only work with "\n" line endings, we may
-	// end up with dangling "\r" characters in the parsed data.
-	src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1)
-
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = &PosError{Pos: pos, Err: errors.New(msg)}
-	}
-
-	f.Node, err = p.objectList(false)
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	f.Comments = p.comments
-	return f, nil
-}
-
-// objectList parses a list of items within an object (generally k/v pairs).
-// The parameter" obj" tells this whether to we are within an object (braces:
-// '{', '}') or just at the top level. If we're within an object, we end
-// at an RBRACE.
-func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		if obj {
-			tok := p.scan()
-			p.unscan()
-			if tok.Type == token.RBRACE {
-				break
-			}
-		}
-
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// object lists can be optionally comma-delimited e.g. when a list of maps
-		// is being expressed, so a comma is allowed here - it's simply consumed
-		tok := p.scan()
-		if tok.Type != token.COMMA {
-			p.unscan()
-		}
-	}
-	return node, nil
-}
-
-func (p *Parser) consumeComment() (comment *ast.Comment, endline int) {
-	endline = p.tok.Pos.Line
-
-	// count the endline if it's multiline comment, ie starting with /*
-	if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' {
-		// don't use range here - no need to decode Unicode code points
-		for i := 0; i < len(p.tok.Text); i++ {
-			if p.tok.Text[i] == '\n' {
-				endline++
-			}
-		}
-	}
-
-	comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text}
-	p.tok = p.sc.Scan()
-	return
-}
-
-func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
-	var list []*ast.Comment
-	endline = p.tok.Pos.Line
-
-	for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n {
-		var comment *ast.Comment
-		comment, endline = p.consumeComment()
-		list = append(list, comment)
-	}
-
-	// add comment group to the comments list
-	comments = &ast.CommentGroup{List: list}
-	p.comments = append(p.comments, comments)
-
-	return
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if len(keys) > 0 && err == errEofToken {
-		// We ignore eof token here since it is an error if we didn't
-		// receive a value (but we did receive a key) for the item.
-		err = nil
-	}
-	if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE {
-		// This is a strange boolean statement, but what it means is:
-		// We have keys with no value, and we're likely in an object
-		// (since RBrace ends an object). For this, we set err to nil so
-		// we continue and get the error below of having the wrong value
-		// type.
-		err = nil
-
-		// Reset the token type so we don't think it completed fine. See
-		// objectType which uses p.tok.Type to check if we're done with
-		// the object.
-		p.tok.Type = token.EOF
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	if p.leadComment != nil {
-		o.LeadComment = p.leadComment
-		p.leadComment = nil
-	}
-
-	switch p.tok.Type {
-	case token.ASSIGN:
-		o.Assign = p.tok.Pos
-		o.Val, err = p.object()
-		if err != nil {
-			return nil, err
-		}
-	case token.LBRACE:
-		o.Val, err = p.objectType()
-		if err != nil {
-			return nil, err
-		}
-	default:
-		keyStr := make([]string, 0, len(keys))
-		for _, k := range keys {
-			keyStr = append(keyStr, k.Token.Text)
-		}
-
-		return nil, &PosError{
-			Pos: p.tok.Pos,
-			Err: fmt.Errorf(
-				"key '%s' expected start of object ('{') or assignment ('=')",
-				strings.Join(keyStr, " ")),
-		}
-	}
-
-	// key=#comment
-	// val
-	if p.lineComment != nil {
-		o.LineComment, p.lineComment = p.lineComment, nil
-	}
-
-	// do a look-ahead for line comment
-	p.scan()
-	if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil {
-		o.LineComment = p.lineComment
-		p.lineComment = nil
-	}
-	p.unscan()
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			// It is very important to also return the keys here as well as
-			// the error. This is because we need to be able to tell if we
-			// did parse keys prior to finding the EOF, or if we just found
-			// a bare EOF.
-			return keys, errEofToken
-		case token.ASSIGN:
-			// assignment or object only, but not nested objects. this is not
-			// allowed: `foo bar = {}`
-			if keyCount > 1 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type),
-				}
-			}
-
-			if keyCount == 0 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: errors.New("no object keys found!"),
-				}
-			}
-
-			return keys, nil
-		case token.LBRACE:
-			var err error
-
-			// If we have no keys, then it is a syntax error. i.e. {{}} is not
-			// allowed.
-			if len(keys) == 0 {
-				err = &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type),
-				}
-			}
-
-			// object
-			return keys, err
-		case token.IDENT, token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{Token: p.tok})
-		case token.ILLEGAL:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("illegal character"),
-			}
-		default:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type),
-			}
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (ast.Node, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.COMMENT:
-		// implement comment
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, &PosError{
-		Pos: tok.Pos,
-		Err: fmt.Errorf("Unknown token: %+v", tok),
-	}
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{
-		Lbrace: p.tok.Pos,
-	}
-
-	l, err := p.objectList(true)
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	// No error, scan and expect the ending to be a brace
-	if tok := p.scan(); tok.Type != token.RBRACE {
-		return nil, &PosError{
-			Pos: tok.Pos,
-			Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type),
-		}
-	}
-
-	o.List = l
-	o.Rbrace = p.tok.Pos // advanced via parseObjectList
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{
-		Lbrack: p.tok.Pos,
-	}
-
-	needComma := false
-	for {
-		tok := p.scan()
-		if needComma {
-			switch tok.Type {
-			case token.COMMA, token.RBRACK:
-			default:
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error parsing list, expected comma or list end, got: %s",
-						tok.Type),
-				}
-			}
-		}
-		switch tok.Type {
-		case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			// If there is a lead comment, apply it
-			if p.leadComment != nil {
-				node.LeadComment = p.leadComment
-				p.leadComment = nil
-			}
-
-			l.Add(node)
-			needComma = true
-		case token.COMMA:
-			// get next list item or we are at the end
-			// do a look-ahead for line comment
-			p.scan()
-			if p.lineComment != nil && len(l.List) > 0 {
-				lit, ok := l.List[len(l.List)-1].(*ast.LiteralType)
-				if ok {
-					lit.LineComment = p.lineComment
-					l.List[len(l.List)-1] = lit
-					p.lineComment = nil
-				}
-			}
-			p.unscan()
-
-			needComma = false
-			continue
-		case token.LBRACE:
-			// Looks like a nested object, so parse it out
-			node, err := p.objectType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse object within list: %s", err),
-				}
-			}
-			l.Add(node)
-			needComma = true
-		case token.LBRACK:
-			node, err := p.listType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse list within list: %s", err),
-				}
-			}
-			l.Add(node)
-		case token.RBRACK:
-			// finished
-			l.Rbrack = p.tok.Pos
-			return l, nil
-		default:
-			return nil, &PosError{
-				Pos: tok.Pos,
-				Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type),
-			}
-		}
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok,
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead. In the process, it collects any
-// comment groups encountered, and remembers the last lead and line comments.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	// Otherwise read the next token from the scanner and Save it to the buffer
-	// in case we unscan later.
-	prev := p.tok
-	p.tok = p.sc.Scan()
-
-	if p.tok.Type == token.COMMENT {
-		var comment *ast.CommentGroup
-		var endline int
-
-		// fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n",
-		// p.tok.Pos.Line, prev.Pos.Line, endline)
-		if p.tok.Pos.Line == prev.Pos.Line {
-			// The comment is on same line as the previous token; it
-			// cannot be a lead comment but may be a line comment.
-			comment, endline = p.consumeCommentGroup(0)
-			if p.tok.Pos.Line != endline {
-				// The next token is on a different line, thus
-				// the last comment group is a line comment.
-				p.lineComment = comment
-			}
-		}
-
-		// consume successor comments, if any
-		endline = -1
-		for p.tok.Type == token.COMMENT {
-			comment, endline = p.consumeCommentGroup(1)
-		}
-
-		if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE {
-			switch p.tok.Type {
-			case token.RBRACE, token.RBRACK:
-				// Do not count for these cases
-			default:
-				// The next token is following on the line immediately after the
-				// comment group, thus the last comment group is a lead comment.
-				p.leadComment = comment
-			}
-		}
-
-	}
-
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
deleted file mode 100644
index 7c038d12..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
+++ /dev/null
@@ -1,789 +0,0 @@
-package printer
-
-import (
-	"bytes"
-	"fmt"
-	"sort"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-const (
-	blank    = byte(' ')
-	newline  = byte('\n')
-	tab      = byte('\t')
-	infinity = 1 << 30 // offset or line
-)
-
-var (
-	unindent = []byte("\uE123") // in the private use space
-)
-
-type printer struct {
-	cfg  Config
-	prev token.Pos
-
-	comments           []*ast.CommentGroup // may be nil, contains all comments
-	standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node)
-
-	enableTrace bool
-	indentTrace int
-}
-
-type ByPosition []*ast.CommentGroup
-
-func (b ByPosition) Len() int           { return len(b) }
-func (b ByPosition) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
-func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) }
-
-// collectComments comments all standalone comments which are not lead or line
-// comment
-func (p *printer) collectComments(node ast.Node) {
-	// first collect all comments. This is already stored in
-	// ast.File.(comments)
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.File:
-			p.comments = t.Comments
-			return nn, false
-		}
-		return nn, true
-	})
-
-	standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0)
-	for _, c := range p.comments {
-		standaloneComments[c.Pos()] = c
-	}
-
-	// next remove all lead and line comments from the overall comment map.
-	// This will give us comments which are standalone, comments which are not
-	// assigned to any kind of node.
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.LiteralType:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		case *ast.ObjectItem:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		}
-
-		return nn, true
-	})
-
-	for _, c := range standaloneComments {
-		p.standaloneComments = append(p.standaloneComments, c)
-	}
-
-	sort.Sort(ByPosition(p.standaloneComments))
-}
-
-// output prints creates b printable HCL output and returns it.
-func (p *printer) output(n interface{}) []byte {
-	var buf bytes.Buffer
-
-	switch t := n.(type) {
-	case *ast.File:
-		// File doesn't trace so we add the tracing here
-		defer un(trace(p, "File"))
-		return p.output(t.Node)
-	case *ast.ObjectList:
-		defer un(trace(p, "ObjectList"))
-
-		var index int
-		for {
-			// Determine the location of the next actual non-comment
-			// item. If we're at the end, the next item is at "infinity"
-			var nextItem token.Pos
-			if index != len(t.Items) {
-				nextItem = t.Items[index].Pos()
-			} else {
-				nextItem = token.Pos{Offset: infinity, Line: infinity}
-			}
-
-			// Go through the standalone comments in the file and print out
-			// the comments that we should be for this object item.
-			for _, c := range p.standaloneComments {
-				// Go through all the comments in the group. The group
-				// should be printed together, not separated by double newlines.
-				printed := false
-				newlinePrinted := false
-				for _, comment := range c.List {
-					// We only care about comments after the previous item
-					// we've printed so that comments are printed in the
-					// correct locations (between two objects for example).
-					// And before the next item.
-					if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-						// if we hit the end add newlines so we can print the comment
-						// we don't do this if prev is invalid which means the
-						// beginning of the file since the first comment should
-						// be at the first line.
-						if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) {
-							buf.Write([]byte{newline, newline})
-							newlinePrinted = true
-						}
-
-						// Write the actual comment.
-						buf.WriteString(comment.Text)
-						buf.WriteByte(newline)
-
-						// Set printed to true to note that we printed something
-						printed = true
-					}
-				}
-
-				// If we're not at the last item, write a new line so
-				// that there is a newline separating this comment from
-				// the next object.
-				if printed && index != len(t.Items) {
-					buf.WriteByte(newline)
-				}
-			}
-
-			if index == len(t.Items) {
-				break
-			}
-
-			buf.Write(p.output(t.Items[index]))
-			if index != len(t.Items)-1 {
-				// Always write a newline to separate us from the next item
-				buf.WriteByte(newline)
-
-				// Need to determine if we're going to separate the next item
-				// with a blank line. The logic here is simple, though there
-				// are a few conditions:
-				//
-				//   1. The next object is more than one line away anyways,
-				//      so we need an empty line.
-				//
-				//   2. The next object is not a "single line" object, so
-				//      we need an empty line.
-				//
-				//   3. This current object is not a single line object,
-				//      so we need an empty line.
-				current := t.Items[index]
-				next := t.Items[index+1]
-				if next.Pos().Line != t.Items[index].Pos().Line+1 ||
-					!p.isSingleLineObject(next) ||
-					!p.isSingleLineObject(current) {
-					buf.WriteByte(newline)
-				}
-			}
-			index++
-		}
-	case *ast.ObjectKey:
-		buf.WriteString(t.Token.Text)
-	case *ast.ObjectItem:
-		p.prev = t.Pos()
-		buf.Write(p.objectItem(t))
-	case *ast.LiteralType:
-		buf.Write(p.literalType(t))
-	case *ast.ListType:
-		buf.Write(p.list(t))
-	case *ast.ObjectType:
-		buf.Write(p.objectType(t))
-	default:
-		fmt.Printf(" unknown type: %T\n", n)
-	}
-
-	return buf.Bytes()
-}
-
-func (p *printer) literalType(lit *ast.LiteralType) []byte {
-	result := []byte(lit.Token.Text)
-	switch lit.Token.Type {
-	case token.HEREDOC:
-		// Clear the trailing newline from heredocs
-		if result[len(result)-1] == '\n' {
-			result = result[:len(result)-1]
-		}
-
-		// Poison lines 2+ so that we don't indent them
-		result = p.heredocIndent(result)
-	case token.STRING:
-		// If this is a multiline string, poison lines 2+ so we don't
-		// indent them.
-		if bytes.IndexRune(result, '\n') >= 0 {
-			result = p.heredocIndent(result)
-		}
-	}
-
-	return result
-}
-
-// objectItem returns the printable HCL form of an object item. An object type
-// starts with one/multiple keys and has a value. The value might be of any
-// type.
-func (p *printer) objectItem(o *ast.ObjectItem) []byte {
-	defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text)))
-	var buf bytes.Buffer
-
-	if o.LeadComment != nil {
-		for _, comment := range o.LeadComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	// If key and val are on different lines, treat line comments like lead comments.
-	if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line {
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	for i, k := range o.Keys {
-		buf.WriteString(k.Token.Text)
-		buf.WriteByte(blank)
-
-		// reach end of key
-		if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 {
-			buf.WriteString("=")
-			buf.WriteByte(blank)
-		}
-	}
-
-	buf.Write(p.output(o.Val))
-
-	if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line {
-		buf.WriteByte(blank)
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// objectType returns the printable HCL form of an object type. An object type
-// begins with a brace and ends with a brace.
-func (p *printer) objectType(o *ast.ObjectType) []byte {
-	defer un(trace(p, "ObjectType"))
-	var buf bytes.Buffer
-	buf.WriteString("{")
-
-	var index int
-	var nextItem token.Pos
-	var commented, newlinePrinted bool
-	for {
-		// Determine the location of the next actual non-comment
-		// item. If we're at the end, the next item is the closing brace
-		if index != len(o.List.Items) {
-			nextItem = o.List.Items[index].Pos()
-		} else {
-			nextItem = o.Rbrace
-		}
-
-		// Go through the standalone comments in the file and print out
-		// the comments that we should be for this object item.
-		for _, c := range p.standaloneComments {
-			printed := false
-			var lastCommentPos token.Pos
-			for _, comment := range c.List {
-				// We only care about comments after the previous item
-				// we've printed so that comments are printed in the
-				// correct locations (between two objects for example).
-				// And before the next item.
-				if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-					// If there are standalone comments and the initial newline has not
-					// been printed yet, do it now.
-					if !newlinePrinted {
-						newlinePrinted = true
-						buf.WriteByte(newline)
-					}
-
-					// add newline if it's between other printed nodes
-					if index > 0 {
-						commented = true
-						buf.WriteByte(newline)
-					}
-
-					// Store this position
-					lastCommentPos = comment.Pos()
-
-					// output the comment itself
-					buf.Write(p.indent(p.heredocIndent([]byte(comment.Text))))
-
-					// Set printed to true to note that we printed something
-					printed = true
-
-					/*
-						if index != len(o.List.Items) {
-							buf.WriteByte(newline) // do not print on the end
-						}
-					*/
-				}
-			}
-
-			// Stuff to do if we had comments
-			if printed {
-				// Always write a newline
-				buf.WriteByte(newline)
-
-				// If there is another item in the object and our comment
-				// didn't hug it directly, then make sure there is a blank
-				// line separating them.
-				if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 {
-					buf.WriteByte(newline)
-				}
-			}
-		}
-
-		if index == len(o.List.Items) {
-			p.prev = o.Rbrace
-			break
-		}
-
-		// At this point we are sure that it's not a totally empty block: print
-		// the initial newline if it hasn't been printed yet by the previous
-		// block about standalone comments.
-		if !newlinePrinted {
-			buf.WriteByte(newline)
-			newlinePrinted = true
-		}
-
-		// check if we have adjacent one liner items. If yes we'll going to align
-		// the comments.
-		var aligned []*ast.ObjectItem
-		for _, item := range o.List.Items[index:] {
-			// we don't group one line lists
-			if len(o.List.Items) == 1 {
-				break
-			}
-
-			// one means a oneliner with out any lead comment
-			// two means a oneliner with lead comment
-			// anything else might be something else
-			cur := lines(string(p.objectItem(item)))
-			if cur > 2 {
-				break
-			}
-
-			curPos := item.Pos()
-
-			nextPos := token.Pos{}
-			if index != len(o.List.Items)-1 {
-				nextPos = o.List.Items[index+1].Pos()
-			}
-
-			prevPos := token.Pos{}
-			if index != 0 {
-				prevPos = o.List.Items[index-1].Pos()
-			}
-
-			// fmt.Println("DEBUG ----------------")
-			// fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos)
-			// fmt.Printf("cur = %+v curPos: %s\n", cur, curPos)
-			// fmt.Printf("next = %+v nextPos: %s\n", next, nextPos)
-
-			if curPos.Line+1 == nextPos.Line {
-				aligned = append(aligned, item)
-				index++
-				continue
-			}
-
-			if curPos.Line-1 == prevPos.Line {
-				aligned = append(aligned, item)
-				index++
-
-				// finish if we have a new line or comment next. This happens
-				// if the next item is not adjacent
-				if curPos.Line+1 != nextPos.Line {
-					break
-				}
-				continue
-			}
-
-			break
-		}
-
-		// put newlines if the items are between other non aligned items.
-		// newlines are also added if there is a standalone comment already, so
-		// check it too
-		if !commented && index != len(aligned) {
-			buf.WriteByte(newline)
-		}
-
-		if len(aligned) >= 1 {
-			p.prev = aligned[len(aligned)-1].Pos()
-
-			items := p.alignedItems(aligned)
-			buf.Write(p.indent(items))
-		} else {
-			p.prev = o.List.Items[index].Pos()
-
-			buf.Write(p.indent(p.objectItem(o.List.Items[index])))
-			index++
-		}
-
-		buf.WriteByte(newline)
-	}
-
-	buf.WriteString("}")
-	return buf.Bytes()
-}
-
-func (p *printer) alignedItems(items []*ast.ObjectItem) []byte {
-	var buf bytes.Buffer
-
-	// find the longest key and value length, needed for alignment
-	var longestKeyLen int // longest key length
-	var longestValLen int // longest value length
-	for _, item := range items {
-		key := len(item.Keys[0].Token.Text)
-		val := len(p.output(item.Val))
-
-		if key > longestKeyLen {
-			longestKeyLen = key
-		}
-
-		if val > longestValLen {
-			longestValLen = val
-		}
-	}
-
-	for i, item := range items {
-		if item.LeadComment != nil {
-			for _, comment := range item.LeadComment.List {
-				buf.WriteString(comment.Text)
-				buf.WriteByte(newline)
-			}
-		}
-
-		for i, k := range item.Keys {
-			keyLen := len(k.Token.Text)
-			buf.WriteString(k.Token.Text)
-			for i := 0; i < longestKeyLen-keyLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			// reach end of key
-			if i == len(item.Keys)-1 && len(item.Keys) == 1 {
-				buf.WriteString("=")
-				buf.WriteByte(blank)
-			}
-		}
-
-		val := p.output(item.Val)
-		valLen := len(val)
-		buf.Write(val)
-
-		if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil {
-			for i := 0; i < longestValLen-valLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range item.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		// do not print for the last item
-		if i != len(items)-1 {
-			buf.WriteByte(newline)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// list returns the printable HCL form of an list type.
-func (p *printer) list(l *ast.ListType) []byte {
-	if p.isSingleLineList(l) {
-		return p.singleLineList(l)
-	}
-
-	var buf bytes.Buffer
-	buf.WriteString("[")
-	buf.WriteByte(newline)
-
-	var longestLine int
-	for _, item := range l.List {
-		// for now we assume that the list only contains literal types
-		if lit, ok := item.(*ast.LiteralType); ok {
-			lineLen := len(lit.Token.Text)
-			if lineLen > longestLine {
-				longestLine = lineLen
-			}
-		}
-	}
-
-	haveEmptyLine := false
-	for i, item := range l.List {
-		// If we have a lead comment, then we want to write that first
-		leadComment := false
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil {
-			leadComment = true
-
-			// Ensure an empty line before every element with a
-			// lead comment (except the first item in a list).
-			if !haveEmptyLine && i != 0 {
-				buf.WriteByte(newline)
-			}
-
-			for _, comment := range lit.LeadComment.List {
-				buf.Write(p.indent([]byte(comment.Text)))
-				buf.WriteByte(newline)
-			}
-		}
-
-		// also indent each line
-		val := p.output(item)
-		curLen := len(val)
-		buf.Write(p.indent(val))
-
-		// if this item is a heredoc, then we output the comma on
-		// the next line. This is the only case this happens.
-		comma := []byte{','}
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-			comma = p.indent(comma)
-		}
-
-		buf.Write(comma)
-
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil {
-			// if the next item doesn't have any comments, do not align
-			buf.WriteByte(blank) // align one space
-			for i := 0; i < longestLine-curLen; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range lit.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		buf.WriteByte(newline)
-
-		// Ensure an empty line after every element with a
-		// lead comment (except the first item in a list).
-		haveEmptyLine = leadComment && i != len(l.List)-1
-		if haveEmptyLine {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// isSingleLineList returns true if:
-// * they were previously formatted entirely on one line
-// * they consist entirely of literals
-// * there are either no heredoc strings or the list has exactly one element
-// * there are no line comments
-func (printer) isSingleLineList(l *ast.ListType) bool {
-	for _, item := range l.List {
-		if item.Pos().Line != l.Lbrack.Line {
-			return false
-		}
-
-		lit, ok := item.(*ast.LiteralType)
-		if !ok {
-			return false
-		}
-
-		if lit.Token.Type == token.HEREDOC && len(l.List) != 1 {
-			return false
-		}
-
-		if lit.LineComment != nil {
-			return false
-		}
-	}
-
-	return true
-}
-
-// singleLineList prints a simple single line list.
-// For a definition of "simple", see isSingleLineList above.
-func (p *printer) singleLineList(l *ast.ListType) []byte {
-	buf := &bytes.Buffer{}
-
-	buf.WriteString("[")
-	for i, item := range l.List {
-		if i != 0 {
-			buf.WriteString(", ")
-		}
-
-		// Output the item itself
-		buf.Write(p.output(item))
-
-		// The heredoc marker needs to be at the end of line.
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// indent indents the lines of the given buffer for each non-empty line
-func (p *printer) indent(buf []byte) []byte {
-	var prefix []byte
-	if p.cfg.SpacesWidth != 0 {
-		for i := 0; i < p.cfg.SpacesWidth; i++ {
-			prefix = append(prefix, blank)
-		}
-	} else {
-		prefix = []byte{tab}
-	}
-
-	var res []byte
-	bol := true
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, prefix...)
-		}
-
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// unindent removes all the indentation from the tombstoned lines
-func (p *printer) unindent(buf []byte) []byte {
-	var res []byte
-	for i := 0; i < len(buf); i++ {
-		skip := len(buf)-i <= len(unindent)
-		if !skip {
-			skip = !bytes.Equal(unindent, buf[i:i+len(unindent)])
-		}
-		if skip {
-			res = append(res, buf[i])
-			continue
-		}
-
-		// We have a marker. we have to backtrace here and clean out
-		// any whitespace ahead of our tombstone up to a \n
-		for j := len(res) - 1; j >= 0; j-- {
-			if res[j] == '\n' {
-				break
-			}
-
-			res = res[:j]
-		}
-
-		// Skip the entire unindent marker
-		i += len(unindent) - 1
-	}
-
-	return res
-}
-
-// heredocIndent marks all the 2nd and further lines as unindentable
-func (p *printer) heredocIndent(buf []byte) []byte {
-	var res []byte
-	bol := false
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, unindent...)
-		}
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// isSingleLineObject tells whether the given object item is a single
-// line object such as "obj {}".
-//
-// A single line object:
-//
-//   * has no lead comments (hence multi-line)
-//   * has no assignment
-//   * has no values in the stanza (within {})
-//
-func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool {
-	// If there is a lead comment, can't be one line
-	if val.LeadComment != nil {
-		return false
-	}
-
-	// If there is assignment, we always break by line
-	if val.Assign.IsValid() {
-		return false
-	}
-
-	// If it isn't an object type, then its not a single line object
-	ot, ok := val.Val.(*ast.ObjectType)
-	if !ok {
-		return false
-	}
-
-	// If the object has no items, it is single line!
-	return len(ot.List.Items) == 0
-}
-
-func lines(txt string) int {
-	endline := 1
-	for i := 0; i < len(txt); i++ {
-		if txt[i] == '\n' {
-			endline++
-		}
-	}
-	return endline
-}
-
-// ----------------------------------------------------------------------------
-// Tracing support
-
-func (p *printer) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	i := 2 * p.indentTrace
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *printer, msg string) *printer {
-	p.printTrace(msg, "(")
-	p.indentTrace++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *printer) {
-	p.indentTrace--
-	p.printTrace(")")
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
deleted file mode 100644
index 6617ab8e..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Package printer implements printing of AST nodes to HCL format.
-package printer
-
-import (
-	"bytes"
-	"io"
-	"text/tabwriter"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-)
-
-var DefaultConfig = Config{
-	SpacesWidth: 2,
-}
-
-// A Config node controls the output of Fprint.
-type Config struct {
-	SpacesWidth int // if set, it will use spaces instead of tabs for alignment
-}
-
-func (c *Config) Fprint(output io.Writer, node ast.Node) error {
-	p := &printer{
-		cfg:                *c,
-		comments:           make([]*ast.CommentGroup, 0),
-		standaloneComments: make([]*ast.CommentGroup, 0),
-		// enableTrace:        true,
-	}
-
-	p.collectComments(node)
-
-	if _, err := output.Write(p.unindent(p.output(node))); err != nil {
-		return err
-	}
-
-	// flush tabwriter, if any
-	var err error
-	if tw, _ := output.(*tabwriter.Writer); tw != nil {
-		err = tw.Flush()
-	}
-
-	return err
-}
-
-// Fprint "pretty-prints" an HCL node to output
-// It calls Config.Fprint with default settings.
-func Fprint(output io.Writer, node ast.Node) error {
-	return DefaultConfig.Fprint(output, node)
-}
-
-// Format formats src HCL and returns the result.
-func Format(src []byte) ([]byte, error) {
-	node, err := parser.Parse(src)
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-	if err := DefaultConfig.Fprint(&buf, node); err != nil {
-		return nil, err
-	}
-
-	// Add trailing newline to result
-	buf.WriteString("\n")
-	return buf.Bytes(), nil
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
deleted file mode 100644
index 624a18fe..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
+++ /dev/null
@@ -1,652 +0,0 @@
-// Package scanner implements a scanner for HCL (HashiCorp Configuration
-// Language) source text.
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"regexp"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == utf8.RuneError && size == 1 {
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	if ch == '\x00' {
-		s.err("unexpected null character (0x00)")
-		return eof
-	}
-
-	if ch == '\uE123' {
-		s.err("unicode code point U+E123 reserved for internal use")
-		return utf8.RuneError
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		tok = token.IDENT
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '#', '/':
-			tok = token.COMMENT
-			s.scanComment(ch)
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '<':
-			tok = token.HEREDOC
-			s.scanHeredoc()
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case '=':
-			tok = token.ASSIGN
-		case '+':
-			tok = token.ADD
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				tok = token.SUB
-			}
-		default:
-			s.err("illegal char")
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-func (s *Scanner) scanComment(ch rune) {
-	// single line comments
-	if ch == '#' || (ch == '/' && s.peek() != '*') {
-		if ch == '/' && s.peek() != '/' {
-			s.err("expected '/' for comment")
-			return
-		}
-
-		ch = s.next()
-		for ch != '\n' && ch >= 0 && ch != eof {
-			ch = s.next()
-		}
-		if ch != eof && ch >= 0 {
-			s.unread()
-		}
-		return
-	}
-
-	// be sure we get the character after /* This allows us to find comment's
-	// that are not erminated
-	if ch == '/' {
-		s.next()
-		ch = s.next() // read character after "/*"
-	}
-
-	// look for /* - style comments
-	for {
-		if ch < 0 || ch == eof {
-			s.err("comment not terminated")
-			break
-		}
-
-		ch0 := ch
-		ch = s.next()
-		if ch0 == '*' && ch == '/' {
-			break
-		}
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	if ch == '0' {
-		// check for hexadecimal, octal or float
-		ch = s.next()
-		if ch == 'x' || ch == 'X' {
-			// hexadecimal
-			ch = s.next()
-			found := false
-			for isHexadecimal(ch) {
-				ch = s.next()
-				found = true
-			}
-
-			if !found {
-				s.err("illegal hexadecimal number")
-			}
-
-			if ch != eof {
-				s.unread()
-			}
-
-			return token.NUMBER
-		}
-
-		// now it's either something like: 0421(octal) or 0.1231(float)
-		illegalOctal := false
-		for isDecimal(ch) {
-			ch = s.next()
-			if ch == '8' || ch == '9' {
-				// this is just a possibility. For example 0159 is illegal, but
-				// 0159.23 is valid. So we mark a possible illegal octal. If
-				// the next character is not a period, we'll print the error.
-				illegalOctal = true
-			}
-		}
-
-		if ch == 'e' || ch == 'E' {
-			ch = s.scanExponent(ch)
-			return token.FLOAT
-		}
-
-		if ch == '.' {
-			ch = s.scanFraction(ch)
-
-			if ch == 'e' || ch == 'E' {
-				ch = s.next()
-				ch = s.scanExponent(ch)
-			}
-			return token.FLOAT
-		}
-
-		if illegalOctal {
-			s.err("illegal octal number")
-		}
-
-		if ch != eof {
-			s.unread()
-		}
-		return token.NUMBER
-	}
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanHeredoc scans a heredoc string
-func (s *Scanner) scanHeredoc() {
-	// Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) {
-				break
-			}
-
-			// Not an anchor match, record the start of a new line
-			lineStart = s.srcPos.Offset
-		}
-
-		if ch == eof {
-			s.err("heredoc not terminated")
-			return
-		}
-	}
-
-	return
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if (ch == '\n' && braces == 0) || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' && braces == 0 {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	start := n
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		if ch == eof {
-			// If we see an EOF, we halt any more scanning of digits
-			// immediately.
-			break
-		}
-
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	if n != start && ch != eof {
-		// we scanned all digits, put the last non digit char back,
-		// only if we read anything at all
-		s.unread()
-	}
-
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isDigit returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isDecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
deleted file mode 100644
index 5f981eaa..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package strconv
-
-import (
-	"errors"
-	"unicode/utf8"
-)
-
-// ErrSyntax indicates that a value does not have the right syntax for the target type.
-var ErrSyntax = errors.New("invalid syntax")
-
-// Unquote interprets s as a single-quoted, double-quoted,
-// or backquoted Go string literal, returning the string value
-// that s quotes.  (If s is single-quoted, it would be a Go
-// character literal; Unquote returns the corresponding
-// one-character string.)
-func Unquote(s string) (t string, err error) {
-	n := len(s)
-	if n < 2 {
-		return "", ErrSyntax
-	}
-	quote := s[0]
-	if quote != s[n-1] {
-		return "", ErrSyntax
-	}
-	s = s[1 : n-1]
-
-	if quote != '"' {
-		return "", ErrSyntax
-	}
-	if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') {
-		return "", ErrSyntax
-	}
-
-	// Is it trivial?  Avoid allocation.
-	if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
-		switch quote {
-		case '"':
-			return s, nil
-		case '\'':
-			r, size := utf8.DecodeRuneInString(s)
-			if size == len(s) && (r != utf8.RuneError || size != 1) {
-				return s, nil
-			}
-		}
-	}
-
-	var runeTmp [utf8.UTFMax]byte
-	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
-	for len(s) > 0 {
-		// If we're starting a '${}' then let it through un-unquoted.
-		// Specifically: we don't unquote any characters within the `${}`
-		// section.
-		if s[0] == '$' && len(s) > 1 && s[1] == '{' {
-			buf = append(buf, '$', '{')
-			s = s[2:]
-
-			// Continue reading until we find the closing brace, copying as-is
-			braces := 1
-			for len(s) > 0 && braces > 0 {
-				r, size := utf8.DecodeRuneInString(s)
-				if r == utf8.RuneError {
-					return "", ErrSyntax
-				}
-
-				s = s[size:]
-
-				n := utf8.EncodeRune(runeTmp[:], r)
-				buf = append(buf, runeTmp[:n]...)
-
-				switch r {
-				case '{':
-					braces++
-				case '}':
-					braces--
-				}
-			}
-			if braces != 0 {
-				return "", ErrSyntax
-			}
-			if len(s) == 0 {
-				// If there's no string left, we're done!
-				break
-			} else {
-				// If there's more left, we need to pop back up to the top of the loop
-				// in case there's another interpolation in this string.
-				continue
-			}
-		}
-
-		if s[0] == '\n' {
-			return "", ErrSyntax
-		}
-
-		c, multibyte, ss, err := unquoteChar(s, quote)
-		if err != nil {
-			return "", err
-		}
-		s = ss
-		if c < utf8.RuneSelf || !multibyte {
-			buf = append(buf, byte(c))
-		} else {
-			n := utf8.EncodeRune(runeTmp[:], c)
-			buf = append(buf, runeTmp[:n]...)
-		}
-		if quote == '\'' && len(s) != 0 {
-			// single-quoted must be single character
-			return "", ErrSyntax
-		}
-	}
-	return string(buf), nil
-}
-
-// contains reports whether the string contains the byte c.
-func contains(s string, c byte) bool {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			return true
-		}
-	}
-	return false
-}
-
-func unhex(b byte) (v rune, ok bool) {
-	c := rune(b)
-	switch {
-	case '0' <= c && c <= '9':
-		return c - '0', true
-	case 'a' <= c && c <= 'f':
-		return c - 'a' + 10, true
-	case 'A' <= c && c <= 'F':
-		return c - 'A' + 10, true
-	}
-	return
-}
-
-func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
-	// easy cases
-	switch c := s[0]; {
-	case c == quote && (quote == '\'' || quote == '"'):
-		err = ErrSyntax
-		return
-	case c >= utf8.RuneSelf:
-		r, size := utf8.DecodeRuneInString(s)
-		return r, true, s[size:], nil
-	case c != '\\':
-		return rune(s[0]), false, s[1:], nil
-	}
-
-	// hard case: c is backslash
-	if len(s) <= 1 {
-		err = ErrSyntax
-		return
-	}
-	c := s[1]
-	s = s[2:]
-
-	switch c {
-	case 'a':
-		value = '\a'
-	case 'b':
-		value = '\b'
-	case 'f':
-		value = '\f'
-	case 'n':
-		value = '\n'
-	case 'r':
-		value = '\r'
-	case 't':
-		value = '\t'
-	case 'v':
-		value = '\v'
-	case 'x', 'u', 'U':
-		n := 0
-		switch c {
-		case 'x':
-			n = 2
-		case 'u':
-			n = 4
-		case 'U':
-			n = 8
-		}
-		var v rune
-		if len(s) < n {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < n; j++ {
-			x, ok := unhex(s[j])
-			if !ok {
-				err = ErrSyntax
-				return
-			}
-			v = v<<4 | x
-		}
-		s = s[n:]
-		if c == 'x' {
-			// single-byte string, possibly not UTF-8
-			value = v
-			break
-		}
-		if v > utf8.MaxRune {
-			err = ErrSyntax
-			return
-		}
-		value = v
-		multibyte = true
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		v := rune(c) - '0'
-		if len(s) < 2 {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < 2; j++ { // one digit already; two more
-			x := rune(s[j]) - '0'
-			if x < 0 || x > 7 {
-				err = ErrSyntax
-				return
-			}
-			v = (v << 3) | x
-		}
-		s = s[2:]
-		if v > 255 {
-			err = ErrSyntax
-			return
-		}
-		value = v
-	case '\\':
-		value = '\\'
-	case '\'', '"':
-		if c != quote {
-			err = ErrSyntax
-			return
-		}
-		value = rune(c)
-	default:
-		err = ErrSyntax
-		return
-	}
-	tail = s
-	return
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/history-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go
deleted file mode 100644
index e37c0664..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package token defines constants representing the lexical tokens for HCL
-// (HashiCorp Configuration Language)
-package token
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-
-	hclstrconv "github.com/hashicorp/hcl/hcl/strconv"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-	JSON bool
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-	COMMENT
-
-	identifier_beg
-	IDENT // literals
-	literal_beg
-	NUMBER  // 12345
-	FLOAT   // 123.45
-	BOOL    // true,false
-	STRING  // "abc"
-	HEREDOC // < 0 {
-			// Pop the current item
-			n := len(frontier)
-			item := frontier[n-1]
-			frontier = frontier[:n-1]
-
-			switch v := item.Val.(type) {
-			case *ast.ObjectType:
-				items, frontier = flattenObjectType(v, item, items, frontier)
-			case *ast.ListType:
-				items, frontier = flattenListType(v, item, items, frontier)
-			default:
-				items = append(items, item)
-			}
-		}
-
-		// Reverse the list since the frontier model runs things backwards
-		for i := len(items)/2 - 1; i >= 0; i-- {
-			opp := len(items) - 1 - i
-			items[i], items[opp] = items[opp], items[i]
-		}
-
-		// Done! Set the original items
-		list.Items = items
-		return n, true
-	})
-}
-
-func flattenListType(
-	ot *ast.ListType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list is empty, keep the original list
-	if len(ot.List) == 0 {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List {
-		if _, ok := subitem.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, elem := range ot.List {
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        item.Keys,
-			Assign:      item.Assign,
-			Val:         elem,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
-
-func flattenObjectType(
-	ot *ast.ObjectType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list has no items we do not have to flatten anything
-	if ot.List.Items == nil {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List.Items {
-		if _, ok := subitem.Val.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, subitem := range ot.List.Items {
-		// Copy the new key
-		keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
-		copy(keys, item.Keys)
-		copy(keys[len(item.Keys):], subitem.Keys)
-
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        keys,
-			Assign:      item.Assign,
-			Val:         subitem.Val,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/history-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go
deleted file mode 100644
index 125a5f07..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go
+++ /dev/null
@@ -1,313 +0,0 @@
-package parser
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-	"github.com/hashicorp/hcl/json/scanner"
-	"github.com/hashicorp/hcl/json/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = fmt.Errorf("%s: %s", pos, msg)
-	}
-
-	// The root must be an object in JSON
-	object, err := p.object()
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	// We make our final node an object list so it is more HCL compatible
-	f.Node = object.List
-
-	// Flatten it, which finds patterns and turns them into more HCL-like
-	// AST trees.
-	flattenObjects(f.Node)
-
-	return f, nil
-}
-
-func (p *Parser) objectList() (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// Check for a followup comma. If it isn't a comma, then we're done
-		if tok := p.scan(); tok.Type != token.COMMA {
-			break
-		}
-	}
-
-	return node, nil
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	switch p.tok.Type {
-	case token.COLON:
-		pos := p.tok.Pos
-		o.Assign = hcltoken.Pos{
-			Filename: pos.Filename,
-			Offset:   pos.Offset,
-			Line:     pos.Line,
-			Column:   pos.Column,
-		}
-
-		o.Val, err = p.objectValue()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			return nil, errEofToken
-		case token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{
-				Token: p.tok.HCLToken(),
-			})
-		case token.COLON:
-			// If we have a zero keycount it means that we never got
-			// an object key, i.e. `{ :`. This is a syntax error.
-			if keyCount == 0 {
-				return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-			}
-
-			// Done
-			return keys, nil
-		case token.ILLEGAL:
-			return nil, errors.New("illegal")
-		default:
-			return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) objectValue() (ast.Node, error) {
-	defer un(trace(p, "ParseObjectValue"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok)
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.LBRACE:
-		return p.objectType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok)
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{}
-
-	l, err := p.objectList()
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	o.List = l
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{}
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.NUMBER, token.FLOAT, token.STRING:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.COMMA:
-			continue
-		case token.LBRACE:
-			node, err := p.objectType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.BOOL:
-			// TODO(arslan) should we support? not supported by HCL yet
-		case token.LBRACK:
-			// TODO(arslan) should we support nested lists? Even though it's
-			// written in README of HCL, it's not a part of the grammar
-			// (not defined in parse.y)
-		case token.RBRACK:
-			// finished
-			return l, nil
-		default:
-			return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type)
-		}
-
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok.HCLToken(),
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	p.tok = p.sc.Scan()
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/history-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
deleted file mode 100644
index fe3f0f09..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
+++ /dev/null
@@ -1,451 +0,0 @@
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/json/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	if ch == utf8.RuneError && size == 1 {
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		} else if lit == "null" {
-			tok = token.NULL
-		} else {
-			s.err("illegal char")
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case ':':
-			tok = token.COLON
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				s.err("illegal char")
-			}
-		default:
-			s.err("illegal char: " + string(ch))
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	zero := ch == '0'
-	pos := s.srcPos
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-
-	// If we have a larger number and this is zero, error
-	if zero && pos != s.srcPos {
-		s.err("numbers cannot start with 0")
-	}
-
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if ch == '\n' || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	// we scanned all digits, put the last non digit char back
-	s.unread()
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/json/token/position.go b/history-api/vendor/github.com/hashicorp/hcl/json/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/json/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/json/token/token.go b/history-api/vendor/github.com/hashicorp/hcl/json/token/token.go
deleted file mode 100644
index 95a0c3ee..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/json/token/token.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package token
-
-import (
-	"fmt"
-	"strconv"
-
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-
-	identifier_beg
-	literal_beg
-	NUMBER // 12345
-	FLOAT  // 123.45
-	BOOL   // true,false
-	STRING // "abc"
-	NULL   // null
-	literal_end
-	identifier_end
-
-	operator_beg
-	LBRACK // [
-	LBRACE // {
-	COMMA  // ,
-	PERIOD // .
-	COLON  // :
-
-	RBRACK // ]
-	RBRACE // }
-
-	operator_end
-)
-
-var tokens = [...]string{
-	ILLEGAL: "ILLEGAL",
-
-	EOF: "EOF",
-
-	NUMBER: "NUMBER",
-	FLOAT:  "FLOAT",
-	BOOL:   "BOOL",
-	STRING: "STRING",
-	NULL:   "NULL",
-
-	LBRACK: "LBRACK",
-	LBRACE: "LBRACE",
-	COMMA:  "COMMA",
-	PERIOD: "PERIOD",
-	COLON:  "COLON",
-
-	RBRACK: "RBRACK",
-	RBRACE: "RBRACE",
-}
-
-// String returns the string corresponding to the token tok.
-func (t Type) String() string {
-	s := ""
-	if 0 <= t && t < Type(len(tokens)) {
-		s = tokens[t]
-	}
-	if s == "" {
-		s = "token(" + strconv.Itoa(int(t)) + ")"
-	}
-	return s
-}
-
-// IsIdentifier returns true for tokens corresponding to identifiers and basic
-// type literals; it returns false otherwise.
-func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end }
-
-// IsLiteral returns true for tokens corresponding to basic type literals; it
-// returns false otherwise.
-func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end }
-
-// IsOperator returns true for tokens corresponding to operators and
-// delimiters; it returns false otherwise.
-func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end }
-
-// String returns the token's literal text. Note that this is only
-// applicable for certain token types, such as token.IDENT,
-// token.STRING, etc..
-func (t Token) String() string {
-	return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
-}
-
-// HCLToken converts this token to an HCL token.
-//
-// The token type must be a literal type or this will panic.
-func (t Token) HCLToken() hcltoken.Token {
-	switch t.Type {
-	case BOOL:
-		return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text}
-	case FLOAT:
-		return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text}
-	case NULL:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: ""}
-	case NUMBER:
-		return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text}
-	case STRING:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true}
-	default:
-		panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type))
-	}
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/lex.go b/history-api/vendor/github.com/hashicorp/hcl/lex.go
deleted file mode 100644
index d9993c29..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/lex.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package hcl
-
-import (
-	"unicode"
-	"unicode/utf8"
-)
-
-type lexModeValue byte
-
-const (
-	lexModeUnknown lexModeValue = iota
-	lexModeHcl
-	lexModeJson
-)
-
-// lexMode returns whether we're going to be parsing in JSON
-// mode or HCL mode.
-func lexMode(v []byte) lexModeValue {
-	var (
-		r      rune
-		w      int
-		offset int
-	)
-
-	for {
-		r, w = utf8.DecodeRune(v[offset:])
-		offset += w
-		if unicode.IsSpace(r) {
-			continue
-		}
-		if r == '{' {
-			return lexModeJson
-		}
-		break
-	}
-
-	return lexModeHcl
-}
diff --git a/history-api/vendor/github.com/hashicorp/hcl/parse.go b/history-api/vendor/github.com/hashicorp/hcl/parse.go
deleted file mode 100644
index 1fca53c4..00000000
--- a/history-api/vendor/github.com/hashicorp/hcl/parse.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package hcl
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hclParser "github.com/hashicorp/hcl/hcl/parser"
-	jsonParser "github.com/hashicorp/hcl/json/parser"
-)
-
-// ParseBytes accepts as input byte slice and returns ast tree.
-//
-// Input can be either JSON or HCL
-func ParseBytes(in []byte) (*ast.File, error) {
-	return parse(in)
-}
-
-// ParseString accepts input as a string and returns ast tree.
-func ParseString(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
-
-func parse(in []byte) (*ast.File, error) {
-	switch lexMode(in) {
-	case lexModeHcl:
-		return hclParser.Parse(in)
-	case lexModeJson:
-		return jsonParser.Parse(in)
-	}
-
-	return nil, fmt.Errorf("unknown config format")
-}
-
-// Parse parses the given input and returns the root object.
-//
-// The input format can be either HCL or JSON.
-func Parse(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/.golangci.yml b/history-api/vendor/github.com/jackc/pgx/v5/.golangci.yml
new file mode 100644
index 00000000..ca74c703
--- /dev/null
+++ b/history-api/vendor/github.com/jackc/pgx/v5/.golangci.yml
@@ -0,0 +1,21 @@
+# See for configurations: https://golangci-lint.run/usage/configuration/
+version: 2
+
+# See: https://golangci-lint.run/usage/formatters/
+formatters:
+  default: none
+  enable:
+    - gofmt # https://pkg.go.dev/cmd/gofmt
+    - gofumpt # https://github.com/mvdan/gofumpt
+
+  settings:
+    gofmt:
+      simplify: true # Simplify code: gofmt with `-s` option.
+
+    gofumpt:
+      # Module path which contains the source code being formatted.
+      # Default: ""
+      module-path: github.com/jackc/pgx/v5 # Should match with module in go.mod
+      # Choose whether to use the extra rules.
+      # Default: false
+      extra-rules: true
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md b/history-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
index a0ff9ba3..6c9c99b5 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
+++ b/history-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
@@ -1,3 +1,54 @@
+# 5.7.6 (September 8, 2025)
+
+* Use ParseConfigError in pgx.ParseConfig and pgxpool.ParseConfig (Yurasov Ilia)
+* Add PrepareConn hook to pgxpool (Jonathan Hall)
+* Reduce allocations in QueryContext (Dominique Lefevre)
+* Add MarshalJSON and UnmarshalJSON for pgtype.Uint32 (Panos Koutsovasilis)
+* Configure ping behavior on pgxpool with ShouldPing (Christian Kiely)
+* zeronull int types implement Int64Valuer and Int64Scanner (Li Zeghong)
+* Fix panic when receiving terminate connection message during CopyFrom (Michal Drausowski)
+* Fix statement cache not being invalidated on error during batch (Muhammadali Nazarov)
+
+# 5.7.5 (May 17, 2025)
+
+* Support sslnegotiation connection option (divyam234)
+* Update golang.org/x/crypto to v0.37.0. This placates security scanners that were unable to see that pgx did not use the behavior affected by https://pkg.go.dev/vuln/GO-2025-3487.
+* TraceLog now logs Acquire and Release at the debug level (dave sinclair)
+* Add support for PGTZ environment variable
+* Add support for PGOPTIONS environment variable
+* Unpin memory used by Rows quicker
+* Remove PlanScan memoization. This resolves a rare issue where scanning could be broken for one type by first scanning another. The problem was in the memoization system and benchmarking revealed that memoization was not providing any meaningful benefit.
+
+# 5.7.4 (March 24, 2025)
+
+* Fix / revert change to scanning JSON `null` (Felix Röhrich)
+
+# 5.7.3 (March 21, 2025)
+
+* Expose EmptyAcquireWaitTime in pgxpool.Stat (vamshiaruru32)
+* Improve SQL sanitizer performance (ninedraft)
+* Fix Scan confusion with json(b), sql.Scanner, and automatic dereferencing (moukoublen, felix-roehrich)
+* Fix Values() for xml type always returning nil instead of []byte
+* Add ability to send Flush message in pipeline mode (zenkovev)
+* Fix pgtype.Timestamp's JSON behavior to match PostgreSQL (pconstantinou)
+* Better error messages when scanning structs (logicbomb)
+* Fix handling of error on batch write (bonnefoa)
+* Match libpq's connection fallback behavior more closely (felix-roehrich)
+* Add MinIdleConns to pgxpool (djahandarie)
+
+# 5.7.2 (December 21, 2024)
+
+* Fix prepared statement already exists on batch prepare failure
+* Add commit query to tx options (Lucas Hild)
+* Fix pgtype.Timestamp json unmarshal (Shean de Montigny-Desautels)
+* Add message body size limits in frontend and backend (zene)
+* Add xid8 type
+* Ensure planning encodes and scans cannot infinitely recurse
+* Implement pgtype.UUID.String() (Konstantin Grachev)
+* Switch from ExecParams to Exec in ValidateConnectTargetSessionAttrs functions (Alexander Rumyantsev)
+* Update golang.org/x/crypto
+* Fix json(b) columns prefer sql.Scanner interface like database/sql (Ludovico Russo)
+
 # 5.7.1 (September 10, 2024)
 
 * Fix data race in tracelog.TraceLog
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/README.md b/history-api/vendor/github.com/jackc/pgx/v5/README.md
index 0cf2c291..cb709e21 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/README.md
+++ b/history-api/vendor/github.com/jackc/pgx/v5/README.md
@@ -84,7 +84,7 @@ It is also possible to use the `database/sql` interface and convert a connection
 
 ## Testing
 
-See CONTRIBUTING.md for setup instructions.
+See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions.
 
 ## Architecture
 
@@ -92,7 +92,7 @@ See the presentation at Golang Estonia, [PGX Top to Bottom](https://www.youtube.
 
 ## Supported Go and PostgreSQL Versions
 
-pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.21 and higher and PostgreSQL 12 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
+pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.23 and higher and PostgreSQL 13 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
 
 ## Version Policy
 
@@ -126,7 +126,8 @@ pgerrcode contains constants for the PostgreSQL error codes.
 
 ## Adapters for 3rd Party Tracers
 
-* [https://github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx)
 
 ## Adapters for 3rd Party Loggers
 
@@ -156,7 +157,7 @@ Library for scanning data from a database into Go structs and more.
 A carefully designed SQL client for making using SQL easier,
 more productive, and less error-prone on Golang.
 
-### [https://github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
+### [github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
 
 Adds GSSAPI / Kerberos authentication support.
 
@@ -169,6 +170,22 @@ Explicit data mapping and scanning library for Go structs and slices.
 Type safe and flexible package for scanning database data into Go types.
 Supports, structs, maps, slices and custom mapping functions.
 
-### [https://github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
+### [github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
 
 Code first migration library for native pgx (no database/sql abstraction).
+
+### [github.com/amirsalarsafaei/sqlc-pgx-monitoring](https://github.com/amirsalarsafaei/sqlc-pgx-monitoring)
+
+A database monitoring/metrics library for pgx and sqlc. Trace, log and monitor your sqlc query performance using OpenTelemetry.
+
+### [https://github.com/nikolayk812/pgx-outbox](https://github.com/nikolayk812/pgx-outbox)
+
+Simple Golang implementation for transactional outbox pattern for PostgreSQL using jackc/pgx driver.
+
+### [https://github.com/Arlandaren/pgxWrappy](https://github.com/Arlandaren/pgxWrappy)
+
+Simplifies working with the pgx library, providing convenient scanning of nested structures.
+
+## [https://github.com/KoNekoD/pgx-colon-query-rewriter](https://github.com/KoNekoD/pgx-colon-query-rewriter)
+
+Implementation of the pgx query rewriter to use ':' instead of '@' in named query parameters.
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/Rakefile b/history-api/vendor/github.com/jackc/pgx/v5/Rakefile
index d957573e..3e3aa503 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/Rakefile
+++ b/history-api/vendor/github.com/jackc/pgx/v5/Rakefile
@@ -2,7 +2,7 @@ require "erb"
 
 rule '.go' => '.go.erb' do |task|
   erb = ERB.new(File.read(task.source))
-  File.write(task.name, "// Do not edit. Generated from #{task.source}\n" + erb.result(binding))
+  File.write(task.name, "// Code generated from #{task.source}. DO NOT EDIT.\n\n" + erb.result(binding))
   sh "goimports", "-w", task.name
 end
 
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/batch.go b/history-api/vendor/github.com/jackc/pgx/v5/batch.go
index c3c2834f..1b1cbd84 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/batch.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/batch.go
@@ -43,6 +43,10 @@ func (qq *QueuedQuery) QueryRow(fn func(row Row) error) {
 }
 
 // Exec sets fn to be called when the response to qq is received.
+//
+// Note: for simple batch insert uses where it is not required to handle
+// each potential error individually, it's sufficient to not set any callbacks,
+// and just handle the return value of BatchResults.Close.
 func (qq *QueuedQuery) Exec(fn func(ct pgconn.CommandTag) error) {
 	qq.Fn = func(br BatchResults) error {
 		ct, err := br.Exec()
@@ -83,7 +87,7 @@ func (b *Batch) Len() int {
 
 type BatchResults interface {
 	// Exec reads the results from the next query in the batch as if the query has been sent with Conn.Exec. Prefer
-	// calling Exec on the QueuedQuery.
+	// calling Exec on the QueuedQuery, or just calling Close.
 	Exec() (pgconn.CommandTag, error)
 
 	// Query reads the results from the next query in the batch as if the query has been sent with Conn.Query. Prefer
@@ -98,6 +102,9 @@ type BatchResults interface {
 	// QueuedQuery.Query, QueuedQuery.QueryRow, or QueuedQuery.Exec will be called. If a callback function returns an
 	// error or the batch encounters an error subsequent callback functions will not be called.
 	//
+	// For simple batch inserts inside a transaction or similar queries, it's sufficient to not set any callbacks,
+	// and just handle the return value of Close.
+	//
 	// Close must be called before the underlying connection can be used again. Any error that occurred during a batch
 	// operation may have made it impossible to resyncronize the connection with the server. In this case the underlying
 	// connection will have been closed.
@@ -207,7 +214,6 @@ func (br *batchResults) Query() (Rows, error) {
 func (br *batchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -220,6 +226,8 @@ func (br *batchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err != nil {
@@ -378,7 +386,6 @@ func (br *pipelineBatchResults) Query() (Rows, error) {
 func (br *pipelineBatchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -391,6 +398,8 @@ func (br *pipelineBatchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err == nil && br.lastRows != nil && br.lastRows.err != nil {
@@ -441,3 +450,20 @@ func (br *pipelineBatchResults) nextQueryAndArgs() (query string, args []any, er
 	br.qqIdx++
 	return bi.SQL, bi.Arguments, nil
 }
+
+// invalidates statement and description caches on batch results error
+func invalidateCachesOnBatchResultsError(conn *Conn, b *Batch, err error) {
+	if err != nil && conn != nil && b != nil {
+		if sc := conn.statementCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+
+		if sc := conn.descriptionCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+	}
+}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/conn.go b/history-api/vendor/github.com/jackc/pgx/v5/conn.go
index 187b3dd5..67b22529 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/conn.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/conn.go
@@ -172,7 +172,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "statement_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse statement_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse statement_cache_capacity", err)
 		}
 		statementCacheCapacity = int(n)
 	}
@@ -182,7 +182,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "description_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse description_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse description_cache_capacity", err)
 		}
 		descriptionCacheCapacity = int(n)
 	}
@@ -202,7 +202,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		case "simple_protocol":
 			defaultQueryExecMode = QueryExecModeSimpleProtocol
 		default:
-			return nil, fmt.Errorf("invalid default_query_exec_mode: %s", s)
+			return nil, pgconn.NewParseConfigError(connString, "invalid default_query_exec_mode", err)
 		}
 	}
 
@@ -420,7 +420,7 @@ func (c *Conn) IsClosed() bool {
 	return c.pgConn.IsClosed()
 }
 
-func (c *Conn) die(err error) {
+func (c *Conn) die() {
 	if c.IsClosed() {
 		return
 	}
@@ -588,14 +588,6 @@ func (c *Conn) execPrepared(ctx context.Context, sd *pgconn.StatementDescription
 	return result.CommandTag, result.Err
 }
 
-type unknownArgumentTypeQueryExecModeExecError struct {
-	arg any
-}
-
-func (e *unknownArgumentTypeQueryExecModeExecError) Error() string {
-	return fmt.Sprintf("cannot use unregistered type %T as query argument in QueryExecModeExec", e.arg)
-}
-
 func (c *Conn) execSQLParams(ctx context.Context, sql string, args []any) (pgconn.CommandTag, error) {
 	err := c.eqb.Build(c.typeMap, nil, args)
 	if err != nil {
@@ -650,21 +642,33 @@ const (
 	// registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are
 	// unregistered or ambiguous. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know
 	// the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot.
+	//
+	// On rare occasions user defined types may behave differently when encoded in the text format instead of the binary
+	// format. For example, this could happen if a "type RomanNumeral int32" implements fmt.Stringer to format integers as
+	// Roman numerals (e.g. 7 is VII). The binary format would properly encode the integer 7 as the binary value for 7.
+	// But the text format would encode the integer 7 as the string "VII". As QueryExecModeExec uses the text format, it
+	// is possible that changing query mode from another mode to QueryExecModeExec could change the behavior of the query.
+	// This should not occur with types pgx supports directly and can be avoided by registering the types with
+	// pgtype.Map.RegisterDefaultPgType and implementing the appropriate type interfaces. In the cas of RomanNumeral, it
+	// should implement pgtype.Int64Valuer.
 	QueryExecModeExec
 
-	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments.
-	// Queries are executed in a single round trip. Type mappings can be registered with
+	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments. This is
+	// especially significant for []byte values. []byte values are encoded as PostgreSQL bytea. string must be used
+	// instead for text type values including json and jsonb. Type mappings can be registered with
 	// pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambiguous.
-	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use
-	// a map[string]string directly as an argument. This mode cannot.
+	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use a
+	// map[string]string directly as an argument. This mode cannot. Queries are executed in a single round trip.
 	//
-	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec with minor
-	// exceptions such as behavior when multiple result returning queries are erroneously sent in a single string.
+	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec. This includes
+	// the warning regarding differences in text format and binary format encoding with user defined types. There may be
+	// other minor exceptions such as behavior when multiple result returning queries are erroneously sent in a single
+	// string.
 	//
 	// QueryExecModeSimpleProtocol uses client side parameter interpolation. All values are quoted and escaped. Prefer
-	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol
-	// should only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does
-	// not support the extended protocol.
+	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol should
+	// only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does not
+	// support the extended protocol.
 	QueryExecModeSimpleProtocol
 )
 
@@ -904,6 +908,9 @@ func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) Row {
 // SendBatch sends all queued queries to the server at once. All queries are run in an implicit transaction unless
 // explicit transaction control statements are executed. The returned BatchResults must be closed before the connection
 // is used again.
+//
+// Depending on the QueryExecMode, all queries may be prepared before any are executed. This means that creating a table
+// and using it in a subsequent query in the same batch can fail.
 func (c *Conn) SendBatch(ctx context.Context, b *Batch) (br BatchResults) {
 	if c.batchTracer != nil {
 		ctx = c.batchTracer.TraceBatchStart(ctx, c, TraceBatchStartData{Batch: b})
@@ -1126,47 +1133,64 @@ func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, d
 
 	// Prepare any needed queries
 	if len(distinctNewQueries) > 0 {
-		for _, sd := range distinctNewQueries {
-			pipeline.SendPrepare(sd.Name, sd.SQL, nil)
-		}
+		err := func() (err error) {
+			for _, sd := range distinctNewQueries {
+				pipeline.SendPrepare(sd.Name, sd.SQL, nil)
+			}
 
-		err := pipeline.Sync()
-		if err != nil {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
-		}
+			// Store all statements we are preparing into the cache. It's fine if it overflows because HandleInvalidated will
+			// clean them up later.
+			if sdCache != nil {
+				for _, sd := range distinctNewQueries {
+					sdCache.Put(sd)
+				}
+			}
+
+			// If something goes wrong preparing the statements, we need to invalidate the cache entries we just added.
+			defer func() {
+				if err != nil && sdCache != nil {
+					for _, sd := range distinctNewQueries {
+						sdCache.Invalidate(sd.SQL)
+					}
+				}
+			}()
+
+			err = pipeline.Sync()
+			if err != nil {
+				return err
+			}
+
+			for _, sd := range distinctNewQueries {
+				results, err := pipeline.GetResults()
+				if err != nil {
+					return err
+				}
+
+				resultSD, ok := results.(*pgconn.StatementDescription)
+				if !ok {
+					return fmt.Errorf("expected statement description, got %T", results)
+				}
+
+				// Fill in the previously empty / pending statement descriptions.
+				sd.ParamOIDs = resultSD.ParamOIDs
+				sd.Fields = resultSD.Fields
+			}
 
-		for _, sd := range distinctNewQueries {
 			results, err := pipeline.GetResults()
 			if err != nil {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
+				return err
 			}
 
-			resultSD, ok := results.(*pgconn.StatementDescription)
+			_, ok := results.(*pgconn.PipelineSync)
 			if !ok {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected statement description, got %T", results), closed: true}
+				return fmt.Errorf("expected sync, got %T", results)
 			}
 
-			// Fill in the previously empty / pending statement descriptions.
-			sd.ParamOIDs = resultSD.ParamOIDs
-			sd.Fields = resultSD.Fields
-		}
-
-		results, err := pipeline.GetResults()
+			return nil
+		}()
 		if err != nil {
 			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
 		}
-
-		_, ok := results.(*pgconn.PipelineSync)
-		if !ok {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected sync, got %T", results), closed: true}
-		}
-	}
-
-	// Put all statements into the cache. It's fine if it overflows because HandleInvalidated will clean them up later.
-	if sdCache != nil {
-		for _, sd := range distinctNewQueries {
-			sdCache.Put(sd)
-		}
 	}
 
 	// Queue the queries.
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/derived_types.go b/history-api/vendor/github.com/jackc/pgx/v5/derived_types.go
index 22ab069c..72c0a242 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/derived_types.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/derived_types.go
@@ -161,7 +161,7 @@ type derivedTypeInfo struct {
 // The result of this call can be passed into RegisterTypes to complete the process.
 func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Type, error) {
 	m := c.TypeMap()
-	if typeNames == nil || len(typeNames) == 0 {
+	if len(typeNames) == 0 {
 		return nil, fmt.Errorf("No type names were supplied.")
 	}
 
@@ -169,13 +169,7 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 	// the SQL not support recent structures such as multirange
 	serverVersion, _ := serverVersion(c)
 	sql := buildLoadDerivedTypesSQL(serverVersion, typeNames)
-	var rows Rows
-	var err error
-	if typeNames == nil {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol)
-	} else {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
-	}
+	rows, err := c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
 	if err != nil {
 		return nil, fmt.Errorf("While generating load types query: %w", err)
 	}
@@ -232,15 +226,15 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 		default:
 			return nil, fmt.Errorf("Unknown typtype %q was found while registering %q", ti.Typtype, ti.TypeName)
 		}
-		if type_ != nil {
-			m.RegisterType(type_)
-			if ti.NspName != "" {
-				nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
-				m.RegisterType(nspType)
-				result = append(result, nspType)
-			}
-			result = append(result, type_)
+
+		// the type_ is imposible to be null
+		m.RegisterType(type_)
+		if ti.NspName != "" {
+			nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
+			m.RegisterType(nspType)
+			result = append(result, nspType)
 		}
+		result = append(result, type_)
 	}
 	return result, nil
 }
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/doc.go b/history-api/vendor/github.com/jackc/pgx/v5/doc.go
index 0e91d64e..5d2ae388 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/doc.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/doc.go
@@ -183,7 +183,7 @@ For debug tracing of the actual PostgreSQL wire protocol messages see github.com
 
 Lower Level PostgreSQL Functionality
 
-github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn in
+github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn is
 implemented on top of pgconn. The Conn.PgConn() method can be used to access this lower layer.
 
 PgBouncer
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh b/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
new file mode 100644
index 00000000..ec0f7b03
--- /dev/null
+++ b/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+current_branch=$(git rev-parse --abbrev-ref HEAD)
+if [ "$current_branch" == "HEAD" ]; then
+    current_branch=$(git rev-parse HEAD)
+fi
+
+restore_branch() {
+    echo "Restoring original branch/commit: $current_branch"
+    git checkout "$current_branch"
+}
+trap restore_branch EXIT
+
+# Check if there are uncommitted changes
+if ! git diff --quiet || ! git diff --cached --quiet; then
+    echo "There are uncommitted changes. Please commit or stash them before running this script."
+    exit 1
+fi
+
+# Ensure that at least one commit argument is passed
+if [ "$#" -lt 1 ]; then
+    echo "Usage: $0   ... "
+    exit 1
+fi
+
+commits=("$@")
+benchmarks_dir=benchmarks
+
+if ! mkdir -p "${benchmarks_dir}"; then
+    echo "Unable to create dir for benchmarks data"
+    exit 1
+fi
+
+# Benchmark results
+bench_files=()
+
+# Run benchmark for each listed commit
+for i in "${!commits[@]}"; do
+    commit="${commits[i]}"
+    git checkout "$commit" || {
+        echo "Failed to checkout $commit"
+        exit 1
+    }
+
+    # Sanitized commmit message
+    commit_message=$(git log -1 --pretty=format:"%s" | tr -c '[:alnum:]-_' '_')
+
+    # Benchmark data will go there
+    bench_file="${benchmarks_dir}/${i}_${commit_message}.bench"
+
+    if ! go test -bench=. -count=10 >"$bench_file"; then
+        echo "Benchmarking failed for commit $commit"
+        exit 1
+    fi
+
+    bench_files+=("$bench_file")
+done
+
+# go install golang.org/x/perf/cmd/benchstat[@latest]
+benchstat "${bench_files[@]}"
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
index df58c448..b516817c 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
@@ -4,8 +4,10 @@ import (
 	"bytes"
 	"encoding/hex"
 	"fmt"
+	"slices"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 	"unicode/utf8"
 )
@@ -24,18 +26,33 @@ type Query struct {
 // https://github.com/jackc/pgx/issues/1380
 const replacementcharacterwidth = 3
 
+const maxBufSize = 16384 // 16 Ki
+
+var bufPool = &pool[*bytes.Buffer]{
+	new: func() *bytes.Buffer {
+		return &bytes.Buffer{}
+	},
+	reset: func(b *bytes.Buffer) bool {
+		n := b.Len()
+		b.Reset()
+		return n < maxBufSize
+	},
+}
+
+var null = []byte("null")
+
 func (q *Query) Sanitize(args ...any) (string, error) {
 	argUse := make([]bool, len(args))
-	buf := &bytes.Buffer{}
+	buf := bufPool.get()
+	defer bufPool.put(buf)
 
 	for _, part := range q.Parts {
-		var str string
 		switch part := part.(type) {
 		case string:
-			str = part
+			buf.WriteString(part)
 		case int:
 			argIdx := part - 1
-
+			var p []byte
 			if argIdx < 0 {
 				return "", fmt.Errorf("first sql argument must be > 0")
 			}
@@ -43,34 +60,41 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 			if argIdx >= len(args) {
 				return "", fmt.Errorf("insufficient arguments")
 			}
+
+			// Prevent SQL injection via Line Comment Creation
+			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
+			buf.WriteByte(' ')
+
 			arg := args[argIdx]
 			switch arg := arg.(type) {
 			case nil:
-				str = "null"
+				p = null
 			case int64:
-				str = strconv.FormatInt(arg, 10)
+				p = strconv.AppendInt(buf.AvailableBuffer(), arg, 10)
 			case float64:
-				str = strconv.FormatFloat(arg, 'f', -1, 64)
+				p = strconv.AppendFloat(buf.AvailableBuffer(), arg, 'f', -1, 64)
 			case bool:
-				str = strconv.FormatBool(arg)
+				p = strconv.AppendBool(buf.AvailableBuffer(), arg)
 			case []byte:
-				str = QuoteBytes(arg)
+				p = QuoteBytes(buf.AvailableBuffer(), arg)
 			case string:
-				str = QuoteString(arg)
+				p = QuoteString(buf.AvailableBuffer(), arg)
 			case time.Time:
-				str = arg.Truncate(time.Microsecond).Format("'2006-01-02 15:04:05.999999999Z07:00:00'")
+				p = arg.Truncate(time.Microsecond).
+					AppendFormat(buf.AvailableBuffer(), "'2006-01-02 15:04:05.999999999Z07:00:00'")
 			default:
 				return "", fmt.Errorf("invalid arg type: %T", arg)
 			}
 			argUse[argIdx] = true
 
+			buf.Write(p)
+
 			// Prevent SQL injection via Line Comment Creation
 			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
-			str = " " + str + " "
+			buf.WriteByte(' ')
 		default:
 			return "", fmt.Errorf("invalid Part type: %T", part)
 		}
-		buf.WriteString(str)
 	}
 
 	for i, used := range argUse {
@@ -82,26 +106,99 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 }
 
 func NewQuery(sql string) (*Query, error) {
-	l := &sqlLexer{
-		src:     sql,
-		stateFn: rawState,
+	query := &Query{}
+	query.init(sql)
+
+	return query, nil
+}
+
+var sqlLexerPool = &pool[*sqlLexer]{
+	new: func() *sqlLexer {
+		return &sqlLexer{}
+	},
+	reset: func(sl *sqlLexer) bool {
+		*sl = sqlLexer{}
+		return true
+	},
+}
+
+func (q *Query) init(sql string) {
+	parts := q.Parts[:0]
+	if parts == nil {
+		// dirty, but fast heuristic to preallocate for ~90% usecases
+		n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1
+		parts = make([]Part, 0, n)
 	}
 
+	l := sqlLexerPool.get()
+	defer sqlLexerPool.put(l)
+
+	l.src = sql
+	l.stateFn = rawState
+	l.parts = parts
+
 	for l.stateFn != nil {
 		l.stateFn = l.stateFn(l)
 	}
 
-	query := &Query{Parts: l.parts}
-
-	return query, nil
+	q.Parts = l.parts
 }
 
-func QuoteString(str string) string {
-	return "'" + strings.ReplaceAll(str, "'", "''") + "'"
+func QuoteString(dst []byte, str string) []byte {
+	const quote = '\''
+
+	// Preallocate space for the worst case scenario
+	dst = slices.Grow(dst, len(str)*2+2)
+
+	// Add opening quote
+	dst = append(dst, quote)
+
+	// Iterate through the string without allocating
+	for i := 0; i < len(str); i++ {
+		if str[i] == quote {
+			dst = append(dst, quote, quote)
+		} else {
+			dst = append(dst, str[i])
+		}
+	}
+
+	// Add closing quote
+	dst = append(dst, quote)
+
+	return dst
 }
 
-func QuoteBytes(buf []byte) string {
-	return `'\x` + hex.EncodeToString(buf) + "'"
+func QuoteBytes(dst, buf []byte) []byte {
+	if len(buf) == 0 {
+		return append(dst, `'\x'`...)
+	}
+
+	// Calculate required length
+	requiredLen := 3 + hex.EncodedLen(len(buf)) + 1
+
+	// Ensure dst has enough capacity
+	if cap(dst)-len(dst) < requiredLen {
+		newDst := make([]byte, len(dst), len(dst)+requiredLen)
+		copy(newDst, dst)
+		dst = newDst
+	}
+
+	// Record original length and extend slice
+	origLen := len(dst)
+	dst = dst[:origLen+requiredLen]
+
+	// Add prefix
+	dst[origLen] = '\''
+	dst[origLen+1] = '\\'
+	dst[origLen+2] = 'x'
+
+	// Encode bytes directly into dst
+	hex.Encode(dst[origLen+3:len(dst)-1], buf)
+
+	// Add suffix
+	dst[len(dst)-1] = '\''
+
+	return dst
 }
 
 type sqlLexer struct {
@@ -319,13 +416,45 @@ func multilineCommentState(l *sqlLexer) stateFn {
 	}
 }
 
+var queryPool = &pool[*Query]{
+	new: func() *Query {
+		return &Query{}
+	},
+	reset: func(q *Query) bool {
+		n := len(q.Parts)
+		q.Parts = q.Parts[:0]
+		return n < 64 // drop too large queries
+	},
+}
+
 // SanitizeSQL replaces placeholder values with args. It quotes and escapes args
 // as necessary. This function is only safe when standard_conforming_strings is
 // on.
 func SanitizeSQL(sql string, args ...any) (string, error) {
-	query, err := NewQuery(sql)
-	if err != nil {
-		return "", err
-	}
+	query := queryPool.get()
+	query.init(sql)
+	defer queryPool.put(query)
+
 	return query.Sanitize(args...)
 }
+
+type pool[E any] struct {
+	p     sync.Pool
+	new   func() E
+	reset func(E) bool
+}
+
+func (pool *pool[E]) get() E {
+	v, ok := pool.p.Get().(E)
+	if !ok {
+		v = pool.new()
+	}
+
+	return v
+}
+
+func (p *pool[E]) put(v E) {
+	if p.reset(v) {
+		p.p.Put(v)
+	}
+}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go b/history-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
index dec83f47..17fec937 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
@@ -31,7 +31,6 @@ func (c *LRUCache) Get(key string) *pgconn.StatementDescription {
 	}
 
 	return nil
-
 }
 
 // Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache or
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
index 06498361..f846ba81 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
@@ -263,7 +263,7 @@ func computeClientProof(saltedPassword, authMessage []byte) []byte {
 	return buf
 }
 
-func computeServerSignature(saltedPassword []byte, authMessage []byte) []byte {
+func computeServerSignature(saltedPassword, authMessage []byte) []byte {
 	serverKey := computeHMAC(saltedPassword, []byte("Server Key"))
 	serverSignature := computeHMAC(serverKey, authMessage)
 	buf := make([]byte, base64.StdEncoding.EncodedLen(len(serverSignature)))
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
index 6a198e67..3937dc40 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
@@ -23,9 +23,11 @@ import (
 	"github.com/jackc/pgx/v5/pgproto3"
 )
 
-type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type GetSSLPasswordFunc func(ctx context.Context) string
+type (
+	AfterConnectFunc    func(ctx context.Context, pgconn *PgConn) error
+	ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
+	GetSSLPasswordFunc  func(ctx context.Context) string
+)
 
 // Config is the settings used to establish a connection to a PostgreSQL server. It must be created by [ParseConfig]. A
 // manually initialized Config will cause ConnectConfig to panic.
@@ -51,6 +53,8 @@ type Config struct {
 	KerberosSpn     string
 	Fallbacks       []*FallbackConfig
 
+	SSLNegotiation string // sslnegotiation=postgres or sslnegotiation=direct
+
 	// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
 	// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
 	// fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs.
@@ -177,7 +181,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //
 // ParseConfig supports specifying multiple hosts in similar manner to libpq. Host and port may include comma separated
 // values that will be tried in order. This can be used as part of a high availability system. See
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
 //
 //	# Example URL
 //	postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb
@@ -198,13 +202,15 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //	PGSSLKEY
 //	PGSSLROOTCERT
 //	PGSSLPASSWORD
+//	PGOPTIONS
 //	PGAPPNAME
 //	PGCONNECT_TIMEOUT
 //	PGTARGETSESSIONATTRS
+//	PGTZ
 //
-// See http://www.postgresql.org/docs/11/static/libpq-envars.html for details on the meaning of environment variables.
+// See http://www.postgresql.org/docs/current/static/libpq-envars.html for details on the meaning of environment variables.
 //
-// See https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
+// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
 // usually but not always the environment variable name downcased and without the "PG" prefix.
 //
 // Important Security Notes:
@@ -212,7 +218,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 // ParseConfig tries to match libpq behavior with regard to PGSSLMODE. This includes defaulting to "prefer" behavior if
 // not set.
 //
-// See http://www.postgresql.org/docs/11/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
+// See http://www.postgresql.org/docs/current/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
 // security each sslmode provides.
 //
 // The sslmode "prefer" (the default), sslmode "allow", and multiple hosts are implemented via the Fallbacks field of
@@ -318,6 +324,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		"sslkey":               {},
 		"sslcert":              {},
 		"sslrootcert":          {},
+		"sslnegotiation":       {},
 		"sslpassword":          {},
 		"sslsni":               {},
 		"krbspn":               {},
@@ -386,6 +393,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 	config.Port = fallbacks[0].Port
 	config.TLSConfig = fallbacks[0].TLSConfig
 	config.Fallbacks = fallbacks[1:]
+	config.SSLNegotiation = settings["sslnegotiation"]
 
 	passfile, err := pgpassfile.ReadPassfile(settings["passfile"])
 	if err == nil {
@@ -449,9 +457,12 @@ func parseEnvSettings() map[string]string {
 		"PGSSLSNI":             "sslsni",
 		"PGSSLROOTCERT":        "sslrootcert",
 		"PGSSLPASSWORD":        "sslpassword",
+		"PGSSLNEGOTIATION":     "sslnegotiation",
 		"PGTARGETSESSIONATTRS": "target_session_attrs",
 		"PGSERVICE":            "service",
 		"PGSERVICEFILE":        "servicefile",
+		"PGTZ":                 "timezone",
+		"PGOPTIONS":            "options",
 	}
 
 	for envname, realname := range nameMap {
@@ -646,6 +657,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 	sslkey := settings["sslkey"]
 	sslpassword := settings["sslpassword"]
 	sslsni := settings["sslsni"]
+	sslnegotiation := settings["sslnegotiation"]
 
 	// Match libpq default behavior
 	if sslmode == "" {
@@ -657,6 +669,13 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 
 	tlsConfig := &tls.Config{}
 
+	if sslnegotiation == "direct" {
+		tlsConfig.NextProtos = []string{"postgresql"}
+		if sslmode == "prefer" {
+			sslmode = "require"
+		}
+	}
+
 	if sslrootcert != "" {
 		var caCertPool *x509.CertPool
 
@@ -696,7 +715,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 		// According to PostgreSQL documentation, if a root CA file exists,
 		// the behavior of sslmode=require should be the same as that of verify-ca
 		//
-		// See https://www.postgresql.org/docs/12/libpq-ssl.html
+		// See https://www.postgresql.org/docs/current/libpq-ssl.html
 		if sslrootcert != "" {
 			goto nextCase
 		}
@@ -767,8 +786,8 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 			if sslpassword != "" {
 				decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
 			}
-			//if sslpassword not provided or has decryption error when use it
-			//try to find sslpassword with callback function
+			// if sslpassword not provided or has decryption error when use it
+			// try to find sslpassword with callback function
 			if sslpassword == "" || decryptedError != nil {
 				if parseConfigOptions.GetSSLPassword != nil {
 					sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
@@ -861,12 +880,12 @@ func makeConnectTimeoutDialFunc(timeout time.Duration) DialFunc {
 // ValidateConnectTargetSessionAttrsReadWrite is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-write.
 func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "on" {
+	if string(result[0].Rows[0][0]) == "on" {
 		return errors.New("read only connection")
 	}
 
@@ -876,12 +895,12 @@ func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgC
 // ValidateConnectTargetSessionAttrsReadOnly is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-only.
 func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "on" {
+	if string(result[0].Rows[0][0]) != "on" {
 		return errors.New("connection is not read only")
 	}
 
@@ -891,12 +910,12 @@ func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgCo
 // ValidateConnectTargetSessionAttrsStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=standby.
 func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return errors.New("server is not in hot standby mode")
 	}
 
@@ -906,12 +925,12 @@ func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPrimary is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=primary.
 func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "t" {
+	if string(result[0].Rows[0][0]) == "t" {
 		return errors.New("server is in standby mode")
 	}
 
@@ -921,12 +940,12 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPreferStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=prefer-standby.
 func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return &NotPreferredError{err: errors.New("server is not in hot standby mode")}
 	}
 
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
index ec4a6d47..d968d3f0 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
@@ -27,7 +27,7 @@ func Timeout(err error) bool {
 }
 
 // PgError represents an error reported by the PostgreSQL server. See
-// http://www.postgresql.org/docs/11/static/protocol-error-fields.html for
+// http://www.postgresql.org/docs/current/static/protocol-error-fields.html for
 // detailed field description.
 type PgError struct {
 	Severity            string
@@ -112,6 +112,14 @@ type ParseConfigError struct {
 	err        error
 }
 
+func NewParseConfigError(conn, msg string, err error) error {
+	return &ParseConfigError{
+		ConnString: conn,
+		msg:        msg,
+		err:        err,
+	}
+}
+
 func (e *ParseConfigError) Error() string {
 	// Now that ParseConfigError is public and ConnString is available to the developer, perhaps it would be better only
 	// return a static string. That would ensure that the error message cannot leak a password. The ConnString field would
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
index 3c1af347..efb0d61b 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
@@ -28,7 +28,7 @@ func RegisterGSSProvider(newGSSArg NewGSSFunc) {
 
 // GSS provides GSSAPI authentication (e.g., Kerberos).
 type GSS interface {
-	GetInitToken(host string, service string) ([]byte, error)
+	GetInitToken(host, service string) ([]byte, error)
 	GetInitTokenFromSPN(spn string) ([]byte, error)
 	Continue(inToken []byte) (done bool, outToken []byte, err error)
 }
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
index 7efb522a..97141c64 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
@@ -1,6 +1,7 @@
 package pgconn
 
 import (
+	"container/list"
 	"context"
 	"crypto/md5"
 	"crypto/tls"
@@ -134,7 +135,7 @@ func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptio
 //
 // If config.Fallbacks are present they will sequentially be tried in case of error establishing network connection. An
 // authentication error will terminate the chain of attempts (like libpq:
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
 func ConnectConfig(ctx context.Context, config *Config) (*PgConn, error) {
 	// Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from
 	// zero values.
@@ -267,12 +268,15 @@ func connectPreferred(ctx context.Context, config *Config, connectOneConfigs []*
 
 		var pgErr *PgError
 		if errors.As(err, &pgErr) {
-			const ERRCODE_INVALID_PASSWORD = "28P01"                    // wrong password
-			const ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION = "28000" // wrong password or bad pg_hba.conf settings
-			const ERRCODE_INVALID_CATALOG_NAME = "3D000"                // db does not exist
-			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501"              // missing connect privilege
+			// pgx will try next host even if libpq does not in certain cases (see #2246)
+			// consider change for the next major version
+
+			const ERRCODE_INVALID_PASSWORD = "28P01"
+			const ERRCODE_INVALID_CATALOG_NAME = "3D000"   // db does not exist
+			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501" // missing connect privilege
+
+			// auth failed due to invalid password, db does not exist or user has no permission
 			if pgErr.Code == ERRCODE_INVALID_PASSWORD ||
-				pgErr.Code == ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION && c.tlsConfig != nil ||
 				pgErr.Code == ERRCODE_INVALID_CATALOG_NAME ||
 				pgErr.Code == ERRCODE_INSUFFICIENT_PRIVILEGE {
 				return nil, allErrors
@@ -321,7 +325,15 @@ func connectOne(ctx context.Context, config *Config, connectConfig *connectOneCo
 	if connectConfig.tlsConfig != nil {
 		pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn})
 		pgConn.contextWatcher.Watch(ctx)
-		tlsConn, err := startTLS(pgConn.conn, connectConfig.tlsConfig)
+		var (
+			tlsConn net.Conn
+			err     error
+		)
+		if config.SSLNegotiation == "direct" {
+			tlsConn = tls.Client(pgConn.conn, connectConfig.tlsConfig)
+		} else {
+			tlsConn, err = startTLS(pgConn.conn, connectConfig.tlsConfig)
+		}
 		pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
 		if err != nil {
 			pgConn.conn.Close()
@@ -979,7 +991,8 @@ func noticeResponseToNotice(msg *pgproto3.NoticeResponse) *Notice {
 
 // CancelRequest sends a cancel request to the PostgreSQL server. It returns an error if unable to deliver the cancel
 // request, but lack of an error does not ensure that the query was canceled. As specified in the documentation, there
-// is no way to be sure a query was canceled. See https://www.postgresql.org/docs/11/protocol-flow.html#id-1.10.5.7.9
+// is no way to be sure a query was canceled.
+// See https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-CANCELING-REQUESTS
 func (pgConn *PgConn) CancelRequest(ctx context.Context) error {
 	// Open a cancellation request to the same server. The address is taken from the net.Conn directly instead of reusing
 	// the connection config. This is important in high availability configurations where fallback connections may be
@@ -1128,7 +1141,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader {
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1154,7 +1167,7 @@ func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues []
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1361,7 +1374,14 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 				close(pgConn.cleanupDone)
 				return CommandTag{}, normalizeTimeoutError(ctx, err)
 			}
-			msg, _ := pgConn.receiveMessage()
+			// peekMessage never returns err in the bufferingReceive mode - it only forwards the bufferingReceive variables.
+			// Therefore, the only case for receiveMessage to return err is during handling of the ErrorResponse message type
+			// and using pgOnError handler to determine the connection is no longer valid (and thus closing the conn).
+			msg, serverError := pgConn.receiveMessage()
+			if serverError != nil {
+				close(abortCopyChan)
+				return CommandTag{}, serverError
+			}
 
 			switch msg := msg.(type) {
 			case *pgproto3.ErrorResponse:
@@ -1408,9 +1428,8 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 
 // MultiResultReader is a reader for a command that could return multiple results such as Exec or ExecBatch.
 type MultiResultReader struct {
-	pgConn   *PgConn
-	ctx      context.Context
-	pipeline *Pipeline
+	pgConn *PgConn
+	ctx    context.Context
 
 	rr *ResultReader
 
@@ -1443,12 +1462,8 @@ func (mrr *MultiResultReader) receiveMessage() (pgproto3.BackendMessage, error)
 	switch msg := msg.(type) {
 	case *pgproto3.ReadyForQuery:
 		mrr.closed = true
-		if mrr.pipeline != nil {
-			mrr.pipeline.expectedReadyForQueryCount--
-		} else {
-			mrr.pgConn.contextWatcher.Unwatch()
-			mrr.pgConn.unlock()
-		}
+		mrr.pgConn.contextWatcher.Unwatch()
+		mrr.pgConn.unlock()
 	case *pgproto3.ErrorResponse:
 		mrr.err = ErrorResponseToPgError(msg)
 	}
@@ -1672,7 +1687,11 @@ func (rr *ResultReader) receiveMessage() (msg pgproto3.BackendMessage, err error
 	case *pgproto3.EmptyQueryResponse:
 		rr.concludeCommand(CommandTag{}, nil)
 	case *pgproto3.ErrorResponse:
-		rr.concludeCommand(CommandTag{}, ErrorResponseToPgError(msg))
+		pgErr := ErrorResponseToPgError(msg)
+		if rr.pipeline != nil {
+			rr.pipeline.state.HandleError(pgErr)
+		}
+		rr.concludeCommand(CommandTag{}, pgErr)
 	}
 
 	return msg, nil
@@ -1701,7 +1720,7 @@ type Batch struct {
 }
 
 // ExecParams appends an ExecParams command to the batch. See PgConn.ExecParams for parameter descriptions.
-func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1714,7 +1733,7 @@ func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uin
 }
 
 // ExecPrepared appends an ExecPrepared e command to the batch. See PgConn.ExecPrepared for parameter descriptions.
-func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1773,9 +1792,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 
 	batch.buf, batch.err = (&pgproto3.Sync{}).Encode(batch.buf)
 	if batch.err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, batch.err)
 		multiResult.closed = true
-		multiResult.err = batch.err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1783,9 +1803,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 	defer pgConn.exitPotentialWriteReadDeadlock()
 	_, err := pgConn.conn.Write(batch.buf)
 	if err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, err)
 		multiResult.closed = true
-		multiResult.err = err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1999,9 +2020,7 @@ type Pipeline struct {
 	conn *PgConn
 	ctx  context.Context
 
-	expectedReadyForQueryCount int
-	pendingSync                bool
-
+	state  pipelineState
 	err    error
 	closed bool
 }
@@ -2012,6 +2031,122 @@ type PipelineSync struct{}
 // CloseComplete is returned by GetResults when a CloseComplete message is received.
 type CloseComplete struct{}
 
+type pipelineRequestType int
+
+const (
+	pipelineNil pipelineRequestType = iota
+	pipelinePrepare
+	pipelineQueryParams
+	pipelineQueryPrepared
+	pipelineDeallocate
+	pipelineSyncRequest
+	pipelineFlushRequest
+)
+
+type pipelineRequestEvent struct {
+	RequestType       pipelineRequestType
+	WasSentToServer   bool
+	BeforeFlushOrSync bool
+}
+
+type pipelineState struct {
+	requestEventQueue          list.List
+	lastRequestType            pipelineRequestType
+	pgErr                      *PgError
+	expectedReadyForQueryCount int
+}
+
+func (s *pipelineState) Init() {
+	s.requestEventQueue.Init()
+	s.lastRequestType = pipelineNil
+}
+
+func (s *pipelineState) RegisterSendingToServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.WasSentToServer {
+			return
+		}
+		val.WasSentToServer = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) registerFlushingBufferOnServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.BeforeFlushOrSync {
+			return
+		}
+		val.BeforeFlushOrSync = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) PushBackRequestType(req pipelineRequestType) {
+	if req == pipelineNil {
+		return
+	}
+
+	if req != pipelineFlushRequest {
+		s.requestEventQueue.PushBack(pipelineRequestEvent{RequestType: req})
+	}
+	if req == pipelineFlushRequest || req == pipelineSyncRequest {
+		s.registerFlushingBufferOnServer()
+	}
+	s.lastRequestType = req
+
+	if req == pipelineSyncRequest {
+		s.expectedReadyForQueryCount++
+	}
+}
+
+func (s *pipelineState) ExtractFrontRequestType() pipelineRequestType {
+	for {
+		elem := s.requestEventQueue.Front()
+		if elem == nil {
+			return pipelineNil
+		}
+		val := elem.Value.(pipelineRequestEvent)
+		if !(val.WasSentToServer && val.BeforeFlushOrSync) {
+			return pipelineNil
+		}
+
+		s.requestEventQueue.Remove(elem)
+		if val.RequestType == pipelineSyncRequest {
+			s.pgErr = nil
+		}
+		if s.pgErr == nil {
+			return val.RequestType
+		}
+	}
+}
+
+func (s *pipelineState) HandleError(err *PgError) {
+	s.pgErr = err
+}
+
+func (s *pipelineState) HandleReadyForQuery() {
+	s.expectedReadyForQueryCount--
+}
+
+func (s *pipelineState) PendingSync() bool {
+	var notPendingSync bool
+
+	if elem := s.requestEventQueue.Back(); elem != nil {
+		val := elem.Value.(pipelineRequestEvent)
+		notPendingSync = (val.RequestType == pipelineSyncRequest) && val.WasSentToServer
+	} else {
+		notPendingSync = (s.lastRequestType == pipelineSyncRequest) || (s.lastRequestType == pipelineNil)
+	}
+
+	return !notPendingSync
+}
+
+func (s *pipelineState) ExpectedReadyForQuery() int {
+	return s.expectedReadyForQueryCount
+}
+
 // StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
 // to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
 // to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
@@ -2020,16 +2155,21 @@ type CloseComplete struct{}
 // Prefer ExecBatch when only sending one group of queries at once.
 func (pgConn *PgConn) StartPipeline(ctx context.Context) *Pipeline {
 	if err := pgConn.lock(); err != nil {
-		return &Pipeline{
+		pipeline := &Pipeline{
 			closed: true,
 			err:    err,
 		}
+		pipeline.state.Init()
+
+		return pipeline
 	}
 
 	pgConn.pipeline = Pipeline{
 		conn: pgConn,
 		ctx:  ctx,
 	}
+	pgConn.pipeline.state.Init()
+
 	pipeline := &pgConn.pipeline
 
 	if ctx != context.Background() {
@@ -2052,10 +2192,10 @@ func (p *Pipeline) SendPrepare(name, sql string, paramOIDs []uint32) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Name: name, Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelinePrepare)
 }
 
 // SendDeallocate deallocates a prepared statement.
@@ -2063,34 +2203,65 @@ func (p *Pipeline) SendDeallocate(name string) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelineDeallocate)
 }
 
 // SendQueryParams is the pipeline version of *PgConn.QueryParams.
-func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryParams)
 }
 
 // SendQueryPrepared is the pipeline version of *PgConn.QueryPrepared.
-func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendBind(&pgproto3.Bind{PreparedStatement: stmtName, ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryPrepared)
+}
+
+// SendFlushRequest sends a request for the server to flush its output buffer.
+//
+// The server flushes its output buffer automatically as a result of Sync being called,
+// or on any request when not in pipeline mode; this function is useful to cause the server
+// to flush its output buffer in pipeline mode without establishing a synchronization point.
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendFlushRequest.
+func (p *Pipeline) SendFlushRequest() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.Send(&pgproto3.Flush{})
+	p.state.PushBackRequestType(pipelineFlushRequest)
+}
+
+// SendPipelineSync marks a synchronization point in a pipeline by sending a sync message
+// without flushing the send buffer. This serves as the delimiter of an implicit
+// transaction and an error recovery point.
+//
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendPipelineSync.
+func (p *Pipeline) SendPipelineSync() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.SendSync(&pgproto3.Sync{})
+	p.state.PushBackRequestType(pipelineSyncRequest)
 }
 
 // Flush flushes the queued requests without establishing a synchronization point.
@@ -2115,28 +2286,14 @@ func (p *Pipeline) Flush() error {
 		return err
 	}
 
+	p.state.RegisterSendingToServer()
 	return nil
 }
 
 // Sync establishes a synchronization point and flushes the queued requests.
 func (p *Pipeline) Sync() error {
-	if p.closed {
-		if p.err != nil {
-			return p.err
-		}
-		return errors.New("pipeline closed")
-	}
-
-	p.conn.frontend.SendSync(&pgproto3.Sync{})
-	err := p.Flush()
-	if err != nil {
-		return err
-	}
-
-	p.pendingSync = false
-	p.expectedReadyForQueryCount++
-
-	return nil
+	p.SendPipelineSync()
+	return p.Flush()
 }
 
 // GetResults gets the next results. If results are present, results may be a *ResultReader, *StatementDescription, or
@@ -2150,7 +2307,7 @@ func (p *Pipeline) GetResults() (results any, err error) {
 		return nil, errors.New("pipeline closed")
 	}
 
-	if p.expectedReadyForQueryCount == 0 {
+	if p.state.ExtractFrontRequestType() == pipelineNil {
 		return nil, nil
 	}
 
@@ -2195,13 +2352,13 @@ func (p *Pipeline) getResults() (results any, err error) {
 		case *pgproto3.CloseComplete:
 			return &CloseComplete{}, nil
 		case *pgproto3.ReadyForQuery:
-			p.expectedReadyForQueryCount--
+			p.state.HandleReadyForQuery()
 			return &PipelineSync{}, nil
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		}
-
 	}
 }
 
@@ -2231,6 +2388,7 @@ func (p *Pipeline) getResultsPrepare() (*StatementDescription, error) {
 		// These should never happen here. But don't take chances that could lead to a deadlock.
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		case *pgproto3.CommandComplete:
 			p.conn.asyncClose()
@@ -2250,7 +2408,7 @@ func (p *Pipeline) Close() error {
 
 	p.closed = true
 
-	if p.pendingSync {
+	if p.state.PendingSync() {
 		p.conn.asyncClose()
 		p.err = errors.New("pipeline has unsynced requests")
 		p.conn.contextWatcher.Unwatch()
@@ -2259,7 +2417,7 @@ func (p *Pipeline) Close() error {
 		return p.err
 	}
 
-	for p.expectedReadyForQueryCount > 0 {
+	for p.state.ExpectedReadyForQuery() > 0 {
 		_, err := p.getResults()
 		if err != nil {
 			p.err = err
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
index ac2962e9..415e1a24 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationCleartextPassword is a message sent from the backend indicating that a clear-text password is required.
-type AuthenticationCleartextPassword struct {
-}
+type AuthenticationCleartextPassword struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationCleartextPassword) Backend() {}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
index ec11d39f..98c0b2d6 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationOk is a message sent from the backend indicating that authentication was successful.
-type AuthenticationOk struct {
-}
+type AuthenticationOk struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationOk) Backend() {}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
index d146c338..28cff049 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
@@ -175,7 +175,13 @@ func (b *Backend) Receive() (FrontendMessage, error) {
 		}
 
 		b.msgType = header[0]
-		b.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4
+
+		msgLength := int(binary.BigEndian.Uint32(header[1:]))
+		if msgLength < 4 {
+			return nil, fmt.Errorf("invalid message length: %d", msgLength)
+		}
+
+		b.bodyLen = msgLength - 4
 		if b.maxBodyLen > 0 && b.bodyLen > b.maxBodyLen {
 			return nil, &ExceededMaxBodyLenErr{b.maxBodyLen, b.bodyLen}
 		}
@@ -282,9 +288,10 @@ func (b *Backend) SetAuthType(authType uint32) error {
 	return nil
 }
 
-// SetMaxBodyLen sets the maximum length of a message body in octets. If a message body exceeds this length, Receive will return
-// an error. This is useful for protecting against malicious clients that send large messages with the intent of
-// causing memory exhaustion.
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against malicious clients that send
+// large messages with the intent of causing memory exhaustion.
 // The default value is 0.
 // If maxBodyLen is 0, then no maximum is enforced.
 func (b *Backend) SetMaxBodyLen(maxBodyLen int) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
index 040814db..c3421a9b 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
@@ -4,8 +4,7 @@ import (
 	"encoding/json"
 )
 
-type CopyDone struct {
-}
+type CopyDone struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*CopyDone) Backend() {}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
index b41abbe1..056e547c 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
@@ -54,6 +54,7 @@ type Frontend struct {
 	portalSuspended                 PortalSuspended
 
 	bodyLen    int
+	maxBodyLen int // maxBodyLen is the maximum length of a message body in octets. If a message body exceeds this length, Receive will return an error.
 	msgType    byte
 	partialMsg bool
 	authType   uint32
@@ -317,6 +318,9 @@ func (f *Frontend) Receive() (BackendMessage, error) {
 		}
 
 		f.bodyLen = msgLength - 4
+		if f.maxBodyLen > 0 && f.bodyLen > f.maxBodyLen {
+			return nil, &ExceededMaxBodyLenErr{f.maxBodyLen, f.bodyLen}
+		}
 		f.partialMsg = true
 	}
 
@@ -452,3 +456,13 @@ func (f *Frontend) GetAuthType() uint32 {
 func (f *Frontend) ReadBufferLen() int {
 	return f.cr.wp - f.cr.rp
 }
+
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against a corrupted server that sends
+// messages with incorrect length, which can cause memory exhaustion.
+// The default value is 0.
+// If maxBodyLen is 0, then no maximum is enforced.
+func (f *Frontend) SetMaxBodyLen(maxBodyLen int) {
+	f.maxBodyLen = maxBodyLen
+}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
index 70cb20cd..122d1341 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
@@ -10,8 +10,7 @@ import (
 
 const gssEncReqNumber = 80877104
 
-type GSSEncRequest struct {
-}
+type GSSEncRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*GSSEncRequest) Frontend() {}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
index d820d327..67b78515 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
@@ -12,7 +12,7 @@ type PasswordMessage struct {
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*PasswordMessage) Frontend() {}
 
-// Frontend identifies this message as an authentication response.
+// InitialResponse identifies this message as an authentication response.
 func (*PasswordMessage) InitialResponse() {}
 
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
index dc2a4ddf..c40a2261 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
@@ -56,7 +56,6 @@ func (*RowDescription) Backend() {}
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
 // type identifier and 4 byte message length.
 func (dst *RowDescription) Decode(src []byte) error {
-
 	if len(src) < 2 {
 		return &invalidMessageFormatErr{messageType: "RowDescription"}
 	}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
index b0fc2847..bdfc7c42 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
@@ -10,8 +10,7 @@ import (
 
 const sslRequestNumber = 80877103
 
-type SSLRequest struct {
-}
+type SSLRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*SSLRequest) Frontend() {}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
index 06b824ad..872a0889 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
@@ -374,8 +374,8 @@ func quoteArrayElementIfNeeded(src string) string {
 	return src
 }
 
-// Array represents a PostgreSQL array for T. It implements the ArrayGetter and ArraySetter interfaces. It preserves
-// PostgreSQL dimensions and custom lower bounds. Use FlatArray if these are not needed.
+// Array represents a PostgreSQL array for T. It implements the [ArrayGetter] and [ArraySetter] interfaces. It preserves
+// PostgreSQL dimensions and custom lower bounds. Use [FlatArray] if these are not needed.
 type Array[T any] struct {
 	Elements []T
 	Dims     []ArrayDimension
@@ -419,8 +419,8 @@ func (a Array[T]) ScanIndexType() any {
 	return new(T)
 }
 
-// FlatArray implements the ArrayGetter and ArraySetter interfaces for any slice of T. It ignores PostgreSQL dimensions
-// and custom lower bounds. Use Array to preserve these.
+// FlatArray implements the [ArrayGetter] and [ArraySetter] interfaces for any slice of T. It ignores PostgreSQL dimensions
+// and custom lower bounds. Use [Array] to preserve these.
 type FlatArray[T any] []T
 
 func (a FlatArray[T]) Dimensions() []ArrayDimension {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
index e7a1d016..2a48e354 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
@@ -23,16 +23,18 @@ type Bits struct {
 	Valid bool
 }
 
+// ScanBits implements the [BitsScanner] interface.
 func (b *Bits) ScanBits(v Bits) error {
 	*b = v
 	return nil
 }
 
+// BitsValue implements the [BitsValuer] interface.
 func (b Bits) BitsValue() (Bits, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bits) Scan(src any) error {
 	if src == nil {
 		*dst = Bits{}
@@ -47,7 +49,7 @@ func (dst *Bits) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bits) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBitsCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BitsCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
index 71caffa7..955f01fe 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
@@ -22,16 +22,18 @@ type Bool struct {
 	Valid bool
 }
 
+// ScanBool implements the [BoolScanner] interface.
 func (b *Bool) ScanBool(v Bool) error {
 	*b = v
 	return nil
 }
 
+// BoolValue implements the [BoolValuer] interface.
 func (b Bool) BoolValue() (Bool, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bool) Scan(src any) error {
 	if src == nil {
 		*dst = Bool{}
@@ -61,7 +63,7 @@ func (dst *Bool) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bool) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Bool) Value() (driver.Value, error) {
 	return src.Bool, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Bool) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -82,6 +85,7 @@ func (src Bool) MarshalJSON() ([]byte, error) {
 	}
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Bool) UnmarshalJSON(b []byte) error {
 	var v *bool
 	err := json.Unmarshal(b, &v)
@@ -200,7 +204,6 @@ func (encodePlanBoolCodecTextBool) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (BoolCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -328,7 +331,7 @@ func (scanPlanTextAnyToBoolScanner) Scan(src []byte, dst any) error {
 	return s.ScanBool(Bool{Bool: v, Valid: true})
 }
 
-// https://www.postgresql.org/docs/11/datatype-boolean.html
+// https://www.postgresql.org/docs/current/datatype-boolean.html
 func planTextToBool(src []byte) (bool, error) {
 	s := string(bytes.ToLower(bytes.TrimSpace(src)))
 
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
index 887d268b..d243f58e 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
@@ -24,16 +24,18 @@ type Box struct {
 	Valid bool
 }
 
+// ScanBox implements the [BoxScanner] interface.
 func (b *Box) ScanBox(v Box) error {
 	*b = v
 	return nil
 }
 
+// BoxValue implements the [BoxValuer] interface.
 func (b Box) BoxValue() (Box, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Box) Scan(src any) error {
 	if src == nil {
 		*dst = Box{}
@@ -48,7 +50,7 @@ func (dst *Box) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Box) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBoxCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BoxCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
index b39d3fa1..84964425 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
@@ -527,6 +527,7 @@ func (w *netIPNetWrapper) ScanNetipPrefix(v netip.Prefix) error {
 
 	return nil
 }
+
 func (w netIPNetWrapper) NetipPrefixValue() (netip.Prefix, error) {
 	ip, ok := netip.AddrFromSlice(w.IP)
 	if !ok {
@@ -881,7 +882,6 @@ func (a *anyMultiDimSliceArray) SetDimensions(dimensions []ArrayDimension) error
 
 		return nil
 	}
-
 }
 
 func (a *anyMultiDimSliceArray) makeMultidimensionalSlice(sliceType reflect.Type, dimensions []ArrayDimension, flatSlice reflect.Value, flatSliceIdx int) reflect.Value {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
index a247705e..6c4f0c5e 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
@@ -148,7 +148,6 @@ func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf
 }
 
 func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
index e8f118cc..fb9b4c11 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
@@ -25,16 +25,18 @@ type Circle struct {
 	Valid bool
 }
 
+// ScanCircle implements the [CircleScanner] interface.
 func (c *Circle) ScanCircle(v Circle) error {
 	*c = v
 	return nil
 }
 
+// CircleValue implements the [CircleValuer] interface.
 func (c Circle) CircleValue() (Circle, error) {
 	return c, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Circle) Scan(src any) error {
 	if src == nil {
 		*dst = Circle{}
@@ -49,7 +51,7 @@ func (dst *Circle) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Circle) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
index fb372325..598cf7af 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
@@ -276,7 +276,6 @@ func (c *CompositeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byt
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
 
 type CompositeBinaryScanner struct {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
index 784b16de..44705686 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
@@ -26,11 +26,13 @@ type Date struct {
 	Valid            bool
 }
 
+// ScanDate implements the [DateScanner] interface.
 func (d *Date) ScanDate(v Date) error {
 	*d = v
 	return nil
 }
 
+// DateValue implements the [DateValuer] interface.
 func (d Date) DateValue() (Date, error) {
 	return d, nil
 }
@@ -40,7 +42,7 @@ const (
 	infinityDayOffset         = 2147483647
 )
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Date) Scan(src any) error {
 	if src == nil {
 		*dst = Date{}
@@ -58,7 +60,7 @@ func (dst *Date) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Date) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Date) Value() (driver.Value, error) {
 	return src.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Date) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -89,6 +92,7 @@ func (src Date) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Date) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -223,7 +227,6 @@ func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
index 7687ea8f..83dfc5de 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
@@ -53,8 +53,8 @@ similar fashion to database/sql. The second is to use a pointer to a pointer.
         return err
     }
 
-When using nullable pgtype types as parameters for queries, one has to remember
-to explicitly set their Valid field to true, otherwise the parameter's value will be NULL.
+When using nullable pgtype types as parameters for queries, one has to remember to explicitly set their Valid field to
+true, otherwise the parameter's value will be NULL.
 
 JSON Support
 
@@ -159,11 +159,16 @@ example_child_records_test.go for an example.
 
 Overview of Scanning Implementation
 
-The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID
-from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for
-scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are
-interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner and
-PointValuer interfaces.
+The first step is to use the OID to lookup the correct Codec. The Map will call the Codec's PlanScan method to get a
+plan for scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types
+are interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner
+and PointValuer interfaces.
+
+If a Go value is not supported directly by a Codec then Map will try see if it is a sql.Scanner. If is then that
+interface will be used to scan the value. Most sql.Scanners require the input to be in the text format (e.g. UUIDs and
+numeric). However, pgx will typically have received the value in the binary format. In this case the binary value will be
+parsed, reencoded as text, and then passed to the sql.Scanner. This may incur additional overhead for query results with
+a large number of affected values.
 
 If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again.
 For example, Int8Codec does not support scanning into a renamed type (e.g. type myInt64 int64). But Map will detect that
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
index 8646d9d2..241a25ad 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
@@ -16,26 +16,29 @@ type Float4 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float4) ScanFloat64(n Float8) error {
 	*f = Float4{Float32: float32(n.Float64), Valid: n.Valid}
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float4) Float64Value() (Float8, error) {
 	return Float8{Float64: float64(f.Float32), Valid: f.Valid}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float4) ScanInt64(n Int8) error {
 	*f = Float4{Float32: float32(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float32), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float4) Scan(src any) error {
 	if src == nil {
 		*f = Float4{}
@@ -58,7 +61,7 @@ func (f *Float4) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float4) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -66,6 +69,7 @@ func (f Float4) Value() (driver.Value, error) {
 	return float64(f.Float32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float4) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -73,6 +77,7 @@ func (f Float4) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float32)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float4) UnmarshalJSON(b []byte) error {
 	var n *float32
 	err := json.Unmarshal(b, &n)
@@ -170,7 +175,6 @@ func (encodePlanFloat4CodecBinaryInt64Valuer) Encode(value any, buf []byte) (new
 }
 
 func (Float4Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
index 9c923c9a..54d6781e 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
@@ -24,26 +24,29 @@ type Float8 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float8) ScanFloat64(n Float8) error {
 	*f = n
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float8) Float64Value() (Float8, error) {
 	return f, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float8) ScanInt64(n Int8) error {
 	*f = Float8{Float64: float64(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float64), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float8) Scan(src any) error {
 	if src == nil {
 		*f = Float8{}
@@ -66,7 +69,7 @@ func (f *Float8) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float8) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -74,6 +77,7 @@ func (f Float8) Value() (driver.Value, error) {
 	return f.Float64, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float8) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -81,6 +85,7 @@ func (f Float8) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float64)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float8) UnmarshalJSON(b []byte) error {
 	var n *float64
 	err := json.Unmarshal(b, &n)
@@ -208,7 +213,6 @@ func (encodePlanTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (Float8Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
index 2f34f4c9..ef864928 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
@@ -22,16 +22,18 @@ type HstoreValuer interface {
 // associated with its keys.
 type Hstore map[string]*string
 
+// ScanHstore implements the [HstoreScanner] interface.
 func (h *Hstore) ScanHstore(v Hstore) error {
 	*h = v
 	return nil
 }
 
+// HstoreValue implements the [HstoreValuer] interface.
 func (h Hstore) HstoreValue() (Hstore, error) {
 	return h, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (h *Hstore) Scan(src any) error {
 	if src == nil {
 		*h = nil
@@ -46,7 +48,7 @@ func (h *Hstore) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (h Hstore) Value() (driver.Value, error) {
 	if h == nil {
 		return nil, nil
@@ -162,7 +164,6 @@ func (encodePlanHstoreCodecText) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (HstoreCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -298,7 +299,7 @@ func (p *hstoreParser) consume() (b byte, end bool) {
 	return b, false
 }
 
-func unexpectedByteErr(actualB byte, expectedB byte) error {
+func unexpectedByteErr(actualB, expectedB byte) error {
 	return fmt.Errorf("expected '%c' ('%#v'); found '%c' ('%#v')", expectedB, expectedB, actualB, actualB)
 }
 
@@ -316,7 +317,7 @@ func (p *hstoreParser) consumeExpectedByte(expectedB byte) error {
 
 // consumeExpected2 consumes two expected bytes or returns an error.
 // This was a bit faster than using a string argument (better inlining? Not sure).
-func (p *hstoreParser) consumeExpected2(one byte, two byte) error {
+func (p *hstoreParser) consumeExpected2(one, two byte) error {
 	if p.pos+2 > len(p.str) {
 		return errors.New("unexpected end of string")
 	}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
index 6ca10ea0..b92edb23 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
@@ -24,7 +24,7 @@ type NetipPrefixValuer interface {
 	NetipPrefixValue() (netip.Prefix, error)
 }
 
-// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are netip.Prefix and netip.Addr. If
+// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are [netip.Prefix] and [netip.Addr]. If
 // IsValid() is false then they are treated as SQL NULL.
 type InetCodec struct{}
 
@@ -107,7 +107,6 @@ func (encodePlanInetCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (InetCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
index 90a20a26..d1b8eb61 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
@@ -1,4 +1,5 @@
-// Do not edit. Generated from pgtype/int.go.erb
+// Code generated from pgtype/int.go.erb. DO NOT EDIT.
+
 package pgtype
 
 import (
@@ -25,7 +26,7 @@ type Int2 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int2) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int2{}
@@ -43,11 +44,12 @@ func (dst *Int2) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int2) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int16), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int2) Scan(src any) error {
 	if src == nil {
 		*dst = Int2{}
@@ -86,7 +88,7 @@ func (dst *Int2) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int2) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -94,6 +96,7 @@ func (src Int2) Value() (driver.Value, error) {
 	return int64(src.Int16), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int2) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -101,6 +104,7 @@ func (src Int2) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int16), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int2) UnmarshalJSON(b []byte) error {
 	var n *int16
 	err := json.Unmarshal(b, &n)
@@ -585,7 +589,7 @@ type Int4 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int4) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int4{}
@@ -603,11 +607,12 @@ func (dst *Int4) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int32), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int4) Scan(src any) error {
 	if src == nil {
 		*dst = Int4{}
@@ -646,7 +651,7 @@ func (dst *Int4) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int4) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -654,6 +659,7 @@ func (src Int4) Value() (driver.Value, error) {
 	return int64(src.Int32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int4) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -661,6 +667,7 @@ func (src Int4) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int32), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int4) UnmarshalJSON(b []byte) error {
 	var n *int32
 	err := json.Unmarshal(b, &n)
@@ -1156,7 +1163,7 @@ type Int8 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int8) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int8{}
@@ -1174,11 +1181,12 @@ func (dst *Int8) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int64), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int8) Scan(src any) error {
 	if src == nil {
 		*dst = Int8{}
@@ -1217,7 +1225,7 @@ func (dst *Int8) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int8) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -1225,6 +1233,7 @@ func (src Int8) Value() (driver.Value, error) {
 	return int64(src.Int64), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int8) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -1232,6 +1241,7 @@ func (src Int8) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int64), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int8) UnmarshalJSON(b []byte) error {
 	var n *int64
 	err := json.Unmarshal(b, &n)
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
index e0c8b7a3..c2d40f60 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
@@ -27,7 +27,7 @@ type Int<%= pg_byte_size %> struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int<%= pg_byte_size %>{}
@@ -45,11 +45,12 @@ func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	if src == nil {
 		*dst = Int<%= pg_byte_size %>{}
@@ -88,7 +89,7 @@ func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +97,7 @@ func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	return int64(src.Int<%= pg_bit_size %>), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -103,6 +105,7 @@ func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error {
 	var n *int<%= pg_bit_size %>
 	err := json.Unmarshal(b, &n)
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
index 0175700a..6f401153 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
@@ -25,7 +25,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go
       rows, _ := conn.Query(
         ctx,
         `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>},  func() error { return nil })
       if err != nil {
@@ -49,7 +49,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array
       rows, _ := conn.Query(
         ctx,
         `select array_agg(n) from generate_series(1, <%= array_size %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{&v},  func() error { return nil })
       if err != nil {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
index 4b511629..ba5e818f 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
@@ -33,16 +33,18 @@ type Interval struct {
 	Valid        bool
 }
 
+// ScanInterval implements the [IntervalScanner] interface.
 func (interval *Interval) ScanInterval(v Interval) error {
 	*interval = v
 	return nil
 }
 
+// IntervalValue implements the [IntervalValuer] interface.
 func (interval Interval) IntervalValue() (Interval, error) {
 	return interval, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (interval *Interval) Scan(src any) error {
 	if src == nil {
 		*interval = Interval{}
@@ -57,7 +59,7 @@ func (interval *Interval) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (interval Interval) Value() (driver.Value, error) {
 	if !interval.Valid {
 		return nil, nil
@@ -157,7 +159,6 @@ func (encodePlanIntervalCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (IntervalCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
index c2aa0d3b..60aa2b71 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
@@ -71,6 +71,27 @@ func (c *JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Enco
 	}
 }
 
+// JSON needs its on scan plan for pointers to handle 'null'::json(b).
+// Consider making pointerPointerScanPlan more flexible in the future.
+type jsonPointerScanPlan struct {
+	next ScanPlan
+}
+
+func (p jsonPointerScanPlan) Scan(src []byte, dst any) error {
+	el := reflect.ValueOf(dst).Elem()
+	if src == nil || string(src) == "null" {
+		el.SetZero()
+		return nil
+	}
+
+	el.Set(reflect.New(el.Type().Elem()))
+	if p.next != nil {
+		return p.next.Scan(src, el.Interface())
+	}
+
+	return nil
+}
+
 type encodePlanJSONCodecEitherFormatString struct{}
 
 func (encodePlanJSONCodecEitherFormatString) Encode(value any, buf []byte) (newBuf []byte, err error) {
@@ -117,41 +138,35 @@ func (e *encodePlanJSONCodecEitherFormatMarshal) Encode(value any, buf []byte) (
 	return buf, nil
 }
 
-func (c *JSONCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+func (c *JSONCodec) PlanScan(m *Map, oid uint32, formatCode int16, target any) ScanPlan {
+	return c.planScan(m, oid, formatCode, target, 0)
+}
+
+// JSON cannot fallback to pointerPointerScanPlan because of 'null'::json(b),
+// so we need to duplicate the logic here.
+func (c *JSONCodec) planScan(m *Map, oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	switch target.(type) {
 	case *string:
-		return scanPlanAnyToString{}
-
-	case **string:
-		// This is to fix **string scanning. It seems wrong to special case **string, but it's not clear what a better
-		// solution would be.
-		//
-		// https://github.com/jackc/pgx/issues/1470 -- **string
-		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
-
-		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
-				if _, failed := nextPlan.(*scanPlanFail); !failed {
-					wrapperPlan.SetNext(nextPlan)
-					return wrapperPlan
-				}
-			}
-		}
-
+		return &scanPlanAnyToString{}
 	case *[]byte:
-		return scanPlanJSONToByteSlice{}
+		return &scanPlanJSONToByteSlice{}
 	case BytesScanner:
-		return scanPlanBinaryBytesToBytesScanner{}
-
-	// Cannot rely on sql.Scanner being handled later because scanPlanJSONToJSONUnmarshal will take precedence.
-	//
-	// https://github.com/jackc/pgx/issues/1418
+		return &scanPlanBinaryBytesToBytesScanner{}
 	case sql.Scanner:
-		return &scanPlanSQLScanner{formatCode: format}
+		return &scanPlanSQLScanner{formatCode: formatCode}
 	}
 
-	return &scanPlanJSONToJSONUnmarshal{
-		unmarshal: c.Unmarshal,
+	rv := reflect.ValueOf(target)
+	if rv.Kind() == reflect.Pointer && rv.Elem().Kind() == reflect.Pointer {
+		var plan jsonPointerScanPlan
+		plan.next = c.planScan(m, oid, formatCode, rv.Elem().Interface(), depth+1)
+		return plan
+	} else {
+		return &scanPlanJSONToJSONUnmarshal{unmarshal: c.Unmarshal}
 	}
 }
 
@@ -196,7 +211,12 @@ func (s *scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error {
 		return fmt.Errorf("cannot scan NULL into %T", dst)
 	}
 
-	elem := reflect.ValueOf(dst).Elem()
+	v := reflect.ValueOf(dst)
+	if v.Kind() != reflect.Pointer || v.IsNil() {
+		return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", dst)
+	}
+
+	elem := v.Elem()
 	elem.Set(reflect.Zero(elem.Type()))
 
 	return s.unmarshal(src, dst)
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
index 4ae8003e..10efc8ce 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
@@ -24,11 +24,13 @@ type Line struct {
 	Valid   bool
 }
 
+// ScanLine implements the [LineScanner] interface.
 func (line *Line) ScanLine(v Line) error {
 	*line = v
 	return nil
 }
 
+// LineValue implements the [LineValuer] interface.
 func (line Line) LineValue() (Line, error) {
 	return line, nil
 }
@@ -37,7 +39,7 @@ func (line *Line) Set(src any) error {
 	return fmt.Errorf("cannot convert %v to Line", src)
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (line *Line) Scan(src any) error {
 	if src == nil {
 		*line = Line{}
@@ -52,7 +54,7 @@ func (line *Line) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (line Line) Value() (driver.Value, error) {
 	if !line.Valid {
 		return nil, nil
@@ -129,7 +131,6 @@ func (encodePlanLineCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LineCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
index 05a86e1c..ed0d40d2 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
@@ -24,16 +24,18 @@ type Lseg struct {
 	Valid bool
 }
 
+// ScanLseg implements the [LsegScanner] interface.
 func (lseg *Lseg) ScanLseg(v Lseg) error {
 	*lseg = v
 	return nil
 }
 
+// LsegValue implements the [LsegValuer] interface.
 func (lseg Lseg) LsegValue() (Lseg, error) {
 	return lseg, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (lseg *Lseg) Scan(src any) error {
 	if src == nil {
 		*lseg = Lseg{}
@@ -48,7 +50,7 @@ func (lseg *Lseg) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (lseg Lseg) Value() (driver.Value, error) {
 	if !lseg.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanLsegCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LsegCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
index e5763788..4fe6dd40 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
@@ -374,7 +374,6 @@ parseValueLoop:
 	}
 
 	return elements, nil
-
 }
 
 func parseRange(buf *bytes.Buffer) (string, error) {
@@ -403,8 +402,8 @@ func parseRange(buf *bytes.Buffer) (string, error) {
 
 // Multirange is a generic multirange type.
 //
-// T should implement RangeValuer and *T should implement RangeScanner. However, there does not appear to be a way to
-// enforce the RangeScanner constraint.
+// T should implement [RangeValuer] and *T should implement [RangeScanner]. However, there does not appear to be a way to
+// enforce the [RangeScanner] constraint.
 type Multirange[T RangeValuer] []T
 
 func (r Multirange[T]) IsNull() bool {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
index 4dbec786..7d236902 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
@@ -27,16 +27,20 @@ const (
 	pgNumericNegInfSign = 0xf000
 )
 
-var big0 *big.Int = big.NewInt(0)
-var big1 *big.Int = big.NewInt(1)
-var big10 *big.Int = big.NewInt(10)
-var big100 *big.Int = big.NewInt(100)
-var big1000 *big.Int = big.NewInt(1000)
+var (
+	big0    *big.Int = big.NewInt(0)
+	big1    *big.Int = big.NewInt(1)
+	big10   *big.Int = big.NewInt(10)
+	big100  *big.Int = big.NewInt(100)
+	big1000 *big.Int = big.NewInt(1000)
+)
 
-var bigNBase *big.Int = big.NewInt(nbase)
-var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
-var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
-var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+var (
+	bigNBase   *big.Int = big.NewInt(nbase)
+	bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
+	bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
+	bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+)
 
 type NumericScanner interface {
 	ScanNumeric(v Numeric) error
@@ -54,15 +58,18 @@ type Numeric struct {
 	Valid            bool
 }
 
+// ScanNumeric implements the [NumericScanner] interface.
 func (n *Numeric) ScanNumeric(v Numeric) error {
 	*n = v
 	return nil
 }
 
+// NumericValue implements the [NumericValuer] interface.
 func (n Numeric) NumericValue() (Numeric, error) {
 	return n, nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (n Numeric) Float64Value() (Float8, error) {
 	if !n.Valid {
 		return Float8{}, nil
@@ -92,6 +99,7 @@ func (n Numeric) Float64Value() (Float8, error) {
 	return Float8{Float64: f, Valid: true}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (n *Numeric) ScanInt64(v Int8) error {
 	if !v.Valid {
 		*n = Numeric{}
@@ -102,6 +110,7 @@ func (n *Numeric) ScanInt64(v Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Numeric) Int64Value() (Int8, error) {
 	if !n.Valid {
 		return Int8{}, nil
@@ -203,7 +212,7 @@ func nbaseDigitsToInt64(src []byte) (accum int64, bytesRead, digitsRead int) {
 	return accum, rp, digits
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (n *Numeric) Scan(src any) error {
 	if src == nil {
 		*n = Numeric{}
@@ -218,7 +227,7 @@ func (n *Numeric) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (n Numeric) Value() (driver.Value, error) {
 	if !n.Valid {
 		return nil, nil
@@ -231,6 +240,7 @@ func (n Numeric) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (n Numeric) MarshalJSON() ([]byte, error) {
 	if !n.Valid {
 		return []byte("null"), nil
@@ -243,6 +253,7 @@ func (n Numeric) MarshalJSON() ([]byte, error) {
 	return n.numberTextBytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (n *Numeric) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte(`null`)) {
 		*n = Numeric{}
@@ -553,7 +564,6 @@ func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) {
 }
 
 func (NumericCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
index 73e0ec52..81dc1e5b 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
@@ -25,16 +25,18 @@ type Path struct {
 	Valid  bool
 }
 
+// ScanPath implements the [PathScanner] interface.
 func (path *Path) ScanPath(v Path) error {
 	*path = v
 	return nil
 }
 
+// PathValue implements the [PathValuer] interface.
 func (path Path) PathValue() (Path, error) {
 	return path, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (path *Path) Scan(src any) error {
 	if src == nil {
 		*path = Path{}
@@ -49,7 +51,7 @@ func (path *Path) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (path Path) Value() (driver.Value, error) {
 	if !path.Valid {
 		return nil, nil
@@ -154,7 +156,6 @@ func (encodePlanPathCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (PathCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
index bdd9f05c..b3ef3207 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
@@ -29,6 +29,7 @@ const (
 	XMLOID                 = 142
 	XMLArrayOID            = 143
 	JSONArrayOID           = 199
+	XID8ArrayOID           = 271
 	PointOID               = 600
 	LsegOID                = 601
 	PathOID                = 602
@@ -117,6 +118,7 @@ const (
 	TstzmultirangeOID      = 4534
 	DatemultirangeOID      = 4535
 	Int8multirangeOID      = 4536
+	XID8OID                = 5069
 	Int4multirangeArrayOID = 6150
 	NummultirangeArrayOID  = 6151
 	TsmultirangeArrayOID   = 6152
@@ -200,7 +202,6 @@ type Map struct {
 
 	reflectTypeToType map[reflect.Type]*Type
 
-	memoizedScanPlans   map[uint32]map[reflect.Type][2]ScanPlan
 	memoizedEncodePlans map[uint32]map[reflect.Type][2]EncodePlan
 
 	// TryWrapEncodePlanFuncs is a slice of functions that will wrap a value that cannot be encoded by the Codec. Every
@@ -234,7 +235,6 @@ func NewMap() *Map {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -274,9 +274,6 @@ func (m *Map) RegisterType(t *Type) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -290,9 +287,6 @@ func (m *Map) RegisterDefaultPgType(value any, name string) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -395,6 +389,7 @@ type scanPlanSQLScanner struct {
 
 func (plan *scanPlanSQLScanner) Scan(src []byte, dst any) error {
 	scanner := dst.(sql.Scanner)
+
 	if src == nil {
 		// This is necessary because interface value []byte:nil does not equal nil:nil for the binary format path and the
 		// text format path would be converted to empty string.
@@ -449,14 +444,14 @@ func (plan *scanPlanFail) Scan(src []byte, dst any) error {
 		// As a horrible hack try all types to find anything that can scan into dst.
 		for oid := range plan.m.oidToType {
 			// using planScan instead of Scan or PlanScan to avoid polluting the planned scan cache.
-			plan := plan.m.planScan(oid, plan.formatCode, dst)
+			plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 			if _, ok := plan.(*scanPlanFail); !ok {
 				return plan.Scan(src, dst)
 			}
 		}
 		for oid := range defaultMap.oidToType {
 			if _, ok := plan.m.oidToType[oid]; !ok {
-				plan := plan.m.planScan(oid, plan.formatCode, dst)
+				plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 				if _, ok := plan.(*scanPlanFail); !ok {
 					return plan.Scan(src, dst)
 				}
@@ -1064,24 +1059,14 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error {
 
 // PlanScan prepares a plan to scan a value into target.
 func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan {
-	oidMemo := m.memoizedScanPlans[oid]
-	if oidMemo == nil {
-		oidMemo = make(map[reflect.Type][2]ScanPlan)
-		m.memoizedScanPlans[oid] = oidMemo
-	}
-	targetReflectType := reflect.TypeOf(target)
-	typeMemo := oidMemo[targetReflectType]
-	plan := typeMemo[formatCode]
-	if plan == nil {
-		plan = m.planScan(oid, formatCode, target)
-		typeMemo[formatCode] = plan
-		oidMemo[targetReflectType] = typeMemo
-	}
-
-	return plan
+	return m.planScan(oid, formatCode, target, 0)
 }
 
-func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
+func (m *Map) planScan(oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	if target == nil {
 		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
 	}
@@ -1141,7 +1126,7 @@ func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
 
 	for _, f := range m.TryWrapScanPlanFuncs {
 		if wrapperPlan, nextDst, ok := f(target); ok {
-			if nextPlan := m.planScan(oid, formatCode, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, formatCode, nextDst, depth+1); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
@@ -1198,9 +1183,18 @@ func codecDecodeToTextFormat(codec Codec, m *Map, oid uint32, format int16, src
 	}
 }
 
-// PlanEncode returns an Encode plan for encoding value into PostgreSQL format for oid and format. If no plan can be
+// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be
 // found then nil is returned.
 func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
+	return m.planEncodeDepth(oid, format, value, 0)
+}
+
+func (m *Map) planEncodeDepth(oid uint32, format int16, value any, depth int) EncodePlan {
+	// Guard against infinite recursion.
+	if depth > 8 {
+		return nil
+	}
+
 	oidMemo := m.memoizedEncodePlans[oid]
 	if oidMemo == nil {
 		oidMemo = make(map[reflect.Type][2]EncodePlan)
@@ -1210,7 +1204,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	typeMemo := oidMemo[targetReflectType]
 	plan := typeMemo[format]
 	if plan == nil {
-		plan = m.planEncode(oid, format, value)
+		plan = m.planEncode(oid, format, value, depth)
 		typeMemo[format] = plan
 		oidMemo[targetReflectType] = typeMemo
 	}
@@ -1218,7 +1212,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	return plan
 }
 
-func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
+func (m *Map) planEncode(oid uint32, format int16, value any, depth int) EncodePlan {
 	if format == TextFormatCode {
 		switch value.(type) {
 		case string:
@@ -1249,7 +1243,7 @@ func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
 
 	for _, f := range m.TryWrapEncodePlanFuncs {
 		if wrapperPlan, nextValue, ok := f(value); ok {
-			if nextPlan := m.PlanEncode(oid, format, nextValue); nextPlan != nil {
+			if nextPlan := m.planEncodeDepth(oid, format, nextValue, depth+1); nextPlan != nil {
 				wrapperPlan.SetNext(nextPlan)
 				return wrapperPlan
 			}
@@ -2012,30 +2006,11 @@ func (w *sqlScannerWrapper) Scan(src any) error {
 	return w.m.Scan(t.OID, TextFormatCode, bufSrc, w.v)
 }
 
-// canBeNil returns true if value can be nil.
-func canBeNil(value any) bool {
-	refVal := reflect.ValueOf(value)
-	kind := refVal.Kind()
-	switch kind {
-	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
-		return true
-	default:
-		return false
-	}
-}
-
-// valuerReflectType is a reflect.Type for driver.Valuer. It has confusing syntax because reflect.TypeOf returns nil
-// when it's argument is a nil interface value. So we use a pointer to the interface and call Elem to get the actual
-// type. Yuck.
-//
-// This can be simplified in Go 1.22 with reflect.TypeFor.
-//
-// var valuerReflectType = reflect.TypeFor[driver.Valuer]()
-var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+var valuerReflectType = reflect.TypeFor[driver.Valuer]()
 
 // isNilDriverValuer returns true if value is any type of nil unless it implements driver.Valuer. *T is not considered to implement
 // driver.Valuer if it is only implemented by T.
-func isNilDriverValuer(value any) (isNil bool, callNilDriverValuer bool) {
+func isNilDriverValuer(value any) (isNil, callNilDriverValuer bool) {
 	if value == nil {
 		return true, false
 	}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
index c8125731..5648d89b 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
@@ -23,7 +23,6 @@ func initDefaultMap() {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -90,7 +89,26 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "varbit", OID: VarbitOID, Codec: BitsCodec{}})
 	defaultMap.RegisterType(&Type{Name: "varchar", OID: VarcharOID, Codec: TextCodec{}})
 	defaultMap.RegisterType(&Type{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}})
-	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{Marshal: xml.Marshal, Unmarshal: xml.Unmarshal}})
+	defaultMap.RegisterType(&Type{Name: "xid8", OID: XID8OID, Codec: Uint64Codec{}})
+	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{
+		Marshal: xml.Marshal,
+		// xml.Unmarshal does not support unmarshalling into *any. However, XMLCodec.DecodeValue calls Unmarshal with a
+		// *any. Wrap xml.Marshal with a function that copies the data into a new byte slice in this case. Not implementing
+		// directly in XMLCodec.DecodeValue to allow for the unlikely possibility that someone uses an alternative XML
+		// unmarshaler that does support unmarshalling into *any.
+		//
+		// https://github.com/jackc/pgx/issues/2227
+		// https://github.com/jackc/pgx/pull/2228
+		Unmarshal: func(data []byte, v any) error {
+			if v, ok := v.(*any); ok {
+				dstBuf := make([]byte, len(data))
+				copy(dstBuf, data)
+				*v = dstBuf
+				return nil
+			}
+			return xml.Unmarshal(data, v)
+		},
+	}})
 
 	// Range types
 	defaultMap.RegisterType(&Type{Name: "daterange", OID: DaterangeOID, Codec: &RangeCodec{ElementType: defaultMap.oidToType[DateOID]}})
@@ -155,6 +173,7 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "_varbit", OID: VarbitArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarbitOID]}})
 	defaultMap.RegisterType(&Type{Name: "_varchar", OID: VarcharArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarcharOID]}})
 	defaultMap.RegisterType(&Type{Name: "_xid", OID: XIDArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XIDOID]}})
+	defaultMap.RegisterType(&Type{Name: "_xid8", OID: XID8ArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XID8OID]}})
 	defaultMap.RegisterType(&Type{Name: "_xml", OID: XMLArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XMLOID]}})
 
 	// Integer types that directly map to a PostgreSQL type
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
index 09b19bb5..b701513d 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
@@ -30,11 +30,13 @@ type Point struct {
 	Valid bool
 }
 
+// ScanPoint implements the [PointScanner] interface.
 func (p *Point) ScanPoint(v Point) error {
 	*p = v
 	return nil
 }
 
+// PointValue implements the [PointValuer] interface.
 func (p Point) PointValue() (Point, error) {
 	return p, nil
 }
@@ -68,7 +70,7 @@ func parsePoint(src []byte) (*Point, error) {
 	return &Point{P: Vec2{x, y}, Valid: true}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Point) Scan(src any) error {
 	if src == nil {
 		*dst = Point{}
@@ -83,7 +85,7 @@ func (dst *Point) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Point) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,7 @@ func (src Point) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Point) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +111,7 @@ func (src Point) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Point) UnmarshalJSON(point []byte) error {
 	p, err := parsePoint(point)
 	if err != nil {
@@ -178,7 +182,6 @@ func (encodePlanPointCodecText) Encode(value any, buf []byte) (newBuf []byte, er
 }
 
 func (PointCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
index 04b0ba6b..a84b25fe 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
@@ -24,16 +24,18 @@ type Polygon struct {
 	Valid bool
 }
 
+// ScanPolygon implements the [PolygonScanner] interface.
 func (p *Polygon) ScanPolygon(v Polygon) error {
 	*p = v
 	return nil
 }
 
+// PolygonValue implements the [PolygonValuer] interface.
 func (p Polygon) PolygonValue() (Polygon, error) {
 	return p, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (p *Polygon) Scan(src any) error {
 	if src == nil {
 		*p = Polygon{}
@@ -48,7 +50,7 @@ func (p *Polygon) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (p Polygon) Value() (driver.Value, error) {
 	if !p.Valid {
 		return nil, nil
@@ -139,7 +141,6 @@ func (encodePlanPolygonCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (PolygonCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
index 16427ccc..62d69990 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
@@ -191,11 +191,13 @@ type untypedBinaryRange struct {
 // 18 = [      = 10010
 // 24 =        = 11000
 
-const emptyMask = 1
-const lowerInclusiveMask = 2
-const upperInclusiveMask = 4
-const lowerUnboundedMask = 8
-const upperUnboundedMask = 16
+const (
+	emptyMask          = 1
+	lowerInclusiveMask = 2
+	upperInclusiveMask = 4
+	lowerUnboundedMask = 8
+	upperUnboundedMask = 16
+)
 
 func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	ubr := &untypedBinaryRange{}
@@ -273,7 +275,6 @@ func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	}
 
 	return ubr, nil
-
 }
 
 // Range is a generic range type.
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
index b3b16604..90b9bd4b 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
@@ -121,5 +121,4 @@ func (RecordCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (an
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
index 021ee331..e08b1254 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
@@ -19,16 +19,18 @@ type Text struct {
 	Valid  bool
 }
 
+// ScanText implements the [TextScanner] interface.
 func (t *Text) ScanText(v Text) error {
 	*t = v
 	return nil
 }
 
+// TextValue implements the [TextValuer] interface.
 func (t Text) TextValue() (Text, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Text) Scan(src any) error {
 	if src == nil {
 		*dst = Text{}
@@ -47,7 +49,7 @@ func (dst *Text) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Text) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -55,6 +57,7 @@ func (src Text) Value() (driver.Value, error) {
 	return src.String, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Text) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -63,6 +66,7 @@ func (src Text) MarshalJSON() ([]byte, error) {
 	return json.Marshal(src.String)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Text) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -146,7 +150,6 @@ func (encodePlanTextCodecTextValuer) Encode(value any, buf []byte) (newBuf []byt
 }
 
 func (TextCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case TextFormatCode, BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
index 9bc2c2a1..05c9e6d9 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
@@ -35,16 +35,18 @@ type TID struct {
 	Valid        bool
 }
 
+// ScanTID implements the [TIDScanner] interface.
 func (b *TID) ScanTID(v TID) error {
 	*b = v
 	return nil
 }
 
+// TIDValue implements the [TIDValuer] interface.
 func (b TID) TIDValue() (TID, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *TID) Scan(src any) error {
 	if src == nil {
 		*dst = TID{}
@@ -59,7 +61,7 @@ func (dst *TID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src TID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -131,7 +133,6 @@ func (encodePlanTIDCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TIDCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
index f8fd9489..4b8f6908 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
@@ -29,16 +29,18 @@ type Time struct {
 	Valid        bool
 }
 
+// ScanTime implements the [TimeScanner] interface.
 func (t *Time) ScanTime(v Time) error {
 	*t = v
 	return nil
 }
 
+// TimeValue implements the [TimeValuer] interface.
 func (t Time) TimeValue() (Time, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (t *Time) Scan(src any) error {
 	if src == nil {
 		*t = Time{}
@@ -58,7 +60,7 @@ func (t *Time) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (t Time) Value() (driver.Value, error) {
 	if !t.Valid {
 		return nil, nil
@@ -137,7 +139,6 @@ func (encodePlanTimeCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TimeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
index 677a2c6e..861fa883 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
@@ -11,7 +11,10 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+const (
+	pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+	jsonISO8601       = "2006-01-02T15:04:05.999999999"
+)
 
 type TimestampScanner interface {
 	ScanTimestamp(v Timestamp) error
@@ -28,16 +31,18 @@ type Timestamp struct {
 	Valid            bool
 }
 
+// ScanTimestamp implements the [TimestampScanner] interface.
 func (ts *Timestamp) ScanTimestamp(v Timestamp) error {
 	*ts = v
 	return nil
 }
 
+// TimestampValue implements the [TimestampValuer] interface.
 func (ts Timestamp) TimestampValue() (Timestamp, error) {
 	return ts, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (ts *Timestamp) Scan(src any) error {
 	if src == nil {
 		*ts = Timestamp{}
@@ -55,7 +60,7 @@ func (ts *Timestamp) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (ts Timestamp) Value() (driver.Value, error) {
 	if !ts.Valid {
 		return nil, nil
@@ -67,6 +72,7 @@ func (ts Timestamp) Value() (driver.Value, error) {
 	return ts.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	if !ts.Valid {
 		return []byte("null"), nil
@@ -76,7 +82,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 
 	switch ts.InfinityModifier {
 	case Finite:
-		s = ts.Time.Format(time.RFC3339Nano)
+		s = ts.Time.Format(jsonISO8601)
 	case Infinity:
 		s = "infinity"
 	case NegativeInfinity:
@@ -86,6 +92,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -104,15 +111,23 @@ func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	case "-infinity":
 		*ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
 	default:
-		// PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz
-		tim, err := time.Parse(time.RFC3339Nano, *s)
-		if err != nil {
-			return err
+		// Parse time with or without timezonr
+		tss := *s
+		//		PostgreSQL uses ISO 8601 without timezone for to_json function and casting from a string to timestampt
+		tim, err := time.Parse(time.RFC3339Nano, tss)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
 		}
-
-		*ts = Timestamp{Time: tim, Valid: true}
+		tim, err = time.ParseInLocation(jsonISO8601, tss, time.UTC)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
+		}
+		ts.Valid = false
+		return fmt.Errorf("cannot unmarshal %s to timestamp with layout %s or %s (%w)",
+			*s, time.RFC3339Nano, jsonISO8601, err)
 	}
-
 	return nil
 }
 
@@ -225,7 +240,6 @@ func discardTimeZone(t time.Time) time.Time {
 }
 
 func (c *TimestampCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
index 7efbcffd..5d67e47f 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
@@ -11,10 +11,12 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07"
-const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00"
-const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00"
-const microsecFromUnixEpochToY2K = 946684800 * 1000000
+const (
+	pgTimestamptzHourFormat    = "2006-01-02 15:04:05.999999999Z07"
+	pgTimestamptzMinuteFormat  = "2006-01-02 15:04:05.999999999Z07:00"
+	pgTimestamptzSecondFormat  = "2006-01-02 15:04:05.999999999Z07:00:00"
+	microsecFromUnixEpochToY2K = 946684800 * 1000000
+)
 
 const (
 	negativeInfinityMicrosecondOffset = -9223372036854775808
@@ -36,16 +38,18 @@ type Timestamptz struct {
 	Valid            bool
 }
 
+// ScanTimestamptz implements the [TimestamptzScanner] interface.
 func (tstz *Timestamptz) ScanTimestamptz(v Timestamptz) error {
 	*tstz = v
 	return nil
 }
 
+// TimestamptzValue implements the [TimestamptzValuer] interface.
 func (tstz Timestamptz) TimestamptzValue() (Timestamptz, error) {
 	return tstz, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (tstz *Timestamptz) Scan(src any) error {
 	if src == nil {
 		*tstz = Timestamptz{}
@@ -63,7 +67,7 @@ func (tstz *Timestamptz) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (tstz Timestamptz) Value() (driver.Value, error) {
 	if !tstz.Valid {
 		return nil, nil
@@ -75,6 +79,7 @@ func (tstz Timestamptz) Value() (driver.Value, error) {
 	return tstz.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	if !tstz.Valid {
 		return []byte("null"), nil
@@ -94,6 +99,7 @@ func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (tstz *Timestamptz) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -225,7 +231,6 @@ func (encodePlanTimestamptzCodecText) Encode(value any, buf []byte) (newBuf []by
 }
 
 func (c *TimestamptzCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
index f2b2fa6d..e6d4b1cf 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
@@ -3,6 +3,7 @@ package pgtype
 import (
 	"database/sql/driver"
 	"encoding/binary"
+	"encoding/json"
 	"fmt"
 	"math"
 	"strconv"
@@ -24,16 +25,18 @@ type Uint32 struct {
 	Valid  bool
 }
 
+// ScanUint32 implements the [Uint32Scanner] interface.
 func (n *Uint32) ScanUint32(v Uint32) error {
 	*n = v
 	return nil
 }
 
+// Uint32Value implements the [Uint32Valuer] interface.
 func (n Uint32) Uint32Value() (Uint32, error) {
 	return n, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Uint32) Scan(src any) error {
 	if src == nil {
 		*dst = Uint32{}
@@ -67,7 +70,7 @@ func (dst *Uint32) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Uint32) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -75,6 +78,31 @@ func (src Uint32) Value() (driver.Value, error) {
 	return int64(src.Uint32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
+func (src Uint32) MarshalJSON() ([]byte, error) {
+	if !src.Valid {
+		return []byte("null"), nil
+	}
+	return json.Marshal(src.Uint32)
+}
+
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
+func (dst *Uint32) UnmarshalJSON(b []byte) error {
+	var n *uint32
+	err := json.Unmarshal(b, &n)
+	if err != nil {
+		return err
+	}
+
+	if n == nil {
+		*dst = Uint32{}
+	} else {
+		*dst = Uint32{Uint32: *n, Valid: true}
+	}
+
+	return nil
+}
+
 type Uint32Codec struct{}
 
 func (Uint32Codec) FormatSupported(format int16) bool {
@@ -197,7 +225,6 @@ func (encodePlanUint32CodecTextInt64Valuer) Encode(value any, buf []byte) (newBu
 }
 
 func (Uint32Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
new file mode 100644
index 00000000..68fd1661
--- /dev/null
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
@@ -0,0 +1,323 @@
+package pgtype
+
+import (
+	"database/sql/driver"
+	"encoding/binary"
+	"fmt"
+	"math"
+	"strconv"
+
+	"github.com/jackc/pgx/v5/internal/pgio"
+)
+
+type Uint64Scanner interface {
+	ScanUint64(v Uint64) error
+}
+
+type Uint64Valuer interface {
+	Uint64Value() (Uint64, error)
+}
+
+// Uint64 is the core type that is used to represent PostgreSQL types such as XID8.
+type Uint64 struct {
+	Uint64 uint64
+	Valid  bool
+}
+
+// ScanUint64 implements the [Uint64Scanner] interface.
+func (n *Uint64) ScanUint64(v Uint64) error {
+	*n = v
+	return nil
+}
+
+// Uint64Value implements the [Uint64Valuer] interface.
+func (n Uint64) Uint64Value() (Uint64, error) {
+	return n, nil
+}
+
+// Scan implements the [database/sql.Scanner] interface.
+func (dst *Uint64) Scan(src any) error {
+	if src == nil {
+		*dst = Uint64{}
+		return nil
+	}
+
+	var n uint64
+
+	switch src := src.(type) {
+	case int64:
+		if src < 0 {
+			return fmt.Errorf("%d is less than the minimum value for Uint64", src)
+		}
+		n = uint64(src)
+	case string:
+		un, err := strconv.ParseUint(src, 10, 64)
+		if err != nil {
+			return err
+		}
+		n = un
+	default:
+		return fmt.Errorf("cannot scan %T", src)
+	}
+
+	*dst = Uint64{Uint64: n, Valid: true}
+
+	return nil
+}
+
+// Value implements the [database/sql/driver.Valuer] interface.
+func (src Uint64) Value() (driver.Value, error) {
+	if !src.Valid {
+		return nil, nil
+	}
+
+	// If the value is greater than the maximum value for int64, return it as a string instead of losing data or returning
+	// an error.
+	if src.Uint64 > math.MaxInt64 {
+		return strconv.FormatUint(src.Uint64, 10), nil
+	}
+
+	return int64(src.Uint64), nil
+}
+
+type Uint64Codec struct{}
+
+func (Uint64Codec) FormatSupported(format int16) bool {
+	return format == TextFormatCode || format == BinaryFormatCode
+}
+
+func (Uint64Codec) PreferredFormat() int16 {
+	return BinaryFormatCode
+}
+
+func (Uint64Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
+	switch format {
+	case BinaryFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecBinaryUint64{}
+		case Uint64Valuer:
+			return encodePlanUint64CodecBinaryUint64Valuer{}
+		case Int64Valuer:
+			return encodePlanUint64CodecBinaryInt64Valuer{}
+		}
+	case TextFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecTextUint64{}
+		case Int64Valuer:
+			return encodePlanUint64CodecTextInt64Valuer{}
+		}
+	}
+
+	return nil
+}
+
+type encodePlanUint64CodecBinaryUint64 struct{}
+
+func (encodePlanUint64CodecBinaryUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return pgio.AppendUint64(buf, v), nil
+}
+
+type encodePlanUint64CodecBinaryUint64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return pgio.AppendUint64(buf, v.Uint64), nil
+}
+
+type encodePlanUint64CodecBinaryInt64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return pgio.AppendUint64(buf, uint64(v.Int64)), nil
+}
+
+type encodePlanUint64CodecTextUint64 struct{}
+
+func (encodePlanUint64CodecTextUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return append(buf, strconv.FormatUint(uint64(v), 10)...), nil
+}
+
+type encodePlanUint64CodecTextUint64Valuer struct{}
+
+func (encodePlanUint64CodecTextUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return append(buf, strconv.FormatUint(v.Uint64, 10)...), nil
+}
+
+type encodePlanUint64CodecTextInt64Valuer struct{}
+
+func (encodePlanUint64CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return append(buf, strconv.FormatInt(v.Int64, 10)...), nil
+}
+
+func (Uint64Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+	switch format {
+	case BinaryFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanBinaryUint64ToUint64{}
+		case Uint64Scanner:
+			return scanPlanBinaryUint64ToUint64Scanner{}
+		case TextScanner:
+			return scanPlanBinaryUint64ToTextScanner{}
+		}
+	case TextFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanTextAnyToUint64{}
+		case Uint64Scanner:
+			return scanPlanTextAnyToUint64Scanner{}
+		}
+	}
+
+	return nil
+}
+
+func (c Uint64Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return int64(n), nil
+}
+
+func (c Uint64Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return n, nil
+}
+
+type scanPlanBinaryUint64ToUint64 struct{}
+
+func (scanPlanBinaryUint64ToUint64) Scan(src []byte, dst any) error {
+	if src == nil {
+		return fmt.Errorf("cannot scan NULL into %T", dst)
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	p := (dst).(*uint64)
+	*p = binary.BigEndian.Uint64(src)
+
+	return nil
+}
+
+type scanPlanBinaryUint64ToUint64Scanner struct{}
+
+func (scanPlanBinaryUint64ToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := binary.BigEndian.Uint64(src)
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
+
+type scanPlanBinaryUint64ToTextScanner struct{}
+
+func (scanPlanBinaryUint64ToTextScanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(TextScanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanText(Text{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := uint64(binary.BigEndian.Uint64(src))
+	return s.ScanText(Text{String: strconv.FormatUint(n, 10), Valid: true})
+}
+
+type scanPlanTextAnyToUint64Scanner struct{}
+
+func (scanPlanTextAnyToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	n, err := strconv.ParseUint(string(src), 10, 64)
+	if err != nil {
+		return err
+	}
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
index d57c0f2f..83d0c412 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
@@ -20,11 +20,13 @@ type UUID struct {
 	Valid bool
 }
 
+// ScanUUID implements the [UUIDScanner] interface.
 func (b *UUID) ScanUUID(v UUID) error {
 	*b = v
 	return nil
 }
 
+// UUIDValue implements the [UUIDValuer] interface.
 func (b UUID) UUIDValue() (UUID, error) {
 	return b, nil
 }
@@ -67,7 +69,7 @@ func encodeUUID(src [16]byte) string {
 	return string(buf[:])
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *UUID) Scan(src any) error {
 	if src == nil {
 		*dst = UUID{}
@@ -87,7 +89,7 @@ func (dst *UUID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src UUID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,15 @@ func (src UUID) Value() (driver.Value, error) {
 	return encodeUUID(src.Bytes), nil
 }
 
+func (src UUID) String() string {
+	if !src.Valid {
+		return ""
+	}
+
+	return encodeUUID(src.Bytes)
+}
+
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src UUID) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +119,7 @@ func (src UUID) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *UUID) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte("null")) {
 		*dst = UUID{}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
index fb4c49ad..79e3698a 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
@@ -113,7 +113,7 @@ func (c *XMLCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPl
 		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
 
 		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, format, nextDst, 0); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go b/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
index fdcba724..addfb412 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
@@ -2,7 +2,7 @@ package pgxpool
 
 import (
 	"context"
-	"fmt"
+	"errors"
 	"math/rand"
 	"runtime"
 	"strconv"
@@ -15,11 +15,14 @@ import (
 	"github.com/jackc/puddle/v2"
 )
 
-var defaultMaxConns = int32(4)
-var defaultMinConns = int32(0)
-var defaultMaxConnLifetime = time.Hour
-var defaultMaxConnIdleTime = time.Minute * 30
-var defaultHealthCheckPeriod = time.Minute
+var (
+	defaultMaxConns          = int32(4)
+	defaultMinConns          = int32(0)
+	defaultMinIdleConns      = int32(0)
+	defaultMaxConnLifetime   = time.Hour
+	defaultMaxConnIdleTime   = time.Minute * 30
+	defaultHealthCheckPeriod = time.Minute
+)
 
 type connResource struct {
 	conn       *pgx.Conn
@@ -83,10 +86,12 @@ type Pool struct {
 	config                *Config
 	beforeConnect         func(context.Context, *pgx.ConnConfig) error
 	afterConnect          func(context.Context, *pgx.Conn) error
-	beforeAcquire         func(context.Context, *pgx.Conn) bool
+	prepareConn           func(context.Context, *pgx.Conn) (bool, error)
 	afterRelease          func(*pgx.Conn) bool
 	beforeClose           func(*pgx.Conn)
+	shouldPing            func(context.Context, ShouldPingParams) bool
 	minConns              int32
+	minIdleConns          int32
 	maxConns              int32
 	maxConnLifetime       time.Duration
 	maxConnLifetimeJitter time.Duration
@@ -102,6 +107,12 @@ type Pool struct {
 	closeChan chan struct{}
 }
 
+// ShouldPingParams are the parameters passed to ShouldPing.
+type ShouldPingParams struct {
+	Conn         *pgx.Conn
+	IdleDuration time.Duration
+}
+
 // Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
 // modified.
 type Config struct {
@@ -117,8 +128,23 @@ type Config struct {
 	// BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the
 	// acquisition or false to indicate that the connection should be destroyed and a different connection should be
 	// acquired.
+	//
+	// Deprecated: Use PrepareConn instead. If both PrepareConn and BeforeAcquire are set, PrepareConn will take
+	// precedence, ignoring BeforeAcquire.
 	BeforeAcquire func(context.Context, *pgx.Conn) bool
 
+	// PrepareConn is called before a connection is acquired from the pool. If this function returns true, the connection
+	// is considered valid, otherwise the connection is destroyed. If the function returns a non-nil error, the instigating
+	// query will fail with the returned error.
+	//
+	// Specifically, this means that:
+	//
+	// 	- If it returns true and a nil error, the query proceeds as normal.
+	// 	- If it returns true and an error, the connection will be returned to the pool, and the instigating query will fail with the returned error.
+	// 	- If it returns false, and an error, the connection will be destroyed, and the query will fail with the returned error.
+	// 	- If it returns false and a nil error, the connection will be destroyed, and the instigating query will be retried on a new connection.
+	PrepareConn func(context.Context, *pgx.Conn) (bool, error)
+
 	// AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to
 	// return the connection to the pool or false to destroy the connection.
 	AfterRelease func(*pgx.Conn) bool
@@ -126,6 +152,10 @@ type Config struct {
 	// BeforeClose is called right before a connection is closed and removed from the pool.
 	BeforeClose func(*pgx.Conn)
 
+	// ShouldPing is called after a connection is acquired from the pool. If it returns true, the connection is pinged to check for liveness.
+	// If this func is not set, the default behavior is to ping connections that have been idle for at least 1 second.
+	ShouldPing func(context.Context, ShouldPingParams) bool
+
 	// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
 	MaxConnLifetime time.Duration
 
@@ -144,6 +174,13 @@ type Config struct {
 	// to create new connections.
 	MinConns int32
 
+	// MinIdleConns is the minimum number of idle connections in the pool. You can increase this to ensure that
+	// there are always idle connections available. This can help reduce tail latencies during request processing,
+	// as you can avoid the latency of establishing a new connection while handling requests. It is superior
+	// to MinConns for this purpose.
+	// Similar to MinConns, the pool might temporarily dip below MinIdleConns after connection closes.
+	MinIdleConns int32
+
 	// HealthCheckPeriod is the duration between checks of the health of idle connections.
 	HealthCheckPeriod time.Duration
 
@@ -181,14 +218,22 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		panic("config must be created by ParseConfig")
 	}
 
+	prepareConn := config.PrepareConn
+	if prepareConn == nil && config.BeforeAcquire != nil {
+		prepareConn = func(ctx context.Context, conn *pgx.Conn) (bool, error) {
+			return config.BeforeAcquire(ctx, conn), nil
+		}
+	}
+
 	p := &Pool{
 		config:                config,
 		beforeConnect:         config.BeforeConnect,
 		afterConnect:          config.AfterConnect,
-		beforeAcquire:         config.BeforeAcquire,
+		prepareConn:           prepareConn,
 		afterRelease:          config.AfterRelease,
 		beforeClose:           config.BeforeClose,
 		minConns:              config.MinConns,
+		minIdleConns:          config.MinIdleConns,
 		maxConns:              config.MaxConns,
 		maxConnLifetime:       config.MaxConnLifetime,
 		maxConnLifetimeJitter: config.MaxConnLifetimeJitter,
@@ -206,6 +251,14 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		p.releaseTracer = t
 	}
 
+	if config.ShouldPing != nil {
+		p.shouldPing = config.ShouldPing
+	} else {
+		p.shouldPing = func(ctx context.Context, params ShouldPingParams) bool {
+			return params.IdleDuration > time.Second
+		}
+	}
+
 	var err error
 	p.p, err = puddle.NewPool(
 		&puddle.Config[*connResource]{
@@ -271,7 +324,8 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 	}
 
 	go func() {
-		p.createIdleResources(ctx, int(p.minConns))
+		targetIdleResources := max(int(p.minConns), int(p.minIdleConns))
+		p.createIdleResources(ctx, targetIdleResources)
 		p.backgroundHealthCheck()
 	}()
 
@@ -281,20 +335,20 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 // ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the
 // addition of the following variables:
 //
-//   - pool_max_conns: integer greater than 0
-//   - pool_min_conns: integer 0 or greater
-//   - pool_max_conn_lifetime: duration string
-//   - pool_max_conn_idle_time: duration string
-//   - pool_health_check_period: duration string
-//   - pool_max_conn_lifetime_jitter: duration string
+//   - pool_max_conns: integer greater than 0 (default 4)
+//   - pool_min_conns: integer 0 or greater (default 0)
+//   - pool_max_conn_lifetime: duration string (default 1 hour)
+//   - pool_max_conn_idle_time: duration string (default 30 minutes)
+//   - pool_health_check_period: duration string (default 1 minute)
+//   - pool_max_conn_lifetime_jitter: duration string (default 0)
 //
 // See Config for definitions of these arguments.
 //
 //	# Example Keyword/Value
-//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
+//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 pool_max_conn_lifetime=1h30m
 //
 //	# Example URL
-//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
+//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10&pool_max_conn_lifetime=1h30m
 func ParseConfig(connString string) (*Config, error) {
 	connConfig, err := pgx.ParseConfig(connString)
 	if err != nil {
@@ -310,10 +364,10 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_max_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conns", err)
 		}
 		if n < 1 {
-			return nil, fmt.Errorf("pool_max_conns too small: %d", n)
+			return nil, pgconn.NewParseConfigError(connString, "pool_max_conns too small", err)
 		}
 		config.MaxConns = int32(n)
 	} else {
@@ -327,18 +381,29 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_min_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_min_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_conns", err)
 		}
 		config.MinConns = int32(n)
 	} else {
 		config.MinConns = defaultMinConns
 	}
 
+	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_idle_conns"]; ok {
+		delete(connConfig.Config.RuntimeParams, "pool_min_idle_conns")
+		n, err := strconv.ParseInt(s, 10, 32)
+		if err != nil {
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_idle_conns", err)
+		}
+		config.MinIdleConns = int32(n)
+	} else {
+		config.MinIdleConns = defaultMinIdleConns
+	}
+
 	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime", err)
 		}
 		config.MaxConnLifetime = d
 	} else {
@@ -349,7 +414,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_idle_time")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_idle_time: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_idle_time", err)
 		}
 		config.MaxConnIdleTime = d
 	} else {
@@ -360,7 +425,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_health_check_period")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_health_check_period: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_health_check_period", err)
 		}
 		config.HealthCheckPeriod = d
 	} else {
@@ -371,7 +436,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime_jitter", err)
 		}
 		config.MaxConnLifetimeJitter = d
 	}
@@ -472,7 +537,9 @@ func (p *Pool) checkMinConns() error {
 	// TotalConns can include ones that are being destroyed but we should have
 	// sleep(500ms) around all of the destroys to help prevent that from throwing
 	// off this check
-	toCreate := p.minConns - p.Stat().TotalConns()
+
+	// Create the number of connections needed to get to both minConns and minIdleConns
+	toCreate := max(p.minConns-p.Stat().TotalConns(), p.minIdleConns-p.Stat().IdleConns())
 	if toCreate > 0 {
 		return p.createIdleResources(context.Background(), int(toCreate))
 	}
@@ -521,7 +588,10 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 		}()
 	}
 
-	for {
+	// Try to acquire from the connection pool up to maxConns + 1 times, so that
+	// any that fatal errors would empty the pool and still at least try 1 fresh
+	// connection.
+	for range p.maxConns + 1 {
 		res, err := p.p.Acquire(ctx)
 		if err != nil {
 			return nil, err
@@ -529,7 +599,8 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 
 		cr := res.Value()
 
-		if res.IdleDuration() > time.Second {
+		shouldPingParams := ShouldPingParams{Conn: cr.conn, IdleDuration: res.IdleDuration()}
+		if p.shouldPing(ctx, shouldPingParams) {
 			err := cr.conn.Ping(ctx)
 			if err != nil {
 				res.Destroy()
@@ -537,12 +608,25 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 			}
 		}
 
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			return cr.getConn(p, res), nil
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok {
+				res.Destroy()
+			}
+			if err != nil {
+				if ok {
+					res.Release()
+				}
+				return nil, err
+			}
+			if !ok {
+				continue
+			}
 		}
 
-		res.Destroy()
+		return cr.getConn(p, res), nil
 	}
+	return nil, errors.New("pgxpool: detected infinite loop acquiring connection; likely bug in PrepareConn or BeforeAcquire hook")
 }
 
 // AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the
@@ -565,11 +649,14 @@ func (p *Pool) AcquireAllIdle(ctx context.Context) []*Conn {
 	conns := make([]*Conn, 0, len(resources))
 	for _, res := range resources {
 		cr := res.Value()
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			conns = append(conns, cr.getConn(p, res))
-		} else {
-			res.Destroy()
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok || err != nil {
+				res.Destroy()
+				continue
+			}
 		}
+		conns = append(conns, cr.getConn(p, res))
 	}
 
 	return conns
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go b/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
index cfa0c4c5..e02b6ac3 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
@@ -82,3 +82,10 @@ func (s *Stat) MaxLifetimeDestroyCount() int64 {
 func (s *Stat) MaxIdleDestroyCount() int64 {
 	return s.idleDestroyCount
 }
+
+// EmptyAcquireWaitTime returns the cumulative time waited for successful acquires
+// from the pool for a resource to be released or constructed because the pool was
+// empty.
+func (s *Stat) EmptyAcquireWaitTime() time.Duration {
+	return s.s.EmptyAcquireWaitTime()
+}
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/rows.go b/history-api/vendor/github.com/jackc/pgx/v5/rows.go
index f23625d4..a5725fdd 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/rows.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/rows.go
@@ -41,22 +41,19 @@ type Rows interface {
 	// when there was an error executing the query.
 	FieldDescriptions() []pgconn.FieldDescription
 
-	// Next prepares the next row for reading. It returns true if there is another
-	// row and false if no more rows are available or a fatal error has occurred.
-	// It automatically closes rows when all rows are read.
+	// Next prepares the next row for reading. It returns true if there is another row and false if no more rows are
+	// available or a fatal error has occurred. It automatically closes rows upon returning false (whether due to all rows
+	// having been read or due to an error).
 	//
-	// Callers should check rows.Err() after rows.Next() returns false to detect
-	// whether result-set reading ended prematurely due to an error. See
-	// Conn.Query for details.
+	// Callers should check rows.Err() after rows.Next() returns false to detect whether result-set reading ended
+	// prematurely due to an error. See Conn.Query for details.
 	//
-	// For simpler error handling, consider using the higher-level pgx v5
-	// CollectRows() and ForEachRow() helpers instead.
+	// For simpler error handling, consider using the higher-level pgx v5 CollectRows() and ForEachRow() helpers instead.
 	Next() bool
 
-	// Scan reads the values from the current row into dest values positionally.
-	// dest can include pointers to core types, values implementing the Scanner
-	// interface, and nil. nil will skip the value entirely. It is an error to
-	// call Scan without first calling Next() and checking that it returned true.
+	// Scan reads the values from the current row into dest values positionally. dest can include pointers to core types,
+	// values implementing the Scanner interface, and nil. nil will skip the value entirely. It is an error to call Scan
+	// without first calling Next() and checking that it returned true. Rows is automatically closed upon error.
 	Scan(dest ...any) error
 
 	// Values returns the decoded row values. As with Scan(), it is an error to
@@ -188,6 +185,17 @@ func (rows *baseRows) Close() {
 	} else if rows.queryTracer != nil {
 		rows.queryTracer.TraceQueryEnd(rows.ctx, rows.conn, TraceQueryEndData{rows.commandTag, rows.err})
 	}
+
+	// Zero references to other memory allocations. This allows them to be GC'd even when the Rows still referenced. In
+	// particular, when using pgxpool GC could be delayed as pgxpool.poolRows are allocated in large slices.
+	//
+	// https://github.com/jackc/pgx/pull/2269
+	rows.values = nil
+	rows.scanPlans = nil
+	rows.scanTypes = nil
+	rows.ctx = nil
+	rows.sql = ""
+	rows.args = nil
 }
 
 func (rows *baseRows) CommandTag() pgconn.CommandTag {
@@ -272,7 +280,7 @@ func (rows *baseRows) Scan(dest ...any) error {
 
 		err := rows.scanPlans[i].Scan(values[i], dst)
 		if err != nil {
-			err = ScanArgError{ColumnIndex: i, Err: err}
+			err = ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 			rows.fatal(err)
 			return err
 		}
@@ -334,11 +342,16 @@ func (rows *baseRows) Conn() *Conn {
 
 type ScanArgError struct {
 	ColumnIndex int
+	FieldName   string
 	Err         error
 }
 
 func (e ScanArgError) Error() string {
-	return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	if e.FieldName == "?column?" { // Don't include the fieldname if it's unknown
+		return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	}
+
+	return fmt.Sprintf("can't scan into dest[%d] (col: %s): %v", e.ColumnIndex, e.FieldName, e.Err)
 }
 
 func (e ScanArgError) Unwrap() error {
@@ -366,7 +379,7 @@ func ScanRow(typeMap *pgtype.Map, fieldDescriptions []pgconn.FieldDescription, v
 
 		err := typeMap.Scan(fieldDescriptions[i].DataTypeOID, fieldDescriptions[i].Format, values[i], d)
 		if err != nil {
-			return ScanArgError{ColumnIndex: i, Err: err}
+			return ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 		}
 	}
 
@@ -468,6 +481,8 @@ func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
 		return value, err
 	}
 
+	// The defer rows.Close() won't have executed yet. If the query returned more than one row, rows would still be open.
+	// rows.Close() must be called before rows.Err() so we explicitly call it here.
 	rows.Close()
 	return value, rows.Err()
 }
@@ -545,7 +560,7 @@ func (rs *mapRowScanner) ScanRow(rows Rows) error {
 	return nil
 }
 
-// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row
+// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number of public fields as row
 // has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then the field will be
 // ignored.
 func RowToStructByPos[T any](row CollectableRow) (T, error) {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go b/history-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
index c1d00ab4..939b9636 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
@@ -216,7 +216,8 @@ func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB {
 
 // OpenDBFromPool creates a new *sql.DB from the given *pgxpool.Pool. Note that this method automatically sets the
 // maximum number of idle connections in *sql.DB to zero, since they must be managed from the *pgxpool.Pool. This is
-// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool.
+// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool. Note
+// that closing the returned *sql.DB will not close the *pgxpool.Pool.
 func OpenDBFromPool(pool *pgxpool.Pool, opts ...OptionOpenDB) *sql.DB {
 	c := GetPoolConnector(pool, opts...)
 	db := sql.OpenDB(c)
@@ -470,7 +471,8 @@ func (c *Conn) ExecContext(ctx context.Context, query string, argsV []driver.Nam
 		return nil, driver.ErrBadConn
 	}
 
-	args := namedValueToInterface(argsV)
+	args := make([]any, len(argsV))
+	convertNamedArguments(args, argsV)
 
 	commandTag, err := c.conn.Exec(ctx, query, args...)
 	// if we got a network error before we had a chance to send the query, retry
@@ -487,8 +489,9 @@ func (c *Conn) QueryContext(ctx context.Context, query string, argsV []driver.Na
 		return nil, driver.ErrBadConn
 	}
 
-	args := []any{databaseSQLResultFormats}
-	args = append(args, namedValueToInterface(argsV)...)
+	args := make([]any, 1+len(argsV))
+	args[0] = databaseSQLResultFormats
+	convertNamedArguments(args[1:], argsV)
 
 	rows, err := c.conn.Query(ctx, query, args...)
 	if err != nil {
@@ -847,28 +850,14 @@ func (r *Rows) Next(dest []driver.Value) error {
 	return nil
 }
 
-func valueToInterface(argsV []driver.Value) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
-		if v != nil {
-			args = append(args, v.(any))
-		} else {
-			args = append(args, nil)
-		}
-	}
-	return args
-}
-
-func namedValueToInterface(argsV []driver.NamedValue) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
+func convertNamedArguments(args []any, argsV []driver.NamedValue) {
+	for i, v := range argsV {
 		if v.Value != nil {
-			args = append(args, v.Value.(any))
+			args[i] = v.Value.(any)
 		} else {
-			args = append(args, nil)
+			args[i] = nil
 		}
 	}
-	return args
 }
 
 type wrapTx struct {
diff --git a/history-api/vendor/github.com/jackc/pgx/v5/tx.go b/history-api/vendor/github.com/jackc/pgx/v5/tx.go
index 8feeb512..571e5e00 100644
--- a/history-api/vendor/github.com/jackc/pgx/v5/tx.go
+++ b/history-api/vendor/github.com/jackc/pgx/v5/tx.go
@@ -3,7 +3,6 @@ package pgx
 import (
 	"context"
 	"errors"
-	"fmt"
 	"strconv"
 	"strings"
 
@@ -48,6 +47,8 @@ type TxOptions struct {
 	// BeginQuery is the SQL query that will be executed to begin the transaction. This allows using non-standard syntax
 	// such as BEGIN PRIORITY HIGH with CockroachDB. If set this will override the other settings.
 	BeginQuery string
+	// CommitQuery is the SQL query that will be executed to commit the transaction.
+	CommitQuery string
 }
 
 var emptyTxOptions TxOptions
@@ -101,11 +102,14 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (Tx, error) {
 	if err != nil {
 		// begin should never fail unless there is an underlying connection issue or
 		// a context timeout. In either case, the connection is possibly broken.
-		c.die(errors.New("failed to begin transaction"))
+		c.die()
 		return nil, err
 	}
 
-	return &dbTx{conn: c}, nil
+	return &dbTx{
+		conn:        c,
+		commitQuery: txOptions.CommitQuery,
+	}, nil
 }
 
 // Tx represents a database transaction.
@@ -154,6 +158,7 @@ type dbTx struct {
 	conn         *Conn
 	savepointNum int64
 	closed       bool
+	commitQuery  string
 }
 
 // Begin starts a pseudo nested transaction implemented with a savepoint.
@@ -177,7 +182,12 @@ func (tx *dbTx) Commit(ctx context.Context) error {
 		return ErrTxClosed
 	}
 
-	commandTag, err := tx.conn.Exec(ctx, "commit")
+	commandSQL := "commit"
+	if tx.commitQuery != "" {
+		commandSQL = tx.commitQuery
+	}
+
+	commandTag, err := tx.conn.Exec(ctx, commandSQL)
 	tx.closed = true
 	if err != nil {
 		if tx.conn.PgConn().TxStatus() != 'I' {
@@ -205,7 +215,7 @@ func (tx *dbTx) Rollback(ctx context.Context) error {
 	tx.closed = true
 	if err != nil {
 		// A rollback failure leaves the connection in an undefined state
-		tx.conn.die(fmt.Errorf("rollback failed: %w", err))
+		tx.conn.die()
 		return err
 	}
 
diff --git a/history-api/vendor/github.com/magiconair/properties/.gitignore b/history-api/vendor/github.com/magiconair/properties/.gitignore
deleted file mode 100644
index e7081ff5..00000000
--- a/history-api/vendor/github.com/magiconair/properties/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-*.sublime-project
-*.sublime-workspace
-*.un~
-*.swp
-.idea/
-*.iml
diff --git a/history-api/vendor/github.com/magiconair/properties/CHANGELOG.md b/history-api/vendor/github.com/magiconair/properties/CHANGELOG.md
deleted file mode 100644
index 842e8e24..00000000
--- a/history-api/vendor/github.com/magiconair/properties/CHANGELOG.md
+++ /dev/null
@@ -1,205 +0,0 @@
-## Changelog
-
-### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
-
- * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
-
-   Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
-
- * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
-
-### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
-
- * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
-
-   Thanks to [@ellie](https://github.com/ellie) for the patch.
-
- * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
-
-   This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
-   author happy until it affects real users.
-
-   Thanks to [@maage](https://github.com/maage) for the patch.
-
-### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
-
- * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
-
-   When reading comments \ are loaded correctly, but when writing they are then
-   replaced by \\. This leads to wrong comments when writing and reading multiple times.
-
-   Thanks to [@doxsch](https://github.com/doxsch) for the patch.
-
-### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
-
- * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
-
-   Thanks to [@sriv](https://github.com/sriv) for the patch.
-
-### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
-
- * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
-
-   The change is include the key in the error message which is causing the circular
-   reference when parsing/loading the properties files.
-
-   Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
-
-### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
-
- * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
-
-   This patch ensures that backslashes are escaped on write. Existing applications which
-   rely on the old behavior may need to be updated.
-
-   Thanks to [@apesternikov](https://github.com/apesternikov) for the patch.
-
- * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL()
-
-   Thanks to [@aliras1](https://github.com/aliras1) for the patch.
-
- * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write()
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
- * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
-### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
-
- * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request
-
-   This patch ensures that in `LoadURL` the response body is always closed.
-
-   Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
-
-### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
-
- * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
-
-   This adds the option to disable property expansion during loading.
-
-   Thanks to [@kmala](https://github.com/kmala) for the patch.
-
-### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
-
- * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
-
-   See PR for an example.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
-
- * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
-
-   Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
-   with a `circular reference error`.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
-
- * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
-
- * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
-
-   Thanks to [@mgurov](https://github.com/mgurov) for the fix.
-
-### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
-
- * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
- * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
-
-### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
-
- * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
- * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
-
-### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
-
- * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
- * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
- * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
- * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
-
-### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
-
- * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
- * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
- * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
-
-### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
-
- * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
-
-### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
-
- * Vendored in gopkg.in/check.v1
-
-### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
-
- * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
-
-### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
-
- * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
-
-### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
-
- * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
-
-### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
-
- * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
- * Add clickable links to README
-
-### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
-
- * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
-   [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
-
-### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
-
- * Added support for single and multi-line comments (reading, writing and updating)
- * The order of keys is now preserved
- * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
- * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
- * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
-
-### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
-
- * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
-
-### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
-
- * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
-
-### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
-
- * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
- * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
-
-### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
-
-* Added support for time.Duration
-* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
-* Changed default of MustXXX() failure from panic to log.Fatal
-
-### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
-
-* Added MustGet... functions
-* Added support for int and uint with range checks on 32 bit platforms
-
-### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
-
-* Renamed from goproperties to properties
-* Added support for expansion of environment vars in
-  filenames and value expressions
-* Fixed bug where value expressions were not at the
-  start of the string
-
-### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
-
-* Initial release
diff --git a/history-api/vendor/github.com/magiconair/properties/LICENSE.md b/history-api/vendor/github.com/magiconair/properties/LICENSE.md
deleted file mode 100644
index 79c87e3e..00000000
--- a/history-api/vendor/github.com/magiconair/properties/LICENSE.md
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2013-2020, Frank Schroeder
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/history-api/vendor/github.com/magiconair/properties/README.md b/history-api/vendor/github.com/magiconair/properties/README.md
deleted file mode 100644
index e2edda02..00000000
--- a/history-api/vendor/github.com/magiconair/properties/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
-[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
-[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
-[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-# Overview
-
-#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
-
-properties is a Go library for reading and writing properties files.
-
-It supports reading from multiple files or URLs and Spring style recursive
-property expansion of expressions like `${key}` to their corresponding value.
-Value expressions can refer to other keys like in `${key}` or to environment
-variables like in `${USER}`.  Filenames can also contain environment variables
-like in `/home/${USER}/myapp.properties`.
-
-Properties can be decoded into structs, maps, arrays and values through
-struct tags.
-
-Comments and the order of keys are preserved. Comments can be modified
-and can be written to the output.
-
-The properties library supports both ISO-8859-1 and UTF-8 encoded data.
-
-Starting from version 1.3.0 the behavior of the MustXXX() functions is
-configurable by providing a custom `ErrorHandler` function. The default has
-changed from `panic` to `log.Fatal` but this is configurable and custom
-error handling functions can be provided. See the package documentation for
-details.
-
-Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-## Getting Started
-
-```go
-import (
-	"flag"
-	"github.com/magiconair/properties"
-)
-
-func main() {
-	// init from a file
-	p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8)
-
-	// or multiple files
-	p = properties.MustLoadFiles([]string{
-			"${HOME}/config.properties",
-			"${HOME}/config-${USER}.properties",
-		}, properties.UTF8, true)
-
-	// or from a map
-	p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"})
-
-	// or from a string
-	p = properties.MustLoadString("key=value\nabc=def")
-
-	// or from a URL
-	p = properties.MustLoadURL("http://host/path")
-
-	// or from multiple URLs
-	p = properties.MustLoadURL([]string{
-			"http://host/config",
-			"http://host/config-${USER}",
-		}, true)
-
-	// or from flags
-	p.MustFlag(flag.CommandLine)
-
-	// get values through getters
-	host := p.MustGetString("host")
-	port := p.GetInt("port", 8080)
-
-	// or through Decode
-	type Config struct {
-		Host    string        `properties:"host"`
-		Port    int           `properties:"port,default=9000"`
-		Accept  []string      `properties:"accept,default=image/png;image;gif"`
-		Timeout time.Duration `properties:"timeout,default=5s"`
-	}
-	var cfg Config
-	if err := p.Decode(&cfg); err != nil {
-		log.Fatal(err)
-	}
-}
-
-```
-
-## Installation and Upgrade
-
-```
-$ go get -u github.com/magiconair/properties
-```
-
-## License
-
-2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details.
-
-## ToDo
-
-* Dump contents with passwords and secrets obscured
-
-## Updated Git tags
-
-#### 13 Feb 2018
-
-I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
-and I've only recently learned that this doesn't play well with `git describe` 😞
-
-I have replaced all lightweight tags with signed tags using this script which should
-retain the commit date, name and email address. Please run `git pull --tags` to update them.
-
-Worst case you have to reclone the repo.
-
-```shell
-#!/bin/bash
-tag=$1
-echo "Updating $tag"
-date=$(git show ${tag}^0 --format=%aD | head -1)
-email=$(git show ${tag}^0 --format=%aE | head -1)
-name=$(git show ${tag}^0 --format=%aN | head -1)
-GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
-```
-
-I apologize for the inconvenience.
-
-Frank
-
diff --git a/history-api/vendor/github.com/magiconair/properties/decode.go b/history-api/vendor/github.com/magiconair/properties/decode.go
deleted file mode 100644
index 8e6aa441..00000000
--- a/history-api/vendor/github.com/magiconair/properties/decode.go
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Decode assigns property values to exported fields of a struct.
-//
-// Decode traverses v recursively and returns an error if a value cannot be
-// converted to the field type or a required value is missing for a field.
-//
-// The following type dependent decodings are used:
-//
-// String, boolean, numeric fields have the value of the property key assigned.
-// The property key name is the name of the field. A different key and a default
-// value can be set in the field's tag. Fields without default value are
-// required. If the value cannot be converted to the field type an error is
-// returned.
-//
-// time.Duration fields have the result of time.ParseDuration() assigned.
-//
-// time.Time fields have the vaule of time.Parse() assigned. The default layout
-// is time.RFC3339 but can be set in the field's tag.
-//
-// Arrays and slices of string, boolean, numeric, time.Duration and time.Time
-// fields have the value interpreted as a comma separated list of values. The
-// individual values are trimmed of whitespace and empty values are ignored. A
-// default value can be provided as a semicolon separated list in the field's
-// tag.
-//
-// Struct fields are decoded recursively using the field name plus "." as
-// prefix. The prefix (without dot) can be overridden in the field's tag.
-// Default values are not supported in the field's tag. Specify them on the
-// fields of the inner struct instead.
-//
-// Map fields must have a key of type string and are decoded recursively by
-// using the field's name plus ".' as prefix and the next element of the key
-// name as map key. The prefix (without dot) can be overridden in the field's
-// tag. Default values are not supported.
-//
-// Examples:
-//
-//	// Field is ignored.
-//	Field int `properties:"-"`
-//
-//	// Field is assigned value of 'Field'.
-//	Field int
-//
-//	// Field is assigned value of 'myName'.
-//	Field int `properties:"myName"`
-//
-//	// Field is assigned value of key 'myName' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:"myName,default=15"`
-//
-//	// Field is assigned value of key 'Field' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:",default=15"`
-//
-//	// Field is assigned value of key 'date' and the date
-//	// is in format 2006-01-02
-//	Field time.Time `properties:"date,layout=2006-01-02"`
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas.
-//	Field []string
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas and has a default
-//	// value ["a", "b", "c"] if the key does not exist.
-//	Field []string `properties:",default=a;b;c"`
-//
-//	// Field is decoded recursively with "Field." as key prefix.
-//	Field SomeStruct
-//
-//	// Field is decoded recursively with "myName." as key prefix.
-//	Field SomeStruct `properties:"myName"`
-//
-//	// Field is decoded recursively with "Field." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string
-//
-//	// Field is decoded recursively with "myName." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string `properties:"myName"`
-func (p *Properties) Decode(x interface{}) error {
-	t, v := reflect.TypeOf(x), reflect.ValueOf(x)
-	if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct {
-		return fmt.Errorf("not a pointer to struct: %s", t)
-	}
-	if err := dec(p, "", nil, nil, v); err != nil {
-		return err
-	}
-	return nil
-}
-
-func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
-	t := v.Type()
-
-	// value returns the property value for key or the default if provided.
-	value := func() (string, error) {
-		if val, ok := p.Get(key); ok {
-			return val, nil
-		}
-		if def != nil {
-			return *def, nil
-		}
-		return "", fmt.Errorf("missing required key %s", key)
-	}
-
-	// conv converts a string to a value of the given type.
-	conv := func(s string, t reflect.Type) (val reflect.Value, err error) {
-		var v interface{}
-
-		switch {
-		case isDuration(t):
-			v, err = time.ParseDuration(s)
-
-		case isTime(t):
-			layout := opts["layout"]
-			if layout == "" {
-				layout = time.RFC3339
-			}
-			v, err = time.Parse(layout, s)
-
-		case isBool(t):
-			v, err = boolVal(s), nil
-
-		case isString(t):
-			v, err = s, nil
-
-		case isFloat(t):
-			v, err = strconv.ParseFloat(s, 64)
-
-		case isInt(t):
-			v, err = strconv.ParseInt(s, 10, 64)
-
-		case isUint(t):
-			v, err = strconv.ParseUint(s, 10, 64)
-
-		default:
-			return reflect.Zero(t), fmt.Errorf("unsupported type %s", t)
-		}
-		if err != nil {
-			return reflect.Zero(t), err
-		}
-		return reflect.ValueOf(v).Convert(t), nil
-	}
-
-	// keydef returns the property key and the default value based on the
-	// name of the struct field and the options in the tag.
-	keydef := func(f reflect.StructField) (string, *string, map[string]string) {
-		_key, _opts := parseTag(f.Tag.Get("properties"))
-
-		var _def *string
-		if d, ok := _opts["default"]; ok {
-			_def = &d
-		}
-		if _key != "" {
-			return _key, _def, _opts
-		}
-		return f.Name, _def, _opts
-	}
-
-	switch {
-	case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t):
-		s, err := value()
-		if err != nil {
-			return err
-		}
-		val, err := conv(s, t)
-		if err != nil {
-			return err
-		}
-		v.Set(val)
-
-	case isPtr(t):
-		return dec(p, key, def, opts, v.Elem())
-
-	case isStruct(t):
-		for i := 0; i < v.NumField(); i++ {
-			fv := v.Field(i)
-			fk, def, opts := keydef(t.Field(i))
-			if !fv.CanSet() {
-				return fmt.Errorf("cannot set %s", t.Field(i).Name)
-			}
-			if fk == "-" {
-				continue
-			}
-			if key != "" {
-				fk = key + "." + fk
-			}
-			if err := dec(p, fk, def, opts, fv); err != nil {
-				return err
-			}
-		}
-		return nil
-
-	case isArray(t):
-		val, err := value()
-		if err != nil {
-			return err
-		}
-		vals := split(val, ";")
-		a := reflect.MakeSlice(t, 0, len(vals))
-		for _, s := range vals {
-			val, err := conv(s, t.Elem())
-			if err != nil {
-				return err
-			}
-			a = reflect.Append(a, val)
-		}
-		v.Set(a)
-
-	case isMap(t):
-		valT := t.Elem()
-		m := reflect.MakeMap(t)
-		for postfix := range p.FilterStripPrefix(key + ".").m {
-			pp := strings.SplitN(postfix, ".", 2)
-			mk, mv := pp[0], reflect.New(valT)
-			if err := dec(p, key+"."+mk, nil, nil, mv); err != nil {
-				return err
-			}
-			m.SetMapIndex(reflect.ValueOf(mk), mv.Elem())
-		}
-		v.Set(m)
-
-	default:
-		return fmt.Errorf("unsupported type %s", t)
-	}
-	return nil
-}
-
-// split splits a string on sep, trims whitespace of elements
-// and omits empty elements
-func split(s string, sep string) []string {
-	var a []string
-	for _, v := range strings.Split(s, sep) {
-		if v = strings.TrimSpace(v); v != "" {
-			a = append(a, v)
-		}
-	}
-	return a
-}
-
-// parseTag parses a "key,k=v,k=v,..."
-func parseTag(tag string) (key string, opts map[string]string) {
-	opts = map[string]string{}
-	for i, s := range strings.Split(tag, ",") {
-		if i == 0 {
-			key = s
-			continue
-		}
-
-		pp := strings.SplitN(s, "=", 2)
-		if len(pp) == 1 {
-			opts[pp[0]] = ""
-		} else {
-			opts[pp[0]] = pp[1]
-		}
-	}
-	return key, opts
-}
-
-func isArray(t reflect.Type) bool    { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice }
-func isBool(t reflect.Type) bool     { return t.Kind() == reflect.Bool }
-func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) }
-func isMap(t reflect.Type) bool      { return t.Kind() == reflect.Map }
-func isPtr(t reflect.Type) bool      { return t.Kind() == reflect.Ptr }
-func isString(t reflect.Type) bool   { return t.Kind() == reflect.String }
-func isStruct(t reflect.Type) bool   { return t.Kind() == reflect.Struct }
-func isTime(t reflect.Type) bool     { return t == reflect.TypeOf(time.Time{}) }
-func isFloat(t reflect.Type) bool {
-	return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64
-}
-func isInt(t reflect.Type) bool {
-	return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64
-}
-func isUint(t reflect.Type) bool {
-	return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/doc.go b/history-api/vendor/github.com/magiconair/properties/doc.go
deleted file mode 100644
index 7c797931..00000000
--- a/history-api/vendor/github.com/magiconair/properties/doc.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package properties provides functions for reading and writing
-// ISO-8859-1 and UTF-8 encoded .properties files and has
-// support for recursive property expansion.
-//
-// Java properties files are ISO-8859-1 encoded and use Unicode
-// literals for characters outside the ISO character set. Unicode
-// literals can be used in UTF-8 encoded properties files but
-// aren't necessary.
-//
-// To load a single properties file use MustLoadFile():
-//
-//	p := properties.MustLoadFile(filename, properties.UTF8)
-//
-// To load multiple properties files use MustLoadFiles()
-// which loads the files in the given order and merges the
-// result. Missing properties files can be ignored if the
-// 'ignoreMissing' flag is set to true.
-//
-// Filenames can contain environment variables which are expanded
-// before loading.
-//
-//	f1 := "/etc/myapp/myapp.conf"
-//	f2 := "/home/${USER}/myapp.conf"
-//	p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)
-//
-// All of the different key/value delimiters ' ', ':' and '=' are
-// supported as well as the comment characters '!' and '#' and
-// multi-line values.
-//
-//	! this is a comment
-//	# and so is this
-//
-//	# the following expressions are equal
-//	key value
-//	key=value
-//	key:value
-//	key = value
-//	key : value
-//	key = val\
-//	      ue
-//
-// Properties stores all comments preceding a key and provides
-// GetComments() and SetComments() methods to retrieve and
-// update them. The convenience functions GetComment() and
-// SetComment() allow access to the last comment. The
-// WriteComment() method writes properties files including
-// the comments and with the keys in the original order.
-// This can be used for sanitizing properties files.
-//
-// Property expansion is recursive and circular references
-// and malformed expressions are not allowed and cause an
-// error. Expansion of environment variables is supported.
-//
-//	# standard property
-//	key = value
-//
-//	# property expansion: key2 = value
-//	key2 = ${key}
-//
-//	# recursive expansion: key3 = value
-//	key3 = ${key2}
-//
-//	# circular reference (error)
-//	key = ${key}
-//
-//	# malformed expression (error)
-//	key = ${ke
-//
-//	# refers to the users' home dir
-//	home = ${HOME}
-//
-//	# local key takes precedence over env var: u = foo
-//	USER = foo
-//	u = ${USER}
-//
-// The default property expansion format is ${key} but can be
-// changed by setting different pre- and postfix values on the
-// Properties object.
-//
-//	p := properties.NewProperties()
-//	p.Prefix = "#["
-//	p.Postfix = "]#"
-//
-// Properties provides convenience functions for getting typed
-// values with default values if the key does not exist or the
-// type conversion failed.
-//
-//	# Returns true if the value is either "1", "on", "yes" or "true"
-//	# Returns false for every other value and the default value if
-//	# the key does not exist.
-//	v = p.GetBool("key", false)
-//
-//	# Returns the value if the key exists and the format conversion
-//	# was successful. Otherwise, the default value is returned.
-//	v = p.GetInt64("key", 999)
-//	v = p.GetUint64("key", 999)
-//	v = p.GetFloat64("key", 123.0)
-//	v = p.GetString("key", "def")
-//	v = p.GetDuration("key", 999)
-//
-// As an alternative properties may be applied with the standard
-// library's flag implementation at any time.
-//
-//	# Standard configuration
-//	v = flag.Int("key", 999, "help message")
-//	flag.Parse()
-//
-//	# Merge p into the flag set
-//	p.MustFlag(flag.CommandLine)
-//
-// Properties provides several MustXXX() convenience functions
-// which will terminate the app if an error occurs. The behavior
-// of the failure is configurable and the default is to call
-// log.Fatal(err). To have the MustXXX() functions panic instead
-// of logging the error set a different ErrorHandler before
-// you use the Properties package.
-//
-//	properties.ErrorHandler = properties.PanicHandler
-//
-//	# Will panic instead of logging an error
-//	p := properties.MustLoadFile("config.properties")
-//
-// You can also provide your own ErrorHandler function. The only requirement
-// is that the error handler function must exit after handling the error.
-//
-//	  properties.ErrorHandler = func(err error) {
-//		     fmt.Println(err)
-//	      os.Exit(1)
-//	  }
-//
-//	  # Will write to stdout and then exit
-//	  p := properties.MustLoadFile("config.properties")
-//
-// Properties can also be loaded into a struct via the `Decode`
-// method, e.g.
-//
-//	type S struct {
-//	    A string        `properties:"a,default=foo"`
-//	    D time.Duration `properties:"timeout,default=5s"`
-//	    E time.Time     `properties:"expires,layout=2006-01-02,default=2015-01-01"`
-//	}
-//
-// See `Decode()` method for the full documentation.
-//
-// The following documents provide a description of the properties
-// file format.
-//
-// http://en.wikipedia.org/wiki/.properties
-//
-// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29
-package properties
diff --git a/history-api/vendor/github.com/magiconair/properties/integrate.go b/history-api/vendor/github.com/magiconair/properties/integrate.go
deleted file mode 100644
index 35d0ae97..00000000
--- a/history-api/vendor/github.com/magiconair/properties/integrate.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import "flag"
-
-// MustFlag sets flags that are skipped by dst.Parse when p contains
-// the respective key for flag.Flag.Name.
-//
-// It's use is recommended with command line arguments as in:
-//
-//	flag.Parse()
-//	p.MustFlag(flag.CommandLine)
-func (p *Properties) MustFlag(dst *flag.FlagSet) {
-	m := make(map[string]*flag.Flag)
-	dst.VisitAll(func(f *flag.Flag) {
-		m[f.Name] = f
-	})
-	dst.Visit(func(f *flag.Flag) {
-		delete(m, f.Name) // overridden
-	})
-
-	for name, f := range m {
-		v, ok := p.Get(name)
-		if !ok {
-			continue
-		}
-
-		if err := f.Value.Set(v); err != nil {
-			ErrorHandler(err)
-		}
-	}
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/lex.go b/history-api/vendor/github.com/magiconair/properties/lex.go
deleted file mode 100644
index 3d15a1f6..00000000
--- a/history-api/vendor/github.com/magiconair/properties/lex.go
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// Parts of the lexer are from the template/text/parser package
-// For these parts the following applies:
-//
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file of the go 1.2
-// distribution.
-
-package properties
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-	"unicode/utf8"
-)
-
-// item represents a token or text string returned from the scanner.
-type item struct {
-	typ itemType // The type of this item.
-	pos int      // The starting position, in bytes, of this item in the input string.
-	val string   // The value of this item.
-}
-
-func (i item) String() string {
-	switch {
-	case i.typ == itemEOF:
-		return "EOF"
-	case i.typ == itemError:
-		return i.val
-	case len(i.val) > 10:
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError itemType = iota // error occurred; value is text of error
-	itemEOF
-	itemKey     // a key
-	itemValue   // a value
-	itemComment // a comment
-)
-
-// defines a constant for EOF
-const eof = -1
-
-// permitted whitespace characters space, FF and TAB
-const whitespace = " \f\t"
-
-// stateFn represents the state of the scanner as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	input   string    // the string being scanned
-	state   stateFn   // the next lexing function to enter
-	pos     int       // current position in the input
-	start   int       // start position of this item
-	width   int       // width of last rune read from input
-	lastPos int       // position of most recent item returned by nextItem
-	runes   []rune    // scanned runes for this item
-	items   chan item // channel of scanned items
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() rune {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
-	l.width = w
-	l.pos += l.width
-	return r
-}
-
-// peek returns but does not consume the next rune in the input.
-func (l *lexer) peek() rune {
-	r := l.next()
-	l.backup()
-	return r
-}
-
-// backup steps back one rune. Can only be called once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	i := item{t, l.start, string(l.runes)}
-	l.items <- i
-	l.start = l.pos
-	l.runes = l.runes[:0]
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// appends the rune to the current value
-func (l *lexer) appendRune(r rune) {
-	l.runes = append(l.runes, r)
-}
-
-// accept consumes the next rune if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.ContainsRune(valid, l.next()) {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.ContainsRune(valid, l.next()) {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on, based on the position of
-// the previous item returned by nextItem. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.lastPos], "\n")
-}
-
-// errorf returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.nextItem.
-func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
-	return nil
-}
-
-// nextItem returns the next item from the input.
-func (l *lexer) nextItem() item {
-	i := <-l.items
-	l.lastPos = i.pos
-	return i
-}
-
-// lex creates a new scanner for the input string.
-func lex(input string) *lexer {
-	l := &lexer{
-		input: input,
-		items: make(chan item),
-		runes: make([]rune, 0, 32),
-	}
-	go l.run()
-	return l
-}
-
-// run runs the state machine for the lexer.
-func (l *lexer) run() {
-	for l.state = lexBeforeKey(l); l.state != nil; {
-		l.state = l.state(l)
-	}
-}
-
-// state functions
-
-// lexBeforeKey scans until a key begins.
-func lexBeforeKey(l *lexer) stateFn {
-	switch r := l.next(); {
-	case isEOF(r):
-		l.emit(itemEOF)
-		return nil
-
-	case isEOL(r):
-		l.ignore()
-		return lexBeforeKey
-
-	case isComment(r):
-		return lexComment
-
-	case isWhitespace(r):
-		l.ignore()
-		return lexBeforeKey
-
-	default:
-		l.backup()
-		return lexKey
-	}
-}
-
-// lexComment scans a comment line. The comment character has already been scanned.
-func lexComment(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.ignore()
-	for {
-		switch r := l.next(); {
-		case isEOF(r):
-			l.ignore()
-			l.emit(itemEOF)
-			return nil
-		case isEOL(r):
-			l.emit(itemComment)
-			return lexBeforeKey
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// lexKey scans the key up to a delimiter
-func lexKey(l *lexer) stateFn {
-	var r rune
-
-Loop:
-	for {
-		switch r = l.next(); {
-
-		case isEscape(r):
-			err := l.scanEscapeSequence()
-			if err != nil {
-				return l.errorf(err.Error())
-			}
-
-		case isEndOfKey(r):
-			l.backup()
-			break Loop
-
-		case isEOF(r):
-			break Loop
-
-		default:
-			l.appendRune(r)
-		}
-	}
-
-	if len(l.runes) > 0 {
-		l.emit(itemKey)
-	}
-
-	if isEOF(r) {
-		l.emit(itemEOF)
-		return nil
-	}
-
-	return lexBeforeValue
-}
-
-// lexBeforeValue scans the delimiter between key and value.
-// Leading and trailing whitespace is ignored.
-// We expect to be just after the key.
-func lexBeforeValue(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.accept(":=")
-	l.acceptRun(whitespace)
-	l.ignore()
-	return lexValue
-}
-
-// lexValue scans text until the end of the line. We expect to be just after the delimiter.
-func lexValue(l *lexer) stateFn {
-	for {
-		switch r := l.next(); {
-		case isEscape(r):
-			if isEOL(l.peek()) {
-				l.next()
-				l.acceptRun(whitespace)
-			} else {
-				err := l.scanEscapeSequence()
-				if err != nil {
-					return l.errorf(err.Error())
-				}
-			}
-
-		case isEOL(r):
-			l.emit(itemValue)
-			l.ignore()
-			return lexBeforeKey
-
-		case isEOF(r):
-			l.emit(itemValue)
-			l.emit(itemEOF)
-			return nil
-
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// scanEscapeSequence scans either one of the escaped characters
-// or a unicode literal. We expect to be after the escape character.
-func (l *lexer) scanEscapeSequence() error {
-	switch r := l.next(); {
-
-	case isEscapedCharacter(r):
-		l.appendRune(decodeEscapedCharacter(r))
-		return nil
-
-	case atUnicodeLiteral(r):
-		return l.scanUnicodeLiteral()
-
-	case isEOF(r):
-		return fmt.Errorf("premature EOF")
-
-	// silently drop the escape character and append the rune as is
-	default:
-		l.appendRune(r)
-		return nil
-	}
-}
-
-// scans a unicode literal in the form \uXXXX. We expect to be after the \u.
-func (l *lexer) scanUnicodeLiteral() error {
-	// scan the digits
-	d := make([]rune, 4)
-	for i := 0; i < 4; i++ {
-		d[i] = l.next()
-		if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) {
-			return fmt.Errorf("invalid unicode literal")
-		}
-	}
-
-	// decode the digits into a rune
-	r, err := strconv.ParseInt(string(d), 16, 0)
-	if err != nil {
-		return err
-	}
-
-	l.appendRune(rune(r))
-	return nil
-}
-
-// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character.
-func decodeEscapedCharacter(r rune) rune {
-	switch r {
-	case 'f':
-		return '\f'
-	case 'n':
-		return '\n'
-	case 'r':
-		return '\r'
-	case 't':
-		return '\t'
-	default:
-		return r
-	}
-}
-
-// atUnicodeLiteral reports whether we are at a unicode literal.
-// The escape character has already been consumed.
-func atUnicodeLiteral(r rune) bool {
-	return r == 'u'
-}
-
-// isComment reports whether we are at the start of a comment.
-func isComment(r rune) bool {
-	return r == '#' || r == '!'
-}
-
-// isEndOfKey reports whether the rune terminates the current key.
-func isEndOfKey(r rune) bool {
-	return strings.ContainsRune(" \f\t\r\n:=", r)
-}
-
-// isEOF reports whether we are at EOF.
-func isEOF(r rune) bool {
-	return r == eof
-}
-
-// isEOL reports whether we are at a new line character.
-func isEOL(r rune) bool {
-	return r == '\n' || r == '\r'
-}
-
-// isEscape reports whether the rune is the escape character which
-// prefixes unicode literals and other escaped characters.
-func isEscape(r rune) bool {
-	return r == '\\'
-}
-
-// isEscapedCharacter reports whether we are at one of the characters that need escaping.
-// The escape character has already been consumed.
-func isEscapedCharacter(r rune) bool {
-	return strings.ContainsRune(" :=fnrt", r)
-}
-
-// isWhitespace reports whether the rune is a whitespace character.
-func isWhitespace(r rune) bool {
-	return strings.ContainsRune(whitespace, r)
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/load.go b/history-api/vendor/github.com/magiconair/properties/load.go
deleted file mode 100644
index 635368dc..00000000
--- a/history-api/vendor/github.com/magiconair/properties/load.go
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"strings"
-)
-
-// Encoding specifies encoding of the input data.
-type Encoding uint
-
-const (
-	// utf8Default is a private placeholder for the zero value of Encoding to
-	// ensure that it has the correct meaning. UTF8 is the default encoding but
-	// was assigned a non-zero value which cannot be changed without breaking
-	// existing code. Clients should continue to use the public constants.
-	utf8Default Encoding = iota
-
-	// UTF8 interprets the input data as UTF-8.
-	UTF8
-
-	// ISO_8859_1 interprets the input data as ISO-8859-1.
-	ISO_8859_1
-)
-
-type Loader struct {
-	// Encoding determines how the data from files and byte buffers
-	// is interpreted. For URLs the Content-Type header is used
-	// to determine the encoding of the data.
-	Encoding Encoding
-
-	// DisableExpansion configures the property expansion of the
-	// returned property object. When set to true, the property values
-	// will not be expanded and the Property object will not be checked
-	// for invalid expansion expressions.
-	DisableExpansion bool
-
-	// IgnoreMissing configures whether missing files or URLs which return
-	// 404 are reported as errors. When set to true, missing files and 404
-	// status codes are not reported as errors.
-	IgnoreMissing bool
-}
-
-// Load reads a buffer into a Properties struct.
-func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
-	return l.loadBytes(buf, l.Encoding)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into
-// a Properties struct. If IgnoreMissing is true then a 404 status code or
-// missing file will not be reported as error. Encoding sets the encoding for
-// files. For the URLs see LoadURL for the Content-Type header and the
-// encoding.
-func (l *Loader) LoadAll(names []string) (*Properties, error) {
-	all := NewProperties()
-	for _, name := range names {
-		n, err := expandName(name)
-		if err != nil {
-			return nil, err
-		}
-
-		var p *Properties
-		switch {
-		case strings.HasPrefix(n, "http://"):
-			p, err = l.LoadURL(n)
-		case strings.HasPrefix(n, "https://"):
-			p, err = l.LoadURL(n)
-		default:
-			p, err = l.LoadFile(n)
-		}
-		if err != nil {
-			return nil, err
-		}
-		all.Merge(p)
-	}
-
-	all.DisableExpansion = l.DisableExpansion
-	if all.DisableExpansion {
-		return all, nil
-	}
-	return all, all.check()
-}
-
-// LoadFile reads a file into a Properties struct.
-// If IgnoreMissing is true then a missing file will not be
-// reported as error.
-func (l *Loader) LoadFile(filename string) (*Properties, error) {
-	data, err := ioutil.ReadFile(filename)
-	if err != nil {
-		if l.IgnoreMissing && os.IsNotExist(err) {
-			LogPrintf("properties: %s not found. skipping", filename)
-			return NewProperties(), nil
-		}
-		return nil, err
-	}
-	return l.loadBytes(data, l.Encoding)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-//
-// The encoding is determined via the Content-Type header which
-// should be set to 'text/plain'. If the 'charset' parameter is
-// missing, 'iso-8859-1' or 'latin1' the encoding is set to
-// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
-// encoding is set to UTF-8. A missing content type header is
-// interpreted as 'text/plain; charset=utf-8'.
-func (l *Loader) LoadURL(url string) (*Properties, error) {
-	resp, err := http.Get(url)
-	if err != nil {
-		return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode == 404 && l.IgnoreMissing {
-		LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
-		return NewProperties(), nil
-	}
-
-	if resp.StatusCode != 200 {
-		return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
-	}
-
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
-	}
-
-	ct := resp.Header.Get("Content-Type")
-	ct = strings.Join(strings.Fields(ct), "")
-	var enc Encoding
-	switch strings.ToLower(ct) {
-	case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1":
-		enc = ISO_8859_1
-	case "", "text/plain;charset=utf-8":
-		enc = UTF8
-	default:
-		return nil, fmt.Errorf("properties: invalid content type %s", ct)
-	}
-
-	return l.loadBytes(body, enc)
-}
-
-func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) {
-	p, err := parse(convert(buf, enc))
-	if err != nil {
-		return nil, err
-	}
-	p.DisableExpansion = l.DisableExpansion
-	if p.DisableExpansion {
-		return p, nil
-	}
-	return p, p.check()
-}
-
-// Load reads a buffer into a Properties struct.
-func Load(buf []byte, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadBytes(buf)
-}
-
-// LoadString reads an UTF8 string into a properties struct.
-func LoadString(s string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadBytes([]byte(s))
-}
-
-// LoadMap creates a new Properties struct from a string map.
-func LoadMap(m map[string]string) *Properties {
-	p := NewProperties()
-	for k, v := range m {
-		p.Set(k, v)
-	}
-	return p
-}
-
-// LoadFile reads a file into a Properties struct.
-func LoadFile(filename string, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadAll([]string{filename})
-}
-
-// LoadFiles reads multiple files in the given order into
-// a Properties struct. If 'ignoreMissing' is true then
-// non-existent files will not be reported as error.
-func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(filenames)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-// See Loader#LoadURL for details.
-func LoadURL(url string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadAll([]string{url})
-}
-
-// LoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct. If IgnoreMissing is true then a 404 status code will
-// not be reported as error. See Loader#LoadURL for the Content-Type header
-// and the encoding.
-func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(urls)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding.
-func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(names)
-}
-
-// MustLoadString reads an UTF8 string into a Properties struct and
-// panics on error.
-func MustLoadString(s string) *Properties {
-	return must(LoadString(s))
-}
-
-// MustLoadFile reads a file into a Properties struct and
-// panics on error.
-func MustLoadFile(filename string, enc Encoding) *Properties {
-	return must(LoadFile(filename, enc))
-}
-
-// MustLoadFiles reads multiple files in the given order into
-// a Properties struct and panics on error. If 'ignoreMissing'
-// is true then non-existent files will not be reported as error.
-func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadFiles(filenames, enc, ignoreMissing))
-}
-
-// MustLoadURL reads the content of a URL into a Properties struct and
-// panics on error.
-func MustLoadURL(url string) *Properties {
-	return must(LoadURL(url))
-}
-
-// MustLoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct and panics on error. If 'ignoreMissing' is true then a 404
-// status code will not be reported as error.
-func MustLoadURLs(urls []string, ignoreMissing bool) *Properties {
-	return must(LoadURLs(urls, ignoreMissing))
-}
-
-// MustLoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding. It panics on error.
-func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadAll(names, enc, ignoreMissing))
-}
-
-func must(p *Properties, err error) *Properties {
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return p
-}
-
-// expandName expands ${ENV_VAR} expressions in a name.
-// If the environment variable does not exist then it will be replaced
-// with an empty string. Malformed expressions like "${ENV_VAR" will
-// be reported as error.
-func expandName(name string) (string, error) {
-	return expand(name, []string{}, "${", "}", make(map[string]string))
-}
-
-// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
-// For ISO-8859-1 we can convert each byte straight into a rune since the
-// first 256 unicode code points cover ISO-8859-1.
-func convert(buf []byte, enc Encoding) string {
-	switch enc {
-	case utf8Default, UTF8:
-		return string(buf)
-	case ISO_8859_1:
-		runes := make([]rune, len(buf))
-		for i, b := range buf {
-			runes[i] = rune(b)
-		}
-		return string(runes)
-	default:
-		ErrorHandler(fmt.Errorf("unsupported encoding %v", enc))
-	}
-	panic("ErrorHandler should exit")
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/parser.go b/history-api/vendor/github.com/magiconair/properties/parser.go
deleted file mode 100644
index fccfd39f..00000000
--- a/history-api/vendor/github.com/magiconair/properties/parser.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"runtime"
-)
-
-type parser struct {
-	lex *lexer
-}
-
-func parse(input string) (properties *Properties, err error) {
-	p := &parser{lex: lex(input)}
-	defer p.recover(&err)
-
-	properties = NewProperties()
-	key := ""
-	comments := []string{}
-
-	for {
-		token := p.expectOneOf(itemComment, itemKey, itemEOF)
-		switch token.typ {
-		case itemEOF:
-			goto done
-		case itemComment:
-			comments = append(comments, token.val)
-			continue
-		case itemKey:
-			key = token.val
-			if _, ok := properties.m[key]; !ok {
-				properties.k = append(properties.k, key)
-			}
-		}
-
-		token = p.expectOneOf(itemValue, itemEOF)
-		if len(comments) > 0 {
-			properties.c[key] = comments
-			comments = []string{}
-		}
-		switch token.typ {
-		case itemEOF:
-			properties.m[key] = ""
-			goto done
-		case itemValue:
-			properties.m[key] = token.val
-		}
-	}
-
-done:
-	return properties, nil
-}
-
-func (p *parser) errorf(format string, args ...interface{}) {
-	format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
-	panic(fmt.Errorf(format, args...))
-}
-
-func (p *parser) expectOneOf(expected ...itemType) (token item) {
-	token = p.lex.nextItem()
-	for _, v := range expected {
-		if token.typ == v {
-			return token
-		}
-	}
-	p.unexpected(token)
-	panic("unexpected token")
-}
-
-func (p *parser) unexpected(token item) {
-	p.errorf(token.String())
-}
-
-// recover is the handler that turns panics into returns from the top level of Parse.
-func (p *parser) recover(errp *error) {
-	e := recover()
-	if e != nil {
-		if _, ok := e.(runtime.Error); ok {
-			panic(e)
-		}
-		*errp = e.(error)
-	}
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/properties.go b/history-api/vendor/github.com/magiconair/properties/properties.go
deleted file mode 100644
index fb2f7b40..00000000
--- a/history-api/vendor/github.com/magiconair/properties/properties.go
+++ /dev/null
@@ -1,848 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer.
-// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used.
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"regexp"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-	"unicode/utf8"
-)
-
-const maxExpansionDepth = 64
-
-// ErrorHandlerFunc defines the type of function which handles failures
-// of the MustXXX() functions. An error handler function must exit
-// the application after handling the error.
-type ErrorHandlerFunc func(error)
-
-// ErrorHandler is the function which handles failures of the MustXXX()
-// functions. The default is LogFatalHandler.
-var ErrorHandler ErrorHandlerFunc = LogFatalHandler
-
-// LogHandlerFunc defines the function prototype for logging errors.
-type LogHandlerFunc func(fmt string, args ...interface{})
-
-// LogPrintf defines a log handler which uses log.Printf.
-var LogPrintf LogHandlerFunc = log.Printf
-
-// LogFatalHandler handles the error by logging a fatal error and exiting.
-func LogFatalHandler(err error) {
-	log.Fatal(err)
-}
-
-// PanicHandler handles the error by panicking.
-func PanicHandler(err error) {
-	panic(err)
-}
-
-// -----------------------------------------------------------------------------
-
-// A Properties contains the key/value pairs from the properties input.
-// All values are stored in unexpanded form and are expanded at runtime
-type Properties struct {
-	// Pre-/Postfix for property expansion.
-	Prefix  string
-	Postfix string
-
-	// DisableExpansion controls the expansion of properties on Get()
-	// and the check for circular references on Set(). When set to
-	// true Properties behaves like a simple key/value store and does
-	// not check for circular references on Get() or on Set().
-	DisableExpansion bool
-
-	// Stores the key/value pairs
-	m map[string]string
-
-	// Stores the comments per key.
-	c map[string][]string
-
-	// Stores the keys in order of appearance.
-	k []string
-
-	// WriteSeparator specifies the separator of key and value while writing the properties.
-	WriteSeparator string
-}
-
-// NewProperties creates a new Properties struct with the default
-// configuration for "${key}" expressions.
-func NewProperties() *Properties {
-	return &Properties{
-		Prefix:  "${",
-		Postfix: "}",
-		m:       map[string]string{},
-		c:       map[string][]string{},
-		k:       []string{},
-	}
-}
-
-// Load reads a buffer into the given Properties struct.
-func (p *Properties) Load(buf []byte, enc Encoding) error {
-	l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion}
-	newProperties, err := l.LoadBytes(buf)
-	if err != nil {
-		return err
-	}
-	p.Merge(newProperties)
-	return nil
-}
-
-// Get returns the expanded value for the given key if exists.
-// Otherwise, ok is false.
-func (p *Properties) Get(key string) (value string, ok bool) {
-	v, ok := p.m[key]
-	if p.DisableExpansion {
-		return v, ok
-	}
-	if !ok {
-		return "", false
-	}
-
-	expanded, err := p.expand(key, v)
-
-	// we guarantee that the expanded value is free of
-	// circular references and malformed expressions
-	// so we panic if we still get an error here.
-	if err != nil {
-		ErrorHandler(err)
-	}
-
-	return expanded, true
-}
-
-// MustGet returns the expanded value for the given key if exists.
-// Otherwise, it panics.
-func (p *Properties) MustGet(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// ClearComments removes the comments for all keys.
-func (p *Properties) ClearComments() {
-	p.c = map[string][]string{}
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComment returns the last comment before the given key or an empty string.
-func (p *Properties) GetComment(key string) string {
-	comments, ok := p.c[key]
-	if !ok || len(comments) == 0 {
-		return ""
-	}
-	return comments[len(comments)-1]
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComments returns all comments that appeared before the given key or nil.
-func (p *Properties) GetComments(key string) []string {
-	if comments, ok := p.c[key]; ok {
-		return comments
-	}
-	return nil
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComment sets the comment for the key.
-func (p *Properties) SetComment(key, comment string) {
-	p.c[key] = []string{comment}
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComments sets the comments for the key. If the comments are nil then
-// all comments for this key are deleted.
-func (p *Properties) SetComments(key string, comments []string) {
-	if comments == nil {
-		delete(p.c, key)
-		return
-	}
-	p.c[key] = comments
-}
-
-// ----------------------------------------------------------------------------
-
-// GetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the default value is returned.
-func (p *Properties) GetBool(key string, def bool) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the function panics.
-func (p *Properties) MustGetBool(key string) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getBool(key string) (value bool, err error) {
-	if v, ok := p.Get(key); ok {
-		return boolVal(v), nil
-	}
-	return false, invalidKeyError(key)
-}
-
-func boolVal(v string) bool {
-	v = strings.ToLower(v)
-	return v == "1" || v == "true" || v == "yes" || v == "on"
-}
-
-// ----------------------------------------------------------------------------
-
-// GetDuration parses the expanded value as an time.Duration (in ns) if the
-// key exists. If key does not exist or the value cannot be parsed the default
-// value is returned. In almost all cases you want to use GetParsedDuration().
-func (p *Properties) GetDuration(key string, def time.Duration) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return time.Duration(v)
-}
-
-// MustGetDuration parses the expanded value as an time.Duration (in ns) if
-// the key exists. If key does not exist or the value cannot be parsed the
-// function panics. In almost all cases you want to use MustGetParsedDuration().
-func (p *Properties) MustGetDuration(key string) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return time.Duration(v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		return def
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetParsedDuration(key string) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		ErrorHandler(invalidKeyError(key))
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-// ----------------------------------------------------------------------------
-
-// GetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetFloat64(key string, def float64) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetFloat64(key string) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getFloat64(key string) (value float64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseFloat(v, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetInt(key string, def int) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return intRangeCheck(key, v)
-}
-
-// MustGetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetInt(key string) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return intRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt64 parses the expanded value as an int64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetInt64(key string, def int64) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetInt64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetInt64(key string) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getInt64(key string) (value int64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseInt(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint parses the expanded value as an uint if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetUint(key string, def uint) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return uintRangeCheck(key, v)
-}
-
-// MustGetUint parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetUint(key string) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return uintRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint64 parses the expanded value as an uint64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetUint64(key string, def uint64) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetUint64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetUint64(key string) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getUint64(key string) (value uint64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseUint(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetString returns the expanded value for the given key if exists or
-// the default value otherwise.
-func (p *Properties) GetString(key, def string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	return def
-}
-
-// MustGetString returns the expanded value for the given key if exists or
-// panics otherwise.
-func (p *Properties) MustGetString(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// Filter returns a new properties object which contains all properties
-// for which the key matches the pattern.
-func (p *Properties) Filter(pattern string) (*Properties, error) {
-	re, err := regexp.Compile(pattern)
-	if err != nil {
-		return nil, err
-	}
-
-	return p.FilterRegexp(re), nil
-}
-
-// FilterRegexp returns a new properties object which contains all properties
-// for which the key matches the regular expression.
-func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if re.MatchString(k) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterPrefix returns a new properties object with a subset of all keys
-// with the given prefix.
-func (p *Properties) FilterPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterStripPrefix returns a new properties object with a subset of all keys
-// with the given prefix and the prefix removed from the keys.
-func (p *Properties) FilterStripPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	n := len(prefix)
-	for _, k := range p.k {
-		if len(k) > len(prefix) && strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference
-			// TODO(fs): this function should probably return an error but the signature is fixed
-			pp.Set(k[n:], p.m[k])
-		}
-	}
-	return pp
-}
-
-// Len returns the number of keys.
-func (p *Properties) Len() int {
-	return len(p.m)
-}
-
-// Keys returns all keys in the same order as in the input.
-func (p *Properties) Keys() []string {
-	keys := make([]string, len(p.k))
-	copy(keys, p.k)
-	return keys
-}
-
-// Set sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. If the value contains a
-// circular reference or a malformed expression then
-// an error is returned.
-// An empty key is silently ignored.
-func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
-	if key == "" {
-		return "", false, nil
-	}
-
-	// if expansion is disabled we allow circular references
-	if p.DisableExpansion {
-		prev, ok = p.Get(key)
-		p.m[key] = value
-		if !ok {
-			p.k = append(p.k, key)
-		}
-		return prev, ok, nil
-	}
-
-	// to check for a circular reference we temporarily need
-	// to set the new value. If there is an error then revert
-	// to the previous state. Only if all tests are successful
-	// then we add the key to the p.k list.
-	prev, ok = p.Get(key)
-	p.m[key] = value
-
-	// now check for a circular reference
-	_, err = p.expand(key, value)
-	if err != nil {
-
-		// revert to the previous state
-		if ok {
-			p.m[key] = prev
-		} else {
-			delete(p.m, key)
-		}
-
-		return "", false, err
-	}
-
-	if !ok {
-		p.k = append(p.k, key)
-	}
-
-	return prev, ok, nil
-}
-
-// SetValue sets property key to the default string value
-// as defined by fmt.Sprintf("%v").
-func (p *Properties) SetValue(key string, value interface{}) error {
-	_, _, err := p.Set(key, fmt.Sprintf("%v", value))
-	return err
-}
-
-// MustSet sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. An empty key is silently ignored.
-func (p *Properties) MustSet(key, value string) (prev string, ok bool) {
-	prev, ok, err := p.Set(key, value)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return prev, ok
-}
-
-// String returns a string of all expanded 'key = value' pairs.
-func (p *Properties) String() string {
-	var s string
-	for _, key := range p.k {
-		value, _ := p.Get(key)
-		s = fmt.Sprintf("%s%s = %s\n", s, key, value)
-	}
-	return s
-}
-
-// Sort sorts the properties keys in alphabetical order.
-// This is helpfully before writing the properties.
-func (p *Properties) Sort() {
-	sort.Strings(p.k)
-}
-
-// Write writes all unexpanded 'key = value' pairs to the given writer.
-// Write returns the number of bytes written and any write error encountered.
-func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) {
-	return p.WriteComment(w, "", enc)
-}
-
-// WriteComment writes all unexpanced 'key = value' pairs to the given writer.
-// If prefix is not empty then comments are written with a blank line and the
-// given prefix. The prefix should be either "# " or "! " to be compatible with
-// the properties file format. Otherwise, the properties parser will not be
-// able to read the file back in. It returns the number of bytes written and
-// any write error encountered.
-func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) {
-	var x int
-
-	for _, key := range p.k {
-		value := p.m[key]
-
-		if prefix != "" {
-			if comments, ok := p.c[key]; ok {
-				// don't print comments if they are all empty
-				allEmpty := true
-				for _, c := range comments {
-					if c != "" {
-						allEmpty = false
-						break
-					}
-				}
-
-				if !allEmpty {
-					// add a blank line between entries but not at the top
-					if len(comments) > 0 && n > 0 {
-						x, err = fmt.Fprintln(w)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-
-					for _, c := range comments {
-						x, err = fmt.Fprintf(w, "%s%s\n", prefix, c)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-				}
-			}
-		}
-		sep := " = "
-		if p.WriteSeparator != "" {
-			sep = p.WriteSeparator
-		}
-		x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc))
-		if err != nil {
-			return
-		}
-		n += x
-	}
-	return
-}
-
-// Map returns a copy of the properties as a map.
-func (p *Properties) Map() map[string]string {
-	m := make(map[string]string)
-	for k, v := range p.m {
-		m[k] = v
-	}
-	return m
-}
-
-// FilterFunc returns a copy of the properties which includes the values which passed all filters.
-func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties {
-	pp := NewProperties()
-outer:
-	for k, v := range p.m {
-		for _, f := range filters {
-			if !f(k, v) {
-				continue outer
-			}
-			pp.Set(k, v)
-		}
-	}
-	return pp
-}
-
-// ----------------------------------------------------------------------------
-
-// Delete removes the key and its comments.
-func (p *Properties) Delete(key string) {
-	delete(p.m, key)
-	delete(p.c, key)
-	newKeys := []string{}
-	for _, k := range p.k {
-		if k != key {
-			newKeys = append(newKeys, k)
-		}
-	}
-	p.k = newKeys
-}
-
-// Merge merges properties, comments and keys from other *Properties into p
-func (p *Properties) Merge(other *Properties) {
-	for _, k := range other.k {
-		if _, ok := p.m[k]; !ok {
-			p.k = append(p.k, k)
-		}
-	}
-	for k, v := range other.m {
-		p.m[k] = v
-	}
-	for k, v := range other.c {
-		p.c[k] = v
-	}
-}
-
-// ----------------------------------------------------------------------------
-
-// check expands all values and returns an error if a circular reference or
-// a malformed expression was found.
-func (p *Properties) check() error {
-	for key, value := range p.m {
-		if _, err := p.expand(key, value); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (p *Properties) expand(key, input string) (string, error) {
-	// no pre/postfix -> nothing to expand
-	if p.Prefix == "" && p.Postfix == "" {
-		return input, nil
-	}
-
-	return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
-}
-
-// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
-// The function keeps track of the keys that were already expanded and stops if it
-// detects a circular reference or a malformed expression of the form '(prefix)key'.
-func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
-	if len(keys) > maxExpansionDepth {
-		return "", fmt.Errorf("expansion too deep")
-	}
-
-	for {
-		start := strings.Index(s, prefix)
-		if start == -1 {
-			return s, nil
-		}
-
-		keyStart := start + len(prefix)
-		keyLen := strings.Index(s[keyStart:], postfix)
-		if keyLen == -1 {
-			return "", fmt.Errorf("malformed expression")
-		}
-
-		end := keyStart + keyLen + len(postfix) - 1
-		key := s[keyStart : keyStart+keyLen]
-
-		// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
-
-		for _, k := range keys {
-			if key == k {
-				var b bytes.Buffer
-				b.WriteString("circular reference in:\n")
-				for _, k1 := range keys {
-					fmt.Fprintf(&b, "%s=%s\n", k1, values[k1])
-				}
-				return "", fmt.Errorf(b.String())
-			}
-		}
-
-		val, ok := values[key]
-		if !ok {
-			val = os.Getenv(key)
-		}
-		new_val, err := expand(val, append(keys, key), prefix, postfix, values)
-		if err != nil {
-			return "", err
-		}
-		s = s[:start] + new_val + s[end+1:]
-	}
-}
-
-// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
-func encode(s string, special string, enc Encoding) string {
-	switch enc {
-	case UTF8:
-		return encodeUtf8(s, special)
-	case ISO_8859_1:
-		return encodeIso(s, special)
-	default:
-		panic(fmt.Sprintf("unsupported encoding %v", enc))
-	}
-}
-
-func encodeUtf8(s string, special string) string {
-	v := ""
-	for pos := 0; pos < len(s); {
-		r, w := utf8.DecodeRuneInString(s[pos:])
-		pos += w
-		v += escape(r, special)
-	}
-	return v
-}
-
-func encodeIso(s string, special string) string {
-	var r rune
-	var w int
-	var v string
-	for pos := 0; pos < len(s); {
-		switch r, w = utf8.DecodeRuneInString(s[pos:]); {
-		case r < 1<<8: // single byte rune -> escape special chars only
-			v += escape(r, special)
-		case r < 1<<16: // two byte rune -> unicode literal
-			v += fmt.Sprintf("\\u%04x", r)
-		default: // more than two bytes per rune -> can't encode
-			v += "?"
-		}
-		pos += w
-	}
-	return v
-}
-
-func escape(r rune, special string) string {
-	switch r {
-	case '\f':
-		return "\\f"
-	case '\n':
-		return "\\n"
-	case '\r':
-		return "\\r"
-	case '\t':
-		return "\\t"
-	case '\\':
-		return "\\\\"
-	default:
-		if strings.ContainsRune(special, r) {
-			return "\\" + string(r)
-		}
-		return string(r)
-	}
-}
-
-func invalidKeyError(key string) error {
-	return fmt.Errorf("unknown property: %s", key)
-}
diff --git a/history-api/vendor/github.com/magiconair/properties/rangecheck.go b/history-api/vendor/github.com/magiconair/properties/rangecheck.go
deleted file mode 100644
index dbd60b36..00000000
--- a/history-api/vendor/github.com/magiconair/properties/rangecheck.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"math"
-)
-
-// make this a var to overwrite it in a test
-var is32Bit = ^uint(0) == math.MaxUint32
-
-// intRangeCheck checks if the value fits into the int type and
-// panics if it does not.
-func intRangeCheck(key string, v int64) int {
-	if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return int(v)
-}
-
-// uintRangeCheck checks if the value fits into the uint type and
-// panics if it does not.
-func uintRangeCheck(key string, v uint64) uint {
-	if is32Bit && v > math.MaxUint32 {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return uint(v)
-}
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/history-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
deleted file mode 100644
index c7582349..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ /dev/null
@@ -1,96 +0,0 @@
-## 1.5.0
-
-* New option `IgnoreUntaggedFields` to ignore decoding to any fields
-  without `mapstructure` (or the configured tag name) set [GH-277]
-* New option `ErrorUnset` which makes it an error if any fields
-  in a target struct are not set by the decoding process. [GH-225]
-* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
-* Decoding to slice from array no longer crashes [GH-265]
-* Decode nested struct pointers to map [GH-271]
-* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
-* Fix issue where fields with `,omitempty` would sometimes decode
-  into a map with an empty string key [GH-281]
-
-## 1.4.3
-
-* Fix cases where `json.Number` didn't decode properly [GH-261]
-
-## 1.4.2
-
-* Custom name matchers to support any sort of casing, formatting, etc. for
-  field names. [GH-250]
-* Fix possible panic in ComposeDecodeHookFunc [GH-251]
-
-## 1.4.1
-
-* Fix regression where `*time.Time` value would be set to empty and not be sent
-  to decode hooks properly [GH-232]
-
-## 1.4.0
-
-* A new decode hook type `DecodeHookFuncValue` has been added that has
-  access to the full values. [GH-183]
-* Squash is now supported with embedded fields that are struct pointers [GH-205]
-* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206]
-
-## 1.3.3
-
-* Decoding maps from maps creates a settable value for decode hooks [GH-203]
-
-## 1.3.2
-
-* Decode into interface type with a struct value is supported [GH-187]
-
-## 1.3.1
-
-* Squash should only squash embedded structs. [GH-194]
-
-## 1.3.0
-
-* Added `",omitempty"` support. This will ignore zero values in the source
-  structure when encoding. [GH-145]
-
-## 1.2.3
-
-* Fix duplicate entries in Keys list with pointer values. [GH-185]
-
-## 1.2.2
-
-* Do not add unsettable (unexported) values to the unused metadata key
-  or "remain" value. [GH-150]
-
-## 1.2.1
-
-* Go modules checksum mismatch fix
-
-## 1.2.0
-
-* Added support to capture unused values in a field using the `",remain"` value
-  in the mapstructure tag. There is an example to showcase usage.
-* Added `DecoderConfig` option to always squash embedded structs
-* `json.Number` can decode into `uint` types
-* Empty slices are preserved and not replaced with nil slices
-* Fix panic that can occur in when decoding a map into a nil slice of structs
-* Improved package documentation for godoc
-
-## 1.1.2
-
-* Fix error when decode hook decodes interface implementation into interface
-  type. [GH-140]
-
-## 1.1.1
-
-* Fix panic that can happen in `decodePtr`
-
-## 1.1.0
-
-* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133]
-* Support struct to struct decoding [GH-137]
-* If source map value is nil, then destination map value is nil (instead of empty)
-* If source slice value is nil, then destination slice value is nil (instead of empty)
-* If source pointer is nil, then destination pointer is set to nil (instead of
-  allocated zero value of type)
-
-## 1.0.0
-
-* Initial tagged stable release.
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/LICENSE b/history-api/vendor/github.com/mitchellh/mapstructure/LICENSE
deleted file mode 100644
index f9c841a5..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Mitchell Hashimoto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/README.md b/history-api/vendor/github.com/mitchellh/mapstructure/README.md
deleted file mode 100644
index 0018dc7d..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure)
-
-mapstructure is a Go library for decoding generic map values to structures
-and vice versa, while providing helpful error handling.
-
-This library is most useful when decoding values from some data stream (JSON,
-Gob, etc.) where you don't _quite_ know the structure of the underlying data
-until you read a part of it. You can therefore read a `map[string]interface{}`
-and use this library to decode it into the proper underlying native Go
-structure.
-
-## Installation
-
-Standard `go get`:
-
-```
-$ go get github.com/mitchellh/mapstructure
-```
-
-## Usage & Example
-
-For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).
-
-The `Decode` function has examples associated with it there.
-
-## But Why?!
-
-Go offers fantastic standard libraries for decoding formats such as JSON.
-The standard method is to have a struct pre-created, and populate that struct
-from the bytes of the encoded format. This is great, but the problem is if
-you have configuration or an encoding that changes slightly depending on
-specific fields. For example, consider this JSON:
-
-```json
-{
-  "type": "person",
-  "name": "Mitchell"
-}
-```
-
-Perhaps we can't populate a specific structure without first reading
-the "type" field from the JSON. We could always do two passes over the
-decoding of the JSON (reading the "type" first, and the rest later).
-However, it is much simpler to just decode this into a `map[string]interface{}`
-structure, read the "type" key, then use something like this library
-to decode it into the proper structure.
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/history-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
deleted file mode 100644
index 3a754ca7..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package mapstructure
-
-import (
-	"encoding"
-	"errors"
-	"fmt"
-	"net"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
-// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
-func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
-	// Create variables here so we can reference them with the reflect pkg
-	var f1 DecodeHookFuncType
-	var f2 DecodeHookFuncKind
-	var f3 DecodeHookFuncValue
-
-	// Fill in the variables into this interface and the rest is done
-	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
-
-	v := reflect.ValueOf(h)
-	vt := v.Type()
-	for _, raw := range potential {
-		pt := reflect.ValueOf(raw).Type()
-		if vt.ConvertibleTo(pt) {
-			return v.Convert(pt).Interface()
-		}
-	}
-
-	return nil
-}
-
-// DecodeHookExec executes the given decode hook. This should be used
-// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
-// that took reflect.Kind instead of reflect.Type.
-func DecodeHookExec(
-	raw DecodeHookFunc,
-	from reflect.Value, to reflect.Value) (interface{}, error) {
-
-	switch f := typedDecodeHook(raw).(type) {
-	case DecodeHookFuncType:
-		return f(from.Type(), to.Type(), from.Interface())
-	case DecodeHookFuncKind:
-		return f(from.Kind(), to.Kind(), from.Interface())
-	case DecodeHookFuncValue:
-		return f(from, to)
-	default:
-		return nil, errors.New("invalid decode hook signature")
-	}
-}
-
-// ComposeDecodeHookFunc creates a single DecodeHookFunc that
-// automatically composes multiple DecodeHookFuncs.
-//
-// The composed funcs are called in order, with the result of the
-// previous transformation.
-func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		var err error
-		data := f.Interface()
-
-		newFrom := f
-		for _, f1 := range fs {
-			data, err = DecodeHookExec(f1, newFrom, t)
-			if err != nil {
-				return nil, err
-			}
-			newFrom = reflect.ValueOf(data)
-		}
-
-		return data, nil
-	}
-}
-
-// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
-// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
-func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	return func(a, b reflect.Value) (interface{}, error) {
-		var allErrs string
-		var out interface{}
-		var err error
-
-		for _, f := range ff {
-			out, err = DecodeHookExec(f, a, b)
-			if err != nil {
-				allErrs += err.Error() + "\n"
-				continue
-			}
-
-			return out, nil
-		}
-
-		return nil, errors.New(allErrs)
-	}
-}
-
-// StringToSliceHookFunc returns a DecodeHookFunc that converts
-// string to []string by splitting on the given sep.
-func StringToSliceHookFunc(sep string) DecodeHookFunc {
-	return func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		if f != reflect.String || t != reflect.Slice {
-			return data, nil
-		}
-
-		raw := data.(string)
-		if raw == "" {
-			return []string{}, nil
-		}
-
-		return strings.Split(raw, sep), nil
-	}
-}
-
-// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
-// strings to time.Duration.
-func StringToTimeDurationHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Duration(5)) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.ParseDuration(data.(string))
-	}
-}
-
-// StringToIPHookFunc returns a DecodeHookFunc that converts
-// strings to net.IP
-func StringToIPHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IP{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		ip := net.ParseIP(data.(string))
-		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
-		}
-
-		return ip, nil
-	}
-}
-
-// StringToIPNetHookFunc returns a DecodeHookFunc that converts
-// strings to net.IPNet
-func StringToIPNetHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IPNet{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
-	}
-}
-
-// StringToTimeHookFunc returns a DecodeHookFunc that converts
-// strings to time.Time.
-func StringToTimeHookFunc(layout string) DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Time{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.Parse(layout, data.(string))
-	}
-}
-
-// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
-// the decoder.
-//
-// Note that this is significantly different from the WeaklyTypedInput option
-// of the DecoderConfig.
-func WeaklyTypedHook(
-	f reflect.Kind,
-	t reflect.Kind,
-	data interface{}) (interface{}, error) {
-	dataVal := reflect.ValueOf(data)
-	switch t {
-	case reflect.String:
-		switch f {
-		case reflect.Bool:
-			if dataVal.Bool() {
-				return "1", nil
-			}
-			return "0", nil
-		case reflect.Float32:
-			return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
-		case reflect.Int:
-			return strconv.FormatInt(dataVal.Int(), 10), nil
-		case reflect.Slice:
-			dataType := dataVal.Type()
-			elemKind := dataType.Elem().Kind()
-			if elemKind == reflect.Uint8 {
-				return string(dataVal.Interface().([]uint8)), nil
-			}
-		case reflect.Uint:
-			return strconv.FormatUint(dataVal.Uint(), 10), nil
-		}
-	}
-
-	return data, nil
-}
-
-func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		if f.Kind() != reflect.Struct {
-			return f.Interface(), nil
-		}
-
-		var i interface{} = struct{}{}
-		if t.Type() != reflect.TypeOf(&i).Elem() {
-			return f.Interface(), nil
-		}
-
-		m := make(map[string]interface{})
-		t.Set(reflect.ValueOf(m))
-
-		return f.Interface(), nil
-	}
-}
-
-// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
-// strings to the UnmarshalText function, when the target type
-// implements the encoding.TextUnmarshaler interface
-func TextUnmarshallerHookFunc() DecodeHookFuncType {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		result := reflect.New(t).Interface()
-		unmarshaller, ok := result.(encoding.TextUnmarshaler)
-		if !ok {
-			return data, nil
-		}
-		if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
-			return nil, err
-		}
-		return result, nil
-	}
-}
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/error.go b/history-api/vendor/github.com/mitchellh/mapstructure/error.go
deleted file mode 100644
index 47a99e5a..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/error.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package mapstructure
-
-import (
-	"errors"
-	"fmt"
-	"sort"
-	"strings"
-)
-
-// Error implements the error interface and can represents multiple
-// errors that occur in the course of a single decode.
-type Error struct {
-	Errors []string
-}
-
-func (e *Error) Error() string {
-	points := make([]string, len(e.Errors))
-	for i, err := range e.Errors {
-		points[i] = fmt.Sprintf("* %s", err)
-	}
-
-	sort.Strings(points)
-	return fmt.Sprintf(
-		"%d error(s) decoding:\n\n%s",
-		len(e.Errors), strings.Join(points, "\n"))
-}
-
-// WrappedErrors implements the errwrap.Wrapper interface to make this
-// return value more useful with the errwrap and go-multierror libraries.
-func (e *Error) WrappedErrors() []error {
-	if e == nil {
-		return nil
-	}
-
-	result := make([]error, len(e.Errors))
-	for i, e := range e.Errors {
-		result[i] = errors.New(e)
-	}
-
-	return result
-}
-
-func appendErrors(errors []string, err error) []string {
-	switch e := err.(type) {
-	case *Error:
-		return append(errors, e.Errors...)
-	default:
-		return append(errors, e.Error())
-	}
-}
diff --git a/history-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/history-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go
deleted file mode 100644
index 1efb22ac..00000000
--- a/history-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ /dev/null
@@ -1,1540 +0,0 @@
-// Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
-// into a native Go structure.
-//
-// The Go structure can be arbitrarily complex, containing slices,
-// other structs, etc. and the decoder will properly decode nested
-// maps and so on into the proper structures in the native Go struct.
-// See the examples to see what the decoder is capable of.
-//
-// The simplest function to start with is Decode.
-//
-// Field Tags
-//
-// When decoding to a struct, mapstructure will use the field name by
-// default to perform the mapping. For example, if a struct has a field
-// "Username" then mapstructure will look for a key in the source value
-// of "username" (case insensitive).
-//
-//     type User struct {
-//         Username string
-//     }
-//
-// You can change the behavior of mapstructure by using struct tags.
-// The default struct tag that mapstructure looks for is "mapstructure"
-// but you can customize it using DecoderConfig.
-//
-// Renaming Fields
-//
-// To rename the key that mapstructure looks for, use the "mapstructure"
-// tag and set a value directly. For example, to change the "username" example
-// above to "user":
-//
-//     type User struct {
-//         Username string `mapstructure:"user"`
-//     }
-//
-// Embedded Structs and Squashing
-//
-// Embedded structs are treated as if they're another field with that name.
-// By default, the two structs below are equivalent when decoding with
-// mapstructure:
-//
-//     type Person struct {
-//         Name string
-//     }
-//
-//     type Friend struct {
-//         Person
-//     }
-//
-//     type Friend struct {
-//         Person Person
-//     }
-//
-// This would require an input that looks like below:
-//
-//     map[string]interface{}{
-//         "person": map[string]interface{}{"name": "alice"},
-//     }
-//
-// If your "person" value is NOT nested, then you can append ",squash" to
-// your tag value and mapstructure will treat it as if the embedded struct
-// were part of the struct directly. Example:
-//
-//     type Friend struct {
-//         Person `mapstructure:",squash"`
-//     }
-//
-// Now the following input would be accepted:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// When decoding from a struct to a map, the squash tag squashes the struct
-// fields into a single map. Using the example structs from above:
-//
-//     Friend{Person: Person{Name: "alice"}}
-//
-// Will be decoded into a map:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// DecoderConfig has a field that changes the behavior of mapstructure
-// to always squash embedded structs.
-//
-// Remainder Values
-//
-// If there are any unmapped keys in the source value, mapstructure by
-// default will silently ignore them. You can error by setting ErrorUnused
-// in DecoderConfig. If you're using Metadata you can also maintain a slice
-// of the unused keys.
-//
-// You can also use the ",remain" suffix on your tag to collect all unused
-// values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
-// See example below:
-//
-//     type Friend struct {
-//         Name  string
-//         Other map[string]interface{} `mapstructure:",remain"`
-//     }
-//
-// Given the input below, Other would be populated with the other
-// values that weren't used (everything but "name"):
-//
-//     map[string]interface{}{
-//         "name":    "bob",
-//         "address": "123 Maple St.",
-//     }
-//
-// Omit Empty Values
-//
-// When decoding from a struct to any other value, you may use the
-// ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
-//
-// For example, the zero type of a numeric type is zero ("0"). If the struct
-// field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
-//
-//     type Source struct {
-//         Age int `mapstructure:",omitempty"`
-//     }
-//
-// Unexported fields
-//
-// Since unexported (private) struct fields cannot be set outside the package
-// where they are defined, the decoder will simply skip them.
-//
-// For this output type definition:
-//
-//     type Exported struct {
-//         private string // this unexported field will be skipped
-//         Public string
-//     }
-//
-// Using this map as input:
-//
-//     map[string]interface{}{
-//         "private": "I will be ignored",
-//         "Public":  "I made it through!",
-//     }
-//
-// The following struct will be decoded:
-//
-//     type Exported struct {
-//         private: "" // field is left with an empty string (zero value)
-//         Public: "I made it through!"
-//     }
-//
-// Other Configuration
-//
-// mapstructure is highly configurable. See the DecoderConfig struct
-// for other features and options that are supported.
-package mapstructure
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-)
-
-// DecodeHookFunc is the callback function that can be used for
-// data transformations. See "DecodeHook" in the DecoderConfig
-// struct.
-//
-// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or
-// DecodeHookFuncValue.
-// Values are a superset of Types (Values can return types), and Types are a
-// superset of Kinds (Types can return Kinds) and are generally a richer thing
-// to use, but Kinds are simpler if you only need those.
-//
-// The reason DecodeHookFunc is multi-typed is for backwards compatibility:
-// we started with Kinds and then realized Types were the better solution,
-// but have a promise to not break backwards compat so we now support
-// both.
-type DecodeHookFunc interface{}
-
-// DecodeHookFuncType is a DecodeHookFunc which has complete information about
-// the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
-
-// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
-// source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
-
-// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
-// values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
-
-// DecoderConfig is the configuration that is used to create a new decoder
-// and allows customization of various aspects of decoding.
-type DecoderConfig struct {
-	// DecodeHook, if set, will be called before any decoding and any
-	// type conversion (if WeaklyTypedInput is on). This lets you modify
-	// the values before they're set down onto the resulting struct. The
-	// DecodeHook is called for every map and value in the input. This means
-	// that if a struct has embedded fields with squash tags the decode hook
-	// is called only once with all of the input data, not once for each
-	// embedded struct.
-	//
-	// If an error is returned, the entire decode will fail with that error.
-	DecodeHook DecodeHookFunc
-
-	// If ErrorUnused is true, then it is an error for there to exist
-	// keys in the original map that were unused in the decoding process
-	// (extra keys).
-	ErrorUnused bool
-
-	// If ErrorUnset is true, then it is an error for there to exist
-	// fields in the result that were not set in the decoding process
-	// (extra fields). This only applies to decoding to a struct. This
-	// will affect all nested structs as well.
-	ErrorUnset bool
-
-	// ZeroFields, if set to true, will zero fields before writing them.
-	// For example, a map will be emptied before decoded values are put in
-	// it. If this is false, a map will be merged.
-	ZeroFields bool
-
-	// If WeaklyTypedInput is true, the decoder will make the following
-	// "weak" conversions:
-	//
-	//   - bools to string (true = "1", false = "0")
-	//   - numbers to string (base 10)
-	//   - bools to int/uint (true = 1, false = 0)
-	//   - strings to int/uint (base implied by prefix)
-	//   - int to bool (true if value != 0)
-	//   - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
-	//     FALSE, false, False. Anything else is an error)
-	//   - empty array = empty map and vice versa
-	//   - negative numbers to overflowed uint values (base 10)
-	//   - slice of maps to a merged map
-	//   - single values are converted to slices if required. Each
-	//     element is weakly decoded. For example: "4" can become []int{4}
-	//     if the target type is an int slice.
-	//
-	WeaklyTypedInput bool
-
-	// Squash will squash embedded structs.  A squash tag may also be
-	// added to an individual struct field using a tag.  For example:
-	//
-	//  type Parent struct {
-	//      Child `mapstructure:",squash"`
-	//  }
-	Squash bool
-
-	// Metadata is the struct that will contain extra metadata about
-	// the decoding. If this is nil, then no metadata will be tracked.
-	Metadata *Metadata
-
-	// Result is a pointer to the struct that will contain the decoded
-	// value.
-	Result interface{}
-
-	// The tag name that mapstructure reads for field names. This
-	// defaults to "mapstructure"
-	TagName string
-
-	// IgnoreUntaggedFields ignores all struct fields without explicit
-	// TagName, comparable to `mapstructure:"-"` as default behaviour.
-	IgnoreUntaggedFields bool
-
-	// MatchName is the function used to match the map key to the struct
-	// field name or tag. Defaults to `strings.EqualFold`. This can be used
-	// to implement case-sensitive tag values, support snake casing, etc.
-	MatchName func(mapKey, fieldName string) bool
-}
-
-// A Decoder takes a raw interface value and turns it into structured
-// data, keeping track of rich error information along the way in case
-// anything goes wrong. Unlike the basic top-level Decode method, you can
-// more finely control how the Decoder behaves using the DecoderConfig
-// structure. The top-level Decode method is just a convenience that sets
-// up the most basic Decoder.
-type Decoder struct {
-	config *DecoderConfig
-}
-
-// Metadata contains information about decoding a structure that
-// is tedious or difficult to get otherwise.
-type Metadata struct {
-	// Keys are the keys of the structure which were successfully decoded
-	Keys []string
-
-	// Unused is a slice of keys that were found in the raw value but
-	// weren't decoded since there was no matching field in the result interface
-	Unused []string
-
-	// Unset is a slice of field names that were found in the result interface
-	// but weren't set in the decoding process since there was no matching value
-	// in the input
-	Unset []string
-}
-
-// Decode takes an input structure and uses reflection to translate it to
-// the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata: nil,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecode is the same as Decode but is shorthand to enable
-// WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata:         nil,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// DecodeMetadata is the same as Decode, but is shorthand to
-// enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata: metadata,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecodeMetadata is the same as Decode, but is shorthand to
-// enable both WeaklyTypedInput and metadata collection. See
-// DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata:         metadata,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// NewDecoder returns a new decoder for the given configuration. Once
-// a decoder has been returned, the same configuration must not be used
-// again.
-func NewDecoder(config *DecoderConfig) (*Decoder, error) {
-	val := reflect.ValueOf(config.Result)
-	if val.Kind() != reflect.Ptr {
-		return nil, errors.New("result must be a pointer")
-	}
-
-	val = val.Elem()
-	if !val.CanAddr() {
-		return nil, errors.New("result must be addressable (a pointer)")
-	}
-
-	if config.Metadata != nil {
-		if config.Metadata.Keys == nil {
-			config.Metadata.Keys = make([]string, 0)
-		}
-
-		if config.Metadata.Unused == nil {
-			config.Metadata.Unused = make([]string, 0)
-		}
-
-		if config.Metadata.Unset == nil {
-			config.Metadata.Unset = make([]string, 0)
-		}
-	}
-
-	if config.TagName == "" {
-		config.TagName = "mapstructure"
-	}
-
-	if config.MatchName == nil {
-		config.MatchName = strings.EqualFold
-	}
-
-	result := &Decoder{
-		config: config,
-	}
-
-	return result, nil
-}
-
-// Decode decodes the given raw interface to the target pointer specified
-// by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
-	return d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
-}
-
-// Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
-	var inputVal reflect.Value
-	if input != nil {
-		inputVal = reflect.ValueOf(input)
-
-		// We need to check here if input is a typed nil. Typed nils won't
-		// match the "input == nil" below so we check that here.
-		if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() {
-			input = nil
-		}
-	}
-
-	if input == nil {
-		// If the data is nil, then we don't set anything, unless ZeroFields is set
-		// to true.
-		if d.config.ZeroFields {
-			outVal.Set(reflect.Zero(outVal.Type()))
-
-			if d.config.Metadata != nil && name != "" {
-				d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-			}
-		}
-		return nil
-	}
-
-	if !inputVal.IsValid() {
-		// If the input value is invalid, then we just set the value
-		// to be the zero value.
-		outVal.Set(reflect.Zero(outVal.Type()))
-		if d.config.Metadata != nil && name != "" {
-			d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-		}
-		return nil
-	}
-
-	if d.config.DecodeHook != nil {
-		// We have a DecodeHook, so let's pre-process the input.
-		var err error
-		input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal)
-		if err != nil {
-			return fmt.Errorf("error decoding '%s': %s", name, err)
-		}
-	}
-
-	var err error
-	outputKind := getKind(outVal)
-	addMetaKey := true
-	switch outputKind {
-	case reflect.Bool:
-		err = d.decodeBool(name, input, outVal)
-	case reflect.Interface:
-		err = d.decodeBasic(name, input, outVal)
-	case reflect.String:
-		err = d.decodeString(name, input, outVal)
-	case reflect.Int:
-		err = d.decodeInt(name, input, outVal)
-	case reflect.Uint:
-		err = d.decodeUint(name, input, outVal)
-	case reflect.Float32:
-		err = d.decodeFloat(name, input, outVal)
-	case reflect.Struct:
-		err = d.decodeStruct(name, input, outVal)
-	case reflect.Map:
-		err = d.decodeMap(name, input, outVal)
-	case reflect.Ptr:
-		addMetaKey, err = d.decodePtr(name, input, outVal)
-	case reflect.Slice:
-		err = d.decodeSlice(name, input, outVal)
-	case reflect.Array:
-		err = d.decodeArray(name, input, outVal)
-	case reflect.Func:
-		err = d.decodeFunc(name, input, outVal)
-	default:
-		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
-	}
-
-	// If we reached here, then we successfully decoded SOMETHING, so
-	// mark the key as used if we're tracking metainput.
-	if addMetaKey && d.config.Metadata != nil && name != "" {
-		d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-	}
-
-	return err
-}
-
-// This decodes a basic type (bool, int, string, etc.) and sets the
-// value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
-	if val.IsValid() && val.Elem().IsValid() {
-		elem := val.Elem()
-
-		// If we can't address this element, then its not writable. Instead,
-		// we make a copy of the value (which is a pointer and therefore
-		// writable), decode into that, and replace the whole value.
-		copied := false
-		if !elem.CanAddr() {
-			copied = true
-
-			// Make *T
-			copy := reflect.New(elem.Type())
-
-			// *T = elem
-			copy.Elem().Set(elem)
-
-			// Set elem so we decode into it
-			elem = copy
-		}
-
-		// Decode. If we have an error then return. We also return right
-		// away if we're not a copy because that means we decoded directly.
-		if err := d.decode(name, data, elem); err != nil || !copied {
-			return err
-		}
-
-		// If we're a copy, we need to set te final result
-		val.Set(elem.Elem())
-		return nil
-	}
-
-	dataVal := reflect.ValueOf(data)
-
-	// If the input data is a pointer, and the assigned type is the dereference
-	// of that exact pointer, then indirect it so that we can assign it.
-	// Example: *string to string
-	if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() {
-		dataVal = reflect.Indirect(dataVal)
-	}
-
-	if !dataVal.IsValid() {
-		dataVal = reflect.Zero(val.Type())
-	}
-
-	dataValType := dataVal.Type()
-	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
-	}
-
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	converted := true
-	switch {
-	case dataKind == reflect.String:
-		val.SetString(dataVal.String())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetString("1")
-		} else {
-			val.SetString("0")
-		}
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatInt(dataVal.Int(), 10))
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
-	case dataKind == reflect.Slice && d.config.WeaklyTypedInput,
-		dataKind == reflect.Array && d.config.WeaklyTypedInput:
-		dataType := dataVal.Type()
-		elemKind := dataType.Elem().Kind()
-		switch elemKind {
-		case reflect.Uint8:
-			var uints []uint8
-			if dataKind == reflect.Array {
-				uints = make([]uint8, dataVal.Len(), dataVal.Len())
-				for i := range uints {
-					uints[i] = dataVal.Index(i).Interface().(uint8)
-				}
-			} else {
-				uints = dataVal.Interface().([]uint8)
-			}
-			val.SetString(string(uints))
-		default:
-			converted = false
-		}
-	default:
-		converted = false
-	}
-
-	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetInt(dataVal.Int())
-	case dataKind == reflect.Uint:
-		val.SetInt(int64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetInt(int64(dataVal.Float()))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetInt(1)
-		} else {
-			val.SetInt(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseInt(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetInt(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Int64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetInt(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		i := dataVal.Int()
-		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
-		}
-		val.SetUint(uint64(i))
-	case dataKind == reflect.Uint:
-		val.SetUint(dataVal.Uint())
-	case dataKind == reflect.Float32:
-		f := dataVal.Float()
-		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
-		}
-		val.SetUint(uint64(f))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetUint(1)
-		} else {
-			val.SetUint(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseUint(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetUint(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := strconv.ParseUint(string(jn), 0, 64)
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetUint(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	switch {
-	case dataKind == reflect.Bool:
-		val.SetBool(dataVal.Bool())
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Int() != 0)
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Uint() != 0)
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Float() != 0)
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		b, err := strconv.ParseBool(dataVal.String())
-		if err == nil {
-			val.SetBool(b)
-		} else if dataVal.String() == "" {
-			val.SetBool(false)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
-		}
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetFloat(float64(dataVal.Int()))
-	case dataKind == reflect.Uint:
-		val.SetFloat(float64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetFloat(dataVal.Float())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetFloat(1)
-		} else {
-			val.SetFloat(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		f, err := strconv.ParseFloat(str, val.Type().Bits())
-		if err == nil {
-			val.SetFloat(f)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Float64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetFloat(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// By default we overwrite keys in the current map
-	valMap := val
-
-	// If the map is nil or we're purposely zeroing fields, make a new map
-	if valMap.IsNil() || d.config.ZeroFields {
-		// Make a new map to hold our result
-		mapType := reflect.MapOf(valKeyType, valElemType)
-		valMap = reflect.MakeMap(mapType)
-	}
-
-	// Check input type and based on the input type jump to the proper func
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	switch dataVal.Kind() {
-	case reflect.Map:
-		return d.decodeMapFromMap(name, dataVal, val, valMap)
-
-	case reflect.Struct:
-		return d.decodeMapFromStruct(name, dataVal, val, valMap)
-
-	case reflect.Array, reflect.Slice:
-		if d.config.WeaklyTypedInput {
-			return d.decodeMapFromSlice(name, dataVal, val, valMap)
-		}
-
-		fallthrough
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	// Special case for BC reasons (covered by tests)
-	if dataVal.Len() == 0 {
-		val.Set(valMap)
-		return nil
-	}
-
-	for i := 0; i < dataVal.Len(); i++ {
-		err := d.decode(
-			name+"["+strconv.Itoa(i)+"]",
-			dataVal.Index(i).Interface(), val)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// Accumulate errors
-	errors := make([]string, 0)
-
-	// If the input data is empty, then we just match what the input data is.
-	if dataVal.Len() == 0 {
-		if dataVal.IsNil() {
-			if !val.IsNil() {
-				val.Set(dataVal)
-			}
-		} else {
-			// Set to empty allocated value
-			val.Set(valMap)
-		}
-
-		return nil
-	}
-
-	for _, k := range dataVal.MapKeys() {
-		fieldName := name + "[" + k.String() + "]"
-
-		// First decode the key into the proper type
-		currentKey := reflect.Indirect(reflect.New(valKeyType))
-		if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		// Next decode the data into the proper type
-		v := dataVal.MapIndex(k).Interface()
-		currentVal := reflect.Indirect(reflect.New(valElemType))
-		if err := d.decode(fieldName, v, currentVal); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		valMap.SetMapIndex(currentKey, currentVal)
-	}
-
-	// Set the built up map to the value
-	val.Set(valMap)
-
-	// If we had errors, return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	typ := dataVal.Type()
-	for i := 0; i < typ.NumField(); i++ {
-		// Get the StructField first since this is a cheap operation. If the
-		// field is unexported, then ignore it.
-		f := typ.Field(i)
-		if f.PkgPath != "" {
-			continue
-		}
-
-		// Next get the actual value of this field and verify it is assignable
-		// to the map value.
-		v := dataVal.Field(i)
-		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
-		}
-
-		tagValue := f.Tag.Get(d.config.TagName)
-		keyName := f.Name
-
-		if tagValue == "" && d.config.IgnoreUntaggedFields {
-			continue
-		}
-
-		// If Squash is set in the config, we squash the field down.
-		squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
-
-		v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
-
-		// Determine the name of the key in the map
-		if index := strings.Index(tagValue, ","); index != -1 {
-			if tagValue[:index] == "-" {
-				continue
-			}
-			// If "omitempty" is specified in the tag, it ignores empty values.
-			if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) {
-				continue
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
-			if squash {
-				// When squashing, the embedded type can be a pointer to a struct.
-				if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
-					v = v.Elem()
-				}
-
-				// The final type must be a struct
-				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
-				}
-			}
-			if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
-				keyName = keyNameTagValue
-			}
-		} else if len(tagValue) > 0 {
-			if tagValue == "-" {
-				continue
-			}
-			keyName = tagValue
-		}
-
-		switch v.Kind() {
-		// this is an embedded struct, so handle it differently
-		case reflect.Struct:
-			x := reflect.New(v.Type())
-			x.Elem().Set(v)
-
-			vType := valMap.Type()
-			vKeyType := vType.Key()
-			vElemType := vType.Elem()
-			mType := reflect.MapOf(vKeyType, vElemType)
-			vMap := reflect.MakeMap(mType)
-
-			// Creating a pointer to a map so that other methods can completely
-			// overwrite the map if need be (looking at you decodeMapFromMap). The
-			// indirection allows the underlying map to be settable (CanSet() == true)
-			// where as reflect.MakeMap returns an unsettable map.
-			addrVal := reflect.New(vMap.Type())
-			reflect.Indirect(addrVal).Set(vMap)
-
-			err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal))
-			if err != nil {
-				return err
-			}
-
-			// the underlying map may have been completely overwritten so pull
-			// it indirectly out of the enclosing value.
-			vMap = reflect.Indirect(addrVal)
-
-			if squash {
-				for _, k := range vMap.MapKeys() {
-					valMap.SetMapIndex(k, vMap.MapIndex(k))
-				}
-			} else {
-				valMap.SetMapIndex(reflect.ValueOf(keyName), vMap)
-			}
-
-		default:
-			valMap.SetMapIndex(reflect.ValueOf(keyName), v)
-		}
-	}
-
-	if val.CanAddr() {
-		val.Set(valMap)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
-	// If the input data is nil, then we want to just set the output
-	// pointer to be nil as well.
-	isNil := data == nil
-	if !isNil {
-		switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
-		case reflect.Chan,
-			reflect.Func,
-			reflect.Interface,
-			reflect.Map,
-			reflect.Ptr,
-			reflect.Slice:
-			isNil = v.IsNil()
-		}
-	}
-	if isNil {
-		if !val.IsNil() && val.CanSet() {
-			nilValue := reflect.New(val.Type()).Elem()
-			val.Set(nilValue)
-		}
-
-		return true, nil
-	}
-
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	valType := val.Type()
-	valElemType := valType.Elem()
-	if val.CanSet() {
-		realVal := val
-		if realVal.IsNil() || d.config.ZeroFields {
-			realVal = reflect.New(valElemType)
-		}
-
-		if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
-			return false, err
-		}
-
-		val.Set(realVal)
-	} else {
-		if err := d.decode(name, data, reflect.Indirect(val)); err != nil {
-			return false, err
-		}
-	}
-	return false, nil
-}
-
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	sliceType := reflect.SliceOf(valElemType)
-
-	// If we have a non array/slice type then we first attempt to convert.
-	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-		if d.config.WeaklyTypedInput {
-			switch {
-			// Slice and array we use the normal logic
-			case dataValKind == reflect.Slice, dataValKind == reflect.Array:
-				break
-
-			// Empty maps turn into empty slices
-			case dataValKind == reflect.Map:
-				if dataVal.Len() == 0 {
-					val.Set(reflect.MakeSlice(sliceType, 0, 0))
-					return nil
-				}
-				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
-
-			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
-				return d.decodeSlice(name, []byte(dataVal.String()), val)
-
-			// All other types we try to convert to the slice type
-			// and "lift" it into it. i.e. a string becomes a string slice.
-			default:
-				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
-			}
-		}
-
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
-	}
-
-	// If the input value is nil, then don't allocate since empty != nil
-	if dataValKind != reflect.Array && dataVal.IsNil() {
-		return nil
-	}
-
-	valSlice := val
-	if valSlice.IsNil() || d.config.ZeroFields {
-		// Make a new slice to hold our result, same size as the original data.
-		valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		for valSlice.Len() <= i {
-			valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
-		}
-		currentField := valSlice.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the slice we built up
-	val.Set(valSlice)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	arrayType := reflect.ArrayOf(valType.Len(), valElemType)
-
-	valArray := val
-
-	if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields {
-		// Check input type
-		if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-			if d.config.WeaklyTypedInput {
-				switch {
-				// Empty maps turn into empty arrays
-				case dataValKind == reflect.Map:
-					if dataVal.Len() == 0 {
-						val.Set(reflect.Zero(arrayType))
-						return nil
-					}
-
-				// All other types we try to convert to the array type
-				// and "lift" it into it. i.e. a string becomes a string array.
-				default:
-					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
-				}
-			}
-
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
-
-		}
-		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
-
-		}
-
-		// Make a new array to hold our result, same size as the original data.
-		valArray = reflect.New(arrayType).Elem()
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		currentField := valArray.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the array we built up
-	val.Set(valArray)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-
-	// If the type of the value to write to and the data match directly,
-	// then we just set it directly instead of recursing into the structure.
-	if dataVal.Type() == val.Type() {
-		val.Set(dataVal)
-		return nil
-	}
-
-	dataValKind := dataVal.Kind()
-	switch dataValKind {
-	case reflect.Map:
-		return d.decodeStructFromMap(name, dataVal, val)
-
-	case reflect.Struct:
-		// Not the most efficient way to do this but we can optimize later if
-		// we want to. To convert from struct to struct we go to map first
-		// as an intermediary.
-
-		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
-		mval := reflect.MakeMap(mapType)
-
-		// Creating a pointer to a map so that other methods can completely
-		// overwrite the map if need be (looking at you decodeMapFromMap). The
-		// indirection allows the underlying map to be settable (CanSet() == true)
-		// where as reflect.MakeMap returns an unsettable map.
-		addrVal := reflect.New(mval.Type())
-
-		reflect.Indirect(addrVal).Set(mval)
-		if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil {
-			return err
-		}
-
-		result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val)
-		return result
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
-	dataValType := dataVal.Type()
-	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
-	}
-
-	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
-	for _, dataValKey := range dataVal.MapKeys() {
-		dataValKeys[dataValKey] = struct{}{}
-		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
-	}
-
-	targetValKeysUnused := make(map[interface{}]struct{})
-	errors := make([]string, 0)
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = val
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-
-	// remainField is set to a valid field set with the "remain" tag if
-	// we are keeping track of remaining values.
-	var remainField *field
-
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			fieldVal := structVal.Field(i)
-			if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct {
-				// Handle embedded struct pointers as embedded structs.
-				fieldVal = fieldVal.Elem()
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous
-			remain := false
-
-			// We always parse the tags cause we're looking for other tags too
-			tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
-			for _, tag := range tagParts[1:] {
-				if tag == "squash" {
-					squash = true
-					break
-				}
-
-				if tag == "remain" {
-					remain = true
-					break
-				}
-			}
-
-			if squash {
-				if fieldVal.Kind() != reflect.Struct {
-					errors = appendErrors(errors,
-						fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
-				} else {
-					structs = append(structs, fieldVal)
-				}
-				continue
-			}
-
-			// Build our field
-			if remain {
-				remainField = &field{fieldType, fieldVal}
-			} else {
-				// Normal struct field, store it away
-				fields = append(fields, field{fieldType, fieldVal})
-			}
-		}
-	}
-
-	// for fieldType, field := range fields {
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(d.config.TagName)
-		tagValue = strings.SplitN(tagValue, ",", 2)[0]
-		if tagValue != "" {
-			fieldName = tagValue
-		}
-
-		rawMapKey := reflect.ValueOf(fieldName)
-		rawMapVal := dataVal.MapIndex(rawMapKey)
-		if !rawMapVal.IsValid() {
-			// Do a slower search by iterating over each key and
-			// doing case-insensitive search.
-			for dataValKey := range dataValKeys {
-				mK, ok := dataValKey.Interface().(string)
-				if !ok {
-					// Not a string key
-					continue
-				}
-
-				if d.config.MatchName(mK, fieldName) {
-					rawMapKey = dataValKey
-					rawMapVal = dataVal.MapIndex(dataValKey)
-					break
-				}
-			}
-
-			if !rawMapVal.IsValid() {
-				// There was no matching key in the map for the value in
-				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
-				continue
-			}
-		}
-
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		// Delete the key we're using from the unused map so we stop tracking
-		delete(dataValKeysUnused, rawMapKey.Interface())
-
-		// If the name is empty string, then we're at the root, and we
-		// don't dot-join the fields.
-		if name != "" {
-			fieldName = name + "." + fieldName
-		}
-
-		if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// If we have a "remain"-tagged field and we have unused keys then
-	// we put the unused keys directly into the remain field.
-	if remainField != nil && len(dataValKeysUnused) > 0 {
-		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
-		for key := range dataValKeysUnused {
-			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
-		}
-
-		// Decode it as-if we were just decoding this map onto our map.
-		if err := d.decodeMap(name, remain, remainField.val); err != nil {
-			errors = appendErrors(errors, err)
-		}
-
-		// Set the map to nil so we have none so that the next check will
-		// not error (ErrorUnused)
-		dataValKeysUnused = nil
-	}
-
-	if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
-		keys := make([]string, 0, len(dataValKeysUnused))
-		for rawKey := range dataValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
-		keys := make([]string, 0, len(targetValKeysUnused))
-		for rawKey := range targetValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	// Add the unused keys to the list of unused keys if we're tracking metadata
-	if d.config.Metadata != nil {
-		for rawKey := range dataValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
-		}
-		for rawKey := range targetValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
-		}
-	}
-
-	return nil
-}
-
-func isEmptyValue(v reflect.Value) bool {
-	switch getKind(v) {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	}
-	return false
-}
-
-func getKind(val reflect.Value) reflect.Kind {
-	kind := val.Kind()
-
-	switch {
-	case kind >= reflect.Int && kind <= reflect.Int64:
-		return reflect.Int
-	case kind >= reflect.Uint && kind <= reflect.Uint64:
-		return reflect.Uint
-	case kind >= reflect.Float32 && kind <= reflect.Float64:
-		return reflect.Float32
-	default:
-		return kind
-	}
-}
-
-func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
-	for i := 0; i < typ.NumField(); i++ {
-		f := typ.Field(i)
-		if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
-			return true
-		}
-		if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
-			return true
-		}
-	}
-	return false
-}
-
-func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
-	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
-		return v
-	}
-	deref := v.Elem()
-	derefT := deref.Type()
-	if isStructTypeConvertibleToMap(derefT, true, tagName) {
-		return deref
-	}
-	return v
-}
diff --git a/history-api/vendor/github.com/prometheus/procfs/.golangci.yml b/history-api/vendor/github.com/prometheus/procfs/.golangci.yml
index 126df9e6..3c3bf910 100644
--- a/history-api/vendor/github.com/prometheus/procfs/.golangci.yml
+++ b/history-api/vendor/github.com/prometheus/procfs/.golangci.yml
@@ -1,22 +1,45 @@
----
+version: "2"
 linters:
   enable:
-  - errcheck
-  - godot
-  - gosimple
-  - govet
-  - ineffassign
-  - misspell
-  - revive
-  - staticcheck
-  - testifylint
-  - unused
-
-linter-settings:
-  godot:
-    capital: true
-    exclude:
-    # Ignore "See: URL"
-    - 'See:'
-  misspell:
-    locale: US
+    - forbidigo
+    - godot
+    - misspell
+    - revive
+    - testifylint
+  settings:
+    forbidigo:
+      forbid:
+        - pattern: ^fmt\.Print.*$
+          msg: Do not commit print statements.
+    godot:
+      exclude:
+        # Ignore "See: URL".
+        - 'See:'
+      capital: true
+    misspell:
+      locale: US
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
+formatters:
+  enable:
+    - gofmt
+    - goimports
+  settings:
+    goimports:
+      local-prefixes:
+        - github.com/prometheus/procfs
+  exclusions:
+    generated: lax
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/history-api/vendor/github.com/prometheus/procfs/Makefile.common b/history-api/vendor/github.com/prometheus/procfs/Makefile.common
index 16172923..4de21512 100644
--- a/history-api/vendor/github.com/prometheus/procfs/Makefile.common
+++ b/history-api/vendor/github.com/prometheus/procfs/Makefile.common
@@ -61,7 +61,8 @@ PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_
 SKIP_GOLANGCI_LINT :=
 GOLANGCI_LINT :=
 GOLANGCI_LINT_OPTS ?=
-GOLANGCI_LINT_VERSION ?= v1.59.0
+GOLANGCI_LINT_VERSION ?= v2.1.5
+GOLANGCI_FMT_OPTS ?=
 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
 # windows isn't included here because of the path separator being different.
 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
@@ -156,9 +157,13 @@ $(GOTEST_DIR):
 	@mkdir -p $@
 
 .PHONY: common-format
-common-format:
+common-format: $(GOLANGCI_LINT)
 	@echo ">> formatting code"
 	$(GO) fmt $(pkgs)
+ifdef GOLANGCI_LINT
+	@echo ">> formatting code with golangci-lint"
+	$(GOLANGCI_LINT) fmt $(GOLANGCI_FMT_OPTS)
+endif
 
 .PHONY: common-vet
 common-vet:
@@ -248,8 +253,8 @@ $(PROMU):
 	cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu
 	rm -r $(PROMU_TMP)
 
-.PHONY: proto
-proto:
+.PHONY: common-proto
+common-proto:
 	@echo ">> generating code from proto files"
 	@./scripts/genproto.sh
 
@@ -275,3 +280,9 @@ $(1)_precheck:
 		exit 1; \
 	fi
 endef
+
+govulncheck: install-govulncheck
+	govulncheck ./...
+
+install-govulncheck:
+	command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest
diff --git a/history-api/vendor/github.com/prometheus/procfs/README.md b/history-api/vendor/github.com/prometheus/procfs/README.md
index 1224816c..0718239c 100644
--- a/history-api/vendor/github.com/prometheus/procfs/README.md
+++ b/history-api/vendor/github.com/prometheus/procfs/README.md
@@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`.
 The procfs library includes a set of test fixtures which include many example files from
 the `/proc` and `/sys` filesystems.  These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
 which is extracted automatically during testing.  To add/update the test fixtures, first
-ensure the `fixtures` directory is up to date by removing the existing directory and then
-extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
+ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then
+extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`.
 
 ```bash
 rm -rf testdata/fixtures
 make test
 ```
 
-Next, make the required changes to the extracted files in the `fixtures` directory.  When
+Next, make the required changes to the extracted files in the `testdata/fixtures` directory.  When
 the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file
 based on the updated `fixtures` directory.  And finally, verify the changes using
 `git diff testdata/fixtures.ttar`.
diff --git a/history-api/vendor/github.com/prometheus/procfs/arp.go b/history-api/vendor/github.com/prometheus/procfs/arp.go
index cdcc8a7c..2e533441 100644
--- a/history-api/vendor/github.com/prometheus/procfs/arp.go
+++ b/history-api/vendor/github.com/prometheus/procfs/arp.go
@@ -23,9 +23,9 @@ import (
 
 // Learned from include/uapi/linux/if_arp.h.
 const (
-	// completed entry (ha valid).
+	// Completed entry (ha valid).
 	ATFComplete = 0x02
-	// permanent entry.
+	// Permanent entry.
 	ATFPermanent = 0x04
 	// Publish entry.
 	ATFPublish = 0x08
diff --git a/history-api/vendor/github.com/prometheus/procfs/fs.go b/history-api/vendor/github.com/prometheus/procfs/fs.go
index 4980c875..9bdaccc7 100644
--- a/history-api/vendor/github.com/prometheus/procfs/fs.go
+++ b/history-api/vendor/github.com/prometheus/procfs/fs.go
@@ -24,8 +24,14 @@ type FS struct {
 	isReal bool
 }
 
-// DefaultMountPoint is the common mount point of the proc filesystem.
-const DefaultMountPoint = fs.DefaultProcMountPoint
+const (
+	// DefaultMountPoint is the common mount point of the proc filesystem.
+	DefaultMountPoint = fs.DefaultProcMountPoint
+
+	// SectorSize represents the size of a sector in bytes.
+	// It is specific to Linux block I/O operations.
+	SectorSize = 512
+)
 
 // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
 // It will error if the mount point directory can't be read or is a file.
diff --git a/history-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/history-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
index 134767d6..1b5bdbdf 100644
--- a/history-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
+++ b/history-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
@@ -17,7 +17,7 @@
 package procfs
 
 // isRealProc returns true on architectures that don't have a Type argument
-// in their Statfs_t struct
-func isRealProc(mountPoint string) (bool, error) {
+// in their Statfs_t struct.
+func isRealProc(_ string) (bool, error) {
 	return true, nil
 }
diff --git a/history-api/vendor/github.com/prometheus/procfs/fscache.go b/history-api/vendor/github.com/prometheus/procfs/fscache.go
index cf2e3eaa..7db86330 100644
--- a/history-api/vendor/github.com/prometheus/procfs/fscache.go
+++ b/history-api/vendor/github.com/prometheus/procfs/fscache.go
@@ -162,7 +162,7 @@ type Fscacheinfo struct {
 	ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
 	// Number of release reqs ignored due to in-progress store
 	ReleaseRequestsIgnoredDueToInProgressStore uint64
-	// Number of page stores cancelled due to release req
+	// Number of page stores canceled due to release req
 	PageStoresCancelledByReleaseRequests uint64
 	VmscanWaiting                        uint64
 	// Number of times async ops added to pending queues
@@ -171,11 +171,11 @@ type Fscacheinfo struct {
 	OpsRunning uint64
 	// Number of times async ops queued for processing
 	OpsEnqueued uint64
-	// Number of async ops cancelled
+	// Number of async ops canceled
 	OpsCancelled uint64
 	// Number of async ops rejected due to object lookup/create failure
 	OpsRejected uint64
-	// Number of async ops initialised
+	// Number of async ops initialized
 	OpsInitialised uint64
 	// Number of async ops queued for deferred release
 	OpsDeferred uint64
diff --git a/history-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/history-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
index 3c18c761..3a43e839 100644
--- a/history-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
+++ b/history-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
@@ -28,6 +28,9 @@ const (
 
 	// DefaultConfigfsMountPoint is the common mount point of the configfs.
 	DefaultConfigfsMountPoint = "/sys/kernel/config"
+
+	// DefaultSelinuxMountPoint is the common mount point of the selinuxfs.
+	DefaultSelinuxMountPoint = "/sys/fs/selinux"
 )
 
 // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
diff --git a/history-api/vendor/github.com/prometheus/procfs/internal/util/parse.go b/history-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
index 14272dc7..5a7d2df0 100644
--- a/history-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
+++ b/history-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
@@ -14,6 +14,7 @@
 package util
 
 import (
+	"errors"
 	"os"
 	"strconv"
 	"strings"
@@ -110,3 +111,16 @@ func ParseBool(b string) *bool {
 	}
 	return &truth
 }
+
+// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX.
+func ReadHexFromFile(path string) (uint64, error) {
+	data, err := os.ReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	hexString := strings.TrimSpace(string(data))
+	if !strings.HasPrefix(hexString, "0x") {
+		return 0, errors.New("invalid format: hex string does not start with '0x'")
+	}
+	return strconv.ParseUint(hexString[2:], 16, 64)
+}
diff --git a/history-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/history-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
index 1ab875ce..d5404a6d 100644
--- a/history-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
+++ b/history-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
@@ -20,6 +20,8 @@ package util
 import (
 	"bytes"
 	"os"
+	"strconv"
+	"strings"
 	"syscall"
 )
 
@@ -48,3 +50,21 @@ func SysReadFile(file string) (string, error) {
 
 	return string(bytes.TrimSpace(b[:n])), nil
 }
+
+// SysReadUintFromFile reads a file using SysReadFile and attempts to parse a uint64 from it.
+func SysReadUintFromFile(path string) (uint64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
+}
+
+// SysReadIntFromFile reads a file using SysReadFile and attempts to parse a int64 from it.
+func SysReadIntFromFile(path string) (int64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
+}
diff --git a/history-api/vendor/github.com/prometheus/procfs/mdstat.go b/history-api/vendor/github.com/prometheus/procfs/mdstat.go
index 67a9d2b4..1fd4381b 100644
--- a/history-api/vendor/github.com/prometheus/procfs/mdstat.go
+++ b/history-api/vendor/github.com/prometheus/procfs/mdstat.go
@@ -123,13 +123,16 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
 		finish := float64(0)
 		pct := float64(0)
 		recovering := strings.Contains(lines[syncLineIdx], "recovery")
+		reshaping := strings.Contains(lines[syncLineIdx], "reshape")
 		resyncing := strings.Contains(lines[syncLineIdx], "resync")
 		checking := strings.Contains(lines[syncLineIdx], "check")
 
 		// Append recovery and resyncing state info.
-		if recovering || resyncing || checking {
+		if recovering || resyncing || checking || reshaping {
 			if recovering {
 				state = "recovering"
+			} else if reshaping {
+				state = "reshaping"
 			} else if checking {
 				state = "checking"
 			} else {
diff --git a/history-api/vendor/github.com/prometheus/procfs/meminfo.go b/history-api/vendor/github.com/prometheus/procfs/meminfo.go
index 4b2c4050..937e1f96 100644
--- a/history-api/vendor/github.com/prometheus/procfs/meminfo.go
+++ b/history-api/vendor/github.com/prometheus/procfs/meminfo.go
@@ -66,6 +66,10 @@ type Meminfo struct {
 	// Memory which has been evicted from RAM, and is temporarily
 	// on the disk
 	SwapFree *uint64
+	// Memory consumed by the zswap backend (compressed size)
+	Zswap *uint64
+	// Amount of anonymous memory stored in zswap (original size)
+	Zswapped *uint64
 	// Memory which is waiting to get written back to the disk
 	Dirty *uint64
 	// Memory which is actively being written back to the disk
@@ -85,6 +89,8 @@ type Meminfo struct {
 	// amount of memory dedicated to the lowest level of page
 	// tables.
 	PageTables *uint64
+	// secondary page tables.
+	SecPageTables *uint64
 	// NFS pages sent to the server, but not yet committed to
 	// stable storage
 	NFSUnstable *uint64
@@ -129,15 +135,18 @@ type Meminfo struct {
 	Percpu            *uint64
 	HardwareCorrupted *uint64
 	AnonHugePages     *uint64
+	FileHugePages     *uint64
 	ShmemHugePages    *uint64
 	ShmemPmdMapped    *uint64
 	CmaTotal          *uint64
 	CmaFree           *uint64
+	Unaccepted        *uint64
 	HugePagesTotal    *uint64
 	HugePagesFree     *uint64
 	HugePagesRsvd     *uint64
 	HugePagesSurp     *uint64
 	Hugepagesize      *uint64
+	Hugetlb           *uint64
 	DirectMap4k       *uint64
 	DirectMap2M       *uint64
 	DirectMap1G       *uint64
@@ -161,6 +170,8 @@ type Meminfo struct {
 	MlockedBytes           *uint64
 	SwapTotalBytes         *uint64
 	SwapFreeBytes          *uint64
+	ZswapBytes             *uint64
+	ZswappedBytes          *uint64
 	DirtyBytes             *uint64
 	WritebackBytes         *uint64
 	AnonPagesBytes         *uint64
@@ -171,6 +182,7 @@ type Meminfo struct {
 	SUnreclaimBytes        *uint64
 	KernelStackBytes       *uint64
 	PageTablesBytes        *uint64
+	SecPageTablesBytes     *uint64
 	NFSUnstableBytes       *uint64
 	BounceBytes            *uint64
 	WritebackTmpBytes      *uint64
@@ -182,11 +194,14 @@ type Meminfo struct {
 	PercpuBytes            *uint64
 	HardwareCorruptedBytes *uint64
 	AnonHugePagesBytes     *uint64
+	FileHugePagesBytes     *uint64
 	ShmemHugePagesBytes    *uint64
 	ShmemPmdMappedBytes    *uint64
 	CmaTotalBytes          *uint64
 	CmaFreeBytes           *uint64
+	UnacceptedBytes        *uint64
 	HugepagesizeBytes      *uint64
+	HugetlbBytes           *uint64
 	DirectMap4kBytes       *uint64
 	DirectMap2MBytes       *uint64
 	DirectMap1GBytes       *uint64
@@ -287,6 +302,12 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "SwapFree:":
 			m.SwapFree = &val
 			m.SwapFreeBytes = &valBytes
+		case "Zswap:":
+			m.Zswap = &val
+			m.ZswapBytes = &valBytes
+		case "Zswapped:":
+			m.Zswapped = &val
+			m.ZswapBytes = &valBytes
 		case "Dirty:":
 			m.Dirty = &val
 			m.DirtyBytes = &valBytes
@@ -317,6 +338,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "PageTables:":
 			m.PageTables = &val
 			m.PageTablesBytes = &valBytes
+		case "SecPageTables:":
+			m.SecPageTables = &val
+			m.SecPageTablesBytes = &valBytes
 		case "NFS_Unstable:":
 			m.NFSUnstable = &val
 			m.NFSUnstableBytes = &valBytes
@@ -350,6 +374,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "AnonHugePages:":
 			m.AnonHugePages = &val
 			m.AnonHugePagesBytes = &valBytes
+		case "FileHugePages:":
+			m.FileHugePages = &val
+			m.FileHugePagesBytes = &valBytes
 		case "ShmemHugePages:":
 			m.ShmemHugePages = &val
 			m.ShmemHugePagesBytes = &valBytes
@@ -362,6 +389,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "CmaFree:":
 			m.CmaFree = &val
 			m.CmaFreeBytes = &valBytes
+		case "Unaccepted:":
+			m.Unaccepted = &val
+			m.UnacceptedBytes = &valBytes
 		case "HugePages_Total:":
 			m.HugePagesTotal = &val
 		case "HugePages_Free:":
@@ -373,6 +403,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "Hugepagesize:":
 			m.Hugepagesize = &val
 			m.HugepagesizeBytes = &valBytes
+		case "Hugetlb:":
+			m.Hugetlb = &val
+			m.HugetlbBytes = &valBytes
 		case "DirectMap4k:":
 			m.DirectMap4k = &val
 			m.DirectMap4kBytes = &valBytes
diff --git a/history-api/vendor/github.com/prometheus/procfs/mountstats.go b/history-api/vendor/github.com/prometheus/procfs/mountstats.go
index 75a3b6c8..50caa732 100644
--- a/history-api/vendor/github.com/prometheus/procfs/mountstats.go
+++ b/history-api/vendor/github.com/prometheus/procfs/mountstats.go
@@ -45,11 +45,11 @@ const (
 	fieldTransport11TCPLen = 13
 	fieldTransport11UDPLen = 10
 
-	// kernel version >= 4.14 MaxLen
+	// Kernel version >= 4.14 MaxLen
 	// See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
 	fieldTransport11RDMAMaxLen = 28
 
-	// kernel version <= 4.2 MinLen
+	// Kernel version <= 4.2 MinLen
 	// See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
 	fieldTransport11RDMAMinLen = 20
 )
@@ -601,11 +601,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	switch statVersion {
 	case statVersion10:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport10TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport10UDPLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if len(ss) != expectedLength {
@@ -613,13 +614,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 		}
 	case statVersion11:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport11TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport11UDPLen
-		} else if protocol == "rdma" {
+		case "rdma":
 			expectedLength = fieldTransport11RDMAMinLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) ||
@@ -655,11 +657,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	// For the udp RPC transport there is no connection count, connect idle time,
 	// or idle time (fields #3, #4, and #5); all other fields are the same. So
 	// we set them to 0 here.
-	if protocol == "udp" {
+	switch protocol {
+	case "udp":
 		ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
-	} else if protocol == "tcp" {
+	case "tcp":
 		ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...)
-	} else if protocol == "rdma" {
+	case "rdma":
 		ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...)
 	}
 
diff --git a/history-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/history-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
new file mode 100644
index 00000000..f50b38e3
--- /dev/null
+++ b/history-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
@@ -0,0 +1,96 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc//net/dev_snmp6/.
+// The outer map's keys are interface names and the inner map's keys are stat names.
+//
+// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type.
+type NetDevSNMP6 map[string]map[string]uint64
+
+// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/
+// directory.
+func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6"))
+}
+
+// Returns kernel/system statistics read from interface files within the /proc//net/dev_snmp6/
+// directory.
+func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(p.path("net/dev_snmp6"))
+}
+
+// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory.
+func newNetDevSNMP6(dir string) (NetDevSNMP6, error) {
+	netDevSNMP6 := make(NetDevSNMP6)
+
+	// The net/dev_snmp6 folders contain one file per interface
+	ifaceFiles, err := os.ReadDir(dir)
+	if err != nil {
+		// On systems with IPv6 disabled, this directory won't exist.
+		// Do nothing.
+		if errors.Is(err, os.ErrNotExist) {
+			return netDevSNMP6, err
+		}
+		return netDevSNMP6, err
+	}
+
+	for _, iFaceFile := range ifaceFiles {
+		f, err := os.Open(dir + "/" + iFaceFile.Name())
+		if err != nil {
+			return netDevSNMP6, err
+		}
+		defer f.Close()
+
+		netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f)
+		if err != nil {
+			return netDevSNMP6, err
+		}
+	}
+
+	return netDevSNMP6, nil
+}
+
+func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) {
+	m := make(map[string]uint64)
+
+	scanner := bufio.NewScanner(r)
+	for scanner.Scan() {
+		stat := strings.Fields(scanner.Text())
+		if len(stat) < 2 {
+			continue
+		}
+		key, val := stat[0], stat[1]
+
+		// Expect stat name to contain "6" or be "ifIndex"
+		if strings.Contains(key, "6") || key == "ifIndex" {
+			v, err := strconv.ParseUint(val, 10, 64)
+			if err != nil {
+				return m, err
+			}
+
+			m[key] = v
+		}
+	}
+	return m, scanner.Err()
+}
diff --git a/history-api/vendor/github.com/prometheus/procfs/net_ip_socket.go b/history-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
index b70f1fc7..19e3378f 100644
--- a/history-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
+++ b/history-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
@@ -25,7 +25,7 @@ import (
 )
 
 const (
-	// readLimit is used by io.LimitReader while reading the content of the
+	// Maximum size limit used by io.LimitReader while reading the content of the
 	// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
 	// as each line represents a single used socket.
 	// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
@@ -50,12 +50,12 @@ type (
 		// UsedSockets shows the total number of parsed lines representing the
 		// number of used sockets.
 		UsedSockets uint64
-		// Drops shows the total number of dropped packets of all UPD sockets.
+		// Drops shows the total number of dropped packets of all UDP sockets.
 		Drops *uint64
 	}
 
-	// netIPSocketLine represents the fields parsed from a single line
-	// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
+	// A single line parser for fields from /proc/net/{t,u}dp{,6}.
+	// Fields which are not used by IPSocket are skipped.
 	// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
 	// For the proc file format details, see https://linux.die.net/man/5/proc.
 	netIPSocketLine struct {
diff --git a/history-api/vendor/github.com/prometheus/procfs/net_protocols.go b/history-api/vendor/github.com/prometheus/procfs/net_protocols.go
index b6c77b70..8d4b1ac0 100644
--- a/history-api/vendor/github.com/prometheus/procfs/net_protocols.go
+++ b/history-api/vendor/github.com/prometheus/procfs/net_protocols.go
@@ -115,22 +115,24 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro
 	if err != nil {
 		return nil, err
 	}
-	if fields[4] == enabled {
+	switch fields[4] {
+	case enabled:
 		line.Pressure = 1
-	} else if fields[4] == disabled {
+	case disabled:
 		line.Pressure = 0
-	} else {
+	default:
 		line.Pressure = -1
 	}
 	line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	if fields[6] == enabled {
+	switch fields[6] {
+	case enabled:
 		line.Slab = true
-	} else if fields[6] == disabled {
+	case disabled:
 		line.Slab = false
-	} else {
+	default:
 		return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name)
 	}
 	line.ModuleName = fields[7]
@@ -168,11 +170,12 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro
 	}
 
 	for i := 0; i < len(capabilities); i++ {
-		if capabilities[i] == "y" {
+		switch capabilities[i] {
+		case "y":
 			*capabilityFields[i] = true
-		} else if capabilities[i] == "n" {
+		case "n":
 			*capabilityFields[i] = false
-		} else {
+		default:
 			return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i)
 		}
 	}
diff --git a/history-api/vendor/github.com/prometheus/procfs/net_tcp.go b/history-api/vendor/github.com/prometheus/procfs/net_tcp.go
index 52776295..0396d720 100644
--- a/history-api/vendor/github.com/prometheus/procfs/net_tcp.go
+++ b/history-api/vendor/github.com/prometheus/procfs/net_tcp.go
@@ -25,24 +25,28 @@ type (
 
 // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCP() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp6"))
 }
 
 // NetTCPSummary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6Summary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp6"))
 }
diff --git a/history-api/vendor/github.com/prometheus/procfs/net_unix.go b/history-api/vendor/github.com/prometheus/procfs/net_unix.go
index d868cebd..d7e0cacb 100644
--- a/history-api/vendor/github.com/prometheus/procfs/net_unix.go
+++ b/history-api/vendor/github.com/prometheus/procfs/net_unix.go
@@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
 	return &nu, nil
 }
 
-func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) {
+func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) {
 	fields := strings.Fields(line)
 
 	l := len(fields)
-	if l < min {
-		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l)
+	if l < minFields {
+		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l)
 	}
 
 	// Field offsets are as follows:
@@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine,
 	}
 
 	// Path field is optional.
-	if l > min {
+	if l > minFields {
 		// Path occurs at either index 6 or 7 depending on whether inode is
 		// already present.
 		pathIdx := 7
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc.go b/history-api/vendor/github.com/prometheus/procfs/proc.go
index 14279636..368187fa 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc.go
@@ -37,9 +37,9 @@ type Proc struct {
 type Procs []Proc
 
 var (
-	ErrFileParse  = errors.New("Error Parsing File")
-	ErrFileRead   = errors.New("Error Reading File")
-	ErrMountPoint = errors.New("Error Accessing Mount point")
+	ErrFileParse  = errors.New("error parsing file")
+	ErrFileRead   = errors.New("error reading file")
+	ErrMountPoint = errors.New("error accessing mount point")
 )
 
 func (p Procs) Len() int           { return len(p) }
@@ -79,7 +79,7 @@ func (fs FS) Self() (Proc, error) {
 	if err != nil {
 		return Proc{}, err
 	}
-	pid, err := strconv.Atoi(strings.Replace(p, string(fs.proc), "", -1))
+	pid, err := strconv.Atoi(strings.ReplaceAll(p, string(fs.proc), ""))
 	if err != nil {
 		return Proc{}, err
 	}
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_cgroup.go b/history-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
index daeed7f5..4a64347c 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
@@ -24,7 +24,7 @@ import (
 )
 
 // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a
-// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource
+// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource
 // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies
 // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in
 // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_io.go b/history-api/vendor/github.com/prometheus/procfs/proc_io.go
index 776f3497..d15b66dd 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_io.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_io.go
@@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) {
 
 	ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
 		"read_bytes: %d\nwrite_bytes: %d\n" +
-		"cancelled_write_bytes: %d\n"
+		"cancelled_write_bytes: %d\n" //nolint:misspell
 
 	_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
 		&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_netstat.go b/history-api/vendor/github.com/prometheus/procfs/proc_netstat.go
index 8e3ff4d7..4248c171 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_netstat.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_netstat.go
@@ -209,232 +209,232 @@ func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
 			case "TcpExt":
 				switch key {
 				case "SyncookiesSent":
-					procNetstat.TcpExt.SyncookiesSent = &value
+					procNetstat.SyncookiesSent = &value
 				case "SyncookiesRecv":
-					procNetstat.TcpExt.SyncookiesRecv = &value
+					procNetstat.SyncookiesRecv = &value
 				case "SyncookiesFailed":
-					procNetstat.TcpExt.SyncookiesFailed = &value
+					procNetstat.SyncookiesFailed = &value
 				case "EmbryonicRsts":
-					procNetstat.TcpExt.EmbryonicRsts = &value
+					procNetstat.EmbryonicRsts = &value
 				case "PruneCalled":
-					procNetstat.TcpExt.PruneCalled = &value
+					procNetstat.PruneCalled = &value
 				case "RcvPruned":
-					procNetstat.TcpExt.RcvPruned = &value
+					procNetstat.RcvPruned = &value
 				case "OfoPruned":
-					procNetstat.TcpExt.OfoPruned = &value
+					procNetstat.OfoPruned = &value
 				case "OutOfWindowIcmps":
-					procNetstat.TcpExt.OutOfWindowIcmps = &value
+					procNetstat.OutOfWindowIcmps = &value
 				case "LockDroppedIcmps":
-					procNetstat.TcpExt.LockDroppedIcmps = &value
+					procNetstat.LockDroppedIcmps = &value
 				case "ArpFilter":
-					procNetstat.TcpExt.ArpFilter = &value
+					procNetstat.ArpFilter = &value
 				case "TW":
-					procNetstat.TcpExt.TW = &value
+					procNetstat.TW = &value
 				case "TWRecycled":
-					procNetstat.TcpExt.TWRecycled = &value
+					procNetstat.TWRecycled = &value
 				case "TWKilled":
-					procNetstat.TcpExt.TWKilled = &value
+					procNetstat.TWKilled = &value
 				case "PAWSActive":
-					procNetstat.TcpExt.PAWSActive = &value
+					procNetstat.PAWSActive = &value
 				case "PAWSEstab":
-					procNetstat.TcpExt.PAWSEstab = &value
+					procNetstat.PAWSEstab = &value
 				case "DelayedACKs":
-					procNetstat.TcpExt.DelayedACKs = &value
+					procNetstat.DelayedACKs = &value
 				case "DelayedACKLocked":
-					procNetstat.TcpExt.DelayedACKLocked = &value
+					procNetstat.DelayedACKLocked = &value
 				case "DelayedACKLost":
-					procNetstat.TcpExt.DelayedACKLost = &value
+					procNetstat.DelayedACKLost = &value
 				case "ListenOverflows":
-					procNetstat.TcpExt.ListenOverflows = &value
+					procNetstat.ListenOverflows = &value
 				case "ListenDrops":
-					procNetstat.TcpExt.ListenDrops = &value
+					procNetstat.ListenDrops = &value
 				case "TCPHPHits":
-					procNetstat.TcpExt.TCPHPHits = &value
+					procNetstat.TCPHPHits = &value
 				case "TCPPureAcks":
-					procNetstat.TcpExt.TCPPureAcks = &value
+					procNetstat.TCPPureAcks = &value
 				case "TCPHPAcks":
-					procNetstat.TcpExt.TCPHPAcks = &value
+					procNetstat.TCPHPAcks = &value
 				case "TCPRenoRecovery":
-					procNetstat.TcpExt.TCPRenoRecovery = &value
+					procNetstat.TCPRenoRecovery = &value
 				case "TCPSackRecovery":
-					procNetstat.TcpExt.TCPSackRecovery = &value
+					procNetstat.TCPSackRecovery = &value
 				case "TCPSACKReneging":
-					procNetstat.TcpExt.TCPSACKReneging = &value
+					procNetstat.TCPSACKReneging = &value
 				case "TCPSACKReorder":
-					procNetstat.TcpExt.TCPSACKReorder = &value
+					procNetstat.TCPSACKReorder = &value
 				case "TCPRenoReorder":
-					procNetstat.TcpExt.TCPRenoReorder = &value
+					procNetstat.TCPRenoReorder = &value
 				case "TCPTSReorder":
-					procNetstat.TcpExt.TCPTSReorder = &value
+					procNetstat.TCPTSReorder = &value
 				case "TCPFullUndo":
-					procNetstat.TcpExt.TCPFullUndo = &value
+					procNetstat.TCPFullUndo = &value
 				case "TCPPartialUndo":
-					procNetstat.TcpExt.TCPPartialUndo = &value
+					procNetstat.TCPPartialUndo = &value
 				case "TCPDSACKUndo":
-					procNetstat.TcpExt.TCPDSACKUndo = &value
+					procNetstat.TCPDSACKUndo = &value
 				case "TCPLossUndo":
-					procNetstat.TcpExt.TCPLossUndo = &value
+					procNetstat.TCPLossUndo = &value
 				case "TCPLostRetransmit":
-					procNetstat.TcpExt.TCPLostRetransmit = &value
+					procNetstat.TCPLostRetransmit = &value
 				case "TCPRenoFailures":
-					procNetstat.TcpExt.TCPRenoFailures = &value
+					procNetstat.TCPRenoFailures = &value
 				case "TCPSackFailures":
-					procNetstat.TcpExt.TCPSackFailures = &value
+					procNetstat.TCPSackFailures = &value
 				case "TCPLossFailures":
-					procNetstat.TcpExt.TCPLossFailures = &value
+					procNetstat.TCPLossFailures = &value
 				case "TCPFastRetrans":
-					procNetstat.TcpExt.TCPFastRetrans = &value
+					procNetstat.TCPFastRetrans = &value
 				case "TCPSlowStartRetrans":
-					procNetstat.TcpExt.TCPSlowStartRetrans = &value
+					procNetstat.TCPSlowStartRetrans = &value
 				case "TCPTimeouts":
-					procNetstat.TcpExt.TCPTimeouts = &value
+					procNetstat.TCPTimeouts = &value
 				case "TCPLossProbes":
-					procNetstat.TcpExt.TCPLossProbes = &value
+					procNetstat.TCPLossProbes = &value
 				case "TCPLossProbeRecovery":
-					procNetstat.TcpExt.TCPLossProbeRecovery = &value
+					procNetstat.TCPLossProbeRecovery = &value
 				case "TCPRenoRecoveryFail":
-					procNetstat.TcpExt.TCPRenoRecoveryFail = &value
+					procNetstat.TCPRenoRecoveryFail = &value
 				case "TCPSackRecoveryFail":
-					procNetstat.TcpExt.TCPSackRecoveryFail = &value
+					procNetstat.TCPSackRecoveryFail = &value
 				case "TCPRcvCollapsed":
-					procNetstat.TcpExt.TCPRcvCollapsed = &value
+					procNetstat.TCPRcvCollapsed = &value
 				case "TCPDSACKOldSent":
-					procNetstat.TcpExt.TCPDSACKOldSent = &value
+					procNetstat.TCPDSACKOldSent = &value
 				case "TCPDSACKOfoSent":
-					procNetstat.TcpExt.TCPDSACKOfoSent = &value
+					procNetstat.TCPDSACKOfoSent = &value
 				case "TCPDSACKRecv":
-					procNetstat.TcpExt.TCPDSACKRecv = &value
+					procNetstat.TCPDSACKRecv = &value
 				case "TCPDSACKOfoRecv":
-					procNetstat.TcpExt.TCPDSACKOfoRecv = &value
+					procNetstat.TCPDSACKOfoRecv = &value
 				case "TCPAbortOnData":
-					procNetstat.TcpExt.TCPAbortOnData = &value
+					procNetstat.TCPAbortOnData = &value
 				case "TCPAbortOnClose":
-					procNetstat.TcpExt.TCPAbortOnClose = &value
+					procNetstat.TCPAbortOnClose = &value
 				case "TCPDeferAcceptDrop":
-					procNetstat.TcpExt.TCPDeferAcceptDrop = &value
+					procNetstat.TCPDeferAcceptDrop = &value
 				case "IPReversePathFilter":
-					procNetstat.TcpExt.IPReversePathFilter = &value
+					procNetstat.IPReversePathFilter = &value
 				case "TCPTimeWaitOverflow":
-					procNetstat.TcpExt.TCPTimeWaitOverflow = &value
+					procNetstat.TCPTimeWaitOverflow = &value
 				case "TCPReqQFullDoCookies":
-					procNetstat.TcpExt.TCPReqQFullDoCookies = &value
+					procNetstat.TCPReqQFullDoCookies = &value
 				case "TCPReqQFullDrop":
-					procNetstat.TcpExt.TCPReqQFullDrop = &value
+					procNetstat.TCPReqQFullDrop = &value
 				case "TCPRetransFail":
-					procNetstat.TcpExt.TCPRetransFail = &value
+					procNetstat.TCPRetransFail = &value
 				case "TCPRcvCoalesce":
-					procNetstat.TcpExt.TCPRcvCoalesce = &value
+					procNetstat.TCPRcvCoalesce = &value
 				case "TCPRcvQDrop":
-					procNetstat.TcpExt.TCPRcvQDrop = &value
+					procNetstat.TCPRcvQDrop = &value
 				case "TCPOFOQueue":
-					procNetstat.TcpExt.TCPOFOQueue = &value
+					procNetstat.TCPOFOQueue = &value
 				case "TCPOFODrop":
-					procNetstat.TcpExt.TCPOFODrop = &value
+					procNetstat.TCPOFODrop = &value
 				case "TCPOFOMerge":
-					procNetstat.TcpExt.TCPOFOMerge = &value
+					procNetstat.TCPOFOMerge = &value
 				case "TCPChallengeACK":
-					procNetstat.TcpExt.TCPChallengeACK = &value
+					procNetstat.TCPChallengeACK = &value
 				case "TCPSYNChallenge":
-					procNetstat.TcpExt.TCPSYNChallenge = &value
+					procNetstat.TCPSYNChallenge = &value
 				case "TCPFastOpenActive":
-					procNetstat.TcpExt.TCPFastOpenActive = &value
+					procNetstat.TCPFastOpenActive = &value
 				case "TCPFastOpenActiveFail":
-					procNetstat.TcpExt.TCPFastOpenActiveFail = &value
+					procNetstat.TCPFastOpenActiveFail = &value
 				case "TCPFastOpenPassive":
-					procNetstat.TcpExt.TCPFastOpenPassive = &value
+					procNetstat.TCPFastOpenPassive = &value
 				case "TCPFastOpenPassiveFail":
-					procNetstat.TcpExt.TCPFastOpenPassiveFail = &value
+					procNetstat.TCPFastOpenPassiveFail = &value
 				case "TCPFastOpenListenOverflow":
-					procNetstat.TcpExt.TCPFastOpenListenOverflow = &value
+					procNetstat.TCPFastOpenListenOverflow = &value
 				case "TCPFastOpenCookieReqd":
-					procNetstat.TcpExt.TCPFastOpenCookieReqd = &value
+					procNetstat.TCPFastOpenCookieReqd = &value
 				case "TCPFastOpenBlackhole":
-					procNetstat.TcpExt.TCPFastOpenBlackhole = &value
+					procNetstat.TCPFastOpenBlackhole = &value
 				case "TCPSpuriousRtxHostQueues":
-					procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value
+					procNetstat.TCPSpuriousRtxHostQueues = &value
 				case "BusyPollRxPackets":
-					procNetstat.TcpExt.BusyPollRxPackets = &value
+					procNetstat.BusyPollRxPackets = &value
 				case "TCPAutoCorking":
-					procNetstat.TcpExt.TCPAutoCorking = &value
+					procNetstat.TCPAutoCorking = &value
 				case "TCPFromZeroWindowAdv":
-					procNetstat.TcpExt.TCPFromZeroWindowAdv = &value
+					procNetstat.TCPFromZeroWindowAdv = &value
 				case "TCPToZeroWindowAdv":
-					procNetstat.TcpExt.TCPToZeroWindowAdv = &value
+					procNetstat.TCPToZeroWindowAdv = &value
 				case "TCPWantZeroWindowAdv":
-					procNetstat.TcpExt.TCPWantZeroWindowAdv = &value
+					procNetstat.TCPWantZeroWindowAdv = &value
 				case "TCPSynRetrans":
-					procNetstat.TcpExt.TCPSynRetrans = &value
+					procNetstat.TCPSynRetrans = &value
 				case "TCPOrigDataSent":
-					procNetstat.TcpExt.TCPOrigDataSent = &value
+					procNetstat.TCPOrigDataSent = &value
 				case "TCPHystartTrainDetect":
-					procNetstat.TcpExt.TCPHystartTrainDetect = &value
+					procNetstat.TCPHystartTrainDetect = &value
 				case "TCPHystartTrainCwnd":
-					procNetstat.TcpExt.TCPHystartTrainCwnd = &value
+					procNetstat.TCPHystartTrainCwnd = &value
 				case "TCPHystartDelayDetect":
-					procNetstat.TcpExt.TCPHystartDelayDetect = &value
+					procNetstat.TCPHystartDelayDetect = &value
 				case "TCPHystartDelayCwnd":
-					procNetstat.TcpExt.TCPHystartDelayCwnd = &value
+					procNetstat.TCPHystartDelayCwnd = &value
 				case "TCPACKSkippedSynRecv":
-					procNetstat.TcpExt.TCPACKSkippedSynRecv = &value
+					procNetstat.TCPACKSkippedSynRecv = &value
 				case "TCPACKSkippedPAWS":
-					procNetstat.TcpExt.TCPACKSkippedPAWS = &value
+					procNetstat.TCPACKSkippedPAWS = &value
 				case "TCPACKSkippedSeq":
-					procNetstat.TcpExt.TCPACKSkippedSeq = &value
+					procNetstat.TCPACKSkippedSeq = &value
 				case "TCPACKSkippedFinWait2":
-					procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value
+					procNetstat.TCPACKSkippedFinWait2 = &value
 				case "TCPACKSkippedTimeWait":
-					procNetstat.TcpExt.TCPACKSkippedTimeWait = &value
+					procNetstat.TCPACKSkippedTimeWait = &value
 				case "TCPACKSkippedChallenge":
-					procNetstat.TcpExt.TCPACKSkippedChallenge = &value
+					procNetstat.TCPACKSkippedChallenge = &value
 				case "TCPWinProbe":
-					procNetstat.TcpExt.TCPWinProbe = &value
+					procNetstat.TCPWinProbe = &value
 				case "TCPKeepAlive":
-					procNetstat.TcpExt.TCPKeepAlive = &value
+					procNetstat.TCPKeepAlive = &value
 				case "TCPMTUPFail":
-					procNetstat.TcpExt.TCPMTUPFail = &value
+					procNetstat.TCPMTUPFail = &value
 				case "TCPMTUPSuccess":
-					procNetstat.TcpExt.TCPMTUPSuccess = &value
+					procNetstat.TCPMTUPSuccess = &value
 				case "TCPWqueueTooBig":
-					procNetstat.TcpExt.TCPWqueueTooBig = &value
+					procNetstat.TCPWqueueTooBig = &value
 				}
 			case "IpExt":
 				switch key {
 				case "InNoRoutes":
-					procNetstat.IpExt.InNoRoutes = &value
+					procNetstat.InNoRoutes = &value
 				case "InTruncatedPkts":
-					procNetstat.IpExt.InTruncatedPkts = &value
+					procNetstat.InTruncatedPkts = &value
 				case "InMcastPkts":
-					procNetstat.IpExt.InMcastPkts = &value
+					procNetstat.InMcastPkts = &value
 				case "OutMcastPkts":
-					procNetstat.IpExt.OutMcastPkts = &value
+					procNetstat.OutMcastPkts = &value
 				case "InBcastPkts":
-					procNetstat.IpExt.InBcastPkts = &value
+					procNetstat.InBcastPkts = &value
 				case "OutBcastPkts":
-					procNetstat.IpExt.OutBcastPkts = &value
+					procNetstat.OutBcastPkts = &value
 				case "InOctets":
-					procNetstat.IpExt.InOctets = &value
+					procNetstat.InOctets = &value
 				case "OutOctets":
-					procNetstat.IpExt.OutOctets = &value
+					procNetstat.OutOctets = &value
 				case "InMcastOctets":
-					procNetstat.IpExt.InMcastOctets = &value
+					procNetstat.InMcastOctets = &value
 				case "OutMcastOctets":
-					procNetstat.IpExt.OutMcastOctets = &value
+					procNetstat.OutMcastOctets = &value
 				case "InBcastOctets":
-					procNetstat.IpExt.InBcastOctets = &value
+					procNetstat.InBcastOctets = &value
 				case "OutBcastOctets":
-					procNetstat.IpExt.OutBcastOctets = &value
+					procNetstat.OutBcastOctets = &value
 				case "InCsumErrors":
-					procNetstat.IpExt.InCsumErrors = &value
+					procNetstat.InCsumErrors = &value
 				case "InNoECTPkts":
-					procNetstat.IpExt.InNoECTPkts = &value
+					procNetstat.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procNetstat.IpExt.InECT1Pkts = &value
+					procNetstat.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procNetstat.IpExt.InECT0Pkts = &value
+					procNetstat.InECT0Pkts = &value
 				case "InCEPkts":
-					procNetstat.IpExt.InCEPkts = &value
+					procNetstat.InCEPkts = &value
 				case "ReasmOverlaps":
-					procNetstat.IpExt.ReasmOverlaps = &value
+					procNetstat.ReasmOverlaps = &value
 				}
 			}
 		}
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_smaps.go b/history-api/vendor/github.com/prometheus/procfs/proc_smaps.go
index 09060e82..9a297afc 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_smaps.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_smaps.go
@@ -19,7 +19,6 @@ package procfs
 import (
 	"bufio"
 	"errors"
-	"fmt"
 	"os"
 	"regexp"
 	"strconv"
@@ -29,7 +28,7 @@ import (
 )
 
 var (
-	// match the header line before each mapped zone in `/proc/pid/smaps`.
+	// Match the header line before each mapped zone in `/proc/pid/smaps`.
 	procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`)
 )
 
@@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) {
 func (s *ProcSMapsRollup) parseLine(line string) error {
 	kv := strings.SplitN(line, ":", 2)
 	if len(kv) != 2 {
-		fmt.Println(line)
 		return errors.New("invalid net/dev line, missing colon")
 	}
 
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_snmp.go b/history-api/vendor/github.com/prometheus/procfs/proc_snmp.go
index b9d2cf64..4bdc90b0 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_snmp.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_snmp.go
@@ -173,138 +173,138 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) {
 			case "Ip":
 				switch key {
 				case "Forwarding":
-					procSnmp.Ip.Forwarding = &value
+					procSnmp.Forwarding = &value
 				case "DefaultTTL":
-					procSnmp.Ip.DefaultTTL = &value
+					procSnmp.DefaultTTL = &value
 				case "InReceives":
-					procSnmp.Ip.InReceives = &value
+					procSnmp.InReceives = &value
 				case "InHdrErrors":
-					procSnmp.Ip.InHdrErrors = &value
+					procSnmp.InHdrErrors = &value
 				case "InAddrErrors":
-					procSnmp.Ip.InAddrErrors = &value
+					procSnmp.InAddrErrors = &value
 				case "ForwDatagrams":
-					procSnmp.Ip.ForwDatagrams = &value
+					procSnmp.ForwDatagrams = &value
 				case "InUnknownProtos":
-					procSnmp.Ip.InUnknownProtos = &value
+					procSnmp.InUnknownProtos = &value
 				case "InDiscards":
-					procSnmp.Ip.InDiscards = &value
+					procSnmp.InDiscards = &value
 				case "InDelivers":
-					procSnmp.Ip.InDelivers = &value
+					procSnmp.InDelivers = &value
 				case "OutRequests":
-					procSnmp.Ip.OutRequests = &value
+					procSnmp.OutRequests = &value
 				case "OutDiscards":
-					procSnmp.Ip.OutDiscards = &value
+					procSnmp.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp.Ip.OutNoRoutes = &value
+					procSnmp.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp.Ip.ReasmTimeout = &value
+					procSnmp.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp.Ip.ReasmReqds = &value
+					procSnmp.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp.Ip.ReasmOKs = &value
+					procSnmp.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp.Ip.ReasmFails = &value
+					procSnmp.ReasmFails = &value
 				case "FragOKs":
-					procSnmp.Ip.FragOKs = &value
+					procSnmp.FragOKs = &value
 				case "FragFails":
-					procSnmp.Ip.FragFails = &value
+					procSnmp.FragFails = &value
 				case "FragCreates":
-					procSnmp.Ip.FragCreates = &value
+					procSnmp.FragCreates = &value
 				}
 			case "Icmp":
 				switch key {
 				case "InMsgs":
-					procSnmp.Icmp.InMsgs = &value
+					procSnmp.InMsgs = &value
 				case "InErrors":
 					procSnmp.Icmp.InErrors = &value
 				case "InCsumErrors":
 					procSnmp.Icmp.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp.Icmp.InDestUnreachs = &value
+					procSnmp.InDestUnreachs = &value
 				case "InTimeExcds":
-					procSnmp.Icmp.InTimeExcds = &value
+					procSnmp.InTimeExcds = &value
 				case "InParmProbs":
-					procSnmp.Icmp.InParmProbs = &value
+					procSnmp.InParmProbs = &value
 				case "InSrcQuenchs":
-					procSnmp.Icmp.InSrcQuenchs = &value
+					procSnmp.InSrcQuenchs = &value
 				case "InRedirects":
-					procSnmp.Icmp.InRedirects = &value
+					procSnmp.InRedirects = &value
 				case "InEchos":
-					procSnmp.Icmp.InEchos = &value
+					procSnmp.InEchos = &value
 				case "InEchoReps":
-					procSnmp.Icmp.InEchoReps = &value
+					procSnmp.InEchoReps = &value
 				case "InTimestamps":
-					procSnmp.Icmp.InTimestamps = &value
+					procSnmp.InTimestamps = &value
 				case "InTimestampReps":
-					procSnmp.Icmp.InTimestampReps = &value
+					procSnmp.InTimestampReps = &value
 				case "InAddrMasks":
-					procSnmp.Icmp.InAddrMasks = &value
+					procSnmp.InAddrMasks = &value
 				case "InAddrMaskReps":
-					procSnmp.Icmp.InAddrMaskReps = &value
+					procSnmp.InAddrMaskReps = &value
 				case "OutMsgs":
-					procSnmp.Icmp.OutMsgs = &value
+					procSnmp.OutMsgs = &value
 				case "OutErrors":
-					procSnmp.Icmp.OutErrors = &value
+					procSnmp.OutErrors = &value
 				case "OutDestUnreachs":
-					procSnmp.Icmp.OutDestUnreachs = &value
+					procSnmp.OutDestUnreachs = &value
 				case "OutTimeExcds":
-					procSnmp.Icmp.OutTimeExcds = &value
+					procSnmp.OutTimeExcds = &value
 				case "OutParmProbs":
-					procSnmp.Icmp.OutParmProbs = &value
+					procSnmp.OutParmProbs = &value
 				case "OutSrcQuenchs":
-					procSnmp.Icmp.OutSrcQuenchs = &value
+					procSnmp.OutSrcQuenchs = &value
 				case "OutRedirects":
-					procSnmp.Icmp.OutRedirects = &value
+					procSnmp.OutRedirects = &value
 				case "OutEchos":
-					procSnmp.Icmp.OutEchos = &value
+					procSnmp.OutEchos = &value
 				case "OutEchoReps":
-					procSnmp.Icmp.OutEchoReps = &value
+					procSnmp.OutEchoReps = &value
 				case "OutTimestamps":
-					procSnmp.Icmp.OutTimestamps = &value
+					procSnmp.OutTimestamps = &value
 				case "OutTimestampReps":
-					procSnmp.Icmp.OutTimestampReps = &value
+					procSnmp.OutTimestampReps = &value
 				case "OutAddrMasks":
-					procSnmp.Icmp.OutAddrMasks = &value
+					procSnmp.OutAddrMasks = &value
 				case "OutAddrMaskReps":
-					procSnmp.Icmp.OutAddrMaskReps = &value
+					procSnmp.OutAddrMaskReps = &value
 				}
 			case "IcmpMsg":
 				switch key {
 				case "InType3":
-					procSnmp.IcmpMsg.InType3 = &value
+					procSnmp.InType3 = &value
 				case "OutType3":
-					procSnmp.IcmpMsg.OutType3 = &value
+					procSnmp.OutType3 = &value
 				}
 			case "Tcp":
 				switch key {
 				case "RtoAlgorithm":
-					procSnmp.Tcp.RtoAlgorithm = &value
+					procSnmp.RtoAlgorithm = &value
 				case "RtoMin":
-					procSnmp.Tcp.RtoMin = &value
+					procSnmp.RtoMin = &value
 				case "RtoMax":
-					procSnmp.Tcp.RtoMax = &value
+					procSnmp.RtoMax = &value
 				case "MaxConn":
-					procSnmp.Tcp.MaxConn = &value
+					procSnmp.MaxConn = &value
 				case "ActiveOpens":
-					procSnmp.Tcp.ActiveOpens = &value
+					procSnmp.ActiveOpens = &value
 				case "PassiveOpens":
-					procSnmp.Tcp.PassiveOpens = &value
+					procSnmp.PassiveOpens = &value
 				case "AttemptFails":
-					procSnmp.Tcp.AttemptFails = &value
+					procSnmp.AttemptFails = &value
 				case "EstabResets":
-					procSnmp.Tcp.EstabResets = &value
+					procSnmp.EstabResets = &value
 				case "CurrEstab":
-					procSnmp.Tcp.CurrEstab = &value
+					procSnmp.CurrEstab = &value
 				case "InSegs":
-					procSnmp.Tcp.InSegs = &value
+					procSnmp.InSegs = &value
 				case "OutSegs":
-					procSnmp.Tcp.OutSegs = &value
+					procSnmp.OutSegs = &value
 				case "RetransSegs":
-					procSnmp.Tcp.RetransSegs = &value
+					procSnmp.RetransSegs = &value
 				case "InErrs":
-					procSnmp.Tcp.InErrs = &value
+					procSnmp.InErrs = &value
 				case "OutRsts":
-					procSnmp.Tcp.OutRsts = &value
+					procSnmp.OutRsts = &value
 				case "InCsumErrors":
 					procSnmp.Tcp.InCsumErrors = &value
 				}
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_snmp6.go b/history-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
index 3059cc6a..fb7fd399 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
@@ -182,161 +182,161 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 			case "Ip6":
 				switch key {
 				case "InReceives":
-					procSnmp6.Ip6.InReceives = &value
+					procSnmp6.InReceives = &value
 				case "InHdrErrors":
-					procSnmp6.Ip6.InHdrErrors = &value
+					procSnmp6.InHdrErrors = &value
 				case "InTooBigErrors":
-					procSnmp6.Ip6.InTooBigErrors = &value
+					procSnmp6.InTooBigErrors = &value
 				case "InNoRoutes":
-					procSnmp6.Ip6.InNoRoutes = &value
+					procSnmp6.InNoRoutes = &value
 				case "InAddrErrors":
-					procSnmp6.Ip6.InAddrErrors = &value
+					procSnmp6.InAddrErrors = &value
 				case "InUnknownProtos":
-					procSnmp6.Ip6.InUnknownProtos = &value
+					procSnmp6.InUnknownProtos = &value
 				case "InTruncatedPkts":
-					procSnmp6.Ip6.InTruncatedPkts = &value
+					procSnmp6.InTruncatedPkts = &value
 				case "InDiscards":
-					procSnmp6.Ip6.InDiscards = &value
+					procSnmp6.InDiscards = &value
 				case "InDelivers":
-					procSnmp6.Ip6.InDelivers = &value
+					procSnmp6.InDelivers = &value
 				case "OutForwDatagrams":
-					procSnmp6.Ip6.OutForwDatagrams = &value
+					procSnmp6.OutForwDatagrams = &value
 				case "OutRequests":
-					procSnmp6.Ip6.OutRequests = &value
+					procSnmp6.OutRequests = &value
 				case "OutDiscards":
-					procSnmp6.Ip6.OutDiscards = &value
+					procSnmp6.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp6.Ip6.OutNoRoutes = &value
+					procSnmp6.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp6.Ip6.ReasmTimeout = &value
+					procSnmp6.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp6.Ip6.ReasmReqds = &value
+					procSnmp6.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp6.Ip6.ReasmOKs = &value
+					procSnmp6.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp6.Ip6.ReasmFails = &value
+					procSnmp6.ReasmFails = &value
 				case "FragOKs":
-					procSnmp6.Ip6.FragOKs = &value
+					procSnmp6.FragOKs = &value
 				case "FragFails":
-					procSnmp6.Ip6.FragFails = &value
+					procSnmp6.FragFails = &value
 				case "FragCreates":
-					procSnmp6.Ip6.FragCreates = &value
+					procSnmp6.FragCreates = &value
 				case "InMcastPkts":
-					procSnmp6.Ip6.InMcastPkts = &value
+					procSnmp6.InMcastPkts = &value
 				case "OutMcastPkts":
-					procSnmp6.Ip6.OutMcastPkts = &value
+					procSnmp6.OutMcastPkts = &value
 				case "InOctets":
-					procSnmp6.Ip6.InOctets = &value
+					procSnmp6.InOctets = &value
 				case "OutOctets":
-					procSnmp6.Ip6.OutOctets = &value
+					procSnmp6.OutOctets = &value
 				case "InMcastOctets":
-					procSnmp6.Ip6.InMcastOctets = &value
+					procSnmp6.InMcastOctets = &value
 				case "OutMcastOctets":
-					procSnmp6.Ip6.OutMcastOctets = &value
+					procSnmp6.OutMcastOctets = &value
 				case "InBcastOctets":
-					procSnmp6.Ip6.InBcastOctets = &value
+					procSnmp6.InBcastOctets = &value
 				case "OutBcastOctets":
-					procSnmp6.Ip6.OutBcastOctets = &value
+					procSnmp6.OutBcastOctets = &value
 				case "InNoECTPkts":
-					procSnmp6.Ip6.InNoECTPkts = &value
+					procSnmp6.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procSnmp6.Ip6.InECT1Pkts = &value
+					procSnmp6.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procSnmp6.Ip6.InECT0Pkts = &value
+					procSnmp6.InECT0Pkts = &value
 				case "InCEPkts":
-					procSnmp6.Ip6.InCEPkts = &value
+					procSnmp6.InCEPkts = &value
 
 				}
 			case "Icmp6":
 				switch key {
 				case "InMsgs":
-					procSnmp6.Icmp6.InMsgs = &value
+					procSnmp6.InMsgs = &value
 				case "InErrors":
 					procSnmp6.Icmp6.InErrors = &value
 				case "OutMsgs":
-					procSnmp6.Icmp6.OutMsgs = &value
+					procSnmp6.OutMsgs = &value
 				case "OutErrors":
-					procSnmp6.Icmp6.OutErrors = &value
+					procSnmp6.OutErrors = &value
 				case "InCsumErrors":
 					procSnmp6.Icmp6.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp6.Icmp6.InDestUnreachs = &value
+					procSnmp6.InDestUnreachs = &value
 				case "InPktTooBigs":
-					procSnmp6.Icmp6.InPktTooBigs = &value
+					procSnmp6.InPktTooBigs = &value
 				case "InTimeExcds":
-					procSnmp6.Icmp6.InTimeExcds = &value
+					procSnmp6.InTimeExcds = &value
 				case "InParmProblems":
-					procSnmp6.Icmp6.InParmProblems = &value
+					procSnmp6.InParmProblems = &value
 				case "InEchos":
-					procSnmp6.Icmp6.InEchos = &value
+					procSnmp6.InEchos = &value
 				case "InEchoReplies":
-					procSnmp6.Icmp6.InEchoReplies = &value
+					procSnmp6.InEchoReplies = &value
 				case "InGroupMembQueries":
-					procSnmp6.Icmp6.InGroupMembQueries = &value
+					procSnmp6.InGroupMembQueries = &value
 				case "InGroupMembResponses":
-					procSnmp6.Icmp6.InGroupMembResponses = &value
+					procSnmp6.InGroupMembResponses = &value
 				case "InGroupMembReductions":
-					procSnmp6.Icmp6.InGroupMembReductions = &value
+					procSnmp6.InGroupMembReductions = &value
 				case "InRouterSolicits":
-					procSnmp6.Icmp6.InRouterSolicits = &value
+					procSnmp6.InRouterSolicits = &value
 				case "InRouterAdvertisements":
-					procSnmp6.Icmp6.InRouterAdvertisements = &value
+					procSnmp6.InRouterAdvertisements = &value
 				case "InNeighborSolicits":
-					procSnmp6.Icmp6.InNeighborSolicits = &value
+					procSnmp6.InNeighborSolicits = &value
 				case "InNeighborAdvertisements":
-					procSnmp6.Icmp6.InNeighborAdvertisements = &value
+					procSnmp6.InNeighborAdvertisements = &value
 				case "InRedirects":
-					procSnmp6.Icmp6.InRedirects = &value
+					procSnmp6.InRedirects = &value
 				case "InMLDv2Reports":
-					procSnmp6.Icmp6.InMLDv2Reports = &value
+					procSnmp6.InMLDv2Reports = &value
 				case "OutDestUnreachs":
-					procSnmp6.Icmp6.OutDestUnreachs = &value
+					procSnmp6.OutDestUnreachs = &value
 				case "OutPktTooBigs":
-					procSnmp6.Icmp6.OutPktTooBigs = &value
+					procSnmp6.OutPktTooBigs = &value
 				case "OutTimeExcds":
-					procSnmp6.Icmp6.OutTimeExcds = &value
+					procSnmp6.OutTimeExcds = &value
 				case "OutParmProblems":
-					procSnmp6.Icmp6.OutParmProblems = &value
+					procSnmp6.OutParmProblems = &value
 				case "OutEchos":
-					procSnmp6.Icmp6.OutEchos = &value
+					procSnmp6.OutEchos = &value
 				case "OutEchoReplies":
-					procSnmp6.Icmp6.OutEchoReplies = &value
+					procSnmp6.OutEchoReplies = &value
 				case "OutGroupMembQueries":
-					procSnmp6.Icmp6.OutGroupMembQueries = &value
+					procSnmp6.OutGroupMembQueries = &value
 				case "OutGroupMembResponses":
-					procSnmp6.Icmp6.OutGroupMembResponses = &value
+					procSnmp6.OutGroupMembResponses = &value
 				case "OutGroupMembReductions":
-					procSnmp6.Icmp6.OutGroupMembReductions = &value
+					procSnmp6.OutGroupMembReductions = &value
 				case "OutRouterSolicits":
-					procSnmp6.Icmp6.OutRouterSolicits = &value
+					procSnmp6.OutRouterSolicits = &value
 				case "OutRouterAdvertisements":
-					procSnmp6.Icmp6.OutRouterAdvertisements = &value
+					procSnmp6.OutRouterAdvertisements = &value
 				case "OutNeighborSolicits":
-					procSnmp6.Icmp6.OutNeighborSolicits = &value
+					procSnmp6.OutNeighborSolicits = &value
 				case "OutNeighborAdvertisements":
-					procSnmp6.Icmp6.OutNeighborAdvertisements = &value
+					procSnmp6.OutNeighborAdvertisements = &value
 				case "OutRedirects":
-					procSnmp6.Icmp6.OutRedirects = &value
+					procSnmp6.OutRedirects = &value
 				case "OutMLDv2Reports":
-					procSnmp6.Icmp6.OutMLDv2Reports = &value
+					procSnmp6.OutMLDv2Reports = &value
 				case "InType1":
-					procSnmp6.Icmp6.InType1 = &value
+					procSnmp6.InType1 = &value
 				case "InType134":
-					procSnmp6.Icmp6.InType134 = &value
+					procSnmp6.InType134 = &value
 				case "InType135":
-					procSnmp6.Icmp6.InType135 = &value
+					procSnmp6.InType135 = &value
 				case "InType136":
-					procSnmp6.Icmp6.InType136 = &value
+					procSnmp6.InType136 = &value
 				case "InType143":
-					procSnmp6.Icmp6.InType143 = &value
+					procSnmp6.InType143 = &value
 				case "OutType133":
-					procSnmp6.Icmp6.OutType133 = &value
+					procSnmp6.OutType133 = &value
 				case "OutType135":
-					procSnmp6.Icmp6.OutType135 = &value
+					procSnmp6.OutType135 = &value
 				case "OutType136":
-					procSnmp6.Icmp6.OutType136 = &value
+					procSnmp6.OutType136 = &value
 				case "OutType143":
-					procSnmp6.Icmp6.OutType143 = &value
+					procSnmp6.OutType143 = &value
 				}
 			case "Udp6":
 				switch key {
@@ -355,7 +355,7 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 				case "InCsumErrors":
 					procSnmp6.Udp6.InCsumErrors = &value
 				case "IgnoredMulti":
-					procSnmp6.Udp6.IgnoredMulti = &value
+					procSnmp6.IgnoredMulti = &value
 				}
 			case "UdpLite6":
 				switch key {
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_stat.go b/history-api/vendor/github.com/prometheus/procfs/proc_stat.go
index 06a8d931..3328556b 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_stat.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_stat.go
@@ -101,6 +101,12 @@ type ProcStat struct {
 	RSS int
 	// Soft limit in bytes on the rss of the process.
 	RSSLimit uint64
+	// The address above which program text can run.
+	StartCode uint64
+	// The address below which program text can run.
+	EndCode uint64
+	// The address of the start (i.e., bottom) of the stack.
+	StartStack uint64
 	// CPU number last executed on.
 	Processor uint
 	// Real-time scheduling priority, a number in the range 1 to 99 for processes
@@ -177,9 +183,9 @@ func (p Proc) Stat() (ProcStat, error) {
 		&s.VSize,
 		&s.RSS,
 		&s.RSSLimit,
-		&ignoreUint64,
-		&ignoreUint64,
-		&ignoreUint64,
+		&s.StartCode,
+		&s.EndCode,
+		&s.StartStack,
 		&ignoreUint64,
 		&ignoreUint64,
 		&ignoreUint64,
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_statm.go b/history-api/vendor/github.com/prometheus/procfs/proc_statm.go
new file mode 100644
index 00000000..ed579842
--- /dev/null
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_statm.go
@@ -0,0 +1,116 @@
+// Copyright 2025 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/prometheus/procfs/internal/util"
+)
+
+// - https://man7.org/linux/man-pages/man5/proc_pid_statm.5.html
+
+// ProcStatm Provides memory usage information for a process, measured in memory pages.
+// Read from /proc/[pid]/statm.
+type ProcStatm struct {
+	// The process ID.
+	PID int
+	// total program size (same as VmSize in status)
+	Size uint64
+	// resident set size (same as VmRSS in status)
+	Resident uint64
+	// number of resident shared pages (i.e., backed by a file)
+	Shared uint64
+	// text (code)
+	Text uint64
+	// library (unused since Linux 2.6; always 0)
+	Lib uint64
+	// data + stack
+	Data uint64
+	// dirty pages (unused since Linux 2.6; always 0)
+	Dt uint64
+}
+
+// NewStatm returns the current status information of the process.
+// Deprecated: Use p.Statm() instead.
+func (p Proc) NewStatm() (ProcStatm, error) {
+	return p.Statm()
+}
+
+// Statm returns the current memory usage information of the process.
+func (p Proc) Statm() (ProcStatm, error) {
+	data, err := util.ReadFileNoStat(p.path("statm"))
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	statmSlice, err := parseStatm(data)
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	procStatm := ProcStatm{
+		PID:      p.PID,
+		Size:     statmSlice[0],
+		Resident: statmSlice[1],
+		Shared:   statmSlice[2],
+		Text:     statmSlice[3],
+		Lib:      statmSlice[4],
+		Data:     statmSlice[5],
+		Dt:       statmSlice[6],
+	}
+
+	return procStatm, nil
+}
+
+// parseStatm return /proc/[pid]/statm data to uint64 slice.
+func parseStatm(data []byte) ([]uint64, error) {
+	var statmSlice []uint64
+	statmItems := strings.Fields(string(data))
+	for i := 0; i < len(statmItems); i++ {
+		statmItem, err := strconv.ParseUint(statmItems[i], 10, 64)
+		if err != nil {
+			return nil, err
+		}
+		statmSlice = append(statmSlice, statmItem)
+	}
+	return statmSlice, nil
+}
+
+// SizeBytes returns the process of total program size in bytes.
+func (s ProcStatm) SizeBytes() uint64 {
+	return s.Size * uint64(os.Getpagesize())
+}
+
+// ResidentBytes returns the process of resident set size in bytes.
+func (s ProcStatm) ResidentBytes() uint64 {
+	return s.Resident * uint64(os.Getpagesize())
+}
+
+// SHRBytes returns the process of share memory size in bytes.
+func (s ProcStatm) SHRBytes() uint64 {
+	return s.Shared * uint64(os.Getpagesize())
+}
+
+// TextBytes returns the process of text (code) size in bytes.
+func (s ProcStatm) TextBytes() uint64 {
+	return s.Text * uint64(os.Getpagesize())
+}
+
+// DataBytes returns the process of data + stack size in bytes.
+func (s ProcStatm) DataBytes() uint64 {
+	return s.Data * uint64(os.Getpagesize())
+}
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_status.go b/history-api/vendor/github.com/prometheus/procfs/proc_status.go
index a055197c..dd8aa568 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_status.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_status.go
@@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
 			}
 		}
 	case "NSpid":
-		s.NSpids = calcNSPidsList(vString)
+		nspids, err := calcNSPidsList(vString)
+		if err != nil {
+			return err
+		}
+		s.NSpids = nspids
 	case "VmPeak":
 		s.VmPeak = vUintBytes
 	case "VmSize":
@@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 {
 	return g
 }
 
-func calcNSPidsList(nspidsString string) []uint64 {
-	s := strings.Split(nspidsString, " ")
+func calcNSPidsList(nspidsString string) ([]uint64, error) {
+	s := strings.Split(nspidsString, "\t")
 	var nspids []uint64
 
 	for _, nspid := range s {
-		nspid, _ := strconv.ParseUint(nspid, 10, 64)
-		if nspid == 0 {
-			continue
+		nspid, err := strconv.ParseUint(nspid, 10, 64)
+		if err != nil {
+			return nil, err
 		}
 		nspids = append(nspids, nspid)
 	}
 
-	return nspids
+	return nspids, nil
 }
diff --git a/history-api/vendor/github.com/prometheus/procfs/proc_sys.go b/history-api/vendor/github.com/prometheus/procfs/proc_sys.go
index 5eefbe2e..3810d1ac 100644
--- a/history-api/vendor/github.com/prometheus/procfs/proc_sys.go
+++ b/history-api/vendor/github.com/prometheus/procfs/proc_sys.go
@@ -21,7 +21,7 @@ import (
 )
 
 func sysctlToPath(sysctl string) string {
-	return strings.Replace(sysctl, ".", "/", -1)
+	return strings.ReplaceAll(sysctl, ".", "/")
 }
 
 func (fs FS) SysctlStrings(sysctl string) ([]string, error) {
diff --git a/history-api/vendor/github.com/prometheus/procfs/softirqs.go b/history-api/vendor/github.com/prometheus/procfs/softirqs.go
index 28708e07..403e6ae7 100644
--- a/history-api/vendor/github.com/prometheus/procfs/softirqs.go
+++ b/history-api/vendor/github.com/prometheus/procfs/softirqs.go
@@ -68,8 +68,8 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 		if len(parts) < 2 {
 			continue
 		}
-		switch {
-		case parts[0] == "HI:":
+		switch parts[0] {
+		case "HI:":
 			perCPU := parts[1:]
 			softirqs.Hi = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -77,7 +77,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TIMER:":
+		case "TIMER:":
 			perCPU := parts[1:]
 			softirqs.Timer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -85,7 +85,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_TX:":
+		case "NET_TX:":
 			perCPU := parts[1:]
 			softirqs.NetTx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -93,7 +93,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_RX:":
+		case "NET_RX:":
 			perCPU := parts[1:]
 			softirqs.NetRx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -101,7 +101,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "BLOCK:":
+		case "BLOCK:":
 			perCPU := parts[1:]
 			softirqs.Block = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -109,7 +109,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "IRQ_POLL:":
+		case "IRQ_POLL:":
 			perCPU := parts[1:]
 			softirqs.IRQPoll = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -117,7 +117,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TASKLET:":
+		case "TASKLET:":
 			perCPU := parts[1:]
 			softirqs.Tasklet = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -125,7 +125,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "SCHED:":
+		case "SCHED:":
 			perCPU := parts[1:]
 			softirqs.Sched = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -133,7 +133,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "HRTIMER:":
+		case "HRTIMER:":
 			perCPU := parts[1:]
 			softirqs.HRTimer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -141,7 +141,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "RCU:":
+		case "RCU:":
 			perCPU := parts[1:]
 			softirqs.RCU = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
diff --git a/history-api/vendor/github.com/rs/cors/cors.go b/history-api/vendor/github.com/rs/cors/cors.go
index da80d343..724f242a 100644
--- a/history-api/vendor/github.com/rs/cors/cors.go
+++ b/history-api/vendor/github.com/rs/cors/cors.go
@@ -364,9 +364,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	// Note: the Fetch standard guarantees that at most one
 	// Access-Control-Request-Headers header is present in the preflight request;
 	// see step 5.2 in https://fetch.spec.whatwg.org/#cors-preflight-fetch-0.
-	reqHeaders, found := first(r.Header, "Access-Control-Request-Headers")
-	if found && !c.allowedHeadersAll && !c.allowedHeaders.Subsumes(reqHeaders[0]) {
-		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders[0])
+	// However, some gateways split that header into multiple headers of the same name;
+	// see https://github.com/rs/cors/issues/184.
+	reqHeaders, found := r.Header["Access-Control-Request-Headers"]
+	if found && !c.allowedHeadersAll && !c.allowedHeaders.Accepts(reqHeaders) {
+		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders)
 		return
 	}
 	if c.allowedOriginsAll {
@@ -391,9 +393,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	if len(c.maxAge) > 0 {
 		headers["Access-Control-Max-Age"] = c.maxAge
 	}
-	if c.Log != nil {
-		c.logf("  Preflight response headers: %v", headers)
-	}
+	c.logf("  Preflight response headers: %v", headers)
 }
 
 // handleActualRequest handles simple cross-origin requests, actual request or redirects
@@ -440,9 +440,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
 	if c.allowCredentials {
 		headers["Access-Control-Allow-Credentials"] = headerTrue
 	}
-	if c.Log != nil {
-		c.logf("  Actual response added headers: %v", headers)
-	}
+	c.logf("  Actual response added headers: %v", headers)
 }
 
 // convenience method. checks if a logger is set.
diff --git a/history-api/vendor/github.com/rs/cors/internal/sortedset.go b/history-api/vendor/github.com/rs/cors/internal/sortedset.go
index 513da20f..844f3f9e 100644
--- a/history-api/vendor/github.com/rs/cors/internal/sortedset.go
+++ b/history-api/vendor/github.com/rs/cors/internal/sortedset.go
@@ -52,46 +52,134 @@ func (set SortedSet) String() string {
 	return strings.Join(elems, ",")
 }
 
-// Subsumes reports whether csv is a sequence of comma-separated names that are
-//   - all elements of set,
-//   - sorted in lexicographically order,
+// Accepts reports whether values is a sequence of list-based field values
+// whose elements are
+//   - all members of set,
+//   - sorted in lexicographical order,
 //   - unique.
-func (set SortedSet) Subsumes(csv string) bool {
-	if csv == "" {
-		return true
+func (set SortedSet) Accepts(values []string) bool {
+	var ( // effectively constant
+		maxLen = maxOWSBytes + set.maxLen + maxOWSBytes + 1 // +1 for comma
+	)
+	var (
+		posOfLastNameSeen = -1
+		name              string
+		commaFound        bool
+		emptyElements     int
+		ok                bool
+	)
+	for _, s := range values {
+		for {
+			// As a defense against maliciously long names in s,
+			// we process only a small number of s's leading bytes per iteration.
+			name, s, commaFound = cutAtComma(s, maxLen)
+			name, ok = trimOWS(name, maxOWSBytes)
+			if !ok {
+				return false
+			}
+			if name == "" {
+				// RFC 9110 requires recipients to tolerate
+				// "a reasonable number of empty list elements"; see
+				// https://httpwg.org/specs/rfc9110.html#abnf.extension.recipient.
+				emptyElements++
+				if emptyElements > maxEmptyElements {
+					return false
+				}
+				if !commaFound { // We have now exhausted the names in s.
+					break
+				}
+				continue
+			}
+			pos, ok := set.m[name]
+			if !ok {
+				return false
+			}
+			// The names in s are expected to be sorted in lexicographical order
+			// and to each appear at most once.
+			// Therefore, the positions (in set) of the names that
+			// appear in s should form a strictly increasing sequence.
+			// If that's not actually the case, bail out.
+			if pos <= posOfLastNameSeen {
+				return false
+			}
+			posOfLastNameSeen = pos
+			if !commaFound { // We have now exhausted the names in s.
+				break
+			}
+		}
+	}
+	return true
+}
+
+const (
+	maxOWSBytes      = 1  // number of leading/trailing OWS bytes tolerated
+	maxEmptyElements = 16 // number of empty list elements tolerated
+)
+
+func cutAtComma(s string, n int) (before, after string, found bool) {
+	// Note: this implementation draws inspiration from strings.Cut's.
+	end := min(len(s), n)
+	if i := strings.IndexByte(s[:end], ','); i >= 0 {
+		after = s[i+1:] // deal with this first to save one bounds check
+		return s[:i], after, true
+	}
+	return s, "", false
+}
+
+// TrimOWS trims up to n bytes of [optional whitespace (OWS)]
+// from the start of and/or the end of s.
+// If no more than n bytes of OWS are found at the start of s
+// and no more than n bytes of OWS are found at the end of s,
+// it returns the trimmed result and true.
+// Otherwise, it returns the original string and false.
+//
+// [optional whitespace (OWS)]: https://httpwg.org/specs/rfc9110.html#whitespace
+func trimOWS(s string, n int) (trimmed string, ok bool) {
+	if s == "" {
+		return s, true
+	}
+	trimmed, ok = trimRightOWS(s, n)
+	if !ok {
+		return s, false
 	}
-	posOfLastNameSeen := -1
-	chunkSize := set.maxLen + 1 // (to accommodate for at least one comma)
-	for {
-		// As a defense against maliciously long names in csv,
-		// we only process at most chunkSize bytes per iteration.
-		end := min(len(csv), chunkSize)
-		comma := strings.IndexByte(csv[:end], ',')
-		var name string
-		if comma == -1 {
-			name = csv
-		} else {
-			name = csv[:comma]
+	trimmed, ok = trimLeftOWS(trimmed, n)
+	if !ok {
+		return s, false
+	}
+	return trimmed, true
+}
+
+func trimLeftOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		pos, found := set.m[name]
-		if !found {
-			return false
+		if !(s[0] == ' ' || s[0] == '\t') {
+			break
 		}
-		// The names in csv are expected to be sorted in lexicographical order
-		// and appear at most once in csv.
-		// Therefore, the positions (in set) of the names that
-		// appear in csv should form a strictly increasing sequence.
-		// If that's not actually the case, bail out.
-		if pos <= posOfLastNameSeen {
-			return false
+		s = s[1:]
+		i++
+	}
+	return s, true
+}
+
+func trimRightOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		posOfLastNameSeen = pos
-		if comma < 0 { // We've now processed all the names in csv.
+		last := len(s) - 1
+		if !(s[last] == ' ' || s[last] == '\t') {
 			break
 		}
-		csv = csv[comma+1:]
+		s = s[:last]
+		i++
 	}
-	return true
+	return s, true
 }
 
 // TODO: when updating go directive to 1.21 or later,
diff --git a/history-api/vendor/github.com/rs/cors/utils.go b/history-api/vendor/github.com/rs/cors/utils.go
index 7019f45c..41b0c283 100644
--- a/history-api/vendor/github.com/rs/cors/utils.go
+++ b/history-api/vendor/github.com/rs/cors/utils.go
@@ -1,7 +1,6 @@
 package cors
 
 import (
-	"net/http"
 	"strings"
 )
 
@@ -24,11 +23,3 @@ func convert(s []string, f func(string) string) []string {
 	}
 	return out
 }
-
-func first(hdrs http.Header, k string) ([]string, bool) {
-	v, found := hdrs[k]
-	if !found || len(v) == 0 {
-		return nil, false
-	}
-	return v[:1], true
-}
diff --git a/history-api/vendor/github.com/rs/zerolog/CNAME b/history-api/vendor/github.com/rs/zerolog/CNAME
deleted file mode 100644
index 9ce57a6e..00000000
--- a/history-api/vendor/github.com/rs/zerolog/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-zerolog.io
\ No newline at end of file
diff --git a/history-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md b/history-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md
new file mode 100644
index 00000000..a09e9e21
--- /dev/null
+++ b/history-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contributing to Zerolog
+
+Thank you for your interest in contributing to **Zerolog**!
+
+Zerolog is a **feature-complete**, high-performance logging library designed to be **lean** and **non-bloated**. The focus of ongoing development is on **bug fixes**, **performance improvements**, and **modernization efforts** (such as keeping up with Go best practices and compatibility with newer Go versions).
+
+## What We're Looking For
+
+We welcome contributions in the following areas:
+
+- **Bug Fixes**: If you find an issue or unexpected behavior, please open an issue and/or submit a fix.
+- **Performance Optimizations**: Improvements that reduce memory usage, allocation count, or CPU cycles without introducing complexity are appreciated.
+- **Modernization**: Compatibility updates for newer Go versions or idiomatic improvements that do not increase library size or complexity.
+- **Documentation Enhancements**: Corrections, clarifications, and improvements to documentation or code comments.
+
+## What We're *Not* Looking For
+
+Zerolog is intended to remain **minimalistic and efficient**. Therefore, we are **not accepting**:
+
+- New features that add optional behaviors or extend API surface area.
+- Built-in support for frameworks or external systems (e.g., bindings, integrations).
+- General-purpose abstractions or configuration helpers.
+
+If you're unsure whether a change aligns with the project's philosophy, feel free to open an issue for discussion before submitting a PR.
+
+## Contributing Guidelines
+
+1. **Fork the repository**
+2. **Create a branch** for your fix or improvement
+3. **Write tests** to cover your changes
+4. Ensure `go test ./...` passes
+5. Run `go fmt` and `go vet` to ensure code consistency
+6. **Submit a pull request** with a clear explanation of the motivation and impact
+
+## Code Style
+
+- Keep the code simple, efficient, and idiomatic.
+- Avoid introducing new dependencies.
+- Preserve backwards compatibility unless explicitly discussed.
+
+---
+
+We appreciate your effort in helping us keep Zerolog fast, minimal, and reliable!
diff --git a/history-api/vendor/github.com/rs/zerolog/README.md b/history-api/vendor/github.com/rs/zerolog/README.md
index 1306a6c1..9d4e8e8d 100644
--- a/history-api/vendor/github.com/rs/zerolog/README.md
+++ b/history-api/vendor/github.com/rs/zerolog/README.md
@@ -366,6 +366,37 @@ log.Info().Str("foo", "bar").Msg("Hello World")
 // Output: 2006-01-02T15:04:05Z07:00 | INFO  | ***Hello World**** foo:BAR
 ```
 
+To use custom advanced formatting:
+
+```go
+output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true,
+    PartsOrder:    []string{"level", "one", "two", "three", "message"},
+    FieldsExclude: []string{"one", "two", "three"}}
+output.FormatLevel = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%-6s", i)) }
+output.FormatFieldName = func(i interface{}) string { return fmt.Sprintf("%s:", i) }
+output.FormatPartValueByName = func(i interface{}, s string) string {
+    var ret string
+    switch s {
+    case "one":
+        ret = strings.ToUpper(fmt.Sprintf("%s", i))
+    case "two":
+        ret = strings.ToLower(fmt.Sprintf("%s", i))
+    case "three":
+        ret = strings.ToLower(fmt.Sprintf("(%s)", i))
+    }
+    return ret
+}
+log := zerolog.New(output)
+
+log.Info().Str("foo", "bar").
+    Str("two", "TEST_TWO").
+    Str("one", "test_one").
+    Str("three", "test_three").
+    Msg("Hello World")
+    
+// Output: INFO   TEST_ONE test_two (test_three) Hello World foo:bar
+```
+
 ### Sub dictionary
 
 ```go
diff --git a/history-api/vendor/github.com/rs/zerolog/_config.yml b/history-api/vendor/github.com/rs/zerolog/_config.yml
deleted file mode 100644
index a1e896d7..00000000
--- a/history-api/vendor/github.com/rs/zerolog/_config.yml
+++ /dev/null
@@ -1 +0,0 @@
-remote_theme: rs/gh-readme
diff --git a/history-api/vendor/github.com/rs/zerolog/console.go b/history-api/vendor/github.com/rs/zerolog/console.go
index 7e65e86f..6c881ef6 100644
--- a/history-api/vendor/github.com/rs/zerolog/console.go
+++ b/history-api/vendor/github.com/rs/zerolog/console.go
@@ -47,6 +47,10 @@ const (
 // Formatter transforms the input into a formatted string.
 type Formatter func(interface{}) string
 
+// FormatterByFieldName transforms the input into a formatted string,
+// being able to differentiate formatting based on field name.
+type FormatterByFieldName func(interface{}, string) string
+
 // ConsoleWriter parses the JSON input and writes it in an
 // (optionally) colorized, human-friendly format to Out.
 type ConsoleWriter struct {
@@ -85,6 +89,9 @@ type ConsoleWriter struct {
 	FormatFieldValue    Formatter
 	FormatErrFieldName  Formatter
 	FormatErrFieldValue Formatter
+	// If this is configured it is used for "part" values and
+	// has precedence on FormatFieldValue
+	FormatPartValueByName FormatterByFieldName
 
 	FormatExtra func(map[string]interface{}, *bytes.Buffer) error
 
@@ -282,8 +289,9 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
 // writePart appends a formatted part to buf.
 func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{}, p string) {
 	var f Formatter
+	var fvn FormatterByFieldName
 
-	if w.PartsExclude != nil && len(w.PartsExclude) > 0 {
+	if len(w.PartsExclude) > 0 {
 		for _, exclude := range w.PartsExclude {
 			if exclude == p {
 				return
@@ -317,14 +325,21 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
 			f = w.FormatCaller
 		}
 	default:
-		if w.FormatFieldValue == nil {
-			f = consoleDefaultFormatFieldValue
-		} else {
+		if w.FormatPartValueByName != nil {
+			fvn = w.FormatPartValueByName
+		} else if w.FormatFieldValue != nil {
 			f = w.FormatFieldValue
+		} else {
+			f = consoleDefaultFormatFieldValue
 		}
 	}
 
-	var s = f(evt[p])
+	var s string
+	if f == nil {
+		s = fvn(evt[p], p)
+	} else {
+		s = f(evt[p])
+	}
 
 	if len(s) > 0 {
 		if buf.Len() > 0 {
diff --git a/history-api/vendor/github.com/rs/zerolog/log.go b/history-api/vendor/github.com/rs/zerolog/log.go
index 6c1d4ead..ea2cd62b 100644
--- a/history-api/vendor/github.com/rs/zerolog/log.go
+++ b/history-api/vendor/github.com/rs/zerolog/log.go
@@ -494,7 +494,7 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event {
 	if level != NoLevel && LevelFieldName != "" {
 		e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
 	}
-	if l.context != nil && len(l.context) > 1 {
+	if len(l.context) > 1 {
 		e.buf = enc.AppendObjectData(e.buf, l.context)
 	}
 	if l.stack {
diff --git a/history-api/vendor/github.com/rs/zerolog/sampler.go b/history-api/vendor/github.com/rs/zerolog/sampler.go
index 83ce2ed3..19e04bd4 100644
--- a/history-api/vendor/github.com/rs/zerolog/sampler.go
+++ b/history-api/vendor/github.com/rs/zerolog/sampler.go
@@ -47,6 +47,9 @@ type BasicSampler struct {
 // Sample implements the Sampler interface.
 func (s *BasicSampler) Sample(lvl Level) bool {
 	n := s.N
+	if n == 0 {
+		return false
+	}
 	if n == 1 {
 		return true
 	}
@@ -87,7 +90,7 @@ func (s *BurstSampler) inc() uint32 {
 	now := TimestampFunc().UnixNano()
 	resetAt := atomic.LoadInt64(&s.resetAt)
 	var c uint32
-	if now > resetAt {
+	if now >= resetAt {
 		c = 1
 		atomic.StoreUint32(&s.counter, c)
 		newResetAt := now + s.Period.Nanoseconds()
diff --git a/history-api/vendor/github.com/rs/zerolog/writer.go b/history-api/vendor/github.com/rs/zerolog/writer.go
index 41b394d7..0fc5ff59 100644
--- a/history-api/vendor/github.com/rs/zerolog/writer.go
+++ b/history-api/vendor/github.com/rs/zerolog/writer.go
@@ -213,6 +213,15 @@ func (w *FilteredLevelWriter) WriteLevel(level Level, p []byte) (int, error) {
 	return len(p), nil
 }
 
+// Call the underlying writer's Close method if it is an io.Closer. Otherwise
+// does nothing.
+func (w *FilteredLevelWriter) Close() error {
+	if closer, ok := w.Writer.(io.Closer); ok {
+		return closer.Close()
+	}
+	return nil
+}
+
 var triggerWriterPool = &sync.Pool{
 	New: func() interface{} {
 		return bytes.NewBuffer(make([]byte, 0, 1024))
diff --git a/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go b/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
index 0b8155aa..f13675ed 100644
--- a/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
+++ b/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -25,72 +26,77 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Add(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Add(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
 	msg, err := server.Read(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterConfigControllerHandlerServer registers the http handlers for service ConfigController to "mux".
 // UnaryRPC     :call ConfigControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterConfigControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ConfigControllerServer) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -102,20 +108,15 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -127,9 +128,7 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -156,7 +155,6 @@ func RegisterConfigControllerHandlerFromEndpoint(ctx context.Context, mux *runti
 			}
 		}()
 	}()
-
 	return RegisterConfigControllerHandler(ctx, mux, conn)
 }
 
@@ -170,16 +168,13 @@ func RegisterConfigControllerHandler(ctx context.Context, mux *runtime.ServeMux,
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ConfigControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ConfigControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "ConfigControllerClient" to call the correct interceptors.
+// "ConfigControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ConfigControllerClient) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -190,18 +185,13 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -212,22 +202,17 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_ConfigController_Add_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
-
+	pattern_ConfigController_Add_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 	pattern_ConfigController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 )
 
 var (
-	forward_ConfigController_Add_0 = runtime.ForwardResponseMessage
-
+	forward_ConfigController_Add_0  = runtime.ForwardResponseMessage
 	forward_ConfigController_Read_0 = runtime.ForwardResponseMessage
 )
diff --git a/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go b/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
index 6246b4bf..c5b245fe 100644
--- a/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
+++ b/history-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,160 +25,144 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Create(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Delete(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ListPage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ListPage(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterDetectorControllerHandlerServer registers the http handlers for service DetectorController to "mux".
 // UnaryRPC     :call DetectorControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDetectorControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DetectorControllerServer) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -189,20 +174,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -214,20 +194,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -239,9 +214,7 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -268,7 +241,6 @@ func RegisterDetectorControllerHandlerFromEndpoint(ctx context.Context, mux *run
 			}
 		}()
 	}()
-
 	return RegisterDetectorControllerHandler(ctx, mux, conn)
 }
 
@@ -282,16 +254,13 @@ func RegisterDetectorControllerHandler(ctx context.Context, mux *runtime.ServeMu
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DetectorControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DetectorControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "DetectorControllerClient" to call the correct interceptors.
+// "DetectorControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DetectorControllerClient) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -302,18 +271,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -324,18 +288,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -346,26 +305,19 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_DetectorController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
-	pattern_DetectorController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
+	pattern_DetectorController_Create_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
+	pattern_DetectorController_Delete_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
 	pattern_DetectorController_ListPage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "detector", "event-processor", "page", "page_num"}, ""))
 )
 
 var (
-	forward_DetectorController_Create_0 = runtime.ForwardResponseMessage
-
-	forward_DetectorController_Delete_0 = runtime.ForwardResponseMessage
-
+	forward_DetectorController_Create_0   = runtime.ForwardResponseMessage
+	forward_DetectorController_Delete_0   = runtime.ForwardResponseMessage
 	forward_DetectorController_ListPage_0 = runtime.ForwardResponseMessage
 )
diff --git a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
index fb4087d9..3604294e 100644
--- a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
+++ b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
@@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
+func (jt JSONTime) String() string {
+	return time.Time(jt).String()
+}
+
 type Token struct {
 	Username              string    `json:"username"`
 	UserID                string    `json:"user_id"`
@@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) {
 		return nil, errors.New("unknown authorization format")
 	}
 
-	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) {
+	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) {
 		return key, nil
 	})
 	if err != nil {
diff --git a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
index 79432fec..24b0d6e3 100644
--- a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
+++ b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
@@ -27,7 +27,7 @@ func SetReady() {
 }
 
 // ReadyHandler handles ready probes.
-func ReadyHandler(w http.ResponseWriter, r *http.Request) {
+func ReadyHandler(w http.ResponseWriter, _ *http.Request) {
 	if IsReady() {
 		// Make it simple: do nothing and have 200 OK
 		return
@@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // LiveHandler handles live probes.
-func LiveHandler(w http.ResponseWriter, r *http.Request) {
+func LiveHandler(http.ResponseWriter, *http.Request) {
 	// Make it simple: do nothing and have 200 OK
 }
diff --git a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
index cb9487d6..822eb440 100644
--- a/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
+++ b/history-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
@@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
 
 const CorrelationHeader = "correlation-id"
 
-func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	var corrID string
 
 	md, ok := metadata.FromIncomingContext(ctx)
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/.envrc b/history-api/vendor/github.com/sagikazarmark/locafero/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/history-api/vendor/github.com/sagikazarmark/locafero/.envrc
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/finder.go b/history-api/vendor/github.com/sagikazarmark/locafero/finder.go
index 754c8b26..ef8d5471 100644
--- a/history-api/vendor/github.com/sagikazarmark/locafero/finder.go
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/finder.go
@@ -27,7 +27,7 @@ type Finder struct {
 	// It provides the capability to search for entries with depth,
 	// meaning it can target deeper locations within the directory structure.
 	//
-	// It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns.
+	// It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns.
 	//
 	// Examples:
 	//   - config.yaml
@@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 			// pool.Go(func() ([]string, error) {
 			// 	// If the name contains any glob character, perform a glob match
-			// 	if strings.ContainsAny(searchName, "*?[]\\^") {
+			// 	if strings.ContainsAny(searchName, globMatch) {
 			// 		return globWalkSearch(fsys, searchPath, searchName, f.Type)
 			// 	}
 			//
@@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 	allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
 		// If the name contains any glob character, perform a glob match
-		if strings.ContainsAny(item.name, "*?[]\\^") {
+		if strings.ContainsAny(item.name, globMatch) {
 			return globWalkSearch(fsys, item.path, item.name, f.Type)
 		}
 
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/flake.lock b/history-api/vendor/github.com/sagikazarmark/locafero/flake.lock
index 46d28f80..df2a8cce 100644
--- a/history-api/vendor/github.com/sagikazarmark/locafero/flake.lock
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1725907707,
+        "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "2bbbbc468fc02257265a79652a8350651cca495a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
+        "lastModified": 1725234343,
+        "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
+        "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6",
         "type": "github"
       },
       "original": {
@@ -60,11 +138,29 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -82,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -95,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
+      "inputs": {
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
         "nixpkgs": [
           "devenv",
           "nixpkgs"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -153,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
+        "lastModified": 1725233747,
+        "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -187,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.05",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1694343207,
-        "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1725910328,
+        "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "78058d810644f5ed276804ce7ea9e82d92bee293",
+        "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4",
         "type": "github"
       },
       "original": {
@@ -217,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -232,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -249,7 +433,7 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
       }
     },
     "systems": {
@@ -266,6 +450,21 @@
         "repo": "default",
         "type": "github"
       }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/flake.nix b/history-api/vendor/github.com/sagikazarmark/locafero/flake.nix
index 209ecf28..312f1ec8 100644
--- a/history-api/vendor/github.com/sagikazarmark/locafero/flake.nix
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.lib.mkDefault pkgs.go_1_23;
             };
 
             packages = with pkgs; [
@@ -34,11 +35,27 @@
 
           ci = devenv.shells.default;
 
-          ci_1_20 = {
+          ci_1_21 = {
             imports = [ devenv.shells.ci ];
 
             languages = {
-              go.package = pkgs.go_1_20;
+              go.package = pkgs.go_1_21;
+            };
+          };
+
+          ci_1_22 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_22;
+            };
+          };
+
+          ci_1_23 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_23;
             };
           };
         };
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/glob.go b/history-api/vendor/github.com/sagikazarmark/locafero/glob.go
new file mode 100644
index 00000000..00f833e9
--- /dev/null
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/glob.go
@@ -0,0 +1,5 @@
+//go:build !windows
+
+package locafero
+
+const globMatch = "*?[]\\^"
diff --git a/history-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/history-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go
new file mode 100644
index 00000000..7aec2b24
--- /dev/null
+++ b/history-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go
@@ -0,0 +1,8 @@
+//go:build windows
+
+package locafero
+
+// See [filepath.Match]:
+//
+//	On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
+const globMatch = "*?[]^"
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/history-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
deleted file mode 100644
index 1fb0e1be..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.nix]
-indent_size = 2
-
-[{Makefile,*.mk}]
-indent_style = tab
-
-[Taskfile.yaml]
-indent_size = 2
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/.envrc b/history-api/vendor/github.com/sagikazarmark/slog-shim/.envrc
deleted file mode 100644
index 3ce7171a..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/.envrc
+++ /dev/null
@@ -1,4 +0,0 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
-fi
-use flake . --impure
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/history-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore
deleted file mode 100644
index dc6d8b58..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/.devenv/
-/.direnv/
-/.task/
-/build/
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/history-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE
deleted file mode 100644
index 6a66aea5..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/README.md b/history-api/vendor/github.com/sagikazarmark/slog-shim/README.md
deleted file mode 100644
index 1f5be85e..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# [slog](https://pkg.go.dev/log/slog) shim
-
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml)
-[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square)
-[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org)
-
-Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library.
-Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately,
-especially since updating to Go 1.21 is a decision that most libraries won't make overnight.
-
-Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog).
-While it's generally advised against using experimental packages in production,
-this one served as a sort of backport package for the last few years,
-incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`).
-
-This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`.
-
-**How does it achieve backwards compatibility?**
-
-Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is.
-(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.)
-
-This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`.
-Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly.
-
-For older Go versions, the library might become unstable after removing the shim.
-However, since those older versions are no longer supported, the promise of backward compatibility remains intact.
-
-## Installation
-
-```shell
-go get github.com/sagikazarmark/slog-shim
-```
-
-## Usage
-
-Import this package into your library and use it in your public API:
-
-```go
-package mylib
-
-import slog "github.com/sagikazarmark/slog-shim"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21):
-
-```go
-package main
-
-import "log/slog"
-
-// OR
-
-import "golang.org/x/exp/slog"
-
-mylib.New(slog.Default())
-```
-
-**Make sure consumers are aware that your API behaves differently on different Go versions.**
-
-Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code:
-
-```diff
-package mylib
-
-- import slog "github.com/sagikazarmark/slog-shim"
-+ import "log/slog"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-## License
-
-The project is licensed under a [BSD-style license](LICENSE).
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/attr.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/attr.go
deleted file mode 100644
index 89608bf3..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/attr.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
deleted file mode 100644
index b6648133..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock
deleted file mode 100644
index 7e8898e9..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock
+++ /dev/null
@@ -1,273 +0,0 @@
-{
-  "nodes": {
-    "devenv": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "flake-compat": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-parts": {
-      "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
-      },
-      "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "type": "github"
-      }
-    },
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "gitignore": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "pre-commit-hooks",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "type": "github"
-      }
-    },
-    "lowdown-src": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
-        "type": "github"
-      },
-      "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "type": "github"
-      }
-    },
-    "nix": {
-      "inputs": {
-        "lowdown-src": "lowdown-src",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "relaxed-flakes",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nixpkgs": {
-      "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-lib": {
-      "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
-        "type": "github"
-      },
-      "original": {
-        "dir": "lib",
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-stable": {
-      "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-23.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1694345580,
-        "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "master",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
-    "root": {
-      "inputs": {
-        "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    }
-  },
-  "root": "root",
-  "version": 7
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix
deleted file mode 100644
index 7239bbc2..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix
+++ /dev/null
@@ -1,57 +0,0 @@
-{
-  inputs = {
-    # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
-    nixpkgs.url = "github:NixOS/nixpkgs/master";
-    flake-parts.url = "github:hercules-ci/flake-parts";
-    devenv.url = "github:cachix/devenv";
-  };
-
-  outputs = inputs@{ flake-parts, ... }:
-    flake-parts.lib.mkFlake { inherit inputs; } {
-      imports = [
-        inputs.devenv.flakeModule
-      ];
-
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
-
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-              go.package = pkgs.lib.mkDefault pkgs.go_1_21;
-            };
-
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
-
-          ci = devenv.shells.default;
-
-          ci_1_19 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_19;
-            };
-          };
-
-          ci_1_20 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_20;
-            };
-          };
-
-          ci_1_21 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_21;
-            };
-          };
-        };
-      };
-    };
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/handler.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/handler.go
deleted file mode 100644
index f55556ae..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/handler.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
deleted file mode 100644
index 67005757..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
deleted file mode 100644
index 7c22bd81..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
deleted file mode 100644
index 7b14f10b..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/level.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/level.go
deleted file mode 100644
index 07288cf8..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/level.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go
deleted file mode 100644
index d3feb942..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/logger.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/logger.go
deleted file mode 100644
index e80036be..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/logger.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-	"log/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
deleted file mode 100644
index 97ebdd5e..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-
-	"golang.org/x/exp/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/record.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/record.go
deleted file mode 100644
index 85ad1f78..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/record.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go
deleted file mode 100644
index c2eaf4e7..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
deleted file mode 100644
index 45f6cfcb..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
deleted file mode 100644
index a69d63cc..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/value.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/value.go
deleted file mode 100644
index 61173eb9..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/value.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/history-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/history-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go
deleted file mode 100644
index 0f9f871e..00000000
--- a/history-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/history-api/vendor/github.com/spf13/cast/README.md b/history-api/vendor/github.com/spf13/cast/README.md
index 58141f02..1be666a4 100644
--- a/history-api/vendor/github.com/spf13/cast/README.md
+++ b/history-api/vendor/github.com/spf13/cast/README.md
@@ -1,9 +1,9 @@
 # cast
 
-[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast)
 ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
-[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast)
+[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast)
 
 Easy and safe casting from one type to another in Go
 
diff --git a/history-api/vendor/github.com/spf13/cast/caste.go b/history-api/vendor/github.com/spf13/cast/caste.go
index d49bbf83..4181a2e7 100644
--- a/history-api/vendor/github.com/spf13/cast/caste.go
+++ b/history-api/vendor/github.com/spf13/cast/caste.go
@@ -18,6 +18,14 @@ import (
 
 var errNegativeNotAllowed = errors.New("unable to cast negative value")
 
+type float64EProvider interface {
+	Float64() (float64, error)
+}
+
+type float64Provider interface {
+	Float64() float64
+}
+
 // ToTimeE casts an interface to a time.Time type.
 func ToTimeE(i interface{}) (tim time.Time, err error) {
 	return ToTimeInDefaultLocationE(i, time.UTC)
@@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
 			d, err = time.ParseDuration(s + "ns")
 		}
 		return
-	case json.Number:
+	case float64EProvider:
 		var v float64
 		v, err = s.Float64()
 		d = time.Duration(v)
 		return
+	case float64Provider:
+		d = time.Duration(s.Float64())
+		return
 	default:
 		err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
 		return
@@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
+	case float64Provider:
+		return s.Float64(), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
+	case float64Provider:
+		return float32(s.Float64()), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) {
 
 	switch s := i.(type) {
 	case string:
-		v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
+		v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0)
 		if err == nil {
 			if v < 0 {
 				return 0, errNegativeNotAllowed
 			}
-			return uint64(v), nil
+			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
 	case json.Number:
@@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
 		return nil
 	}
 
-	var errorType = reflect.TypeOf((*error)(nil)).Elem()
-	var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+	errorType := reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
 
 	v := reflect.ValueOf(a)
 	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
@@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
 
 // ToStringMapStringE casts an interface to a map[string]string type.
 func ToStringMapStringE(i interface{}) (map[string]string, error) {
-	var m = map[string]string{}
+	m := map[string]string{}
 
 	switch v := i.(type) {
 	case map[string]string:
@@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
 
 // ToStringMapStringSliceE casts an interface to a map[string][]string type.
 func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
-	var m = map[string][]string{}
+	m := map[string][]string{}
 
 	switch v := i.(type) {
 	case map[string][]string:
@@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
 
 // ToStringMapBoolE casts an interface to a map[string]bool type.
 func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
-	var m = map[string]bool{}
+	m := map[string]bool{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
 
 // ToStringMapE casts an interface to a map[string]interface{} type.
 func ToStringMapE(i interface{}) (map[string]interface{}, error) {
-	var m = map[string]interface{}{}
+	m := map[string]interface{}{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
 
 // ToStringMapIntE casts an interface to a map[string]int{} type.
 func ToStringMapIntE(i interface{}) (map[string]int, error) {
-	var m = map[string]int{}
+	m := map[string]int{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
 	}
@@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
 
 // ToStringMapInt64E casts an interface to a map[string]int64{} type.
 func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
-	var m = map[string]int64{}
+	m := map[string]int64{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
 	}
@@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
 	return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
 }
 
-var (
-	timeFormats = []timeFormat{
-		// Keep common formats at the top.
-		{"2006-01-02", timeFormatNoTimezone},
-		{time.RFC3339, timeFormatNumericTimezone},
-		{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
-		{time.RFC1123Z, timeFormatNumericTimezone},
-		{time.RFC1123, timeFormatNamedTimezone},
-		{time.RFC822Z, timeFormatNumericTimezone},
-		{time.RFC822, timeFormatNamedTimezone},
-		{time.RFC850, timeFormatNamedTimezone},
-		{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
-		{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
-		{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
-		{"2006-01-02 15:04:05", timeFormatNoTimezone},
-		{time.ANSIC, timeFormatNoTimezone},
-		{time.UnixDate, timeFormatNamedTimezone},
-		{time.RubyDate, timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
-		{"02 Jan 2006", timeFormatNoTimezone},
-		{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
-		{time.Kitchen, timeFormatTimeOnly},
-		{time.Stamp, timeFormatTimeOnly},
-		{time.StampMilli, timeFormatTimeOnly},
-		{time.StampMicro, timeFormatTimeOnly},
-		{time.StampNano, timeFormatTimeOnly},
-	}
-)
+var timeFormats = []timeFormat{
+	// Keep common formats at the top.
+	{"2006-01-02", timeFormatNoTimezone},
+	{time.RFC3339, timeFormatNumericTimezone},
+	{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
+	{time.RFC1123Z, timeFormatNumericTimezone},
+	{time.RFC1123, timeFormatNamedTimezone},
+	{time.RFC822Z, timeFormatNumericTimezone},
+	{time.RFC822, timeFormatNamedTimezone},
+	{time.RFC850, timeFormatNamedTimezone},
+	{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
+	{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
+	{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
+	{"2006-01-02 15:04:05", timeFormatNoTimezone},
+	{time.ANSIC, timeFormatNoTimezone},
+	{time.UnixDate, timeFormatNamedTimezone},
+	{time.RubyDate, timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
+	{"02 Jan 2006", timeFormatNoTimezone},
+	{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
+	{time.Kitchen, timeFormatTimeOnly},
+	{time.Stamp, timeFormatTimeOnly},
+	{time.StampMilli, timeFormatTimeOnly},
+	{time.StampMicro, timeFormatTimeOnly},
+	{time.StampNano, timeFormatTimeOnly},
+}
 
 func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
-
 	for _, format := range formats {
 		if d, e = time.Parse(format.format, s); e == nil {
 
diff --git a/history-api/vendor/github.com/spf13/pflag/README.md b/history-api/vendor/github.com/spf13/pflag/README.md
index 7eacc5bd..388c4e5e 100644
--- a/history-api/vendor/github.com/spf13/pflag/README.md
+++ b/history-api/vendor/github.com/spf13/pflag/README.md
@@ -284,6 +284,33 @@ func main() {
 }
 ```
 
+### Using pflag with go test
+`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`).
+For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details.
+
+For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this:
+```bash
+go test /your/tests -run ^YourTest -v --your-test-pflags
+```
+will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
+To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
+
+**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
+```go
+import (
+	goflag "flag"
+	flag "github.com/spf13/pflag"
+)
+
+var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+
+func main() {
+	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
+    flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
+	flag.Parse()
+}
+```
+
 ## More info
 
 You can see the full reference documentation of the pflag package
diff --git a/history-api/vendor/github.com/spf13/pflag/bool_func.go b/history-api/vendor/github.com/spf13/pflag/bool_func.go
new file mode 100644
index 00000000..83d77afa
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/pflag/bool_func.go
@@ -0,0 +1,40 @@
+package pflag
+
+// -- func Value
+type boolfuncValue func(string) error
+
+func (f boolfuncValue) Set(s string) error { return f(s) }
+
+func (f boolfuncValue) Type() string { return "boolfunc" }
+
+func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+func (f boolfuncValue) IsBoolFlag() bool { return true }
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) {
+	f.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	var val Value = boolfuncValue(fn)
+	flag := f.VarPF(val, name, shorthand, usage)
+	flag.NoOptDefVal = "true"
+}
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func BoolFunc(name string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, shorthand, usage, fn)
+}
diff --git a/history-api/vendor/github.com/spf13/pflag/count.go b/history-api/vendor/github.com/spf13/pflag/count.go
index a0b2679f..d49c0143 100644
--- a/history-api/vendor/github.com/spf13/pflag/count.go
+++ b/history-api/vendor/github.com/spf13/pflag/count.go
@@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
 
 // Count defines a count flag with specified name, default value, and usage string.
 // The return value is the address of an int variable that stores the value of the flag.
-// A count flag will add 1 to its value evey time it is found on the command line
+// A count flag will add 1 to its value every time it is found on the command line
 func Count(name string, usage string) *int {
 	return CommandLine.CountP(name, "", usage)
 }
diff --git a/history-api/vendor/github.com/spf13/pflag/errors.go b/history-api/vendor/github.com/spf13/pflag/errors.go
new file mode 100644
index 00000000..ff11b66b
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/pflag/errors.go
@@ -0,0 +1,149 @@
+package pflag
+
+import "fmt"
+
+// notExistErrorMessageType specifies which flavor of "flag does not exist"
+// is printed by NotExistError. This allows the related errors to be grouped
+// under a single NotExistError struct without making a breaking change to
+// the error message text.
+type notExistErrorMessageType int
+
+const (
+	flagNotExistMessage notExistErrorMessageType = iota
+	flagNotDefinedMessage
+	flagNoSuchFlagMessage
+	flagUnknownFlagMessage
+	flagUnknownShorthandFlagMessage
+)
+
+// NotExistError is the error returned when trying to access a flag that
+// does not exist in the FlagSet.
+type NotExistError struct {
+	name                string
+	specifiedShorthands string
+	messageType         notExistErrorMessageType
+}
+
+// Error implements error.
+func (e *NotExistError) Error() string {
+	switch e.messageType {
+	case flagNotExistMessage:
+		return fmt.Sprintf("flag %q does not exist", e.name)
+
+	case flagNotDefinedMessage:
+		return fmt.Sprintf("flag accessed but not defined: %s", e.name)
+
+	case flagNoSuchFlagMessage:
+		return fmt.Sprintf("no such flag -%v", e.name)
+
+	case flagUnknownFlagMessage:
+		return fmt.Sprintf("unknown flag: --%s", e.name)
+
+	case flagUnknownShorthandFlagMessage:
+		c := rune(e.name[0])
+		return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *NotExistError) GetSpecifiedName() string {
+	return e.name
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *NotExistError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// ValueRequiredError is the error returned when a flag needs an argument but
+// no argument was provided.
+type ValueRequiredError struct {
+	flag                *Flag
+	specifiedName       string
+	specifiedShorthands string
+}
+
+// Error implements error.
+func (e *ValueRequiredError) Error() string {
+	if len(e.specifiedShorthands) > 0 {
+		c := rune(e.specifiedName[0])
+		return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *ValueRequiredError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *ValueRequiredError) GetSpecifiedName() string {
+	return e.specifiedName
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *ValueRequiredError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// InvalidValueError is the error returned when an invalid value is used
+// for a flag.
+type InvalidValueError struct {
+	flag  *Flag
+	value string
+	cause error
+}
+
+// Error implements error.
+func (e *InvalidValueError) Error() string {
+	flag := e.flag
+	var flagName string
+	if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
+		flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
+	} else {
+		flagName = fmt.Sprintf("--%s", flag.Name)
+	}
+	return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
+}
+
+// Unwrap implements errors.Unwrap.
+func (e *InvalidValueError) Unwrap() error {
+	return e.cause
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *InvalidValueError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetValue returns the invalid value that was provided.
+func (e *InvalidValueError) GetValue() string {
+	return e.value
+}
+
+// InvalidSyntaxError is the error returned when a bad flag name is passed on
+// the command line.
+type InvalidSyntaxError struct {
+	specifiedFlag string
+}
+
+// Error implements error.
+func (e *InvalidSyntaxError) Error() string {
+	return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
+}
+
+// GetSpecifiedName returns the exact flag (with dashes) as it
+// appeared in the parsed arguments.
+func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
+	return e.specifiedFlag
+}
diff --git a/history-api/vendor/github.com/spf13/pflag/flag.go b/history-api/vendor/github.com/spf13/pflag/flag.go
index 7c058de3..d4dfbc5e 100644
--- a/history-api/vendor/github.com/spf13/pflag/flag.go
+++ b/history-api/vendor/github.com/spf13/pflag/flag.go
@@ -27,23 +27,32 @@ unaffected.
 Define flags using flag.String(), Bool(), Int(), etc.
 
 This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
+
 	var ip = flag.Int("flagname", 1234, "help message for flagname")
+
 If you like, you can bind the flag to a variable using the Var() functions.
+
 	var flagvar int
 	func init() {
 		flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
 	}
+
 Or you can create custom flags that satisfy the Value interface (with
 pointer receivers) and couple them to flag parsing by
+
 	flag.Var(&flagVal, "name", "help message for flagname")
+
 For such flags, the default value is just the initial value of the variable.
 
 After all flags are defined, call
+
 	flag.Parse()
+
 to parse the command line into the defined flags.
 
 Flags may then be used directly. If you're using the flags themselves,
 they are all pointers; if you bind to variables, they're values.
+
 	fmt.Println("ip has value ", *ip)
 	fmt.Println("flagvar has value ", flagvar)
 
@@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1.
 The pflag package also defines some new functions that are not in flag,
 that give one-letter shorthands for flags. You can use these by appending
 'P' to the name of any function that defines a flag.
+
 	var ip = flag.IntP("flagname", "f", 1234, "help message")
 	var flagvar bool
 	func init() {
 		flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
 	}
 	flag.VarP(&flagval, "varname", "v", "help message")
+
 Shorthand letters can be used with single dashes on the command line.
 Boolean shorthand flags can be combined with other shorthand flags.
 
 Command line flag syntax:
+
 	--flag    // boolean flags only
 	--flag=x
 
 Unlike the flag package, a single dash before an option means something
 different than a double dash. Single dashes signify a series of shorthand
 letters for flags. All but the last shorthand letter must be boolean flags.
+
 	// boolean flags
 	-f
 	-abc
@@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
 func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
 	flag := f.Lookup(name)
 	if flag == nil {
-		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
 		return nil, err
 	}
 
@@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
 func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
 func (f *FlagSet) MarkHidden(name string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	flag.Hidden = true
 	return nil
@@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 
 	err := flag.Value.Set(value)
 	if err != nil {
-		var flagName string
-		if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
-			flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
-		} else {
-			flagName = fmt.Sprintf("--%s", flag.Name)
+		return &InvalidValueError{
+			flag:  flag,
+			value: value,
+			cause: err,
 		}
-		return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
 	}
 
 	if !flag.Changed {
@@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 	if flag.Annotations == nil {
 		flag.Annotations = map[string][]string{}
@@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() {
 func (f *Flag) defaultIsZeroValue() bool {
 	switch f.Value.(type) {
 	case boolFlag:
-		return f.DefValue == "false"
+		return f.DefValue == "false" || f.DefValue == ""
 	case *durationValue:
 		// Beginning in Go 1.7, duration zero values are "0s"
 		return f.DefValue == "0" || f.DefValue == "0s"
@@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool {
 	case *intSliceValue, *stringSliceValue, *stringArrayValue:
 		return f.DefValue == "[]"
 	default:
-		switch f.Value.String() {
+		switch f.DefValue {
 		case "false":
 			return true
 		case "":
@@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
 
 	name = flag.Value.Type()
 	switch name {
-	case "bool":
+	case "bool", "boolfunc":
 		name = ""
+	case "func":
+		name = "value"
 	case "float64":
 		name = "float"
 	case "int64":
@@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 			switch flag.Value.Type() {
 			case "string":
 				line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
-			case "bool":
+			case "bool", "boolfunc":
 				if flag.NoOptDefVal != "true" {
 					line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
 				}
@@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) {
 	CommandLine.VarP(value, name, shorthand, usage)
 }
 
-// failf prints to standard error a formatted error and usage message and
+// fail prints an error message and usage message to standard error and
 // returns the error.
-func (f *FlagSet) failf(format string, a ...interface{}) error {
-	err := fmt.Errorf(format, a...)
+func (f *FlagSet) fail(err error) error {
 	if f.errorHandling != ContinueOnError {
 		fmt.Fprintln(f.Output(), err)
 		f.usage()
@@ -934,9 +946,9 @@ func (f *FlagSet) usage() {
 	}
 }
 
-//--unknown (args will be empty)
-//--unknown --next-flag ... (args will be --next-flag ...)
-//--unknown arg ... (args will be arg ...)
+// --unknown (args will be empty)
+// --unknown --next-flag ... (args will be --next-flag ...)
+// --unknown arg ... (args will be arg ...)
 func stripUnknownFlagValue(args []string) []string {
 	if len(args) == 0 {
 		//--unknown
@@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 	a = args
 	name := s[2:]
 	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
-		err = f.failf("bad flag syntax: %s", s)
+		err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
 		return
 	}
 
@@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 
 			return stripUnknownFlagValue(a), nil
 		default:
-			err = f.failf("unknown flag: --%s", name)
+			err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
 			return
 		}
 	}
@@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 		a = a[1:]
 	} else {
 		// '--flag' (arg was required)
-		err = f.failf("flag needs an argument: %s", s)
+		err = f.fail(&ValueRequiredError{
+			flag:          flag,
+			specifiedName: name,
+		})
 		return
 	}
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
 	outArgs = args
 
-	if strings.HasPrefix(shorthands, "test.") {
+	if isGotestShorthandFlag(shorthands) {
 		return
 	}
 
@@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 			outArgs = stripUnknownFlagValue(outArgs)
 			return
 		default:
-			err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
+			err = f.fail(&NotExistError{
+				name:                string(c),
+				specifiedShorthands: shorthands,
+				messageType:         flagUnknownShorthandFlagMessage,
+			})
 			return
 		}
 	}
@@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 		outArgs = args[1:]
 	} else {
 		// '-f' (arg was required)
-		err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
+		err = f.fail(&ValueRequiredError{
+			flag:                flag,
+			specifiedName:       string(c),
+			specifiedShorthands: shorthands,
+		})
 		return
 	}
 
@@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error {
 	}
 	f.parsed = true
 
-	if len(arguments) < 0 {
+	if len(arguments) == 0 {
 		return nil
 	}
 
diff --git a/history-api/vendor/github.com/spf13/pflag/func.go b/history-api/vendor/github.com/spf13/pflag/func.go
new file mode 100644
index 00000000..9f4d88f2
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/pflag/func.go
@@ -0,0 +1,37 @@
+package pflag
+
+// -- func Value
+type funcValue func(string) error
+
+func (f funcValue) Set(s string) error { return f(s) }
+
+func (f funcValue) Type() string { return "func" }
+
+func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func (f *FlagSet) Func(name string, usage string, fn func(string) error) {
+	f.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) {
+	var val Value = funcValue(fn)
+	f.VarP(val, name, shorthand, usage)
+}
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func Func(name string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func FuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, shorthand, usage, fn)
+}
diff --git a/history-api/vendor/github.com/spf13/pflag/golangflag.go b/history-api/vendor/github.com/spf13/pflag/golangflag.go
index d3dd72b7..f563907e 100644
--- a/history-api/vendor/github.com/spf13/pflag/golangflag.go
+++ b/history-api/vendor/github.com/spf13/pflag/golangflag.go
@@ -10,6 +10,15 @@ import (
 	"strings"
 )
 
+// go test flags prefixes
+func isGotestFlag(flag string) bool {
+	return strings.HasPrefix(flag, "-test.")
+}
+
+func isGotestShorthandFlag(flag string) bool {
+	return strings.HasPrefix(flag, "test.")
+}
+
 // flagValueWrapper implements pflag.Value around a flag.Value.  The main
 // difference here is the addition of the Type method that returns a string
 // name of the type.  As this is generally unknown, we approximate that with
@@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
 	}
 	f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
 }
+
+// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(),
+// since by default those are skipped by pflag.Parse().
+// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)`
+func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
+	var skippedFlags []string
+	for _, f := range osArgs {
+		if isGotestFlag(f) {
+			skippedFlags = append(skippedFlags, f)
+		}
+	}
+	return goFlagSet.Parse(skippedFlags)
+}
diff --git a/history-api/vendor/github.com/spf13/pflag/ipnet_slice.go b/history-api/vendor/github.com/spf13/pflag/ipnet_slice.go
index 6b541aa8..c6e89da1 100644
--- a/history-api/vendor/github.com/spf13/pflag/ipnet_slice.go
+++ b/history-api/vendor/github.com/spf13/pflag/ipnet_slice.go
@@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string {
 
 func ipNetSliceConv(val string) (interface{}, error) {
 	val = strings.Trim(val, "[]")
-	// Emtpy string would cause a slice with one (empty) entry
+	// Empty string would cause a slice with one (empty) entry
 	if len(val) == 0 {
 		return []net.IPNet{}, nil
 	}
diff --git a/history-api/vendor/github.com/spf13/pflag/text.go b/history-api/vendor/github.com/spf13/pflag/text.go
new file mode 100644
index 00000000..886d5a3d
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/pflag/text.go
@@ -0,0 +1,81 @@
+package pflag
+
+import (
+	"encoding"
+	"fmt"
+	"reflect"
+)
+
+// following is copied from go 1.23.4 flag.go
+type textValue struct{ p encoding.TextUnmarshaler }
+
+func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
+	ptrVal := reflect.ValueOf(p)
+	if ptrVal.Kind() != reflect.Ptr {
+		panic("variable value type must be a pointer")
+	}
+	defVal := reflect.ValueOf(val)
+	if defVal.Kind() == reflect.Ptr {
+		defVal = defVal.Elem()
+	}
+	if defVal.Type() != ptrVal.Type().Elem() {
+		panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
+	}
+	ptrVal.Elem().Set(defVal)
+	return textValue{p}
+}
+
+func (v textValue) Set(s string) error {
+	return v.p.UnmarshalText([]byte(s))
+}
+
+func (v textValue) Get() interface{} {
+	return v.p
+}
+
+func (v textValue) String() string {
+	if m, ok := v.p.(encoding.TextMarshaler); ok {
+		if b, err := m.MarshalText(); err == nil {
+			return string(b)
+		}
+	}
+	return ""
+}
+
+//end of copy
+
+func (v textValue) Type() string {
+	return reflect.ValueOf(v.p).Type().Name()
+}
+
+// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
+func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
+	flag := f.Lookup(name)
+	if flag == nil {
+		return fmt.Errorf("flag accessed but not defined: %s", name)
+	}
+	if flag.Value.Type() != reflect.TypeOf(out).Name() {
+		return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
+	}
+	return out.UnmarshalText([]byte(flag.Value.String()))
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, shorthand, usage)
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, shorthand, usage)
+}
diff --git a/history-api/vendor/github.com/spf13/pflag/time.go b/history-api/vendor/github.com/spf13/pflag/time.go
new file mode 100644
index 00000000..dc024807
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/pflag/time.go
@@ -0,0 +1,118 @@
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"time"
+)
+
+// TimeValue adapts time.Time for use as a flag.
+type timeValue struct {
+	*time.Time
+	formats []string
+}
+
+func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue {
+	*p = val
+	return &timeValue{
+		Time:    p,
+		formats: formats,
+	}
+}
+
+// Set time.Time value from string based on accepted formats.
+func (d *timeValue) Set(s string) error {
+	s = strings.TrimSpace(s)
+	for _, f := range d.formats {
+		v, err := time.Parse(f, s)
+		if err != nil {
+			continue
+		}
+		*d.Time = v
+		return nil
+	}
+
+	formatsString := ""
+	for i, f := range d.formats {
+		if i > 0 {
+			formatsString += ", "
+		}
+		formatsString += fmt.Sprintf("`%s`", f)
+	}
+
+	return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString)
+}
+
+// Type name for time.Time flags.
+func (d *timeValue) Type() string {
+	return "time"
+}
+
+func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) }
+
+// GetTime return the time value of a flag with the given name
+func (f *FlagSet) GetTime(name string) (time.Time, error) {
+	flag := f.Lookup(name)
+	if flag == nil {
+		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		return time.Time{}, err
+	}
+
+	if flag.Value.Type() != "time" {
+		err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type())
+		return time.Time{}, err
+	}
+
+	val, ok := flag.Value.(*timeValue)
+	if !ok {
+		return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value)
+	}
+
+	return *val.Time, nil
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	f.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	f.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	CommandLine.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return f.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	p := new(time.Time)
+	f.TimeVarP(p, name, shorthand, value, formats, usage)
+	return p
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, shorthand, value, formats, usage)
+}
diff --git a/history-api/vendor/github.com/spf13/viper/.envrc b/history-api/vendor/github.com/spf13/viper/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/history-api/vendor/github.com/spf13/viper/.envrc
+++ b/history-api/vendor/github.com/spf13/viper/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/history-api/vendor/github.com/spf13/viper/.golangci.yaml b/history-api/vendor/github.com/spf13/viper/.golangci.yaml
index acd9eeba..474f4163 100644
--- a/history-api/vendor/github.com/spf13/viper/.golangci.yaml
+++ b/history-api/vendor/github.com/spf13/viper/.golangci.yaml
@@ -7,8 +7,16 @@ linters-settings:
             - standard
             - default
             - prefix(github.com/spf13/viper)
-    golint:
-        min-confidence: 0
+    gocritic:
+        # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
+        enabled-tags:
+            - diagnostic
+            - experimental
+            - opinionated
+            - style
+        disabled-checks:
+            - importShadow
+            - unnamedResult
     goimports:
         local-prefixes: github.com/spf13/viper
 
@@ -20,8 +28,9 @@ linters:
         - dupl
         - durationcheck
         - exhaustive
-        - exportloopref
         - gci
+        - gocritic
+        - godot
         - gofmt
         - gofumpt
         - goimports
@@ -62,9 +71,7 @@ linters:
         # - gochecknoinits
         # - gocognit
         # - goconst
-        # - gocritic
         # - gocyclo
-        # - godot
         # - gosec
         # - gosimple
         # - ifshort
diff --git a/history-api/vendor/github.com/spf13/viper/README.md b/history-api/vendor/github.com/spf13/viper/README.md
index 78102fbe..769a5d90 100644
--- a/history-api/vendor/github.com/spf13/viper/README.md
+++ b/history-api/vendor/github.com/spf13/viper/README.md
@@ -3,7 +3,8 @@
 >
 > **Thank you!**
 
-![Viper](.github/logo.png?raw=true)
+![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e)
+
 
 [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
 [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
@@ -11,7 +12,7 @@
 [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
 [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-61CFDD.svg?style=flat-square)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
 
 **Go configuration with fangs!**
@@ -39,7 +40,7 @@ Many Go projects are built using Viper including:
 go get github.com/spf13/viper
 ```
 
-**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
+**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
 
 
 ## What is Viper?
@@ -418,7 +419,9 @@ in a Key/Value store such as etcd or Consul.  These values take precedence over
 default values, but are overridden by configuration values retrieved from disk,
 flags, or environment variables.
 
-Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
+Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
+
+Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
 configuration from the K/V store, which means that you can store your
 configuration values encrypted and have them automatically decrypted if you have
 the correct gpg keyring.  Encryption is optional.
@@ -430,7 +433,7 @@ independently of it.
 K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
 
 ```bash
-$ go get github.com/bketelsen/crypt/bin/crypt
+$ go get github.com/sagikazarmark/crypt/bin/crypt
 $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
 ```
 
@@ -563,6 +566,9 @@ 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
 has been provided.
 
+The zero value will also be returned if the value is set, but fails to parse
+as the requested type.
+
 Example:
 ```go
 viper.GetString("logfile") // case-insensitive Setting & Getting
@@ -797,7 +803,7 @@ if err != nil {
 }
 ```
 
-Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
+Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
 
 ### Decoding custom formats
 
@@ -831,13 +837,15 @@ func yamlStringSettings() string {
 
 ## Viper or Vipers?
 
-Viper comes ready to use out of the box. There is no configuration or
-initialization needed to begin using Viper. Since most applications will want
-to use a single central repository for their configuration, the viper package
-provides this. It is similar to a singleton.
+Viper comes with a global instance (singleton) out of the box.
+
+Although it makes setting up configuration easy,
+using it is generally discouraged as it makes testing harder and can lead to unexpected behavior.
+
+The best practice is to initialize a Viper instance and pass that around when necessary.
 
-In all of the examples above, they demonstrate using viper in its singleton
-style approach.
+The global instance _MAY_ be deprecated in the future.
+See [#1855](https://github.com/spf13/viper/issues/1855) for more details.
 
 ### Working with multiple vipers
 
diff --git a/history-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/history-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
index c4e36c68..b68993d4 100644
--- a/history-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
+++ b/history-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
@@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
 ```
 
 As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
-Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
+Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
 
 The solution is easy: switch to using Go Modules.
-Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that.
+Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
 
 **tl;dr* `export GO111MODULE=on`
 
diff --git a/history-api/vendor/github.com/spf13/viper/UPDATES.md b/history-api/vendor/github.com/spf13/viper/UPDATES.md
new file mode 100644
index 00000000..ccf413ed
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/UPDATES.md
@@ -0,0 +1,126 @@
+# Update Log
+
+**This document details any major updates required to use new features or improvements in Viper.**
+
+## v1.20.x
+
+### New file searching API
+
+Viper now includes a new file searching API that allows users to customize how Viper looks for config files.
+
+Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation:
+
+```go
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+```
+
+It is supposed to return a list of paths to config files.
+
+The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood.
+
+You can supply your own implementation using `WithFinder`:
+
+```go
+v := viper.NewWithOptions(
+    viper.WithFinder(&MyFinder{}),
+)
+```
+
+For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder)
+and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package.
+
+### New encoding API
+
+Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data:
+
+```go
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+```
+
+By default, Viper includes the following codecs:
+
+- JSON
+- TOML
+- YAML
+- Dotenv
+
+The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding)
+
+Customizing the encoding layer is possible by providing a custom registry of codecs:
+
+- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry)
+- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry)
+- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry)
+
+You can supply the registry of codecs to Viper using the appropriate `With*Registry` function:
+
+```go
+codecRegistry := viper.NewCodecRegistry()
+
+codecRegistry.RegisterCodec("myformat", &MyCodec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
+
+### BREAKING: HCL, Java properties, INI removed from core
+
+In order to reduce third-party dependencies, Viper dropped support for the following formats from the core:
+
+- HCL
+- Java properties
+- INI
+
+You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding):
+
+```go
+import (
+    "github.com/go-viper/encoding/hcl"
+    "github.com/go-viper/encoding/javaproperties"
+    "github.com/go-viper/encoding/ini"
+)
+
+codecRegistry := viper.NewCodecRegistry()
+
+{
+    codec := hcl.Codec{}
+
+    codecRegistry.RegisterCodec("hcl", codec)
+    codecRegistry.RegisterCodec("tfvars", codec)
+
+}
+
+{
+    codec := &javaproperties.Codec{}
+
+    codecRegistry.RegisterCodec("properties", codec)
+    codecRegistry.RegisterCodec("props", codec)
+    codecRegistry.RegisterCodec("prop", codec)
+}
+
+codecRegistry.RegisterCodec("ini", ini.Codec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
diff --git a/history-api/vendor/github.com/spf13/viper/encoding.go b/history-api/vendor/github.com/spf13/viper/encoding.go
new file mode 100644
index 00000000..a7da5586
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/encoding.go
@@ -0,0 +1,181 @@
+package viper
+
+import (
+	"errors"
+	"strings"
+	"sync"
+
+	"github.com/spf13/viper/internal/encoding/dotenv"
+	"github.com/spf13/viper/internal/encoding/json"
+	"github.com/spf13/viper/internal/encoding/toml"
+	"github.com/spf13/viper/internal/encoding/yaml"
+)
+
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+
+// TODO: consider adding specific errors for not found scenarios
+
+// EncoderRegistry returns an [Encoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [EncoderRegistry] returns an error if no [Encoder] is registered for the format.
+type EncoderRegistry interface {
+	Encoder(format string) (Encoder, error)
+}
+
+// DecoderRegistry returns an [Decoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [DecoderRegistry] returns an error if no [Decoder] is registered for the format.
+type DecoderRegistry interface {
+	Decoder(format string) (Decoder, error)
+}
+
+// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces.
+type CodecRegistry interface {
+	EncoderRegistry
+	DecoderRegistry
+}
+
+// WithEncoderRegistry sets a custom [EncoderRegistry].
+func WithEncoderRegistry(r EncoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+	})
+}
+
+// WithDecoderRegistry sets a custom [DecoderRegistry].
+func WithDecoderRegistry(r DecoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.decoderRegistry = r
+	})
+}
+
+// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry].
+func WithCodecRegistry(r CodecRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+		v.decoderRegistry = r
+	})
+}
+
+// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s.
+type DefaultCodecRegistry struct {
+	codecs map[string]Codec
+
+	mu   sync.RWMutex
+	once sync.Once
+}
+
+// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s.
+func NewCodecRegistry() *DefaultCodecRegistry {
+	r := &DefaultCodecRegistry{}
+
+	r.init()
+
+	return r
+}
+
+func (r *DefaultCodecRegistry) init() {
+	r.once.Do(func() {
+		r.codecs = map[string]Codec{}
+	})
+}
+
+// RegisterCodec registers a custom [Codec].
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error {
+	r.init()
+
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	r.codecs[strings.ToLower(format)] = codec
+
+	return nil
+}
+
+// Encoder implements the [EncoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) {
+	encoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("encoder not found for this format")
+	}
+
+	return encoder, nil
+}
+
+// Decoder implements the [DecoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) {
+	decoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("decoder not found for this format")
+	}
+
+	return decoder, nil
+}
+
+func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	format = strings.ToLower(format)
+
+	if r.codecs != nil {
+		codec, ok := r.codecs[format]
+		if ok {
+			return codec, true
+		}
+	}
+
+	switch format {
+	case "yaml", "yml":
+		return yaml.Codec{}, true
+
+	case "json":
+		return json.Codec{}, true
+
+	case "toml":
+		return toml.Codec{}, true
+
+	case "dotenv", "env":
+		return &dotenv.Codec{}, true
+	}
+
+	return nil, false
+}
diff --git a/history-api/vendor/github.com/spf13/viper/experimental.go b/history-api/vendor/github.com/spf13/viper/experimental.go
new file mode 100644
index 00000000..6e19e8a1
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/experimental.go
@@ -0,0 +1,8 @@
+package viper
+
+// ExperimentalBindStruct tells Viper to use the new bind struct feature.
+func ExperimentalBindStruct() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalBindStruct = true
+	})
+}
diff --git a/history-api/vendor/github.com/spf13/viper/file.go b/history-api/vendor/github.com/spf13/viper/file.go
new file mode 100644
index 00000000..50a40581
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/file.go
@@ -0,0 +1,104 @@
+package viper
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/sagikazarmark/locafero"
+	"github.com/spf13/afero"
+)
+
+// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files.
+func ExperimentalFinder() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalFinder = true
+	})
+}
+
+// Search for a config file.
+func (v *Viper) findConfigFile() (string, error) {
+	finder := v.finder
+
+	if finder == nil && v.experimentalFinder {
+		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,
+		}
+	}
+
+	if finder != nil {
+		return v.findConfigFileWithFinder(finder)
+	}
+
+	return v.findConfigFileOld()
+}
+
+func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) {
+	results, err := finder.Find(v.fs)
+	if err != nil {
+		return "", err
+	}
+
+	if len(results) == 0 {
+		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+	}
+
+	// We call clean on the final result to ensure that the path is in its canonical form.
+	// This is mostly for consistent path handling and to make sure tests pass.
+	return results[0], nil
+}
+
+// Search all configPaths for any config file.
+// Returns the first path that exists (and is a config file).
+func (v *Viper) findConfigFileOld() (string, error) {
+	v.logger.Info("searching for config in paths", "paths", v.configPaths)
+
+	for _, cp := range v.configPaths {
+		file := v.searchInPath(cp)
+		if file != "" {
+			return file, nil
+		}
+	}
+	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+}
+
+func (v *Viper) searchInPath(in string) (filename string) {
+	v.logger.Debug("searching for config in path", "path", in)
+	for _, ext := range SupportedExts {
+		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
+			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
+			return filepath.Join(in, v.configName+"."+ext)
+		}
+	}
+
+	if v.configType != "" {
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
+			return filepath.Join(in, v.configName)
+		}
+	}
+
+	return ""
+}
+
+// exists checks if file exists.
+func exists(fs afero.Fs, path string) (bool, error) {
+	stat, err := fs.Stat(path)
+	if err == nil {
+		return !stat.IsDir(), nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
diff --git a/history-api/vendor/github.com/spf13/viper/finder.go b/history-api/vendor/github.com/spf13/viper/finder.go
new file mode 100644
index 00000000..9b203ea6
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/finder.go
@@ -0,0 +1,55 @@
+package viper
+
+import (
+	"errors"
+
+	"github.com/spf13/afero"
+)
+
+// WithFinder sets a custom [Finder].
+func WithFinder(f Finder) Option {
+	return optionFunc(func(v *Viper) {
+		if f == nil {
+			return
+		}
+
+		v.finder = f
+	})
+}
+
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+
+// Finders combines multiple finders into one.
+func Finders(finders ...Finder) Finder {
+	return &combinedFinder{finders: finders}
+}
+
+// combinedFinder is a Finder that combines multiple finders.
+type combinedFinder struct {
+	finders []Finder
+}
+
+// Find implements the [Finder] interface.
+func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) {
+	var results []string
+	var errs []error
+
+	for _, finder := range c.finders {
+		if finder == nil {
+			continue
+		}
+
+		r, err := finder.Find(fsys)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		results = append(results, r...)
+	}
+
+	return results, errors.Join(errs...)
+}
diff --git a/history-api/vendor/github.com/spf13/viper/flags.go b/history-api/vendor/github.com/spf13/viper/flags.go
index ddb4da60..de033ed5 100644
--- a/history-api/vendor/github.com/spf13/viper/flags.go
+++ b/history-api/vendor/github.com/spf13/viper/flags.go
@@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
 }
 
 // pflagValue is a wrapper around *pflag.flag
-// that implements FlagValue
+// that implements FlagValue.
 type pflagValue struct {
 	flag *pflag.Flag
 }
diff --git a/history-api/vendor/github.com/spf13/viper/flake.lock b/history-api/vendor/github.com/spf13/viper/flake.lock
index 78da5109..d76dfbdd 100644
--- a/history-api/vendor/github.com/spf13/viper/flake.lock
+++ b/history-api/vendor/github.com/spf13/viper/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1724763216,
+        "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1687972261,
-        "narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "e85df562088573305e55906eaa964341f8cb0d9f",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1687762428,
-        "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=",
+        "lastModified": 1722555600,
+        "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836",
+        "rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
         "type": "github"
       },
       "original": {
@@ -56,12 +134,33 @@
       }
     },
     "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
       "locked": {
-        "lastModified": 1667395993,
-        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -79,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -92,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
         "nixpkgs": [
           "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
           "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -150,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1685564631,
-        "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=",
+        "lastModified": 1722555339,
+        "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -184,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1678872516,
-        "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-22.11",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1687886075,
-        "narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1724748588,
+        "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "a565059a348422af5af9026b5174dc5c0dcefdae",
+        "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99",
         "type": "github"
       },
       "original": {
@@ -214,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -229,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1686050334,
-        "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -246,7 +433,37 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
       }
     }
   },
diff --git a/history-api/vendor/github.com/spf13/viper/flake.nix b/history-api/vendor/github.com/spf13/viper/flake.nix
index 9b26c3fc..52ad7d58 100644
--- a/history-api/vendor/github.com/spf13/viper/flake.nix
+++ b/history-api/vendor/github.com/spf13/viper/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.go_1_23;
             };
 
             pre-commit.hooks = {
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go
deleted file mode 100644
index 8a7b1dbc..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Decoder decodes the contents of b into v.
-// It's primarily used for decoding contents of a file into a map[string]any.
-type Decoder interface {
-	Decode(b []byte, v map[string]any) error
-}
-
-const (
-	// ErrDecoderNotFound is returned when there is no decoder registered for a format.
-	ErrDecoderNotFound = encodingError("decoder not found for this format")
-
-	// ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
-	ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
-)
-
-// DecoderRegistry can choose an appropriate Decoder based on the provided format.
-type DecoderRegistry struct {
-	decoders map[string]Decoder
-
-	mu sync.RWMutex
-}
-
-// NewDecoderRegistry returns a new, initialized DecoderRegistry.
-func NewDecoderRegistry() *DecoderRegistry {
-	return &DecoderRegistry{
-		decoders: make(map[string]Decoder),
-	}
-}
-
-// RegisterDecoder registers a Decoder for a format.
-// Registering a Decoder for an already existing format is not supported.
-func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.decoders[format]; ok {
-		return ErrDecoderFormatAlreadyRegistered
-	}
-
-	e.decoders[format] = enc
-
-	return nil
-}
-
-// Decode calls the underlying Decoder based on the format.
-func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
-	e.mu.RLock()
-	decoder, ok := e.decoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return ErrDecoderNotFound
-	}
-
-	return decoder.Decode(b, v)
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
index 1340c730..8bfe0a9d 100644
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
+++ b/history-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
@@ -8,8 +8,8 @@ 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]any, m map[string]any, prefix string, delimiter string) map[string]any {
+// TODO: move it to a common place.
+func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go
deleted file mode 100644
index 65958596..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Encoder encodes the contents of v into a byte representation.
-// It's primarily used for encoding a map[string]any into a file format.
-type Encoder interface {
-	Encode(v map[string]any) ([]byte, error)
-}
-
-const (
-	// ErrEncoderNotFound is returned when there is no encoder registered for a format.
-	ErrEncoderNotFound = encodingError("encoder not found for this format")
-
-	// ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format.
-	ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format")
-)
-
-// EncoderRegistry can choose an appropriate Encoder based on the provided format.
-type EncoderRegistry struct {
-	encoders map[string]Encoder
-
-	mu sync.RWMutex
-}
-
-// NewEncoderRegistry returns a new, initialized EncoderRegistry.
-func NewEncoderRegistry() *EncoderRegistry {
-	return &EncoderRegistry{
-		encoders: make(map[string]Encoder),
-	}
-}
-
-// RegisterEncoder registers an Encoder for a format.
-// Registering a Encoder for an already existing format is not supported.
-func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.encoders[format]; ok {
-		return ErrEncoderFormatAlreadyRegistered
-	}
-
-	e.encoders[format] = enc
-
-	return nil
-}
-
-func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
-	e.mu.RLock()
-	encoder, ok := e.encoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return nil, ErrEncoderNotFound
-	}
-
-	return encoder.Encode(v)
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/error.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/error.go
deleted file mode 100644
index e4cde02d..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/error.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package encoding
-
-type encodingError string
-
-func (e encodingError) Error() string {
-	return string(e)
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
deleted file mode 100644
index d7fa8a1b..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package hcl
-
-import (
-	"bytes"
-	"encoding/json"
-
-	"github.com/hashicorp/hcl"
-	"github.com/hashicorp/hcl/hcl/printer"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding.
-// TODO: add printer config to the codec?
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
-	b, err := json.Marshal(v)
-	if err != nil {
-		return nil, err
-	}
-
-	// TODO: use printer.Format? Is the trailing newline an issue?
-
-	ast, err := hcl.Parse(string(b))
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-
-	err = printer.Fprint(&buf, ast.Node)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
-	return hcl.Unmarshal(b, &v)
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
deleted file mode 100644
index d91cf59d..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package ini
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/spf13/cast"
-	"gopkg.in/ini.v1"
-)
-
-// LoadOptions contains all customized options used for load data source(s).
-// This type is added here for convenience: this way consumers can import a single package called "ini".
-type LoadOptions = ini.LoadOptions
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding.
-type Codec struct {
-	KeyDelimiter string
-	LoadOptions  LoadOptions
-}
-
-func (c Codec) Encode(v map[string]any) ([]byte, error) {
-	cfg := ini.Empty()
-	ini.PrettyFormat = false
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		sectionName, keyName := "", key
-
-		lastSep := strings.LastIndex(key, ".")
-		if lastSep != -1 {
-			sectionName = key[:(lastSep)]
-			keyName = key[(lastSep + 1):]
-		}
-
-		// TODO: is this a good idea?
-		if sectionName == "default" {
-			sectionName = ""
-		}
-
-		cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
-	}
-
-	var buf bytes.Buffer
-
-	_, err := cfg.WriteTo(&buf)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (c Codec) Decode(b []byte, v map[string]any) error {
-	cfg := ini.Empty(c.LoadOptions)
-
-	err := cfg.Append(b)
-	if err != nil {
-		return err
-	}
-
-	sections := cfg.Sections()
-
-	for i := 0; i < len(sections); i++ {
-		section := sections[i]
-		keys := section.Keys()
-
-		for j := 0; j < len(keys); j++ {
-			key := keys[j]
-			value := cfg.Section(section.Name()).Key(key.Name()).String()
-
-			deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
-
-			// set innermost value
-			deepestMap[key.Name()] = value
-		}
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
deleted file mode 100644
index c1919a38..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package ini
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
deleted file mode 100644
index e92e5172..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package javaproperties
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/magiconair/properties"
-	"github.com/spf13/cast"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
-type Codec struct {
-	KeyDelimiter string
-
-	// Store read properties on the object so that we can write back in order with comments.
-	// This will only be used if the configuration read is a properties file.
-	// TODO: drop this feature in v2
-	// TODO: make use of the global properties object optional
-	Properties *properties.Properties
-}
-
-func (c *Codec) Encode(v map[string]any) ([]byte, error) {
-	if c.Properties == nil {
-		c.Properties = properties.NewProperties()
-	}
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		_, _, err := c.Properties.Set(key, cast.ToString(flattened[key]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	var buf bytes.Buffer
-
-	_, err := c.Properties.WriteComment(&buf, "#", properties.UTF8)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-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 {
-		return err
-	}
-
-	for _, key := range c.Properties.Keys() {
-		// ignore existence check: we know it's there
-		value, _ := c.Properties.Get(key)
-
-		// recursively build nested maps
-		path := strings.Split(key, c.keyDelimiter())
-		lastKey := strings.ToLower(path[len(path)-1])
-		deepestMap := deepSearch(v, path[0:len(path)-1])
-
-		// set innermost value
-		deepestMap[lastKey] = value
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
deleted file mode 100644
index 8386920a..00000000
--- a/history-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package javaproperties
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go b/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go
new file mode 100644
index 00000000..89302c21
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go
@@ -0,0 +1,5 @@
+//go:build viper_bind_struct
+
+package features
+
+const BindStruct = true
diff --git a/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go b/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
new file mode 100644
index 00000000..edfaf73b
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_bind_struct
+
+package features
+
+const BindStruct = false
diff --git a/history-api/vendor/github.com/spf13/viper/internal/features/finder.go b/history-api/vendor/github.com/spf13/viper/internal/features/finder.go
new file mode 100644
index 00000000..983ea3a9
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/internal/features/finder.go
@@ -0,0 +1,5 @@
+//go:build viper_finder
+
+package features
+
+const Finder = true
diff --git a/history-api/vendor/github.com/spf13/viper/internal/features/finder_default.go b/history-api/vendor/github.com/spf13/viper/internal/features/finder_default.go
new file mode 100644
index 00000000..89bcb06e
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/internal/features/finder_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_finder
+
+package features
+
+const Finder = false
diff --git a/history-api/vendor/github.com/spf13/viper/logger.go b/history-api/vendor/github.com/spf13/viper/logger.go
index 8938053b..828042f2 100644
--- a/history-api/vendor/github.com/spf13/viper/logger.go
+++ b/history-api/vendor/github.com/spf13/viper/logger.go
@@ -2,46 +2,9 @@ package viper
 
 import (
 	"context"
-
-	slog "github.com/sagikazarmark/slog-shim"
+	"log/slog"
 )
 
-// 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 ...any)
-
-	// Debug logs a Debug event.
-	//
-	// A verbose series of information events.
-	// They are useful when debugging the system.
-	Debug(msg string, keyvals ...any)
-
-	// Info logs an Info event.
-	//
-	// General information about what's happening inside the system.
-	Info(msg string, keyvals ...any)
-
-	// Warn logs a Warn(ing) event.
-	//
-	// Non-critical events that should be looked at.
-	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 ...any)
-}
-
 // WithLogger sets a custom logger.
 func WithLogger(l *slog.Logger) Option {
 	return optionFunc(func(v *Viper) {
diff --git a/history-api/vendor/github.com/spf13/viper/remote.go b/history-api/vendor/github.com/spf13/viper/remote.go
new file mode 100644
index 00000000..bdde7de2
--- /dev/null
+++ b/history-api/vendor/github.com/spf13/viper/remote.go
@@ -0,0 +1,256 @@
+package viper
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"slices"
+)
+
+// SupportedRemoteProviders are universally supported remote providers.
+var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+
+func resetRemote() {
+	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+}
+
+type remoteConfigFactory interface {
+	Get(rp RemoteProvider) (io.Reader, error)
+	Watch(rp RemoteProvider) (io.Reader, error)
+	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
+}
+
+type RemoteResponse struct {
+	Value []byte
+	Error error
+}
+
+// RemoteConfig is optional, see the remote package.
+var RemoteConfig remoteConfigFactory
+
+// UnsupportedRemoteProviderError denotes encountering an unsupported remote
+// provider. Currently only etcd and Consul are supported.
+type UnsupportedRemoteProviderError string
+
+// Error returns the formatted remote provider error.
+func (str UnsupportedRemoteProviderError) Error() string {
+	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
+}
+
+// RemoteConfigError denotes encountering an error while trying to
+// pull the configuration from the remote provider.
+type RemoteConfigError string
+
+// Error returns the formatted remote provider error.
+func (rce RemoteConfigError) Error() string {
+	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
+}
+
+type defaultRemoteProvider struct {
+	provider      string
+	endpoint      string
+	path          string
+	secretKeyring string
+}
+
+func (rp defaultRemoteProvider) Provider() string {
+	return rp.provider
+}
+
+func (rp defaultRemoteProvider) Endpoint() string {
+	return rp.endpoint
+}
+
+func (rp defaultRemoteProvider) Path() string {
+	return rp.path
+}
+
+func (rp defaultRemoteProvider) SecretKeyring() string {
+	return rp.secretKeyring
+}
+
+// RemoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type RemoteProvider interface {
+	Provider() string
+	Endpoint() string
+	Path() string
+	SecretKeyring() string
+}
+
+// AddRemoteProvider adds a remote configuration source.
+// Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+func AddRemoteProvider(provider, endpoint, path string) error {
+	return v.AddRemoteProvider(provider, endpoint, path)
+}
+
+func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint: endpoint,
+			provider: provider,
+			path:     path,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+// AddSecureRemoteProvider adds a remote configuration source.
+// Secure Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
+// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
+func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
+}
+
+func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint:      endpoint,
+			provider:      provider,
+			path:          path,
+			secretKeyring: secretkeyring,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
+	for _, y := range v.remoteProviders {
+		if reflect.DeepEqual(y, p) {
+			return true
+		}
+	}
+	return false
+}
+
+// ReadRemoteConfig attempts to get configuration from a remote source
+// and read it in the remote configuration registry.
+func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
+
+func (v *Viper) ReadRemoteConfig() error {
+	return v.getKeyValueConfig()
+}
+
+func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
+func (v *Viper) WatchRemoteConfig() error {
+	return v.watchKeyValueConfig()
+}
+
+func (v *Viper) WatchRemoteConfigOnChannel() error {
+	return v.watchKeyValueConfigOnChannel()
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) getKeyValueConfig() error {
+	if RemoteConfig == nil {
+		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
+	}
+
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.getRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
+
+			continue
+		}
+
+		v.kvstore = val
+
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Get(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfigOnChannel() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		respc, _ := RemoteConfig.WatchChannel(rp)
+		// Todo: Add quit channel
+		go func(rc <-chan *RemoteResponse) {
+			for {
+				b := <-rc
+				reader := bytes.NewReader(b.Value)
+				v.unmarshalReader(reader, v.kvstore)
+			}
+		}(respc)
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfig() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.watchRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
+
+			continue
+		}
+		v.kvstore = val
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Watch(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
diff --git a/history-api/vendor/github.com/spf13/viper/util.go b/history-api/vendor/github.com/spf13/viper/util.go
index 52116ac4..2a08074b 100644
--- a/history-api/vendor/github.com/spf13/viper/util.go
+++ b/history-api/vendor/github.com/spf13/viper/util.go
@@ -12,13 +12,13 @@ package viper
 
 import (
 	"fmt"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"runtime"
 	"strings"
 	"unicode"
 
-	slog "github.com/sagikazarmark/slog-shim"
 	"github.com/spf13/cast"
 )
 
@@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string {
 	return ""
 }
 
-func stringInSlice(a string, list []string) bool {
-	for _, b := range list {
-		if b == a {
-			return true
-		}
-	}
-	return false
-}
-
 func userHomeDir() string {
 	if runtime.GOOS == "windows" {
 		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
@@ -156,7 +147,7 @@ func safeMul(a, b uint) uint {
 	return c
 }
 
-// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
+// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
 func parseSizeInBytes(sizeStr string) uint {
 	sizeStr = strings.TrimSpace(sizeStr)
 	lastChar := len(sizeStr) - 1
diff --git a/history-api/vendor/github.com/spf13/viper/viper.go b/history-api/vendor/github.com/spf13/viper/viper.go
index c1eab71b..a58d757b 100644
--- a/history-api/vendor/github.com/spf13/viper/viper.go
+++ b/history-api/vendor/github.com/spf13/viper/viper.go
@@ -25,29 +25,23 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"reflect"
+	"slices"
 	"strconv"
 	"strings"
 	"sync"
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"github.com/mitchellh/mapstructure"
-	slog "github.com/sagikazarmark/slog-shim"
+	"github.com/go-viper/mapstructure/v2"
 	"github.com/spf13/afero"
 	"github.com/spf13/cast"
 	"github.com/spf13/pflag"
 
-	"github.com/spf13/viper/internal/encoding"
-	"github.com/spf13/viper/internal/encoding/dotenv"
-	"github.com/spf13/viper/internal/encoding/hcl"
-	"github.com/spf13/viper/internal/encoding/ini"
-	"github.com/spf13/viper/internal/encoding/javaproperties"
-	"github.com/spf13/viper/internal/encoding/json"
-	"github.com/spf13/viper/internal/encoding/toml"
-	"github.com/spf13/viper/internal/encoding/yaml"
+	"github.com/spf13/viper/internal/features"
 )
 
 // ConfigMarshalError happens when failing to marshal the configuration.
@@ -62,24 +56,10 @@ func (e ConfigMarshalError) Error() string {
 
 var v *Viper
 
-type RemoteResponse struct {
-	Value []byte
-	Error error
-}
-
 func init() {
 	v = New()
 }
 
-type remoteConfigFactory interface {
-	Get(rp RemoteProvider) (io.Reader, error)
-	Watch(rp RemoteProvider) (io.Reader, error)
-	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
-}
-
-// RemoteConfig is optional, see the remote package
-var RemoteConfig remoteConfigFactory
-
 // UnsupportedConfigError denotes encountering an unsupported
 // configuration filetype.
 type UnsupportedConfigError string
@@ -89,24 +69,6 @@ func (str UnsupportedConfigError) Error() string {
 	return fmt.Sprintf("Unsupported Config Type %q", string(str))
 }
 
-// UnsupportedRemoteProviderError denotes encountering an unsupported remote
-// provider. Currently only etcd and Consul are supported.
-type UnsupportedRemoteProviderError string
-
-// Error returns the formatted remote provider error.
-func (str UnsupportedRemoteProviderError) Error() string {
-	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
-}
-
-// RemoteConfigError denotes encountering an error while trying to
-// pull the configuration from the remote provider.
-type RemoteConfigError string
-
-// Error returns the formatted remote provider error
-func (rce RemoteConfigError) Error() string {
-	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
-}
-
 // ConfigFileNotFoundError denotes failing to find configuration file.
 type ConfigFileNotFoundError struct {
 	name, locations string
@@ -126,7 +88,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string {
 }
 
 // A DecoderConfigOption can be passed to viper.Unmarshal to configure
-// mapstructure.DecoderConfig options
+// mapstructure.DecoderConfig options.
 type DecoderConfigOption func(*mapstructure.DecoderConfig)
 
 // DecodeHook returns a DecoderConfigOption which overrides the default
@@ -189,6 +151,8 @@ type Viper struct {
 	// The filesystem to read config from.
 	fs afero.Fs
 
+	finder Finder
+
 	// A set of remote providers to search for the configuration
 	remoteProviders []*defaultRemoteProvider
 
@@ -199,9 +163,6 @@ type Viper struct {
 	configPermissions os.FileMode
 	envPrefix         string
 
-	// Specific commands for ini parsing
-	iniLoadOptions ini.LoadOptions
-
 	automaticEnvApplied bool
 	envKeyReplacer      StringReplacer
 	allowEmptyEnv       bool
@@ -220,9 +181,13 @@ type Viper struct {
 
 	logger *slog.Logger
 
-	// TODO: should probably be protected with a mutex
-	encoderRegistry *encoding.EncoderRegistry
-	decoderRegistry *encoding.DecoderRegistry
+	encoderRegistry EncoderRegistry
+	decoderRegistry DecoderRegistry
+
+	decodeHook mapstructure.DecodeHookFunc
+
+	experimentalFinder     bool
+	experimentalBindStruct bool
 }
 
 // New returns an initialized Viper instance.
@@ -243,7 +208,13 @@ func New() *Viper {
 	v.typeByDefValue = false
 	v.logger = slog.New(&discardHandler{})
 
-	v.resetEncoding()
+	codecRegistry := NewCodecRegistry()
+
+	v.encoderRegistry = codecRegistry
+	v.decoderRegistry = codecRegistry
+
+	v.experimentalFinder = features.Finder
+	v.experimentalBindStruct = features.BindStruct
 
 	return v
 }
@@ -279,10 +250,25 @@ type StringReplacer interface {
 // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys.
 func EnvKeyReplacer(r StringReplacer) Option {
 	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
 		v.envKeyReplacer = r
 	})
 }
 
+// WithDecodeHook sets a default decode hook for mapstructure.
+func WithDecodeHook(h mapstructure.DecodeHookFunc) Option {
+	return optionFunc(func(v *Viper) {
+		if h == nil {
+			return
+		}
+
+		v.decodeHook = h
+	})
+}
+
 // NewWithOptions creates a new Viper instance.
 func NewWithOptions(opts ...Option) *Viper {
 	v := New()
@@ -291,138 +277,32 @@ func NewWithOptions(opts ...Option) *Viper {
 		opt.apply(v)
 	}
 
-	v.resetEncoding()
-
 	return v
 }
 
+// SetOptions sets the options on the global Viper instance.
+//
+// Be careful when using this function: subsequent calls may override options you set.
+// It's always better to use a local Viper instance.
+func SetOptions(opts ...Option) {
+	for _, opt := range opts {
+		opt.apply(v)
+	}
+}
+
 // Reset is intended for testing, will reset all to default settings.
 // In the public interface for the viper package so applications
 // can use it in their testing as well.
 func Reset() {
 	v = New()
 	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
-	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-}
-
-// TODO: make this lazy initialization instead
-func (v *Viper) resetEncoding() {
-	encoderRegistry := encoding.NewEncoderRegistry()
-	decoderRegistry := encoding.NewDecoderRegistry()
-
-	{
-		codec := yaml.Codec{}
-
-		encoderRegistry.RegisterEncoder("yaml", codec)
-		decoderRegistry.RegisterDecoder("yaml", codec)
-
-		encoderRegistry.RegisterEncoder("yml", codec)
-		decoderRegistry.RegisterDecoder("yml", codec)
-	}
-
-	{
-		codec := json.Codec{}
-
-		encoderRegistry.RegisterEncoder("json", codec)
-		decoderRegistry.RegisterDecoder("json", codec)
-	}
-
-	{
-		codec := toml.Codec{}
-
-		encoderRegistry.RegisterEncoder("toml", codec)
-		decoderRegistry.RegisterDecoder("toml", codec)
-	}
-
-	{
-		codec := hcl.Codec{}
-
-		encoderRegistry.RegisterEncoder("hcl", codec)
-		decoderRegistry.RegisterDecoder("hcl", codec)
-
-		encoderRegistry.RegisterEncoder("tfvars", codec)
-		decoderRegistry.RegisterDecoder("tfvars", codec)
-	}
-
-	{
-		codec := ini.Codec{
-			KeyDelimiter: v.keyDelim,
-			LoadOptions:  v.iniLoadOptions,
-		}
-
-		encoderRegistry.RegisterEncoder("ini", codec)
-		decoderRegistry.RegisterDecoder("ini", codec)
-	}
-
-	{
-		codec := &javaproperties.Codec{
-			KeyDelimiter: v.keyDelim,
-		}
-
-		encoderRegistry.RegisterEncoder("properties", codec)
-		decoderRegistry.RegisterDecoder("properties", codec)
-
-		encoderRegistry.RegisterEncoder("props", codec)
-		decoderRegistry.RegisterDecoder("props", codec)
-
-		encoderRegistry.RegisterEncoder("prop", codec)
-		decoderRegistry.RegisterDecoder("prop", codec)
-	}
-
-	{
-		codec := &dotenv.Codec{}
 
-		encoderRegistry.RegisterEncoder("dotenv", codec)
-		decoderRegistry.RegisterDecoder("dotenv", codec)
-
-		encoderRegistry.RegisterEncoder("env", codec)
-		decoderRegistry.RegisterDecoder("env", codec)
-	}
-
-	v.encoderRegistry = encoderRegistry
-	v.decoderRegistry = decoderRegistry
-}
-
-type defaultRemoteProvider struct {
-	provider      string
-	endpoint      string
-	path          string
-	secretKeyring string
-}
-
-func (rp defaultRemoteProvider) Provider() string {
-	return rp.provider
-}
-
-func (rp defaultRemoteProvider) Endpoint() string {
-	return rp.endpoint
-}
-
-func (rp defaultRemoteProvider) Path() string {
-	return rp.path
-}
-
-func (rp defaultRemoteProvider) SecretKeyring() string {
-	return rp.secretKeyring
-}
-
-// RemoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type RemoteProvider interface {
-	Provider() string
-	Endpoint() string
-	Path() string
-	SecretKeyring() string
+	resetRemote()
 }
 
 // SupportedExts are universally supported extensions.
 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
 
-// SupportedRemoteProviders are universally supported remote providers.
-var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-
 // OnConfigChange sets the event handler that is called when a config file changes.
 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
 
@@ -439,7 +319,7 @@ func (v *Viper) WatchConfig() {
 	initWG := sync.WaitGroup{}
 	initWG.Add(1)
 	go func() {
-		watcher, err := newWatcher()
+		watcher, err := fsnotify.NewWatcher()
 		if err != nil {
 			v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
 			os.Exit(1)
@@ -573,90 +453,20 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile }
 func AddConfigPath(in string) { v.AddConfigPath(in) }
 
 func (v *Viper) AddConfigPath(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath"))
+	}
+
 	if in != "" {
 		absin := absPathify(v.logger, in)
 
 		v.logger.Info("adding path to search paths", "path", absin)
-		if !stringInSlice(absin, v.configPaths) {
+		if !slices.Contains(v.configPaths, absin) {
 			v.configPaths = append(v.configPaths, absin)
 		}
 	}
 }
 
-// AddRemoteProvider adds a remote configuration source.
-// Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-func AddRemoteProvider(provider, endpoint, path string) error {
-	return v.AddRemoteProvider(provider, endpoint, path)
-}
-
-func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint: endpoint,
-			provider: provider,
-			path:     path,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-// AddSecureRemoteProvider adds a remote configuration source.
-// Secure Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
-// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-// Secure Remote Providers are implemented with github.com/bketelsen/crypt
-func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
-}
-
-func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint:      endpoint,
-			provider:      provider,
-			path:          path,
-			secretKeyring: secretkeyring,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
-	for _, y := range v.remoteProviders {
-		if reflect.DeepEqual(y, p) {
-			return true
-		}
-	}
-	return false
-}
-
 // 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.
@@ -827,10 +637,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string
 //	"foo.bar.baz" in a lower-priority map
 func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
 	// unify input map
-	var m map[string]any
-	switch mi.(type) {
-	case map[string]string, map[string]FlagValue:
-		m = cast.ToStringMap(mi)
+	var m map[string]interface{}
+	switch miv := mi.(type) {
+	case map[string]string:
+		m = castMapStringToMapInterface(miv)
+	case map[string]FlagValue:
+		m = castMapFlagToMapInterface(miv)
 	default:
 		return ""
 	}
@@ -957,10 +769,12 @@ func (v *Viper) Sub(key string) *Viper {
 	}
 
 	if reflect.TypeOf(data).Kind() == reflect.Map {
-		subv.parents = append(v.parents, strings.ToLower(key))
+		subv.parents = append([]string(nil), v.parents...)
+		subv.parents = append(subv.parents, strings.ToLower(key))
 		subv.automaticEnvApplied = v.automaticEnvApplied
 		subv.envPrefix = v.envPrefix
 		subv.envKeyReplacer = v.envKeyReplacer
+		subv.keyDelim = v.keyDelim
 		subv.config = cast.ToStringMap(data)
 		return subv
 	}
@@ -1002,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 {
 	return cast.ToInt64(v.Get(key))
 }
 
+// GetUint8 returns the value associated with the key as an unsigned integer.
+func GetUint8(key string) uint8 { return v.GetUint8(key) }
+
+func (v *Viper) GetUint8(key string) uint8 {
+	return cast.ToUint8(v.Get(key))
+}
+
 // GetUint returns the value associated with the key as an unsigned integer.
 func GetUint(key string) uint { return v.GetUint(key) }
 
@@ -1101,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
+	return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...))
 }
 
 // Unmarshal unmarshals the config into a Struct. Make sure that the tags
@@ -1111,28 +932,91 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...))
+}
+
+func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
+	var structKeyMap map[string]any
+
+	err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...))
+	if err != nil {
+		return nil, err
+	}
+
+	flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
+
+	r := make([]string, 0, len(flattenedStructKeyMap))
+	for v := range flattenedStructKeyMap {
+		r = append(r, v)
+	}
+
+	return r, nil
 }
 
 // defaultDecoderConfig returns default mapstructure.DecoderConfig with support
-// of time.Duration values & string slices
-func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+// of time.Duration values & string slices.
+func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+	decodeHook := v.decodeHook
+	if decodeHook == nil {
+		decodeHook = mapstructure.ComposeDecodeHookFunc(
+			mapstructure.StringToTimeDurationHookFunc(),
+			// mapstructure.StringToSliceHookFunc(","),
+			stringToWeakSliceHookFunc(","),
+		)
+	}
+
 	c := &mapstructure.DecoderConfig{
 		Metadata:         nil,
-		Result:           output,
 		WeaklyTypedInput: true,
-		DecodeHook: mapstructure.ComposeDecodeHookFunc(
-			mapstructure.StringToTimeDurationHookFunc(),
-			mapstructure.StringToSliceHookFunc(","),
-		),
+		DecodeHook:       decodeHook,
 	}
+
 	for _, opt := range opts {
 		opt(c)
 	}
+
+	// Do not allow overwriting the output
+	c.Result = output
+
 	return c
 }
 
-// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
+// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice.
+// This function removes that check.
+// TODO: implement a function that checks if the value can be converted to the return type and use it instead.
+func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data interface{},
+	) (interface{}, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
+// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
 func decode(input any, config *mapstructure.DecoderConfig) error {
 	decoder, err := mapstructure.NewDecoder(config)
 	if err != nil {
@@ -1148,10 +1032,23 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
-	config := defaultDecoderConfig(rawVal, opts...)
+	config := v.defaultDecoderConfig(rawVal, opts...)
 	config.ErrorUnused = true
 
-	return decode(v.AllSettings(), config)
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), config)
 }
 
 // BindPFlags binds a full flag set to the configuration, using each flag's long
@@ -1405,11 +1302,11 @@ 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	r := csv.NewReader(strings.NewReader(val))
@@ -1429,11 +1326,11 @@ func stringToStringConv(val string) any {
 }
 
 // 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	ss := strings.Split(val, ",")
@@ -1481,13 +1378,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
 
 // RegisterAlias creates an alias that provides another accessor for the same key.
 // This enables one to change a name without breaking the application.
-func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
+func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
 
-func (v *Viper) RegisterAlias(alias string, key string) {
+func (v *Viper) RegisterAlias(alias, key string) {
 	v.registerAlias(alias, strings.ToLower(key))
 }
 
-func (v *Viper) registerAlias(alias string, key string) {
+func (v *Viper) registerAlias(alias, key string) {
 	alias = strings.ToLower(alias)
 	if alias != key && alias != v.realKey(key) {
 		_, exists := v.aliases[alias]
@@ -1590,7 +1487,7 @@ func (v *Viper) ReadInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1621,7 +1518,7 @@ func (v *Viper) MergeInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1638,19 +1535,29 @@ 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]any)
-	return v.unmarshalReader(in, v.config)
+	config := make(map[string]any)
+
+	err := v.unmarshalReader(in, config)
+	if err != nil {
+		return err
+	}
+
+	v.config = config
+
+	return nil
 }
 
 // MergeConfig merges a new configuration with an existing config.
 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
 
 func (v *Viper) MergeConfig(in io.Reader) error {
-	cfg := make(map[string]any)
-	if err := v.unmarshalReader(in, cfg); err != nil {
+	config := make(map[string]any)
+
+	if err := v.unmarshalReader(in, config); err != nil {
 		return err
 	}
-	return v.MergeConfigMap(cfg)
+
+	return v.MergeConfigMap(config)
 }
 
 // MergeConfigMap merges the configuration from the map given with an existing config.
@@ -1694,6 +1601,19 @@ func (v *Viper) WriteConfigAs(filename string) error {
 	return v.writeConfig(filename, true)
 }
 
+// WriteConfigTo writes current configuration to an [io.Writer].
+func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) }
+
+func (v *Viper) WriteConfigTo(w io.Writer) error {
+	format := strings.ToLower(v.getConfigType())
+
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	return v.marshalWriter(w, format)
+}
+
 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
 
@@ -1720,7 +1640,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 		return fmt.Errorf("config type could not be determined for %s", filename)
 	}
 
-	if !stringInSlice(configType, SupportedExts) {
+	if !slices.Contains(SupportedExts, configType) {
 		return UnsupportedConfigError(configType)
 	}
 	if v.config == nil {
@@ -1743,22 +1663,30 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 	return f.Sync()
 }
 
-// Unmarshal a Reader into a map.
-// Should probably be an unexported function.
-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]any) error {
+	format := strings.ToLower(v.getConfigType())
+	if format == "" {
+		return errors.New("cannot decode configuration: unable to determine config type")
+	}
+
 	buf := new(bytes.Buffer)
 	buf.ReadFrom(in)
 
-	switch format := strings.ToLower(v.getConfigType()); format {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
-		err := v.decoderRegistry.Decode(format, buf.Bytes(), c)
-		if err != nil {
-			return ConfigParseError{err}
-		}
+	// TODO: remove this once SupportedExts is deprecated/removed
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	// TODO: return [UnsupportedConfigError] if the registry does not contain the format
+	// TODO: consider deprecating this error type
+	decoder, err := v.decoderRegistry.Decoder(format)
+	if err != nil {
+		return ConfigParseError{err}
+	}
+
+	err = decoder.Decode(buf.Bytes(), c)
+	if err != nil {
+		return ConfigParseError{err}
 	}
 
 	insensitiviseMap(c)
@@ -1766,20 +1694,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
 }
 
 // Marshal a map into Writer.
-func (v *Viper) marshalWriter(f afero.File, configType string) error {
+func (v *Viper) marshalWriter(w io.Writer, configType string) error {
 	c := v.AllSettings()
-	switch configType {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
-		b, err := v.encoderRegistry.Encode(configType, c)
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
 
-		_, err = f.WriteString(string(b))
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
+	encoder, err := v.encoderRegistry.Encoder(configType)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	b, err := encoder.Encode(c)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	_, err = w.Write(b)
+	if err != nil {
+		return ConfigMarshalError{err}
 	}
+
 	return nil
 }
 
@@ -1911,108 +1843,8 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
 	}
 }
 
-// ReadRemoteConfig attempts to get configuration from a remote source
-// and read it in the remote configuration registry.
-func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
-
-func (v *Viper) ReadRemoteConfig() error {
-	return v.getKeyValueConfig()
-}
-
-func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
-func (v *Viper) WatchRemoteConfig() error {
-	return v.watchKeyValueConfig()
-}
-
-func (v *Viper) WatchRemoteConfigOnChannel() error {
-	return v.watchKeyValueConfigOnChannel()
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) getKeyValueConfig() error {
-	if RemoteConfig == nil {
-		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
-	}
-
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.getRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
-
-			continue
-		}
-
-		v.kvstore = val
-
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Get(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfigOnChannel() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		respc, _ := RemoteConfig.WatchChannel(rp)
-		// Todo: Add quit channel
-		go func(rc <-chan *RemoteResponse) {
-			for {
-				b := <-rc
-				reader := bytes.NewReader(b.Value)
-				v.unmarshalReader(reader, v.kvstore)
-			}
-		}(respc)
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfig() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.watchRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
-
-			continue
-		}
-		v.kvstore = val
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Watch(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
 // AllKeys returns all keys holding a value, regardless of where they are set.
-// Nested keys are returned with a v.keyDelim separator
+// Nested keys are returned with a v.keyDelim separator.
 func AllKeys() []string { return v.AllKeys() }
 
 func (v *Viper) AllKeys() []string {
@@ -2098,9 +1930,13 @@ outer:
 func AllSettings() map[string]any { return v.AllSettings() }
 
 func (v *Viper) AllSettings() map[string]any {
+	return v.getSettings(v.AllKeys())
+}
+
+func (v *Viper) getSettings(keys []string) 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() {
+	for _, k := range keys {
 		value := v.Get(k)
 		if value == nil {
 			// should not happen, since AllKeys() returns only keys holding a value,
@@ -2128,6 +1964,10 @@ func (v *Viper) SetFs(fs afero.Fs) {
 func SetConfigName(in string) { v.SetConfigName(in) }
 
 func (v *Viper) SetConfigName(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName"))
+	}
+
 	if in != "" {
 		v.configName = in
 		v.configFile = ""
@@ -2151,13 +1991,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) {
 	v.configPermissions = perm.Perm()
 }
 
-// IniLoadOptions sets the load options for ini parsing.
-func IniLoadOptions(in ini.LoadOptions) Option {
-	return optionFunc(func(v *Viper) {
-		v.iniLoadOptions = in
-	})
-}
-
 func (v *Viper) getConfigType() string {
 	if v.configType != "" {
 		return v.configType
diff --git a/history-api/vendor/github.com/spf13/viper/viper_go1_15.go b/history-api/vendor/github.com/spf13/viper/viper_go1_15.go
deleted file mode 100644
index 7fc6aff3..00000000
--- a/history-api/vendor/github.com/spf13/viper/viper_go1_15.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build !finder
-
-package viper
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-
-	"github.com/spf13/afero"
-)
-
-// Search all configPaths for any config file.
-// Returns the first path that exists (and is a config file).
-func (v *Viper) findConfigFile() (string, error) {
-	v.logger.Info("searching for config in paths", "paths", v.configPaths)
-
-	for _, cp := range v.configPaths {
-		file := v.searchInPath(cp)
-		if file != "" {
-			return file, nil
-		}
-	}
-	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-}
-
-func (v *Viper) searchInPath(in string) (filename string) {
-	v.logger.Debug("searching for config in path", "path", in)
-	for _, ext := range SupportedExts {
-		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
-			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
-			return filepath.Join(in, v.configName+"."+ext)
-		}
-	}
-
-	if v.configType != "" {
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
-			return filepath.Join(in, v.configName)
-		}
-	}
-
-	return ""
-}
-
-// Check if file Exists
-func exists(fs afero.Fs, path string) (bool, error) {
-	stat, err := fs.Stat(path)
-	if err == nil {
-		return !stat.IsDir(), nil
-	}
-	if os.IsNotExist(err) {
-		return false, nil
-	}
-	return false, err
-}
diff --git a/history-api/vendor/github.com/spf13/viper/viper_go1_16.go b/history-api/vendor/github.com/spf13/viper/viper_go1_16.go
deleted file mode 100644
index d96a1bd2..00000000
--- a/history-api/vendor/github.com/spf13/viper/viper_go1_16.go
+++ /dev/null
@@ -1,38 +0,0 @@
-//go:build finder
-
-package viper
-
-import (
-	"fmt"
-
-	"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) {
-	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,
-	}
-
-	results, err := finder.Find(v.fs)
-	if err != nil {
-		return "", err
-	}
-
-	if len(results) == 0 {
-		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-	}
-
-	return results[0], nil
-}
diff --git a/history-api/vendor/github.com/spf13/viper/watch.go b/history-api/vendor/github.com/spf13/viper/watch.go
deleted file mode 100644
index e98fce89..00000000
--- a/history-api/vendor/github.com/spf13/viper/watch.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
-
-package viper
-
-import "github.com/fsnotify/fsnotify"
-
-type watcher = fsnotify.Watcher
-
-func newWatcher() (*watcher, error) {
-	return fsnotify.NewWatcher()
-}
diff --git a/history-api/vendor/github.com/spf13/viper/watch_unsupported.go b/history-api/vendor/github.com/spf13/viper/watch_unsupported.go
deleted file mode 100644
index 70764056..00000000
--- a/history-api/vendor/github.com/spf13/viper/watch_unsupported.go
+++ /dev/null
@@ -1,31 +0,0 @@
-//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
-
-package viper
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/fsnotify/fsnotify"
-)
-
-func newWatcher() (*watcher, error) {
-	return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-type watcher struct {
-	Events chan fsnotify.Event
-	Errors chan error
-}
-
-func (*watcher) Close() error {
-	return nil
-}
-
-func (*watcher) Add(name string) error {
-	return nil
-}
-
-func (*watcher) Remove(name string) error {
-	return nil
-}
diff --git a/history-api/vendor/go.opentelemetry.io/otel/attribute/filter.go b/history-api/vendor/go.opentelemetry.io/otel/attribute/filter.go
index be9cd922..3eeaa5d4 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/attribute/filter.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/attribute/filter.go
@@ -19,7 +19,7 @@ func NewAllowKeysFilter(keys ...Key) Filter {
 		return func(kv KeyValue) bool { return false }
 	}
 
-	allowed := make(map[Key]struct{})
+	allowed := make(map[Key]struct{}, len(keys))
 	for _, k := range keys {
 		allowed[k] = struct{}{}
 	}
@@ -38,7 +38,7 @@ func NewDenyKeysFilter(keys ...Key) Filter {
 		return func(kv KeyValue) bool { return true }
 	}
 
-	forbid := make(map[Key]struct{})
+	forbid := make(map[Key]struct{}, len(keys))
 	for _, k := range keys {
 		forbid[k] = struct{}{}
 	}
diff --git a/history-api/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go b/history-api/vendor/go.opentelemetry.io/otel/attribute/internal/attribute.go
similarity index 97%
rename from history-api/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go
rename to history-api/vendor/go.opentelemetry.io/otel/attribute/internal/attribute.go
index 691d96c7..b76d2bbf 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/attribute/internal/attribute.go
@@ -5,7 +5,7 @@
 Package attribute provide several helper functions for some commonly used
 logic of processing attributes.
 */
-package attribute // import "go.opentelemetry.io/otel/internal/attribute"
+package attribute // import "go.opentelemetry.io/otel/attribute/internal"
 
 import (
 	"reflect"
diff --git a/history-api/vendor/go.opentelemetry.io/otel/attribute/rawhelpers.go b/history-api/vendor/go.opentelemetry.io/otel/attribute/rawhelpers.go
new file mode 100644
index 00000000..5791c6e7
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/attribute/rawhelpers.go
@@ -0,0 +1,37 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package attribute // import "go.opentelemetry.io/otel/attribute"
+
+import (
+	"math"
+)
+
+func boolToRaw(b bool) uint64 { // nolint:revive  // b is not a control flag.
+	if b {
+		return 1
+	}
+	return 0
+}
+
+func rawToBool(r uint64) bool {
+	return r != 0
+}
+
+func int64ToRaw(i int64) uint64 {
+	// Assumes original was a valid int64 (overflow not checked).
+	return uint64(i) // nolint: gosec
+}
+
+func rawToInt64(r uint64) int64 {
+	// Assumes original was a valid int64 (overflow not checked).
+	return int64(r) // nolint: gosec
+}
+
+func float64ToRaw(f float64) uint64 {
+	return math.Float64bits(f)
+}
+
+func rawToFloat64(r uint64) float64 {
+	return math.Float64frombits(r)
+}
diff --git a/history-api/vendor/go.opentelemetry.io/otel/attribute/value.go b/history-api/vendor/go.opentelemetry.io/otel/attribute/value.go
index 9ea0ecbb..817eecac 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/attribute/value.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/attribute/value.go
@@ -9,8 +9,7 @@ import (
 	"reflect"
 	"strconv"
 
-	"go.opentelemetry.io/otel/internal"
-	"go.opentelemetry.io/otel/internal/attribute"
+	attribute "go.opentelemetry.io/otel/attribute/internal"
 )
 
 //go:generate stringer -type=Type
@@ -51,7 +50,7 @@ const (
 func BoolValue(v bool) Value {
 	return Value{
 		vtype:   BOOL,
-		numeric: internal.BoolToRaw(v),
+		numeric: boolToRaw(v),
 	}
 }
 
@@ -82,7 +81,7 @@ func IntSliceValue(v []int) Value {
 func Int64Value(v int64) Value {
 	return Value{
 		vtype:   INT64,
-		numeric: internal.Int64ToRaw(v),
+		numeric: int64ToRaw(v),
 	}
 }
 
@@ -95,7 +94,7 @@ func Int64SliceValue(v []int64) Value {
 func Float64Value(v float64) Value {
 	return Value{
 		vtype:   FLOAT64,
-		numeric: internal.Float64ToRaw(v),
+		numeric: float64ToRaw(v),
 	}
 }
 
@@ -125,7 +124,7 @@ func (v Value) Type() Type {
 // AsBool returns the bool value. Make sure that the Value's type is
 // BOOL.
 func (v Value) AsBool() bool {
-	return internal.RawToBool(v.numeric)
+	return rawToBool(v.numeric)
 }
 
 // AsBoolSlice returns the []bool value. Make sure that the Value's type is
@@ -144,7 +143,7 @@ func (v Value) asBoolSlice() []bool {
 // AsInt64 returns the int64 value. Make sure that the Value's type is
 // INT64.
 func (v Value) AsInt64() int64 {
-	return internal.RawToInt64(v.numeric)
+	return rawToInt64(v.numeric)
 }
 
 // AsInt64Slice returns the []int64 value. Make sure that the Value's type is
@@ -163,7 +162,7 @@ func (v Value) asInt64Slice() []int64 {
 // AsFloat64 returns the float64 value. Make sure that the Value's
 // type is FLOAT64.
 func (v Value) AsFloat64() float64 {
-	return internal.RawToFloat64(v.numeric)
+	return rawToFloat64(v.numeric)
 }
 
 // AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
diff --git a/history-api/vendor/go.opentelemetry.io/otel/internal/gen.go b/history-api/vendor/go.opentelemetry.io/otel/internal/gen.go
deleted file mode 100644
index 4259f032..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/internal/gen.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-package internal // import "go.opentelemetry.io/otel/internal"
-
-//go:generate gotmpl --body=./shared/matchers/expectation.go.tmpl "--data={}" --out=matchers/expectation.go
-//go:generate gotmpl --body=./shared/matchers/expecter.go.tmpl "--data={}" --out=matchers/expecter.go
-//go:generate gotmpl --body=./shared/matchers/temporal_matcher.go.tmpl "--data={}" --out=matchers/temporal_matcher.go
-
-//go:generate gotmpl --body=./shared/internaltest/alignment.go.tmpl "--data={}" --out=internaltest/alignment.go
-//go:generate gotmpl --body=./shared/internaltest/env.go.tmpl "--data={}" --out=internaltest/env.go
-//go:generate gotmpl --body=./shared/internaltest/env_test.go.tmpl "--data={}" --out=internaltest/env_test.go
-//go:generate gotmpl --body=./shared/internaltest/errors.go.tmpl "--data={}" --out=internaltest/errors.go
-//go:generate gotmpl --body=./shared/internaltest/harness.go.tmpl "--data={\"matchersImportPath\": \"go.opentelemetry.io/otel/internal/matchers\"}" --out=internaltest/harness.go
-//go:generate gotmpl --body=./shared/internaltest/text_map_carrier.go.tmpl "--data={}" --out=internaltest/text_map_carrier.go
-//go:generate gotmpl --body=./shared/internaltest/text_map_carrier_test.go.tmpl "--data={}" --out=internaltest/text_map_carrier_test.go
-//go:generate gotmpl --body=./shared/internaltest/text_map_propagator.go.tmpl "--data={}" --out=internaltest/text_map_propagator.go
-//go:generate gotmpl --body=./shared/internaltest/text_map_propagator_test.go.tmpl "--data={}" --out=internaltest/text_map_propagator_test.go
diff --git a/history-api/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go b/history-api/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
deleted file mode 100644
index b2fe3e41..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-package internal // import "go.opentelemetry.io/otel/internal"
-
-import (
-	"math"
-	"unsafe"
-)
-
-func BoolToRaw(b bool) uint64 { // nolint:revive  // b is not a control flag.
-	if b {
-		return 1
-	}
-	return 0
-}
-
-func RawToBool(r uint64) bool {
-	return r != 0
-}
-
-func Int64ToRaw(i int64) uint64 {
-	// Assumes original was a valid int64 (overflow not checked).
-	return uint64(i) // nolint: gosec
-}
-
-func RawToInt64(r uint64) int64 {
-	// Assumes original was a valid int64 (overflow not checked).
-	return int64(r) // nolint: gosec
-}
-
-func Float64ToRaw(f float64) uint64 {
-	return math.Float64bits(f)
-}
-
-func RawToFloat64(r uint64) float64 {
-	return math.Float64frombits(r)
-}
-
-func RawPtrToFloat64Ptr(r *uint64) *float64 {
-	// Assumes original was a valid *float64 (overflow not checked).
-	return (*float64)(unsafe.Pointer(r)) // nolint: gosec
-}
-
-func RawPtrToInt64Ptr(r *uint64) *int64 {
-	// Assumes original was a valid *int64 (overflow not checked).
-	return (*int64)(unsafe.Pointer(r)) // nolint: gosec
-}
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/README.md b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/README.md
deleted file mode 100644
index 2de1fc3c..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Semconv v1.26.0
-
-[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.26.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.26.0)
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/attribute_group.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/attribute_group.go
deleted file mode 100644
index d8dc822b..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/attribute_group.go
+++ /dev/null
@@ -1,8996 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated from semantic convention specification. DO NOT EDIT.
-
-package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
-
-import "go.opentelemetry.io/otel/attribute"
-
-// The Android platform on which the Android application is running.
-const (
-	// AndroidOSAPILevelKey is the attribute Key conforming to the
-	// "android.os.api_level" semantic conventions. It represents the uniquely
-	// identifies the framework API revision offered by a version
-	// (`os.version`) of the android operating system. More information can be
-	// found
-	// [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '33', '32'
-	AndroidOSAPILevelKey = attribute.Key("android.os.api_level")
-)
-
-// AndroidOSAPILevel returns an attribute KeyValue conforming to the
-// "android.os.api_level" semantic conventions. It represents the uniquely
-// identifies the framework API revision offered by a version (`os.version`) of
-// the android operating system. More information can be found
-// [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels).
-func AndroidOSAPILevel(val string) attribute.KeyValue {
-	return AndroidOSAPILevelKey.String(val)
-}
-
-// ASP.NET Core attributes
-const (
-	// AspnetcoreRateLimitingResultKey is the attribute Key conforming to the
-	// "aspnetcore.rate_limiting.result" semantic conventions. It represents
-	// the rate-limiting result, shows whether the lease was acquired or
-	// contains a rejection reason
-	//
-	// Type: Enum
-	// RequirementLevel: Required
-	// Stability: stable
-	// Examples: 'acquired', 'request_canceled'
-	AspnetcoreRateLimitingResultKey = attribute.Key("aspnetcore.rate_limiting.result")
-
-	// AspnetcoreDiagnosticsHandlerTypeKey is the attribute Key conforming to
-	// the "aspnetcore.diagnostics.handler.type" semantic conventions. It
-	// represents the full type name of the
-	// [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler)
-	// implementation that handled the exception.
-	//
-	// Type: string
-	// RequirementLevel: ConditionallyRequired (if and only if the exception
-	// was handled by this handler.)
-	// Stability: stable
-	// Examples: 'Contoso.MyHandler'
-	AspnetcoreDiagnosticsHandlerTypeKey = attribute.Key("aspnetcore.diagnostics.handler.type")
-
-	// AspnetcoreDiagnosticsExceptionResultKey is the attribute Key conforming
-	// to the "aspnetcore.diagnostics.exception.result" semantic conventions.
-	// It represents the aSP.NET Core exception middleware handling result
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'handled', 'unhandled'
-	AspnetcoreDiagnosticsExceptionResultKey = attribute.Key("aspnetcore.diagnostics.exception.result")
-
-	// AspnetcoreRateLimitingPolicyKey is the attribute Key conforming to the
-	// "aspnetcore.rate_limiting.policy" semantic conventions. It represents
-	// the rate limiting policy name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'fixed', 'sliding', 'token'
-	AspnetcoreRateLimitingPolicyKey = attribute.Key("aspnetcore.rate_limiting.policy")
-
-	// AspnetcoreRequestIsUnhandledKey is the attribute Key conforming to the
-	// "aspnetcore.request.is_unhandled" semantic conventions. It represents
-	// the flag indicating if request was handled by the application pipeline.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: True
-	AspnetcoreRequestIsUnhandledKey = attribute.Key("aspnetcore.request.is_unhandled")
-
-	// AspnetcoreRoutingIsFallbackKey is the attribute Key conforming to the
-	// "aspnetcore.routing.is_fallback" semantic conventions. It represents a
-	// value that indicates whether the matched route is a fallback route.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: True
-	AspnetcoreRoutingIsFallbackKey = attribute.Key("aspnetcore.routing.is_fallback")
-
-	// AspnetcoreRoutingMatchStatusKey is the attribute Key conforming to the
-	// "aspnetcore.routing.match_status" semantic conventions. It represents
-	// the match result - success or failure
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'success', 'failure'
-	AspnetcoreRoutingMatchStatusKey = attribute.Key("aspnetcore.routing.match_status")
-)
-
-var (
-	// Lease was acquired
-	AspnetcoreRateLimitingResultAcquired = AspnetcoreRateLimitingResultKey.String("acquired")
-	// Lease request was rejected by the endpoint limiter
-	AspnetcoreRateLimitingResultEndpointLimiter = AspnetcoreRateLimitingResultKey.String("endpoint_limiter")
-	// Lease request was rejected by the global limiter
-	AspnetcoreRateLimitingResultGlobalLimiter = AspnetcoreRateLimitingResultKey.String("global_limiter")
-	// Lease request was canceled
-	AspnetcoreRateLimitingResultRequestCanceled = AspnetcoreRateLimitingResultKey.String("request_canceled")
-)
-
-var (
-	// Exception was handled by the exception handling middleware
-	AspnetcoreDiagnosticsExceptionResultHandled = AspnetcoreDiagnosticsExceptionResultKey.String("handled")
-	// Exception was not handled by the exception handling middleware
-	AspnetcoreDiagnosticsExceptionResultUnhandled = AspnetcoreDiagnosticsExceptionResultKey.String("unhandled")
-	// Exception handling was skipped because the response had started
-	AspnetcoreDiagnosticsExceptionResultSkipped = AspnetcoreDiagnosticsExceptionResultKey.String("skipped")
-	// Exception handling didn't run because the request was aborted
-	AspnetcoreDiagnosticsExceptionResultAborted = AspnetcoreDiagnosticsExceptionResultKey.String("aborted")
-)
-
-var (
-	// Match succeeded
-	AspnetcoreRoutingMatchStatusSuccess = AspnetcoreRoutingMatchStatusKey.String("success")
-	// Match failed
-	AspnetcoreRoutingMatchStatusFailure = AspnetcoreRoutingMatchStatusKey.String("failure")
-)
-
-// AspnetcoreDiagnosticsHandlerType returns an attribute KeyValue conforming
-// to the "aspnetcore.diagnostics.handler.type" semantic conventions. It
-// represents the full type name of the
-// [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler)
-// implementation that handled the exception.
-func AspnetcoreDiagnosticsHandlerType(val string) attribute.KeyValue {
-	return AspnetcoreDiagnosticsHandlerTypeKey.String(val)
-}
-
-// AspnetcoreRateLimitingPolicy returns an attribute KeyValue conforming to
-// the "aspnetcore.rate_limiting.policy" semantic conventions. It represents
-// the rate limiting policy name.
-func AspnetcoreRateLimitingPolicy(val string) attribute.KeyValue {
-	return AspnetcoreRateLimitingPolicyKey.String(val)
-}
-
-// AspnetcoreRequestIsUnhandled returns an attribute KeyValue conforming to
-// the "aspnetcore.request.is_unhandled" semantic conventions. It represents
-// the flag indicating if request was handled by the application pipeline.
-func AspnetcoreRequestIsUnhandled(val bool) attribute.KeyValue {
-	return AspnetcoreRequestIsUnhandledKey.Bool(val)
-}
-
-// AspnetcoreRoutingIsFallback returns an attribute KeyValue conforming to
-// the "aspnetcore.routing.is_fallback" semantic conventions. It represents a
-// value that indicates whether the matched route is a fallback route.
-func AspnetcoreRoutingIsFallback(val bool) attribute.KeyValue {
-	return AspnetcoreRoutingIsFallbackKey.Bool(val)
-}
-
-// Generic attributes for AWS services.
-const (
-	// AWSRequestIDKey is the attribute Key conforming to the "aws.request_id"
-	// semantic conventions. It represents the AWS request ID as returned in
-	// the response headers `x-amz-request-id` or `x-amz-requestid`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '79b9da39-b7ae-508a-a6bc-864b2829c622', 'C9ER4AJX75574TDJ'
-	AWSRequestIDKey = attribute.Key("aws.request_id")
-)
-
-// AWSRequestID returns an attribute KeyValue conforming to the
-// "aws.request_id" semantic conventions. It represents the AWS request ID as
-// returned in the response headers `x-amz-request-id` or `x-amz-requestid`.
-func AWSRequestID(val string) attribute.KeyValue {
-	return AWSRequestIDKey.String(val)
-}
-
-// Attributes for AWS DynamoDB.
-const (
-	// AWSDynamoDBAttributeDefinitionsKey is the attribute Key conforming to
-	// the "aws.dynamodb.attribute_definitions" semantic conventions. It
-	// represents the JSON-serialized value of each item in the
-	// `AttributeDefinitions` request field.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "AttributeName": "string", "AttributeType": "string" }'
-	AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions")
-
-	// AWSDynamoDBAttributesToGetKey is the attribute Key conforming to the
-	// "aws.dynamodb.attributes_to_get" semantic conventions. It represents the
-	// value of the `AttributesToGet` request parameter.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'lives', 'id'
-	AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get")
-
-	// AWSDynamoDBConsistentReadKey is the attribute Key conforming to the
-	// "aws.dynamodb.consistent_read" semantic conventions. It represents the
-	// value of the `ConsistentRead` request parameter.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read")
-
-	// AWSDynamoDBConsumedCapacityKey is the attribute Key conforming to the
-	// "aws.dynamodb.consumed_capacity" semantic conventions. It represents the
-	// JSON-serialized value of each item in the `ConsumedCapacity` response
-	// field.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": {
-	// "string" : { "CapacityUnits": number, "ReadCapacityUnits": number,
-	// "WriteCapacityUnits": number } }, "LocalSecondaryIndexes": { "string" :
-	// { "CapacityUnits": number, "ReadCapacityUnits": number,
-	// "WriteCapacityUnits": number } }, "ReadCapacityUnits": number, "Table":
-	// { "CapacityUnits": number, "ReadCapacityUnits": number,
-	// "WriteCapacityUnits": number }, "TableName": "string",
-	// "WriteCapacityUnits": number }'
-	AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity")
-
-	// AWSDynamoDBCountKey is the attribute Key conforming to the
-	// "aws.dynamodb.count" semantic conventions. It represents the value of
-	// the `Count` response parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 10
-	AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count")
-
-	// AWSDynamoDBExclusiveStartTableKey is the attribute Key conforming to the
-	// "aws.dynamodb.exclusive_start_table" semantic conventions. It represents
-	// the value of the `ExclusiveStartTableName` request parameter.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Users', 'CatsTable'
-	AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table")
-
-	// AWSDynamoDBGlobalSecondaryIndexUpdatesKey is the attribute Key
-	// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic
-	// conventions. It represents the JSON-serialized value of each item in the
-	// `GlobalSecondaryIndexUpdates` request field.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ {
-	// "AttributeName": "string", "KeyType": "string" } ], "Projection": {
-	// "NonKeyAttributes": [ "string" ], "ProjectionType": "string" },
-	// "ProvisionedThroughput": { "ReadCapacityUnits": number,
-	// "WriteCapacityUnits": number } }'
-	AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates")
-
-	// AWSDynamoDBGlobalSecondaryIndexesKey is the attribute Key conforming to
-	// the "aws.dynamodb.global_secondary_indexes" semantic conventions. It
-	// represents the JSON-serialized value of each item of the
-	// `GlobalSecondaryIndexes` request field
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName":
-	// "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [
-	// "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": {
-	// "ReadCapacityUnits": number, "WriteCapacityUnits": number } }'
-	AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes")
-
-	// AWSDynamoDBIndexNameKey is the attribute Key conforming to the
-	// "aws.dynamodb.index_name" semantic conventions. It represents the value
-	// of the `IndexName` request parameter.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'name_to_group'
-	AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name")
-
-	// AWSDynamoDBItemCollectionMetricsKey is the attribute Key conforming to
-	// the "aws.dynamodb.item_collection_metrics" semantic conventions. It
-	// represents the JSON-serialized value of the `ItemCollectionMetrics`
-	// response field.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B":
-	// blob, "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": {
-	// "string" : "AttributeValue" }, "N": "string", "NS": [ "string" ],
-	// "NULL": boolean, "S": "string", "SS": [ "string" ] } },
-	// "SizeEstimateRangeGB": [ number ] } ] }'
-	AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics")
-
-	// AWSDynamoDBLimitKey is the attribute Key conforming to the
-	// "aws.dynamodb.limit" semantic conventions. It represents the value of
-	// the `Limit` request parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 10
-	AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit")
-
-	// AWSDynamoDBLocalSecondaryIndexesKey is the attribute Key conforming to
-	// the "aws.dynamodb.local_secondary_indexes" semantic conventions. It
-	// represents the JSON-serialized value of each item of the
-	// `LocalSecondaryIndexes` request field.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '{ "IndexARN": "string", "IndexName": "string",
-	// "IndexSizeBytes": number, "ItemCount": number, "KeySchema": [ {
-	// "AttributeName": "string", "KeyType": "string" } ], "Projection": {
-	// "NonKeyAttributes": [ "string" ], "ProjectionType": "string" } }'
-	AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes")
-
-	// AWSDynamoDBProjectionKey is the attribute Key conforming to the
-	// "aws.dynamodb.projection" semantic conventions. It represents the value
-	// of the `ProjectionExpression` request parameter.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Title', 'Title, Price, Color', 'Title, Description,
-	// RelatedItems, ProductReviews'
-	AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection")
-
-	// AWSDynamoDBProvisionedReadCapacityKey is the attribute Key conforming to
-	// the "aws.dynamodb.provisioned_read_capacity" semantic conventions. It
-	// represents the value of the `ProvisionedThroughput.ReadCapacityUnits`
-	// request parameter.
-	//
-	// Type: double
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1.0, 2.0
-	AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity")
-
-	// AWSDynamoDBProvisionedWriteCapacityKey is the attribute Key conforming
-	// to the "aws.dynamodb.provisioned_write_capacity" semantic conventions.
-	// It represents the value of the
-	// `ProvisionedThroughput.WriteCapacityUnits` request parameter.
-	//
-	// Type: double
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1.0, 2.0
-	AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity")
-
-	// AWSDynamoDBScanForwardKey is the attribute Key conforming to the
-	// "aws.dynamodb.scan_forward" semantic conventions. It represents the
-	// value of the `ScanIndexForward` request parameter.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward")
-
-	// AWSDynamoDBScannedCountKey is the attribute Key conforming to the
-	// "aws.dynamodb.scanned_count" semantic conventions. It represents the
-	// value of the `ScannedCount` response parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 50
-	AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count")
-
-	// AWSDynamoDBSegmentKey is the attribute Key conforming to the
-	// "aws.dynamodb.segment" semantic conventions. It represents the value of
-	// the `Segment` request parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 10
-	AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment")
-
-	// AWSDynamoDBSelectKey is the attribute Key conforming to the
-	// "aws.dynamodb.select" semantic conventions. It represents the value of
-	// the `Select` request parameter.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ALL_ATTRIBUTES', 'COUNT'
-	AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select")
-
-	// AWSDynamoDBTableCountKey is the attribute Key conforming to the
-	// "aws.dynamodb.table_count" semantic conventions. It represents the
-	// number of items in the `TableNames` response parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 20
-	AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count")
-
-	// AWSDynamoDBTableNamesKey is the attribute Key conforming to the
-	// "aws.dynamodb.table_names" semantic conventions. It represents the keys
-	// in the `RequestItems` object field.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Users', 'Cats'
-	AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names")
-
-	// AWSDynamoDBTotalSegmentsKey is the attribute Key conforming to the
-	// "aws.dynamodb.total_segments" semantic conventions. It represents the
-	// value of the `TotalSegments` request parameter.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 100
-	AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments")
-)
-
-// AWSDynamoDBAttributeDefinitions returns an attribute KeyValue conforming
-// to the "aws.dynamodb.attribute_definitions" semantic conventions. It
-// represents the JSON-serialized value of each item in the
-// `AttributeDefinitions` request field.
-func AWSDynamoDBAttributeDefinitions(val ...string) attribute.KeyValue {
-	return AWSDynamoDBAttributeDefinitionsKey.StringSlice(val)
-}
-
-// AWSDynamoDBAttributesToGet returns an attribute KeyValue conforming to
-// the "aws.dynamodb.attributes_to_get" semantic conventions. It represents the
-// value of the `AttributesToGet` request parameter.
-func AWSDynamoDBAttributesToGet(val ...string) attribute.KeyValue {
-	return AWSDynamoDBAttributesToGetKey.StringSlice(val)
-}
-
-// AWSDynamoDBConsistentRead returns an attribute KeyValue conforming to the
-// "aws.dynamodb.consistent_read" semantic conventions. It represents the value
-// of the `ConsistentRead` request parameter.
-func AWSDynamoDBConsistentRead(val bool) attribute.KeyValue {
-	return AWSDynamoDBConsistentReadKey.Bool(val)
-}
-
-// AWSDynamoDBConsumedCapacity returns an attribute KeyValue conforming to
-// the "aws.dynamodb.consumed_capacity" semantic conventions. It represents the
-// JSON-serialized value of each item in the `ConsumedCapacity` response field.
-func AWSDynamoDBConsumedCapacity(val ...string) attribute.KeyValue {
-	return AWSDynamoDBConsumedCapacityKey.StringSlice(val)
-}
-
-// AWSDynamoDBCount returns an attribute KeyValue conforming to the
-// "aws.dynamodb.count" semantic conventions. It represents the value of the
-// `Count` response parameter.
-func AWSDynamoDBCount(val int) attribute.KeyValue {
-	return AWSDynamoDBCountKey.Int(val)
-}
-
-// AWSDynamoDBExclusiveStartTable returns an attribute KeyValue conforming
-// to the "aws.dynamodb.exclusive_start_table" semantic conventions. It
-// represents the value of the `ExclusiveStartTableName` request parameter.
-func AWSDynamoDBExclusiveStartTable(val string) attribute.KeyValue {
-	return AWSDynamoDBExclusiveStartTableKey.String(val)
-}
-
-// AWSDynamoDBGlobalSecondaryIndexUpdates returns an attribute KeyValue
-// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic
-// conventions. It represents the JSON-serialized value of each item in the
-// `GlobalSecondaryIndexUpdates` request field.
-func AWSDynamoDBGlobalSecondaryIndexUpdates(val ...string) attribute.KeyValue {
-	return AWSDynamoDBGlobalSecondaryIndexUpdatesKey.StringSlice(val)
-}
-
-// AWSDynamoDBGlobalSecondaryIndexes returns an attribute KeyValue
-// conforming to the "aws.dynamodb.global_secondary_indexes" semantic
-// conventions. It represents the JSON-serialized value of each item of the
-// `GlobalSecondaryIndexes` request field
-func AWSDynamoDBGlobalSecondaryIndexes(val ...string) attribute.KeyValue {
-	return AWSDynamoDBGlobalSecondaryIndexesKey.StringSlice(val)
-}
-
-// AWSDynamoDBIndexName returns an attribute KeyValue conforming to the
-// "aws.dynamodb.index_name" semantic conventions. It represents the value of
-// the `IndexName` request parameter.
-func AWSDynamoDBIndexName(val string) attribute.KeyValue {
-	return AWSDynamoDBIndexNameKey.String(val)
-}
-
-// AWSDynamoDBItemCollectionMetrics returns an attribute KeyValue conforming
-// to the "aws.dynamodb.item_collection_metrics" semantic conventions. It
-// represents the JSON-serialized value of the `ItemCollectionMetrics` response
-// field.
-func AWSDynamoDBItemCollectionMetrics(val string) attribute.KeyValue {
-	return AWSDynamoDBItemCollectionMetricsKey.String(val)
-}
-
-// AWSDynamoDBLimit returns an attribute KeyValue conforming to the
-// "aws.dynamodb.limit" semantic conventions. It represents the value of the
-// `Limit` request parameter.
-func AWSDynamoDBLimit(val int) attribute.KeyValue {
-	return AWSDynamoDBLimitKey.Int(val)
-}
-
-// AWSDynamoDBLocalSecondaryIndexes returns an attribute KeyValue conforming
-// to the "aws.dynamodb.local_secondary_indexes" semantic conventions. It
-// represents the JSON-serialized value of each item of the
-// `LocalSecondaryIndexes` request field.
-func AWSDynamoDBLocalSecondaryIndexes(val ...string) attribute.KeyValue {
-	return AWSDynamoDBLocalSecondaryIndexesKey.StringSlice(val)
-}
-
-// AWSDynamoDBProjection returns an attribute KeyValue conforming to the
-// "aws.dynamodb.projection" semantic conventions. It represents the value of
-// the `ProjectionExpression` request parameter.
-func AWSDynamoDBProjection(val string) attribute.KeyValue {
-	return AWSDynamoDBProjectionKey.String(val)
-}
-
-// AWSDynamoDBProvisionedReadCapacity returns an attribute KeyValue
-// conforming to the "aws.dynamodb.provisioned_read_capacity" semantic
-// conventions. It represents the value of the
-// `ProvisionedThroughput.ReadCapacityUnits` request parameter.
-func AWSDynamoDBProvisionedReadCapacity(val float64) attribute.KeyValue {
-	return AWSDynamoDBProvisionedReadCapacityKey.Float64(val)
-}
-
-// AWSDynamoDBProvisionedWriteCapacity returns an attribute KeyValue
-// conforming to the "aws.dynamodb.provisioned_write_capacity" semantic
-// conventions. It represents the value of the
-// `ProvisionedThroughput.WriteCapacityUnits` request parameter.
-func AWSDynamoDBProvisionedWriteCapacity(val float64) attribute.KeyValue {
-	return AWSDynamoDBProvisionedWriteCapacityKey.Float64(val)
-}
-
-// AWSDynamoDBScanForward returns an attribute KeyValue conforming to the
-// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of
-// the `ScanIndexForward` request parameter.
-func AWSDynamoDBScanForward(val bool) attribute.KeyValue {
-	return AWSDynamoDBScanForwardKey.Bool(val)
-}
-
-// AWSDynamoDBScannedCount returns an attribute KeyValue conforming to the
-// "aws.dynamodb.scanned_count" semantic conventions. It represents the value
-// of the `ScannedCount` response parameter.
-func AWSDynamoDBScannedCount(val int) attribute.KeyValue {
-	return AWSDynamoDBScannedCountKey.Int(val)
-}
-
-// AWSDynamoDBSegment returns an attribute KeyValue conforming to the
-// "aws.dynamodb.segment" semantic conventions. It represents the value of the
-// `Segment` request parameter.
-func AWSDynamoDBSegment(val int) attribute.KeyValue {
-	return AWSDynamoDBSegmentKey.Int(val)
-}
-
-// AWSDynamoDBSelect returns an attribute KeyValue conforming to the
-// "aws.dynamodb.select" semantic conventions. It represents the value of the
-// `Select` request parameter.
-func AWSDynamoDBSelect(val string) attribute.KeyValue {
-	return AWSDynamoDBSelectKey.String(val)
-}
-
-// AWSDynamoDBTableCount returns an attribute KeyValue conforming to the
-// "aws.dynamodb.table_count" semantic conventions. It represents the number of
-// items in the `TableNames` response parameter.
-func AWSDynamoDBTableCount(val int) attribute.KeyValue {
-	return AWSDynamoDBTableCountKey.Int(val)
-}
-
-// AWSDynamoDBTableNames returns an attribute KeyValue conforming to the
-// "aws.dynamodb.table_names" semantic conventions. It represents the keys in
-// the `RequestItems` object field.
-func AWSDynamoDBTableNames(val ...string) attribute.KeyValue {
-	return AWSDynamoDBTableNamesKey.StringSlice(val)
-}
-
-// AWSDynamoDBTotalSegments returns an attribute KeyValue conforming to the
-// "aws.dynamodb.total_segments" semantic conventions. It represents the value
-// of the `TotalSegments` request parameter.
-func AWSDynamoDBTotalSegments(val int) attribute.KeyValue {
-	return AWSDynamoDBTotalSegmentsKey.Int(val)
-}
-
-// Attributes for AWS Elastic Container Service (ECS).
-const (
-	// AWSECSTaskIDKey is the attribute Key conforming to the "aws.ecs.task.id"
-	// semantic conventions. It represents the ID of a running ECS task. The ID
-	// MUST be extracted from `task.arn`.
-	//
-	// Type: string
-	// RequirementLevel: ConditionallyRequired (If and only if `task.arn` is
-	// populated.)
-	// Stability: experimental
-	// Examples: '10838bed-421f-43ef-870a-f43feacbbb5b',
-	// '23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd'
-	AWSECSTaskIDKey = attribute.Key("aws.ecs.task.id")
-
-	// AWSECSClusterARNKey is the attribute Key conforming to the
-	// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an
-	// [ECS
-	// cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster'
-	AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn")
-
-	// AWSECSContainerARNKey is the attribute Key conforming to the
-	// "aws.ecs.container.arn" semantic conventions. It represents the Amazon
-	// Resource Name (ARN) of an [ECS container
-	// instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'arn:aws:ecs:us-west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9'
-	AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn")
-
-	// AWSECSLaunchtypeKey is the attribute Key conforming to the
-	// "aws.ecs.launchtype" semantic conventions. It represents the [launch
-	// type](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html)
-	// for an ECS task.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype")
-
-	// AWSECSTaskARNKey is the attribute Key conforming to the
-	// "aws.ecs.task.arn" semantic conventions. It represents the ARN of a
-	// running [ECS
-	// task](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'arn:aws:ecs:us-west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b',
-	// 'arn:aws:ecs:us-west-1:123456789123:task/my-cluster/task-id/23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd'
-	AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn")
-
-	// AWSECSTaskFamilyKey is the attribute Key conforming to the
-	// "aws.ecs.task.family" semantic conventions. It represents the family
-	// name of the [ECS task
-	// definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html)
-	// used to create the ECS task.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry-family'
-	AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family")
-
-	// AWSECSTaskRevisionKey is the attribute Key conforming to the
-	// "aws.ecs.task.revision" semantic conventions. It represents the revision
-	// for the task definition used to create the ECS task.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '8', '26'
-	AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision")
-)
-
-var (
-	// ec2
-	AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2")
-	// fargate
-	AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate")
-)
-
-// AWSECSTaskID returns an attribute KeyValue conforming to the
-// "aws.ecs.task.id" semantic conventions. It represents the ID of a running
-// ECS task. The ID MUST be extracted from `task.arn`.
-func AWSECSTaskID(val string) attribute.KeyValue {
-	return AWSECSTaskIDKey.String(val)
-}
-
-// AWSECSClusterARN returns an attribute KeyValue conforming to the
-// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an [ECS
-// cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html).
-func AWSECSClusterARN(val string) attribute.KeyValue {
-	return AWSECSClusterARNKey.String(val)
-}
-
-// AWSECSContainerARN returns an attribute KeyValue conforming to the
-// "aws.ecs.container.arn" semantic conventions. It represents the Amazon
-// Resource Name (ARN) of an [ECS container
-// instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html).
-func AWSECSContainerARN(val string) attribute.KeyValue {
-	return AWSECSContainerARNKey.String(val)
-}
-
-// AWSECSTaskARN returns an attribute KeyValue conforming to the
-// "aws.ecs.task.arn" semantic conventions. It represents the ARN of a running
-// [ECS
-// task](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids).
-func AWSECSTaskARN(val string) attribute.KeyValue {
-	return AWSECSTaskARNKey.String(val)
-}
-
-// AWSECSTaskFamily returns an attribute KeyValue conforming to the
-// "aws.ecs.task.family" semantic conventions. It represents the family name of
-// the [ECS task
-// definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html)
-// used to create the ECS task.
-func AWSECSTaskFamily(val string) attribute.KeyValue {
-	return AWSECSTaskFamilyKey.String(val)
-}
-
-// AWSECSTaskRevision returns an attribute KeyValue conforming to the
-// "aws.ecs.task.revision" semantic conventions. It represents the revision for
-// the task definition used to create the ECS task.
-func AWSECSTaskRevision(val string) attribute.KeyValue {
-	return AWSECSTaskRevisionKey.String(val)
-}
-
-// Attributes for AWS Elastic Kubernetes Service (EKS).
-const (
-	// AWSEKSClusterARNKey is the attribute Key conforming to the
-	// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an
-	// EKS cluster.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster'
-	AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn")
-)
-
-// AWSEKSClusterARN returns an attribute KeyValue conforming to the
-// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS
-// cluster.
-func AWSEKSClusterARN(val string) attribute.KeyValue {
-	return AWSEKSClusterARNKey.String(val)
-}
-
-// Attributes for AWS Logs.
-const (
-	// AWSLogGroupARNsKey is the attribute Key conforming to the
-	// "aws.log.group.arns" semantic conventions. It represents the Amazon
-	// Resource Name(s) (ARN) of the AWS log group(s).
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*'
-	// Note: See the [log group ARN format
-	// documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format).
-	AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns")
-
-	// AWSLogGroupNamesKey is the attribute Key conforming to the
-	// "aws.log.group.names" semantic conventions. It represents the name(s) of
-	// the AWS log group(s) an application is writing to.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/aws/lambda/my-function', 'opentelemetry-service'
-	// Note: Multiple log groups must be supported for cases like
-	// multi-container applications, where a single application has sidecar
-	// containers, and each write to their own log group.
-	AWSLogGroupNamesKey = attribute.Key("aws.log.group.names")
-
-	// AWSLogStreamARNsKey is the attribute Key conforming to the
-	// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of
-	// the AWS log stream(s).
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b'
-	// Note: See the [log stream ARN format
-	// documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format).
-	// One log group can contain several log streams, so these ARNs necessarily
-	// identify both a log group and a log stream.
-	AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns")
-
-	// AWSLogStreamNamesKey is the attribute Key conforming to the
-	// "aws.log.stream.names" semantic conventions. It represents the name(s)
-	// of the AWS log stream(s) an application is writing to.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b'
-	AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names")
-)
-
-// AWSLogGroupARNs returns an attribute KeyValue conforming to the
-// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource
-// Name(s) (ARN) of the AWS log group(s).
-func AWSLogGroupARNs(val ...string) attribute.KeyValue {
-	return AWSLogGroupARNsKey.StringSlice(val)
-}
-
-// AWSLogGroupNames returns an attribute KeyValue conforming to the
-// "aws.log.group.names" semantic conventions. It represents the name(s) of the
-// AWS log group(s) an application is writing to.
-func AWSLogGroupNames(val ...string) attribute.KeyValue {
-	return AWSLogGroupNamesKey.StringSlice(val)
-}
-
-// AWSLogStreamARNs returns an attribute KeyValue conforming to the
-// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the
-// AWS log stream(s).
-func AWSLogStreamARNs(val ...string) attribute.KeyValue {
-	return AWSLogStreamARNsKey.StringSlice(val)
-}
-
-// AWSLogStreamNames returns an attribute KeyValue conforming to the
-// "aws.log.stream.names" semantic conventions. It represents the name(s) of
-// the AWS log stream(s) an application is writing to.
-func AWSLogStreamNames(val ...string) attribute.KeyValue {
-	return AWSLogStreamNamesKey.StringSlice(val)
-}
-
-// Attributes for AWS Lambda.
-const (
-	// AWSLambdaInvokedARNKey is the attribute Key conforming to the
-	// "aws.lambda.invoked_arn" semantic conventions. It represents the full
-	// invoked ARN as provided on the `Context` passed to the function
-	// (`Lambda-Runtime-Invoked-Function-ARN` header on the
-	// `/runtime/invocation/next` applicable).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'arn:aws:lambda:us-east-1:123456:function:myfunction:myalias'
-	// Note: This may be different from `cloud.resource_id` if an alias is
-	// involved.
-	AWSLambdaInvokedARNKey = attribute.Key("aws.lambda.invoked_arn")
-)
-
-// AWSLambdaInvokedARN returns an attribute KeyValue conforming to the
-// "aws.lambda.invoked_arn" semantic conventions. It represents the full
-// invoked ARN as provided on the `Context` passed to the function
-// (`Lambda-Runtime-Invoked-Function-ARN` header on the
-// `/runtime/invocation/next` applicable).
-func AWSLambdaInvokedARN(val string) attribute.KeyValue {
-	return AWSLambdaInvokedARNKey.String(val)
-}
-
-// Attributes for AWS S3.
-const (
-	// AWSS3BucketKey is the attribute Key conforming to the "aws.s3.bucket"
-	// semantic conventions. It represents the S3 bucket name the request
-	// refers to. Corresponds to the `--bucket` parameter of the [S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)
-	// operations.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'some-bucket-name'
-	// Note: The `bucket` attribute is applicable to all S3 operations that
-	// reference a bucket, i.e. that require the bucket name as a mandatory
-	// parameter.
-	// This applies to almost all S3 operations except `list-buckets`.
-	AWSS3BucketKey = attribute.Key("aws.s3.bucket")
-
-	// AWSS3CopySourceKey is the attribute Key conforming to the
-	// "aws.s3.copy_source" semantic conventions. It represents the source
-	// object (in the form `bucket`/`key`) for the copy operation.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'someFile.yml'
-	// Note: The `copy_source` attribute applies to S3 copy operations and
-	// corresponds to the `--copy-source` parameter
-	// of the [copy-object operation within the S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html).
-	// This applies in particular to the following operations:
-	//
-	// -
-	// [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html)
-	// -
-	// [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
-	AWSS3CopySourceKey = attribute.Key("aws.s3.copy_source")
-
-	// AWSS3DeleteKey is the attribute Key conforming to the "aws.s3.delete"
-	// semantic conventions. It represents the delete request container that
-	// specifies the objects to be deleted.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'Objects=[{Key=string,VersionID=string},{Key=string,VersionID=string}],Quiet=boolean'
-	// Note: The `delete` attribute is only applicable to the
-	// [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html)
-	// operation.
-	// The `delete` attribute corresponds to the `--delete` parameter of the
-	// [delete-objects operation within the S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-objects.html).
-	AWSS3DeleteKey = attribute.Key("aws.s3.delete")
-
-	// AWSS3KeyKey is the attribute Key conforming to the "aws.s3.key" semantic
-	// conventions. It represents the S3 object key the request refers to.
-	// Corresponds to the `--key` parameter of the [S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)
-	// operations.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'someFile.yml'
-	// Note: The `key` attribute is applicable to all object-related S3
-	// operations, i.e. that require the object key as a mandatory parameter.
-	// This applies in particular to the following operations:
-	//
-	// -
-	// [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html)
-	// -
-	// [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html)
-	// -
-	// [get-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html)
-	// -
-	// [head-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/head-object.html)
-	// -
-	// [put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html)
-	// -
-	// [restore-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/restore-object.html)
-	// -
-	// [select-object-content](https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html)
-	// -
-	// [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
-	// -
-	// [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
-	// -
-	// [create-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html)
-	// -
-	// [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
-	// -
-	// [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
-	// -
-	// [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
-	AWSS3KeyKey = attribute.Key("aws.s3.key")
-
-	// AWSS3PartNumberKey is the attribute Key conforming to the
-	// "aws.s3.part_number" semantic conventions. It represents the part number
-	// of the part being uploaded in a multipart-upload operation. This is a
-	// positive integer between 1 and 10,000.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3456
-	// Note: The `part_number` attribute is only applicable to the
-	// [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
-	// and
-	// [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
-	// operations.
-	// The `part_number` attribute corresponds to the `--part-number` parameter
-	// of the
-	// [upload-part operation within the S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html).
-	AWSS3PartNumberKey = attribute.Key("aws.s3.part_number")
-
-	// AWSS3UploadIDKey is the attribute Key conforming to the
-	// "aws.s3.upload_id" semantic conventions. It represents the upload ID
-	// that identifies the multipart upload.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ'
-	// Note: The `upload_id` attribute applies to S3 multipart-upload
-	// operations and corresponds to the `--upload-id` parameter
-	// of the [S3
-	// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)
-	// multipart operations.
-	// This applies in particular to the following operations:
-	//
-	// -
-	// [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
-	// -
-	// [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
-	// -
-	// [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
-	// -
-	// [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
-	// -
-	// [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
-	AWSS3UploadIDKey = attribute.Key("aws.s3.upload_id")
-)
-
-// AWSS3Bucket returns an attribute KeyValue conforming to the
-// "aws.s3.bucket" semantic conventions. It represents the S3 bucket name the
-// request refers to. Corresponds to the `--bucket` parameter of the [S3
-// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)
-// operations.
-func AWSS3Bucket(val string) attribute.KeyValue {
-	return AWSS3BucketKey.String(val)
-}
-
-// AWSS3CopySource returns an attribute KeyValue conforming to the
-// "aws.s3.copy_source" semantic conventions. It represents the source object
-// (in the form `bucket`/`key`) for the copy operation.
-func AWSS3CopySource(val string) attribute.KeyValue {
-	return AWSS3CopySourceKey.String(val)
-}
-
-// AWSS3Delete returns an attribute KeyValue conforming to the
-// "aws.s3.delete" semantic conventions. It represents the delete request
-// container that specifies the objects to be deleted.
-func AWSS3Delete(val string) attribute.KeyValue {
-	return AWSS3DeleteKey.String(val)
-}
-
-// AWSS3Key returns an attribute KeyValue conforming to the "aws.s3.key"
-// semantic conventions. It represents the S3 object key the request refers to.
-// Corresponds to the `--key` parameter of the [S3
-// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html)
-// operations.
-func AWSS3Key(val string) attribute.KeyValue {
-	return AWSS3KeyKey.String(val)
-}
-
-// AWSS3PartNumber returns an attribute KeyValue conforming to the
-// "aws.s3.part_number" semantic conventions. It represents the part number of
-// the part being uploaded in a multipart-upload operation. This is a positive
-// integer between 1 and 10,000.
-func AWSS3PartNumber(val int) attribute.KeyValue {
-	return AWSS3PartNumberKey.Int(val)
-}
-
-// AWSS3UploadID returns an attribute KeyValue conforming to the
-// "aws.s3.upload_id" semantic conventions. It represents the upload ID that
-// identifies the multipart upload.
-func AWSS3UploadID(val string) attribute.KeyValue {
-	return AWSS3UploadIDKey.String(val)
-}
-
-// The web browser attributes
-const (
-	// BrowserBrandsKey is the attribute Key conforming to the "browser.brands"
-	// semantic conventions. It represents the array of brand name and version
-	// separated by a space
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: ' Not A;Brand 99', 'Chromium 99', 'Chrome 99'
-	// Note: This value is intended to be taken from the [UA client hints
-	// API](https://wicg.github.io/ua-client-hints/#interface)
-	// (`navigator.userAgentData.brands`).
-	BrowserBrandsKey = attribute.Key("browser.brands")
-
-	// BrowserLanguageKey is the attribute Key conforming to the
-	// "browser.language" semantic conventions. It represents the preferred
-	// language of the user using the browser
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'en', 'en-US', 'fr', 'fr-FR'
-	// Note: This value is intended to be taken from the Navigator API
-	// `navigator.language`.
-	BrowserLanguageKey = attribute.Key("browser.language")
-
-	// BrowserMobileKey is the attribute Key conforming to the "browser.mobile"
-	// semantic conventions. It represents a boolean that is true if the
-	// browser is running on a mobile device
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: This value is intended to be taken from the [UA client hints
-	// API](https://wicg.github.io/ua-client-hints/#interface)
-	// (`navigator.userAgentData.mobile`). If unavailable, this attribute
-	// SHOULD be left unset.
-	BrowserMobileKey = attribute.Key("browser.mobile")
-
-	// BrowserPlatformKey is the attribute Key conforming to the
-	// "browser.platform" semantic conventions. It represents the platform on
-	// which the browser is running
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Windows', 'macOS', 'Android'
-	// Note: This value is intended to be taken from the [UA client hints
-	// API](https://wicg.github.io/ua-client-hints/#interface)
-	// (`navigator.userAgentData.platform`). If unavailable, the legacy
-	// `navigator.platform` API SHOULD NOT be used instead and this attribute
-	// SHOULD be left unset in order for the values to be consistent.
-	// The list of possible values is defined in the [W3C User-Agent Client
-	// Hints
-	// specification](https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform).
-	// Note that some (but not all) of these values can overlap with values in
-	// the [`os.type` and `os.name` attributes](./os.md). However, for
-	// consistency, the values in the `browser.platform` attribute should
-	// capture the exact value that the user agent provides.
-	BrowserPlatformKey = attribute.Key("browser.platform")
-)
-
-// BrowserBrands returns an attribute KeyValue conforming to the
-// "browser.brands" semantic conventions. It represents the array of brand name
-// and version separated by a space
-func BrowserBrands(val ...string) attribute.KeyValue {
-	return BrowserBrandsKey.StringSlice(val)
-}
-
-// BrowserLanguage returns an attribute KeyValue conforming to the
-// "browser.language" semantic conventions. It represents the preferred
-// language of the user using the browser
-func BrowserLanguage(val string) attribute.KeyValue {
-	return BrowserLanguageKey.String(val)
-}
-
-// BrowserMobile returns an attribute KeyValue conforming to the
-// "browser.mobile" semantic conventions. It represents a boolean that is true
-// if the browser is running on a mobile device
-func BrowserMobile(val bool) attribute.KeyValue {
-	return BrowserMobileKey.Bool(val)
-}
-
-// BrowserPlatform returns an attribute KeyValue conforming to the
-// "browser.platform" semantic conventions. It represents the platform on which
-// the browser is running
-func BrowserPlatform(val string) attribute.KeyValue {
-	return BrowserPlatformKey.String(val)
-}
-
-// These attributes may be used to describe the client in a connection-based
-// network interaction where there is one side that initiates the connection
-// (the client is the side that initiates the connection). This covers all TCP
-// network interactions since TCP is connection-based and one side initiates
-// the connection (an exception is made for peer-to-peer communication over TCP
-// where the "user-facing" surface of the protocol / API doesn't expose a clear
-// notion of client and server). This also covers UDP network interactions
-// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS.
-const (
-	// ClientAddressKey is the attribute Key conforming to the "client.address"
-	// semantic conventions. It represents the client address - domain name if
-	// available without reverse DNS lookup; otherwise, IP address or Unix
-	// domain socket name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'client.example.com', '10.1.2.80', '/tmp/my.sock'
-	// Note: When observed from the server side, and when communicating through
-	// an intermediary, `client.address` SHOULD represent the client address
-	// behind any intermediaries,  for example proxies, if it's available.
-	ClientAddressKey = attribute.Key("client.address")
-
-	// ClientPortKey is the attribute Key conforming to the "client.port"
-	// semantic conventions. It represents the client port number.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 65123
-	// Note: When observed from the server side, and when communicating through
-	// an intermediary, `client.port` SHOULD represent the client port behind
-	// any intermediaries,  for example proxies, if it's available.
-	ClientPortKey = attribute.Key("client.port")
-)
-
-// ClientAddress returns an attribute KeyValue conforming to the
-// "client.address" semantic conventions. It represents the client address -
-// domain name if available without reverse DNS lookup; otherwise, IP address
-// or Unix domain socket name.
-func ClientAddress(val string) attribute.KeyValue {
-	return ClientAddressKey.String(val)
-}
-
-// ClientPort returns an attribute KeyValue conforming to the "client.port"
-// semantic conventions. It represents the client port number.
-func ClientPort(val int) attribute.KeyValue {
-	return ClientPortKey.Int(val)
-}
-
-// A cloud environment (e.g. GCP, Azure, AWS).
-const (
-	// CloudAccountIDKey is the attribute Key conforming to the
-	// "cloud.account.id" semantic conventions. It represents the cloud account
-	// ID the resource is assigned to.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '111111111111', 'opentelemetry'
-	CloudAccountIDKey = attribute.Key("cloud.account.id")
-
-	// CloudAvailabilityZoneKey is the attribute Key conforming to the
-	// "cloud.availability_zone" semantic conventions. It represents the cloud
-	// regions often have multiple, isolated locations known as zones to
-	// increase availability. Availability zone represents the zone where the
-	// resource is running.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'us-east-1c'
-	// Note: Availability zones are called "zones" on Alibaba Cloud and Google
-	// Cloud.
-	CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone")
-
-	// CloudPlatformKey is the attribute Key conforming to the "cloud.platform"
-	// semantic conventions. It represents the cloud platform in use.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: The prefix of the service SHOULD match the one specified in
-	// `cloud.provider`.
-	CloudPlatformKey = attribute.Key("cloud.platform")
-
-	// CloudProviderKey is the attribute Key conforming to the "cloud.provider"
-	// semantic conventions. It represents the name of the cloud provider.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	CloudProviderKey = attribute.Key("cloud.provider")
-
-	// CloudRegionKey is the attribute Key conforming to the "cloud.region"
-	// semantic conventions. It represents the geographical region the resource
-	// is running.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'us-central1', 'us-east-1'
-	// Note: Refer to your provider's docs to see the available regions, for
-	// example [Alibaba Cloud
-	// regions](https://www.alibabacloud.com/help/doc-detail/40654.htm), [AWS
-	// regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/),
-	// [Azure
-	// regions](https://azure.microsoft.com/global-infrastructure/geographies/),
-	// [Google Cloud regions](https://cloud.google.com/about/locations), or
-	// [Tencent Cloud
-	// regions](https://www.tencentcloud.com/document/product/213/6091).
-	CloudRegionKey = attribute.Key("cloud.region")
-
-	// CloudResourceIDKey is the attribute Key conforming to the
-	// "cloud.resource_id" semantic conventions. It represents the cloud
-	// provider-specific native identifier of the monitored cloud resource
-	// (e.g. an
-	// [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
-	// on AWS, a [fully qualified resource
-	// ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id)
-	// on Azure, a [full resource
-	// name](https://cloud.google.com/apis/design/resource_names#full_resource_name)
-	// on GCP)
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function',
-	// '//run.googleapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID',
-	// '/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/'
-	// Note: On some cloud providers, it may not be possible to determine the
-	// full ID at startup,
-	// so it may be necessary to set `cloud.resource_id` as a span attribute
-	// instead.
-	//
-	// The exact value to use for `cloud.resource_id` depends on the cloud
-	// provider.
-	// The following well-known definitions MUST be used if you set this
-	// attribute and they apply:
-	//
-	// * **AWS Lambda:** The function
-	// [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html).
-	//   Take care not to use the "invoked ARN" directly but replace any
-	//   [alias
-	// suffix](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html)
-	//   with the resolved function version, as the same runtime instance may
-	// be invokable with
-	//   multiple different aliases.
-	// * **GCP:** The [URI of the
-	// resource](https://cloud.google.com/iam/docs/full-resource-names)
-	// * **Azure:** The [Fully Qualified Resource
-	// ID](https://docs.microsoft.com/rest/api/resources/resources/get-by-id)
-	// of the invoked function,
-	//   *not* the function app, having the form
-	// `/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/`.
-	//   This means that a span attribute MUST be used, as an Azure function
-	// app can host multiple functions that would usually share
-	//   a TracerProvider.
-	CloudResourceIDKey = attribute.Key("cloud.resource_id")
-)
-
-var (
-	// Alibaba Cloud Elastic Compute Service
-	CloudPlatformAlibabaCloudECS = CloudPlatformKey.String("alibaba_cloud_ecs")
-	// Alibaba Cloud Function Compute
-	CloudPlatformAlibabaCloudFc = CloudPlatformKey.String("alibaba_cloud_fc")
-	// Red Hat OpenShift on Alibaba Cloud
-	CloudPlatformAlibabaCloudOpenshift = CloudPlatformKey.String("alibaba_cloud_openshift")
-	// AWS Elastic Compute Cloud
-	CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2")
-	// AWS Elastic Container Service
-	CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs")
-	// AWS Elastic Kubernetes Service
-	CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks")
-	// AWS Lambda
-	CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda")
-	// AWS Elastic Beanstalk
-	CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk")
-	// AWS App Runner
-	CloudPlatformAWSAppRunner = CloudPlatformKey.String("aws_app_runner")
-	// Red Hat OpenShift on AWS (ROSA)
-	CloudPlatformAWSOpenshift = CloudPlatformKey.String("aws_openshift")
-	// Azure Virtual Machines
-	CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm")
-	// Azure Container Apps
-	CloudPlatformAzureContainerApps = CloudPlatformKey.String("azure_container_apps")
-	// Azure Container Instances
-	CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances")
-	// Azure Kubernetes Service
-	CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks")
-	// Azure Functions
-	CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions")
-	// Azure App Service
-	CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service")
-	// Azure Red Hat OpenShift
-	CloudPlatformAzureOpenshift = CloudPlatformKey.String("azure_openshift")
-	// Google Bare Metal Solution (BMS)
-	CloudPlatformGCPBareMetalSolution = CloudPlatformKey.String("gcp_bare_metal_solution")
-	// Google Cloud Compute Engine (GCE)
-	CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine")
-	// Google Cloud Run
-	CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run")
-	// Google Cloud Kubernetes Engine (GKE)
-	CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine")
-	// Google Cloud Functions (GCF)
-	CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions")
-	// Google Cloud App Engine (GAE)
-	CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine")
-	// Red Hat OpenShift on Google Cloud
-	CloudPlatformGCPOpenshift = CloudPlatformKey.String("gcp_openshift")
-	// Red Hat OpenShift on IBM Cloud
-	CloudPlatformIbmCloudOpenshift = CloudPlatformKey.String("ibm_cloud_openshift")
-	// Tencent Cloud Cloud Virtual Machine (CVM)
-	CloudPlatformTencentCloudCvm = CloudPlatformKey.String("tencent_cloud_cvm")
-	// Tencent Cloud Elastic Kubernetes Service (EKS)
-	CloudPlatformTencentCloudEKS = CloudPlatformKey.String("tencent_cloud_eks")
-	// Tencent Cloud Serverless Cloud Function (SCF)
-	CloudPlatformTencentCloudScf = CloudPlatformKey.String("tencent_cloud_scf")
-)
-
-var (
-	// Alibaba Cloud
-	CloudProviderAlibabaCloud = CloudProviderKey.String("alibaba_cloud")
-	// Amazon Web Services
-	CloudProviderAWS = CloudProviderKey.String("aws")
-	// Microsoft Azure
-	CloudProviderAzure = CloudProviderKey.String("azure")
-	// Google Cloud Platform
-	CloudProviderGCP = CloudProviderKey.String("gcp")
-	// Heroku Platform as a Service
-	CloudProviderHeroku = CloudProviderKey.String("heroku")
-	// IBM Cloud
-	CloudProviderIbmCloud = CloudProviderKey.String("ibm_cloud")
-	// Tencent Cloud
-	CloudProviderTencentCloud = CloudProviderKey.String("tencent_cloud")
-)
-
-// CloudAccountID returns an attribute KeyValue conforming to the
-// "cloud.account.id" semantic conventions. It represents the cloud account ID
-// the resource is assigned to.
-func CloudAccountID(val string) attribute.KeyValue {
-	return CloudAccountIDKey.String(val)
-}
-
-// CloudAvailabilityZone returns an attribute KeyValue conforming to the
-// "cloud.availability_zone" semantic conventions. It represents the cloud
-// regions often have multiple, isolated locations known as zones to increase
-// availability. Availability zone represents the zone where the resource is
-// running.
-func CloudAvailabilityZone(val string) attribute.KeyValue {
-	return CloudAvailabilityZoneKey.String(val)
-}
-
-// CloudRegion returns an attribute KeyValue conforming to the
-// "cloud.region" semantic conventions. It represents the geographical region
-// the resource is running.
-func CloudRegion(val string) attribute.KeyValue {
-	return CloudRegionKey.String(val)
-}
-
-// CloudResourceID returns an attribute KeyValue conforming to the
-// "cloud.resource_id" semantic conventions. It represents the cloud
-// provider-specific native identifier of the monitored cloud resource (e.g. an
-// [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
-// on AWS, a [fully qualified resource
-// ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id) on
-// Azure, a [full resource
-// name](https://cloud.google.com/apis/design/resource_names#full_resource_name)
-// on GCP)
-func CloudResourceID(val string) attribute.KeyValue {
-	return CloudResourceIDKey.String(val)
-}
-
-// Attributes for CloudEvents.
-const (
-	// CloudeventsEventIDKey is the attribute Key conforming to the
-	// "cloudevents.event_id" semantic conventions. It represents the
-	// [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id)
-	// uniquely identifies the event.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '123e4567-e89b-12d3-a456-426614174000', '0001'
-	CloudeventsEventIDKey = attribute.Key("cloudevents.event_id")
-
-	// CloudeventsEventSourceKey is the attribute Key conforming to the
-	// "cloudevents.event_source" semantic conventions. It represents the
-	// [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1)
-	// identifies the context in which an event happened.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'https://github.com/cloudevents',
-	// '/cloudevents/spec/pull/123', 'my-service'
-	CloudeventsEventSourceKey = attribute.Key("cloudevents.event_source")
-
-	// CloudeventsEventSpecVersionKey is the attribute Key conforming to the
-	// "cloudevents.event_spec_version" semantic conventions. It represents the
-	// [version of the CloudEvents
-	// specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion)
-	// which the event uses.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1.0'
-	CloudeventsEventSpecVersionKey = attribute.Key("cloudevents.event_spec_version")
-
-	// CloudeventsEventSubjectKey is the attribute Key conforming to the
-	// "cloudevents.event_subject" semantic conventions. It represents the
-	// [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject)
-	// of the event in the context of the event producer (identified by
-	// source).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'mynewfile.jpg'
-	CloudeventsEventSubjectKey = attribute.Key("cloudevents.event_subject")
-
-	// CloudeventsEventTypeKey is the attribute Key conforming to the
-	// "cloudevents.event_type" semantic conventions. It represents the
-	// [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type)
-	// contains a value describing the type of event related to the originating
-	// occurrence.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'com.github.pull_request.opened',
-	// 'com.example.object.deleted.v2'
-	CloudeventsEventTypeKey = attribute.Key("cloudevents.event_type")
-)
-
-// CloudeventsEventID returns an attribute KeyValue conforming to the
-// "cloudevents.event_id" semantic conventions. It represents the
-// [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id)
-// uniquely identifies the event.
-func CloudeventsEventID(val string) attribute.KeyValue {
-	return CloudeventsEventIDKey.String(val)
-}
-
-// CloudeventsEventSource returns an attribute KeyValue conforming to the
-// "cloudevents.event_source" semantic conventions. It represents the
-// [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1)
-// identifies the context in which an event happened.
-func CloudeventsEventSource(val string) attribute.KeyValue {
-	return CloudeventsEventSourceKey.String(val)
-}
-
-// CloudeventsEventSpecVersion returns an attribute KeyValue conforming to
-// the "cloudevents.event_spec_version" semantic conventions. It represents the
-// [version of the CloudEvents
-// specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion)
-// which the event uses.
-func CloudeventsEventSpecVersion(val string) attribute.KeyValue {
-	return CloudeventsEventSpecVersionKey.String(val)
-}
-
-// CloudeventsEventSubject returns an attribute KeyValue conforming to the
-// "cloudevents.event_subject" semantic conventions. It represents the
-// [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject)
-// of the event in the context of the event producer (identified by source).
-func CloudeventsEventSubject(val string) attribute.KeyValue {
-	return CloudeventsEventSubjectKey.String(val)
-}
-
-// CloudeventsEventType returns an attribute KeyValue conforming to the
-// "cloudevents.event_type" semantic conventions. It represents the
-// [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type)
-// contains a value describing the type of event related to the originating
-// occurrence.
-func CloudeventsEventType(val string) attribute.KeyValue {
-	return CloudeventsEventTypeKey.String(val)
-}
-
-// These attributes allow to report this unit of code and therefore to provide
-// more context about the span.
-const (
-	// CodeColumnKey is the attribute Key conforming to the "code.column"
-	// semantic conventions. It represents the column number in `code.filepath`
-	// best representing the operation. It SHOULD point within the code unit
-	// named in `code.function`.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 16
-	CodeColumnKey = attribute.Key("code.column")
-
-	// CodeFilepathKey is the attribute Key conforming to the "code.filepath"
-	// semantic conventions. It represents the source code file name that
-	// identifies the code unit as uniquely as possible (preferably an absolute
-	// file path).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/usr/local/MyApplication/content_root/app/index.php'
-	CodeFilepathKey = attribute.Key("code.filepath")
-
-	// CodeFunctionKey is the attribute Key conforming to the "code.function"
-	// semantic conventions. It represents the method or function name, or
-	// equivalent (usually rightmost part of the code unit's name).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'serveRequest'
-	CodeFunctionKey = attribute.Key("code.function")
-
-	// CodeLineNumberKey is the attribute Key conforming to the "code.lineno"
-	// semantic conventions. It represents the line number in `code.filepath`
-	// best representing the operation. It SHOULD point within the code unit
-	// named in `code.function`.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 42
-	CodeLineNumberKey = attribute.Key("code.lineno")
-
-	// CodeNamespaceKey is the attribute Key conforming to the "code.namespace"
-	// semantic conventions. It represents the "namespace" within which
-	// `code.function` is defined. Usually the qualified class or module name,
-	// such that `code.namespace` + some separator + `code.function` form a
-	// unique identifier for the code unit.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'com.example.MyHTTPService'
-	CodeNamespaceKey = attribute.Key("code.namespace")
-
-	// CodeStacktraceKey is the attribute Key conforming to the
-	// "code.stacktrace" semantic conventions. It represents a stacktrace as a
-	// string in the natural representation for the language runtime. The
-	// representation is to be determined and documented by each language SIG.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'at
-	// com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at '
-	//  'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at '
-	//  'com.example.GenerateTrace.main(GenerateTrace.java:5)'
-	CodeStacktraceKey = attribute.Key("code.stacktrace")
-)
-
-// CodeColumn returns an attribute KeyValue conforming to the "code.column"
-// semantic conventions. It represents the column number in `code.filepath`
-// best representing the operation. It SHOULD point within the code unit named
-// in `code.function`.
-func CodeColumn(val int) attribute.KeyValue {
-	return CodeColumnKey.Int(val)
-}
-
-// CodeFilepath returns an attribute KeyValue conforming to the
-// "code.filepath" semantic conventions. It represents the source code file
-// name that identifies the code unit as uniquely as possible (preferably an
-// absolute file path).
-func CodeFilepath(val string) attribute.KeyValue {
-	return CodeFilepathKey.String(val)
-}
-
-// CodeFunction returns an attribute KeyValue conforming to the
-// "code.function" semantic conventions. It represents the method or function
-// name, or equivalent (usually rightmost part of the code unit's name).
-func CodeFunction(val string) attribute.KeyValue {
-	return CodeFunctionKey.String(val)
-}
-
-// CodeLineNumber returns an attribute KeyValue conforming to the "code.lineno"
-// semantic conventions. It represents the line number in `code.filepath` best
-// representing the operation. It SHOULD point within the code unit named in
-// `code.function`.
-func CodeLineNumber(val int) attribute.KeyValue {
-	return CodeLineNumberKey.Int(val)
-}
-
-// CodeNamespace returns an attribute KeyValue conforming to the
-// "code.namespace" semantic conventions. It represents the "namespace" within
-// which `code.function` is defined. Usually the qualified class or module
-// name, such that `code.namespace` + some separator + `code.function` form a
-// unique identifier for the code unit.
-func CodeNamespace(val string) attribute.KeyValue {
-	return CodeNamespaceKey.String(val)
-}
-
-// CodeStacktrace returns an attribute KeyValue conforming to the
-// "code.stacktrace" semantic conventions. It represents a stacktrace as a
-// string in the natural representation for the language runtime. The
-// representation is to be determined and documented by each language SIG.
-func CodeStacktrace(val string) attribute.KeyValue {
-	return CodeStacktraceKey.String(val)
-}
-
-// A container instance.
-const (
-	// ContainerCommandKey is the attribute Key conforming to the
-	// "container.command" semantic conventions. It represents the command used
-	// to run the container (i.e. the command name).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'otelcontribcol'
-	// Note: If using embedded credentials or sensitive data, it is recommended
-	// to remove them to prevent potential leakage.
-	ContainerCommandKey = attribute.Key("container.command")
-
-	// ContainerCommandArgsKey is the attribute Key conforming to the
-	// "container.command_args" semantic conventions. It represents the all the
-	// command arguments (including the command/executable itself) run by the
-	// container. [2]
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'otelcontribcol, --config, config.yaml'
-	ContainerCommandArgsKey = attribute.Key("container.command_args")
-
-	// ContainerCommandLineKey is the attribute Key conforming to the
-	// "container.command_line" semantic conventions. It represents the full
-	// command run by the container as a single string representing the full
-	// command. [2]
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'otelcontribcol --config config.yaml'
-	ContainerCommandLineKey = attribute.Key("container.command_line")
-
-	// ContainerCPUStateKey is the attribute Key conforming to the
-	// "container.cpu.state" semantic conventions. It represents the CPU state
-	// for this data point.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'user', 'kernel'
-	ContainerCPUStateKey = attribute.Key("container.cpu.state")
-
-	// ContainerIDKey is the attribute Key conforming to the "container.id"
-	// semantic conventions. It represents the container ID. Usually a UUID, as
-	// for example used to [identify Docker
-	// containers](https://docs.docker.com/engine/reference/run/#container-identification).
-	// The UUID might be abbreviated.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'a3bf90e006b2'
-	ContainerIDKey = attribute.Key("container.id")
-
-	// ContainerImageIDKey is the attribute Key conforming to the
-	// "container.image.id" semantic conventions. It represents the runtime
-	// specific image identifier. Usually a hash algorithm followed by a UUID.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f'
-	// Note: Docker defines a sha256 of the image id; `container.image.id`
-	// corresponds to the `Image` field from the Docker container inspect
-	// [API](https://docs.docker.com/engine/api/v1.43/#tag/Container/operation/ContainerInspect)
-	// endpoint.
-	// K8S defines a link to the container registry repository with digest
-	// `"imageID": "registry.azurecr.io
-	// /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"`.
-	// The ID is assigned by the container runtime and can vary in different
-	// environments. Consider using `oci.manifest.digest` if it is important to
-	// identify the same image in different environments/runtimes.
-	ContainerImageIDKey = attribute.Key("container.image.id")
-
-	// ContainerImageNameKey is the attribute Key conforming to the
-	// "container.image.name" semantic conventions. It represents the name of
-	// the image the container was built on.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'gcr.io/opentelemetry/operator'
-	ContainerImageNameKey = attribute.Key("container.image.name")
-
-	// ContainerImageRepoDigestsKey is the attribute Key conforming to the
-	// "container.image.repo_digests" semantic conventions. It represents the
-	// repo digests of the container image as provided by the container
-	// runtime.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb',
-	// 'internal.registry.example.com:5000/example@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578'
-	// Note:
-	// [Docker](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect)
-	// and
-	// [CRI](https://github.com/kubernetes/cri-api/blob/c75ef5b473bbe2d0a4fc92f82235efd665ea8e9f/pkg/apis/runtime/v1/api.proto#L1237-L1238)
-	// report those under the `RepoDigests` field.
-	ContainerImageRepoDigestsKey = attribute.Key("container.image.repo_digests")
-
-	// ContainerImageTagsKey is the attribute Key conforming to the
-	// "container.image.tags" semantic conventions. It represents the container
-	// image tags. An example can be found in [Docker Image
-	// Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect).
-	// Should be only the `` section of the full name for example from
-	// `registry.example.com/my-org/my-image:`.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'v1.27.1', '3.5.7-0'
-	ContainerImageTagsKey = attribute.Key("container.image.tags")
-
-	// ContainerNameKey is the attribute Key conforming to the "container.name"
-	// semantic conventions. It represents the container name used by container
-	// runtime.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry-autoconf'
-	ContainerNameKey = attribute.Key("container.name")
-
-	// ContainerRuntimeKey is the attribute Key conforming to the
-	// "container.runtime" semantic conventions. It represents the container
-	// runtime managing this container.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'docker', 'containerd', 'rkt'
-	ContainerRuntimeKey = attribute.Key("container.runtime")
-)
-
-var (
-	// When tasks of the cgroup are in user mode (Linux). When all container processes are in user mode (Windows)
-	ContainerCPUStateUser = ContainerCPUStateKey.String("user")
-	// When CPU is used by the system (host OS)
-	ContainerCPUStateSystem = ContainerCPUStateKey.String("system")
-	// When tasks of the cgroup are in kernel mode (Linux). When all container processes are in kernel mode (Windows)
-	ContainerCPUStateKernel = ContainerCPUStateKey.String("kernel")
-)
-
-// ContainerCommand returns an attribute KeyValue conforming to the
-// "container.command" semantic conventions. It represents the command used to
-// run the container (i.e. the command name).
-func ContainerCommand(val string) attribute.KeyValue {
-	return ContainerCommandKey.String(val)
-}
-
-// ContainerCommandArgs returns an attribute KeyValue conforming to the
-// "container.command_args" semantic conventions. It represents the all the
-// command arguments (including the command/executable itself) run by the
-// container. [2]
-func ContainerCommandArgs(val ...string) attribute.KeyValue {
-	return ContainerCommandArgsKey.StringSlice(val)
-}
-
-// ContainerCommandLine returns an attribute KeyValue conforming to the
-// "container.command_line" semantic conventions. It represents the full
-// command run by the container as a single string representing the full
-// command. [2]
-func ContainerCommandLine(val string) attribute.KeyValue {
-	return ContainerCommandLineKey.String(val)
-}
-
-// ContainerID returns an attribute KeyValue conforming to the
-// "container.id" semantic conventions. It represents the container ID. Usually
-// a UUID, as for example used to [identify Docker
-// containers](https://docs.docker.com/engine/reference/run/#container-identification).
-// The UUID might be abbreviated.
-func ContainerID(val string) attribute.KeyValue {
-	return ContainerIDKey.String(val)
-}
-
-// ContainerImageID returns an attribute KeyValue conforming to the
-// "container.image.id" semantic conventions. It represents the runtime
-// specific image identifier. Usually a hash algorithm followed by a UUID.
-func ContainerImageID(val string) attribute.KeyValue {
-	return ContainerImageIDKey.String(val)
-}
-
-// ContainerImageName returns an attribute KeyValue conforming to the
-// "container.image.name" semantic conventions. It represents the name of the
-// image the container was built on.
-func ContainerImageName(val string) attribute.KeyValue {
-	return ContainerImageNameKey.String(val)
-}
-
-// ContainerImageRepoDigests returns an attribute KeyValue conforming to the
-// "container.image.repo_digests" semantic conventions. It represents the repo
-// digests of the container image as provided by the container runtime.
-func ContainerImageRepoDigests(val ...string) attribute.KeyValue {
-	return ContainerImageRepoDigestsKey.StringSlice(val)
-}
-
-// ContainerImageTags returns an attribute KeyValue conforming to the
-// "container.image.tags" semantic conventions. It represents the container
-// image tags. An example can be found in [Docker Image
-// Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect).
-// Should be only the `` section of the full name for example from
-// `registry.example.com/my-org/my-image:`.
-func ContainerImageTags(val ...string) attribute.KeyValue {
-	return ContainerImageTagsKey.StringSlice(val)
-}
-
-// ContainerName returns an attribute KeyValue conforming to the
-// "container.name" semantic conventions. It represents the container name used
-// by container runtime.
-func ContainerName(val string) attribute.KeyValue {
-	return ContainerNameKey.String(val)
-}
-
-// ContainerRuntime returns an attribute KeyValue conforming to the
-// "container.runtime" semantic conventions. It represents the container
-// runtime managing this container.
-func ContainerRuntime(val string) attribute.KeyValue {
-	return ContainerRuntimeKey.String(val)
-}
-
-// This group defines the attributes used to describe telemetry in the context
-// of databases.
-const (
-	// DBClientConnectionsPoolNameKey is the attribute Key conforming to the
-	// "db.client.connections.pool.name" semantic conventions. It represents
-	// the name of the connection pool; unique within the instrumented
-	// application. In case the connection pool implementation doesn't provide
-	// a name, instrumentation should use a combination of `server.address` and
-	// `server.port` attributes formatted as `server.address:server.port`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myDataSource'
-	DBClientConnectionsPoolNameKey = attribute.Key("db.client.connections.pool.name")
-
-	// DBClientConnectionsStateKey is the attribute Key conforming to the
-	// "db.client.connections.state" semantic conventions. It represents the
-	// state of a connection in the pool
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'idle'
-	DBClientConnectionsStateKey = attribute.Key("db.client.connections.state")
-
-	// DBCollectionNameKey is the attribute Key conforming to the
-	// "db.collection.name" semantic conventions. It represents the name of a
-	// collection (table, container) within the database.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'public.users', 'customers'
-	// Note: If the collection name is parsed from the query, it SHOULD match
-	// the value provided in the query and may be qualified with the schema and
-	// database name.
-	// It is RECOMMENDED to capture the value as provided by the application
-	// without attempting to do any case normalization.
-	DBCollectionNameKey = attribute.Key("db.collection.name")
-
-	// DBNamespaceKey is the attribute Key conforming to the "db.namespace"
-	// semantic conventions. It represents the name of the database, fully
-	// qualified within the server address and port.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'customers', 'test.users'
-	// Note: If a database system has multiple namespace components, they
-	// SHOULD be concatenated (potentially using database system specific
-	// conventions) from most general to most specific namespace component, and
-	// more specific namespaces SHOULD NOT be captured without the more general
-	// namespaces, to ensure that "startswith" queries for the more general
-	// namespaces will be valid.
-	// Semantic conventions for individual database systems SHOULD document
-	// what `db.namespace` means in the context of that system.
-	// It is RECOMMENDED to capture the value as provided by the application
-	// without attempting to do any case normalization.
-	DBNamespaceKey = attribute.Key("db.namespace")
-
-	// DBOperationNameKey is the attribute Key conforming to the
-	// "db.operation.name" semantic conventions. It represents the name of the
-	// operation or command being executed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'findAndModify', 'HMSET', 'SELECT'
-	// Note: It is RECOMMENDED to capture the value as provided by the
-	// application without attempting to do any case normalization.
-	DBOperationNameKey = attribute.Key("db.operation.name")
-
-	// DBQueryTextKey is the attribute Key conforming to the "db.query.text"
-	// semantic conventions. It represents the database query being executed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'SELECT * FROM wuser_table where username = ?', 'SET mykey
-	// "WuValue"'
-	DBQueryTextKey = attribute.Key("db.query.text")
-
-	// DBSystemKey is the attribute Key conforming to the "db.system" semantic
-	// conventions. It represents the database management system (DBMS) product
-	// as identified by the client instrumentation.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: The actual DBMS may differ from the one identified by the client.
-	// For example, when using PostgreSQL client libraries to connect to a
-	// CockroachDB, the `db.system` is set to `postgresql` based on the
-	// instrumentation's best knowledge.
-	DBSystemKey = attribute.Key("db.system")
-)
-
-var (
-	// idle
-	DBClientConnectionsStateIdle = DBClientConnectionsStateKey.String("idle")
-	// used
-	DBClientConnectionsStateUsed = DBClientConnectionsStateKey.String("used")
-)
-
-var (
-	// Some other SQL database. Fallback only. See notes
-	DBSystemOtherSQL = DBSystemKey.String("other_sql")
-	// Microsoft SQL Server
-	DBSystemMSSQL = DBSystemKey.String("mssql")
-	// Microsoft SQL Server Compact
-	DBSystemMssqlcompact = DBSystemKey.String("mssqlcompact")
-	// MySQL
-	DBSystemMySQL = DBSystemKey.String("mysql")
-	// Oracle Database
-	DBSystemOracle = DBSystemKey.String("oracle")
-	// IBM DB2
-	DBSystemDB2 = DBSystemKey.String("db2")
-	// PostgreSQL
-	DBSystemPostgreSQL = DBSystemKey.String("postgresql")
-	// Amazon Redshift
-	DBSystemRedshift = DBSystemKey.String("redshift")
-	// Apache Hive
-	DBSystemHive = DBSystemKey.String("hive")
-	// Cloudscape
-	DBSystemCloudscape = DBSystemKey.String("cloudscape")
-	// HyperSQL DataBase
-	DBSystemHSQLDB = DBSystemKey.String("hsqldb")
-	// Progress Database
-	DBSystemProgress = DBSystemKey.String("progress")
-	// SAP MaxDB
-	DBSystemMaxDB = DBSystemKey.String("maxdb")
-	// SAP HANA
-	DBSystemHanaDB = DBSystemKey.String("hanadb")
-	// Ingres
-	DBSystemIngres = DBSystemKey.String("ingres")
-	// FirstSQL
-	DBSystemFirstSQL = DBSystemKey.String("firstsql")
-	// EnterpriseDB
-	DBSystemEDB = DBSystemKey.String("edb")
-	// InterSystems Caché
-	DBSystemCache = DBSystemKey.String("cache")
-	// Adabas (Adaptable Database System)
-	DBSystemAdabas = DBSystemKey.String("adabas")
-	// Firebird
-	DBSystemFirebird = DBSystemKey.String("firebird")
-	// Apache Derby
-	DBSystemDerby = DBSystemKey.String("derby")
-	// FileMaker
-	DBSystemFilemaker = DBSystemKey.String("filemaker")
-	// Informix
-	DBSystemInformix = DBSystemKey.String("informix")
-	// InstantDB
-	DBSystemInstantDB = DBSystemKey.String("instantdb")
-	// InterBase
-	DBSystemInterbase = DBSystemKey.String("interbase")
-	// MariaDB
-	DBSystemMariaDB = DBSystemKey.String("mariadb")
-	// Netezza
-	DBSystemNetezza = DBSystemKey.String("netezza")
-	// Pervasive PSQL
-	DBSystemPervasive = DBSystemKey.String("pervasive")
-	// PointBase
-	DBSystemPointbase = DBSystemKey.String("pointbase")
-	// SQLite
-	DBSystemSqlite = DBSystemKey.String("sqlite")
-	// Sybase
-	DBSystemSybase = DBSystemKey.String("sybase")
-	// Teradata
-	DBSystemTeradata = DBSystemKey.String("teradata")
-	// Vertica
-	DBSystemVertica = DBSystemKey.String("vertica")
-	// H2
-	DBSystemH2 = DBSystemKey.String("h2")
-	// ColdFusion IMQ
-	DBSystemColdfusion = DBSystemKey.String("coldfusion")
-	// Apache Cassandra
-	DBSystemCassandra = DBSystemKey.String("cassandra")
-	// Apache HBase
-	DBSystemHBase = DBSystemKey.String("hbase")
-	// MongoDB
-	DBSystemMongoDB = DBSystemKey.String("mongodb")
-	// Redis
-	DBSystemRedis = DBSystemKey.String("redis")
-	// Couchbase
-	DBSystemCouchbase = DBSystemKey.String("couchbase")
-	// CouchDB
-	DBSystemCouchDB = DBSystemKey.String("couchdb")
-	// Microsoft Azure Cosmos DB
-	DBSystemCosmosDB = DBSystemKey.String("cosmosdb")
-	// Amazon DynamoDB
-	DBSystemDynamoDB = DBSystemKey.String("dynamodb")
-	// Neo4j
-	DBSystemNeo4j = DBSystemKey.String("neo4j")
-	// Apache Geode
-	DBSystemGeode = DBSystemKey.String("geode")
-	// Elasticsearch
-	DBSystemElasticsearch = DBSystemKey.String("elasticsearch")
-	// Memcached
-	DBSystemMemcached = DBSystemKey.String("memcached")
-	// CockroachDB
-	DBSystemCockroachdb = DBSystemKey.String("cockroachdb")
-	// OpenSearch
-	DBSystemOpensearch = DBSystemKey.String("opensearch")
-	// ClickHouse
-	DBSystemClickhouse = DBSystemKey.String("clickhouse")
-	// Cloud Spanner
-	DBSystemSpanner = DBSystemKey.String("spanner")
-	// Trino
-	DBSystemTrino = DBSystemKey.String("trino")
-)
-
-// DBClientConnectionsPoolName returns an attribute KeyValue conforming to
-// the "db.client.connections.pool.name" semantic conventions. It represents
-// the name of the connection pool; unique within the instrumented application.
-// In case the connection pool implementation doesn't provide a name,
-// instrumentation should use a combination of `server.address` and
-// `server.port` attributes formatted as `server.address:server.port`.
-func DBClientConnectionsPoolName(val string) attribute.KeyValue {
-	return DBClientConnectionsPoolNameKey.String(val)
-}
-
-// DBCollectionName returns an attribute KeyValue conforming to the
-// "db.collection.name" semantic conventions. It represents the name of a
-// collection (table, container) within the database.
-func DBCollectionName(val string) attribute.KeyValue {
-	return DBCollectionNameKey.String(val)
-}
-
-// DBNamespace returns an attribute KeyValue conforming to the
-// "db.namespace" semantic conventions. It represents the name of the database,
-// fully qualified within the server address and port.
-func DBNamespace(val string) attribute.KeyValue {
-	return DBNamespaceKey.String(val)
-}
-
-// DBOperationName returns an attribute KeyValue conforming to the
-// "db.operation.name" semantic conventions. It represents the name of the
-// operation or command being executed.
-func DBOperationName(val string) attribute.KeyValue {
-	return DBOperationNameKey.String(val)
-}
-
-// DBQueryText returns an attribute KeyValue conforming to the
-// "db.query.text" semantic conventions. It represents the database query being
-// executed.
-func DBQueryText(val string) attribute.KeyValue {
-	return DBQueryTextKey.String(val)
-}
-
-// This group defines attributes for Cassandra.
-const (
-	// DBCassandraConsistencyLevelKey is the attribute Key conforming to the
-	// "db.cassandra.consistency_level" semantic conventions. It represents the
-	// consistency level of the query. Based on consistency values from
-	// [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html).
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	DBCassandraConsistencyLevelKey = attribute.Key("db.cassandra.consistency_level")
-
-	// DBCassandraCoordinatorDCKey is the attribute Key conforming to the
-	// "db.cassandra.coordinator.dc" semantic conventions. It represents the
-	// data center of the coordinating node for a query.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'us-west-2'
-	DBCassandraCoordinatorDCKey = attribute.Key("db.cassandra.coordinator.dc")
-
-	// DBCassandraCoordinatorIDKey is the attribute Key conforming to the
-	// "db.cassandra.coordinator.id" semantic conventions. It represents the ID
-	// of the coordinating node for a query.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af'
-	DBCassandraCoordinatorIDKey = attribute.Key("db.cassandra.coordinator.id")
-
-	// DBCassandraIdempotenceKey is the attribute Key conforming to the
-	// "db.cassandra.idempotence" semantic conventions. It represents the
-	// whether or not the query is idempotent.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	DBCassandraIdempotenceKey = attribute.Key("db.cassandra.idempotence")
-
-	// DBCassandraPageSizeKey is the attribute Key conforming to the
-	// "db.cassandra.page_size" semantic conventions. It represents the fetch
-	// size used for paging, i.e. how many rows will be returned at once.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 5000
-	DBCassandraPageSizeKey = attribute.Key("db.cassandra.page_size")
-
-	// DBCassandraSpeculativeExecutionCountKey is the attribute Key conforming
-	// to the "db.cassandra.speculative_execution_count" semantic conventions.
-	// It represents the number of times a query was speculatively executed.
-	// Not set or `0` if the query was not executed speculatively.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 0, 2
-	DBCassandraSpeculativeExecutionCountKey = attribute.Key("db.cassandra.speculative_execution_count")
-)
-
-var (
-	// all
-	DBCassandraConsistencyLevelAll = DBCassandraConsistencyLevelKey.String("all")
-	// each_quorum
-	DBCassandraConsistencyLevelEachQuorum = DBCassandraConsistencyLevelKey.String("each_quorum")
-	// quorum
-	DBCassandraConsistencyLevelQuorum = DBCassandraConsistencyLevelKey.String("quorum")
-	// local_quorum
-	DBCassandraConsistencyLevelLocalQuorum = DBCassandraConsistencyLevelKey.String("local_quorum")
-	// one
-	DBCassandraConsistencyLevelOne = DBCassandraConsistencyLevelKey.String("one")
-	// two
-	DBCassandraConsistencyLevelTwo = DBCassandraConsistencyLevelKey.String("two")
-	// three
-	DBCassandraConsistencyLevelThree = DBCassandraConsistencyLevelKey.String("three")
-	// local_one
-	DBCassandraConsistencyLevelLocalOne = DBCassandraConsistencyLevelKey.String("local_one")
-	// any
-	DBCassandraConsistencyLevelAny = DBCassandraConsistencyLevelKey.String("any")
-	// serial
-	DBCassandraConsistencyLevelSerial = DBCassandraConsistencyLevelKey.String("serial")
-	// local_serial
-	DBCassandraConsistencyLevelLocalSerial = DBCassandraConsistencyLevelKey.String("local_serial")
-)
-
-// DBCassandraCoordinatorDC returns an attribute KeyValue conforming to the
-// "db.cassandra.coordinator.dc" semantic conventions. It represents the data
-// center of the coordinating node for a query.
-func DBCassandraCoordinatorDC(val string) attribute.KeyValue {
-	return DBCassandraCoordinatorDCKey.String(val)
-}
-
-// DBCassandraCoordinatorID returns an attribute KeyValue conforming to the
-// "db.cassandra.coordinator.id" semantic conventions. It represents the ID of
-// the coordinating node for a query.
-func DBCassandraCoordinatorID(val string) attribute.KeyValue {
-	return DBCassandraCoordinatorIDKey.String(val)
-}
-
-// DBCassandraIdempotence returns an attribute KeyValue conforming to the
-// "db.cassandra.idempotence" semantic conventions. It represents the whether
-// or not the query is idempotent.
-func DBCassandraIdempotence(val bool) attribute.KeyValue {
-	return DBCassandraIdempotenceKey.Bool(val)
-}
-
-// DBCassandraPageSize returns an attribute KeyValue conforming to the
-// "db.cassandra.page_size" semantic conventions. It represents the fetch size
-// used for paging, i.e. how many rows will be returned at once.
-func DBCassandraPageSize(val int) attribute.KeyValue {
-	return DBCassandraPageSizeKey.Int(val)
-}
-
-// DBCassandraSpeculativeExecutionCount returns an attribute KeyValue
-// conforming to the "db.cassandra.speculative_execution_count" semantic
-// conventions. It represents the number of times a query was speculatively
-// executed. Not set or `0` if the query was not executed speculatively.
-func DBCassandraSpeculativeExecutionCount(val int) attribute.KeyValue {
-	return DBCassandraSpeculativeExecutionCountKey.Int(val)
-}
-
-// This group defines attributes for Azure Cosmos DB.
-const (
-	// DBCosmosDBClientIDKey is the attribute Key conforming to the
-	// "db.cosmosdb.client_id" semantic conventions. It represents the unique
-	// Cosmos client instance id.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '3ba4827d-4422-483f-b59f-85b74211c11d'
-	DBCosmosDBClientIDKey = attribute.Key("db.cosmosdb.client_id")
-
-	// DBCosmosDBConnectionModeKey is the attribute Key conforming to the
-	// "db.cosmosdb.connection_mode" semantic conventions. It represents the
-	// cosmos client connection mode.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	DBCosmosDBConnectionModeKey = attribute.Key("db.cosmosdb.connection_mode")
-
-	// DBCosmosDBOperationTypeKey is the attribute Key conforming to the
-	// "db.cosmosdb.operation_type" semantic conventions. It represents the
-	// cosmosDB Operation Type.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	DBCosmosDBOperationTypeKey = attribute.Key("db.cosmosdb.operation_type")
-
-	// DBCosmosDBRequestChargeKey is the attribute Key conforming to the
-	// "db.cosmosdb.request_charge" semantic conventions. It represents the rU
-	// consumed for that operation
-	//
-	// Type: double
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 46.18, 1.0
-	DBCosmosDBRequestChargeKey = attribute.Key("db.cosmosdb.request_charge")
-
-	// DBCosmosDBRequestContentLengthKey is the attribute Key conforming to the
-	// "db.cosmosdb.request_content_length" semantic conventions. It represents
-	// the request payload size in bytes
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	DBCosmosDBRequestContentLengthKey = attribute.Key("db.cosmosdb.request_content_length")
-
-	// DBCosmosDBStatusCodeKey is the attribute Key conforming to the
-	// "db.cosmosdb.status_code" semantic conventions. It represents the cosmos
-	// DB status code.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 200, 201
-	DBCosmosDBStatusCodeKey = attribute.Key("db.cosmosdb.status_code")
-
-	// DBCosmosDBSubStatusCodeKey is the attribute Key conforming to the
-	// "db.cosmosdb.sub_status_code" semantic conventions. It represents the
-	// cosmos DB sub status code.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1000, 1002
-	DBCosmosDBSubStatusCodeKey = attribute.Key("db.cosmosdb.sub_status_code")
-)
-
-var (
-	// Gateway (HTTP) connections mode
-	DBCosmosDBConnectionModeGateway = DBCosmosDBConnectionModeKey.String("gateway")
-	// Direct connection
-	DBCosmosDBConnectionModeDirect = DBCosmosDBConnectionModeKey.String("direct")
-)
-
-var (
-	// invalid
-	DBCosmosDBOperationTypeInvalid = DBCosmosDBOperationTypeKey.String("Invalid")
-	// create
-	DBCosmosDBOperationTypeCreate = DBCosmosDBOperationTypeKey.String("Create")
-	// patch
-	DBCosmosDBOperationTypePatch = DBCosmosDBOperationTypeKey.String("Patch")
-	// read
-	DBCosmosDBOperationTypeRead = DBCosmosDBOperationTypeKey.String("Read")
-	// read_feed
-	DBCosmosDBOperationTypeReadFeed = DBCosmosDBOperationTypeKey.String("ReadFeed")
-	// delete
-	DBCosmosDBOperationTypeDelete = DBCosmosDBOperationTypeKey.String("Delete")
-	// replace
-	DBCosmosDBOperationTypeReplace = DBCosmosDBOperationTypeKey.String("Replace")
-	// execute
-	DBCosmosDBOperationTypeExecute = DBCosmosDBOperationTypeKey.String("Execute")
-	// query
-	DBCosmosDBOperationTypeQuery = DBCosmosDBOperationTypeKey.String("Query")
-	// head
-	DBCosmosDBOperationTypeHead = DBCosmosDBOperationTypeKey.String("Head")
-	// head_feed
-	DBCosmosDBOperationTypeHeadFeed = DBCosmosDBOperationTypeKey.String("HeadFeed")
-	// upsert
-	DBCosmosDBOperationTypeUpsert = DBCosmosDBOperationTypeKey.String("Upsert")
-	// batch
-	DBCosmosDBOperationTypeBatch = DBCosmosDBOperationTypeKey.String("Batch")
-	// query_plan
-	DBCosmosDBOperationTypeQueryPlan = DBCosmosDBOperationTypeKey.String("QueryPlan")
-	// execute_javascript
-	DBCosmosDBOperationTypeExecuteJavascript = DBCosmosDBOperationTypeKey.String("ExecuteJavaScript")
-)
-
-// DBCosmosDBClientID returns an attribute KeyValue conforming to the
-// "db.cosmosdb.client_id" semantic conventions. It represents the unique
-// Cosmos client instance id.
-func DBCosmosDBClientID(val string) attribute.KeyValue {
-	return DBCosmosDBClientIDKey.String(val)
-}
-
-// DBCosmosDBRequestCharge returns an attribute KeyValue conforming to the
-// "db.cosmosdb.request_charge" semantic conventions. It represents the rU
-// consumed for that operation
-func DBCosmosDBRequestCharge(val float64) attribute.KeyValue {
-	return DBCosmosDBRequestChargeKey.Float64(val)
-}
-
-// DBCosmosDBRequestContentLength returns an attribute KeyValue conforming
-// to the "db.cosmosdb.request_content_length" semantic conventions. It
-// represents the request payload size in bytes
-func DBCosmosDBRequestContentLength(val int) attribute.KeyValue {
-	return DBCosmosDBRequestContentLengthKey.Int(val)
-}
-
-// DBCosmosDBStatusCode returns an attribute KeyValue conforming to the
-// "db.cosmosdb.status_code" semantic conventions. It represents the cosmos DB
-// status code.
-func DBCosmosDBStatusCode(val int) attribute.KeyValue {
-	return DBCosmosDBStatusCodeKey.Int(val)
-}
-
-// DBCosmosDBSubStatusCode returns an attribute KeyValue conforming to the
-// "db.cosmosdb.sub_status_code" semantic conventions. It represents the cosmos
-// DB sub status code.
-func DBCosmosDBSubStatusCode(val int) attribute.KeyValue {
-	return DBCosmosDBSubStatusCodeKey.Int(val)
-}
-
-// This group defines attributes for Elasticsearch.
-const (
-	// DBElasticsearchClusterNameKey is the attribute Key conforming to the
-	// "db.elasticsearch.cluster.name" semantic conventions. It represents the
-	// represents the identifier of an Elasticsearch cluster.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'e9106fc68e3044f0b1475b04bf4ffd5f'
-	DBElasticsearchClusterNameKey = attribute.Key("db.elasticsearch.cluster.name")
-
-	// DBElasticsearchNodeNameKey is the attribute Key conforming to the
-	// "db.elasticsearch.node.name" semantic conventions. It represents the
-	// represents the human-readable identifier of the node/instance to which a
-	// request was routed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'instance-0000000001'
-	DBElasticsearchNodeNameKey = attribute.Key("db.elasticsearch.node.name")
-)
-
-// DBElasticsearchClusterName returns an attribute KeyValue conforming to
-// the "db.elasticsearch.cluster.name" semantic conventions. It represents the
-// represents the identifier of an Elasticsearch cluster.
-func DBElasticsearchClusterName(val string) attribute.KeyValue {
-	return DBElasticsearchClusterNameKey.String(val)
-}
-
-// DBElasticsearchNodeName returns an attribute KeyValue conforming to the
-// "db.elasticsearch.node.name" semantic conventions. It represents the
-// represents the human-readable identifier of the node/instance to which a
-// request was routed.
-func DBElasticsearchNodeName(val string) attribute.KeyValue {
-	return DBElasticsearchNodeNameKey.String(val)
-}
-
-// Attributes for software deployments.
-const (
-	// DeploymentEnvironmentKey is the attribute Key conforming to the
-	// "deployment.environment" semantic conventions. It represents the name of
-	// the [deployment
-	// environment](https://wikipedia.org/wiki/Deployment_environment) (aka
-	// deployment tier).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'staging', 'production'
-	// Note: `deployment.environment` does not affect the uniqueness
-	// constraints defined through
-	// the `service.namespace`, `service.name` and `service.instance.id`
-	// resource attributes.
-	// This implies that resources carrying the following attribute
-	// combinations MUST be
-	// considered to be identifying the same service:
-	//
-	// * `service.name=frontend`, `deployment.environment=production`
-	// * `service.name=frontend`, `deployment.environment=staging`.
-	DeploymentEnvironmentKey = attribute.Key("deployment.environment")
-)
-
-// DeploymentEnvironment returns an attribute KeyValue conforming to the
-// "deployment.environment" semantic conventions. It represents the name of the
-// [deployment environment](https://wikipedia.org/wiki/Deployment_environment)
-// (aka deployment tier).
-func DeploymentEnvironment(val string) attribute.KeyValue {
-	return DeploymentEnvironmentKey.String(val)
-}
-
-// Attributes that represents an occurrence of a lifecycle transition on the
-// Android platform.
-const (
-	// AndroidStateKey is the attribute Key conforming to the "android.state"
-	// semantic conventions. It represents the deprecated use the
-	// `device.app.lifecycle` event definition including `android.state` as a
-	// payload field instead.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: The Android lifecycle states are defined in [Activity lifecycle
-	// callbacks](https://developer.android.com/guide/components/activities/activity-lifecycle#lc),
-	// and from which the `OS identifiers` are derived.
-	AndroidStateKey = attribute.Key("android.state")
-)
-
-var (
-	// Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time
-	AndroidStateCreated = AndroidStateKey.String("created")
-	// Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state
-	AndroidStateBackground = AndroidStateKey.String("background")
-	// Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states
-	AndroidStateForeground = AndroidStateKey.String("foreground")
-)
-
-// These attributes may be used to describe the receiver of a network
-// exchange/packet. These should be used when there is no client/server
-// relationship between the two sides, or when that relationship is unknown.
-// This covers low-level network interactions (e.g. packet tracing) where you
-// don't know if there was a connection or which side initiated it. This also
-// covers unidirectional UDP flows and peer-to-peer communication where the
-// "user-facing" surface of the protocol / API doesn't expose a clear notion of
-// client and server.
-const (
-	// DestinationAddressKey is the attribute Key conforming to the
-	// "destination.address" semantic conventions. It represents the
-	// destination address - domain name if available without reverse DNS
-	// lookup; otherwise, IP address or Unix domain socket name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'destination.example.com', '10.1.2.80', '/tmp/my.sock'
-	// Note: When observed from the source side, and when communicating through
-	// an intermediary, `destination.address` SHOULD represent the destination
-	// address behind any intermediaries, for example proxies, if it's
-	// available.
-	DestinationAddressKey = attribute.Key("destination.address")
-
-	// DestinationPortKey is the attribute Key conforming to the
-	// "destination.port" semantic conventions. It represents the destination
-	// port number
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3389, 2888
-	DestinationPortKey = attribute.Key("destination.port")
-)
-
-// DestinationAddress returns an attribute KeyValue conforming to the
-// "destination.address" semantic conventions. It represents the destination
-// address - domain name if available without reverse DNS lookup; otherwise, IP
-// address or Unix domain socket name.
-func DestinationAddress(val string) attribute.KeyValue {
-	return DestinationAddressKey.String(val)
-}
-
-// DestinationPort returns an attribute KeyValue conforming to the
-// "destination.port" semantic conventions. It represents the destination port
-// number
-func DestinationPort(val int) attribute.KeyValue {
-	return DestinationPortKey.Int(val)
-}
-
-// Describes device attributes.
-const (
-	// DeviceIDKey is the attribute Key conforming to the "device.id" semantic
-	// conventions. It represents a unique identifier representing the device
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092'
-	// Note: The device identifier MUST only be defined using the values
-	// outlined below. This value is not an advertising identifier and MUST NOT
-	// be used as such. On iOS (Swift or Objective-C), this value MUST be equal
-	// to the [vendor
-	// identifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor).
-	// On Android (Java or Kotlin), this value MUST be equal to the Firebase
-	// Installation ID or a globally unique UUID which is persisted across
-	// sessions in your application. More information can be found
-	// [here](https://developer.android.com/training/articles/user-data-ids) on
-	// best practices and exact implementation details. Caution should be taken
-	// when storing personal data or anything which can identify a user. GDPR
-	// and data protection laws may apply, ensure you do your own due
-	// diligence.
-	DeviceIDKey = attribute.Key("device.id")
-
-	// DeviceManufacturerKey is the attribute Key conforming to the
-	// "device.manufacturer" semantic conventions. It represents the name of
-	// the device manufacturer
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Apple', 'Samsung'
-	// Note: The Android OS provides this field via
-	// [Build](https://developer.android.com/reference/android/os/Build#MANUFACTURER).
-	// iOS apps SHOULD hardcode the value `Apple`.
-	DeviceManufacturerKey = attribute.Key("device.manufacturer")
-
-	// DeviceModelIdentifierKey is the attribute Key conforming to the
-	// "device.model.identifier" semantic conventions. It represents the model
-	// identifier for the device
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'iPhone3,4', 'SM-G920F'
-	// Note: It's recommended this value represents a machine-readable version
-	// of the model identifier rather than the market or consumer-friendly name
-	// of the device.
-	DeviceModelIdentifierKey = attribute.Key("device.model.identifier")
-
-	// DeviceModelNameKey is the attribute Key conforming to the
-	// "device.model.name" semantic conventions. It represents the marketing
-	// name for the device model
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6'
-	// Note: It's recommended this value represents a human-readable version of
-	// the device model rather than a machine-readable alternative.
-	DeviceModelNameKey = attribute.Key("device.model.name")
-)
-
-// DeviceID returns an attribute KeyValue conforming to the "device.id"
-// semantic conventions. It represents a unique identifier representing the
-// device
-func DeviceID(val string) attribute.KeyValue {
-	return DeviceIDKey.String(val)
-}
-
-// DeviceManufacturer returns an attribute KeyValue conforming to the
-// "device.manufacturer" semantic conventions. It represents the name of the
-// device manufacturer
-func DeviceManufacturer(val string) attribute.KeyValue {
-	return DeviceManufacturerKey.String(val)
-}
-
-// DeviceModelIdentifier returns an attribute KeyValue conforming to the
-// "device.model.identifier" semantic conventions. It represents the model
-// identifier for the device
-func DeviceModelIdentifier(val string) attribute.KeyValue {
-	return DeviceModelIdentifierKey.String(val)
-}
-
-// DeviceModelName returns an attribute KeyValue conforming to the
-// "device.model.name" semantic conventions. It represents the marketing name
-// for the device model
-func DeviceModelName(val string) attribute.KeyValue {
-	return DeviceModelNameKey.String(val)
-}
-
-// These attributes may be used for any disk related operation.
-const (
-	// DiskIoDirectionKey is the attribute Key conforming to the
-	// "disk.io.direction" semantic conventions. It represents the disk IO
-	// operation direction.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'read'
-	DiskIoDirectionKey = attribute.Key("disk.io.direction")
-)
-
-var (
-	// read
-	DiskIoDirectionRead = DiskIoDirectionKey.String("read")
-	// write
-	DiskIoDirectionWrite = DiskIoDirectionKey.String("write")
-)
-
-// The shared attributes used to report a DNS query.
-const (
-	// DNSQuestionNameKey is the attribute Key conforming to the
-	// "dns.question.name" semantic conventions. It represents the name being
-	// queried.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'www.example.com', 'opentelemetry.io'
-	// Note: If the name field contains non-printable characters (below 32 or
-	// above 126), those characters should be represented as escaped base 10
-	// integers (\DDD). Back slashes and quotes should be escaped. Tabs,
-	// carriage returns, and line feeds should be converted to \t, \r, and \n
-	// respectively.
-	DNSQuestionNameKey = attribute.Key("dns.question.name")
-)
-
-// DNSQuestionName returns an attribute KeyValue conforming to the
-// "dns.question.name" semantic conventions. It represents the name being
-// queried.
-func DNSQuestionName(val string) attribute.KeyValue {
-	return DNSQuestionNameKey.String(val)
-}
-
-// Attributes for operations with an authenticated and/or authorized enduser.
-const (
-	// EnduserIDKey is the attribute Key conforming to the "enduser.id"
-	// semantic conventions. It represents the username or client_id extracted
-	// from the access token or
-	// [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header
-	// in the inbound request from outside the system.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'username'
-	EnduserIDKey = attribute.Key("enduser.id")
-
-	// EnduserRoleKey is the attribute Key conforming to the "enduser.role"
-	// semantic conventions. It represents the actual/assumed role the client
-	// is making the request under extracted from token or application security
-	// context.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'admin'
-	EnduserRoleKey = attribute.Key("enduser.role")
-
-	// EnduserScopeKey is the attribute Key conforming to the "enduser.scope"
-	// semantic conventions. It represents the scopes or granted authorities
-	// the client currently possesses extracted from token or application
-	// security context. The value would come from the scope associated with an
-	// [OAuth 2.0 Access
-	// Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute
-	// value in a [SAML 2.0
-	// Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'read:message, write:files'
-	EnduserScopeKey = attribute.Key("enduser.scope")
-)
-
-// EnduserID returns an attribute KeyValue conforming to the "enduser.id"
-// semantic conventions. It represents the username or client_id extracted from
-// the access token or
-// [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header in
-// the inbound request from outside the system.
-func EnduserID(val string) attribute.KeyValue {
-	return EnduserIDKey.String(val)
-}
-
-// EnduserRole returns an attribute KeyValue conforming to the
-// "enduser.role" semantic conventions. It represents the actual/assumed role
-// the client is making the request under extracted from token or application
-// security context.
-func EnduserRole(val string) attribute.KeyValue {
-	return EnduserRoleKey.String(val)
-}
-
-// EnduserScope returns an attribute KeyValue conforming to the
-// "enduser.scope" semantic conventions. It represents the scopes or granted
-// authorities the client currently possesses extracted from token or
-// application security context. The value would come from the scope associated
-// with an [OAuth 2.0 Access
-// Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute
-// value in a [SAML 2.0
-// Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html).
-func EnduserScope(val string) attribute.KeyValue {
-	return EnduserScopeKey.String(val)
-}
-
-// The shared attributes used to report an error.
-const (
-	// ErrorTypeKey is the attribute Key conforming to the "error.type"
-	// semantic conventions. It represents the describes a class of error the
-	// operation ended with.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'timeout', 'java.net.UnknownHostException',
-	// 'server_certificate_invalid', '500'
-	// Note: The `error.type` SHOULD be predictable, and SHOULD have low
-	// cardinality.
-	//
-	// When `error.type` is set to a type (e.g., an exception type), its
-	// canonical class name identifying the type within the artifact SHOULD be
-	// used.
-	//
-	// Instrumentations SHOULD document the list of errors they report.
-	//
-	// The cardinality of `error.type` within one instrumentation library
-	// SHOULD be low.
-	// Telemetry consumers that aggregate data from multiple instrumentation
-	// libraries and applications
-	// should be prepared for `error.type` to have high cardinality at query
-	// time when no
-	// additional filters are applied.
-	//
-	// If the operation has completed successfully, instrumentations SHOULD NOT
-	// set `error.type`.
-	//
-	// If a specific domain defines its own set of error identifiers (such as
-	// HTTP or gRPC status codes),
-	// it's RECOMMENDED to:
-	//
-	// * Use a domain-specific attribute
-	// * Set `error.type` to capture all errors, regardless of whether they are
-	// defined within the domain-specific set or not.
-	ErrorTypeKey = attribute.Key("error.type")
-)
-
-var (
-	// A fallback error value to be used when the instrumentation doesn't define a custom value
-	ErrorTypeOther = ErrorTypeKey.String("_OTHER")
-)
-
-// Attributes for Events represented using Log Records.
-const (
-	// EventNameKey is the attribute Key conforming to the "event.name"
-	// semantic conventions. It represents the identifies the class / type of
-	// event.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'browser.mouse.click', 'device.app.lifecycle'
-	// Note: Event names are subject to the same rules as [attribute
-	// names](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.33.0/specification/common/attribute-naming.md).
-	// Notably, event names are namespaced to avoid collisions and provide a
-	// clean separation of semantics for events in separate domains like
-	// browser, mobile, and kubernetes.
-	EventNameKey = attribute.Key("event.name")
-)
-
-// EventName returns an attribute KeyValue conforming to the "event.name"
-// semantic conventions. It represents the identifies the class / type of
-// event.
-func EventName(val string) attribute.KeyValue {
-	return EventNameKey.String(val)
-}
-
-// The shared attributes used to report a single exception associated with a
-// span or log.
-const (
-	// ExceptionEscapedKey is the attribute Key conforming to the
-	// "exception.escaped" semantic conventions. It represents the sHOULD be
-	// set to true if the exception event is recorded at a point where it is
-	// known that the exception is escaping the scope of the span.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Note: An exception is considered to have escaped (or left) the scope of
-	// a span,
-	// if that span is ended while the exception is still logically "in
-	// flight".
-	// This may be actually "in flight" in some languages (e.g. if the
-	// exception
-	// is passed to a Context manager's `__exit__` method in Python) but will
-	// usually be caught at the point of recording the exception in most
-	// languages.
-	//
-	// It is usually not possible to determine at the point where an exception
-	// is thrown
-	// whether it will escape the scope of a span.
-	// However, it is trivial to know that an exception
-	// will escape, if one checks for an active exception just before ending
-	// the span,
-	// as done in the [example for recording span
-	// exceptions](https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-spans/#recording-an-exception).
-	//
-	// It follows that an exception may still escape the scope of the span
-	// even if the `exception.escaped` attribute was not set or set to false,
-	// since the event might have been recorded at a time where it was not
-	// clear whether the exception will escape.
-	ExceptionEscapedKey = attribute.Key("exception.escaped")
-
-	// ExceptionMessageKey is the attribute Key conforming to the
-	// "exception.message" semantic conventions. It represents the exception
-	// message.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'Division by zero', "Can't convert 'int' object to str
-	// implicitly"
-	ExceptionMessageKey = attribute.Key("exception.message")
-
-	// ExceptionStacktraceKey is the attribute Key conforming to the
-	// "exception.stacktrace" semantic conventions. It represents a stacktrace
-	// as a string in the natural representation for the language runtime. The
-	// representation is to be determined and documented by each language SIG.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'Exception in thread "main" java.lang.RuntimeException: Test
-	// exception\\n at '
-	//  'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at '
-	//  'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at '
-	//  'com.example.GenerateTrace.main(GenerateTrace.java:5)'
-	ExceptionStacktraceKey = attribute.Key("exception.stacktrace")
-
-	// ExceptionTypeKey is the attribute Key conforming to the "exception.type"
-	// semantic conventions. It represents the type of the exception (its
-	// fully-qualified class name, if applicable). The dynamic type of the
-	// exception should be preferred over the static type in languages that
-	// support it.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'java.net.ConnectException', 'OSError'
-	ExceptionTypeKey = attribute.Key("exception.type")
-)
-
-// ExceptionEscaped returns an attribute KeyValue conforming to the
-// "exception.escaped" semantic conventions. It represents the sHOULD be set to
-// true if the exception event is recorded at a point where it is known that
-// the exception is escaping the scope of the span.
-func ExceptionEscaped(val bool) attribute.KeyValue {
-	return ExceptionEscapedKey.Bool(val)
-}
-
-// ExceptionMessage returns an attribute KeyValue conforming to the
-// "exception.message" semantic conventions. It represents the exception
-// message.
-func ExceptionMessage(val string) attribute.KeyValue {
-	return ExceptionMessageKey.String(val)
-}
-
-// ExceptionStacktrace returns an attribute KeyValue conforming to the
-// "exception.stacktrace" semantic conventions. It represents a stacktrace as a
-// string in the natural representation for the language runtime. The
-// representation is to be determined and documented by each language SIG.
-func ExceptionStacktrace(val string) attribute.KeyValue {
-	return ExceptionStacktraceKey.String(val)
-}
-
-// ExceptionType returns an attribute KeyValue conforming to the
-// "exception.type" semantic conventions. It represents the type of the
-// exception (its fully-qualified class name, if applicable). The dynamic type
-// of the exception should be preferred over the static type in languages that
-// support it.
-func ExceptionType(val string) attribute.KeyValue {
-	return ExceptionTypeKey.String(val)
-}
-
-// FaaS attributes
-const (
-	// FaaSColdstartKey is the attribute Key conforming to the "faas.coldstart"
-	// semantic conventions. It represents a boolean that is true if the
-	// serverless function is executed for the first time (aka cold-start).
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	FaaSColdstartKey = attribute.Key("faas.coldstart")
-
-	// FaaSCronKey is the attribute Key conforming to the "faas.cron" semantic
-	// conventions. It represents a string containing the schedule period as
-	// [Cron
-	// Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '0/5 * * * ? *'
-	FaaSCronKey = attribute.Key("faas.cron")
-
-	// FaaSDocumentCollectionKey is the attribute Key conforming to the
-	// "faas.document.collection" semantic conventions. It represents the name
-	// of the source on which the triggering operation was performed. For
-	// example, in Cloud Storage or S3 corresponds to the bucket name, and in
-	// Cosmos DB to the database name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myBucketName', 'myDBName'
-	FaaSDocumentCollectionKey = attribute.Key("faas.document.collection")
-
-	// FaaSDocumentNameKey is the attribute Key conforming to the
-	// "faas.document.name" semantic conventions. It represents the document
-	// name/table subjected to the operation. For example, in Cloud Storage or
-	// S3 is the name of the file, and in Cosmos DB the table name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myFile.txt', 'myTableName'
-	FaaSDocumentNameKey = attribute.Key("faas.document.name")
-
-	// FaaSDocumentOperationKey is the attribute Key conforming to the
-	// "faas.document.operation" semantic conventions. It represents the
-	// describes the type of the operation that was performed on the data.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	FaaSDocumentOperationKey = attribute.Key("faas.document.operation")
-
-	// FaaSDocumentTimeKey is the attribute Key conforming to the
-	// "faas.document.time" semantic conventions. It represents a string
-	// containing the time when the data was accessed in the [ISO
-	// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format
-	// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2020-01-23T13:47:06Z'
-	FaaSDocumentTimeKey = attribute.Key("faas.document.time")
-
-	// FaaSInstanceKey is the attribute Key conforming to the "faas.instance"
-	// semantic conventions. It represents the execution environment ID as a
-	// string, that will be potentially reused for other invocations to the
-	// same function/function version.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de'
-	// Note: * **AWS Lambda:** Use the (full) log stream name.
-	FaaSInstanceKey = attribute.Key("faas.instance")
-
-	// FaaSInvocationIDKey is the attribute Key conforming to the
-	// "faas.invocation_id" semantic conventions. It represents the invocation
-	// ID of the current function invocation.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28'
-	FaaSInvocationIDKey = attribute.Key("faas.invocation_id")
-
-	// FaaSInvokedNameKey is the attribute Key conforming to the
-	// "faas.invoked_name" semantic conventions. It represents the name of the
-	// invoked function.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'my-function'
-	// Note: SHOULD be equal to the `faas.name` resource attribute of the
-	// invoked function.
-	FaaSInvokedNameKey = attribute.Key("faas.invoked_name")
-
-	// FaaSInvokedProviderKey is the attribute Key conforming to the
-	// "faas.invoked_provider" semantic conventions. It represents the cloud
-	// provider of the invoked function.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: SHOULD be equal to the `cloud.provider` resource attribute of the
-	// invoked function.
-	FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider")
-
-	// FaaSInvokedRegionKey is the attribute Key conforming to the
-	// "faas.invoked_region" semantic conventions. It represents the cloud
-	// region of the invoked function.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'eu-central-1'
-	// Note: SHOULD be equal to the `cloud.region` resource attribute of the
-	// invoked function.
-	FaaSInvokedRegionKey = attribute.Key("faas.invoked_region")
-
-	// FaaSMaxMemoryKey is the attribute Key conforming to the
-	// "faas.max_memory" semantic conventions. It represents the amount of
-	// memory available to the serverless function converted to Bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 134217728
-	// Note: It's recommended to set this attribute since e.g. too little
-	// memory can easily stop a Java AWS Lambda function from working
-	// correctly. On AWS Lambda, the environment variable
-	// `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this information (which must
-	// be multiplied by 1,048,576).
-	FaaSMaxMemoryKey = attribute.Key("faas.max_memory")
-
-	// FaaSNameKey is the attribute Key conforming to the "faas.name" semantic
-	// conventions. It represents the name of the single function that this
-	// runtime instance executes.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'my-function', 'myazurefunctionapp/some-function-name'
-	// Note: This is the name of the function as configured/deployed on the
-	// FaaS
-	// platform and is usually different from the name of the callback
-	// function (which may be stored in the
-	// [`code.namespace`/`code.function`](/docs/general/attributes.md#source-code-attributes)
-	// span attributes).
-	//
-	// For some cloud providers, the above definition is ambiguous. The
-	// following
-	// definition of function name MUST be used for this attribute
-	// (and consequently the span name) for the listed cloud
-	// providers/products:
-	//
-	// * **Azure:**  The full name `/`, i.e., function app name
-	//   followed by a forward slash followed by the function name (this form
-	//   can also be seen in the resource JSON for the function).
-	//   This means that a span attribute MUST be used, as an Azure function
-	//   app can host multiple functions that would usually share
-	//   a TracerProvider (see also the `cloud.resource_id` attribute).
-	FaaSNameKey = attribute.Key("faas.name")
-
-	// FaaSTimeKey is the attribute Key conforming to the "faas.time" semantic
-	// conventions. It represents a string containing the function invocation
-	// time in the [ISO
-	// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format
-	// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2020-01-23T13:47:06Z'
-	FaaSTimeKey = attribute.Key("faas.time")
-
-	// FaaSTriggerKey is the attribute Key conforming to the "faas.trigger"
-	// semantic conventions. It represents the type of the trigger which caused
-	// this function invocation.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	FaaSTriggerKey = attribute.Key("faas.trigger")
-
-	// FaaSVersionKey is the attribute Key conforming to the "faas.version"
-	// semantic conventions. It represents the immutable version of the
-	// function being executed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '26', 'pinkfroid-00002'
-	// Note: Depending on the cloud provider and platform, use:
-	//
-	// * **AWS Lambda:** The [function
-	// version](https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html)
-	//   (an integer represented as a decimal string).
-	// * **Google Cloud Run (Services):** The
-	// [revision](https://cloud.google.com/run/docs/managing/revisions)
-	//   (i.e., the function name plus the revision suffix).
-	// * **Google Cloud Functions:** The value of the
-	//   [`K_REVISION` environment
-	// variable](https://cloud.google.com/functions/docs/env-var#runtime_environment_variables_set_automatically).
-	// * **Azure Functions:** Not applicable. Do not set this attribute.
-	FaaSVersionKey = attribute.Key("faas.version")
-)
-
-var (
-	// When a new object is created
-	FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert")
-	// When an object is modified
-	FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit")
-	// When an object is deleted
-	FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete")
-)
-
-var (
-	// Alibaba Cloud
-	FaaSInvokedProviderAlibabaCloud = FaaSInvokedProviderKey.String("alibaba_cloud")
-	// Amazon Web Services
-	FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws")
-	// Microsoft Azure
-	FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure")
-	// Google Cloud Platform
-	FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp")
-	// Tencent Cloud
-	FaaSInvokedProviderTencentCloud = FaaSInvokedProviderKey.String("tencent_cloud")
-)
-
-var (
-	// A response to some data source operation such as a database or filesystem read/write
-	FaaSTriggerDatasource = FaaSTriggerKey.String("datasource")
-	// To provide an answer to an inbound HTTP request
-	FaaSTriggerHTTP = FaaSTriggerKey.String("http")
-	// A function is set to be executed when messages are sent to a messaging system
-	FaaSTriggerPubsub = FaaSTriggerKey.String("pubsub")
-	// A function is scheduled to be executed regularly
-	FaaSTriggerTimer = FaaSTriggerKey.String("timer")
-	// If none of the others apply
-	FaaSTriggerOther = FaaSTriggerKey.String("other")
-)
-
-// FaaSColdstart returns an attribute KeyValue conforming to the
-// "faas.coldstart" semantic conventions. It represents a boolean that is true
-// if the serverless function is executed for the first time (aka cold-start).
-func FaaSColdstart(val bool) attribute.KeyValue {
-	return FaaSColdstartKey.Bool(val)
-}
-
-// FaaSCron returns an attribute KeyValue conforming to the "faas.cron"
-// semantic conventions. It represents a string containing the schedule period
-// as [Cron
-// Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm).
-func FaaSCron(val string) attribute.KeyValue {
-	return FaaSCronKey.String(val)
-}
-
-// FaaSDocumentCollection returns an attribute KeyValue conforming to the
-// "faas.document.collection" semantic conventions. It represents the name of
-// the source on which the triggering operation was performed. For example, in
-// Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the
-// database name.
-func FaaSDocumentCollection(val string) attribute.KeyValue {
-	return FaaSDocumentCollectionKey.String(val)
-}
-
-// FaaSDocumentName returns an attribute KeyValue conforming to the
-// "faas.document.name" semantic conventions. It represents the document
-// name/table subjected to the operation. For example, in Cloud Storage or S3
-// is the name of the file, and in Cosmos DB the table name.
-func FaaSDocumentName(val string) attribute.KeyValue {
-	return FaaSDocumentNameKey.String(val)
-}
-
-// FaaSDocumentTime returns an attribute KeyValue conforming to the
-// "faas.document.time" semantic conventions. It represents a string containing
-// the time when the data was accessed in the [ISO
-// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format
-// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime).
-func FaaSDocumentTime(val string) attribute.KeyValue {
-	return FaaSDocumentTimeKey.String(val)
-}
-
-// FaaSInstance returns an attribute KeyValue conforming to the
-// "faas.instance" semantic conventions. It represents the execution
-// environment ID as a string, that will be potentially reused for other
-// invocations to the same function/function version.
-func FaaSInstance(val string) attribute.KeyValue {
-	return FaaSInstanceKey.String(val)
-}
-
-// FaaSInvocationID returns an attribute KeyValue conforming to the
-// "faas.invocation_id" semantic conventions. It represents the invocation ID
-// of the current function invocation.
-func FaaSInvocationID(val string) attribute.KeyValue {
-	return FaaSInvocationIDKey.String(val)
-}
-
-// FaaSInvokedName returns an attribute KeyValue conforming to the
-// "faas.invoked_name" semantic conventions. It represents the name of the
-// invoked function.
-func FaaSInvokedName(val string) attribute.KeyValue {
-	return FaaSInvokedNameKey.String(val)
-}
-
-// FaaSInvokedRegion returns an attribute KeyValue conforming to the
-// "faas.invoked_region" semantic conventions. It represents the cloud region
-// of the invoked function.
-func FaaSInvokedRegion(val string) attribute.KeyValue {
-	return FaaSInvokedRegionKey.String(val)
-}
-
-// FaaSMaxMemory returns an attribute KeyValue conforming to the
-// "faas.max_memory" semantic conventions. It represents the amount of memory
-// available to the serverless function converted to Bytes.
-func FaaSMaxMemory(val int) attribute.KeyValue {
-	return FaaSMaxMemoryKey.Int(val)
-}
-
-// FaaSName returns an attribute KeyValue conforming to the "faas.name"
-// semantic conventions. It represents the name of the single function that
-// this runtime instance executes.
-func FaaSName(val string) attribute.KeyValue {
-	return FaaSNameKey.String(val)
-}
-
-// FaaSTime returns an attribute KeyValue conforming to the "faas.time"
-// semantic conventions. It represents a string containing the function
-// invocation time in the [ISO
-// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format
-// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime).
-func FaaSTime(val string) attribute.KeyValue {
-	return FaaSTimeKey.String(val)
-}
-
-// FaaSVersion returns an attribute KeyValue conforming to the
-// "faas.version" semantic conventions. It represents the immutable version of
-// the function being executed.
-func FaaSVersion(val string) attribute.KeyValue {
-	return FaaSVersionKey.String(val)
-}
-
-// Attributes for Feature Flags.
-const (
-	// FeatureFlagKeyKey is the attribute Key conforming to the
-	// "feature_flag.key" semantic conventions. It represents the unique
-	// identifier of the feature flag.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'logo-color'
-	FeatureFlagKeyKey = attribute.Key("feature_flag.key")
-
-	// FeatureFlagProviderNameKey is the attribute Key conforming to the
-	// "feature_flag.provider_name" semantic conventions. It represents the
-	// name of the service provider that performs the flag evaluation.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Flag Manager'
-	FeatureFlagProviderNameKey = attribute.Key("feature_flag.provider_name")
-
-	// FeatureFlagVariantKey is the attribute Key conforming to the
-	// "feature_flag.variant" semantic conventions. It represents the sHOULD be
-	// a semantic identifier for a value. If one is unavailable, a stringified
-	// version of the value can be used.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'red', 'true', 'on'
-	// Note: A semantic identifier, commonly referred to as a variant, provides
-	// a means
-	// for referring to a value without including the value itself. This can
-	// provide additional context for understanding the meaning behind a value.
-	// For example, the variant `red` maybe be used for the value `#c05543`.
-	//
-	// A stringified version of the value can be used in situations where a
-	// semantic identifier is unavailable. String representation of the value
-	// should be determined by the implementer.
-	FeatureFlagVariantKey = attribute.Key("feature_flag.variant")
-)
-
-// FeatureFlagKey returns an attribute KeyValue conforming to the
-// "feature_flag.key" semantic conventions. It represents the unique identifier
-// of the feature flag.
-func FeatureFlagKey(val string) attribute.KeyValue {
-	return FeatureFlagKeyKey.String(val)
-}
-
-// FeatureFlagProviderName returns an attribute KeyValue conforming to the
-// "feature_flag.provider_name" semantic conventions. It represents the name of
-// the service provider that performs the flag evaluation.
-func FeatureFlagProviderName(val string) attribute.KeyValue {
-	return FeatureFlagProviderNameKey.String(val)
-}
-
-// FeatureFlagVariant returns an attribute KeyValue conforming to the
-// "feature_flag.variant" semantic conventions. It represents the sHOULD be a
-// semantic identifier for a value. If one is unavailable, a stringified
-// version of the value can be used.
-func FeatureFlagVariant(val string) attribute.KeyValue {
-	return FeatureFlagVariantKey.String(val)
-}
-
-// Describes file attributes.
-const (
-	// FileDirectoryKey is the attribute Key conforming to the "file.directory"
-	// semantic conventions. It represents the directory where the file is
-	// located. It should include the drive letter, when appropriate.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/home/user', 'C:\\Program Files\\MyApp'
-	FileDirectoryKey = attribute.Key("file.directory")
-
-	// FileExtensionKey is the attribute Key conforming to the "file.extension"
-	// semantic conventions. It represents the file extension, excluding the
-	// leading dot.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'png', 'gz'
-	// Note: When the file name has multiple extensions (example.tar.gz), only
-	// the last one should be captured ("gz", not "tar.gz").
-	FileExtensionKey = attribute.Key("file.extension")
-
-	// FileNameKey is the attribute Key conforming to the "file.name" semantic
-	// conventions. It represents the name of the file including the extension,
-	// without the directory.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'example.png'
-	FileNameKey = attribute.Key("file.name")
-
-	// FilePathKey is the attribute Key conforming to the "file.path" semantic
-	// conventions. It represents the full path to the file, including the file
-	// name. It should include the drive letter, when appropriate.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/home/alice/example.png', 'C:\\Program
-	// Files\\MyApp\\myapp.exe'
-	FilePathKey = attribute.Key("file.path")
-
-	// FileSizeKey is the attribute Key conforming to the "file.size" semantic
-	// conventions. It represents the file size in bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	FileSizeKey = attribute.Key("file.size")
-)
-
-// FileDirectory returns an attribute KeyValue conforming to the
-// "file.directory" semantic conventions. It represents the directory where the
-// file is located. It should include the drive letter, when appropriate.
-func FileDirectory(val string) attribute.KeyValue {
-	return FileDirectoryKey.String(val)
-}
-
-// FileExtension returns an attribute KeyValue conforming to the
-// "file.extension" semantic conventions. It represents the file extension,
-// excluding the leading dot.
-func FileExtension(val string) attribute.KeyValue {
-	return FileExtensionKey.String(val)
-}
-
-// FileName returns an attribute KeyValue conforming to the "file.name"
-// semantic conventions. It represents the name of the file including the
-// extension, without the directory.
-func FileName(val string) attribute.KeyValue {
-	return FileNameKey.String(val)
-}
-
-// FilePath returns an attribute KeyValue conforming to the "file.path"
-// semantic conventions. It represents the full path to the file, including the
-// file name. It should include the drive letter, when appropriate.
-func FilePath(val string) attribute.KeyValue {
-	return FilePathKey.String(val)
-}
-
-// FileSize returns an attribute KeyValue conforming to the "file.size"
-// semantic conventions. It represents the file size in bytes.
-func FileSize(val int) attribute.KeyValue {
-	return FileSizeKey.Int(val)
-}
-
-// Attributes for Google Cloud Run.
-const (
-	// GCPCloudRunJobExecutionKey is the attribute Key conforming to the
-	// "gcp.cloud_run.job.execution" semantic conventions. It represents the
-	// name of the Cloud Run
-	// [execution](https://cloud.google.com/run/docs/managing/job-executions)
-	// being run for the Job, as set by the
-	// [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars)
-	// environment variable.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'job-name-xxxx', 'sample-job-mdw84'
-	GCPCloudRunJobExecutionKey = attribute.Key("gcp.cloud_run.job.execution")
-
-	// GCPCloudRunJobTaskIndexKey is the attribute Key conforming to the
-	// "gcp.cloud_run.job.task_index" semantic conventions. It represents the
-	// index for a task within an execution as provided by the
-	// [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars)
-	// environment variable.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 0, 1
-	GCPCloudRunJobTaskIndexKey = attribute.Key("gcp.cloud_run.job.task_index")
-)
-
-// GCPCloudRunJobExecution returns an attribute KeyValue conforming to the
-// "gcp.cloud_run.job.execution" semantic conventions. It represents the name
-// of the Cloud Run
-// [execution](https://cloud.google.com/run/docs/managing/job-executions) being
-// run for the Job, as set by the
-// [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars)
-// environment variable.
-func GCPCloudRunJobExecution(val string) attribute.KeyValue {
-	return GCPCloudRunJobExecutionKey.String(val)
-}
-
-// GCPCloudRunJobTaskIndex returns an attribute KeyValue conforming to the
-// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index
-// for a task within an execution as provided by the
-// [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars)
-// environment variable.
-func GCPCloudRunJobTaskIndex(val int) attribute.KeyValue {
-	return GCPCloudRunJobTaskIndexKey.Int(val)
-}
-
-// Attributes for Google Compute Engine (GCE).
-const (
-	// GCPGceInstanceHostnameKey is the attribute Key conforming to the
-	// "gcp.gce.instance.hostname" semantic conventions. It represents the
-	// hostname of a GCE instance. This is the full value of the default or
-	// [custom
-	// hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'my-host1234.example.com',
-	// 'sample-vm.us-west1-b.c.my-project.internal'
-	GCPGceInstanceHostnameKey = attribute.Key("gcp.gce.instance.hostname")
-
-	// GCPGceInstanceNameKey is the attribute Key conforming to the
-	// "gcp.gce.instance.name" semantic conventions. It represents the instance
-	// name of a GCE instance. This is the value provided by `host.name`, the
-	// visible name of the instance in the Cloud Console UI, and the prefix for
-	// the default hostname of the instance as defined by the [default internal
-	// DNS
-	// name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'instance-1', 'my-vm-name'
-	GCPGceInstanceNameKey = attribute.Key("gcp.gce.instance.name")
-)
-
-// GCPGceInstanceHostname returns an attribute KeyValue conforming to the
-// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname
-// of a GCE instance. This is the full value of the default or [custom
-// hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm).
-func GCPGceInstanceHostname(val string) attribute.KeyValue {
-	return GCPGceInstanceHostnameKey.String(val)
-}
-
-// GCPGceInstanceName returns an attribute KeyValue conforming to the
-// "gcp.gce.instance.name" semantic conventions. It represents the instance
-// name of a GCE instance. This is the value provided by `host.name`, the
-// visible name of the instance in the Cloud Console UI, and the prefix for the
-// default hostname of the instance as defined by the [default internal DNS
-// name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names).
-func GCPGceInstanceName(val string) attribute.KeyValue {
-	return GCPGceInstanceNameKey.String(val)
-}
-
-// The attributes used to describe telemetry in the context of LLM (Large
-// Language Models) requests and responses.
-const (
-	// GenAiCompletionKey is the attribute Key conforming to the
-	// "gen_ai.completion" semantic conventions. It represents the full
-	// response received from the LLM.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: "[{'role': 'assistant', 'content': 'The capital of France is
-	// Paris.'}]"
-	// Note: It's RECOMMENDED to format completions as JSON string matching
-	// [OpenAI messages
-	// format](https://platform.openai.com/docs/guides/text-generation)
-	GenAiCompletionKey = attribute.Key("gen_ai.completion")
-
-	// GenAiPromptKey is the attribute Key conforming to the "gen_ai.prompt"
-	// semantic conventions. It represents the full prompt sent to an LLM.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: "[{'role': 'user', 'content': 'What is the capital of
-	// France?'}]"
-	// Note: It's RECOMMENDED to format prompts as JSON string matching [OpenAI
-	// messages
-	// format](https://platform.openai.com/docs/guides/text-generation)
-	GenAiPromptKey = attribute.Key("gen_ai.prompt")
-
-	// GenAiRequestMaxTokensKey is the attribute Key conforming to the
-	// "gen_ai.request.max_tokens" semantic conventions. It represents the
-	// maximum number of tokens the LLM generates for a request.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 100
-	GenAiRequestMaxTokensKey = attribute.Key("gen_ai.request.max_tokens")
-
-	// GenAiRequestModelKey is the attribute Key conforming to the
-	// "gen_ai.request.model" semantic conventions. It represents the name of
-	// the LLM a request is being made to.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'gpt-4'
-	GenAiRequestModelKey = attribute.Key("gen_ai.request.model")
-
-	// GenAiRequestTemperatureKey is the attribute Key conforming to the
-	// "gen_ai.request.temperature" semantic conventions. It represents the
-	// temperature setting for the LLM request.
-	//
-	// Type: double
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 0.0
-	GenAiRequestTemperatureKey = attribute.Key("gen_ai.request.temperature")
-
-	// GenAiRequestTopPKey is the attribute Key conforming to the
-	// "gen_ai.request.top_p" semantic conventions. It represents the top_p
-	// sampling setting for the LLM request.
-	//
-	// Type: double
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1.0
-	GenAiRequestTopPKey = attribute.Key("gen_ai.request.top_p")
-
-	// GenAiResponseFinishReasonsKey is the attribute Key conforming to the
-	// "gen_ai.response.finish_reasons" semantic conventions. It represents the
-	// array of reasons the model stopped generating tokens, corresponding to
-	// each generation received.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'stop'
-	GenAiResponseFinishReasonsKey = attribute.Key("gen_ai.response.finish_reasons")
-
-	// GenAiResponseIDKey is the attribute Key conforming to the
-	// "gen_ai.response.id" semantic conventions. It represents the unique
-	// identifier for the completion.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'chatcmpl-123'
-	GenAiResponseIDKey = attribute.Key("gen_ai.response.id")
-
-	// GenAiResponseModelKey is the attribute Key conforming to the
-	// "gen_ai.response.model" semantic conventions. It represents the name of
-	// the LLM a response was generated from.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'gpt-4-0613'
-	GenAiResponseModelKey = attribute.Key("gen_ai.response.model")
-
-	// GenAiSystemKey is the attribute Key conforming to the "gen_ai.system"
-	// semantic conventions. It represents the Generative AI product as
-	// identified by the client instrumentation.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'openai'
-	// Note: The actual GenAI product may differ from the one identified by the
-	// client. For example, when using OpenAI client libraries to communicate
-	// with Mistral, the `gen_ai.system` is set to `openai` based on the
-	// instrumentation's best knowledge.
-	GenAiSystemKey = attribute.Key("gen_ai.system")
-
-	// GenAiUsageCompletionTokensKey is the attribute Key conforming to the
-	// "gen_ai.usage.completion_tokens" semantic conventions. It represents the
-	// number of tokens used in the LLM response (completion).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 180
-	GenAiUsageCompletionTokensKey = attribute.Key("gen_ai.usage.completion_tokens")
-
-	// GenAiUsagePromptTokensKey is the attribute Key conforming to the
-	// "gen_ai.usage.prompt_tokens" semantic conventions. It represents the
-	// number of tokens used in the LLM prompt.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 100
-	GenAiUsagePromptTokensKey = attribute.Key("gen_ai.usage.prompt_tokens")
-)
-
-var (
-	// OpenAI
-	GenAiSystemOpenai = GenAiSystemKey.String("openai")
-)
-
-// GenAiCompletion returns an attribute KeyValue conforming to the
-// "gen_ai.completion" semantic conventions. It represents the full response
-// received from the LLM.
-func GenAiCompletion(val string) attribute.KeyValue {
-	return GenAiCompletionKey.String(val)
-}
-
-// GenAiPrompt returns an attribute KeyValue conforming to the
-// "gen_ai.prompt" semantic conventions. It represents the full prompt sent to
-// an LLM.
-func GenAiPrompt(val string) attribute.KeyValue {
-	return GenAiPromptKey.String(val)
-}
-
-// GenAiRequestMaxTokens returns an attribute KeyValue conforming to the
-// "gen_ai.request.max_tokens" semantic conventions. It represents the maximum
-// number of tokens the LLM generates for a request.
-func GenAiRequestMaxTokens(val int) attribute.KeyValue {
-	return GenAiRequestMaxTokensKey.Int(val)
-}
-
-// GenAiRequestModel returns an attribute KeyValue conforming to the
-// "gen_ai.request.model" semantic conventions. It represents the name of the
-// LLM a request is being made to.
-func GenAiRequestModel(val string) attribute.KeyValue {
-	return GenAiRequestModelKey.String(val)
-}
-
-// GenAiRequestTemperature returns an attribute KeyValue conforming to the
-// "gen_ai.request.temperature" semantic conventions. It represents the
-// temperature setting for the LLM request.
-func GenAiRequestTemperature(val float64) attribute.KeyValue {
-	return GenAiRequestTemperatureKey.Float64(val)
-}
-
-// GenAiRequestTopP returns an attribute KeyValue conforming to the
-// "gen_ai.request.top_p" semantic conventions. It represents the top_p
-// sampling setting for the LLM request.
-func GenAiRequestTopP(val float64) attribute.KeyValue {
-	return GenAiRequestTopPKey.Float64(val)
-}
-
-// GenAiResponseFinishReasons returns an attribute KeyValue conforming to
-// the "gen_ai.response.finish_reasons" semantic conventions. It represents the
-// array of reasons the model stopped generating tokens, corresponding to each
-// generation received.
-func GenAiResponseFinishReasons(val ...string) attribute.KeyValue {
-	return GenAiResponseFinishReasonsKey.StringSlice(val)
-}
-
-// GenAiResponseID returns an attribute KeyValue conforming to the
-// "gen_ai.response.id" semantic conventions. It represents the unique
-// identifier for the completion.
-func GenAiResponseID(val string) attribute.KeyValue {
-	return GenAiResponseIDKey.String(val)
-}
-
-// GenAiResponseModel returns an attribute KeyValue conforming to the
-// "gen_ai.response.model" semantic conventions. It represents the name of the
-// LLM a response was generated from.
-func GenAiResponseModel(val string) attribute.KeyValue {
-	return GenAiResponseModelKey.String(val)
-}
-
-// GenAiUsageCompletionTokens returns an attribute KeyValue conforming to
-// the "gen_ai.usage.completion_tokens" semantic conventions. It represents the
-// number of tokens used in the LLM response (completion).
-func GenAiUsageCompletionTokens(val int) attribute.KeyValue {
-	return GenAiUsageCompletionTokensKey.Int(val)
-}
-
-// GenAiUsagePromptTokens returns an attribute KeyValue conforming to the
-// "gen_ai.usage.prompt_tokens" semantic conventions. It represents the number
-// of tokens used in the LLM prompt.
-func GenAiUsagePromptTokens(val int) attribute.KeyValue {
-	return GenAiUsagePromptTokensKey.Int(val)
-}
-
-// Attributes for GraphQL.
-const (
-	// GraphqlDocumentKey is the attribute Key conforming to the
-	// "graphql.document" semantic conventions. It represents the GraphQL
-	// document being executed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'query findBookByID { bookByID(id: ?) { name } }'
-	// Note: The value may be sanitized to exclude sensitive information.
-	GraphqlDocumentKey = attribute.Key("graphql.document")
-
-	// GraphqlOperationNameKey is the attribute Key conforming to the
-	// "graphql.operation.name" semantic conventions. It represents the name of
-	// the operation being executed.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'findBookByID'
-	GraphqlOperationNameKey = attribute.Key("graphql.operation.name")
-
-	// GraphqlOperationTypeKey is the attribute Key conforming to the
-	// "graphql.operation.type" semantic conventions. It represents the type of
-	// the operation being executed.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'query', 'mutation', 'subscription'
-	GraphqlOperationTypeKey = attribute.Key("graphql.operation.type")
-)
-
-var (
-	// GraphQL query
-	GraphqlOperationTypeQuery = GraphqlOperationTypeKey.String("query")
-	// GraphQL mutation
-	GraphqlOperationTypeMutation = GraphqlOperationTypeKey.String("mutation")
-	// GraphQL subscription
-	GraphqlOperationTypeSubscription = GraphqlOperationTypeKey.String("subscription")
-)
-
-// GraphqlDocument returns an attribute KeyValue conforming to the
-// "graphql.document" semantic conventions. It represents the GraphQL document
-// being executed.
-func GraphqlDocument(val string) attribute.KeyValue {
-	return GraphqlDocumentKey.String(val)
-}
-
-// GraphqlOperationName returns an attribute KeyValue conforming to the
-// "graphql.operation.name" semantic conventions. It represents the name of the
-// operation being executed.
-func GraphqlOperationName(val string) attribute.KeyValue {
-	return GraphqlOperationNameKey.String(val)
-}
-
-// Attributes for the Android platform on which the Android application is
-// running.
-const (
-	// HerokuAppIDKey is the attribute Key conforming to the "heroku.app.id"
-	// semantic conventions. It represents the unique identifier for the
-	// application
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2daa2797-e42b-4624-9322-ec3f968df4da'
-	HerokuAppIDKey = attribute.Key("heroku.app.id")
-
-	// HerokuReleaseCommitKey is the attribute Key conforming to the
-	// "heroku.release.commit" semantic conventions. It represents the commit
-	// hash for the current release
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'e6134959463efd8966b20e75b913cafe3f5ec'
-	HerokuReleaseCommitKey = attribute.Key("heroku.release.commit")
-
-	// HerokuReleaseCreationTimestampKey is the attribute Key conforming to the
-	// "heroku.release.creation_timestamp" semantic conventions. It represents
-	// the time and date the release was created
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2022-10-23T18:00:42Z'
-	HerokuReleaseCreationTimestampKey = attribute.Key("heroku.release.creation_timestamp")
-)
-
-// HerokuAppID returns an attribute KeyValue conforming to the
-// "heroku.app.id" semantic conventions. It represents the unique identifier
-// for the application
-func HerokuAppID(val string) attribute.KeyValue {
-	return HerokuAppIDKey.String(val)
-}
-
-// HerokuReleaseCommit returns an attribute KeyValue conforming to the
-// "heroku.release.commit" semantic conventions. It represents the commit hash
-// for the current release
-func HerokuReleaseCommit(val string) attribute.KeyValue {
-	return HerokuReleaseCommitKey.String(val)
-}
-
-// HerokuReleaseCreationTimestamp returns an attribute KeyValue conforming
-// to the "heroku.release.creation_timestamp" semantic conventions. It
-// represents the time and date the release was created
-func HerokuReleaseCreationTimestamp(val string) attribute.KeyValue {
-	return HerokuReleaseCreationTimestampKey.String(val)
-}
-
-// A host is defined as a computing instance. For example, physical servers,
-// virtual machines, switches or disk array.
-const (
-	// HostArchKey is the attribute Key conforming to the "host.arch" semantic
-	// conventions. It represents the CPU architecture the host system is
-	// running on.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	HostArchKey = attribute.Key("host.arch")
-
-	// HostCPUCacheL2SizeKey is the attribute Key conforming to the
-	// "host.cpu.cache.l2.size" semantic conventions. It represents the amount
-	// of level 2 memory cache available to the processor (in Bytes).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 12288000
-	HostCPUCacheL2SizeKey = attribute.Key("host.cpu.cache.l2.size")
-
-	// HostCPUFamilyKey is the attribute Key conforming to the
-	// "host.cpu.family" semantic conventions. It represents the family or
-	// generation of the CPU.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '6', 'PA-RISC 1.1e'
-	HostCPUFamilyKey = attribute.Key("host.cpu.family")
-
-	// HostCPUModelIDKey is the attribute Key conforming to the
-	// "host.cpu.model.id" semantic conventions. It represents the model
-	// identifier. It provides more granular information about the CPU,
-	// distinguishing it from other CPUs within the same family.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '6', '9000/778/B180L'
-	HostCPUModelIDKey = attribute.Key("host.cpu.model.id")
-
-	// HostCPUModelNameKey is the attribute Key conforming to the
-	// "host.cpu.model.name" semantic conventions. It represents the model
-	// designation of the processor.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz'
-	HostCPUModelNameKey = attribute.Key("host.cpu.model.name")
-
-	// HostCPUSteppingKey is the attribute Key conforming to the
-	// "host.cpu.stepping" semantic conventions. It represents the stepping or
-	// core revisions.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1', 'r1p1'
-	HostCPUSteppingKey = attribute.Key("host.cpu.stepping")
-
-	// HostCPUVendorIDKey is the attribute Key conforming to the
-	// "host.cpu.vendor.id" semantic conventions. It represents the processor
-	// manufacturer identifier. A maximum 12-character string.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'GenuineIntel'
-	// Note: [CPUID](https://wiki.osdev.org/CPUID) command returns the vendor
-	// ID string in EBX, EDX and ECX registers. Writing these to memory in this
-	// order results in a 12-character string.
-	HostCPUVendorIDKey = attribute.Key("host.cpu.vendor.id")
-
-	// HostIDKey is the attribute Key conforming to the "host.id" semantic
-	// conventions. It represents the unique host ID. For Cloud, this must be
-	// the instance_id assigned by the cloud provider. For non-containerized
-	// systems, this should be the `machine-id`. See the table below for the
-	// sources to use to determine the `machine-id` based on operating system.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'fdbf79e8af94cb7f9e8df36789187052'
-	HostIDKey = attribute.Key("host.id")
-
-	// HostImageIDKey is the attribute Key conforming to the "host.image.id"
-	// semantic conventions. It represents the vM image ID or host OS image ID.
-	// For Cloud, this value is from the provider.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ami-07b06b442921831e5'
-	HostImageIDKey = attribute.Key("host.image.id")
-
-	// HostImageNameKey is the attribute Key conforming to the
-	// "host.image.name" semantic conventions. It represents the name of the VM
-	// image or OS install the host was instantiated from.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905'
-	HostImageNameKey = attribute.Key("host.image.name")
-
-	// HostImageVersionKey is the attribute Key conforming to the
-	// "host.image.version" semantic conventions. It represents the version
-	// string of the VM image or host OS as defined in [Version
-	// Attributes](/docs/resource/README.md#version-attributes).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '0.1'
-	HostImageVersionKey = attribute.Key("host.image.version")
-
-	// HostIPKey is the attribute Key conforming to the "host.ip" semantic
-	// conventions. It represents the available IP addresses of the host,
-	// excluding loopback interfaces.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '192.168.1.140', 'fe80::abc2:4a28:737a:609e'
-	// Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6
-	// addresses MUST be specified in the [RFC
-	// 5952](https://www.rfc-editor.org/rfc/rfc5952.html) format.
-	HostIPKey = attribute.Key("host.ip")
-
-	// HostMacKey is the attribute Key conforming to the "host.mac" semantic
-	// conventions. It represents the available MAC addresses of the host,
-	// excluding loopback interfaces.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'AC-DE-48-23-45-67', 'AC-DE-48-23-45-67-01-9F'
-	// Note: MAC Addresses MUST be represented in [IEEE RA hexadecimal
-	// form](https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf):
-	// as hyphen-separated octets in uppercase hexadecimal form from most to
-	// least significant.
-	HostMacKey = attribute.Key("host.mac")
-
-	// HostNameKey is the attribute Key conforming to the "host.name" semantic
-	// conventions. It represents the name of the host. On Unix systems, it may
-	// contain what the hostname command returns, or the fully qualified
-	// hostname, or another name specified by the user.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry-test'
-	HostNameKey = attribute.Key("host.name")
-
-	// HostTypeKey is the attribute Key conforming to the "host.type" semantic
-	// conventions. It represents the type of host. For Cloud, this must be the
-	// machine type.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'n1-standard-1'
-	HostTypeKey = attribute.Key("host.type")
-)
-
-var (
-	// AMD64
-	HostArchAMD64 = HostArchKey.String("amd64")
-	// ARM32
-	HostArchARM32 = HostArchKey.String("arm32")
-	// ARM64
-	HostArchARM64 = HostArchKey.String("arm64")
-	// Itanium
-	HostArchIA64 = HostArchKey.String("ia64")
-	// 32-bit PowerPC
-	HostArchPPC32 = HostArchKey.String("ppc32")
-	// 64-bit PowerPC
-	HostArchPPC64 = HostArchKey.String("ppc64")
-	// IBM z/Architecture
-	HostArchS390x = HostArchKey.String("s390x")
-	// 32-bit x86
-	HostArchX86 = HostArchKey.String("x86")
-)
-
-// HostCPUCacheL2Size returns an attribute KeyValue conforming to the
-// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of
-// level 2 memory cache available to the processor (in Bytes).
-func HostCPUCacheL2Size(val int) attribute.KeyValue {
-	return HostCPUCacheL2SizeKey.Int(val)
-}
-
-// HostCPUFamily returns an attribute KeyValue conforming to the
-// "host.cpu.family" semantic conventions. It represents the family or
-// generation of the CPU.
-func HostCPUFamily(val string) attribute.KeyValue {
-	return HostCPUFamilyKey.String(val)
-}
-
-// HostCPUModelID returns an attribute KeyValue conforming to the
-// "host.cpu.model.id" semantic conventions. It represents the model
-// identifier. It provides more granular information about the CPU,
-// distinguishing it from other CPUs within the same family.
-func HostCPUModelID(val string) attribute.KeyValue {
-	return HostCPUModelIDKey.String(val)
-}
-
-// HostCPUModelName returns an attribute KeyValue conforming to the
-// "host.cpu.model.name" semantic conventions. It represents the model
-// designation of the processor.
-func HostCPUModelName(val string) attribute.KeyValue {
-	return HostCPUModelNameKey.String(val)
-}
-
-// HostCPUStepping returns an attribute KeyValue conforming to the
-// "host.cpu.stepping" semantic conventions. It represents the stepping or core
-// revisions.
-func HostCPUStepping(val string) attribute.KeyValue {
-	return HostCPUSteppingKey.String(val)
-}
-
-// HostCPUVendorID returns an attribute KeyValue conforming to the
-// "host.cpu.vendor.id" semantic conventions. It represents the processor
-// manufacturer identifier. A maximum 12-character string.
-func HostCPUVendorID(val string) attribute.KeyValue {
-	return HostCPUVendorIDKey.String(val)
-}
-
-// HostID returns an attribute KeyValue conforming to the "host.id" semantic
-// conventions. It represents the unique host ID. For Cloud, this must be the
-// instance_id assigned by the cloud provider. For non-containerized systems,
-// this should be the `machine-id`. See the table below for the sources to use
-// to determine the `machine-id` based on operating system.
-func HostID(val string) attribute.KeyValue {
-	return HostIDKey.String(val)
-}
-
-// HostImageID returns an attribute KeyValue conforming to the
-// "host.image.id" semantic conventions. It represents the vM image ID or host
-// OS image ID. For Cloud, this value is from the provider.
-func HostImageID(val string) attribute.KeyValue {
-	return HostImageIDKey.String(val)
-}
-
-// HostImageName returns an attribute KeyValue conforming to the
-// "host.image.name" semantic conventions. It represents the name of the VM
-// image or OS install the host was instantiated from.
-func HostImageName(val string) attribute.KeyValue {
-	return HostImageNameKey.String(val)
-}
-
-// HostImageVersion returns an attribute KeyValue conforming to the
-// "host.image.version" semantic conventions. It represents the version string
-// of the VM image or host OS as defined in [Version
-// Attributes](/docs/resource/README.md#version-attributes).
-func HostImageVersion(val string) attribute.KeyValue {
-	return HostImageVersionKey.String(val)
-}
-
-// HostIP returns an attribute KeyValue conforming to the "host.ip" semantic
-// conventions. It represents the available IP addresses of the host, excluding
-// loopback interfaces.
-func HostIP(val ...string) attribute.KeyValue {
-	return HostIPKey.StringSlice(val)
-}
-
-// HostMac returns an attribute KeyValue conforming to the "host.mac"
-// semantic conventions. It represents the available MAC addresses of the host,
-// excluding loopback interfaces.
-func HostMac(val ...string) attribute.KeyValue {
-	return HostMacKey.StringSlice(val)
-}
-
-// HostName returns an attribute KeyValue conforming to the "host.name"
-// semantic conventions. It represents the name of the host. On Unix systems,
-// it may contain what the hostname command returns, or the fully qualified
-// hostname, or another name specified by the user.
-func HostName(val string) attribute.KeyValue {
-	return HostNameKey.String(val)
-}
-
-// HostType returns an attribute KeyValue conforming to the "host.type"
-// semantic conventions. It represents the type of host. For Cloud, this must
-// be the machine type.
-func HostType(val string) attribute.KeyValue {
-	return HostTypeKey.String(val)
-}
-
-// Semantic convention attributes in the HTTP namespace.
-const (
-	// HTTPConnectionStateKey is the attribute Key conforming to the
-	// "http.connection.state" semantic conventions. It represents the state of
-	// the HTTP connection in the HTTP connection pool.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'active', 'idle'
-	HTTPConnectionStateKey = attribute.Key("http.connection.state")
-
-	// HTTPRequestBodySizeKey is the attribute Key conforming to the
-	// "http.request.body.size" semantic conventions. It represents the size of
-	// the request payload body in bytes. This is the number of bytes
-	// transferred excluding headers and is often, but not always, present as
-	// the
-	// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length)
-	// header. For requests using transport encoding, this should be the
-	// compressed size.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3495
-	HTTPRequestBodySizeKey = attribute.Key("http.request.body.size")
-
-	// HTTPRequestMethodKey is the attribute Key conforming to the
-	// "http.request.method" semantic conventions. It represents the hTTP
-	// request method.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'GET', 'POST', 'HEAD'
-	// Note: HTTP request method value SHOULD be "known" to the
-	// instrumentation.
-	// By default, this convention defines "known" methods as the ones listed
-	// in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)
-	// and the PATCH method defined in
-	// [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).
-	//
-	// If the HTTP request method is not known to instrumentation, it MUST set
-	// the `http.request.method` attribute to `_OTHER`.
-	//
-	// If the HTTP instrumentation could end up converting valid HTTP request
-	// methods to `_OTHER`, then it MUST provide a way to override
-	// the list of known HTTP methods. If this override is done via environment
-	// variable, then the environment variable MUST be named
-	// OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated
-	// list of case-sensitive known HTTP methods
-	// (this list MUST be a full override of the default known method, it is
-	// not a list of known methods in addition to the defaults).
-	//
-	// HTTP method names are case-sensitive and `http.request.method` attribute
-	// value MUST match a known HTTP method name exactly.
-	// Instrumentations for specific web frameworks that consider HTTP methods
-	// to be case insensitive, SHOULD populate a canonical equivalent.
-	// Tracing instrumentations that do so, MUST also set
-	// `http.request.method_original` to the original value.
-	HTTPRequestMethodKey = attribute.Key("http.request.method")
-
-	// HTTPRequestMethodOriginalKey is the attribute Key conforming to the
-	// "http.request.method_original" semantic conventions. It represents the
-	// original HTTP method sent by the client in the request line.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'GeT', 'ACL', 'foo'
-	HTTPRequestMethodOriginalKey = attribute.Key("http.request.method_original")
-
-	// HTTPRequestResendCountKey is the attribute Key conforming to the
-	// "http.request.resend_count" semantic conventions. It represents the
-	// ordinal number of request resending attempt (for any reason, including
-	// redirects).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 3
-	// Note: The resend count SHOULD be updated each time an HTTP request gets
-	// resent by the client, regardless of what was the cause of the resending
-	// (e.g. redirection, authorization failure, 503 Server Unavailable,
-	// network issues, or any other).
-	HTTPRequestResendCountKey = attribute.Key("http.request.resend_count")
-
-	// HTTPRequestSizeKey is the attribute Key conforming to the
-	// "http.request.size" semantic conventions. It represents the total size
-	// of the request in bytes. This should be the total number of bytes sent
-	// over the wire, including the request line (HTTP/1.1), framing (HTTP/2
-	// and HTTP/3), headers, and request body if any.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1437
-	HTTPRequestSizeKey = attribute.Key("http.request.size")
-
-	// HTTPResponseBodySizeKey is the attribute Key conforming to the
-	// "http.response.body.size" semantic conventions. It represents the size
-	// of the response payload body in bytes. This is the number of bytes
-	// transferred excluding headers and is often, but not always, present as
-	// the
-	// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length)
-	// header. For requests using transport encoding, this should be the
-	// compressed size.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3495
-	HTTPResponseBodySizeKey = attribute.Key("http.response.body.size")
-
-	// HTTPResponseSizeKey is the attribute Key conforming to the
-	// "http.response.size" semantic conventions. It represents the total size
-	// of the response in bytes. This should be the total number of bytes sent
-	// over the wire, including the status line (HTTP/1.1), framing (HTTP/2 and
-	// HTTP/3), headers, and response body and trailers if any.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1437
-	HTTPResponseSizeKey = attribute.Key("http.response.size")
-
-	// HTTPResponseStatusCodeKey is the attribute Key conforming to the
-	// "http.response.status_code" semantic conventions. It represents the
-	// [HTTP response status
-	// code](https://tools.ietf.org/html/rfc7231#section-6).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 200
-	HTTPResponseStatusCodeKey = attribute.Key("http.response.status_code")
-
-	// HTTPRouteKey is the attribute Key conforming to the "http.route"
-	// semantic conventions. It represents the matched route, that is, the path
-	// template in the format used by the respective server framework.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '/users/:userID?', '{controller}/{action}/{id?}'
-	// Note: MUST NOT be populated when this is not supported by the HTTP
-	// server framework as the route attribute should have low-cardinality and
-	// the URI path can NOT substitute it.
-	// SHOULD include the [application
-	// root](/docs/http/http-spans.md#http-server-definitions) if there is one.
-	HTTPRouteKey = attribute.Key("http.route")
-)
-
-var (
-	// active state
-	HTTPConnectionStateActive = HTTPConnectionStateKey.String("active")
-	// idle state
-	HTTPConnectionStateIdle = HTTPConnectionStateKey.String("idle")
-)
-
-var (
-	// CONNECT method
-	HTTPRequestMethodConnect = HTTPRequestMethodKey.String("CONNECT")
-	// DELETE method
-	HTTPRequestMethodDelete = HTTPRequestMethodKey.String("DELETE")
-	// GET method
-	HTTPRequestMethodGet = HTTPRequestMethodKey.String("GET")
-	// HEAD method
-	HTTPRequestMethodHead = HTTPRequestMethodKey.String("HEAD")
-	// OPTIONS method
-	HTTPRequestMethodOptions = HTTPRequestMethodKey.String("OPTIONS")
-	// PATCH method
-	HTTPRequestMethodPatch = HTTPRequestMethodKey.String("PATCH")
-	// POST method
-	HTTPRequestMethodPost = HTTPRequestMethodKey.String("POST")
-	// PUT method
-	HTTPRequestMethodPut = HTTPRequestMethodKey.String("PUT")
-	// TRACE method
-	HTTPRequestMethodTrace = HTTPRequestMethodKey.String("TRACE")
-	// Any HTTP method that the instrumentation has no prior knowledge of
-	HTTPRequestMethodOther = HTTPRequestMethodKey.String("_OTHER")
-)
-
-// HTTPRequestBodySize returns an attribute KeyValue conforming to the
-// "http.request.body.size" semantic conventions. It represents the size of the
-// request payload body in bytes. This is the number of bytes transferred
-// excluding headers and is often, but not always, present as the
-// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length)
-// header. For requests using transport encoding, this should be the compressed
-// size.
-func HTTPRequestBodySize(val int) attribute.KeyValue {
-	return HTTPRequestBodySizeKey.Int(val)
-}
-
-// HTTPRequestMethodOriginal returns an attribute KeyValue conforming to the
-// "http.request.method_original" semantic conventions. It represents the
-// original HTTP method sent by the client in the request line.
-func HTTPRequestMethodOriginal(val string) attribute.KeyValue {
-	return HTTPRequestMethodOriginalKey.String(val)
-}
-
-// HTTPRequestResendCount returns an attribute KeyValue conforming to the
-// "http.request.resend_count" semantic conventions. It represents the ordinal
-// number of request resending attempt (for any reason, including redirects).
-func HTTPRequestResendCount(val int) attribute.KeyValue {
-	return HTTPRequestResendCountKey.Int(val)
-}
-
-// HTTPRequestSize returns an attribute KeyValue conforming to the
-// "http.request.size" semantic conventions. It represents the total size of
-// the request in bytes. This should be the total number of bytes sent over the
-// wire, including the request line (HTTP/1.1), framing (HTTP/2 and HTTP/3),
-// headers, and request body if any.
-func HTTPRequestSize(val int) attribute.KeyValue {
-	return HTTPRequestSizeKey.Int(val)
-}
-
-// HTTPResponseBodySize returns an attribute KeyValue conforming to the
-// "http.response.body.size" semantic conventions. It represents the size of
-// the response payload body in bytes. This is the number of bytes transferred
-// excluding headers and is often, but not always, present as the
-// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length)
-// header. For requests using transport encoding, this should be the compressed
-// size.
-func HTTPResponseBodySize(val int) attribute.KeyValue {
-	return HTTPResponseBodySizeKey.Int(val)
-}
-
-// HTTPResponseSize returns an attribute KeyValue conforming to the
-// "http.response.size" semantic conventions. It represents the total size of
-// the response in bytes. This should be the total number of bytes sent over
-// the wire, including the status line (HTTP/1.1), framing (HTTP/2 and HTTP/3),
-// headers, and response body and trailers if any.
-func HTTPResponseSize(val int) attribute.KeyValue {
-	return HTTPResponseSizeKey.Int(val)
-}
-
-// HTTPResponseStatusCode returns an attribute KeyValue conforming to the
-// "http.response.status_code" semantic conventions. It represents the [HTTP
-// response status code](https://tools.ietf.org/html/rfc7231#section-6).
-func HTTPResponseStatusCode(val int) attribute.KeyValue {
-	return HTTPResponseStatusCodeKey.Int(val)
-}
-
-// HTTPRoute returns an attribute KeyValue conforming to the "http.route"
-// semantic conventions. It represents the matched route, that is, the path
-// template in the format used by the respective server framework.
-func HTTPRoute(val string) attribute.KeyValue {
-	return HTTPRouteKey.String(val)
-}
-
-// Java Virtual machine related attributes.
-const (
-	// JvmBufferPoolNameKey is the attribute Key conforming to the
-	// "jvm.buffer.pool.name" semantic conventions. It represents the name of
-	// the buffer pool.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'mapped', 'direct'
-	// Note: Pool names are generally obtained via
-	// [BufferPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/BufferPoolMXBean.html#getName()).
-	JvmBufferPoolNameKey = attribute.Key("jvm.buffer.pool.name")
-
-	// JvmGcActionKey is the attribute Key conforming to the "jvm.gc.action"
-	// semantic conventions. It represents the name of the garbage collector
-	// action.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'end of minor GC', 'end of major GC'
-	// Note: Garbage collector action is generally obtained via
-	// [GarbageCollectionNotificationInfo#getGcAction()](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.management/com/sun/management/GarbageCollectionNotificationInfo.html#getGcAction()).
-	JvmGcActionKey = attribute.Key("jvm.gc.action")
-
-	// JvmGcNameKey is the attribute Key conforming to the "jvm.gc.name"
-	// semantic conventions. It represents the name of the garbage collector.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'G1 Young Generation', 'G1 Old Generation'
-	// Note: Garbage collector name is generally obtained via
-	// [GarbageCollectionNotificationInfo#getGcName()](https://docs.oracle.com/en/java/javase/11/docs/api/jdk.management/com/sun/management/GarbageCollectionNotificationInfo.html#getGcName()).
-	JvmGcNameKey = attribute.Key("jvm.gc.name")
-
-	// JvmMemoryPoolNameKey is the attribute Key conforming to the
-	// "jvm.memory.pool.name" semantic conventions. It represents the name of
-	// the memory pool.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'G1 Old Gen', 'G1 Eden space', 'G1 Survivor Space'
-	// Note: Pool names are generally obtained via
-	// [MemoryPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html#getName()).
-	JvmMemoryPoolNameKey = attribute.Key("jvm.memory.pool.name")
-
-	// JvmMemoryTypeKey is the attribute Key conforming to the
-	// "jvm.memory.type" semantic conventions. It represents the type of
-	// memory.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'heap', 'non_heap'
-	JvmMemoryTypeKey = attribute.Key("jvm.memory.type")
-
-	// JvmThreadDaemonKey is the attribute Key conforming to the
-	// "jvm.thread.daemon" semantic conventions. It represents the whether the
-	// thread is daemon or not.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: stable
-	JvmThreadDaemonKey = attribute.Key("jvm.thread.daemon")
-
-	// JvmThreadStateKey is the attribute Key conforming to the
-	// "jvm.thread.state" semantic conventions. It represents the state of the
-	// thread.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'runnable', 'blocked'
-	JvmThreadStateKey = attribute.Key("jvm.thread.state")
-)
-
-var (
-	// Heap memory
-	JvmMemoryTypeHeap = JvmMemoryTypeKey.String("heap")
-	// Non-heap memory
-	JvmMemoryTypeNonHeap = JvmMemoryTypeKey.String("non_heap")
-)
-
-var (
-	// A thread that has not yet started is in this state
-	JvmThreadStateNew = JvmThreadStateKey.String("new")
-	// A thread executing in the Java virtual machine is in this state
-	JvmThreadStateRunnable = JvmThreadStateKey.String("runnable")
-	// A thread that is blocked waiting for a monitor lock is in this state
-	JvmThreadStateBlocked = JvmThreadStateKey.String("blocked")
-	// A thread that is waiting indefinitely for another thread to perform a particular action is in this state
-	JvmThreadStateWaiting = JvmThreadStateKey.String("waiting")
-	// A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state
-	JvmThreadStateTimedWaiting = JvmThreadStateKey.String("timed_waiting")
-	// A thread that has exited is in this state
-	JvmThreadStateTerminated = JvmThreadStateKey.String("terminated")
-)
-
-// JvmBufferPoolName returns an attribute KeyValue conforming to the
-// "jvm.buffer.pool.name" semantic conventions. It represents the name of the
-// buffer pool.
-func JvmBufferPoolName(val string) attribute.KeyValue {
-	return JvmBufferPoolNameKey.String(val)
-}
-
-// JvmGcAction returns an attribute KeyValue conforming to the
-// "jvm.gc.action" semantic conventions. It represents the name of the garbage
-// collector action.
-func JvmGcAction(val string) attribute.KeyValue {
-	return JvmGcActionKey.String(val)
-}
-
-// JvmGcName returns an attribute KeyValue conforming to the "jvm.gc.name"
-// semantic conventions. It represents the name of the garbage collector.
-func JvmGcName(val string) attribute.KeyValue {
-	return JvmGcNameKey.String(val)
-}
-
-// JvmMemoryPoolName returns an attribute KeyValue conforming to the
-// "jvm.memory.pool.name" semantic conventions. It represents the name of the
-// memory pool.
-func JvmMemoryPoolName(val string) attribute.KeyValue {
-	return JvmMemoryPoolNameKey.String(val)
-}
-
-// JvmThreadDaemon returns an attribute KeyValue conforming to the
-// "jvm.thread.daemon" semantic conventions. It represents the whether the
-// thread is daemon or not.
-func JvmThreadDaemon(val bool) attribute.KeyValue {
-	return JvmThreadDaemonKey.Bool(val)
-}
-
-// Kubernetes resource attributes.
-const (
-	// K8SClusterNameKey is the attribute Key conforming to the
-	// "k8s.cluster.name" semantic conventions. It represents the name of the
-	// cluster.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry-cluster'
-	K8SClusterNameKey = attribute.Key("k8s.cluster.name")
-
-	// K8SClusterUIDKey is the attribute Key conforming to the
-	// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for
-	// the cluster, set to the UID of the `kube-system` namespace.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '218fc5a9-a5f1-4b54-aa05-46717d0ab26d'
-	// Note: K8S doesn't have support for obtaining a cluster ID. If this is
-	// ever
-	// added, we will recommend collecting the `k8s.cluster.uid` through the
-	// official APIs. In the meantime, we are able to use the `uid` of the
-	// `kube-system` namespace as a proxy for cluster ID. Read on for the
-	// rationale.
-	//
-	// Every object created in a K8S cluster is assigned a distinct UID. The
-	// `kube-system` namespace is used by Kubernetes itself and will exist
-	// for the lifetime of the cluster. Using the `uid` of the `kube-system`
-	// namespace is a reasonable proxy for the K8S ClusterID as it will only
-	// change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are
-	// UUIDs as standardized by
-	// [ISO/IEC 9834-8 and ITU-T
-	// X.667](https://www.itu.int/ITU-T/studygroups/com17/oid.html).
-	// Which states:
-	//
-	// > If generated according to one of the mechanisms defined in Rec.
-	//   ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be
-	//   different from all other UUIDs generated before 3603 A.D., or is
-	//   extremely likely to be different (depending on the mechanism chosen).
-	//
-	// Therefore, UIDs between clusters should be extremely unlikely to
-	// conflict.
-	K8SClusterUIDKey = attribute.Key("k8s.cluster.uid")
-
-	// K8SContainerNameKey is the attribute Key conforming to the
-	// "k8s.container.name" semantic conventions. It represents the name of the
-	// Container from Pod specification, must be unique within a Pod. Container
-	// runtime usually uses different globally unique name (`container.name`).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'redis'
-	K8SContainerNameKey = attribute.Key("k8s.container.name")
-
-	// K8SContainerRestartCountKey is the attribute Key conforming to the
-	// "k8s.container.restart_count" semantic conventions. It represents the
-	// number of times the container was restarted. This attribute can be used
-	// to identify a particular container (running or stopped) within a
-	// container spec.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	K8SContainerRestartCountKey = attribute.Key("k8s.container.restart_count")
-
-	// K8SContainerStatusLastTerminatedReasonKey is the attribute Key
-	// conforming to the "k8s.container.status.last_terminated_reason" semantic
-	// conventions. It represents the last terminated reason of the Container.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Evicted', 'Error'
-	K8SContainerStatusLastTerminatedReasonKey = attribute.Key("k8s.container.status.last_terminated_reason")
-
-	// K8SCronJobNameKey is the attribute Key conforming to the
-	// "k8s.cronjob.name" semantic conventions. It represents the name of the
-	// CronJob.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SCronJobNameKey = attribute.Key("k8s.cronjob.name")
-
-	// K8SCronJobUIDKey is the attribute Key conforming to the
-	// "k8s.cronjob.uid" semantic conventions. It represents the UID of the
-	// CronJob.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid")
-
-	// K8SDaemonSetNameKey is the attribute Key conforming to the
-	// "k8s.daemonset.name" semantic conventions. It represents the name of the
-	// DaemonSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SDaemonSetNameKey = attribute.Key("k8s.daemonset.name")
-
-	// K8SDaemonSetUIDKey is the attribute Key conforming to the
-	// "k8s.daemonset.uid" semantic conventions. It represents the UID of the
-	// DaemonSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SDaemonSetUIDKey = attribute.Key("k8s.daemonset.uid")
-
-	// K8SDeploymentNameKey is the attribute Key conforming to the
-	// "k8s.deployment.name" semantic conventions. It represents the name of
-	// the Deployment.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SDeploymentNameKey = attribute.Key("k8s.deployment.name")
-
-	// K8SDeploymentUIDKey is the attribute Key conforming to the
-	// "k8s.deployment.uid" semantic conventions. It represents the UID of the
-	// Deployment.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid")
-
-	// K8SJobNameKey is the attribute Key conforming to the "k8s.job.name"
-	// semantic conventions. It represents the name of the Job.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SJobNameKey = attribute.Key("k8s.job.name")
-
-	// K8SJobUIDKey is the attribute Key conforming to the "k8s.job.uid"
-	// semantic conventions. It represents the UID of the Job.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SJobUIDKey = attribute.Key("k8s.job.uid")
-
-	// K8SNamespaceNameKey is the attribute Key conforming to the
-	// "k8s.namespace.name" semantic conventions. It represents the name of the
-	// namespace that the pod is running in.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'default'
-	K8SNamespaceNameKey = attribute.Key("k8s.namespace.name")
-
-	// K8SNodeNameKey is the attribute Key conforming to the "k8s.node.name"
-	// semantic conventions. It represents the name of the Node.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'node-1'
-	K8SNodeNameKey = attribute.Key("k8s.node.name")
-
-	// K8SNodeUIDKey is the attribute Key conforming to the "k8s.node.uid"
-	// semantic conventions. It represents the UID of the Node.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2'
-	K8SNodeUIDKey = attribute.Key("k8s.node.uid")
-
-	// K8SPodNameKey is the attribute Key conforming to the "k8s.pod.name"
-	// semantic conventions. It represents the name of the Pod.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry-pod-autoconf'
-	K8SPodNameKey = attribute.Key("k8s.pod.name")
-
-	// K8SPodUIDKey is the attribute Key conforming to the "k8s.pod.uid"
-	// semantic conventions. It represents the UID of the Pod.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SPodUIDKey = attribute.Key("k8s.pod.uid")
-
-	// K8SReplicaSetNameKey is the attribute Key conforming to the
-	// "k8s.replicaset.name" semantic conventions. It represents the name of
-	// the ReplicaSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SReplicaSetNameKey = attribute.Key("k8s.replicaset.name")
-
-	// K8SReplicaSetUIDKey is the attribute Key conforming to the
-	// "k8s.replicaset.uid" semantic conventions. It represents the UID of the
-	// ReplicaSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SReplicaSetUIDKey = attribute.Key("k8s.replicaset.uid")
-
-	// K8SStatefulSetNameKey is the attribute Key conforming to the
-	// "k8s.statefulset.name" semantic conventions. It represents the name of
-	// the StatefulSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry'
-	K8SStatefulSetNameKey = attribute.Key("k8s.statefulset.name")
-
-	// K8SStatefulSetUIDKey is the attribute Key conforming to the
-	// "k8s.statefulset.uid" semantic conventions. It represents the UID of the
-	// StatefulSet.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
-	K8SStatefulSetUIDKey = attribute.Key("k8s.statefulset.uid")
-)
-
-// K8SClusterName returns an attribute KeyValue conforming to the
-// "k8s.cluster.name" semantic conventions. It represents the name of the
-// cluster.
-func K8SClusterName(val string) attribute.KeyValue {
-	return K8SClusterNameKey.String(val)
-}
-
-// K8SClusterUID returns an attribute KeyValue conforming to the
-// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for the
-// cluster, set to the UID of the `kube-system` namespace.
-func K8SClusterUID(val string) attribute.KeyValue {
-	return K8SClusterUIDKey.String(val)
-}
-
-// K8SContainerName returns an attribute KeyValue conforming to the
-// "k8s.container.name" semantic conventions. It represents the name of the
-// Container from Pod specification, must be unique within a Pod. Container
-// runtime usually uses different globally unique name (`container.name`).
-func K8SContainerName(val string) attribute.KeyValue {
-	return K8SContainerNameKey.String(val)
-}
-
-// K8SContainerRestartCount returns an attribute KeyValue conforming to the
-// "k8s.container.restart_count" semantic conventions. It represents the number
-// of times the container was restarted. This attribute can be used to identify
-// a particular container (running or stopped) within a container spec.
-func K8SContainerRestartCount(val int) attribute.KeyValue {
-	return K8SContainerRestartCountKey.Int(val)
-}
-
-// K8SContainerStatusLastTerminatedReason returns an attribute KeyValue
-// conforming to the "k8s.container.status.last_terminated_reason" semantic
-// conventions. It represents the last terminated reason of the Container.
-func K8SContainerStatusLastTerminatedReason(val string) attribute.KeyValue {
-	return K8SContainerStatusLastTerminatedReasonKey.String(val)
-}
-
-// K8SCronJobName returns an attribute KeyValue conforming to the
-// "k8s.cronjob.name" semantic conventions. It represents the name of the
-// CronJob.
-func K8SCronJobName(val string) attribute.KeyValue {
-	return K8SCronJobNameKey.String(val)
-}
-
-// K8SCronJobUID returns an attribute KeyValue conforming to the
-// "k8s.cronjob.uid" semantic conventions. It represents the UID of the
-// CronJob.
-func K8SCronJobUID(val string) attribute.KeyValue {
-	return K8SCronJobUIDKey.String(val)
-}
-
-// K8SDaemonSetName returns an attribute KeyValue conforming to the
-// "k8s.daemonset.name" semantic conventions. It represents the name of the
-// DaemonSet.
-func K8SDaemonSetName(val string) attribute.KeyValue {
-	return K8SDaemonSetNameKey.String(val)
-}
-
-// K8SDaemonSetUID returns an attribute KeyValue conforming to the
-// "k8s.daemonset.uid" semantic conventions. It represents the UID of the
-// DaemonSet.
-func K8SDaemonSetUID(val string) attribute.KeyValue {
-	return K8SDaemonSetUIDKey.String(val)
-}
-
-// K8SDeploymentName returns an attribute KeyValue conforming to the
-// "k8s.deployment.name" semantic conventions. It represents the name of the
-// Deployment.
-func K8SDeploymentName(val string) attribute.KeyValue {
-	return K8SDeploymentNameKey.String(val)
-}
-
-// K8SDeploymentUID returns an attribute KeyValue conforming to the
-// "k8s.deployment.uid" semantic conventions. It represents the UID of the
-// Deployment.
-func K8SDeploymentUID(val string) attribute.KeyValue {
-	return K8SDeploymentUIDKey.String(val)
-}
-
-// K8SJobName returns an attribute KeyValue conforming to the "k8s.job.name"
-// semantic conventions. It represents the name of the Job.
-func K8SJobName(val string) attribute.KeyValue {
-	return K8SJobNameKey.String(val)
-}
-
-// K8SJobUID returns an attribute KeyValue conforming to the "k8s.job.uid"
-// semantic conventions. It represents the UID of the Job.
-func K8SJobUID(val string) attribute.KeyValue {
-	return K8SJobUIDKey.String(val)
-}
-
-// K8SNamespaceName returns an attribute KeyValue conforming to the
-// "k8s.namespace.name" semantic conventions. It represents the name of the
-// namespace that the pod is running in.
-func K8SNamespaceName(val string) attribute.KeyValue {
-	return K8SNamespaceNameKey.String(val)
-}
-
-// K8SNodeName returns an attribute KeyValue conforming to the
-// "k8s.node.name" semantic conventions. It represents the name of the Node.
-func K8SNodeName(val string) attribute.KeyValue {
-	return K8SNodeNameKey.String(val)
-}
-
-// K8SNodeUID returns an attribute KeyValue conforming to the "k8s.node.uid"
-// semantic conventions. It represents the UID of the Node.
-func K8SNodeUID(val string) attribute.KeyValue {
-	return K8SNodeUIDKey.String(val)
-}
-
-// K8SPodName returns an attribute KeyValue conforming to the "k8s.pod.name"
-// semantic conventions. It represents the name of the Pod.
-func K8SPodName(val string) attribute.KeyValue {
-	return K8SPodNameKey.String(val)
-}
-
-// K8SPodUID returns an attribute KeyValue conforming to the "k8s.pod.uid"
-// semantic conventions. It represents the UID of the Pod.
-func K8SPodUID(val string) attribute.KeyValue {
-	return K8SPodUIDKey.String(val)
-}
-
-// K8SReplicaSetName returns an attribute KeyValue conforming to the
-// "k8s.replicaset.name" semantic conventions. It represents the name of the
-// ReplicaSet.
-func K8SReplicaSetName(val string) attribute.KeyValue {
-	return K8SReplicaSetNameKey.String(val)
-}
-
-// K8SReplicaSetUID returns an attribute KeyValue conforming to the
-// "k8s.replicaset.uid" semantic conventions. It represents the UID of the
-// ReplicaSet.
-func K8SReplicaSetUID(val string) attribute.KeyValue {
-	return K8SReplicaSetUIDKey.String(val)
-}
-
-// K8SStatefulSetName returns an attribute KeyValue conforming to the
-// "k8s.statefulset.name" semantic conventions. It represents the name of the
-// StatefulSet.
-func K8SStatefulSetName(val string) attribute.KeyValue {
-	return K8SStatefulSetNameKey.String(val)
-}
-
-// K8SStatefulSetUID returns an attribute KeyValue conforming to the
-// "k8s.statefulset.uid" semantic conventions. It represents the UID of the
-// StatefulSet.
-func K8SStatefulSetUID(val string) attribute.KeyValue {
-	return K8SStatefulSetUIDKey.String(val)
-}
-
-// Log attributes
-const (
-	// LogIostreamKey is the attribute Key conforming to the "log.iostream"
-	// semantic conventions. It represents the stream associated with the log.
-	// See below for a list of well-known values.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	LogIostreamKey = attribute.Key("log.iostream")
-)
-
-var (
-	// Logs from stdout stream
-	LogIostreamStdout = LogIostreamKey.String("stdout")
-	// Events from stderr stream
-	LogIostreamStderr = LogIostreamKey.String("stderr")
-)
-
-// Attributes for a file to which log was emitted.
-const (
-	// LogFileNameKey is the attribute Key conforming to the "log.file.name"
-	// semantic conventions. It represents the basename of the file.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'audit.log'
-	LogFileNameKey = attribute.Key("log.file.name")
-
-	// LogFileNameResolvedKey is the attribute Key conforming to the
-	// "log.file.name_resolved" semantic conventions. It represents the
-	// basename of the file, with symlinks resolved.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'uuid.log'
-	LogFileNameResolvedKey = attribute.Key("log.file.name_resolved")
-
-	// LogFilePathKey is the attribute Key conforming to the "log.file.path"
-	// semantic conventions. It represents the full path to the file.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/var/log/mysql/audit.log'
-	LogFilePathKey = attribute.Key("log.file.path")
-
-	// LogFilePathResolvedKey is the attribute Key conforming to the
-	// "log.file.path_resolved" semantic conventions. It represents the full
-	// path to the file, with symlinks resolved.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/var/lib/docker/uuid.log'
-	LogFilePathResolvedKey = attribute.Key("log.file.path_resolved")
-)
-
-// LogFileName returns an attribute KeyValue conforming to the
-// "log.file.name" semantic conventions. It represents the basename of the
-// file.
-func LogFileName(val string) attribute.KeyValue {
-	return LogFileNameKey.String(val)
-}
-
-// LogFileNameResolved returns an attribute KeyValue conforming to the
-// "log.file.name_resolved" semantic conventions. It represents the basename of
-// the file, with symlinks resolved.
-func LogFileNameResolved(val string) attribute.KeyValue {
-	return LogFileNameResolvedKey.String(val)
-}
-
-// LogFilePath returns an attribute KeyValue conforming to the
-// "log.file.path" semantic conventions. It represents the full path to the
-// file.
-func LogFilePath(val string) attribute.KeyValue {
-	return LogFilePathKey.String(val)
-}
-
-// LogFilePathResolved returns an attribute KeyValue conforming to the
-// "log.file.path_resolved" semantic conventions. It represents the full path
-// to the file, with symlinks resolved.
-func LogFilePathResolved(val string) attribute.KeyValue {
-	return LogFilePathResolvedKey.String(val)
-}
-
-// The generic attributes that may be used in any Log Record.
-const (
-	// LogRecordUIDKey is the attribute Key conforming to the "log.record.uid"
-	// semantic conventions. It represents a unique identifier for the Log
-	// Record.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '01ARZ3NDEKTSV4RRFFQ69G5FAV'
-	// Note: If an id is provided, other log records with the same id will be
-	// considered duplicates and can be removed safely. This means, that two
-	// distinguishable log records MUST have different values.
-	// The id MAY be an [Universally Unique Lexicographically Sortable
-	// Identifier (ULID)](https://github.com/ulid/spec), but other identifiers
-	// (e.g. UUID) may be used as needed.
-	LogRecordUIDKey = attribute.Key("log.record.uid")
-)
-
-// LogRecordUID returns an attribute KeyValue conforming to the
-// "log.record.uid" semantic conventions. It represents a unique identifier for
-// the Log Record.
-func LogRecordUID(val string) attribute.KeyValue {
-	return LogRecordUIDKey.String(val)
-}
-
-// Attributes describing telemetry around messaging systems and messaging
-// activities.
-const (
-	// MessagingBatchMessageCountKey is the attribute Key conforming to the
-	// "messaging.batch.message_count" semantic conventions. It represents the
-	// number of messages sent, received, or processed in the scope of the
-	// batching operation.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 0, 1, 2
-	// Note: Instrumentations SHOULD NOT set `messaging.batch.message_count` on
-	// spans that operate with a single message. When a messaging client
-	// library supports both batch and single-message API for the same
-	// operation, instrumentations SHOULD use `messaging.batch.message_count`
-	// for batching APIs and SHOULD NOT use it for single-message APIs.
-	MessagingBatchMessageCountKey = attribute.Key("messaging.batch.message_count")
-
-	// MessagingClientIDKey is the attribute Key conforming to the
-	// "messaging.client.id" semantic conventions. It represents a unique
-	// identifier for the client that consumes or produces a message.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'client-5', 'myhost@8742@s8083jm'
-	MessagingClientIDKey = attribute.Key("messaging.client.id")
-
-	// MessagingDestinationAnonymousKey is the attribute Key conforming to the
-	// "messaging.destination.anonymous" semantic conventions. It represents a
-	// boolean that is true if the message destination is anonymous (could be
-	// unnamed or have auto-generated name).
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingDestinationAnonymousKey = attribute.Key("messaging.destination.anonymous")
-
-	// MessagingDestinationNameKey is the attribute Key conforming to the
-	// "messaging.destination.name" semantic conventions. It represents the
-	// message destination name
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MyQueue', 'MyTopic'
-	// Note: Destination name SHOULD uniquely identify a specific queue, topic
-	// or other entity within the broker. If
-	// the broker doesn't have such notion, the destination name SHOULD
-	// uniquely identify the broker.
-	MessagingDestinationNameKey = attribute.Key("messaging.destination.name")
-
-	// MessagingDestinationPartitionIDKey is the attribute Key conforming to
-	// the "messaging.destination.partition.id" semantic conventions. It
-	// represents the identifier of the partition messages are sent to or
-	// received from, unique within the `messaging.destination.name`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1'
-	MessagingDestinationPartitionIDKey = attribute.Key("messaging.destination.partition.id")
-
-	// MessagingDestinationTemplateKey is the attribute Key conforming to the
-	// "messaging.destination.template" semantic conventions. It represents the
-	// low cardinality representation of the messaging destination name
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/customers/{customerID}'
-	// Note: Destination names could be constructed from templates. An example
-	// would be a destination name involving a user name or product id.
-	// Although the destination name in this case is of high cardinality, the
-	// underlying template is of low cardinality and can be effectively used
-	// for grouping and aggregation.
-	MessagingDestinationTemplateKey = attribute.Key("messaging.destination.template")
-
-	// MessagingDestinationTemporaryKey is the attribute Key conforming to the
-	// "messaging.destination.temporary" semantic conventions. It represents a
-	// boolean that is true if the message destination is temporary and might
-	// not exist anymore after messages are processed.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingDestinationTemporaryKey = attribute.Key("messaging.destination.temporary")
-
-	// MessagingDestinationPublishAnonymousKey is the attribute Key conforming
-	// to the "messaging.destination_publish.anonymous" semantic conventions.
-	// It represents a boolean that is true if the publish message destination
-	// is anonymous (could be unnamed or have auto-generated name).
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingDestinationPublishAnonymousKey = attribute.Key("messaging.destination_publish.anonymous")
-
-	// MessagingDestinationPublishNameKey is the attribute Key conforming to
-	// the "messaging.destination_publish.name" semantic conventions. It
-	// represents the name of the original destination the message was
-	// published to
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MyQueue', 'MyTopic'
-	// Note: The name SHOULD uniquely identify a specific queue, topic, or
-	// other entity within the broker. If
-	// the broker doesn't have such notion, the original destination name
-	// SHOULD uniquely identify the broker.
-	MessagingDestinationPublishNameKey = attribute.Key("messaging.destination_publish.name")
-
-	// MessagingMessageBodySizeKey is the attribute Key conforming to the
-	// "messaging.message.body.size" semantic conventions. It represents the
-	// size of the message body in bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1439
-	// Note: This can refer to both the compressed or uncompressed body size.
-	// If both sizes are known, the uncompressed
-	// body size should be used.
-	MessagingMessageBodySizeKey = attribute.Key("messaging.message.body.size")
-
-	// MessagingMessageConversationIDKey is the attribute Key conforming to the
-	// "messaging.message.conversation_id" semantic conventions. It represents
-	// the conversation ID identifying the conversation to which the message
-	// belongs, represented as a string. Sometimes called "Correlation ID".
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MyConversationID'
-	MessagingMessageConversationIDKey = attribute.Key("messaging.message.conversation_id")
-
-	// MessagingMessageEnvelopeSizeKey is the attribute Key conforming to the
-	// "messaging.message.envelope.size" semantic conventions. It represents
-	// the size of the message body and metadata in bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 2738
-	// Note: This can refer to both the compressed or uncompressed size. If
-	// both sizes are known, the uncompressed
-	// size should be used.
-	MessagingMessageEnvelopeSizeKey = attribute.Key("messaging.message.envelope.size")
-
-	// MessagingMessageIDKey is the attribute Key conforming to the
-	// "messaging.message.id" semantic conventions. It represents a value used
-	// by the messaging system as an identifier for the message, represented as
-	// a string.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '452a7c7c7c7048c2f887f61572b18fc2'
-	MessagingMessageIDKey = attribute.Key("messaging.message.id")
-
-	// MessagingOperationNameKey is the attribute Key conforming to the
-	// "messaging.operation.name" semantic conventions. It represents the
-	// system-specific name of the messaging operation.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ack', 'nack', 'send'
-	MessagingOperationNameKey = attribute.Key("messaging.operation.name")
-
-	// MessagingOperationTypeKey is the attribute Key conforming to the
-	// "messaging.operation.type" semantic conventions. It represents a string
-	// identifying the type of the messaging operation.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: If a custom value is used, it MUST be of low cardinality.
-	MessagingOperationTypeKey = attribute.Key("messaging.operation.type")
-
-	// MessagingSystemKey is the attribute Key conforming to the
-	// "messaging.system" semantic conventions. It represents the messaging
-	// system as identified by the client instrumentation.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: The actual messaging system may differ from the one known by the
-	// client. For example, when using Kafka client libraries to communicate
-	// with Azure Event Hubs, the `messaging.system` is set to `kafka` based on
-	// the instrumentation's best knowledge.
-	MessagingSystemKey = attribute.Key("messaging.system")
-)
-
-var (
-	// One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the "Publish" span can be used as the creation context and no "Create" span needs to be created
-	MessagingOperationTypePublish = MessagingOperationTypeKey.String("publish")
-	// A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios
-	MessagingOperationTypeCreate = MessagingOperationTypeKey.String("create")
-	// One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages
-	MessagingOperationTypeReceive = MessagingOperationTypeKey.String("receive")
-	// One or more messages are delivered to or processed by a consumer
-	MessagingOperationTypeDeliver = MessagingOperationTypeKey.String("process")
-	// One or more messages are settled
-	MessagingOperationTypeSettle = MessagingOperationTypeKey.String("settle")
-)
-
-var (
-	// Apache ActiveMQ
-	MessagingSystemActivemq = MessagingSystemKey.String("activemq")
-	// Amazon Simple Queue Service (SQS)
-	MessagingSystemAWSSqs = MessagingSystemKey.String("aws_sqs")
-	// Azure Event Grid
-	MessagingSystemEventgrid = MessagingSystemKey.String("eventgrid")
-	// Azure Event Hubs
-	MessagingSystemEventhubs = MessagingSystemKey.String("eventhubs")
-	// Azure Service Bus
-	MessagingSystemServicebus = MessagingSystemKey.String("servicebus")
-	// Google Cloud Pub/Sub
-	MessagingSystemGCPPubsub = MessagingSystemKey.String("gcp_pubsub")
-	// Java Message Service
-	MessagingSystemJms = MessagingSystemKey.String("jms")
-	// Apache Kafka
-	MessagingSystemKafka = MessagingSystemKey.String("kafka")
-	// RabbitMQ
-	MessagingSystemRabbitmq = MessagingSystemKey.String("rabbitmq")
-	// Apache RocketMQ
-	MessagingSystemRocketmq = MessagingSystemKey.String("rocketmq")
-)
-
-// MessagingBatchMessageCount returns an attribute KeyValue conforming to
-// the "messaging.batch.message_count" semantic conventions. It represents the
-// number of messages sent, received, or processed in the scope of the batching
-// operation.
-func MessagingBatchMessageCount(val int) attribute.KeyValue {
-	return MessagingBatchMessageCountKey.Int(val)
-}
-
-// MessagingClientID returns an attribute KeyValue conforming to the
-// "messaging.client.id" semantic conventions. It represents a unique
-// identifier for the client that consumes or produces a message.
-func MessagingClientID(val string) attribute.KeyValue {
-	return MessagingClientIDKey.String(val)
-}
-
-// MessagingDestinationAnonymous returns an attribute KeyValue conforming to
-// the "messaging.destination.anonymous" semantic conventions. It represents a
-// boolean that is true if the message destination is anonymous (could be
-// unnamed or have auto-generated name).
-func MessagingDestinationAnonymous(val bool) attribute.KeyValue {
-	return MessagingDestinationAnonymousKey.Bool(val)
-}
-
-// MessagingDestinationName returns an attribute KeyValue conforming to the
-// "messaging.destination.name" semantic conventions. It represents the message
-// destination name
-func MessagingDestinationName(val string) attribute.KeyValue {
-	return MessagingDestinationNameKey.String(val)
-}
-
-// MessagingDestinationPartitionID returns an attribute KeyValue conforming
-// to the "messaging.destination.partition.id" semantic conventions. It
-// represents the identifier of the partition messages are sent to or received
-// from, unique within the `messaging.destination.name`.
-func MessagingDestinationPartitionID(val string) attribute.KeyValue {
-	return MessagingDestinationPartitionIDKey.String(val)
-}
-
-// MessagingDestinationTemplate returns an attribute KeyValue conforming to
-// the "messaging.destination.template" semantic conventions. It represents the
-// low cardinality representation of the messaging destination name
-func MessagingDestinationTemplate(val string) attribute.KeyValue {
-	return MessagingDestinationTemplateKey.String(val)
-}
-
-// MessagingDestinationTemporary returns an attribute KeyValue conforming to
-// the "messaging.destination.temporary" semantic conventions. It represents a
-// boolean that is true if the message destination is temporary and might not
-// exist anymore after messages are processed.
-func MessagingDestinationTemporary(val bool) attribute.KeyValue {
-	return MessagingDestinationTemporaryKey.Bool(val)
-}
-
-// MessagingDestinationPublishAnonymous returns an attribute KeyValue
-// conforming to the "messaging.destination_publish.anonymous" semantic
-// conventions. It represents a boolean that is true if the publish message
-// destination is anonymous (could be unnamed or have auto-generated name).
-func MessagingDestinationPublishAnonymous(val bool) attribute.KeyValue {
-	return MessagingDestinationPublishAnonymousKey.Bool(val)
-}
-
-// MessagingDestinationPublishName returns an attribute KeyValue conforming
-// to the "messaging.destination_publish.name" semantic conventions. It
-// represents the name of the original destination the message was published to
-func MessagingDestinationPublishName(val string) attribute.KeyValue {
-	return MessagingDestinationPublishNameKey.String(val)
-}
-
-// MessagingMessageBodySize returns an attribute KeyValue conforming to the
-// "messaging.message.body.size" semantic conventions. It represents the size
-// of the message body in bytes.
-func MessagingMessageBodySize(val int) attribute.KeyValue {
-	return MessagingMessageBodySizeKey.Int(val)
-}
-
-// MessagingMessageConversationID returns an attribute KeyValue conforming
-// to the "messaging.message.conversation_id" semantic conventions. It
-// represents the conversation ID identifying the conversation to which the
-// message belongs, represented as a string. Sometimes called "Correlation ID".
-func MessagingMessageConversationID(val string) attribute.KeyValue {
-	return MessagingMessageConversationIDKey.String(val)
-}
-
-// MessagingMessageEnvelopeSize returns an attribute KeyValue conforming to
-// the "messaging.message.envelope.size" semantic conventions. It represents
-// the size of the message body and metadata in bytes.
-func MessagingMessageEnvelopeSize(val int) attribute.KeyValue {
-	return MessagingMessageEnvelopeSizeKey.Int(val)
-}
-
-// MessagingMessageID returns an attribute KeyValue conforming to the
-// "messaging.message.id" semantic conventions. It represents a value used by
-// the messaging system as an identifier for the message, represented as a
-// string.
-func MessagingMessageID(val string) attribute.KeyValue {
-	return MessagingMessageIDKey.String(val)
-}
-
-// MessagingOperationName returns an attribute KeyValue conforming to the
-// "messaging.operation.name" semantic conventions. It represents the
-// system-specific name of the messaging operation.
-func MessagingOperationName(val string) attribute.KeyValue {
-	return MessagingOperationNameKey.String(val)
-}
-
-// This group describes attributes specific to Apache Kafka.
-const (
-	// MessagingKafkaConsumerGroupKey is the attribute Key conforming to the
-	// "messaging.kafka.consumer.group" semantic conventions. It represents the
-	// name of the Kafka Consumer Group that is handling the message. Only
-	// applies to consumers, not producers.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'my-group'
-	MessagingKafkaConsumerGroupKey = attribute.Key("messaging.kafka.consumer.group")
-
-	// MessagingKafkaMessageKeyKey is the attribute Key conforming to the
-	// "messaging.kafka.message.key" semantic conventions. It represents the
-	// message keys in Kafka are used for grouping alike messages to ensure
-	// they're processed on the same partition. They differ from
-	// `messaging.message.id` in that they're not unique. If the key is `null`,
-	// the attribute MUST NOT be set.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myKey'
-	// Note: If the key type is not string, it's string representation has to
-	// be supplied for the attribute. If the key has no unambiguous, canonical
-	// string form, don't include its value.
-	MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message.key")
-
-	// MessagingKafkaMessageOffsetKey is the attribute Key conforming to the
-	// "messaging.kafka.message.offset" semantic conventions. It represents the
-	// offset of a record in the corresponding Kafka partition.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 42
-	MessagingKafkaMessageOffsetKey = attribute.Key("messaging.kafka.message.offset")
-
-	// MessagingKafkaMessageTombstoneKey is the attribute Key conforming to the
-	// "messaging.kafka.message.tombstone" semantic conventions. It represents
-	// a boolean that is true if the message is a tombstone.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingKafkaMessageTombstoneKey = attribute.Key("messaging.kafka.message.tombstone")
-)
-
-// MessagingKafkaConsumerGroup returns an attribute KeyValue conforming to
-// the "messaging.kafka.consumer.group" semantic conventions. It represents the
-// name of the Kafka Consumer Group that is handling the message. Only applies
-// to consumers, not producers.
-func MessagingKafkaConsumerGroup(val string) attribute.KeyValue {
-	return MessagingKafkaConsumerGroupKey.String(val)
-}
-
-// MessagingKafkaMessageKey returns an attribute KeyValue conforming to the
-// "messaging.kafka.message.key" semantic conventions. It represents the
-// message keys in Kafka are used for grouping alike messages to ensure they're
-// processed on the same partition. They differ from `messaging.message.id` in
-// that they're not unique. If the key is `null`, the attribute MUST NOT be
-// set.
-func MessagingKafkaMessageKey(val string) attribute.KeyValue {
-	return MessagingKafkaMessageKeyKey.String(val)
-}
-
-// MessagingKafkaMessageOffset returns an attribute KeyValue conforming to
-// the "messaging.kafka.message.offset" semantic conventions. It represents the
-// offset of a record in the corresponding Kafka partition.
-func MessagingKafkaMessageOffset(val int) attribute.KeyValue {
-	return MessagingKafkaMessageOffsetKey.Int(val)
-}
-
-// MessagingKafkaMessageTombstone returns an attribute KeyValue conforming
-// to the "messaging.kafka.message.tombstone" semantic conventions. It
-// represents a boolean that is true if the message is a tombstone.
-func MessagingKafkaMessageTombstone(val bool) attribute.KeyValue {
-	return MessagingKafkaMessageTombstoneKey.Bool(val)
-}
-
-// This group describes attributes specific to RabbitMQ.
-const (
-	// MessagingRabbitmqDestinationRoutingKeyKey is the attribute Key
-	// conforming to the "messaging.rabbitmq.destination.routing_key" semantic
-	// conventions. It represents the rabbitMQ message routing key.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myKey'
-	MessagingRabbitmqDestinationRoutingKeyKey = attribute.Key("messaging.rabbitmq.destination.routing_key")
-
-	// MessagingRabbitmqMessageDeliveryTagKey is the attribute Key conforming
-	// to the "messaging.rabbitmq.message.delivery_tag" semantic conventions.
-	// It represents the rabbitMQ message delivery tag
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 123
-	MessagingRabbitmqMessageDeliveryTagKey = attribute.Key("messaging.rabbitmq.message.delivery_tag")
-)
-
-// MessagingRabbitmqDestinationRoutingKey returns an attribute KeyValue
-// conforming to the "messaging.rabbitmq.destination.routing_key" semantic
-// conventions. It represents the rabbitMQ message routing key.
-func MessagingRabbitmqDestinationRoutingKey(val string) attribute.KeyValue {
-	return MessagingRabbitmqDestinationRoutingKeyKey.String(val)
-}
-
-// MessagingRabbitmqMessageDeliveryTag returns an attribute KeyValue
-// conforming to the "messaging.rabbitmq.message.delivery_tag" semantic
-// conventions. It represents the rabbitMQ message delivery tag
-func MessagingRabbitmqMessageDeliveryTag(val int) attribute.KeyValue {
-	return MessagingRabbitmqMessageDeliveryTagKey.Int(val)
-}
-
-// This group describes attributes specific to RocketMQ.
-const (
-	// MessagingRocketmqClientGroupKey is the attribute Key conforming to the
-	// "messaging.rocketmq.client_group" semantic conventions. It represents
-	// the name of the RocketMQ producer/consumer group that is handling the
-	// message. The client type is identified by the SpanKind.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myConsumerGroup'
-	MessagingRocketmqClientGroupKey = attribute.Key("messaging.rocketmq.client_group")
-
-	// MessagingRocketmqConsumptionModelKey is the attribute Key conforming to
-	// the "messaging.rocketmq.consumption_model" semantic conventions. It
-	// represents the model of message consumption. This only applies to
-	// consumer spans.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingRocketmqConsumptionModelKey = attribute.Key("messaging.rocketmq.consumption_model")
-
-	// MessagingRocketmqMessageDelayTimeLevelKey is the attribute Key
-	// conforming to the "messaging.rocketmq.message.delay_time_level" semantic
-	// conventions. It represents the delay time level for delay message, which
-	// determines the message delay time.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3
-	MessagingRocketmqMessageDelayTimeLevelKey = attribute.Key("messaging.rocketmq.message.delay_time_level")
-
-	// MessagingRocketmqMessageDeliveryTimestampKey is the attribute Key
-	// conforming to the "messaging.rocketmq.message.delivery_timestamp"
-	// semantic conventions. It represents the timestamp in milliseconds that
-	// the delay message is expected to be delivered to consumer.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1665987217045
-	MessagingRocketmqMessageDeliveryTimestampKey = attribute.Key("messaging.rocketmq.message.delivery_timestamp")
-
-	// MessagingRocketmqMessageGroupKey is the attribute Key conforming to the
-	// "messaging.rocketmq.message.group" semantic conventions. It represents
-	// the it is essential for FIFO message. Messages that belong to the same
-	// message group are always processed one by one within the same consumer
-	// group.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myMessageGroup'
-	MessagingRocketmqMessageGroupKey = attribute.Key("messaging.rocketmq.message.group")
-
-	// MessagingRocketmqMessageKeysKey is the attribute Key conforming to the
-	// "messaging.rocketmq.message.keys" semantic conventions. It represents
-	// the key(s) of message, another way to mark message besides message id.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'keyA', 'keyB'
-	MessagingRocketmqMessageKeysKey = attribute.Key("messaging.rocketmq.message.keys")
-
-	// MessagingRocketmqMessageTagKey is the attribute Key conforming to the
-	// "messaging.rocketmq.message.tag" semantic conventions. It represents the
-	// secondary classifier of message besides topic.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'tagA'
-	MessagingRocketmqMessageTagKey = attribute.Key("messaging.rocketmq.message.tag")
-
-	// MessagingRocketmqMessageTypeKey is the attribute Key conforming to the
-	// "messaging.rocketmq.message.type" semantic conventions. It represents
-	// the type of message.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingRocketmqMessageTypeKey = attribute.Key("messaging.rocketmq.message.type")
-
-	// MessagingRocketmqNamespaceKey is the attribute Key conforming to the
-	// "messaging.rocketmq.namespace" semantic conventions. It represents the
-	// namespace of RocketMQ resources, resources in different namespaces are
-	// individual.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myNamespace'
-	MessagingRocketmqNamespaceKey = attribute.Key("messaging.rocketmq.namespace")
-)
-
-var (
-	// Clustering consumption model
-	MessagingRocketmqConsumptionModelClustering = MessagingRocketmqConsumptionModelKey.String("clustering")
-	// Broadcasting consumption model
-	MessagingRocketmqConsumptionModelBroadcasting = MessagingRocketmqConsumptionModelKey.String("broadcasting")
-)
-
-var (
-	// Normal message
-	MessagingRocketmqMessageTypeNormal = MessagingRocketmqMessageTypeKey.String("normal")
-	// FIFO message
-	MessagingRocketmqMessageTypeFifo = MessagingRocketmqMessageTypeKey.String("fifo")
-	// Delay message
-	MessagingRocketmqMessageTypeDelay = MessagingRocketmqMessageTypeKey.String("delay")
-	// Transaction message
-	MessagingRocketmqMessageTypeTransaction = MessagingRocketmqMessageTypeKey.String("transaction")
-)
-
-// MessagingRocketmqClientGroup returns an attribute KeyValue conforming to
-// the "messaging.rocketmq.client_group" semantic conventions. It represents
-// the name of the RocketMQ producer/consumer group that is handling the
-// message. The client type is identified by the SpanKind.
-func MessagingRocketmqClientGroup(val string) attribute.KeyValue {
-	return MessagingRocketmqClientGroupKey.String(val)
-}
-
-// MessagingRocketmqMessageDelayTimeLevel returns an attribute KeyValue
-// conforming to the "messaging.rocketmq.message.delay_time_level" semantic
-// conventions. It represents the delay time level for delay message, which
-// determines the message delay time.
-func MessagingRocketmqMessageDelayTimeLevel(val int) attribute.KeyValue {
-	return MessagingRocketmqMessageDelayTimeLevelKey.Int(val)
-}
-
-// MessagingRocketmqMessageDeliveryTimestamp returns an attribute KeyValue
-// conforming to the "messaging.rocketmq.message.delivery_timestamp" semantic
-// conventions. It represents the timestamp in milliseconds that the delay
-// message is expected to be delivered to consumer.
-func MessagingRocketmqMessageDeliveryTimestamp(val int) attribute.KeyValue {
-	return MessagingRocketmqMessageDeliveryTimestampKey.Int(val)
-}
-
-// MessagingRocketmqMessageGroup returns an attribute KeyValue conforming to
-// the "messaging.rocketmq.message.group" semantic conventions. It represents
-// the it is essential for FIFO message. Messages that belong to the same
-// message group are always processed one by one within the same consumer
-// group.
-func MessagingRocketmqMessageGroup(val string) attribute.KeyValue {
-	return MessagingRocketmqMessageGroupKey.String(val)
-}
-
-// MessagingRocketmqMessageKeys returns an attribute KeyValue conforming to
-// the "messaging.rocketmq.message.keys" semantic conventions. It represents
-// the key(s) of message, another way to mark message besides message id.
-func MessagingRocketmqMessageKeys(val ...string) attribute.KeyValue {
-	return MessagingRocketmqMessageKeysKey.StringSlice(val)
-}
-
-// MessagingRocketmqMessageTag returns an attribute KeyValue conforming to
-// the "messaging.rocketmq.message.tag" semantic conventions. It represents the
-// secondary classifier of message besides topic.
-func MessagingRocketmqMessageTag(val string) attribute.KeyValue {
-	return MessagingRocketmqMessageTagKey.String(val)
-}
-
-// MessagingRocketmqNamespace returns an attribute KeyValue conforming to
-// the "messaging.rocketmq.namespace" semantic conventions. It represents the
-// namespace of RocketMQ resources, resources in different namespaces are
-// individual.
-func MessagingRocketmqNamespace(val string) attribute.KeyValue {
-	return MessagingRocketmqNamespaceKey.String(val)
-}
-
-// This group describes attributes specific to GCP Pub/Sub.
-const (
-	// MessagingGCPPubsubMessageAckDeadlineKey is the attribute Key conforming
-	// to the "messaging.gcp_pubsub.message.ack_deadline" semantic conventions.
-	// It represents the ack deadline in seconds set for the modify ack
-	// deadline request.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 10
-	MessagingGCPPubsubMessageAckDeadlineKey = attribute.Key("messaging.gcp_pubsub.message.ack_deadline")
-
-	// MessagingGCPPubsubMessageAckIDKey is the attribute Key conforming to the
-	// "messaging.gcp_pubsub.message.ack_id" semantic conventions. It
-	// represents the ack id for a given message.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ack_id'
-	MessagingGCPPubsubMessageAckIDKey = attribute.Key("messaging.gcp_pubsub.message.ack_id")
-
-	// MessagingGCPPubsubMessageDeliveryAttemptKey is the attribute Key
-	// conforming to the "messaging.gcp_pubsub.message.delivery_attempt"
-	// semantic conventions. It represents the delivery attempt for a given
-	// message.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 2
-	MessagingGCPPubsubMessageDeliveryAttemptKey = attribute.Key("messaging.gcp_pubsub.message.delivery_attempt")
-
-	// MessagingGCPPubsubMessageOrderingKeyKey is the attribute Key conforming
-	// to the "messaging.gcp_pubsub.message.ordering_key" semantic conventions.
-	// It represents the ordering key for a given message. If the attribute is
-	// not present, the message does not have an ordering key.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ordering_key'
-	MessagingGCPPubsubMessageOrderingKeyKey = attribute.Key("messaging.gcp_pubsub.message.ordering_key")
-)
-
-// MessagingGCPPubsubMessageAckDeadline returns an attribute KeyValue
-// conforming to the "messaging.gcp_pubsub.message.ack_deadline" semantic
-// conventions. It represents the ack deadline in seconds set for the modify
-// ack deadline request.
-func MessagingGCPPubsubMessageAckDeadline(val int) attribute.KeyValue {
-	return MessagingGCPPubsubMessageAckDeadlineKey.Int(val)
-}
-
-// MessagingGCPPubsubMessageAckID returns an attribute KeyValue conforming
-// to the "messaging.gcp_pubsub.message.ack_id" semantic conventions. It
-// represents the ack id for a given message.
-func MessagingGCPPubsubMessageAckID(val string) attribute.KeyValue {
-	return MessagingGCPPubsubMessageAckIDKey.String(val)
-}
-
-// MessagingGCPPubsubMessageDeliveryAttempt returns an attribute KeyValue
-// conforming to the "messaging.gcp_pubsub.message.delivery_attempt" semantic
-// conventions. It represents the delivery attempt for a given message.
-func MessagingGCPPubsubMessageDeliveryAttempt(val int) attribute.KeyValue {
-	return MessagingGCPPubsubMessageDeliveryAttemptKey.Int(val)
-}
-
-// MessagingGCPPubsubMessageOrderingKey returns an attribute KeyValue
-// conforming to the "messaging.gcp_pubsub.message.ordering_key" semantic
-// conventions. It represents the ordering key for a given message. If the
-// attribute is not present, the message does not have an ordering key.
-func MessagingGCPPubsubMessageOrderingKey(val string) attribute.KeyValue {
-	return MessagingGCPPubsubMessageOrderingKeyKey.String(val)
-}
-
-// This group describes attributes specific to Azure Service Bus.
-const (
-	// MessagingServicebusDestinationSubscriptionNameKey is the attribute Key
-	// conforming to the "messaging.servicebus.destination.subscription_name"
-	// semantic conventions. It represents the name of the subscription in the
-	// topic messages are received from.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'mySubscription'
-	MessagingServicebusDestinationSubscriptionNameKey = attribute.Key("messaging.servicebus.destination.subscription_name")
-
-	// MessagingServicebusDispositionStatusKey is the attribute Key conforming
-	// to the "messaging.servicebus.disposition_status" semantic conventions.
-	// It represents the describes the [settlement
-	// type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock).
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	MessagingServicebusDispositionStatusKey = attribute.Key("messaging.servicebus.disposition_status")
-
-	// MessagingServicebusMessageDeliveryCountKey is the attribute Key
-	// conforming to the "messaging.servicebus.message.delivery_count" semantic
-	// conventions. It represents the number of deliveries that have been
-	// attempted for this message.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 2
-	MessagingServicebusMessageDeliveryCountKey = attribute.Key("messaging.servicebus.message.delivery_count")
-
-	// MessagingServicebusMessageEnqueuedTimeKey is the attribute Key
-	// conforming to the "messaging.servicebus.message.enqueued_time" semantic
-	// conventions. It represents the UTC epoch seconds at which the message
-	// has been accepted and stored in the entity.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1701393730
-	MessagingServicebusMessageEnqueuedTimeKey = attribute.Key("messaging.servicebus.message.enqueued_time")
-)
-
-var (
-	// Message is completed
-	MessagingServicebusDispositionStatusComplete = MessagingServicebusDispositionStatusKey.String("complete")
-	// Message is abandoned
-	MessagingServicebusDispositionStatusAbandon = MessagingServicebusDispositionStatusKey.String("abandon")
-	// Message is sent to dead letter queue
-	MessagingServicebusDispositionStatusDeadLetter = MessagingServicebusDispositionStatusKey.String("dead_letter")
-	// Message is deferred
-	MessagingServicebusDispositionStatusDefer = MessagingServicebusDispositionStatusKey.String("defer")
-)
-
-// MessagingServicebusDestinationSubscriptionName returns an attribute
-// KeyValue conforming to the
-// "messaging.servicebus.destination.subscription_name" semantic conventions.
-// It represents the name of the subscription in the topic messages are
-// received from.
-func MessagingServicebusDestinationSubscriptionName(val string) attribute.KeyValue {
-	return MessagingServicebusDestinationSubscriptionNameKey.String(val)
-}
-
-// MessagingServicebusMessageDeliveryCount returns an attribute KeyValue
-// conforming to the "messaging.servicebus.message.delivery_count" semantic
-// conventions. It represents the number of deliveries that have been attempted
-// for this message.
-func MessagingServicebusMessageDeliveryCount(val int) attribute.KeyValue {
-	return MessagingServicebusMessageDeliveryCountKey.Int(val)
-}
-
-// MessagingServicebusMessageEnqueuedTime returns an attribute KeyValue
-// conforming to the "messaging.servicebus.message.enqueued_time" semantic
-// conventions. It represents the UTC epoch seconds at which the message has
-// been accepted and stored in the entity.
-func MessagingServicebusMessageEnqueuedTime(val int) attribute.KeyValue {
-	return MessagingServicebusMessageEnqueuedTimeKey.Int(val)
-}
-
-// This group describes attributes specific to Azure Event Hubs.
-const (
-	// MessagingEventhubsConsumerGroupKey is the attribute Key conforming to
-	// the "messaging.eventhubs.consumer.group" semantic conventions. It
-	// represents the name of the consumer group the event consumer is
-	// associated with.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'indexer'
-	MessagingEventhubsConsumerGroupKey = attribute.Key("messaging.eventhubs.consumer.group")
-
-	// MessagingEventhubsMessageEnqueuedTimeKey is the attribute Key conforming
-	// to the "messaging.eventhubs.message.enqueued_time" semantic conventions.
-	// It represents the UTC epoch seconds at which the message has been
-	// accepted and stored in the entity.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1701393730
-	MessagingEventhubsMessageEnqueuedTimeKey = attribute.Key("messaging.eventhubs.message.enqueued_time")
-)
-
-// MessagingEventhubsConsumerGroup returns an attribute KeyValue conforming
-// to the "messaging.eventhubs.consumer.group" semantic conventions. It
-// represents the name of the consumer group the event consumer is associated
-// with.
-func MessagingEventhubsConsumerGroup(val string) attribute.KeyValue {
-	return MessagingEventhubsConsumerGroupKey.String(val)
-}
-
-// MessagingEventhubsMessageEnqueuedTime returns an attribute KeyValue
-// conforming to the "messaging.eventhubs.message.enqueued_time" semantic
-// conventions. It represents the UTC epoch seconds at which the message has
-// been accepted and stored in the entity.
-func MessagingEventhubsMessageEnqueuedTime(val int) attribute.KeyValue {
-	return MessagingEventhubsMessageEnqueuedTimeKey.Int(val)
-}
-
-// These attributes may be used for any network related operation.
-const (
-	// NetworkCarrierIccKey is the attribute Key conforming to the
-	// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1
-	// alpha-2 2-character country code associated with the mobile carrier
-	// network.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'DE'
-	NetworkCarrierIccKey = attribute.Key("network.carrier.icc")
-
-	// NetworkCarrierMccKey is the attribute Key conforming to the
-	// "network.carrier.mcc" semantic conventions. It represents the mobile
-	// carrier country code.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '310'
-	NetworkCarrierMccKey = attribute.Key("network.carrier.mcc")
-
-	// NetworkCarrierMncKey is the attribute Key conforming to the
-	// "network.carrier.mnc" semantic conventions. It represents the mobile
-	// carrier network code.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '001'
-	NetworkCarrierMncKey = attribute.Key("network.carrier.mnc")
-
-	// NetworkCarrierNameKey is the attribute Key conforming to the
-	// "network.carrier.name" semantic conventions. It represents the name of
-	// the mobile carrier.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'sprint'
-	NetworkCarrierNameKey = attribute.Key("network.carrier.name")
-
-	// NetworkConnectionSubtypeKey is the attribute Key conforming to the
-	// "network.connection.subtype" semantic conventions. It represents the
-	// this describes more details regarding the connection.type. It may be the
-	// type of cell technology connection, but it could be used for describing
-	// details about a wifi connection.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'LTE'
-	NetworkConnectionSubtypeKey = attribute.Key("network.connection.subtype")
-
-	// NetworkConnectionTypeKey is the attribute Key conforming to the
-	// "network.connection.type" semantic conventions. It represents the
-	// internet connection type.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'wifi'
-	NetworkConnectionTypeKey = attribute.Key("network.connection.type")
-
-	// NetworkIoDirectionKey is the attribute Key conforming to the
-	// "network.io.direction" semantic conventions. It represents the network
-	// IO operation direction.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'transmit'
-	NetworkIoDirectionKey = attribute.Key("network.io.direction")
-
-	// NetworkLocalAddressKey is the attribute Key conforming to the
-	// "network.local.address" semantic conventions. It represents the local
-	// address of the network connection - IP address or Unix domain socket
-	// name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '10.1.2.80', '/tmp/my.sock'
-	NetworkLocalAddressKey = attribute.Key("network.local.address")
-
-	// NetworkLocalPortKey is the attribute Key conforming to the
-	// "network.local.port" semantic conventions. It represents the local port
-	// number of the network connection.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 65123
-	NetworkLocalPortKey = attribute.Key("network.local.port")
-
-	// NetworkPeerAddressKey is the attribute Key conforming to the
-	// "network.peer.address" semantic conventions. It represents the peer
-	// address of the network connection - IP address or Unix domain socket
-	// name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '10.1.2.80', '/tmp/my.sock'
-	NetworkPeerAddressKey = attribute.Key("network.peer.address")
-
-	// NetworkPeerPortKey is the attribute Key conforming to the
-	// "network.peer.port" semantic conventions. It represents the peer port
-	// number of the network connection.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 65123
-	NetworkPeerPortKey = attribute.Key("network.peer.port")
-
-	// NetworkProtocolNameKey is the attribute Key conforming to the
-	// "network.protocol.name" semantic conventions. It represents the [OSI
-	// application layer](https://osi-model.com/application-layer/) or non-OSI
-	// equivalent.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'amqp', 'http', 'mqtt'
-	// Note: The value SHOULD be normalized to lowercase.
-	NetworkProtocolNameKey = attribute.Key("network.protocol.name")
-
-	// NetworkProtocolVersionKey is the attribute Key conforming to the
-	// "network.protocol.version" semantic conventions. It represents the
-	// actual version of the protocol used for network communication.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '1.1', '2'
-	// Note: If protocol version is subject to negotiation (for example using
-	// [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute
-	// SHOULD be set to the negotiated version. If the actual protocol version
-	// is not known, this attribute SHOULD NOT be set.
-	NetworkProtocolVersionKey = attribute.Key("network.protocol.version")
-
-	// NetworkTransportKey is the attribute Key conforming to the
-	// "network.transport" semantic conventions. It represents the [OSI
-	// transport layer](https://osi-model.com/transport-layer/) or
-	// [inter-process communication
-	// method](https://wikipedia.org/wiki/Inter-process_communication).
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'tcp', 'udp'
-	// Note: The value SHOULD be normalized to lowercase.
-	//
-	// Consider always setting the transport when setting a port number, since
-	// a port number is ambiguous without knowing the transport. For example
-	// different processes could be listening on TCP port 12345 and UDP port
-	// 12345.
-	NetworkTransportKey = attribute.Key("network.transport")
-
-	// NetworkTypeKey is the attribute Key conforming to the "network.type"
-	// semantic conventions. It represents the [OSI network
-	// layer](https://osi-model.com/network-layer/) or non-OSI equivalent.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'ipv4', 'ipv6'
-	// Note: The value SHOULD be normalized to lowercase.
-	NetworkTypeKey = attribute.Key("network.type")
-)
-
-var (
-	// GPRS
-	NetworkConnectionSubtypeGprs = NetworkConnectionSubtypeKey.String("gprs")
-	// EDGE
-	NetworkConnectionSubtypeEdge = NetworkConnectionSubtypeKey.String("edge")
-	// UMTS
-	NetworkConnectionSubtypeUmts = NetworkConnectionSubtypeKey.String("umts")
-	// CDMA
-	NetworkConnectionSubtypeCdma = NetworkConnectionSubtypeKey.String("cdma")
-	// EVDO Rel. 0
-	NetworkConnectionSubtypeEvdo0 = NetworkConnectionSubtypeKey.String("evdo_0")
-	// EVDO Rev. A
-	NetworkConnectionSubtypeEvdoA = NetworkConnectionSubtypeKey.String("evdo_a")
-	// CDMA2000 1XRTT
-	NetworkConnectionSubtypeCdma20001xrtt = NetworkConnectionSubtypeKey.String("cdma2000_1xrtt")
-	// HSDPA
-	NetworkConnectionSubtypeHsdpa = NetworkConnectionSubtypeKey.String("hsdpa")
-	// HSUPA
-	NetworkConnectionSubtypeHsupa = NetworkConnectionSubtypeKey.String("hsupa")
-	// HSPA
-	NetworkConnectionSubtypeHspa = NetworkConnectionSubtypeKey.String("hspa")
-	// IDEN
-	NetworkConnectionSubtypeIden = NetworkConnectionSubtypeKey.String("iden")
-	// EVDO Rev. B
-	NetworkConnectionSubtypeEvdoB = NetworkConnectionSubtypeKey.String("evdo_b")
-	// LTE
-	NetworkConnectionSubtypeLte = NetworkConnectionSubtypeKey.String("lte")
-	// EHRPD
-	NetworkConnectionSubtypeEhrpd = NetworkConnectionSubtypeKey.String("ehrpd")
-	// HSPAP
-	NetworkConnectionSubtypeHspap = NetworkConnectionSubtypeKey.String("hspap")
-	// GSM
-	NetworkConnectionSubtypeGsm = NetworkConnectionSubtypeKey.String("gsm")
-	// TD-SCDMA
-	NetworkConnectionSubtypeTdScdma = NetworkConnectionSubtypeKey.String("td_scdma")
-	// IWLAN
-	NetworkConnectionSubtypeIwlan = NetworkConnectionSubtypeKey.String("iwlan")
-	// 5G NR (New Radio)
-	NetworkConnectionSubtypeNr = NetworkConnectionSubtypeKey.String("nr")
-	// 5G NRNSA (New Radio Non-Standalone)
-	NetworkConnectionSubtypeNrnsa = NetworkConnectionSubtypeKey.String("nrnsa")
-	// LTE CA
-	NetworkConnectionSubtypeLteCa = NetworkConnectionSubtypeKey.String("lte_ca")
-)
-
-var (
-	// wifi
-	NetworkConnectionTypeWifi = NetworkConnectionTypeKey.String("wifi")
-	// wired
-	NetworkConnectionTypeWired = NetworkConnectionTypeKey.String("wired")
-	// cell
-	NetworkConnectionTypeCell = NetworkConnectionTypeKey.String("cell")
-	// unavailable
-	NetworkConnectionTypeUnavailable = NetworkConnectionTypeKey.String("unavailable")
-	// unknown
-	NetworkConnectionTypeUnknown = NetworkConnectionTypeKey.String("unknown")
-)
-
-var (
-	// transmit
-	NetworkIoDirectionTransmit = NetworkIoDirectionKey.String("transmit")
-	// receive
-	NetworkIoDirectionReceive = NetworkIoDirectionKey.String("receive")
-)
-
-var (
-	// TCP
-	NetworkTransportTCP = NetworkTransportKey.String("tcp")
-	// UDP
-	NetworkTransportUDP = NetworkTransportKey.String("udp")
-	// Named or anonymous pipe
-	NetworkTransportPipe = NetworkTransportKey.String("pipe")
-	// Unix domain socket
-	NetworkTransportUnix = NetworkTransportKey.String("unix")
-)
-
-var (
-	// IPv4
-	NetworkTypeIpv4 = NetworkTypeKey.String("ipv4")
-	// IPv6
-	NetworkTypeIpv6 = NetworkTypeKey.String("ipv6")
-)
-
-// NetworkCarrierIcc returns an attribute KeyValue conforming to the
-// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1
-// alpha-2 2-character country code associated with the mobile carrier network.
-func NetworkCarrierIcc(val string) attribute.KeyValue {
-	return NetworkCarrierIccKey.String(val)
-}
-
-// NetworkCarrierMcc returns an attribute KeyValue conforming to the
-// "network.carrier.mcc" semantic conventions. It represents the mobile carrier
-// country code.
-func NetworkCarrierMcc(val string) attribute.KeyValue {
-	return NetworkCarrierMccKey.String(val)
-}
-
-// NetworkCarrierMnc returns an attribute KeyValue conforming to the
-// "network.carrier.mnc" semantic conventions. It represents the mobile carrier
-// network code.
-func NetworkCarrierMnc(val string) attribute.KeyValue {
-	return NetworkCarrierMncKey.String(val)
-}
-
-// NetworkCarrierName returns an attribute KeyValue conforming to the
-// "network.carrier.name" semantic conventions. It represents the name of the
-// mobile carrier.
-func NetworkCarrierName(val string) attribute.KeyValue {
-	return NetworkCarrierNameKey.String(val)
-}
-
-// NetworkLocalAddress returns an attribute KeyValue conforming to the
-// "network.local.address" semantic conventions. It represents the local
-// address of the network connection - IP address or Unix domain socket name.
-func NetworkLocalAddress(val string) attribute.KeyValue {
-	return NetworkLocalAddressKey.String(val)
-}
-
-// NetworkLocalPort returns an attribute KeyValue conforming to the
-// "network.local.port" semantic conventions. It represents the local port
-// number of the network connection.
-func NetworkLocalPort(val int) attribute.KeyValue {
-	return NetworkLocalPortKey.Int(val)
-}
-
-// NetworkPeerAddress returns an attribute KeyValue conforming to the
-// "network.peer.address" semantic conventions. It represents the peer address
-// of the network connection - IP address or Unix domain socket name.
-func NetworkPeerAddress(val string) attribute.KeyValue {
-	return NetworkPeerAddressKey.String(val)
-}
-
-// NetworkPeerPort returns an attribute KeyValue conforming to the
-// "network.peer.port" semantic conventions. It represents the peer port number
-// of the network connection.
-func NetworkPeerPort(val int) attribute.KeyValue {
-	return NetworkPeerPortKey.Int(val)
-}
-
-// NetworkProtocolName returns an attribute KeyValue conforming to the
-// "network.protocol.name" semantic conventions. It represents the [OSI
-// application layer](https://osi-model.com/application-layer/) or non-OSI
-// equivalent.
-func NetworkProtocolName(val string) attribute.KeyValue {
-	return NetworkProtocolNameKey.String(val)
-}
-
-// NetworkProtocolVersion returns an attribute KeyValue conforming to the
-// "network.protocol.version" semantic conventions. It represents the actual
-// version of the protocol used for network communication.
-func NetworkProtocolVersion(val string) attribute.KeyValue {
-	return NetworkProtocolVersionKey.String(val)
-}
-
-// An OCI image manifest.
-const (
-	// OciManifestDigestKey is the attribute Key conforming to the
-	// "oci.manifest.digest" semantic conventions. It represents the digest of
-	// the OCI image manifest. For container images specifically is the digest
-	// by which the container image is known.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// 'sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4'
-	// Note: Follows [OCI Image Manifest
-	// Specification](https://github.com/opencontainers/image-spec/blob/main/manifest.md),
-	// and specifically the [Digest
-	// property](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests).
-	// An example can be found in [Example Image
-	// Manifest](https://docs.docker.com/registry/spec/manifest-v2-2/#example-image-manifest).
-	OciManifestDigestKey = attribute.Key("oci.manifest.digest")
-)
-
-// OciManifestDigest returns an attribute KeyValue conforming to the
-// "oci.manifest.digest" semantic conventions. It represents the digest of the
-// OCI image manifest. For container images specifically is the digest by which
-// the container image is known.
-func OciManifestDigest(val string) attribute.KeyValue {
-	return OciManifestDigestKey.String(val)
-}
-
-// Attributes used by the OpenTracing Shim layer.
-const (
-	// OpentracingRefTypeKey is the attribute Key conforming to the
-	// "opentracing.ref_type" semantic conventions. It represents the
-	// parent-child Reference type
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: The causal relationship between a child Span and a parent Span.
-	OpentracingRefTypeKey = attribute.Key("opentracing.ref_type")
-)
-
-var (
-	// The parent Span depends on the child Span in some capacity
-	OpentracingRefTypeChildOf = OpentracingRefTypeKey.String("child_of")
-	// The parent Span doesn't depend in any way on the result of the child Span
-	OpentracingRefTypeFollowsFrom = OpentracingRefTypeKey.String("follows_from")
-)
-
-// The operating system (OS) on which the process represented by this resource
-// is running.
-const (
-	// OSBuildIDKey is the attribute Key conforming to the "os.build_id"
-	// semantic conventions. It represents the unique identifier for a
-	// particular build or compilation of the operating system.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'TQ3C.230805.001.B2', '20E247', '22621'
-	OSBuildIDKey = attribute.Key("os.build_id")
-
-	// OSDescriptionKey is the attribute Key conforming to the "os.description"
-	// semantic conventions. It represents the human readable (not intended to
-	// be parsed) OS version information, like e.g. reported by `ver` or
-	// `lsb_release -a` commands.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1
-	// LTS'
-	OSDescriptionKey = attribute.Key("os.description")
-
-	// OSNameKey is the attribute Key conforming to the "os.name" semantic
-	// conventions. It represents the human readable operating system name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'iOS', 'Android', 'Ubuntu'
-	OSNameKey = attribute.Key("os.name")
-
-	// OSTypeKey is the attribute Key conforming to the "os.type" semantic
-	// conventions. It represents the operating system type.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	OSTypeKey = attribute.Key("os.type")
-
-	// OSVersionKey is the attribute Key conforming to the "os.version"
-	// semantic conventions. It represents the version string of the operating
-	// system as defined in [Version
-	// Attributes](/docs/resource/README.md#version-attributes).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '14.2.1', '18.04.1'
-	OSVersionKey = attribute.Key("os.version")
-)
-
-var (
-	// Microsoft Windows
-	OSTypeWindows = OSTypeKey.String("windows")
-	// Linux
-	OSTypeLinux = OSTypeKey.String("linux")
-	// Apple Darwin
-	OSTypeDarwin = OSTypeKey.String("darwin")
-	// FreeBSD
-	OSTypeFreeBSD = OSTypeKey.String("freebsd")
-	// NetBSD
-	OSTypeNetBSD = OSTypeKey.String("netbsd")
-	// OpenBSD
-	OSTypeOpenBSD = OSTypeKey.String("openbsd")
-	// DragonFly BSD
-	OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd")
-	// HP-UX (Hewlett Packard Unix)
-	OSTypeHPUX = OSTypeKey.String("hpux")
-	// AIX (Advanced Interactive eXecutive)
-	OSTypeAIX = OSTypeKey.String("aix")
-	// SunOS, Oracle Solaris
-	OSTypeSolaris = OSTypeKey.String("solaris")
-	// IBM z/OS
-	OSTypeZOS = OSTypeKey.String("z_os")
-)
-
-// OSBuildID returns an attribute KeyValue conforming to the "os.build_id"
-// semantic conventions. It represents the unique identifier for a particular
-// build or compilation of the operating system.
-func OSBuildID(val string) attribute.KeyValue {
-	return OSBuildIDKey.String(val)
-}
-
-// OSDescription returns an attribute KeyValue conforming to the
-// "os.description" semantic conventions. It represents the human readable (not
-// intended to be parsed) OS version information, like e.g. reported by `ver`
-// or `lsb_release -a` commands.
-func OSDescription(val string) attribute.KeyValue {
-	return OSDescriptionKey.String(val)
-}
-
-// OSName returns an attribute KeyValue conforming to the "os.name" semantic
-// conventions. It represents the human readable operating system name.
-func OSName(val string) attribute.KeyValue {
-	return OSNameKey.String(val)
-}
-
-// OSVersion returns an attribute KeyValue conforming to the "os.version"
-// semantic conventions. It represents the version string of the operating
-// system as defined in [Version
-// Attributes](/docs/resource/README.md#version-attributes).
-func OSVersion(val string) attribute.KeyValue {
-	return OSVersionKey.String(val)
-}
-
-// Attributes reserved for OpenTelemetry
-const (
-	// OTelStatusCodeKey is the attribute Key conforming to the
-	// "otel.status_code" semantic conventions. It represents the name of the
-	// code, either "OK" or "ERROR". MUST NOT be set if the status code is
-	// UNSET.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	OTelStatusCodeKey = attribute.Key("otel.status_code")
-
-	// OTelStatusDescriptionKey is the attribute Key conforming to the
-	// "otel.status_description" semantic conventions. It represents the
-	// description of the Status if it has a value, otherwise not set.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'resource not found'
-	OTelStatusDescriptionKey = attribute.Key("otel.status_description")
-)
-
-var (
-	// The operation has been validated by an Application developer or Operator to have completed successfully
-	OTelStatusCodeOk = OTelStatusCodeKey.String("OK")
-	// The operation contains an error
-	OTelStatusCodeError = OTelStatusCodeKey.String("ERROR")
-)
-
-// OTelStatusDescription returns an attribute KeyValue conforming to the
-// "otel.status_description" semantic conventions. It represents the
-// description of the Status if it has a value, otherwise not set.
-func OTelStatusDescription(val string) attribute.KeyValue {
-	return OTelStatusDescriptionKey.String(val)
-}
-
-// Attributes used by non-OTLP exporters to represent OpenTelemetry Scope's
-// concepts.
-const (
-	// OTelScopeNameKey is the attribute Key conforming to the
-	// "otel.scope.name" semantic conventions. It represents the name of the
-	// instrumentation scope - (`InstrumentationScope.Name` in OTLP).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'io.opentelemetry.contrib.mongodb'
-	OTelScopeNameKey = attribute.Key("otel.scope.name")
-
-	// OTelScopeVersionKey is the attribute Key conforming to the
-	// "otel.scope.version" semantic conventions. It represents the version of
-	// the instrumentation scope - (`InstrumentationScope.Version` in OTLP).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '1.0.0'
-	OTelScopeVersionKey = attribute.Key("otel.scope.version")
-)
-
-// OTelScopeName returns an attribute KeyValue conforming to the
-// "otel.scope.name" semantic conventions. It represents the name of the
-// instrumentation scope - (`InstrumentationScope.Name` in OTLP).
-func OTelScopeName(val string) attribute.KeyValue {
-	return OTelScopeNameKey.String(val)
-}
-
-// OTelScopeVersion returns an attribute KeyValue conforming to the
-// "otel.scope.version" semantic conventions. It represents the version of the
-// instrumentation scope - (`InstrumentationScope.Version` in OTLP).
-func OTelScopeVersion(val string) attribute.KeyValue {
-	return OTelScopeVersionKey.String(val)
-}
-
-// Operations that access some remote service.
-const (
-	// PeerServiceKey is the attribute Key conforming to the "peer.service"
-	// semantic conventions. It represents the
-	// [`service.name`](/docs/resource/README.md#service) of the remote
-	// service. SHOULD be equal to the actual `service.name` resource attribute
-	// of the remote service if any.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'AuthTokenCache'
-	PeerServiceKey = attribute.Key("peer.service")
-)
-
-// PeerService returns an attribute KeyValue conforming to the
-// "peer.service" semantic conventions. It represents the
-// [`service.name`](/docs/resource/README.md#service) of the remote service.
-// SHOULD be equal to the actual `service.name` resource attribute of the
-// remote service if any.
-func PeerService(val string) attribute.KeyValue {
-	return PeerServiceKey.String(val)
-}
-
-// An operating system process.
-const (
-	// ProcessCommandKey is the attribute Key conforming to the
-	// "process.command" semantic conventions. It represents the command used
-	// to launch the process (i.e. the command name). On Linux based systems,
-	// can be set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can
-	// be set to the first parameter extracted from `GetCommandLineW`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'cmd/otelcol'
-	ProcessCommandKey = attribute.Key("process.command")
-
-	// ProcessCommandArgsKey is the attribute Key conforming to the
-	// "process.command_args" semantic conventions. It represents the all the
-	// command arguments (including the command/executable itself) as received
-	// by the process. On Linux-based systems (and some other Unixoid systems
-	// supporting procfs), can be set according to the list of null-delimited
-	// strings extracted from `proc/[pid]/cmdline`. For libc-based executables,
-	// this would be the full argv vector passed to `main`.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'cmd/otecol', '--config=config.yaml'
-	ProcessCommandArgsKey = attribute.Key("process.command_args")
-
-	// ProcessCommandLineKey is the attribute Key conforming to the
-	// "process.command_line" semantic conventions. It represents the full
-	// command used to launch the process as a single string representing the
-	// full command. On Windows, can be set to the result of `GetCommandLineW`.
-	// Do not set this if you have to assemble it just for monitoring; use
-	// `process.command_args` instead.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"'
-	ProcessCommandLineKey = attribute.Key("process.command_line")
-
-	// ProcessContextSwitchTypeKey is the attribute Key conforming to the
-	// "process.context_switch_type" semantic conventions. It represents the
-	// specifies whether the context switches for this data point were
-	// voluntary or involuntary.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	ProcessContextSwitchTypeKey = attribute.Key("process.context_switch_type")
-
-	// ProcessCreationTimeKey is the attribute Key conforming to the
-	// "process.creation.time" semantic conventions. It represents the date and
-	// time the process was created, in ISO 8601 format.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2023-11-21T09:25:34.853Z'
-	ProcessCreationTimeKey = attribute.Key("process.creation.time")
-
-	// ProcessExecutableNameKey is the attribute Key conforming to the
-	// "process.executable.name" semantic conventions. It represents the name
-	// of the process executable. On Linux based systems, can be set to the
-	// `Name` in `proc/[pid]/status`. On Windows, can be set to the base name
-	// of `GetProcessImageFileNameW`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'otelcol'
-	ProcessExecutableNameKey = attribute.Key("process.executable.name")
-
-	// ProcessExecutablePathKey is the attribute Key conforming to the
-	// "process.executable.path" semantic conventions. It represents the full
-	// path to the process executable. On Linux based systems, can be set to
-	// the target of `proc/[pid]/exe`. On Windows, can be set to the result of
-	// `GetProcessImageFileNameW`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/usr/bin/cmd/otelcol'
-	ProcessExecutablePathKey = attribute.Key("process.executable.path")
-
-	// ProcessExitCodeKey is the attribute Key conforming to the
-	// "process.exit.code" semantic conventions. It represents the exit code of
-	// the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 127
-	ProcessExitCodeKey = attribute.Key("process.exit.code")
-
-	// ProcessExitTimeKey is the attribute Key conforming to the
-	// "process.exit.time" semantic conventions. It represents the date and
-	// time the process exited, in ISO 8601 format.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2023-11-21T09:26:12.315Z'
-	ProcessExitTimeKey = attribute.Key("process.exit.time")
-
-	// ProcessGroupLeaderPIDKey is the attribute Key conforming to the
-	// "process.group_leader.pid" semantic conventions. It represents the PID
-	// of the process's group leader. This is also the process group ID (PGID)
-	// of the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 23
-	ProcessGroupLeaderPIDKey = attribute.Key("process.group_leader.pid")
-
-	// ProcessInteractiveKey is the attribute Key conforming to the
-	// "process.interactive" semantic conventions. It represents the whether
-	// the process is connected to an interactive shell.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	ProcessInteractiveKey = attribute.Key("process.interactive")
-
-	// ProcessOwnerKey is the attribute Key conforming to the "process.owner"
-	// semantic conventions. It represents the username of the user that owns
-	// the process.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'root'
-	ProcessOwnerKey = attribute.Key("process.owner")
-
-	// ProcessPagingFaultTypeKey is the attribute Key conforming to the
-	// "process.paging.fault_type" semantic conventions. It represents the type
-	// of page fault for this data point. Type `major` is for major/hard page
-	// faults, and `minor` is for minor/soft page faults.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	ProcessPagingFaultTypeKey = attribute.Key("process.paging.fault_type")
-
-	// ProcessParentPIDKey is the attribute Key conforming to the
-	// "process.parent_pid" semantic conventions. It represents the parent
-	// Process identifier (PPID).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 111
-	ProcessParentPIDKey = attribute.Key("process.parent_pid")
-
-	// ProcessPIDKey is the attribute Key conforming to the "process.pid"
-	// semantic conventions. It represents the process identifier (PID).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1234
-	ProcessPIDKey = attribute.Key("process.pid")
-
-	// ProcessRealUserIDKey is the attribute Key conforming to the
-	// "process.real_user.id" semantic conventions. It represents the real user
-	// ID (RUID) of the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1000
-	ProcessRealUserIDKey = attribute.Key("process.real_user.id")
-
-	// ProcessRealUserNameKey is the attribute Key conforming to the
-	// "process.real_user.name" semantic conventions. It represents the
-	// username of the real user of the process.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'operator'
-	ProcessRealUserNameKey = attribute.Key("process.real_user.name")
-
-	// ProcessRuntimeDescriptionKey is the attribute Key conforming to the
-	// "process.runtime.description" semantic conventions. It represents an
-	// additional description about the runtime of the process, for example a
-	// specific vendor customization of the runtime environment.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0'
-	ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description")
-
-	// ProcessRuntimeNameKey is the attribute Key conforming to the
-	// "process.runtime.name" semantic conventions. It represents the name of
-	// the runtime of this process. For compiled native binaries, this SHOULD
-	// be the name of the compiler.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'OpenJDK Runtime Environment'
-	ProcessRuntimeNameKey = attribute.Key("process.runtime.name")
-
-	// ProcessRuntimeVersionKey is the attribute Key conforming to the
-	// "process.runtime.version" semantic conventions. It represents the
-	// version of the runtime of this process, as returned by the runtime
-	// without modification.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '14.0.2'
-	ProcessRuntimeVersionKey = attribute.Key("process.runtime.version")
-
-	// ProcessSavedUserIDKey is the attribute Key conforming to the
-	// "process.saved_user.id" semantic conventions. It represents the saved
-	// user ID (SUID) of the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1002
-	ProcessSavedUserIDKey = attribute.Key("process.saved_user.id")
-
-	// ProcessSavedUserNameKey is the attribute Key conforming to the
-	// "process.saved_user.name" semantic conventions. It represents the
-	// username of the saved user.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'operator'
-	ProcessSavedUserNameKey = attribute.Key("process.saved_user.name")
-
-	// ProcessSessionLeaderPIDKey is the attribute Key conforming to the
-	// "process.session_leader.pid" semantic conventions. It represents the PID
-	// of the process's session leader. This is also the session ID (SID) of
-	// the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 14
-	ProcessSessionLeaderPIDKey = attribute.Key("process.session_leader.pid")
-
-	// ProcessUserIDKey is the attribute Key conforming to the
-	// "process.user.id" semantic conventions. It represents the effective user
-	// ID (EUID) of the process.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1001
-	ProcessUserIDKey = attribute.Key("process.user.id")
-
-	// ProcessUserNameKey is the attribute Key conforming to the
-	// "process.user.name" semantic conventions. It represents the username of
-	// the effective user of the process.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'root'
-	ProcessUserNameKey = attribute.Key("process.user.name")
-
-	// ProcessVpidKey is the attribute Key conforming to the "process.vpid"
-	// semantic conventions. It represents the virtual process identifier.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 12
-	// Note: The process ID within a PID namespace. This is not necessarily
-	// unique across all processes on the host but it is unique within the
-	// process namespace that the process exists within.
-	ProcessVpidKey = attribute.Key("process.vpid")
-)
-
-var (
-	// voluntary
-	ProcessContextSwitchTypeVoluntary = ProcessContextSwitchTypeKey.String("voluntary")
-	// involuntary
-	ProcessContextSwitchTypeInvoluntary = ProcessContextSwitchTypeKey.String("involuntary")
-)
-
-var (
-	// major
-	ProcessPagingFaultTypeMajor = ProcessPagingFaultTypeKey.String("major")
-	// minor
-	ProcessPagingFaultTypeMinor = ProcessPagingFaultTypeKey.String("minor")
-)
-
-// ProcessCommand returns an attribute KeyValue conforming to the
-// "process.command" semantic conventions. It represents the command used to
-// launch the process (i.e. the command name). On Linux based systems, can be
-// set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can be set to
-// the first parameter extracted from `GetCommandLineW`.
-func ProcessCommand(val string) attribute.KeyValue {
-	return ProcessCommandKey.String(val)
-}
-
-// ProcessCommandArgs returns an attribute KeyValue conforming to the
-// "process.command_args" semantic conventions. It represents the all the
-// command arguments (including the command/executable itself) as received by
-// the process. On Linux-based systems (and some other Unixoid systems
-// supporting procfs), can be set according to the list of null-delimited
-// strings extracted from `proc/[pid]/cmdline`. For libc-based executables,
-// this would be the full argv vector passed to `main`.
-func ProcessCommandArgs(val ...string) attribute.KeyValue {
-	return ProcessCommandArgsKey.StringSlice(val)
-}
-
-// ProcessCommandLine returns an attribute KeyValue conforming to the
-// "process.command_line" semantic conventions. It represents the full command
-// used to launch the process as a single string representing the full command.
-// On Windows, can be set to the result of `GetCommandLineW`. Do not set this
-// if you have to assemble it just for monitoring; use `process.command_args`
-// instead.
-func ProcessCommandLine(val string) attribute.KeyValue {
-	return ProcessCommandLineKey.String(val)
-}
-
-// ProcessCreationTime returns an attribute KeyValue conforming to the
-// "process.creation.time" semantic conventions. It represents the date and
-// time the process was created, in ISO 8601 format.
-func ProcessCreationTime(val string) attribute.KeyValue {
-	return ProcessCreationTimeKey.String(val)
-}
-
-// ProcessExecutableName returns an attribute KeyValue conforming to the
-// "process.executable.name" semantic conventions. It represents the name of
-// the process executable. On Linux based systems, can be set to the `Name` in
-// `proc/[pid]/status`. On Windows, can be set to the base name of
-// `GetProcessImageFileNameW`.
-func ProcessExecutableName(val string) attribute.KeyValue {
-	return ProcessExecutableNameKey.String(val)
-}
-
-// ProcessExecutablePath returns an attribute KeyValue conforming to the
-// "process.executable.path" semantic conventions. It represents the full path
-// to the process executable. On Linux based systems, can be set to the target
-// of `proc/[pid]/exe`. On Windows, can be set to the result of
-// `GetProcessImageFileNameW`.
-func ProcessExecutablePath(val string) attribute.KeyValue {
-	return ProcessExecutablePathKey.String(val)
-}
-
-// ProcessExitCode returns an attribute KeyValue conforming to the
-// "process.exit.code" semantic conventions. It represents the exit code of the
-// process.
-func ProcessExitCode(val int) attribute.KeyValue {
-	return ProcessExitCodeKey.Int(val)
-}
-
-// ProcessExitTime returns an attribute KeyValue conforming to the
-// "process.exit.time" semantic conventions. It represents the date and time
-// the process exited, in ISO 8601 format.
-func ProcessExitTime(val string) attribute.KeyValue {
-	return ProcessExitTimeKey.String(val)
-}
-
-// ProcessGroupLeaderPID returns an attribute KeyValue conforming to the
-// "process.group_leader.pid" semantic conventions. It represents the PID of
-// the process's group leader. This is also the process group ID (PGID) of the
-// process.
-func ProcessGroupLeaderPID(val int) attribute.KeyValue {
-	return ProcessGroupLeaderPIDKey.Int(val)
-}
-
-// ProcessInteractive returns an attribute KeyValue conforming to the
-// "process.interactive" semantic conventions. It represents the whether the
-// process is connected to an interactive shell.
-func ProcessInteractive(val bool) attribute.KeyValue {
-	return ProcessInteractiveKey.Bool(val)
-}
-
-// ProcessOwner returns an attribute KeyValue conforming to the
-// "process.owner" semantic conventions. It represents the username of the user
-// that owns the process.
-func ProcessOwner(val string) attribute.KeyValue {
-	return ProcessOwnerKey.String(val)
-}
-
-// ProcessParentPID returns an attribute KeyValue conforming to the
-// "process.parent_pid" semantic conventions. It represents the parent Process
-// identifier (PPID).
-func ProcessParentPID(val int) attribute.KeyValue {
-	return ProcessParentPIDKey.Int(val)
-}
-
-// ProcessPID returns an attribute KeyValue conforming to the "process.pid"
-// semantic conventions. It represents the process identifier (PID).
-func ProcessPID(val int) attribute.KeyValue {
-	return ProcessPIDKey.Int(val)
-}
-
-// ProcessRealUserID returns an attribute KeyValue conforming to the
-// "process.real_user.id" semantic conventions. It represents the real user ID
-// (RUID) of the process.
-func ProcessRealUserID(val int) attribute.KeyValue {
-	return ProcessRealUserIDKey.Int(val)
-}
-
-// ProcessRealUserName returns an attribute KeyValue conforming to the
-// "process.real_user.name" semantic conventions. It represents the username of
-// the real user of the process.
-func ProcessRealUserName(val string) attribute.KeyValue {
-	return ProcessRealUserNameKey.String(val)
-}
-
-// ProcessRuntimeDescription returns an attribute KeyValue conforming to the
-// "process.runtime.description" semantic conventions. It represents an
-// additional description about the runtime of the process, for example a
-// specific vendor customization of the runtime environment.
-func ProcessRuntimeDescription(val string) attribute.KeyValue {
-	return ProcessRuntimeDescriptionKey.String(val)
-}
-
-// ProcessRuntimeName returns an attribute KeyValue conforming to the
-// "process.runtime.name" semantic conventions. It represents the name of the
-// runtime of this process. For compiled native binaries, this SHOULD be the
-// name of the compiler.
-func ProcessRuntimeName(val string) attribute.KeyValue {
-	return ProcessRuntimeNameKey.String(val)
-}
-
-// ProcessRuntimeVersion returns an attribute KeyValue conforming to the
-// "process.runtime.version" semantic conventions. It represents the version of
-// the runtime of this process, as returned by the runtime without
-// modification.
-func ProcessRuntimeVersion(val string) attribute.KeyValue {
-	return ProcessRuntimeVersionKey.String(val)
-}
-
-// ProcessSavedUserID returns an attribute KeyValue conforming to the
-// "process.saved_user.id" semantic conventions. It represents the saved user
-// ID (SUID) of the process.
-func ProcessSavedUserID(val int) attribute.KeyValue {
-	return ProcessSavedUserIDKey.Int(val)
-}
-
-// ProcessSavedUserName returns an attribute KeyValue conforming to the
-// "process.saved_user.name" semantic conventions. It represents the username
-// of the saved user.
-func ProcessSavedUserName(val string) attribute.KeyValue {
-	return ProcessSavedUserNameKey.String(val)
-}
-
-// ProcessSessionLeaderPID returns an attribute KeyValue conforming to the
-// "process.session_leader.pid" semantic conventions. It represents the PID of
-// the process's session leader. This is also the session ID (SID) of the
-// process.
-func ProcessSessionLeaderPID(val int) attribute.KeyValue {
-	return ProcessSessionLeaderPIDKey.Int(val)
-}
-
-// ProcessUserID returns an attribute KeyValue conforming to the
-// "process.user.id" semantic conventions. It represents the effective user ID
-// (EUID) of the process.
-func ProcessUserID(val int) attribute.KeyValue {
-	return ProcessUserIDKey.Int(val)
-}
-
-// ProcessUserName returns an attribute KeyValue conforming to the
-// "process.user.name" semantic conventions. It represents the username of the
-// effective user of the process.
-func ProcessUserName(val string) attribute.KeyValue {
-	return ProcessUserNameKey.String(val)
-}
-
-// ProcessVpid returns an attribute KeyValue conforming to the
-// "process.vpid" semantic conventions. It represents the virtual process
-// identifier.
-func ProcessVpid(val int) attribute.KeyValue {
-	return ProcessVpidKey.Int(val)
-}
-
-// Attributes for process CPU
-const (
-	// ProcessCPUStateKey is the attribute Key conforming to the
-	// "process.cpu.state" semantic conventions. It represents the CPU state of
-	// the process.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	ProcessCPUStateKey = attribute.Key("process.cpu.state")
-)
-
-var (
-	// system
-	ProcessCPUStateSystem = ProcessCPUStateKey.String("system")
-	// user
-	ProcessCPUStateUser = ProcessCPUStateKey.String("user")
-	// wait
-	ProcessCPUStateWait = ProcessCPUStateKey.String("wait")
-)
-
-// Attributes for remote procedure calls.
-const (
-	// RPCConnectRPCErrorCodeKey is the attribute Key conforming to the
-	// "rpc.connect_rpc.error_code" semantic conventions. It represents the
-	// [error codes](https://connect.build/docs/protocol/#error-codes) of the
-	// Connect request. Error codes are always string values.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCConnectRPCErrorCodeKey = attribute.Key("rpc.connect_rpc.error_code")
-
-	// RPCGRPCStatusCodeKey is the attribute Key conforming to the
-	// "rpc.grpc.status_code" semantic conventions. It represents the [numeric
-	// status
-	// code](https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md) of
-	// the gRPC request.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
-
-	// RPCJsonrpcErrorCodeKey is the attribute Key conforming to the
-	// "rpc.jsonrpc.error_code" semantic conventions. It represents the
-	// `error.code` property of response if it is an error response.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: -32700, 100
-	RPCJsonrpcErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code")
-
-	// RPCJsonrpcErrorMessageKey is the attribute Key conforming to the
-	// "rpc.jsonrpc.error_message" semantic conventions. It represents the
-	// `error.message` property of response if it is an error response.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Parse error', 'User already exists'
-	RPCJsonrpcErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message")
-
-	// RPCJsonrpcRequestIDKey is the attribute Key conforming to the
-	// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id`
-	// property of request or response. Since protocol allows id to be int,
-	// string, `null` or missing (for notifications), value is expected to be
-	// cast to string for simplicity. Use empty string in case of `null` value.
-	// Omit entirely if this is a notification.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '10', 'request-7', ''
-	RPCJsonrpcRequestIDKey = attribute.Key("rpc.jsonrpc.request_id")
-
-	// RPCJsonrpcVersionKey is the attribute Key conforming to the
-	// "rpc.jsonrpc.version" semantic conventions. It represents the protocol
-	// version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0
-	// doesn't specify this, the value can be omitted.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2.0', '1.0'
-	RPCJsonrpcVersionKey = attribute.Key("rpc.jsonrpc.version")
-
-	// RPCMessageCompressedSizeKey is the attribute Key conforming to the
-	// "rpc.message.compressed_size" semantic conventions. It represents the
-	// compressed size of the message in bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCMessageCompressedSizeKey = attribute.Key("rpc.message.compressed_size")
-
-	// RPCMessageIDKey is the attribute Key conforming to the "rpc.message.id"
-	// semantic conventions. It represents the mUST be calculated as two
-	// different counters starting from `1` one for sent messages and one for
-	// received message.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Note: This way we guarantee that the values will be consistent between
-	// different implementations.
-	RPCMessageIDKey = attribute.Key("rpc.message.id")
-
-	// RPCMessageTypeKey is the attribute Key conforming to the
-	// "rpc.message.type" semantic conventions. It represents the whether this
-	// is a received or sent message.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCMessageTypeKey = attribute.Key("rpc.message.type")
-
-	// RPCMessageUncompressedSizeKey is the attribute Key conforming to the
-	// "rpc.message.uncompressed_size" semantic conventions. It represents the
-	// uncompressed size of the message in bytes.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCMessageUncompressedSizeKey = attribute.Key("rpc.message.uncompressed_size")
-
-	// RPCMethodKey is the attribute Key conforming to the "rpc.method"
-	// semantic conventions. It represents the name of the (logical) method
-	// being called, must be equal to the $method part in the span name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'exampleMethod'
-	// Note: This is the logical name of the method from the RPC interface
-	// perspective, which can be different from the name of any implementing
-	// method/function. The `code.function` attribute may be used to store the
-	// latter (e.g., method actually executing the call on the server side, RPC
-	// client stub method on the client side).
-	RPCMethodKey = attribute.Key("rpc.method")
-
-	// RPCServiceKey is the attribute Key conforming to the "rpc.service"
-	// semantic conventions. It represents the full (logical) name of the
-	// service being called, including its package name, if applicable.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'myservice.EchoService'
-	// Note: This is the logical name of the service from the RPC interface
-	// perspective, which can be different from the name of any implementing
-	// class. The `code.namespace` attribute may be used to store the latter
-	// (despite the attribute name, it may include a class name; e.g., class
-	// with method actually executing the call on the server side, RPC client
-	// stub class on the client side).
-	RPCServiceKey = attribute.Key("rpc.service")
-
-	// RPCSystemKey is the attribute Key conforming to the "rpc.system"
-	// semantic conventions. It represents a string identifying the remoting
-	// system. See below for a list of well-known identifiers.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	RPCSystemKey = attribute.Key("rpc.system")
-)
-
-var (
-	// cancelled
-	RPCConnectRPCErrorCodeCancelled = RPCConnectRPCErrorCodeKey.String("cancelled")
-	// unknown
-	RPCConnectRPCErrorCodeUnknown = RPCConnectRPCErrorCodeKey.String("unknown")
-	// invalid_argument
-	RPCConnectRPCErrorCodeInvalidArgument = RPCConnectRPCErrorCodeKey.String("invalid_argument")
-	// deadline_exceeded
-	RPCConnectRPCErrorCodeDeadlineExceeded = RPCConnectRPCErrorCodeKey.String("deadline_exceeded")
-	// not_found
-	RPCConnectRPCErrorCodeNotFound = RPCConnectRPCErrorCodeKey.String("not_found")
-	// already_exists
-	RPCConnectRPCErrorCodeAlreadyExists = RPCConnectRPCErrorCodeKey.String("already_exists")
-	// permission_denied
-	RPCConnectRPCErrorCodePermissionDenied = RPCConnectRPCErrorCodeKey.String("permission_denied")
-	// resource_exhausted
-	RPCConnectRPCErrorCodeResourceExhausted = RPCConnectRPCErrorCodeKey.String("resource_exhausted")
-	// failed_precondition
-	RPCConnectRPCErrorCodeFailedPrecondition = RPCConnectRPCErrorCodeKey.String("failed_precondition")
-	// aborted
-	RPCConnectRPCErrorCodeAborted = RPCConnectRPCErrorCodeKey.String("aborted")
-	// out_of_range
-	RPCConnectRPCErrorCodeOutOfRange = RPCConnectRPCErrorCodeKey.String("out_of_range")
-	// unimplemented
-	RPCConnectRPCErrorCodeUnimplemented = RPCConnectRPCErrorCodeKey.String("unimplemented")
-	// internal
-	RPCConnectRPCErrorCodeInternal = RPCConnectRPCErrorCodeKey.String("internal")
-	// unavailable
-	RPCConnectRPCErrorCodeUnavailable = RPCConnectRPCErrorCodeKey.String("unavailable")
-	// data_loss
-	RPCConnectRPCErrorCodeDataLoss = RPCConnectRPCErrorCodeKey.String("data_loss")
-	// unauthenticated
-	RPCConnectRPCErrorCodeUnauthenticated = RPCConnectRPCErrorCodeKey.String("unauthenticated")
-)
-
-var (
-	// OK
-	RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0)
-	// CANCELLED
-	RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1)
-	// UNKNOWN
-	RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2)
-	// INVALID_ARGUMENT
-	RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3)
-	// DEADLINE_EXCEEDED
-	RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4)
-	// NOT_FOUND
-	RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5)
-	// ALREADY_EXISTS
-	RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6)
-	// PERMISSION_DENIED
-	RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7)
-	// RESOURCE_EXHAUSTED
-	RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8)
-	// FAILED_PRECONDITION
-	RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9)
-	// ABORTED
-	RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10)
-	// OUT_OF_RANGE
-	RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11)
-	// UNIMPLEMENTED
-	RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12)
-	// INTERNAL
-	RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13)
-	// UNAVAILABLE
-	RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14)
-	// DATA_LOSS
-	RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15)
-	// UNAUTHENTICATED
-	RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16)
-)
-
-var (
-	// sent
-	RPCMessageTypeSent = RPCMessageTypeKey.String("SENT")
-	// received
-	RPCMessageTypeReceived = RPCMessageTypeKey.String("RECEIVED")
-)
-
-var (
-	// gRPC
-	RPCSystemGRPC = RPCSystemKey.String("grpc")
-	// Java RMI
-	RPCSystemJavaRmi = RPCSystemKey.String("java_rmi")
-	// .NET WCF
-	RPCSystemDotnetWcf = RPCSystemKey.String("dotnet_wcf")
-	// Apache Dubbo
-	RPCSystemApacheDubbo = RPCSystemKey.String("apache_dubbo")
-	// Connect RPC
-	RPCSystemConnectRPC = RPCSystemKey.String("connect_rpc")
-)
-
-// RPCJsonrpcErrorCode returns an attribute KeyValue conforming to the
-// "rpc.jsonrpc.error_code" semantic conventions. It represents the
-// `error.code` property of response if it is an error response.
-func RPCJsonrpcErrorCode(val int) attribute.KeyValue {
-	return RPCJsonrpcErrorCodeKey.Int(val)
-}
-
-// RPCJsonrpcErrorMessage returns an attribute KeyValue conforming to the
-// "rpc.jsonrpc.error_message" semantic conventions. It represents the
-// `error.message` property of response if it is an error response.
-func RPCJsonrpcErrorMessage(val string) attribute.KeyValue {
-	return RPCJsonrpcErrorMessageKey.String(val)
-}
-
-// RPCJsonrpcRequestID returns an attribute KeyValue conforming to the
-// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id`
-// property of request or response. Since protocol allows id to be int, string,
-// `null` or missing (for notifications), value is expected to be cast to
-// string for simplicity. Use empty string in case of `null` value. Omit
-// entirely if this is a notification.
-func RPCJsonrpcRequestID(val string) attribute.KeyValue {
-	return RPCJsonrpcRequestIDKey.String(val)
-}
-
-// RPCJsonrpcVersion returns an attribute KeyValue conforming to the
-// "rpc.jsonrpc.version" semantic conventions. It represents the protocol
-// version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0
-// doesn't specify this, the value can be omitted.
-func RPCJsonrpcVersion(val string) attribute.KeyValue {
-	return RPCJsonrpcVersionKey.String(val)
-}
-
-// RPCMessageCompressedSize returns an attribute KeyValue conforming to the
-// "rpc.message.compressed_size" semantic conventions. It represents the
-// compressed size of the message in bytes.
-func RPCMessageCompressedSize(val int) attribute.KeyValue {
-	return RPCMessageCompressedSizeKey.Int(val)
-}
-
-// RPCMessageID returns an attribute KeyValue conforming to the
-// "rpc.message.id" semantic conventions. It represents the mUST be calculated
-// as two different counters starting from `1` one for sent messages and one
-// for received message.
-func RPCMessageID(val int) attribute.KeyValue {
-	return RPCMessageIDKey.Int(val)
-}
-
-// RPCMessageUncompressedSize returns an attribute KeyValue conforming to
-// the "rpc.message.uncompressed_size" semantic conventions. It represents the
-// uncompressed size of the message in bytes.
-func RPCMessageUncompressedSize(val int) attribute.KeyValue {
-	return RPCMessageUncompressedSizeKey.Int(val)
-}
-
-// RPCMethod returns an attribute KeyValue conforming to the "rpc.method"
-// semantic conventions. It represents the name of the (logical) method being
-// called, must be equal to the $method part in the span name.
-func RPCMethod(val string) attribute.KeyValue {
-	return RPCMethodKey.String(val)
-}
-
-// RPCService returns an attribute KeyValue conforming to the "rpc.service"
-// semantic conventions. It represents the full (logical) name of the service
-// being called, including its package name, if applicable.
-func RPCService(val string) attribute.KeyValue {
-	return RPCServiceKey.String(val)
-}
-
-// These attributes may be used to describe the server in a connection-based
-// network interaction where there is one side that initiates the connection
-// (the client is the side that initiates the connection). This covers all TCP
-// network interactions since TCP is connection-based and one side initiates
-// the connection (an exception is made for peer-to-peer communication over TCP
-// where the "user-facing" surface of the protocol / API doesn't expose a clear
-// notion of client and server). This also covers UDP network interactions
-// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS.
-const (
-	// ServerAddressKey is the attribute Key conforming to the "server.address"
-	// semantic conventions. It represents the server domain name if available
-	// without reverse DNS lookup; otherwise, IP address or Unix domain socket
-	// name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'example.com', '10.1.2.80', '/tmp/my.sock'
-	// Note: When observed from the client side, and when communicating through
-	// an intermediary, `server.address` SHOULD represent the server address
-	// behind any intermediaries, for example proxies, if it's available.
-	ServerAddressKey = attribute.Key("server.address")
-
-	// ServerPortKey is the attribute Key conforming to the "server.port"
-	// semantic conventions. It represents the server port number.
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 80, 8080, 443
-	// Note: When observed from the client side, and when communicating through
-	// an intermediary, `server.port` SHOULD represent the server port behind
-	// any intermediaries, for example proxies, if it's available.
-	ServerPortKey = attribute.Key("server.port")
-)
-
-// ServerAddress returns an attribute KeyValue conforming to the
-// "server.address" semantic conventions. It represents the server domain name
-// if available without reverse DNS lookup; otherwise, IP address or Unix
-// domain socket name.
-func ServerAddress(val string) attribute.KeyValue {
-	return ServerAddressKey.String(val)
-}
-
-// ServerPort returns an attribute KeyValue conforming to the "server.port"
-// semantic conventions. It represents the server port number.
-func ServerPort(val int) attribute.KeyValue {
-	return ServerPortKey.Int(val)
-}
-
-// A service instance.
-const (
-	// ServiceInstanceIDKey is the attribute Key conforming to the
-	// "service.instance.id" semantic conventions. It represents the string ID
-	// of the service instance.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '627cc493-f310-47de-96bd-71410b7dec09'
-	// Note: MUST be unique for each instance of the same
-	// `service.namespace,service.name` pair (in other words
-	// `service.namespace,service.name,service.instance.id` triplet MUST be
-	// globally unique). The ID helps to
-	// distinguish instances of the same service that exist at the same time
-	// (e.g. instances of a horizontally scaled
-	// service).
-	//
-	// Implementations, such as SDKs, are recommended to generate a random
-	// Version 1 or Version 4 [RFC
-	// 4122](https://www.ietf.org/rfc/rfc4122.txt) UUID, but are free to use an
-	// inherent unique ID as the source of
-	// this value if stability is desirable. In that case, the ID SHOULD be
-	// used as source of a UUID Version 5 and
-	// SHOULD use the following UUID as the namespace:
-	// `4d63009a-8d0f-11ee-aad7-4c796ed8e320`.
-	//
-	// UUIDs are typically recommended, as only an opaque value for the
-	// purposes of identifying a service instance is
-	// needed. Similar to what can be seen in the man page for the
-	// [`/etc/machine-id`](https://www.freedesktop.org/software/systemd/man/machine-id.html)
-	// file, the underlying
-	// data, such as pod name and namespace should be treated as confidential,
-	// being the user's choice to expose it
-	// or not via another resource attribute.
-	//
-	// For applications running behind an application server (like unicorn), we
-	// do not recommend using one identifier
-	// for all processes participating in the application. Instead, it's
-	// recommended each division (e.g. a worker
-	// thread in unicorn) to have its own instance.id.
-	//
-	// It's not recommended for a Collector to set `service.instance.id` if it
-	// can't unambiguously determine the
-	// service instance that is generating that telemetry. For instance,
-	// creating an UUID based on `pod.name` will
-	// likely be wrong, as the Collector might not know from which container
-	// within that pod the telemetry originated.
-	// However, Collectors can set the `service.instance.id` if they can
-	// unambiguously determine the service instance
-	// for that telemetry. This is typically the case for scraping receivers,
-	// as they know the target address and
-	// port.
-	ServiceInstanceIDKey = attribute.Key("service.instance.id")
-
-	// ServiceNameKey is the attribute Key conforming to the "service.name"
-	// semantic conventions. It represents the logical name of the service.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'shoppingcart'
-	// Note: MUST be the same for all instances of horizontally scaled
-	// services. If the value was not specified, SDKs MUST fallback to
-	// `unknown_service:` concatenated with
-	// [`process.executable.name`](process.md), e.g. `unknown_service:bash`. If
-	// `process.executable.name` is not available, the value MUST be set to
-	// `unknown_service`.
-	ServiceNameKey = attribute.Key("service.name")
-
-	// ServiceNamespaceKey is the attribute Key conforming to the
-	// "service.namespace" semantic conventions. It represents a namespace for
-	// `service.name`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Shop'
-	// Note: A string value having a meaning that helps to distinguish a group
-	// of services, for example the team name that owns a group of services.
-	// `service.name` is expected to be unique within the same namespace. If
-	// `service.namespace` is not specified in the Resource then `service.name`
-	// is expected to be unique for all services that have no explicit
-	// namespace defined (so the empty/unspecified namespace is simply one more
-	// valid namespace). Zero-length namespace string is assumed equal to
-	// unspecified namespace.
-	ServiceNamespaceKey = attribute.Key("service.namespace")
-
-	// ServiceVersionKey is the attribute Key conforming to the
-	// "service.version" semantic conventions. It represents the version string
-	// of the service API or implementation. The format is not defined by these
-	// conventions.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '2.0.0', 'a01dbef8a'
-	ServiceVersionKey = attribute.Key("service.version")
-)
-
-// ServiceInstanceID returns an attribute KeyValue conforming to the
-// "service.instance.id" semantic conventions. It represents the string ID of
-// the service instance.
-func ServiceInstanceID(val string) attribute.KeyValue {
-	return ServiceInstanceIDKey.String(val)
-}
-
-// ServiceName returns an attribute KeyValue conforming to the
-// "service.name" semantic conventions. It represents the logical name of the
-// service.
-func ServiceName(val string) attribute.KeyValue {
-	return ServiceNameKey.String(val)
-}
-
-// ServiceNamespace returns an attribute KeyValue conforming to the
-// "service.namespace" semantic conventions. It represents a namespace for
-// `service.name`.
-func ServiceNamespace(val string) attribute.KeyValue {
-	return ServiceNamespaceKey.String(val)
-}
-
-// ServiceVersion returns an attribute KeyValue conforming to the
-// "service.version" semantic conventions. It represents the version string of
-// the service API or implementation. The format is not defined by these
-// conventions.
-func ServiceVersion(val string) attribute.KeyValue {
-	return ServiceVersionKey.String(val)
-}
-
-// Session is defined as the period of time encompassing all activities
-// performed by the application and the actions executed by the end user.
-// Consequently, a Session is represented as a collection of Logs, Events, and
-// Spans emitted by the Client Application throughout the Session's duration.
-// Each Session is assigned a unique identifier, which is included as an
-// attribute in the Logs, Events, and Spans generated during the Session's
-// lifecycle.
-// When a session reaches end of life, typically due to user inactivity or
-// session timeout, a new session identifier will be assigned. The previous
-// session identifier may be provided by the instrumentation so that telemetry
-// backends can link the two sessions.
-const (
-	// SessionIDKey is the attribute Key conforming to the "session.id"
-	// semantic conventions. It represents a unique id to identify a session.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '00112233-4455-6677-8899-aabbccddeeff'
-	SessionIDKey = attribute.Key("session.id")
-
-	// SessionPreviousIDKey is the attribute Key conforming to the
-	// "session.previous_id" semantic conventions. It represents the previous
-	// `session.id` for this user, when known.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '00112233-4455-6677-8899-aabbccddeeff'
-	SessionPreviousIDKey = attribute.Key("session.previous_id")
-)
-
-// SessionID returns an attribute KeyValue conforming to the "session.id"
-// semantic conventions. It represents a unique id to identify a session.
-func SessionID(val string) attribute.KeyValue {
-	return SessionIDKey.String(val)
-}
-
-// SessionPreviousID returns an attribute KeyValue conforming to the
-// "session.previous_id" semantic conventions. It represents the previous
-// `session.id` for this user, when known.
-func SessionPreviousID(val string) attribute.KeyValue {
-	return SessionPreviousIDKey.String(val)
-}
-
-// SignalR attributes
-const (
-	// SignalrConnectionStatusKey is the attribute Key conforming to the
-	// "signalr.connection.status" semantic conventions. It represents the
-	// signalR HTTP connection closure status.
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'app_shutdown', 'timeout'
-	SignalrConnectionStatusKey = attribute.Key("signalr.connection.status")
-
-	// SignalrTransportKey is the attribute Key conforming to the
-	// "signalr.transport" semantic conventions. It represents the [SignalR
-	// transport
-	// type](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md)
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'web_sockets', 'long_polling'
-	SignalrTransportKey = attribute.Key("signalr.transport")
-)
-
-var (
-	// The connection was closed normally
-	SignalrConnectionStatusNormalClosure = SignalrConnectionStatusKey.String("normal_closure")
-	// The connection was closed due to a timeout
-	SignalrConnectionStatusTimeout = SignalrConnectionStatusKey.String("timeout")
-	// The connection was closed because the app is shutting down
-	SignalrConnectionStatusAppShutdown = SignalrConnectionStatusKey.String("app_shutdown")
-)
-
-var (
-	// ServerSentEvents protocol
-	SignalrTransportServerSentEvents = SignalrTransportKey.String("server_sent_events")
-	// LongPolling protocol
-	SignalrTransportLongPolling = SignalrTransportKey.String("long_polling")
-	// WebSockets protocol
-	SignalrTransportWebSockets = SignalrTransportKey.String("web_sockets")
-)
-
-// These attributes may be used to describe the sender of a network
-// exchange/packet. These should be used when there is no client/server
-// relationship between the two sides, or when that relationship is unknown.
-// This covers low-level network interactions (e.g. packet tracing) where you
-// don't know if there was a connection or which side initiated it. This also
-// covers unidirectional UDP flows and peer-to-peer communication where the
-// "user-facing" surface of the protocol / API doesn't expose a clear notion of
-// client and server.
-const (
-	// SourceAddressKey is the attribute Key conforming to the "source.address"
-	// semantic conventions. It represents the source address - domain name if
-	// available without reverse DNS lookup; otherwise, IP address or Unix
-	// domain socket name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'source.example.com', '10.1.2.80', '/tmp/my.sock'
-	// Note: When observed from the destination side, and when communicating
-	// through an intermediary, `source.address` SHOULD represent the source
-	// address behind any intermediaries, for example proxies, if it's
-	// available.
-	SourceAddressKey = attribute.Key("source.address")
-
-	// SourcePortKey is the attribute Key conforming to the "source.port"
-	// semantic conventions. It represents the source port number
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 3389, 2888
-	SourcePortKey = attribute.Key("source.port")
-)
-
-// SourceAddress returns an attribute KeyValue conforming to the
-// "source.address" semantic conventions. It represents the source address -
-// domain name if available without reverse DNS lookup; otherwise, IP address
-// or Unix domain socket name.
-func SourceAddress(val string) attribute.KeyValue {
-	return SourceAddressKey.String(val)
-}
-
-// SourcePort returns an attribute KeyValue conforming to the "source.port"
-// semantic conventions. It represents the source port number
-func SourcePort(val int) attribute.KeyValue {
-	return SourcePortKey.Int(val)
-}
-
-// Describes System attributes
-const (
-	// SystemDeviceKey is the attribute Key conforming to the "system.device"
-	// semantic conventions. It represents the device identifier
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '(identifier)'
-	SystemDeviceKey = attribute.Key("system.device")
-)
-
-// SystemDevice returns an attribute KeyValue conforming to the
-// "system.device" semantic conventions. It represents the device identifier
-func SystemDevice(val string) attribute.KeyValue {
-	return SystemDeviceKey.String(val)
-}
-
-// Describes System CPU attributes
-const (
-	// SystemCPULogicalNumberKey is the attribute Key conforming to the
-	// "system.cpu.logical_number" semantic conventions. It represents the
-	// logical CPU number [0..n-1]
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 1
-	SystemCPULogicalNumberKey = attribute.Key("system.cpu.logical_number")
-
-	// SystemCPUStateKey is the attribute Key conforming to the
-	// "system.cpu.state" semantic conventions. It represents the state of the
-	// CPU
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'idle', 'interrupt'
-	SystemCPUStateKey = attribute.Key("system.cpu.state")
-)
-
-var (
-	// user
-	SystemCPUStateUser = SystemCPUStateKey.String("user")
-	// system
-	SystemCPUStateSystem = SystemCPUStateKey.String("system")
-	// nice
-	SystemCPUStateNice = SystemCPUStateKey.String("nice")
-	// idle
-	SystemCPUStateIdle = SystemCPUStateKey.String("idle")
-	// iowait
-	SystemCPUStateIowait = SystemCPUStateKey.String("iowait")
-	// interrupt
-	SystemCPUStateInterrupt = SystemCPUStateKey.String("interrupt")
-	// steal
-	SystemCPUStateSteal = SystemCPUStateKey.String("steal")
-)
-
-// SystemCPULogicalNumber returns an attribute KeyValue conforming to the
-// "system.cpu.logical_number" semantic conventions. It represents the logical
-// CPU number [0..n-1]
-func SystemCPULogicalNumber(val int) attribute.KeyValue {
-	return SystemCPULogicalNumberKey.Int(val)
-}
-
-// Describes System Memory attributes
-const (
-	// SystemMemoryStateKey is the attribute Key conforming to the
-	// "system.memory.state" semantic conventions. It represents the memory
-	// state
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'free', 'cached'
-	SystemMemoryStateKey = attribute.Key("system.memory.state")
-)
-
-var (
-	// used
-	SystemMemoryStateUsed = SystemMemoryStateKey.String("used")
-	// free
-	SystemMemoryStateFree = SystemMemoryStateKey.String("free")
-	// shared
-	SystemMemoryStateShared = SystemMemoryStateKey.String("shared")
-	// buffers
-	SystemMemoryStateBuffers = SystemMemoryStateKey.String("buffers")
-	// cached
-	SystemMemoryStateCached = SystemMemoryStateKey.String("cached")
-)
-
-// Describes System Memory Paging attributes
-const (
-	// SystemPagingDirectionKey is the attribute Key conforming to the
-	// "system.paging.direction" semantic conventions. It represents the paging
-	// access direction
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'in'
-	SystemPagingDirectionKey = attribute.Key("system.paging.direction")
-
-	// SystemPagingStateKey is the attribute Key conforming to the
-	// "system.paging.state" semantic conventions. It represents the memory
-	// paging state
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'free'
-	SystemPagingStateKey = attribute.Key("system.paging.state")
-
-	// SystemPagingTypeKey is the attribute Key conforming to the
-	// "system.paging.type" semantic conventions. It represents the memory
-	// paging type
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'minor'
-	SystemPagingTypeKey = attribute.Key("system.paging.type")
-)
-
-var (
-	// in
-	SystemPagingDirectionIn = SystemPagingDirectionKey.String("in")
-	// out
-	SystemPagingDirectionOut = SystemPagingDirectionKey.String("out")
-)
-
-var (
-	// used
-	SystemPagingStateUsed = SystemPagingStateKey.String("used")
-	// free
-	SystemPagingStateFree = SystemPagingStateKey.String("free")
-)
-
-var (
-	// major
-	SystemPagingTypeMajor = SystemPagingTypeKey.String("major")
-	// minor
-	SystemPagingTypeMinor = SystemPagingTypeKey.String("minor")
-)
-
-// Describes Filesystem attributes
-const (
-	// SystemFilesystemModeKey is the attribute Key conforming to the
-	// "system.filesystem.mode" semantic conventions. It represents the
-	// filesystem mode
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'rw, ro'
-	SystemFilesystemModeKey = attribute.Key("system.filesystem.mode")
-
-	// SystemFilesystemMountpointKey is the attribute Key conforming to the
-	// "system.filesystem.mountpoint" semantic conventions. It represents the
-	// filesystem mount path
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/mnt/data'
-	SystemFilesystemMountpointKey = attribute.Key("system.filesystem.mountpoint")
-
-	// SystemFilesystemStateKey is the attribute Key conforming to the
-	// "system.filesystem.state" semantic conventions. It represents the
-	// filesystem state
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'used'
-	SystemFilesystemStateKey = attribute.Key("system.filesystem.state")
-
-	// SystemFilesystemTypeKey is the attribute Key conforming to the
-	// "system.filesystem.type" semantic conventions. It represents the
-	// filesystem type
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'ext4'
-	SystemFilesystemTypeKey = attribute.Key("system.filesystem.type")
-)
-
-var (
-	// used
-	SystemFilesystemStateUsed = SystemFilesystemStateKey.String("used")
-	// free
-	SystemFilesystemStateFree = SystemFilesystemStateKey.String("free")
-	// reserved
-	SystemFilesystemStateReserved = SystemFilesystemStateKey.String("reserved")
-)
-
-var (
-	// fat32
-	SystemFilesystemTypeFat32 = SystemFilesystemTypeKey.String("fat32")
-	// exfat
-	SystemFilesystemTypeExfat = SystemFilesystemTypeKey.String("exfat")
-	// ntfs
-	SystemFilesystemTypeNtfs = SystemFilesystemTypeKey.String("ntfs")
-	// refs
-	SystemFilesystemTypeRefs = SystemFilesystemTypeKey.String("refs")
-	// hfsplus
-	SystemFilesystemTypeHfsplus = SystemFilesystemTypeKey.String("hfsplus")
-	// ext4
-	SystemFilesystemTypeExt4 = SystemFilesystemTypeKey.String("ext4")
-)
-
-// SystemFilesystemMode returns an attribute KeyValue conforming to the
-// "system.filesystem.mode" semantic conventions. It represents the filesystem
-// mode
-func SystemFilesystemMode(val string) attribute.KeyValue {
-	return SystemFilesystemModeKey.String(val)
-}
-
-// SystemFilesystemMountpoint returns an attribute KeyValue conforming to
-// the "system.filesystem.mountpoint" semantic conventions. It represents the
-// filesystem mount path
-func SystemFilesystemMountpoint(val string) attribute.KeyValue {
-	return SystemFilesystemMountpointKey.String(val)
-}
-
-// Describes Network attributes
-const (
-	// SystemNetworkStateKey is the attribute Key conforming to the
-	// "system.network.state" semantic conventions. It represents a stateless
-	// protocol MUST NOT set this attribute
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'close_wait'
-	SystemNetworkStateKey = attribute.Key("system.network.state")
-)
-
-var (
-	// close
-	SystemNetworkStateClose = SystemNetworkStateKey.String("close")
-	// close_wait
-	SystemNetworkStateCloseWait = SystemNetworkStateKey.String("close_wait")
-	// closing
-	SystemNetworkStateClosing = SystemNetworkStateKey.String("closing")
-	// delete
-	SystemNetworkStateDelete = SystemNetworkStateKey.String("delete")
-	// established
-	SystemNetworkStateEstablished = SystemNetworkStateKey.String("established")
-	// fin_wait_1
-	SystemNetworkStateFinWait1 = SystemNetworkStateKey.String("fin_wait_1")
-	// fin_wait_2
-	SystemNetworkStateFinWait2 = SystemNetworkStateKey.String("fin_wait_2")
-	// last_ack
-	SystemNetworkStateLastAck = SystemNetworkStateKey.String("last_ack")
-	// listen
-	SystemNetworkStateListen = SystemNetworkStateKey.String("listen")
-	// syn_recv
-	SystemNetworkStateSynRecv = SystemNetworkStateKey.String("syn_recv")
-	// syn_sent
-	SystemNetworkStateSynSent = SystemNetworkStateKey.String("syn_sent")
-	// time_wait
-	SystemNetworkStateTimeWait = SystemNetworkStateKey.String("time_wait")
-)
-
-// Describes System Process attributes
-const (
-	// SystemProcessStatusKey is the attribute Key conforming to the
-	// "system.process.status" semantic conventions. It represents the process
-	// state, e.g., [Linux Process State
-	// Codes](https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES)
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'running'
-	SystemProcessStatusKey = attribute.Key("system.process.status")
-)
-
-var (
-	// running
-	SystemProcessStatusRunning = SystemProcessStatusKey.String("running")
-	// sleeping
-	SystemProcessStatusSleeping = SystemProcessStatusKey.String("sleeping")
-	// stopped
-	SystemProcessStatusStopped = SystemProcessStatusKey.String("stopped")
-	// defunct
-	SystemProcessStatusDefunct = SystemProcessStatusKey.String("defunct")
-)
-
-// Attributes for telemetry SDK.
-const (
-	// TelemetrySDKLanguageKey is the attribute Key conforming to the
-	// "telemetry.sdk.language" semantic conventions. It represents the
-	// language of the telemetry SDK.
-	//
-	// Type: Enum
-	// RequirementLevel: Required
-	// Stability: stable
-	TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language")
-
-	// TelemetrySDKNameKey is the attribute Key conforming to the
-	// "telemetry.sdk.name" semantic conventions. It represents the name of the
-	// telemetry SDK as defined above.
-	//
-	// Type: string
-	// RequirementLevel: Required
-	// Stability: stable
-	// Examples: 'opentelemetry'
-	// Note: The OpenTelemetry SDK MUST set the `telemetry.sdk.name` attribute
-	// to `opentelemetry`.
-	// If another SDK, like a fork or a vendor-provided implementation, is
-	// used, this SDK MUST set the
-	// `telemetry.sdk.name` attribute to the fully-qualified class or module
-	// name of this SDK's main entry point
-	// or another suitable identifier depending on the language.
-	// The identifier `opentelemetry` is reserved and MUST NOT be used in this
-	// case.
-	// All custom identifiers SHOULD be stable across different versions of an
-	// implementation.
-	TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name")
-
-	// TelemetrySDKVersionKey is the attribute Key conforming to the
-	// "telemetry.sdk.version" semantic conventions. It represents the version
-	// string of the telemetry SDK.
-	//
-	// Type: string
-	// RequirementLevel: Required
-	// Stability: stable
-	// Examples: '1.2.3'
-	TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version")
-
-	// TelemetryDistroNameKey is the attribute Key conforming to the
-	// "telemetry.distro.name" semantic conventions. It represents the name of
-	// the auto instrumentation agent or distribution, if used.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'parts-unlimited-java'
-	// Note: Official auto instrumentation agents and distributions SHOULD set
-	// the `telemetry.distro.name` attribute to
-	// a string starting with `opentelemetry-`, e.g.
-	// `opentelemetry-java-instrumentation`.
-	TelemetryDistroNameKey = attribute.Key("telemetry.distro.name")
-
-	// TelemetryDistroVersionKey is the attribute Key conforming to the
-	// "telemetry.distro.version" semantic conventions. It represents the
-	// version string of the auto instrumentation agent or distribution, if
-	// used.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1.2.3'
-	TelemetryDistroVersionKey = attribute.Key("telemetry.distro.version")
-)
-
-var (
-	// cpp
-	TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp")
-	// dotnet
-	TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet")
-	// erlang
-	TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang")
-	// go
-	TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go")
-	// java
-	TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java")
-	// nodejs
-	TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs")
-	// php
-	TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php")
-	// python
-	TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python")
-	// ruby
-	TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby")
-	// rust
-	TelemetrySDKLanguageRust = TelemetrySDKLanguageKey.String("rust")
-	// swift
-	TelemetrySDKLanguageSwift = TelemetrySDKLanguageKey.String("swift")
-	// webjs
-	TelemetrySDKLanguageWebjs = TelemetrySDKLanguageKey.String("webjs")
-)
-
-// TelemetrySDKName returns an attribute KeyValue conforming to the
-// "telemetry.sdk.name" semantic conventions. It represents the name of the
-// telemetry SDK as defined above.
-func TelemetrySDKName(val string) attribute.KeyValue {
-	return TelemetrySDKNameKey.String(val)
-}
-
-// TelemetrySDKVersion returns an attribute KeyValue conforming to the
-// "telemetry.sdk.version" semantic conventions. It represents the version
-// string of the telemetry SDK.
-func TelemetrySDKVersion(val string) attribute.KeyValue {
-	return TelemetrySDKVersionKey.String(val)
-}
-
-// TelemetryDistroName returns an attribute KeyValue conforming to the
-// "telemetry.distro.name" semantic conventions. It represents the name of the
-// auto instrumentation agent or distribution, if used.
-func TelemetryDistroName(val string) attribute.KeyValue {
-	return TelemetryDistroNameKey.String(val)
-}
-
-// TelemetryDistroVersion returns an attribute KeyValue conforming to the
-// "telemetry.distro.version" semantic conventions. It represents the version
-// string of the auto instrumentation agent or distribution, if used.
-func TelemetryDistroVersion(val string) attribute.KeyValue {
-	return TelemetryDistroVersionKey.String(val)
-}
-
-// These attributes may be used for any operation to store information about a
-// thread that started a span.
-const (
-	// ThreadIDKey is the attribute Key conforming to the "thread.id" semantic
-	// conventions. It represents the current "managed" thread ID (as opposed
-	// to OS thread ID).
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 42
-	ThreadIDKey = attribute.Key("thread.id")
-
-	// ThreadNameKey is the attribute Key conforming to the "thread.name"
-	// semantic conventions. It represents the current thread name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'main'
-	ThreadNameKey = attribute.Key("thread.name")
-)
-
-// ThreadID returns an attribute KeyValue conforming to the "thread.id"
-// semantic conventions. It represents the current "managed" thread ID (as
-// opposed to OS thread ID).
-func ThreadID(val int) attribute.KeyValue {
-	return ThreadIDKey.Int(val)
-}
-
-// ThreadName returns an attribute KeyValue conforming to the "thread.name"
-// semantic conventions. It represents the current thread name.
-func ThreadName(val string) attribute.KeyValue {
-	return ThreadNameKey.String(val)
-}
-
-// Semantic convention attributes in the TLS namespace.
-const (
-	// TLSCipherKey is the attribute Key conforming to the "tls.cipher"
-	// semantic conventions. It represents the string indicating the
-	// [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5)
-	// used during the current connection.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'TLS_RSA_WITH_3DES_EDE_CBC_SHA',
-	// 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256'
-	// Note: The values allowed for `tls.cipher` MUST be one of the
-	// `Descriptions` of the [registered TLS Cipher
-	// Suits](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4).
-	TLSCipherKey = attribute.Key("tls.cipher")
-
-	// TLSClientCertificateKey is the attribute Key conforming to the
-	// "tls.client.certificate" semantic conventions. It represents the
-	// pEM-encoded stand-alone certificate offered by the client. This is
-	// usually mutually-exclusive of `client.certificate_chain` since this
-	// value also exists in that list.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MII...'
-	TLSClientCertificateKey = attribute.Key("tls.client.certificate")
-
-	// TLSClientCertificateChainKey is the attribute Key conforming to the
-	// "tls.client.certificate_chain" semantic conventions. It represents the
-	// array of PEM-encoded certificates that make up the certificate chain
-	// offered by the client. This is usually mutually-exclusive of
-	// `client.certificate` since that value should be the first certificate in
-	// the chain.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MII...', 'MI...'
-	TLSClientCertificateChainKey = attribute.Key("tls.client.certificate_chain")
-
-	// TLSClientHashMd5Key is the attribute Key conforming to the
-	// "tls.client.hash.md5" semantic conventions. It represents the
-	// certificate fingerprint using the MD5 digest of DER-encoded version of
-	// certificate offered by the client. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC'
-	TLSClientHashMd5Key = attribute.Key("tls.client.hash.md5")
-
-	// TLSClientHashSha1Key is the attribute Key conforming to the
-	// "tls.client.hash.sha1" semantic conventions. It represents the
-	// certificate fingerprint using the SHA1 digest of DER-encoded version of
-	// certificate offered by the client. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A'
-	TLSClientHashSha1Key = attribute.Key("tls.client.hash.sha1")
-
-	// TLSClientHashSha256Key is the attribute Key conforming to the
-	// "tls.client.hash.sha256" semantic conventions. It represents the
-	// certificate fingerprint using the SHA256 digest of DER-encoded version
-	// of certificate offered by the client. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0'
-	TLSClientHashSha256Key = attribute.Key("tls.client.hash.sha256")
-
-	// TLSClientIssuerKey is the attribute Key conforming to the
-	// "tls.client.issuer" semantic conventions. It represents the
-	// distinguished name of
-	// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)
-	// of the issuer of the x.509 certificate presented by the client.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example,
-	// DC=com'
-	TLSClientIssuerKey = attribute.Key("tls.client.issuer")
-
-	// TLSClientJa3Key is the attribute Key conforming to the "tls.client.ja3"
-	// semantic conventions. It represents a hash that identifies clients based
-	// on how they perform an SSL/TLS handshake.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'd4e5b18d6b55c71272893221c96ba240'
-	TLSClientJa3Key = attribute.Key("tls.client.ja3")
-
-	// TLSClientNotAfterKey is the attribute Key conforming to the
-	// "tls.client.not_after" semantic conventions. It represents the date/Time
-	// indicating when client certificate is no longer considered valid.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2021-01-01T00:00:00.000Z'
-	TLSClientNotAfterKey = attribute.Key("tls.client.not_after")
-
-	// TLSClientNotBeforeKey is the attribute Key conforming to the
-	// "tls.client.not_before" semantic conventions. It represents the
-	// date/Time indicating when client certificate is first considered valid.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1970-01-01T00:00:00.000Z'
-	TLSClientNotBeforeKey = attribute.Key("tls.client.not_before")
-
-	// TLSClientServerNameKey is the attribute Key conforming to the
-	// "tls.client.server_name" semantic conventions. It represents the also
-	// called an SNI, this tells the server which hostname to which the client
-	// is attempting to connect to.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'opentelemetry.io'
-	TLSClientServerNameKey = attribute.Key("tls.client.server_name")
-
-	// TLSClientSubjectKey is the attribute Key conforming to the
-	// "tls.client.subject" semantic conventions. It represents the
-	// distinguished name of subject of the x.509 certificate presented by the
-	// client.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'CN=myclient, OU=Documentation Team, DC=example, DC=com'
-	TLSClientSubjectKey = attribute.Key("tls.client.subject")
-
-	// TLSClientSupportedCiphersKey is the attribute Key conforming to the
-	// "tls.client.supported_ciphers" semantic conventions. It represents the
-	// array of ciphers offered by the client during the client hello.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
-	// "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "..."'
-	TLSClientSupportedCiphersKey = attribute.Key("tls.client.supported_ciphers")
-
-	// TLSCurveKey is the attribute Key conforming to the "tls.curve" semantic
-	// conventions. It represents the string indicating the curve used for the
-	// given cipher, when applicable
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'secp256r1'
-	TLSCurveKey = attribute.Key("tls.curve")
-
-	// TLSEstablishedKey is the attribute Key conforming to the
-	// "tls.established" semantic conventions. It represents the boolean flag
-	// indicating if the TLS negotiation was successful and transitioned to an
-	// encrypted tunnel.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: True
-	TLSEstablishedKey = attribute.Key("tls.established")
-
-	// TLSNextProtocolKey is the attribute Key conforming to the
-	// "tls.next_protocol" semantic conventions. It represents the string
-	// indicating the protocol being tunneled. Per the values in the [IANA
-	// registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),
-	// this string should be lower case.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'http/1.1'
-	TLSNextProtocolKey = attribute.Key("tls.next_protocol")
-
-	// TLSProtocolNameKey is the attribute Key conforming to the
-	// "tls.protocol.name" semantic conventions. It represents the normalized
-	// lowercase protocol name parsed from original string of the negotiated
-	// [SSL/TLS protocol
-	// version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES)
-	//
-	// Type: Enum
-	// RequirementLevel: Optional
-	// Stability: experimental
-	TLSProtocolNameKey = attribute.Key("tls.protocol.name")
-
-	// TLSProtocolVersionKey is the attribute Key conforming to the
-	// "tls.protocol.version" semantic conventions. It represents the numeric
-	// part of the version parsed from the original string of the negotiated
-	// [SSL/TLS protocol
-	// version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES)
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1.2', '3'
-	TLSProtocolVersionKey = attribute.Key("tls.protocol.version")
-
-	// TLSResumedKey is the attribute Key conforming to the "tls.resumed"
-	// semantic conventions. It represents the boolean flag indicating if this
-	// TLS connection was resumed from an existing TLS negotiation.
-	//
-	// Type: boolean
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: True
-	TLSResumedKey = attribute.Key("tls.resumed")
-
-	// TLSServerCertificateKey is the attribute Key conforming to the
-	// "tls.server.certificate" semantic conventions. It represents the
-	// pEM-encoded stand-alone certificate offered by the server. This is
-	// usually mutually-exclusive of `server.certificate_chain` since this
-	// value also exists in that list.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MII...'
-	TLSServerCertificateKey = attribute.Key("tls.server.certificate")
-
-	// TLSServerCertificateChainKey is the attribute Key conforming to the
-	// "tls.server.certificate_chain" semantic conventions. It represents the
-	// array of PEM-encoded certificates that make up the certificate chain
-	// offered by the server. This is usually mutually-exclusive of
-	// `server.certificate` since that value should be the first certificate in
-	// the chain.
-	//
-	// Type: string[]
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'MII...', 'MI...'
-	TLSServerCertificateChainKey = attribute.Key("tls.server.certificate_chain")
-
-	// TLSServerHashMd5Key is the attribute Key conforming to the
-	// "tls.server.hash.md5" semantic conventions. It represents the
-	// certificate fingerprint using the MD5 digest of DER-encoded version of
-	// certificate offered by the server. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC'
-	TLSServerHashMd5Key = attribute.Key("tls.server.hash.md5")
-
-	// TLSServerHashSha1Key is the attribute Key conforming to the
-	// "tls.server.hash.sha1" semantic conventions. It represents the
-	// certificate fingerprint using the SHA1 digest of DER-encoded version of
-	// certificate offered by the server. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A'
-	TLSServerHashSha1Key = attribute.Key("tls.server.hash.sha1")
-
-	// TLSServerHashSha256Key is the attribute Key conforming to the
-	// "tls.server.hash.sha256" semantic conventions. It represents the
-	// certificate fingerprint using the SHA256 digest of DER-encoded version
-	// of certificate offered by the server. For consistency with other hash
-	// values, this value should be formatted as an uppercase hash.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples:
-	// '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0'
-	TLSServerHashSha256Key = attribute.Key("tls.server.hash.sha256")
-
-	// TLSServerIssuerKey is the attribute Key conforming to the
-	// "tls.server.issuer" semantic conventions. It represents the
-	// distinguished name of
-	// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)
-	// of the issuer of the x.509 certificate presented by the client.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example,
-	// DC=com'
-	TLSServerIssuerKey = attribute.Key("tls.server.issuer")
-
-	// TLSServerJa3sKey is the attribute Key conforming to the
-	// "tls.server.ja3s" semantic conventions. It represents a hash that
-	// identifies servers based on how they perform an SSL/TLS handshake.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'd4e5b18d6b55c71272893221c96ba240'
-	TLSServerJa3sKey = attribute.Key("tls.server.ja3s")
-
-	// TLSServerNotAfterKey is the attribute Key conforming to the
-	// "tls.server.not_after" semantic conventions. It represents the date/Time
-	// indicating when server certificate is no longer considered valid.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '2021-01-01T00:00:00.000Z'
-	TLSServerNotAfterKey = attribute.Key("tls.server.not_after")
-
-	// TLSServerNotBeforeKey is the attribute Key conforming to the
-	// "tls.server.not_before" semantic conventions. It represents the
-	// date/Time indicating when server certificate is first considered valid.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '1970-01-01T00:00:00.000Z'
-	TLSServerNotBeforeKey = attribute.Key("tls.server.not_before")
-
-	// TLSServerSubjectKey is the attribute Key conforming to the
-	// "tls.server.subject" semantic conventions. It represents the
-	// distinguished name of subject of the x.509 certificate presented by the
-	// server.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'CN=myserver, OU=Documentation Team, DC=example, DC=com'
-	TLSServerSubjectKey = attribute.Key("tls.server.subject")
-)
-
-var (
-	// ssl
-	TLSProtocolNameSsl = TLSProtocolNameKey.String("ssl")
-	// tls
-	TLSProtocolNameTLS = TLSProtocolNameKey.String("tls")
-)
-
-// TLSCipher returns an attribute KeyValue conforming to the "tls.cipher"
-// semantic conventions. It represents the string indicating the
-// [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5) used
-// during the current connection.
-func TLSCipher(val string) attribute.KeyValue {
-	return TLSCipherKey.String(val)
-}
-
-// TLSClientCertificate returns an attribute KeyValue conforming to the
-// "tls.client.certificate" semantic conventions. It represents the pEM-encoded
-// stand-alone certificate offered by the client. This is usually
-// mutually-exclusive of `client.certificate_chain` since this value also
-// exists in that list.
-func TLSClientCertificate(val string) attribute.KeyValue {
-	return TLSClientCertificateKey.String(val)
-}
-
-// TLSClientCertificateChain returns an attribute KeyValue conforming to the
-// "tls.client.certificate_chain" semantic conventions. It represents the array
-// of PEM-encoded certificates that make up the certificate chain offered by
-// the client. This is usually mutually-exclusive of `client.certificate` since
-// that value should be the first certificate in the chain.
-func TLSClientCertificateChain(val ...string) attribute.KeyValue {
-	return TLSClientCertificateChainKey.StringSlice(val)
-}
-
-// TLSClientHashMd5 returns an attribute KeyValue conforming to the
-// "tls.client.hash.md5" semantic conventions. It represents the certificate
-// fingerprint using the MD5 digest of DER-encoded version of certificate
-// offered by the client. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSClientHashMd5(val string) attribute.KeyValue {
-	return TLSClientHashMd5Key.String(val)
-}
-
-// TLSClientHashSha1 returns an attribute KeyValue conforming to the
-// "tls.client.hash.sha1" semantic conventions. It represents the certificate
-// fingerprint using the SHA1 digest of DER-encoded version of certificate
-// offered by the client. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSClientHashSha1(val string) attribute.KeyValue {
-	return TLSClientHashSha1Key.String(val)
-}
-
-// TLSClientHashSha256 returns an attribute KeyValue conforming to the
-// "tls.client.hash.sha256" semantic conventions. It represents the certificate
-// fingerprint using the SHA256 digest of DER-encoded version of certificate
-// offered by the client. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSClientHashSha256(val string) attribute.KeyValue {
-	return TLSClientHashSha256Key.String(val)
-}
-
-// TLSClientIssuer returns an attribute KeyValue conforming to the
-// "tls.client.issuer" semantic conventions. It represents the distinguished
-// name of
-// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of
-// the issuer of the x.509 certificate presented by the client.
-func TLSClientIssuer(val string) attribute.KeyValue {
-	return TLSClientIssuerKey.String(val)
-}
-
-// TLSClientJa3 returns an attribute KeyValue conforming to the
-// "tls.client.ja3" semantic conventions. It represents a hash that identifies
-// clients based on how they perform an SSL/TLS handshake.
-func TLSClientJa3(val string) attribute.KeyValue {
-	return TLSClientJa3Key.String(val)
-}
-
-// TLSClientNotAfter returns an attribute KeyValue conforming to the
-// "tls.client.not_after" semantic conventions. It represents the date/Time
-// indicating when client certificate is no longer considered valid.
-func TLSClientNotAfter(val string) attribute.KeyValue {
-	return TLSClientNotAfterKey.String(val)
-}
-
-// TLSClientNotBefore returns an attribute KeyValue conforming to the
-// "tls.client.not_before" semantic conventions. It represents the date/Time
-// indicating when client certificate is first considered valid.
-func TLSClientNotBefore(val string) attribute.KeyValue {
-	return TLSClientNotBeforeKey.String(val)
-}
-
-// TLSClientServerName returns an attribute KeyValue conforming to the
-// "tls.client.server_name" semantic conventions. It represents the also called
-// an SNI, this tells the server which hostname to which the client is
-// attempting to connect to.
-func TLSClientServerName(val string) attribute.KeyValue {
-	return TLSClientServerNameKey.String(val)
-}
-
-// TLSClientSubject returns an attribute KeyValue conforming to the
-// "tls.client.subject" semantic conventions. It represents the distinguished
-// name of subject of the x.509 certificate presented by the client.
-func TLSClientSubject(val string) attribute.KeyValue {
-	return TLSClientSubjectKey.String(val)
-}
-
-// TLSClientSupportedCiphers returns an attribute KeyValue conforming to the
-// "tls.client.supported_ciphers" semantic conventions. It represents the array
-// of ciphers offered by the client during the client hello.
-func TLSClientSupportedCiphers(val ...string) attribute.KeyValue {
-	return TLSClientSupportedCiphersKey.StringSlice(val)
-}
-
-// TLSCurve returns an attribute KeyValue conforming to the "tls.curve"
-// semantic conventions. It represents the string indicating the curve used for
-// the given cipher, when applicable
-func TLSCurve(val string) attribute.KeyValue {
-	return TLSCurveKey.String(val)
-}
-
-// TLSEstablished returns an attribute KeyValue conforming to the
-// "tls.established" semantic conventions. It represents the boolean flag
-// indicating if the TLS negotiation was successful and transitioned to an
-// encrypted tunnel.
-func TLSEstablished(val bool) attribute.KeyValue {
-	return TLSEstablishedKey.Bool(val)
-}
-
-// TLSNextProtocol returns an attribute KeyValue conforming to the
-// "tls.next_protocol" semantic conventions. It represents the string
-// indicating the protocol being tunneled. Per the values in the [IANA
-// registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),
-// this string should be lower case.
-func TLSNextProtocol(val string) attribute.KeyValue {
-	return TLSNextProtocolKey.String(val)
-}
-
-// TLSProtocolVersion returns an attribute KeyValue conforming to the
-// "tls.protocol.version" semantic conventions. It represents the numeric part
-// of the version parsed from the original string of the negotiated [SSL/TLS
-// protocol
-// version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES)
-func TLSProtocolVersion(val string) attribute.KeyValue {
-	return TLSProtocolVersionKey.String(val)
-}
-
-// TLSResumed returns an attribute KeyValue conforming to the "tls.resumed"
-// semantic conventions. It represents the boolean flag indicating if this TLS
-// connection was resumed from an existing TLS negotiation.
-func TLSResumed(val bool) attribute.KeyValue {
-	return TLSResumedKey.Bool(val)
-}
-
-// TLSServerCertificate returns an attribute KeyValue conforming to the
-// "tls.server.certificate" semantic conventions. It represents the pEM-encoded
-// stand-alone certificate offered by the server. This is usually
-// mutually-exclusive of `server.certificate_chain` since this value also
-// exists in that list.
-func TLSServerCertificate(val string) attribute.KeyValue {
-	return TLSServerCertificateKey.String(val)
-}
-
-// TLSServerCertificateChain returns an attribute KeyValue conforming to the
-// "tls.server.certificate_chain" semantic conventions. It represents the array
-// of PEM-encoded certificates that make up the certificate chain offered by
-// the server. This is usually mutually-exclusive of `server.certificate` since
-// that value should be the first certificate in the chain.
-func TLSServerCertificateChain(val ...string) attribute.KeyValue {
-	return TLSServerCertificateChainKey.StringSlice(val)
-}
-
-// TLSServerHashMd5 returns an attribute KeyValue conforming to the
-// "tls.server.hash.md5" semantic conventions. It represents the certificate
-// fingerprint using the MD5 digest of DER-encoded version of certificate
-// offered by the server. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSServerHashMd5(val string) attribute.KeyValue {
-	return TLSServerHashMd5Key.String(val)
-}
-
-// TLSServerHashSha1 returns an attribute KeyValue conforming to the
-// "tls.server.hash.sha1" semantic conventions. It represents the certificate
-// fingerprint using the SHA1 digest of DER-encoded version of certificate
-// offered by the server. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSServerHashSha1(val string) attribute.KeyValue {
-	return TLSServerHashSha1Key.String(val)
-}
-
-// TLSServerHashSha256 returns an attribute KeyValue conforming to the
-// "tls.server.hash.sha256" semantic conventions. It represents the certificate
-// fingerprint using the SHA256 digest of DER-encoded version of certificate
-// offered by the server. For consistency with other hash values, this value
-// should be formatted as an uppercase hash.
-func TLSServerHashSha256(val string) attribute.KeyValue {
-	return TLSServerHashSha256Key.String(val)
-}
-
-// TLSServerIssuer returns an attribute KeyValue conforming to the
-// "tls.server.issuer" semantic conventions. It represents the distinguished
-// name of
-// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of
-// the issuer of the x.509 certificate presented by the client.
-func TLSServerIssuer(val string) attribute.KeyValue {
-	return TLSServerIssuerKey.String(val)
-}
-
-// TLSServerJa3s returns an attribute KeyValue conforming to the
-// "tls.server.ja3s" semantic conventions. It represents a hash that identifies
-// servers based on how they perform an SSL/TLS handshake.
-func TLSServerJa3s(val string) attribute.KeyValue {
-	return TLSServerJa3sKey.String(val)
-}
-
-// TLSServerNotAfter returns an attribute KeyValue conforming to the
-// "tls.server.not_after" semantic conventions. It represents the date/Time
-// indicating when server certificate is no longer considered valid.
-func TLSServerNotAfter(val string) attribute.KeyValue {
-	return TLSServerNotAfterKey.String(val)
-}
-
-// TLSServerNotBefore returns an attribute KeyValue conforming to the
-// "tls.server.not_before" semantic conventions. It represents the date/Time
-// indicating when server certificate is first considered valid.
-func TLSServerNotBefore(val string) attribute.KeyValue {
-	return TLSServerNotBeforeKey.String(val)
-}
-
-// TLSServerSubject returns an attribute KeyValue conforming to the
-// "tls.server.subject" semantic conventions. It represents the distinguished
-// name of subject of the x.509 certificate presented by the server.
-func TLSServerSubject(val string) attribute.KeyValue {
-	return TLSServerSubjectKey.String(val)
-}
-
-// Attributes describing URL.
-const (
-	// URLDomainKey is the attribute Key conforming to the "url.domain"
-	// semantic conventions. It represents the domain extracted from the
-	// `url.full`, such as "opentelemetry.io".
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'www.foo.bar', 'opentelemetry.io', '3.12.167.2',
-	// '[1080:0:0:0:8:800:200C:417A]'
-	// Note: In some cases a URL may refer to an IP and/or port directly,
-	// without a domain name. In this case, the IP address would go to the
-	// domain field. If the URL contains a [literal IPv6
-	// address](https://www.rfc-editor.org/rfc/rfc2732#section-2) enclosed by
-	// `[` and `]`, the `[` and `]` characters should also be captured in the
-	// domain field.
-	URLDomainKey = attribute.Key("url.domain")
-
-	// URLExtensionKey is the attribute Key conforming to the "url.extension"
-	// semantic conventions. It represents the file extension extracted from
-	// the `url.full`, excluding the leading dot.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'png', 'gz'
-	// Note: The file extension is only set if it exists, as not every url has
-	// a file extension. When the file name has multiple extensions
-	// `example.tar.gz`, only the last one should be captured `gz`, not
-	// `tar.gz`.
-	URLExtensionKey = attribute.Key("url.extension")
-
-	// URLFragmentKey is the attribute Key conforming to the "url.fragment"
-	// semantic conventions. It represents the [URI
-	// fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'SemConv'
-	URLFragmentKey = attribute.Key("url.fragment")
-
-	// URLFullKey is the attribute Key conforming to the "url.full" semantic
-	// conventions. It represents the absolute URL describing a network
-	// resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv',
-	// '//localhost'
-	// Note: For network calls, URL usually has
-	// `scheme://host[:port][path][?query][#fragment]` format, where the
-	// fragment is not transmitted over HTTP, but if it is known, it SHOULD be
-	// included nevertheless.
-	// `url.full` MUST NOT contain credentials passed via URL in form of
-	// `https://username:password@www.example.com/`. In such case username and
-	// password SHOULD be redacted and attribute's value SHOULD be
-	// `https://REDACTED:REDACTED@www.example.com/`.
-	// `url.full` SHOULD capture the absolute URL when it is available (or can
-	// be reconstructed). Sensitive content provided in `url.full` SHOULD be
-	// scrubbed when instrumentations can identify it.
-	URLFullKey = attribute.Key("url.full")
-
-	// URLOriginalKey is the attribute Key conforming to the "url.original"
-	// semantic conventions. It represents the unmodified original URL as seen
-	// in the event source.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv',
-	// 'search?q=OpenTelemetry'
-	// Note: In network monitoring, the observed URL may be a full URL, whereas
-	// in access logs, the URL is often just represented as a path. This field
-	// is meant to represent the URL as it was observed, complete or not.
-	// `url.original` might contain credentials passed via URL in form of
-	// `https://username:password@www.example.com/`. In such case password and
-	// username SHOULD NOT be redacted and attribute's value SHOULD remain the
-	// same.
-	URLOriginalKey = attribute.Key("url.original")
-
-	// URLPathKey is the attribute Key conforming to the "url.path" semantic
-	// conventions. It represents the [URI
-	// path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: '/search'
-	// Note: Sensitive content provided in `url.path` SHOULD be scrubbed when
-	// instrumentations can identify it.
-	URLPathKey = attribute.Key("url.path")
-
-	// URLPortKey is the attribute Key conforming to the "url.port" semantic
-	// conventions. It represents the port extracted from the `url.full`
-	//
-	// Type: int
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 443
-	URLPortKey = attribute.Key("url.port")
-
-	// URLQueryKey is the attribute Key conforming to the "url.query" semantic
-	// conventions. It represents the [URI
-	// query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'q=OpenTelemetry'
-	// Note: Sensitive content provided in `url.query` SHOULD be scrubbed when
-	// instrumentations can identify it.
-	URLQueryKey = attribute.Key("url.query")
-
-	// URLRegisteredDomainKey is the attribute Key conforming to the
-	// "url.registered_domain" semantic conventions. It represents the highest
-	// registered url domain, stripped of the subdomain.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'example.com', 'foo.co.uk'
-	// Note: This value can be determined precisely with the [public suffix
-	// list](http://publicsuffix.org). For example, the registered domain for
-	// `foo.example.com` is `example.com`. Trying to approximate this by simply
-	// taking the last two labels will not work well for TLDs such as `co.uk`.
-	URLRegisteredDomainKey = attribute.Key("url.registered_domain")
-
-	// URLSchemeKey is the attribute Key conforming to the "url.scheme"
-	// semantic conventions. It represents the [URI
-	// scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component
-	// identifying the used protocol.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'https', 'ftp', 'telnet'
-	URLSchemeKey = attribute.Key("url.scheme")
-
-	// URLSubdomainKey is the attribute Key conforming to the "url.subdomain"
-	// semantic conventions. It represents the subdomain portion of a fully
-	// qualified domain name includes all of the names except the host name
-	// under the registered_domain. In a partially qualified domain, or if the
-	// qualification level of the full name cannot be determined, subdomain
-	// contains all of the names below the registered domain.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'east', 'sub2.sub1'
-	// Note: The subdomain portion of `www.east.mydomain.co.uk` is `east`. If
-	// the domain has multiple levels of subdomain, such as
-	// `sub2.sub1.example.com`, the subdomain field should contain `sub2.sub1`,
-	// with no trailing period.
-	URLSubdomainKey = attribute.Key("url.subdomain")
-
-	// URLTemplateKey is the attribute Key conforming to the "url.template"
-	// semantic conventions. It represents the low-cardinality template of an
-	// [absolute path
-	// reference](https://www.rfc-editor.org/rfc/rfc3986#section-4.2).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '/users/{id}', '/users/:id', '/users?id={id}'
-	URLTemplateKey = attribute.Key("url.template")
-
-	// URLTopLevelDomainKey is the attribute Key conforming to the
-	// "url.top_level_domain" semantic conventions. It represents the effective
-	// top level domain (eTLD), also known as the domain suffix, is the last
-	// part of the domain name. For example, the top level domain for
-	// example.com is `com`.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'com', 'co.uk'
-	// Note: This value can be determined precisely with the [public suffix
-	// list](http://publicsuffix.org).
-	URLTopLevelDomainKey = attribute.Key("url.top_level_domain")
-)
-
-// URLDomain returns an attribute KeyValue conforming to the "url.domain"
-// semantic conventions. It represents the domain extracted from the
-// `url.full`, such as "opentelemetry.io".
-func URLDomain(val string) attribute.KeyValue {
-	return URLDomainKey.String(val)
-}
-
-// URLExtension returns an attribute KeyValue conforming to the
-// "url.extension" semantic conventions. It represents the file extension
-// extracted from the `url.full`, excluding the leading dot.
-func URLExtension(val string) attribute.KeyValue {
-	return URLExtensionKey.String(val)
-}
-
-// URLFragment returns an attribute KeyValue conforming to the
-// "url.fragment" semantic conventions. It represents the [URI
-// fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component
-func URLFragment(val string) attribute.KeyValue {
-	return URLFragmentKey.String(val)
-}
-
-// URLFull returns an attribute KeyValue conforming to the "url.full"
-// semantic conventions. It represents the absolute URL describing a network
-// resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)
-func URLFull(val string) attribute.KeyValue {
-	return URLFullKey.String(val)
-}
-
-// URLOriginal returns an attribute KeyValue conforming to the
-// "url.original" semantic conventions. It represents the unmodified original
-// URL as seen in the event source.
-func URLOriginal(val string) attribute.KeyValue {
-	return URLOriginalKey.String(val)
-}
-
-// URLPath returns an attribute KeyValue conforming to the "url.path"
-// semantic conventions. It represents the [URI
-// path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component
-func URLPath(val string) attribute.KeyValue {
-	return URLPathKey.String(val)
-}
-
-// URLPort returns an attribute KeyValue conforming to the "url.port"
-// semantic conventions. It represents the port extracted from the `url.full`
-func URLPort(val int) attribute.KeyValue {
-	return URLPortKey.Int(val)
-}
-
-// URLQuery returns an attribute KeyValue conforming to the "url.query"
-// semantic conventions. It represents the [URI
-// query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component
-func URLQuery(val string) attribute.KeyValue {
-	return URLQueryKey.String(val)
-}
-
-// URLRegisteredDomain returns an attribute KeyValue conforming to the
-// "url.registered_domain" semantic conventions. It represents the highest
-// registered url domain, stripped of the subdomain.
-func URLRegisteredDomain(val string) attribute.KeyValue {
-	return URLRegisteredDomainKey.String(val)
-}
-
-// URLScheme returns an attribute KeyValue conforming to the "url.scheme"
-// semantic conventions. It represents the [URI
-// scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component
-// identifying the used protocol.
-func URLScheme(val string) attribute.KeyValue {
-	return URLSchemeKey.String(val)
-}
-
-// URLSubdomain returns an attribute KeyValue conforming to the
-// "url.subdomain" semantic conventions. It represents the subdomain portion of
-// a fully qualified domain name includes all of the names except the host name
-// under the registered_domain. In a partially qualified domain, or if the
-// qualification level of the full name cannot be determined, subdomain
-// contains all of the names below the registered domain.
-func URLSubdomain(val string) attribute.KeyValue {
-	return URLSubdomainKey.String(val)
-}
-
-// URLTemplate returns an attribute KeyValue conforming to the
-// "url.template" semantic conventions. It represents the low-cardinality
-// template of an [absolute path
-// reference](https://www.rfc-editor.org/rfc/rfc3986#section-4.2).
-func URLTemplate(val string) attribute.KeyValue {
-	return URLTemplateKey.String(val)
-}
-
-// URLTopLevelDomain returns an attribute KeyValue conforming to the
-// "url.top_level_domain" semantic conventions. It represents the effective top
-// level domain (eTLD), also known as the domain suffix, is the last part of
-// the domain name. For example, the top level domain for example.com is `com`.
-func URLTopLevelDomain(val string) attribute.KeyValue {
-	return URLTopLevelDomainKey.String(val)
-}
-
-// Describes user-agent attributes.
-const (
-	// UserAgentNameKey is the attribute Key conforming to the
-	// "user_agent.name" semantic conventions. It represents the name of the
-	// user-agent extracted from original. Usually refers to the browser's
-	// name.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'Safari', 'YourApp'
-	// Note: [Example](https://www.whatsmyua.info) of extracting browser's name
-	// from original string. In the case of using a user-agent for non-browser
-	// products, such as microservices with multiple names/versions inside the
-	// `user_agent.original`, the most significant name SHOULD be selected. In
-	// such a scenario it should align with `user_agent.version`
-	UserAgentNameKey = attribute.Key("user_agent.name")
-
-	// UserAgentOriginalKey is the attribute Key conforming to the
-	// "user_agent.original" semantic conventions. It represents the value of
-	// the [HTTP
-	// User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent)
-	// header sent by the client.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: stable
-	// Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU
-	// iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)
-	// Version/14.1.2 Mobile/15E148 Safari/604.1', 'YourApp/1.0.0
-	// grpc-java-okhttp/1.27.2'
-	UserAgentOriginalKey = attribute.Key("user_agent.original")
-
-	// UserAgentVersionKey is the attribute Key conforming to the
-	// "user_agent.version" semantic conventions. It represents the version of
-	// the user-agent extracted from original. Usually refers to the browser's
-	// version
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '14.1.2', '1.0.0'
-	// Note: [Example](https://www.whatsmyua.info) of extracting browser's
-	// version from original string. In the case of using a user-agent for
-	// non-browser products, such as microservices with multiple names/versions
-	// inside the `user_agent.original`, the most significant version SHOULD be
-	// selected. In such a scenario it should align with `user_agent.name`
-	UserAgentVersionKey = attribute.Key("user_agent.version")
-)
-
-// UserAgentName returns an attribute KeyValue conforming to the
-// "user_agent.name" semantic conventions. It represents the name of the
-// user-agent extracted from original. Usually refers to the browser's name.
-func UserAgentName(val string) attribute.KeyValue {
-	return UserAgentNameKey.String(val)
-}
-
-// UserAgentOriginal returns an attribute KeyValue conforming to the
-// "user_agent.original" semantic conventions. It represents the value of the
-// [HTTP
-// User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent)
-// header sent by the client.
-func UserAgentOriginal(val string) attribute.KeyValue {
-	return UserAgentOriginalKey.String(val)
-}
-
-// UserAgentVersion returns an attribute KeyValue conforming to the
-// "user_agent.version" semantic conventions. It represents the version of the
-// user-agent extracted from original. Usually refers to the browser's version
-func UserAgentVersion(val string) attribute.KeyValue {
-	return UserAgentVersionKey.String(val)
-}
-
-// The attributes used to describe the packaged software running the
-// application code.
-const (
-	// WebEngineDescriptionKey is the attribute Key conforming to the
-	// "webengine.description" semantic conventions. It represents the
-	// additional description of the web engine (e.g. detailed version and
-	// edition information).
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) -
-	// 2.2.2.Final'
-	WebEngineDescriptionKey = attribute.Key("webengine.description")
-
-	// WebEngineNameKey is the attribute Key conforming to the "webengine.name"
-	// semantic conventions. It represents the name of the web engine.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: 'WildFly'
-	WebEngineNameKey = attribute.Key("webengine.name")
-
-	// WebEngineVersionKey is the attribute Key conforming to the
-	// "webengine.version" semantic conventions. It represents the version of
-	// the web engine.
-	//
-	// Type: string
-	// RequirementLevel: Optional
-	// Stability: experimental
-	// Examples: '21.0.0'
-	WebEngineVersionKey = attribute.Key("webengine.version")
-)
-
-// WebEngineDescription returns an attribute KeyValue conforming to the
-// "webengine.description" semantic conventions. It represents the additional
-// description of the web engine (e.g. detailed version and edition
-// information).
-func WebEngineDescription(val string) attribute.KeyValue {
-	return WebEngineDescriptionKey.String(val)
-}
-
-// WebEngineName returns an attribute KeyValue conforming to the
-// "webengine.name" semantic conventions. It represents the name of the web
-// engine.
-func WebEngineName(val string) attribute.KeyValue {
-	return WebEngineNameKey.String(val)
-}
-
-// WebEngineVersion returns an attribute KeyValue conforming to the
-// "webengine.version" semantic conventions. It represents the version of the
-// web engine.
-func WebEngineVersion(val string) attribute.KeyValue {
-	return WebEngineVersionKey.String(val)
-}
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/doc.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/doc.go
deleted file mode 100644
index d031bbea..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/doc.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-// Package semconv implements OpenTelemetry semantic conventions.
-//
-// OpenTelemetry semantic conventions are agreed standardized naming
-// patterns for OpenTelemetry things. This package represents the v1.26.0
-// version of the OpenTelemetry semantic conventions.
-package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/exception.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/exception.go
deleted file mode 100644
index bfaee0d5..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/exception.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
-
-const (
-	// ExceptionEventName is the name of the Span event representing an exception.
-	ExceptionEventName = "exception"
-)
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/metric.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/metric.go
deleted file mode 100644
index fcdb9f48..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/metric.go
+++ /dev/null
@@ -1,1307 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-// Code generated from semantic convention specification. DO NOT EDIT.
-
-package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
-
-const (
-
-	// ContainerCPUTime is the metric conforming to the "container.cpu.time"
-	// semantic conventions. It represents the total CPU time consumed.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Experimental
-	ContainerCPUTimeName        = "container.cpu.time"
-	ContainerCPUTimeUnit        = "s"
-	ContainerCPUTimeDescription = "Total CPU time consumed"
-
-	// ContainerMemoryUsage is the metric conforming to the
-	// "container.memory.usage" semantic conventions. It represents the memory
-	// usage of the container.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	ContainerMemoryUsageName        = "container.memory.usage"
-	ContainerMemoryUsageUnit        = "By"
-	ContainerMemoryUsageDescription = "Memory usage of the container."
-
-	// ContainerDiskIo is the metric conforming to the "container.disk.io" semantic
-	// conventions. It represents the disk bytes for the container.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	ContainerDiskIoName        = "container.disk.io"
-	ContainerDiskIoUnit        = "By"
-	ContainerDiskIoDescription = "Disk bytes for the container."
-
-	// ContainerNetworkIo is the metric conforming to the "container.network.io"
-	// semantic conventions. It represents the network bytes for the container.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	ContainerNetworkIoName        = "container.network.io"
-	ContainerNetworkIoUnit        = "By"
-	ContainerNetworkIoDescription = "Network bytes for the container."
-
-	// DBClientOperationDuration is the metric conforming to the
-	// "db.client.operation.duration" semantic conventions. It represents the
-	// duration of database client operations.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	DBClientOperationDurationName        = "db.client.operation.duration"
-	DBClientOperationDurationUnit        = "s"
-	DBClientOperationDurationDescription = "Duration of database client operations."
-
-	// DBClientConnectionCount is the metric conforming to the
-	// "db.client.connection.count" semantic conventions. It represents the number
-	// of connections that are currently in state described by the `state`
-	// attribute.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionCountName        = "db.client.connection.count"
-	DBClientConnectionCountUnit        = "{connection}"
-	DBClientConnectionCountDescription = "The number of connections that are currently in state described by the `state` attribute"
-
-	// DBClientConnectionIdleMax is the metric conforming to the
-	// "db.client.connection.idle.max" semantic conventions. It represents the
-	// maximum number of idle open connections allowed.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionIdleMaxName        = "db.client.connection.idle.max"
-	DBClientConnectionIdleMaxUnit        = "{connection}"
-	DBClientConnectionIdleMaxDescription = "The maximum number of idle open connections allowed"
-
-	// DBClientConnectionIdleMin is the metric conforming to the
-	// "db.client.connection.idle.min" semantic conventions. It represents the
-	// minimum number of idle open connections allowed.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionIdleMinName        = "db.client.connection.idle.min"
-	DBClientConnectionIdleMinUnit        = "{connection}"
-	DBClientConnectionIdleMinDescription = "The minimum number of idle open connections allowed"
-
-	// DBClientConnectionMax is the metric conforming to the
-	// "db.client.connection.max" semantic conventions. It represents the maximum
-	// number of open connections allowed.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionMaxName        = "db.client.connection.max"
-	DBClientConnectionMaxUnit        = "{connection}"
-	DBClientConnectionMaxDescription = "The maximum number of open connections allowed"
-
-	// DBClientConnectionPendingRequests is the metric conforming to the
-	// "db.client.connection.pending_requests" semantic conventions. It represents
-	// the number of pending requests for an open connection, cumulative for the
-	// entire pool.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Experimental
-	DBClientConnectionPendingRequestsName        = "db.client.connection.pending_requests"
-	DBClientConnectionPendingRequestsUnit        = "{request}"
-	DBClientConnectionPendingRequestsDescription = "The number of pending requests for an open connection, cumulative for the entire pool"
-
-	// DBClientConnectionTimeouts is the metric conforming to the
-	// "db.client.connection.timeouts" semantic conventions. It represents the
-	// number of connection timeouts that have occurred trying to obtain a
-	// connection from the pool.
-	// Instrument: counter
-	// Unit: {timeout}
-	// Stability: Experimental
-	DBClientConnectionTimeoutsName        = "db.client.connection.timeouts"
-	DBClientConnectionTimeoutsUnit        = "{timeout}"
-	DBClientConnectionTimeoutsDescription = "The number of connection timeouts that have occurred trying to obtain a connection from the pool"
-
-	// DBClientConnectionCreateTime is the metric conforming to the
-	// "db.client.connection.create_time" semantic conventions. It represents the
-	// time it took to create a new connection.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	DBClientConnectionCreateTimeName        = "db.client.connection.create_time"
-	DBClientConnectionCreateTimeUnit        = "s"
-	DBClientConnectionCreateTimeDescription = "The time it took to create a new connection"
-
-	// DBClientConnectionWaitTime is the metric conforming to the
-	// "db.client.connection.wait_time" semantic conventions. It represents the
-	// time it took to obtain an open connection from the pool.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	DBClientConnectionWaitTimeName        = "db.client.connection.wait_time"
-	DBClientConnectionWaitTimeUnit        = "s"
-	DBClientConnectionWaitTimeDescription = "The time it took to obtain an open connection from the pool"
-
-	// DBClientConnectionUseTime is the metric conforming to the
-	// "db.client.connection.use_time" semantic conventions. It represents the time
-	// between borrowing a connection and returning it to the pool.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	DBClientConnectionUseTimeName        = "db.client.connection.use_time"
-	DBClientConnectionUseTimeUnit        = "s"
-	DBClientConnectionUseTimeDescription = "The time between borrowing a connection and returning it to the pool"
-
-	// DBClientConnectionsUsage is the metric conforming to the
-	// "db.client.connections.usage" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.count` instead.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionsUsageName        = "db.client.connections.usage"
-	DBClientConnectionsUsageUnit        = "{connection}"
-	DBClientConnectionsUsageDescription = "Deprecated, use `db.client.connection.count` instead."
-
-	// DBClientConnectionsIdleMax is the metric conforming to the
-	// "db.client.connections.idle.max" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.idle.max` instead.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionsIdleMaxName        = "db.client.connections.idle.max"
-	DBClientConnectionsIdleMaxUnit        = "{connection}"
-	DBClientConnectionsIdleMaxDescription = "Deprecated, use `db.client.connection.idle.max` instead."
-
-	// DBClientConnectionsIdleMin is the metric conforming to the
-	// "db.client.connections.idle.min" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.idle.min` instead.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionsIdleMinName        = "db.client.connections.idle.min"
-	DBClientConnectionsIdleMinUnit        = "{connection}"
-	DBClientConnectionsIdleMinDescription = "Deprecated, use `db.client.connection.idle.min` instead."
-
-	// DBClientConnectionsMax is the metric conforming to the
-	// "db.client.connections.max" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.max` instead.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	DBClientConnectionsMaxName        = "db.client.connections.max"
-	DBClientConnectionsMaxUnit        = "{connection}"
-	DBClientConnectionsMaxDescription = "Deprecated, use `db.client.connection.max` instead."
-
-	// DBClientConnectionsPendingRequests is the metric conforming to the
-	// "db.client.connections.pending_requests" semantic conventions. It represents
-	// the deprecated, use `db.client.connection.pending_requests` instead.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Experimental
-	DBClientConnectionsPendingRequestsName        = "db.client.connections.pending_requests"
-	DBClientConnectionsPendingRequestsUnit        = "{request}"
-	DBClientConnectionsPendingRequestsDescription = "Deprecated, use `db.client.connection.pending_requests` instead."
-
-	// DBClientConnectionsTimeouts is the metric conforming to the
-	// "db.client.connections.timeouts" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.timeouts` instead.
-	// Instrument: counter
-	// Unit: {timeout}
-	// Stability: Experimental
-	DBClientConnectionsTimeoutsName        = "db.client.connections.timeouts"
-	DBClientConnectionsTimeoutsUnit        = "{timeout}"
-	DBClientConnectionsTimeoutsDescription = "Deprecated, use `db.client.connection.timeouts` instead."
-
-	// DBClientConnectionsCreateTime is the metric conforming to the
-	// "db.client.connections.create_time" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.create_time` instead. Note: the unit
-	// also changed from `ms` to `s`.
-	// Instrument: histogram
-	// Unit: ms
-	// Stability: Experimental
-	DBClientConnectionsCreateTimeName        = "db.client.connections.create_time"
-	DBClientConnectionsCreateTimeUnit        = "ms"
-	DBClientConnectionsCreateTimeDescription = "Deprecated, use `db.client.connection.create_time` instead. Note: the unit also changed from `ms` to `s`."
-
-	// DBClientConnectionsWaitTime is the metric conforming to the
-	// "db.client.connections.wait_time" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.wait_time` instead. Note: the unit
-	// also changed from `ms` to `s`.
-	// Instrument: histogram
-	// Unit: ms
-	// Stability: Experimental
-	DBClientConnectionsWaitTimeName        = "db.client.connections.wait_time"
-	DBClientConnectionsWaitTimeUnit        = "ms"
-	DBClientConnectionsWaitTimeDescription = "Deprecated, use `db.client.connection.wait_time` instead. Note: the unit also changed from `ms` to `s`."
-
-	// DBClientConnectionsUseTime is the metric conforming to the
-	// "db.client.connections.use_time" semantic conventions. It represents the
-	// deprecated, use `db.client.connection.use_time` instead. Note: the unit also
-	// changed from `ms` to `s`.
-	// Instrument: histogram
-	// Unit: ms
-	// Stability: Experimental
-	DBClientConnectionsUseTimeName        = "db.client.connections.use_time"
-	DBClientConnectionsUseTimeUnit        = "ms"
-	DBClientConnectionsUseTimeDescription = "Deprecated, use `db.client.connection.use_time` instead. Note: the unit also changed from `ms` to `s`."
-
-	// DNSLookupDuration is the metric conforming to the "dns.lookup.duration"
-	// semantic conventions. It represents the measures the time taken to perform a
-	// DNS lookup.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	DNSLookupDurationName        = "dns.lookup.duration"
-	DNSLookupDurationUnit        = "s"
-	DNSLookupDurationDescription = "Measures the time taken to perform a DNS lookup."
-
-	// AspnetcoreRoutingMatchAttempts is the metric conforming to the
-	// "aspnetcore.routing.match_attempts" semantic conventions. It represents the
-	// number of requests that were attempted to be matched to an endpoint.
-	// Instrument: counter
-	// Unit: {match_attempt}
-	// Stability: Stable
-	AspnetcoreRoutingMatchAttemptsName        = "aspnetcore.routing.match_attempts"
-	AspnetcoreRoutingMatchAttemptsUnit        = "{match_attempt}"
-	AspnetcoreRoutingMatchAttemptsDescription = "Number of requests that were attempted to be matched to an endpoint."
-
-	// AspnetcoreDiagnosticsExceptions is the metric conforming to the
-	// "aspnetcore.diagnostics.exceptions" semantic conventions. It represents the
-	// number of exceptions caught by exception handling middleware.
-	// Instrument: counter
-	// Unit: {exception}
-	// Stability: Stable
-	AspnetcoreDiagnosticsExceptionsName        = "aspnetcore.diagnostics.exceptions"
-	AspnetcoreDiagnosticsExceptionsUnit        = "{exception}"
-	AspnetcoreDiagnosticsExceptionsDescription = "Number of exceptions caught by exception handling middleware."
-
-	// AspnetcoreRateLimitingActiveRequestLeases is the metric conforming to the
-	// "aspnetcore.rate_limiting.active_request_leases" semantic conventions. It
-	// represents the number of requests that are currently active on the server
-	// that hold a rate limiting lease.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Stable
-	AspnetcoreRateLimitingActiveRequestLeasesName        = "aspnetcore.rate_limiting.active_request_leases"
-	AspnetcoreRateLimitingActiveRequestLeasesUnit        = "{request}"
-	AspnetcoreRateLimitingActiveRequestLeasesDescription = "Number of requests that are currently active on the server that hold a rate limiting lease."
-
-	// AspnetcoreRateLimitingRequestLeaseDuration is the metric conforming to the
-	// "aspnetcore.rate_limiting.request_lease.duration" semantic conventions. It
-	// represents the duration of rate limiting lease held by requests on the
-	// server.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	AspnetcoreRateLimitingRequestLeaseDurationName        = "aspnetcore.rate_limiting.request_lease.duration"
-	AspnetcoreRateLimitingRequestLeaseDurationUnit        = "s"
-	AspnetcoreRateLimitingRequestLeaseDurationDescription = "The duration of rate limiting lease held by requests on the server."
-
-	// AspnetcoreRateLimitingRequestTimeInQueue is the metric conforming to the
-	// "aspnetcore.rate_limiting.request.time_in_queue" semantic conventions. It
-	// represents the time the request spent in a queue waiting to acquire a rate
-	// limiting lease.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	AspnetcoreRateLimitingRequestTimeInQueueName        = "aspnetcore.rate_limiting.request.time_in_queue"
-	AspnetcoreRateLimitingRequestTimeInQueueUnit        = "s"
-	AspnetcoreRateLimitingRequestTimeInQueueDescription = "The time the request spent in a queue waiting to acquire a rate limiting lease."
-
-	// AspnetcoreRateLimitingQueuedRequests is the metric conforming to the
-	// "aspnetcore.rate_limiting.queued_requests" semantic conventions. It
-	// represents the number of requests that are currently queued, waiting to
-	// acquire a rate limiting lease.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Stable
-	AspnetcoreRateLimitingQueuedRequestsName        = "aspnetcore.rate_limiting.queued_requests"
-	AspnetcoreRateLimitingQueuedRequestsUnit        = "{request}"
-	AspnetcoreRateLimitingQueuedRequestsDescription = "Number of requests that are currently queued, waiting to acquire a rate limiting lease."
-
-	// AspnetcoreRateLimitingRequests is the metric conforming to the
-	// "aspnetcore.rate_limiting.requests" semantic conventions. It represents the
-	// number of requests that tried to acquire a rate limiting lease.
-	// Instrument: counter
-	// Unit: {request}
-	// Stability: Stable
-	AspnetcoreRateLimitingRequestsName        = "aspnetcore.rate_limiting.requests"
-	AspnetcoreRateLimitingRequestsUnit        = "{request}"
-	AspnetcoreRateLimitingRequestsDescription = "Number of requests that tried to acquire a rate limiting lease."
-
-	// KestrelActiveConnections is the metric conforming to the
-	// "kestrel.active_connections" semantic conventions. It represents the number
-	// of connections that are currently active on the server.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Stable
-	KestrelActiveConnectionsName        = "kestrel.active_connections"
-	KestrelActiveConnectionsUnit        = "{connection}"
-	KestrelActiveConnectionsDescription = "Number of connections that are currently active on the server."
-
-	// KestrelConnectionDuration is the metric conforming to the
-	// "kestrel.connection.duration" semantic conventions. It represents the
-	// duration of connections on the server.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	KestrelConnectionDurationName        = "kestrel.connection.duration"
-	KestrelConnectionDurationUnit        = "s"
-	KestrelConnectionDurationDescription = "The duration of connections on the server."
-
-	// KestrelRejectedConnections is the metric conforming to the
-	// "kestrel.rejected_connections" semantic conventions. It represents the
-	// number of connections rejected by the server.
-	// Instrument: counter
-	// Unit: {connection}
-	// Stability: Stable
-	KestrelRejectedConnectionsName        = "kestrel.rejected_connections"
-	KestrelRejectedConnectionsUnit        = "{connection}"
-	KestrelRejectedConnectionsDescription = "Number of connections rejected by the server."
-
-	// KestrelQueuedConnections is the metric conforming to the
-	// "kestrel.queued_connections" semantic conventions. It represents the number
-	// of connections that are currently queued and are waiting to start.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Stable
-	KestrelQueuedConnectionsName        = "kestrel.queued_connections"
-	KestrelQueuedConnectionsUnit        = "{connection}"
-	KestrelQueuedConnectionsDescription = "Number of connections that are currently queued and are waiting to start."
-
-	// KestrelQueuedRequests is the metric conforming to the
-	// "kestrel.queued_requests" semantic conventions. It represents the number of
-	// HTTP requests on multiplexed connections (HTTP/2 and HTTP/3) that are
-	// currently queued and are waiting to start.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Stable
-	KestrelQueuedRequestsName        = "kestrel.queued_requests"
-	KestrelQueuedRequestsUnit        = "{request}"
-	KestrelQueuedRequestsDescription = "Number of HTTP requests on multiplexed connections (HTTP/2 and HTTP/3) that are currently queued and are waiting to start."
-
-	// KestrelUpgradedConnections is the metric conforming to the
-	// "kestrel.upgraded_connections" semantic conventions. It represents the
-	// number of connections that are currently upgraded (WebSockets). .
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Stable
-	KestrelUpgradedConnectionsName        = "kestrel.upgraded_connections"
-	KestrelUpgradedConnectionsUnit        = "{connection}"
-	KestrelUpgradedConnectionsDescription = "Number of connections that are currently upgraded (WebSockets). ."
-
-	// KestrelTLSHandshakeDuration is the metric conforming to the
-	// "kestrel.tls_handshake.duration" semantic conventions. It represents the
-	// duration of TLS handshakes on the server.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	KestrelTLSHandshakeDurationName        = "kestrel.tls_handshake.duration"
-	KestrelTLSHandshakeDurationUnit        = "s"
-	KestrelTLSHandshakeDurationDescription = "The duration of TLS handshakes on the server."
-
-	// KestrelActiveTLSHandshakes is the metric conforming to the
-	// "kestrel.active_tls_handshakes" semantic conventions. It represents the
-	// number of TLS handshakes that are currently in progress on the server.
-	// Instrument: updowncounter
-	// Unit: {handshake}
-	// Stability: Stable
-	KestrelActiveTLSHandshakesName        = "kestrel.active_tls_handshakes"
-	KestrelActiveTLSHandshakesUnit        = "{handshake}"
-	KestrelActiveTLSHandshakesDescription = "Number of TLS handshakes that are currently in progress on the server."
-
-	// SignalrServerConnectionDuration is the metric conforming to the
-	// "signalr.server.connection.duration" semantic conventions. It represents the
-	// duration of connections on the server.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	SignalrServerConnectionDurationName        = "signalr.server.connection.duration"
-	SignalrServerConnectionDurationUnit        = "s"
-	SignalrServerConnectionDurationDescription = "The duration of connections on the server."
-
-	// SignalrServerActiveConnections is the metric conforming to the
-	// "signalr.server.active_connections" semantic conventions. It represents the
-	// number of connections that are currently active on the server.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Stable
-	SignalrServerActiveConnectionsName        = "signalr.server.active_connections"
-	SignalrServerActiveConnectionsUnit        = "{connection}"
-	SignalrServerActiveConnectionsDescription = "Number of connections that are currently active on the server."
-
-	// FaaSInvokeDuration is the metric conforming to the "faas.invoke_duration"
-	// semantic conventions. It represents the measures the duration of the
-	// function's logic execution.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	FaaSInvokeDurationName        = "faas.invoke_duration"
-	FaaSInvokeDurationUnit        = "s"
-	FaaSInvokeDurationDescription = "Measures the duration of the function's logic execution"
-
-	// FaaSInitDuration is the metric conforming to the "faas.init_duration"
-	// semantic conventions. It represents the measures the duration of the
-	// function's initialization, such as a cold start.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	FaaSInitDurationName        = "faas.init_duration"
-	FaaSInitDurationUnit        = "s"
-	FaaSInitDurationDescription = "Measures the duration of the function's initialization, such as a cold start"
-
-	// FaaSColdstarts is the metric conforming to the "faas.coldstarts" semantic
-	// conventions. It represents the number of invocation cold starts.
-	// Instrument: counter
-	// Unit: {coldstart}
-	// Stability: Experimental
-	FaaSColdstartsName        = "faas.coldstarts"
-	FaaSColdstartsUnit        = "{coldstart}"
-	FaaSColdstartsDescription = "Number of invocation cold starts"
-
-	// FaaSErrors is the metric conforming to the "faas.errors" semantic
-	// conventions. It represents the number of invocation errors.
-	// Instrument: counter
-	// Unit: {error}
-	// Stability: Experimental
-	FaaSErrorsName        = "faas.errors"
-	FaaSErrorsUnit        = "{error}"
-	FaaSErrorsDescription = "Number of invocation errors"
-
-	// FaaSInvocations is the metric conforming to the "faas.invocations" semantic
-	// conventions. It represents the number of successful invocations.
-	// Instrument: counter
-	// Unit: {invocation}
-	// Stability: Experimental
-	FaaSInvocationsName        = "faas.invocations"
-	FaaSInvocationsUnit        = "{invocation}"
-	FaaSInvocationsDescription = "Number of successful invocations"
-
-	// FaaSTimeouts is the metric conforming to the "faas.timeouts" semantic
-	// conventions. It represents the number of invocation timeouts.
-	// Instrument: counter
-	// Unit: {timeout}
-	// Stability: Experimental
-	FaaSTimeoutsName        = "faas.timeouts"
-	FaaSTimeoutsUnit        = "{timeout}"
-	FaaSTimeoutsDescription = "Number of invocation timeouts"
-
-	// FaaSMemUsage is the metric conforming to the "faas.mem_usage" semantic
-	// conventions. It represents the distribution of max memory usage per
-	// invocation.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	FaaSMemUsageName        = "faas.mem_usage"
-	FaaSMemUsageUnit        = "By"
-	FaaSMemUsageDescription = "Distribution of max memory usage per invocation"
-
-	// FaaSCPUUsage is the metric conforming to the "faas.cpu_usage" semantic
-	// conventions. It represents the distribution of CPU usage per invocation.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	FaaSCPUUsageName        = "faas.cpu_usage"
-	FaaSCPUUsageUnit        = "s"
-	FaaSCPUUsageDescription = "Distribution of CPU usage per invocation"
-
-	// FaaSNetIo is the metric conforming to the "faas.net_io" semantic
-	// conventions. It represents the distribution of net I/O usage per invocation.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	FaaSNetIoName        = "faas.net_io"
-	FaaSNetIoUnit        = "By"
-	FaaSNetIoDescription = "Distribution of net I/O usage per invocation"
-
-	// HTTPServerRequestDuration is the metric conforming to the
-	// "http.server.request.duration" semantic conventions. It represents the
-	// duration of HTTP server requests.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	HTTPServerRequestDurationName        = "http.server.request.duration"
-	HTTPServerRequestDurationUnit        = "s"
-	HTTPServerRequestDurationDescription = "Duration of HTTP server requests."
-
-	// HTTPServerActiveRequests is the metric conforming to the
-	// "http.server.active_requests" semantic conventions. It represents the number
-	// of active HTTP server requests.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Experimental
-	HTTPServerActiveRequestsName        = "http.server.active_requests"
-	HTTPServerActiveRequestsUnit        = "{request}"
-	HTTPServerActiveRequestsDescription = "Number of active HTTP server requests."
-
-	// HTTPServerRequestBodySize is the metric conforming to the
-	// "http.server.request.body.size" semantic conventions. It represents the size
-	// of HTTP server request bodies.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	HTTPServerRequestBodySizeName        = "http.server.request.body.size"
-	HTTPServerRequestBodySizeUnit        = "By"
-	HTTPServerRequestBodySizeDescription = "Size of HTTP server request bodies."
-
-	// HTTPServerResponseBodySize is the metric conforming to the
-	// "http.server.response.body.size" semantic conventions. It represents the
-	// size of HTTP server response bodies.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	HTTPServerResponseBodySizeName        = "http.server.response.body.size"
-	HTTPServerResponseBodySizeUnit        = "By"
-	HTTPServerResponseBodySizeDescription = "Size of HTTP server response bodies."
-
-	// HTTPClientRequestDuration is the metric conforming to the
-	// "http.client.request.duration" semantic conventions. It represents the
-	// duration of HTTP client requests.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	HTTPClientRequestDurationName        = "http.client.request.duration"
-	HTTPClientRequestDurationUnit        = "s"
-	HTTPClientRequestDurationDescription = "Duration of HTTP client requests."
-
-	// HTTPClientRequestBodySize is the metric conforming to the
-	// "http.client.request.body.size" semantic conventions. It represents the size
-	// of HTTP client request bodies.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	HTTPClientRequestBodySizeName        = "http.client.request.body.size"
-	HTTPClientRequestBodySizeUnit        = "By"
-	HTTPClientRequestBodySizeDescription = "Size of HTTP client request bodies."
-
-	// HTTPClientResponseBodySize is the metric conforming to the
-	// "http.client.response.body.size" semantic conventions. It represents the
-	// size of HTTP client response bodies.
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	HTTPClientResponseBodySizeName        = "http.client.response.body.size"
-	HTTPClientResponseBodySizeUnit        = "By"
-	HTTPClientResponseBodySizeDescription = "Size of HTTP client response bodies."
-
-	// HTTPClientOpenConnections is the metric conforming to the
-	// "http.client.open_connections" semantic conventions. It represents the
-	// number of outbound HTTP connections that are currently active or idle on the
-	// client.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	HTTPClientOpenConnectionsName        = "http.client.open_connections"
-	HTTPClientOpenConnectionsUnit        = "{connection}"
-	HTTPClientOpenConnectionsDescription = "Number of outbound HTTP connections that are currently active or idle on the client."
-
-	// HTTPClientConnectionDuration is the metric conforming to the
-	// "http.client.connection.duration" semantic conventions. It represents the
-	// duration of the successfully established outbound HTTP connections.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	HTTPClientConnectionDurationName        = "http.client.connection.duration"
-	HTTPClientConnectionDurationUnit        = "s"
-	HTTPClientConnectionDurationDescription = "The duration of the successfully established outbound HTTP connections."
-
-	// HTTPClientActiveRequests is the metric conforming to the
-	// "http.client.active_requests" semantic conventions. It represents the number
-	// of active HTTP requests.
-	// Instrument: updowncounter
-	// Unit: {request}
-	// Stability: Experimental
-	HTTPClientActiveRequestsName        = "http.client.active_requests"
-	HTTPClientActiveRequestsUnit        = "{request}"
-	HTTPClientActiveRequestsDescription = "Number of active HTTP requests."
-
-	// JvmMemoryInit is the metric conforming to the "jvm.memory.init" semantic
-	// conventions. It represents the measure of initial memory requested.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	JvmMemoryInitName        = "jvm.memory.init"
-	JvmMemoryInitUnit        = "By"
-	JvmMemoryInitDescription = "Measure of initial memory requested."
-
-	// JvmSystemCPUUtilization is the metric conforming to the
-	// "jvm.system.cpu.utilization" semantic conventions. It represents the recent
-	// CPU utilization for the whole system as reported by the JVM.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	JvmSystemCPUUtilizationName        = "jvm.system.cpu.utilization"
-	JvmSystemCPUUtilizationUnit        = "1"
-	JvmSystemCPUUtilizationDescription = "Recent CPU utilization for the whole system as reported by the JVM."
-
-	// JvmSystemCPULoad1m is the metric conforming to the "jvm.system.cpu.load_1m"
-	// semantic conventions. It represents the average CPU load of the whole system
-	// for the last minute as reported by the JVM.
-	// Instrument: gauge
-	// Unit: {run_queue_item}
-	// Stability: Experimental
-	JvmSystemCPULoad1mName        = "jvm.system.cpu.load_1m"
-	JvmSystemCPULoad1mUnit        = "{run_queue_item}"
-	JvmSystemCPULoad1mDescription = "Average CPU load of the whole system for the last minute as reported by the JVM."
-
-	// JvmBufferMemoryUsage is the metric conforming to the
-	// "jvm.buffer.memory.usage" semantic conventions. It represents the measure of
-	// memory used by buffers.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	JvmBufferMemoryUsageName        = "jvm.buffer.memory.usage"
-	JvmBufferMemoryUsageUnit        = "By"
-	JvmBufferMemoryUsageDescription = "Measure of memory used by buffers."
-
-	// JvmBufferMemoryLimit is the metric conforming to the
-	// "jvm.buffer.memory.limit" semantic conventions. It represents the measure of
-	// total memory capacity of buffers.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	JvmBufferMemoryLimitName        = "jvm.buffer.memory.limit"
-	JvmBufferMemoryLimitUnit        = "By"
-	JvmBufferMemoryLimitDescription = "Measure of total memory capacity of buffers."
-
-	// JvmBufferCount is the metric conforming to the "jvm.buffer.count" semantic
-	// conventions. It represents the number of buffers in the pool.
-	// Instrument: updowncounter
-	// Unit: {buffer}
-	// Stability: Experimental
-	JvmBufferCountName        = "jvm.buffer.count"
-	JvmBufferCountUnit        = "{buffer}"
-	JvmBufferCountDescription = "Number of buffers in the pool."
-
-	// JvmMemoryUsed is the metric conforming to the "jvm.memory.used" semantic
-	// conventions. It represents the measure of memory used.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Stable
-	JvmMemoryUsedName        = "jvm.memory.used"
-	JvmMemoryUsedUnit        = "By"
-	JvmMemoryUsedDescription = "Measure of memory used."
-
-	// JvmMemoryCommitted is the metric conforming to the "jvm.memory.committed"
-	// semantic conventions. It represents the measure of memory committed.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Stable
-	JvmMemoryCommittedName        = "jvm.memory.committed"
-	JvmMemoryCommittedUnit        = "By"
-	JvmMemoryCommittedDescription = "Measure of memory committed."
-
-	// JvmMemoryLimit is the metric conforming to the "jvm.memory.limit" semantic
-	// conventions. It represents the measure of max obtainable memory.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Stable
-	JvmMemoryLimitName        = "jvm.memory.limit"
-	JvmMemoryLimitUnit        = "By"
-	JvmMemoryLimitDescription = "Measure of max obtainable memory."
-
-	// JvmMemoryUsedAfterLastGc is the metric conforming to the
-	// "jvm.memory.used_after_last_gc" semantic conventions. It represents the
-	// measure of memory used, as measured after the most recent garbage collection
-	// event on this pool.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Stable
-	JvmMemoryUsedAfterLastGcName        = "jvm.memory.used_after_last_gc"
-	JvmMemoryUsedAfterLastGcUnit        = "By"
-	JvmMemoryUsedAfterLastGcDescription = "Measure of memory used, as measured after the most recent garbage collection event on this pool."
-
-	// JvmGcDuration is the metric conforming to the "jvm.gc.duration" semantic
-	// conventions. It represents the duration of JVM garbage collection actions.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Stable
-	JvmGcDurationName        = "jvm.gc.duration"
-	JvmGcDurationUnit        = "s"
-	JvmGcDurationDescription = "Duration of JVM garbage collection actions."
-
-	// JvmThreadCount is the metric conforming to the "jvm.thread.count" semantic
-	// conventions. It represents the number of executing platform threads.
-	// Instrument: updowncounter
-	// Unit: {thread}
-	// Stability: Stable
-	JvmThreadCountName        = "jvm.thread.count"
-	JvmThreadCountUnit        = "{thread}"
-	JvmThreadCountDescription = "Number of executing platform threads."
-
-	// JvmClassLoaded is the metric conforming to the "jvm.class.loaded" semantic
-	// conventions. It represents the number of classes loaded since JVM start.
-	// Instrument: counter
-	// Unit: {class}
-	// Stability: Stable
-	JvmClassLoadedName        = "jvm.class.loaded"
-	JvmClassLoadedUnit        = "{class}"
-	JvmClassLoadedDescription = "Number of classes loaded since JVM start."
-
-	// JvmClassUnloaded is the metric conforming to the "jvm.class.unloaded"
-	// semantic conventions. It represents the number of classes unloaded since JVM
-	// start.
-	// Instrument: counter
-	// Unit: {class}
-	// Stability: Stable
-	JvmClassUnloadedName        = "jvm.class.unloaded"
-	JvmClassUnloadedUnit        = "{class}"
-	JvmClassUnloadedDescription = "Number of classes unloaded since JVM start."
-
-	// JvmClassCount is the metric conforming to the "jvm.class.count" semantic
-	// conventions. It represents the number of classes currently loaded.
-	// Instrument: updowncounter
-	// Unit: {class}
-	// Stability: Stable
-	JvmClassCountName        = "jvm.class.count"
-	JvmClassCountUnit        = "{class}"
-	JvmClassCountDescription = "Number of classes currently loaded."
-
-	// JvmCPUCount is the metric conforming to the "jvm.cpu.count" semantic
-	// conventions. It represents the number of processors available to the Java
-	// virtual machine.
-	// Instrument: updowncounter
-	// Unit: {cpu}
-	// Stability: Stable
-	JvmCPUCountName        = "jvm.cpu.count"
-	JvmCPUCountUnit        = "{cpu}"
-	JvmCPUCountDescription = "Number of processors available to the Java virtual machine."
-
-	// JvmCPUTime is the metric conforming to the "jvm.cpu.time" semantic
-	// conventions. It represents the cPU time used by the process as reported by
-	// the JVM.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Stable
-	JvmCPUTimeName        = "jvm.cpu.time"
-	JvmCPUTimeUnit        = "s"
-	JvmCPUTimeDescription = "CPU time used by the process as reported by the JVM."
-
-	// JvmCPURecentUtilization is the metric conforming to the
-	// "jvm.cpu.recent_utilization" semantic conventions. It represents the recent
-	// CPU utilization for the process as reported by the JVM.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Stable
-	JvmCPURecentUtilizationName        = "jvm.cpu.recent_utilization"
-	JvmCPURecentUtilizationUnit        = "1"
-	JvmCPURecentUtilizationDescription = "Recent CPU utilization for the process as reported by the JVM."
-
-	// MessagingPublishDuration is the metric conforming to the
-	// "messaging.publish.duration" semantic conventions. It represents the
-	// measures the duration of publish operation.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	MessagingPublishDurationName        = "messaging.publish.duration"
-	MessagingPublishDurationUnit        = "s"
-	MessagingPublishDurationDescription = "Measures the duration of publish operation."
-
-	// MessagingReceiveDuration is the metric conforming to the
-	// "messaging.receive.duration" semantic conventions. It represents the
-	// measures the duration of receive operation.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	MessagingReceiveDurationName        = "messaging.receive.duration"
-	MessagingReceiveDurationUnit        = "s"
-	MessagingReceiveDurationDescription = "Measures the duration of receive operation."
-
-	// MessagingProcessDuration is the metric conforming to the
-	// "messaging.process.duration" semantic conventions. It represents the
-	// measures the duration of process operation.
-	// Instrument: histogram
-	// Unit: s
-	// Stability: Experimental
-	MessagingProcessDurationName        = "messaging.process.duration"
-	MessagingProcessDurationUnit        = "s"
-	MessagingProcessDurationDescription = "Measures the duration of process operation."
-
-	// MessagingPublishMessages is the metric conforming to the
-	// "messaging.publish.messages" semantic conventions. It represents the
-	// measures the number of published messages.
-	// Instrument: counter
-	// Unit: {message}
-	// Stability: Experimental
-	MessagingPublishMessagesName        = "messaging.publish.messages"
-	MessagingPublishMessagesUnit        = "{message}"
-	MessagingPublishMessagesDescription = "Measures the number of published messages."
-
-	// MessagingReceiveMessages is the metric conforming to the
-	// "messaging.receive.messages" semantic conventions. It represents the
-	// measures the number of received messages.
-	// Instrument: counter
-	// Unit: {message}
-	// Stability: Experimental
-	MessagingReceiveMessagesName        = "messaging.receive.messages"
-	MessagingReceiveMessagesUnit        = "{message}"
-	MessagingReceiveMessagesDescription = "Measures the number of received messages."
-
-	// MessagingProcessMessages is the metric conforming to the
-	// "messaging.process.messages" semantic conventions. It represents the
-	// measures the number of processed messages.
-	// Instrument: counter
-	// Unit: {message}
-	// Stability: Experimental
-	MessagingProcessMessagesName        = "messaging.process.messages"
-	MessagingProcessMessagesUnit        = "{message}"
-	MessagingProcessMessagesDescription = "Measures the number of processed messages."
-
-	// ProcessCPUTime is the metric conforming to the "process.cpu.time" semantic
-	// conventions. It represents the total CPU seconds broken down by different
-	// states.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Experimental
-	ProcessCPUTimeName        = "process.cpu.time"
-	ProcessCPUTimeUnit        = "s"
-	ProcessCPUTimeDescription = "Total CPU seconds broken down by different states."
-
-	// ProcessCPUUtilization is the metric conforming to the
-	// "process.cpu.utilization" semantic conventions. It represents the difference
-	// in process.cpu.time since the last measurement, divided by the elapsed time
-	// and number of CPUs available to the process.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	ProcessCPUUtilizationName        = "process.cpu.utilization"
-	ProcessCPUUtilizationUnit        = "1"
-	ProcessCPUUtilizationDescription = "Difference in process.cpu.time since the last measurement, divided by the elapsed time and number of CPUs available to the process."
-
-	// ProcessMemoryUsage is the metric conforming to the "process.memory.usage"
-	// semantic conventions. It represents the amount of physical memory in use.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	ProcessMemoryUsageName        = "process.memory.usage"
-	ProcessMemoryUsageUnit        = "By"
-	ProcessMemoryUsageDescription = "The amount of physical memory in use."
-
-	// ProcessMemoryVirtual is the metric conforming to the
-	// "process.memory.virtual" semantic conventions. It represents the amount of
-	// committed virtual memory.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	ProcessMemoryVirtualName        = "process.memory.virtual"
-	ProcessMemoryVirtualUnit        = "By"
-	ProcessMemoryVirtualDescription = "The amount of committed virtual memory."
-
-	// ProcessDiskIo is the metric conforming to the "process.disk.io" semantic
-	// conventions. It represents the disk bytes transferred.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	ProcessDiskIoName        = "process.disk.io"
-	ProcessDiskIoUnit        = "By"
-	ProcessDiskIoDescription = "Disk bytes transferred."
-
-	// ProcessNetworkIo is the metric conforming to the "process.network.io"
-	// semantic conventions. It represents the network bytes transferred.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	ProcessNetworkIoName        = "process.network.io"
-	ProcessNetworkIoUnit        = "By"
-	ProcessNetworkIoDescription = "Network bytes transferred."
-
-	// ProcessThreadCount is the metric conforming to the "process.thread.count"
-	// semantic conventions. It represents the process threads count.
-	// Instrument: updowncounter
-	// Unit: {thread}
-	// Stability: Experimental
-	ProcessThreadCountName        = "process.thread.count"
-	ProcessThreadCountUnit        = "{thread}"
-	ProcessThreadCountDescription = "Process threads count."
-
-	// ProcessOpenFileDescriptorCount is the metric conforming to the
-	// "process.open_file_descriptor.count" semantic conventions. It represents the
-	// number of file descriptors in use by the process.
-	// Instrument: updowncounter
-	// Unit: {count}
-	// Stability: Experimental
-	ProcessOpenFileDescriptorCountName        = "process.open_file_descriptor.count"
-	ProcessOpenFileDescriptorCountUnit        = "{count}"
-	ProcessOpenFileDescriptorCountDescription = "Number of file descriptors in use by the process."
-
-	// ProcessContextSwitches is the metric conforming to the
-	// "process.context_switches" semantic conventions. It represents the number of
-	// times the process has been context switched.
-	// Instrument: counter
-	// Unit: {count}
-	// Stability: Experimental
-	ProcessContextSwitchesName        = "process.context_switches"
-	ProcessContextSwitchesUnit        = "{count}"
-	ProcessContextSwitchesDescription = "Number of times the process has been context switched."
-
-	// ProcessPagingFaults is the metric conforming to the "process.paging.faults"
-	// semantic conventions. It represents the number of page faults the process
-	// has made.
-	// Instrument: counter
-	// Unit: {fault}
-	// Stability: Experimental
-	ProcessPagingFaultsName        = "process.paging.faults"
-	ProcessPagingFaultsUnit        = "{fault}"
-	ProcessPagingFaultsDescription = "Number of page faults the process has made."
-
-	// RPCServerDuration is the metric conforming to the "rpc.server.duration"
-	// semantic conventions. It represents the measures the duration of inbound
-	// RPC.
-	// Instrument: histogram
-	// Unit: ms
-	// Stability: Experimental
-	RPCServerDurationName        = "rpc.server.duration"
-	RPCServerDurationUnit        = "ms"
-	RPCServerDurationDescription = "Measures the duration of inbound RPC."
-
-	// RPCServerRequestSize is the metric conforming to the
-	// "rpc.server.request.size" semantic conventions. It represents the measures
-	// the size of RPC request messages (uncompressed).
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	RPCServerRequestSizeName        = "rpc.server.request.size"
-	RPCServerRequestSizeUnit        = "By"
-	RPCServerRequestSizeDescription = "Measures the size of RPC request messages (uncompressed)."
-
-	// RPCServerResponseSize is the metric conforming to the
-	// "rpc.server.response.size" semantic conventions. It represents the measures
-	// the size of RPC response messages (uncompressed).
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	RPCServerResponseSizeName        = "rpc.server.response.size"
-	RPCServerResponseSizeUnit        = "By"
-	RPCServerResponseSizeDescription = "Measures the size of RPC response messages (uncompressed)."
-
-	// RPCServerRequestsPerRPC is the metric conforming to the
-	// "rpc.server.requests_per_rpc" semantic conventions. It represents the
-	// measures the number of messages received per RPC.
-	// Instrument: histogram
-	// Unit: {count}
-	// Stability: Experimental
-	RPCServerRequestsPerRPCName        = "rpc.server.requests_per_rpc"
-	RPCServerRequestsPerRPCUnit        = "{count}"
-	RPCServerRequestsPerRPCDescription = "Measures the number of messages received per RPC."
-
-	// RPCServerResponsesPerRPC is the metric conforming to the
-	// "rpc.server.responses_per_rpc" semantic conventions. It represents the
-	// measures the number of messages sent per RPC.
-	// Instrument: histogram
-	// Unit: {count}
-	// Stability: Experimental
-	RPCServerResponsesPerRPCName        = "rpc.server.responses_per_rpc"
-	RPCServerResponsesPerRPCUnit        = "{count}"
-	RPCServerResponsesPerRPCDescription = "Measures the number of messages sent per RPC."
-
-	// RPCClientDuration is the metric conforming to the "rpc.client.duration"
-	// semantic conventions. It represents the measures the duration of outbound
-	// RPC.
-	// Instrument: histogram
-	// Unit: ms
-	// Stability: Experimental
-	RPCClientDurationName        = "rpc.client.duration"
-	RPCClientDurationUnit        = "ms"
-	RPCClientDurationDescription = "Measures the duration of outbound RPC."
-
-	// RPCClientRequestSize is the metric conforming to the
-	// "rpc.client.request.size" semantic conventions. It represents the measures
-	// the size of RPC request messages (uncompressed).
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	RPCClientRequestSizeName        = "rpc.client.request.size"
-	RPCClientRequestSizeUnit        = "By"
-	RPCClientRequestSizeDescription = "Measures the size of RPC request messages (uncompressed)."
-
-	// RPCClientResponseSize is the metric conforming to the
-	// "rpc.client.response.size" semantic conventions. It represents the measures
-	// the size of RPC response messages (uncompressed).
-	// Instrument: histogram
-	// Unit: By
-	// Stability: Experimental
-	RPCClientResponseSizeName        = "rpc.client.response.size"
-	RPCClientResponseSizeUnit        = "By"
-	RPCClientResponseSizeDescription = "Measures the size of RPC response messages (uncompressed)."
-
-	// RPCClientRequestsPerRPC is the metric conforming to the
-	// "rpc.client.requests_per_rpc" semantic conventions. It represents the
-	// measures the number of messages received per RPC.
-	// Instrument: histogram
-	// Unit: {count}
-	// Stability: Experimental
-	RPCClientRequestsPerRPCName        = "rpc.client.requests_per_rpc"
-	RPCClientRequestsPerRPCUnit        = "{count}"
-	RPCClientRequestsPerRPCDescription = "Measures the number of messages received per RPC."
-
-	// RPCClientResponsesPerRPC is the metric conforming to the
-	// "rpc.client.responses_per_rpc" semantic conventions. It represents the
-	// measures the number of messages sent per RPC.
-	// Instrument: histogram
-	// Unit: {count}
-	// Stability: Experimental
-	RPCClientResponsesPerRPCName        = "rpc.client.responses_per_rpc"
-	RPCClientResponsesPerRPCUnit        = "{count}"
-	RPCClientResponsesPerRPCDescription = "Measures the number of messages sent per RPC."
-
-	// SystemCPUTime is the metric conforming to the "system.cpu.time" semantic
-	// conventions. It represents the seconds each logical CPU spent on each mode.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Experimental
-	SystemCPUTimeName        = "system.cpu.time"
-	SystemCPUTimeUnit        = "s"
-	SystemCPUTimeDescription = "Seconds each logical CPU spent on each mode"
-
-	// SystemCPUUtilization is the metric conforming to the
-	// "system.cpu.utilization" semantic conventions. It represents the difference
-	// in system.cpu.time since the last measurement, divided by the elapsed time
-	// and number of logical CPUs.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	SystemCPUUtilizationName        = "system.cpu.utilization"
-	SystemCPUUtilizationUnit        = "1"
-	SystemCPUUtilizationDescription = "Difference in system.cpu.time since the last measurement, divided by the elapsed time and number of logical CPUs"
-
-	// SystemCPUFrequency is the metric conforming to the "system.cpu.frequency"
-	// semantic conventions. It represents the reports the current frequency of the
-	// CPU in Hz.
-	// Instrument: gauge
-	// Unit: {Hz}
-	// Stability: Experimental
-	SystemCPUFrequencyName        = "system.cpu.frequency"
-	SystemCPUFrequencyUnit        = "{Hz}"
-	SystemCPUFrequencyDescription = "Reports the current frequency of the CPU in Hz"
-
-	// SystemCPUPhysicalCount is the metric conforming to the
-	// "system.cpu.physical.count" semantic conventions. It represents the reports
-	// the number of actual physical processor cores on the hardware.
-	// Instrument: updowncounter
-	// Unit: {cpu}
-	// Stability: Experimental
-	SystemCPUPhysicalCountName        = "system.cpu.physical.count"
-	SystemCPUPhysicalCountUnit        = "{cpu}"
-	SystemCPUPhysicalCountDescription = "Reports the number of actual physical processor cores on the hardware"
-
-	// SystemCPULogicalCount is the metric conforming to the
-	// "system.cpu.logical.count" semantic conventions. It represents the reports
-	// the number of logical (virtual) processor cores created by the operating
-	// system to manage multitasking.
-	// Instrument: updowncounter
-	// Unit: {cpu}
-	// Stability: Experimental
-	SystemCPULogicalCountName        = "system.cpu.logical.count"
-	SystemCPULogicalCountUnit        = "{cpu}"
-	SystemCPULogicalCountDescription = "Reports the number of logical (virtual) processor cores created by the operating system to manage multitasking"
-
-	// SystemMemoryUsage is the metric conforming to the "system.memory.usage"
-	// semantic conventions. It represents the reports memory in use by state.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	SystemMemoryUsageName        = "system.memory.usage"
-	SystemMemoryUsageUnit        = "By"
-	SystemMemoryUsageDescription = "Reports memory in use by state."
-
-	// SystemMemoryLimit is the metric conforming to the "system.memory.limit"
-	// semantic conventions. It represents the total memory available in the
-	// system.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	SystemMemoryLimitName        = "system.memory.limit"
-	SystemMemoryLimitUnit        = "By"
-	SystemMemoryLimitDescription = "Total memory available in the system."
-
-	// SystemMemoryShared is the metric conforming to the "system.memory.shared"
-	// semantic conventions. It represents the shared memory used (mostly by
-	// tmpfs).
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	SystemMemorySharedName        = "system.memory.shared"
-	SystemMemorySharedUnit        = "By"
-	SystemMemorySharedDescription = "Shared memory used (mostly by tmpfs)."
-
-	// SystemMemoryUtilization is the metric conforming to the
-	// "system.memory.utilization" semantic conventions.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemMemoryUtilizationName = "system.memory.utilization"
-	SystemMemoryUtilizationUnit = "1"
-
-	// SystemPagingUsage is the metric conforming to the "system.paging.usage"
-	// semantic conventions. It represents the unix swap or windows pagefile usage.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	SystemPagingUsageName        = "system.paging.usage"
-	SystemPagingUsageUnit        = "By"
-	SystemPagingUsageDescription = "Unix swap or windows pagefile usage"
-
-	// SystemPagingUtilization is the metric conforming to the
-	// "system.paging.utilization" semantic conventions.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemPagingUtilizationName = "system.paging.utilization"
-	SystemPagingUtilizationUnit = "1"
-
-	// SystemPagingFaults is the metric conforming to the "system.paging.faults"
-	// semantic conventions.
-	// Instrument: counter
-	// Unit: {fault}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemPagingFaultsName = "system.paging.faults"
-	SystemPagingFaultsUnit = "{fault}"
-
-	// SystemPagingOperations is the metric conforming to the
-	// "system.paging.operations" semantic conventions.
-	// Instrument: counter
-	// Unit: {operation}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemPagingOperationsName = "system.paging.operations"
-	SystemPagingOperationsUnit = "{operation}"
-
-	// SystemDiskIo is the metric conforming to the "system.disk.io" semantic
-	// conventions.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemDiskIoName = "system.disk.io"
-	SystemDiskIoUnit = "By"
-
-	// SystemDiskOperations is the metric conforming to the
-	// "system.disk.operations" semantic conventions.
-	// Instrument: counter
-	// Unit: {operation}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemDiskOperationsName = "system.disk.operations"
-	SystemDiskOperationsUnit = "{operation}"
-
-	// SystemDiskIoTime is the metric conforming to the "system.disk.io_time"
-	// semantic conventions. It represents the time disk spent activated.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Experimental
-	SystemDiskIoTimeName        = "system.disk.io_time"
-	SystemDiskIoTimeUnit        = "s"
-	SystemDiskIoTimeDescription = "Time disk spent activated"
-
-	// SystemDiskOperationTime is the metric conforming to the
-	// "system.disk.operation_time" semantic conventions. It represents the sum of
-	// the time each operation took to complete.
-	// Instrument: counter
-	// Unit: s
-	// Stability: Experimental
-	SystemDiskOperationTimeName        = "system.disk.operation_time"
-	SystemDiskOperationTimeUnit        = "s"
-	SystemDiskOperationTimeDescription = "Sum of the time each operation took to complete"
-
-	// SystemDiskMerged is the metric conforming to the "system.disk.merged"
-	// semantic conventions.
-	// Instrument: counter
-	// Unit: {operation}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemDiskMergedName = "system.disk.merged"
-	SystemDiskMergedUnit = "{operation}"
-
-	// SystemFilesystemUsage is the metric conforming to the
-	// "system.filesystem.usage" semantic conventions.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemFilesystemUsageName = "system.filesystem.usage"
-	SystemFilesystemUsageUnit = "By"
-
-	// SystemFilesystemUtilization is the metric conforming to the
-	// "system.filesystem.utilization" semantic conventions.
-	// Instrument: gauge
-	// Unit: 1
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemFilesystemUtilizationName = "system.filesystem.utilization"
-	SystemFilesystemUtilizationUnit = "1"
-
-	// SystemNetworkDropped is the metric conforming to the
-	// "system.network.dropped" semantic conventions. It represents the count of
-	// packets that are dropped or discarded even though there was no error.
-	// Instrument: counter
-	// Unit: {packet}
-	// Stability: Experimental
-	SystemNetworkDroppedName        = "system.network.dropped"
-	SystemNetworkDroppedUnit        = "{packet}"
-	SystemNetworkDroppedDescription = "Count of packets that are dropped or discarded even though there was no error"
-
-	// SystemNetworkPackets is the metric conforming to the
-	// "system.network.packets" semantic conventions.
-	// Instrument: counter
-	// Unit: {packet}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemNetworkPacketsName = "system.network.packets"
-	SystemNetworkPacketsUnit = "{packet}"
-
-	// SystemNetworkErrors is the metric conforming to the "system.network.errors"
-	// semantic conventions. It represents the count of network errors detected.
-	// Instrument: counter
-	// Unit: {error}
-	// Stability: Experimental
-	SystemNetworkErrorsName        = "system.network.errors"
-	SystemNetworkErrorsUnit        = "{error}"
-	SystemNetworkErrorsDescription = "Count of network errors detected"
-
-	// SystemNetworkIo is the metric conforming to the "system.network.io" semantic
-	// conventions.
-	// Instrument: counter
-	// Unit: By
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemNetworkIoName = "system.network.io"
-	SystemNetworkIoUnit = "By"
-
-	// SystemNetworkConnections is the metric conforming to the
-	// "system.network.connections" semantic conventions.
-	// Instrument: updowncounter
-	// Unit: {connection}
-	// Stability: Experimental
-	// NOTE: The description (brief) for this metric is not defined in the semantic-conventions repository.
-	SystemNetworkConnectionsName = "system.network.connections"
-	SystemNetworkConnectionsUnit = "{connection}"
-
-	// SystemProcessCount is the metric conforming to the "system.process.count"
-	// semantic conventions. It represents the total number of processes in each
-	// state.
-	// Instrument: updowncounter
-	// Unit: {process}
-	// Stability: Experimental
-	SystemProcessCountName        = "system.process.count"
-	SystemProcessCountUnit        = "{process}"
-	SystemProcessCountDescription = "Total number of processes in each state"
-
-	// SystemProcessCreated is the metric conforming to the
-	// "system.process.created" semantic conventions. It represents the total
-	// number of processes created over uptime of the host.
-	// Instrument: counter
-	// Unit: {process}
-	// Stability: Experimental
-	SystemProcessCreatedName        = "system.process.created"
-	SystemProcessCreatedUnit        = "{process}"
-	SystemProcessCreatedDescription = "Total number of processes created over uptime of the host"
-
-	// SystemLinuxMemoryAvailable is the metric conforming to the
-	// "system.linux.memory.available" semantic conventions. It represents an
-	// estimate of how much memory is available for starting new applications,
-	// without causing swapping.
-	// Instrument: updowncounter
-	// Unit: By
-	// Stability: Experimental
-	SystemLinuxMemoryAvailableName        = "system.linux.memory.available"
-	SystemLinuxMemoryAvailableUnit        = "By"
-	SystemLinuxMemoryAvailableDescription = "An estimate of how much memory is available for starting new applications, without causing swapping"
-)
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/schema.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/schema.go
deleted file mode 100644
index 4c87c7ad..00000000
--- a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.26.0/schema.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright The OpenTelemetry Authors
-// SPDX-License-Identifier: Apache-2.0
-
-package semconv // import "go.opentelemetry.io/otel/semconv/v1.26.0"
-
-// SchemaURL is the schema URL that matches the version of the semantic conventions
-// that this package defines. Semconv packages starting from v1.4.0 must declare
-// non-empty schema URL in the form https://opentelemetry.io/schemas/
-const SchemaURL = "https://opentelemetry.io/schemas/1.26.0"
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/MIGRATION.md b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/MIGRATION.md
new file mode 100644
index 00000000..02b56115
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/MIGRATION.md
@@ -0,0 +1,4 @@
+
+# Migration from v1.33.0 to v1.34.0
+
+The `go.opentelemetry.io/otel/semconv/v1.34.0` package should be a drop-in replacement for `go.opentelemetry.io/otel/semconv/v1.33.0`.
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/README.md b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/README.md
new file mode 100644
index 00000000..fab06c97
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/README.md
@@ -0,0 +1,3 @@
+# Semconv v1.34.0
+
+[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.34.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.34.0)
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/attribute_group.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/attribute_group.go
new file mode 100644
index 00000000..5b566625
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/attribute_group.go
@@ -0,0 +1,13851 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+// Code generated from semantic convention specification. DO NOT EDIT.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
+
+import "go.opentelemetry.io/otel/attribute"
+
+// Namespace: android
+const (
+	// AndroidAppStateKey is the attribute Key conforming to the "android.app.state"
+	// semantic conventions. It represents the this attribute represents the state
+	// of the application.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "created"
+	// Note: The Android lifecycle states are defined in
+	// [Activity lifecycle callbacks], and from which the `OS identifiers` are
+	// derived.
+	//
+	// [Activity lifecycle callbacks]: https://developer.android.com/guide/components/activities/activity-lifecycle#lc
+	AndroidAppStateKey = attribute.Key("android.app.state")
+
+	// AndroidOSAPILevelKey is the attribute Key conforming to the
+	// "android.os.api_level" semantic conventions. It represents the uniquely
+	// identifies the framework API revision offered by a version (`os.version`) of
+	// the android operating system. More information can be found [here].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "33", "32"
+	//
+	// [here]: https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels
+	AndroidOSAPILevelKey = attribute.Key("android.os.api_level")
+)
+
+// AndroidOSAPILevel returns an attribute KeyValue conforming to the
+// "android.os.api_level" semantic conventions. It represents the uniquely
+// identifies the framework API revision offered by a version (`os.version`) of
+// the android operating system. More information can be found [here].
+//
+// [here]: https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels
+func AndroidOSAPILevel(val string) attribute.KeyValue {
+	return AndroidOSAPILevelKey.String(val)
+}
+
+// Enum values for android.app.state
+var (
+	// Any time before Activity.onResume() or, if the app has no Activity,
+	// Context.startService() has been called in the app for the first time.
+	//
+	// Stability: development
+	AndroidAppStateCreated = AndroidAppStateKey.String("created")
+	// Any time after Activity.onPause() or, if the app has no Activity,
+	// Context.stopService() has been called when the app was in the foreground
+	// state.
+	//
+	// Stability: development
+	AndroidAppStateBackground = AndroidAppStateKey.String("background")
+	// Any time after Activity.onResume() or, if the app has no Activity,
+	// Context.startService() has been called when the app was in either the created
+	// or background states.
+	//
+	// Stability: development
+	AndroidAppStateForeground = AndroidAppStateKey.String("foreground")
+)
+
+// Namespace: app
+const (
+	// AppInstallationIDKey is the attribute Key conforming to the
+	// "app.installation.id" semantic conventions. It represents a unique identifier
+	// representing the installation of an application on a specific device.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2ab2916d-a51f-4ac8-80ee-45ac31a28092"
+	// Note: Its value SHOULD persist across launches of the same application
+	// installation, including through application upgrades.
+	// It SHOULD change if the application is uninstalled or if all applications of
+	// the vendor are uninstalled.
+	// Additionally, users might be able to reset this value (e.g. by clearing
+	// application data).
+	// If an app is installed multiple times on the same device (e.g. in different
+	// accounts on Android), each `app.installation.id` SHOULD have a different
+	// value.
+	// If multiple OpenTelemetry SDKs are used within the same application, they
+	// SHOULD use the same value for `app.installation.id`.
+	// Hardware IDs (e.g. serial number, IMEI, MAC address) MUST NOT be used as the
+	// `app.installation.id`.
+	//
+	// For iOS, this value SHOULD be equal to the [vendor identifier].
+	//
+	// For Android, examples of `app.installation.id` implementations include:
+	//
+	//   - [Firebase Installation ID].
+	//   - A globally unique UUID which is persisted across sessions in your
+	//     application.
+	//   - [App set ID].
+	//   - [`Settings.getString(Settings.Secure.ANDROID_ID)`].
+	//
+	// More information about Android identifier best practices can be found [here]
+	// .
+	//
+	// [vendor identifier]: https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor
+	// [Firebase Installation ID]: https://firebase.google.com/docs/projects/manage-installations
+	// [App set ID]: https://developer.android.com/identity/app-set-id
+	// [`Settings.getString(Settings.Secure.ANDROID_ID)`]: https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID
+	// [here]: https://developer.android.com/training/articles/user-data-ids
+	AppInstallationIDKey = attribute.Key("app.installation.id")
+
+	// AppScreenCoordinateXKey is the attribute Key conforming to the
+	// "app.screen.coordinate.x" semantic conventions. It represents the x
+	// (horizontal) coordinate of a screen coordinate, in screen pixels.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0, 131
+	AppScreenCoordinateXKey = attribute.Key("app.screen.coordinate.x")
+
+	// AppScreenCoordinateYKey is the attribute Key conforming to the
+	// "app.screen.coordinate.y" semantic conventions. It represents the y
+	// (vertical) component of a screen coordinate, in screen pixels.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 12, 99
+	AppScreenCoordinateYKey = attribute.Key("app.screen.coordinate.y")
+
+	// AppWidgetIDKey is the attribute Key conforming to the "app.widget.id"
+	// semantic conventions. It represents an identifier that uniquely
+	// differentiates this widget from other widgets in the same application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "f9bc787d-ff05-48ad-90e1-fca1d46130b3", "submit_order_1829"
+	// Note: A widget is an application component, typically an on-screen visual GUI
+	// element.
+	AppWidgetIDKey = attribute.Key("app.widget.id")
+
+	// AppWidgetNameKey is the attribute Key conforming to the "app.widget.name"
+	// semantic conventions. It represents the name of an application widget.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "submit", "attack", "Clear Cart"
+	// Note: A widget is an application component, typically an on-screen visual GUI
+	// element.
+	AppWidgetNameKey = attribute.Key("app.widget.name")
+)
+
+// AppInstallationID returns an attribute KeyValue conforming to the
+// "app.installation.id" semantic conventions. It represents a unique identifier
+// representing the installation of an application on a specific device.
+func AppInstallationID(val string) attribute.KeyValue {
+	return AppInstallationIDKey.String(val)
+}
+
+// AppScreenCoordinateX returns an attribute KeyValue conforming to the
+// "app.screen.coordinate.x" semantic conventions. It represents the x
+// (horizontal) coordinate of a screen coordinate, in screen pixels.
+func AppScreenCoordinateX(val int) attribute.KeyValue {
+	return AppScreenCoordinateXKey.Int(val)
+}
+
+// AppScreenCoordinateY returns an attribute KeyValue conforming to the
+// "app.screen.coordinate.y" semantic conventions. It represents the y (vertical)
+// component of a screen coordinate, in screen pixels.
+func AppScreenCoordinateY(val int) attribute.KeyValue {
+	return AppScreenCoordinateYKey.Int(val)
+}
+
+// AppWidgetID returns an attribute KeyValue conforming to the "app.widget.id"
+// semantic conventions. It represents an identifier that uniquely differentiates
+// this widget from other widgets in the same application.
+func AppWidgetID(val string) attribute.KeyValue {
+	return AppWidgetIDKey.String(val)
+}
+
+// AppWidgetName returns an attribute KeyValue conforming to the
+// "app.widget.name" semantic conventions. It represents the name of an
+// application widget.
+func AppWidgetName(val string) attribute.KeyValue {
+	return AppWidgetNameKey.String(val)
+}
+
+// Namespace: artifact
+const (
+	// ArtifactAttestationFilenameKey is the attribute Key conforming to the
+	// "artifact.attestation.filename" semantic conventions. It represents the
+	// provenance filename of the built attestation which directly relates to the
+	// build artifact filename. This filename SHOULD accompany the artifact at
+	// publish time. See the [SLSA Relationship] specification for more information.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "golang-binary-amd64-v0.1.0.attestation",
+	// "docker-image-amd64-v0.1.0.intoto.json1", "release-1.tar.gz.attestation",
+	// "file-name-package.tar.gz.intoto.json1"
+	//
+	// [SLSA Relationship]: https://slsa.dev/spec/v1.0/distributing-provenance#relationship-between-artifacts-and-attestations
+	ArtifactAttestationFilenameKey = attribute.Key("artifact.attestation.filename")
+
+	// ArtifactAttestationHashKey is the attribute Key conforming to the
+	// "artifact.attestation.hash" semantic conventions. It represents the full
+	// [hash value (see glossary)], of the built attestation. Some envelopes in the
+	// [software attestation space] also refer to this as the **digest**.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1b31dfcd5b7f9267bf2ff47651df1cfb9147b9e4df1f335accf65b4cda498408"
+	//
+	// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+	// [software attestation space]: https://github.com/in-toto/attestation/tree/main/spec
+	ArtifactAttestationHashKey = attribute.Key("artifact.attestation.hash")
+
+	// ArtifactAttestationIDKey is the attribute Key conforming to the
+	// "artifact.attestation.id" semantic conventions. It represents the id of the
+	// build [software attestation].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "123"
+	//
+	// [software attestation]: https://slsa.dev/attestation-model
+	ArtifactAttestationIDKey = attribute.Key("artifact.attestation.id")
+
+	// ArtifactFilenameKey is the attribute Key conforming to the
+	// "artifact.filename" semantic conventions. It represents the human readable
+	// file name of the artifact, typically generated during build and release
+	// processes. Often includes the package name and version in the file name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "golang-binary-amd64-v0.1.0", "docker-image-amd64-v0.1.0",
+	// "release-1.tar.gz", "file-name-package.tar.gz"
+	// Note: This file name can also act as the [Package Name]
+	// in cases where the package ecosystem maps accordingly.
+	// Additionally, the artifact [can be published]
+	// for others, but that is not a guarantee.
+	//
+	// [Package Name]: https://slsa.dev/spec/v1.0/terminology#package-model
+	// [can be published]: https://slsa.dev/spec/v1.0/terminology#software-supply-chain
+	ArtifactFilenameKey = attribute.Key("artifact.filename")
+
+	// ArtifactHashKey is the attribute Key conforming to the "artifact.hash"
+	// semantic conventions. It represents the full [hash value (see glossary)],
+	// often found in checksum.txt on a release of the artifact and used to verify
+	// package integrity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "9ff4c52759e2c4ac70b7d517bc7fcdc1cda631ca0045271ddd1b192544f8a3e9"
+	// Note: The specific algorithm used to create the cryptographic hash value is
+	// not defined. In situations where an artifact has multiple
+	// cryptographic hashes, it is up to the implementer to choose which
+	// hash value to set here; this should be the most secure hash algorithm
+	// that is suitable for the situation and consistent with the
+	// corresponding attestation. The implementer can then provide the other
+	// hash values through an additional set of attribute extensions as they
+	// deem necessary.
+	//
+	// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+	ArtifactHashKey = attribute.Key("artifact.hash")
+
+	// ArtifactPurlKey is the attribute Key conforming to the "artifact.purl"
+	// semantic conventions. It represents the [Package URL] of the
+	// [package artifact] provides a standard way to identify and locate the
+	// packaged artifact.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "pkg:github/package-url/purl-spec@1209109710924",
+	// "pkg:npm/foo@12.12.3"
+	//
+	// [Package URL]: https://github.com/package-url/purl-spec
+	// [package artifact]: https://slsa.dev/spec/v1.0/terminology#package-model
+	ArtifactPurlKey = attribute.Key("artifact.purl")
+
+	// ArtifactVersionKey is the attribute Key conforming to the "artifact.version"
+	// semantic conventions. It represents the version of the artifact.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "v0.1.0", "1.2.1", "122691-build"
+	ArtifactVersionKey = attribute.Key("artifact.version")
+)
+
+// ArtifactAttestationFilename returns an attribute KeyValue conforming to the
+// "artifact.attestation.filename" semantic conventions. It represents the
+// provenance filename of the built attestation which directly relates to the
+// build artifact filename. This filename SHOULD accompany the artifact at
+// publish time. See the [SLSA Relationship] specification for more information.
+//
+// [SLSA Relationship]: https://slsa.dev/spec/v1.0/distributing-provenance#relationship-between-artifacts-and-attestations
+func ArtifactAttestationFilename(val string) attribute.KeyValue {
+	return ArtifactAttestationFilenameKey.String(val)
+}
+
+// ArtifactAttestationHash returns an attribute KeyValue conforming to the
+// "artifact.attestation.hash" semantic conventions. It represents the full
+// [hash value (see glossary)], of the built attestation. Some envelopes in the
+// [software attestation space] also refer to this as the **digest**.
+//
+// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+// [software attestation space]: https://github.com/in-toto/attestation/tree/main/spec
+func ArtifactAttestationHash(val string) attribute.KeyValue {
+	return ArtifactAttestationHashKey.String(val)
+}
+
+// ArtifactAttestationID returns an attribute KeyValue conforming to the
+// "artifact.attestation.id" semantic conventions. It represents the id of the
+// build [software attestation].
+//
+// [software attestation]: https://slsa.dev/attestation-model
+func ArtifactAttestationID(val string) attribute.KeyValue {
+	return ArtifactAttestationIDKey.String(val)
+}
+
+// ArtifactFilename returns an attribute KeyValue conforming to the
+// "artifact.filename" semantic conventions. It represents the human readable
+// file name of the artifact, typically generated during build and release
+// processes. Often includes the package name and version in the file name.
+func ArtifactFilename(val string) attribute.KeyValue {
+	return ArtifactFilenameKey.String(val)
+}
+
+// ArtifactHash returns an attribute KeyValue conforming to the "artifact.hash"
+// semantic conventions. It represents the full [hash value (see glossary)],
+// often found in checksum.txt on a release of the artifact and used to verify
+// package integrity.
+//
+// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+func ArtifactHash(val string) attribute.KeyValue {
+	return ArtifactHashKey.String(val)
+}
+
+// ArtifactPurl returns an attribute KeyValue conforming to the "artifact.purl"
+// semantic conventions. It represents the [Package URL] of the
+// [package artifact] provides a standard way to identify and locate the packaged
+// artifact.
+//
+// [Package URL]: https://github.com/package-url/purl-spec
+// [package artifact]: https://slsa.dev/spec/v1.0/terminology#package-model
+func ArtifactPurl(val string) attribute.KeyValue {
+	return ArtifactPurlKey.String(val)
+}
+
+// ArtifactVersion returns an attribute KeyValue conforming to the
+// "artifact.version" semantic conventions. It represents the version of the
+// artifact.
+func ArtifactVersion(val string) attribute.KeyValue {
+	return ArtifactVersionKey.String(val)
+}
+
+// Namespace: aws
+const (
+	// AWSBedrockGuardrailIDKey is the attribute Key conforming to the
+	// "aws.bedrock.guardrail.id" semantic conventions. It represents the unique
+	// identifier of the AWS Bedrock Guardrail. A [guardrail] helps safeguard and
+	// prevent unwanted behavior from model responses or user messages.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "sgi5gkybzqak"
+	//
+	// [guardrail]: https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html
+	AWSBedrockGuardrailIDKey = attribute.Key("aws.bedrock.guardrail.id")
+
+	// AWSBedrockKnowledgeBaseIDKey is the attribute Key conforming to the
+	// "aws.bedrock.knowledge_base.id" semantic conventions. It represents the
+	// unique identifier of the AWS Bedrock Knowledge base. A [knowledge base] is a
+	// bank of information that can be queried by models to generate more relevant
+	// responses and augment prompts.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "XFWUPB9PAW"
+	//
+	// [knowledge base]: https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html
+	AWSBedrockKnowledgeBaseIDKey = attribute.Key("aws.bedrock.knowledge_base.id")
+
+	// AWSDynamoDBAttributeDefinitionsKey is the attribute Key conforming to the
+	// "aws.dynamodb.attribute_definitions" semantic conventions. It represents the
+	// JSON-serialized value of each item in the `AttributeDefinitions` request
+	// field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "AttributeName": "string", "AttributeType": "string" }"
+	AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions")
+
+	// AWSDynamoDBAttributesToGetKey is the attribute Key conforming to the
+	// "aws.dynamodb.attributes_to_get" semantic conventions. It represents the
+	// value of the `AttributesToGet` request parameter.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "lives", "id"
+	AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get")
+
+	// AWSDynamoDBConsistentReadKey is the attribute Key conforming to the
+	// "aws.dynamodb.consistent_read" semantic conventions. It represents the value
+	// of the `ConsistentRead` request parameter.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read")
+
+	// AWSDynamoDBConsumedCapacityKey is the attribute Key conforming to the
+	// "aws.dynamodb.consumed_capacity" semantic conventions. It represents the
+	// JSON-serialized value of each item in the `ConsumedCapacity` response field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" :
+	// { "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits":
+	// number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number,
+	// "ReadCapacityUnits": number, "WriteCapacityUnits": number } },
+	// "ReadCapacityUnits": number, "Table": { "CapacityUnits": number,
+	// "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName":
+	// "string", "WriteCapacityUnits": number }"
+	AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity")
+
+	// AWSDynamoDBCountKey is the attribute Key conforming to the
+	// "aws.dynamodb.count" semantic conventions. It represents the value of the
+	// `Count` response parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 10
+	AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count")
+
+	// AWSDynamoDBExclusiveStartTableKey is the attribute Key conforming to the
+	// "aws.dynamodb.exclusive_start_table" semantic conventions. It represents the
+	// value of the `ExclusiveStartTableName` request parameter.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Users", "CatsTable"
+	AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table")
+
+	// AWSDynamoDBGlobalSecondaryIndexUpdatesKey is the attribute Key conforming to
+	// the "aws.dynamodb.global_secondary_index_updates" semantic conventions. It
+	// represents the JSON-serialized value of each item in the
+	// `GlobalSecondaryIndexUpdates` request field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "Create": { "IndexName": "string", "KeySchema": [ {
+	// "AttributeName": "string", "KeyType": "string" } ], "Projection": {
+	// "NonKeyAttributes": [ "string" ], "ProjectionType": "string" },
+	// "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits":
+	// number } }"
+	AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates")
+
+	// AWSDynamoDBGlobalSecondaryIndexesKey is the attribute Key conforming to the
+	// "aws.dynamodb.global_secondary_indexes" semantic conventions. It represents
+	// the JSON-serialized value of each item of the `GlobalSecondaryIndexes`
+	// request field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "IndexName": "string", "KeySchema": [ { "AttributeName":
+	// "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [
+	// "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": {
+	// "ReadCapacityUnits": number, "WriteCapacityUnits": number } }"
+	AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes")
+
+	// AWSDynamoDBIndexNameKey is the attribute Key conforming to the
+	// "aws.dynamodb.index_name" semantic conventions. It represents the value of
+	// the `IndexName` request parameter.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "name_to_group"
+	AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name")
+
+	// AWSDynamoDBItemCollectionMetricsKey is the attribute Key conforming to the
+	// "aws.dynamodb.item_collection_metrics" semantic conventions. It represents
+	// the JSON-serialized value of the `ItemCollectionMetrics` response field.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob,
+	// "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" :
+	// "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S":
+	// "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }"
+	AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics")
+
+	// AWSDynamoDBLimitKey is the attribute Key conforming to the
+	// "aws.dynamodb.limit" semantic conventions. It represents the value of the
+	// `Limit` request parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 10
+	AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit")
+
+	// AWSDynamoDBLocalSecondaryIndexesKey is the attribute Key conforming to the
+	// "aws.dynamodb.local_secondary_indexes" semantic conventions. It represents
+	// the JSON-serialized value of each item of the `LocalSecondaryIndexes` request
+	// field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "{ "IndexArn": "string", "IndexName": "string", "IndexSizeBytes":
+	// number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string",
+	// "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ],
+	// "ProjectionType": "string" } }"
+	AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes")
+
+	// AWSDynamoDBProjectionKey is the attribute Key conforming to the
+	// "aws.dynamodb.projection" semantic conventions. It represents the value of
+	// the `ProjectionExpression` request parameter.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Title", "Title, Price, Color", "Title, Description, RelatedItems,
+	// ProductReviews"
+	AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection")
+
+	// AWSDynamoDBProvisionedReadCapacityKey is the attribute Key conforming to the
+	// "aws.dynamodb.provisioned_read_capacity" semantic conventions. It represents
+	// the value of the `ProvisionedThroughput.ReadCapacityUnits` request parameter.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1.0, 2.0
+	AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity")
+
+	// AWSDynamoDBProvisionedWriteCapacityKey is the attribute Key conforming to the
+	// "aws.dynamodb.provisioned_write_capacity" semantic conventions. It represents
+	// the value of the `ProvisionedThroughput.WriteCapacityUnits` request
+	// parameter.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1.0, 2.0
+	AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity")
+
+	// AWSDynamoDBScanForwardKey is the attribute Key conforming to the
+	// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of
+	// the `ScanIndexForward` request parameter.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward")
+
+	// AWSDynamoDBScannedCountKey is the attribute Key conforming to the
+	// "aws.dynamodb.scanned_count" semantic conventions. It represents the value of
+	// the `ScannedCount` response parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 50
+	AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count")
+
+	// AWSDynamoDBSegmentKey is the attribute Key conforming to the
+	// "aws.dynamodb.segment" semantic conventions. It represents the value of the
+	// `Segment` request parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 10
+	AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment")
+
+	// AWSDynamoDBSelectKey is the attribute Key conforming to the
+	// "aws.dynamodb.select" semantic conventions. It represents the value of the
+	// `Select` request parameter.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "ALL_ATTRIBUTES", "COUNT"
+	AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select")
+
+	// AWSDynamoDBTableCountKey is the attribute Key conforming to the
+	// "aws.dynamodb.table_count" semantic conventions. It represents the number of
+	// items in the `TableNames` response parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 20
+	AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count")
+
+	// AWSDynamoDBTableNamesKey is the attribute Key conforming to the
+	// "aws.dynamodb.table_names" semantic conventions. It represents the keys in
+	// the `RequestItems` object field.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Users", "Cats"
+	AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names")
+
+	// AWSDynamoDBTotalSegmentsKey is the attribute Key conforming to the
+	// "aws.dynamodb.total_segments" semantic conventions. It represents the value
+	// of the `TotalSegments` request parameter.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 100
+	AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments")
+
+	// AWSECSClusterARNKey is the attribute Key conforming to the
+	// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an
+	// [ECS cluster].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster"
+	//
+	// [ECS cluster]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html
+	AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn")
+
+	// AWSECSContainerARNKey is the attribute Key conforming to the
+	// "aws.ecs.container.arn" semantic conventions. It represents the Amazon
+	// Resource Name (ARN) of an [ECS container instance].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "arn:aws:ecs:us-west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9"
+	//
+	// [ECS container instance]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html
+	AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn")
+
+	// AWSECSLaunchtypeKey is the attribute Key conforming to the
+	// "aws.ecs.launchtype" semantic conventions. It represents the [launch type]
+	// for an ECS task.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [launch type]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html
+	AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype")
+
+	// AWSECSTaskARNKey is the attribute Key conforming to the "aws.ecs.task.arn"
+	// semantic conventions. It represents the ARN of a running [ECS task].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "arn:aws:ecs:us-west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b",
+	// "arn:aws:ecs:us-west-1:123456789123:task/my-cluster/task-id/23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd"
+	//
+	// [ECS task]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids
+	AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn")
+
+	// AWSECSTaskFamilyKey is the attribute Key conforming to the
+	// "aws.ecs.task.family" semantic conventions. It represents the family name of
+	// the [ECS task definition] used to create the ECS task.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry-family"
+	//
+	// [ECS task definition]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html
+	AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family")
+
+	// AWSECSTaskIDKey is the attribute Key conforming to the "aws.ecs.task.id"
+	// semantic conventions. It represents the ID of a running ECS task. The ID MUST
+	// be extracted from `task.arn`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "10838bed-421f-43ef-870a-f43feacbbb5b",
+	// "23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd"
+	AWSECSTaskIDKey = attribute.Key("aws.ecs.task.id")
+
+	// AWSECSTaskRevisionKey is the attribute Key conforming to the
+	// "aws.ecs.task.revision" semantic conventions. It represents the revision for
+	// the task definition used to create the ECS task.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "8", "26"
+	AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision")
+
+	// AWSEKSClusterARNKey is the attribute Key conforming to the
+	// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS
+	// cluster.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster"
+	AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn")
+
+	// AWSExtendedRequestIDKey is the attribute Key conforming to the
+	// "aws.extended_request_id" semantic conventions. It represents the AWS
+	// extended request ID as returned in the response header `x-amz-id-2`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "wzHcyEWfmOGDIE5QOhTAqFDoDWP3y8IUvpNINCwL9N4TEHbUw0/gZJ+VZTmCNCWR7fezEN3eCiQ="
+	AWSExtendedRequestIDKey = attribute.Key("aws.extended_request_id")
+
+	// AWSKinesisStreamNameKey is the attribute Key conforming to the
+	// "aws.kinesis.stream_name" semantic conventions. It represents the name of the
+	// AWS Kinesis [stream] the request refers to. Corresponds to the
+	// `--stream-name` parameter of the Kinesis [describe-stream] operation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "some-stream-name"
+	//
+	// [stream]: https://docs.aws.amazon.com/streams/latest/dev/introduction.html
+	// [describe-stream]: https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html
+	AWSKinesisStreamNameKey = attribute.Key("aws.kinesis.stream_name")
+
+	// AWSLambdaInvokedARNKey is the attribute Key conforming to the
+	// "aws.lambda.invoked_arn" semantic conventions. It represents the full invoked
+	// ARN as provided on the `Context` passed to the function (
+	// `Lambda-Runtime-Invoked-Function-Arn` header on the
+	// `/runtime/invocation/next` applicable).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:lambda:us-east-1:123456:function:myfunction:myalias"
+	// Note: This may be different from `cloud.resource_id` if an alias is involved.
+	AWSLambdaInvokedARNKey = attribute.Key("aws.lambda.invoked_arn")
+
+	// AWSLambdaResourceMappingIDKey is the attribute Key conforming to the
+	// "aws.lambda.resource_mapping.id" semantic conventions. It represents the UUID
+	// of the [AWS Lambda EvenSource Mapping]. An event source is mapped to a lambda
+	// function. It's contents are read by Lambda and used to trigger a function.
+	// This isn't available in the lambda execution context or the lambda runtime
+	// environtment. This is going to be populated by the AWS SDK for each language
+	// when that UUID is present. Some of these operations are
+	// Create/Delete/Get/List/Update EventSourceMapping.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "587ad24b-03b9-4413-8202-bbd56b36e5b7"
+	//
+	// [AWS Lambda EvenSource Mapping]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html
+	AWSLambdaResourceMappingIDKey = attribute.Key("aws.lambda.resource_mapping.id")
+
+	// AWSLogGroupARNsKey is the attribute Key conforming to the
+	// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource
+	// Name(s) (ARN) of the AWS log group(s).
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*"
+	// Note: See the [log group ARN format documentation].
+	//
+	// [log group ARN format documentation]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format
+	AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns")
+
+	// AWSLogGroupNamesKey is the attribute Key conforming to the
+	// "aws.log.group.names" semantic conventions. It represents the name(s) of the
+	// AWS log group(s) an application is writing to.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/aws/lambda/my-function", "opentelemetry-service"
+	// Note: Multiple log groups must be supported for cases like multi-container
+	// applications, where a single application has sidecar containers, and each
+	// write to their own log group.
+	AWSLogGroupNamesKey = attribute.Key("aws.log.group.names")
+
+	// AWSLogStreamARNsKey is the attribute Key conforming to the
+	// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the
+	// AWS log stream(s).
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b"
+	// Note: See the [log stream ARN format documentation]. One log group can
+	// contain several log streams, so these ARNs necessarily identify both a log
+	// group and a log stream.
+	//
+	// [log stream ARN format documentation]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format
+	AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns")
+
+	// AWSLogStreamNamesKey is the attribute Key conforming to the
+	// "aws.log.stream.names" semantic conventions. It represents the name(s) of the
+	// AWS log stream(s) an application is writing to.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "logs/main/10838bed-421f-43ef-870a-f43feacbbb5b"
+	AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names")
+
+	// AWSRequestIDKey is the attribute Key conforming to the "aws.request_id"
+	// semantic conventions. It represents the AWS request ID as returned in the
+	// response headers `x-amzn-requestid`, `x-amzn-request-id` or
+	// `x-amz-request-id`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "79b9da39-b7ae-508a-a6bc-864b2829c622", "C9ER4AJX75574TDJ"
+	AWSRequestIDKey = attribute.Key("aws.request_id")
+
+	// AWSS3BucketKey is the attribute Key conforming to the "aws.s3.bucket"
+	// semantic conventions. It represents the S3 bucket name the request refers to.
+	// Corresponds to the `--bucket` parameter of the [S3 API] operations.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "some-bucket-name"
+	// Note: The `bucket` attribute is applicable to all S3 operations that
+	// reference a bucket, i.e. that require the bucket name as a mandatory
+	// parameter.
+	// This applies to almost all S3 operations except `list-buckets`.
+	//
+	// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html
+	AWSS3BucketKey = attribute.Key("aws.s3.bucket")
+
+	// AWSS3CopySourceKey is the attribute Key conforming to the
+	// "aws.s3.copy_source" semantic conventions. It represents the source object
+	// (in the form `bucket`/`key`) for the copy operation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "someFile.yml"
+	// Note: The `copy_source` attribute applies to S3 copy operations and
+	// corresponds to the `--copy-source` parameter
+	// of the [copy-object operation within the S3 API].
+	// This applies in particular to the following operations:
+	//
+	//   - [copy-object]
+	//   - [upload-part-copy]
+	//
+	//
+	// [copy-object operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html
+	// [copy-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html
+	// [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html
+	AWSS3CopySourceKey = attribute.Key("aws.s3.copy_source")
+
+	// AWSS3DeleteKey is the attribute Key conforming to the "aws.s3.delete"
+	// semantic conventions. It represents the delete request container that
+	// specifies the objects to be deleted.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "Objects=[{Key=string,VersionId=string},{Key=string,VersionId=string}],Quiet=boolean"
+	// Note: The `delete` attribute is only applicable to the [delete-object]
+	// operation.
+	// The `delete` attribute corresponds to the `--delete` parameter of the
+	// [delete-objects operation within the S3 API].
+	//
+	// [delete-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html
+	// [delete-objects operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-objects.html
+	AWSS3DeleteKey = attribute.Key("aws.s3.delete")
+
+	// AWSS3KeyKey is the attribute Key conforming to the "aws.s3.key" semantic
+	// conventions. It represents the S3 object key the request refers to.
+	// Corresponds to the `--key` parameter of the [S3 API] operations.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "someFile.yml"
+	// Note: The `key` attribute is applicable to all object-related S3 operations,
+	// i.e. that require the object key as a mandatory parameter.
+	// This applies in particular to the following operations:
+	//
+	//   - [copy-object]
+	//   - [delete-object]
+	//   - [get-object]
+	//   - [head-object]
+	//   - [put-object]
+	//   - [restore-object]
+	//   - [select-object-content]
+	//   - [abort-multipart-upload]
+	//   - [complete-multipart-upload]
+	//   - [create-multipart-upload]
+	//   - [list-parts]
+	//   - [upload-part]
+	//   - [upload-part-copy]
+	//
+	//
+	// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html
+	// [copy-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html
+	// [delete-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html
+	// [get-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html
+	// [head-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/head-object.html
+	// [put-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html
+	// [restore-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/restore-object.html
+	// [select-object-content]: https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html
+	// [abort-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html
+	// [complete-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html
+	// [create-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html
+	// [list-parts]: https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html
+	// [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html
+	// [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html
+	AWSS3KeyKey = attribute.Key("aws.s3.key")
+
+	// AWSS3PartNumberKey is the attribute Key conforming to the
+	// "aws.s3.part_number" semantic conventions. It represents the part number of
+	// the part being uploaded in a multipart-upload operation. This is a positive
+	// integer between 1 and 10,000.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 3456
+	// Note: The `part_number` attribute is only applicable to the [upload-part]
+	// and [upload-part-copy] operations.
+	// The `part_number` attribute corresponds to the `--part-number` parameter of
+	// the
+	// [upload-part operation within the S3 API].
+	//
+	// [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html
+	// [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html
+	// [upload-part operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html
+	AWSS3PartNumberKey = attribute.Key("aws.s3.part_number")
+
+	// AWSS3UploadIDKey is the attribute Key conforming to the "aws.s3.upload_id"
+	// semantic conventions. It represents the upload ID that identifies the
+	// multipart upload.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ"
+	// Note: The `upload_id` attribute applies to S3 multipart-upload operations and
+	// corresponds to the `--upload-id` parameter
+	// of the [S3 API] multipart operations.
+	// This applies in particular to the following operations:
+	//
+	//   - [abort-multipart-upload]
+	//   - [complete-multipart-upload]
+	//   - [list-parts]
+	//   - [upload-part]
+	//   - [upload-part-copy]
+	//
+	//
+	// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html
+	// [abort-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html
+	// [complete-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html
+	// [list-parts]: https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html
+	// [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html
+	// [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html
+	AWSS3UploadIDKey = attribute.Key("aws.s3.upload_id")
+
+	// AWSSecretsmanagerSecretARNKey is the attribute Key conforming to the
+	// "aws.secretsmanager.secret.arn" semantic conventions. It represents the ARN
+	// of the Secret stored in the Secrets Mangger.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "arn:aws:secretsmanager:us-east-1:123456789012:secret:SecretName-6RandomCharacters"
+	AWSSecretsmanagerSecretARNKey = attribute.Key("aws.secretsmanager.secret.arn")
+
+	// AWSSNSTopicARNKey is the attribute Key conforming to the "aws.sns.topic.arn"
+	// semantic conventions. It represents the ARN of the AWS SNS Topic. An Amazon
+	// SNS [topic] is a logical access point that acts as a communication channel.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:sns:us-east-1:123456789012:mystack-mytopic-NZJ5JSMVGFIE"
+	//
+	// [topic]: https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html
+	AWSSNSTopicARNKey = attribute.Key("aws.sns.topic.arn")
+
+	// AWSSQSQueueURLKey is the attribute Key conforming to the "aws.sqs.queue.url"
+	// semantic conventions. It represents the URL of the AWS SQS Queue. It's a
+	// unique identifier for a queue in Amazon Simple Queue Service (SQS) and is
+	// used to access the queue and perform actions on it.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue"
+	AWSSQSQueueURLKey = attribute.Key("aws.sqs.queue.url")
+
+	// AWSStepFunctionsActivityARNKey is the attribute Key conforming to the
+	// "aws.step_functions.activity.arn" semantic conventions. It represents the ARN
+	// of the AWS Step Functions Activity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:states:us-east-1:123456789012:activity:get-greeting"
+	AWSStepFunctionsActivityARNKey = attribute.Key("aws.step_functions.activity.arn")
+
+	// AWSStepFunctionsStateMachineARNKey is the attribute Key conforming to the
+	// "aws.step_functions.state_machine.arn" semantic conventions. It represents
+	// the ARN of the AWS Step Functions State Machine.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "arn:aws:states:us-east-1:123456789012:stateMachine:myStateMachine:1"
+	AWSStepFunctionsStateMachineARNKey = attribute.Key("aws.step_functions.state_machine.arn")
+)
+
+// AWSBedrockGuardrailID returns an attribute KeyValue conforming to the
+// "aws.bedrock.guardrail.id" semantic conventions. It represents the unique
+// identifier of the AWS Bedrock Guardrail. A [guardrail] helps safeguard and
+// prevent unwanted behavior from model responses or user messages.
+//
+// [guardrail]: https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html
+func AWSBedrockGuardrailID(val string) attribute.KeyValue {
+	return AWSBedrockGuardrailIDKey.String(val)
+}
+
+// AWSBedrockKnowledgeBaseID returns an attribute KeyValue conforming to the
+// "aws.bedrock.knowledge_base.id" semantic conventions. It represents the unique
+// identifier of the AWS Bedrock Knowledge base. A [knowledge base] is a bank of
+// information that can be queried by models to generate more relevant responses
+// and augment prompts.
+//
+// [knowledge base]: https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html
+func AWSBedrockKnowledgeBaseID(val string) attribute.KeyValue {
+	return AWSBedrockKnowledgeBaseIDKey.String(val)
+}
+
+// AWSDynamoDBAttributeDefinitions returns an attribute KeyValue conforming to
+// the "aws.dynamodb.attribute_definitions" semantic conventions. It represents
+// the JSON-serialized value of each item in the `AttributeDefinitions` request
+// field.
+func AWSDynamoDBAttributeDefinitions(val ...string) attribute.KeyValue {
+	return AWSDynamoDBAttributeDefinitionsKey.StringSlice(val)
+}
+
+// AWSDynamoDBAttributesToGet returns an attribute KeyValue conforming to the
+// "aws.dynamodb.attributes_to_get" semantic conventions. It represents the value
+// of the `AttributesToGet` request parameter.
+func AWSDynamoDBAttributesToGet(val ...string) attribute.KeyValue {
+	return AWSDynamoDBAttributesToGetKey.StringSlice(val)
+}
+
+// AWSDynamoDBConsistentRead returns an attribute KeyValue conforming to the
+// "aws.dynamodb.consistent_read" semantic conventions. It represents the value
+// of the `ConsistentRead` request parameter.
+func AWSDynamoDBConsistentRead(val bool) attribute.KeyValue {
+	return AWSDynamoDBConsistentReadKey.Bool(val)
+}
+
+// AWSDynamoDBConsumedCapacity returns an attribute KeyValue conforming to the
+// "aws.dynamodb.consumed_capacity" semantic conventions. It represents the
+// JSON-serialized value of each item in the `ConsumedCapacity` response field.
+func AWSDynamoDBConsumedCapacity(val ...string) attribute.KeyValue {
+	return AWSDynamoDBConsumedCapacityKey.StringSlice(val)
+}
+
+// AWSDynamoDBCount returns an attribute KeyValue conforming to the
+// "aws.dynamodb.count" semantic conventions. It represents the value of the
+// `Count` response parameter.
+func AWSDynamoDBCount(val int) attribute.KeyValue {
+	return AWSDynamoDBCountKey.Int(val)
+}
+
+// AWSDynamoDBExclusiveStartTable returns an attribute KeyValue conforming to the
+// "aws.dynamodb.exclusive_start_table" semantic conventions. It represents the
+// value of the `ExclusiveStartTableName` request parameter.
+func AWSDynamoDBExclusiveStartTable(val string) attribute.KeyValue {
+	return AWSDynamoDBExclusiveStartTableKey.String(val)
+}
+
+// AWSDynamoDBGlobalSecondaryIndexUpdates returns an attribute KeyValue
+// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic
+// conventions. It represents the JSON-serialized value of each item in the
+// `GlobalSecondaryIndexUpdates` request field.
+func AWSDynamoDBGlobalSecondaryIndexUpdates(val ...string) attribute.KeyValue {
+	return AWSDynamoDBGlobalSecondaryIndexUpdatesKey.StringSlice(val)
+}
+
+// AWSDynamoDBGlobalSecondaryIndexes returns an attribute KeyValue conforming to
+// the "aws.dynamodb.global_secondary_indexes" semantic conventions. It
+// represents the JSON-serialized value of each item of the
+// `GlobalSecondaryIndexes` request field.
+func AWSDynamoDBGlobalSecondaryIndexes(val ...string) attribute.KeyValue {
+	return AWSDynamoDBGlobalSecondaryIndexesKey.StringSlice(val)
+}
+
+// AWSDynamoDBIndexName returns an attribute KeyValue conforming to the
+// "aws.dynamodb.index_name" semantic conventions. It represents the value of the
+// `IndexName` request parameter.
+func AWSDynamoDBIndexName(val string) attribute.KeyValue {
+	return AWSDynamoDBIndexNameKey.String(val)
+}
+
+// AWSDynamoDBItemCollectionMetrics returns an attribute KeyValue conforming to
+// the "aws.dynamodb.item_collection_metrics" semantic conventions. It represents
+// the JSON-serialized value of the `ItemCollectionMetrics` response field.
+func AWSDynamoDBItemCollectionMetrics(val string) attribute.KeyValue {
+	return AWSDynamoDBItemCollectionMetricsKey.String(val)
+}
+
+// AWSDynamoDBLimit returns an attribute KeyValue conforming to the
+// "aws.dynamodb.limit" semantic conventions. It represents the value of the
+// `Limit` request parameter.
+func AWSDynamoDBLimit(val int) attribute.KeyValue {
+	return AWSDynamoDBLimitKey.Int(val)
+}
+
+// AWSDynamoDBLocalSecondaryIndexes returns an attribute KeyValue conforming to
+// the "aws.dynamodb.local_secondary_indexes" semantic conventions. It represents
+// the JSON-serialized value of each item of the `LocalSecondaryIndexes` request
+// field.
+func AWSDynamoDBLocalSecondaryIndexes(val ...string) attribute.KeyValue {
+	return AWSDynamoDBLocalSecondaryIndexesKey.StringSlice(val)
+}
+
+// AWSDynamoDBProjection returns an attribute KeyValue conforming to the
+// "aws.dynamodb.projection" semantic conventions. It represents the value of the
+// `ProjectionExpression` request parameter.
+func AWSDynamoDBProjection(val string) attribute.KeyValue {
+	return AWSDynamoDBProjectionKey.String(val)
+}
+
+// AWSDynamoDBProvisionedReadCapacity returns an attribute KeyValue conforming to
+// the "aws.dynamodb.provisioned_read_capacity" semantic conventions. It
+// represents the value of the `ProvisionedThroughput.ReadCapacityUnits` request
+// parameter.
+func AWSDynamoDBProvisionedReadCapacity(val float64) attribute.KeyValue {
+	return AWSDynamoDBProvisionedReadCapacityKey.Float64(val)
+}
+
+// AWSDynamoDBProvisionedWriteCapacity returns an attribute KeyValue conforming
+// to the "aws.dynamodb.provisioned_write_capacity" semantic conventions. It
+// represents the value of the `ProvisionedThroughput.WriteCapacityUnits` request
+// parameter.
+func AWSDynamoDBProvisionedWriteCapacity(val float64) attribute.KeyValue {
+	return AWSDynamoDBProvisionedWriteCapacityKey.Float64(val)
+}
+
+// AWSDynamoDBScanForward returns an attribute KeyValue conforming to the
+// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of
+// the `ScanIndexForward` request parameter.
+func AWSDynamoDBScanForward(val bool) attribute.KeyValue {
+	return AWSDynamoDBScanForwardKey.Bool(val)
+}
+
+// AWSDynamoDBScannedCount returns an attribute KeyValue conforming to the
+// "aws.dynamodb.scanned_count" semantic conventions. It represents the value of
+// the `ScannedCount` response parameter.
+func AWSDynamoDBScannedCount(val int) attribute.KeyValue {
+	return AWSDynamoDBScannedCountKey.Int(val)
+}
+
+// AWSDynamoDBSegment returns an attribute KeyValue conforming to the
+// "aws.dynamodb.segment" semantic conventions. It represents the value of the
+// `Segment` request parameter.
+func AWSDynamoDBSegment(val int) attribute.KeyValue {
+	return AWSDynamoDBSegmentKey.Int(val)
+}
+
+// AWSDynamoDBSelect returns an attribute KeyValue conforming to the
+// "aws.dynamodb.select" semantic conventions. It represents the value of the
+// `Select` request parameter.
+func AWSDynamoDBSelect(val string) attribute.KeyValue {
+	return AWSDynamoDBSelectKey.String(val)
+}
+
+// AWSDynamoDBTableCount returns an attribute KeyValue conforming to the
+// "aws.dynamodb.table_count" semantic conventions. It represents the number of
+// items in the `TableNames` response parameter.
+func AWSDynamoDBTableCount(val int) attribute.KeyValue {
+	return AWSDynamoDBTableCountKey.Int(val)
+}
+
+// AWSDynamoDBTableNames returns an attribute KeyValue conforming to the
+// "aws.dynamodb.table_names" semantic conventions. It represents the keys in the
+// `RequestItems` object field.
+func AWSDynamoDBTableNames(val ...string) attribute.KeyValue {
+	return AWSDynamoDBTableNamesKey.StringSlice(val)
+}
+
+// AWSDynamoDBTotalSegments returns an attribute KeyValue conforming to the
+// "aws.dynamodb.total_segments" semantic conventions. It represents the value of
+// the `TotalSegments` request parameter.
+func AWSDynamoDBTotalSegments(val int) attribute.KeyValue {
+	return AWSDynamoDBTotalSegmentsKey.Int(val)
+}
+
+// AWSECSClusterARN returns an attribute KeyValue conforming to the
+// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an
+// [ECS cluster].
+//
+// [ECS cluster]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html
+func AWSECSClusterARN(val string) attribute.KeyValue {
+	return AWSECSClusterARNKey.String(val)
+}
+
+// AWSECSContainerARN returns an attribute KeyValue conforming to the
+// "aws.ecs.container.arn" semantic conventions. It represents the Amazon
+// Resource Name (ARN) of an [ECS container instance].
+//
+// [ECS container instance]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html
+func AWSECSContainerARN(val string) attribute.KeyValue {
+	return AWSECSContainerARNKey.String(val)
+}
+
+// AWSECSTaskARN returns an attribute KeyValue conforming to the
+// "aws.ecs.task.arn" semantic conventions. It represents the ARN of a running
+// [ECS task].
+//
+// [ECS task]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids
+func AWSECSTaskARN(val string) attribute.KeyValue {
+	return AWSECSTaskARNKey.String(val)
+}
+
+// AWSECSTaskFamily returns an attribute KeyValue conforming to the
+// "aws.ecs.task.family" semantic conventions. It represents the family name of
+// the [ECS task definition] used to create the ECS task.
+//
+// [ECS task definition]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html
+func AWSECSTaskFamily(val string) attribute.KeyValue {
+	return AWSECSTaskFamilyKey.String(val)
+}
+
+// AWSECSTaskID returns an attribute KeyValue conforming to the "aws.ecs.task.id"
+// semantic conventions. It represents the ID of a running ECS task. The ID MUST
+// be extracted from `task.arn`.
+func AWSECSTaskID(val string) attribute.KeyValue {
+	return AWSECSTaskIDKey.String(val)
+}
+
+// AWSECSTaskRevision returns an attribute KeyValue conforming to the
+// "aws.ecs.task.revision" semantic conventions. It represents the revision for
+// the task definition used to create the ECS task.
+func AWSECSTaskRevision(val string) attribute.KeyValue {
+	return AWSECSTaskRevisionKey.String(val)
+}
+
+// AWSEKSClusterARN returns an attribute KeyValue conforming to the
+// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS
+// cluster.
+func AWSEKSClusterARN(val string) attribute.KeyValue {
+	return AWSEKSClusterARNKey.String(val)
+}
+
+// AWSExtendedRequestID returns an attribute KeyValue conforming to the
+// "aws.extended_request_id" semantic conventions. It represents the AWS extended
+// request ID as returned in the response header `x-amz-id-2`.
+func AWSExtendedRequestID(val string) attribute.KeyValue {
+	return AWSExtendedRequestIDKey.String(val)
+}
+
+// AWSKinesisStreamName returns an attribute KeyValue conforming to the
+// "aws.kinesis.stream_name" semantic conventions. It represents the name of the
+// AWS Kinesis [stream] the request refers to. Corresponds to the `--stream-name`
+//  parameter of the Kinesis [describe-stream] operation.
+//
+// [stream]: https://docs.aws.amazon.com/streams/latest/dev/introduction.html
+// [describe-stream]: https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html
+func AWSKinesisStreamName(val string) attribute.KeyValue {
+	return AWSKinesisStreamNameKey.String(val)
+}
+
+// AWSLambdaInvokedARN returns an attribute KeyValue conforming to the
+// "aws.lambda.invoked_arn" semantic conventions. It represents the full invoked
+// ARN as provided on the `Context` passed to the function (
+// `Lambda-Runtime-Invoked-Function-Arn` header on the `/runtime/invocation/next`
+//  applicable).
+func AWSLambdaInvokedARN(val string) attribute.KeyValue {
+	return AWSLambdaInvokedARNKey.String(val)
+}
+
+// AWSLambdaResourceMappingID returns an attribute KeyValue conforming to the
+// "aws.lambda.resource_mapping.id" semantic conventions. It represents the UUID
+// of the [AWS Lambda EvenSource Mapping]. An event source is mapped to a lambda
+// function. It's contents are read by Lambda and used to trigger a function.
+// This isn't available in the lambda execution context or the lambda runtime
+// environtment. This is going to be populated by the AWS SDK for each language
+// when that UUID is present. Some of these operations are
+// Create/Delete/Get/List/Update EventSourceMapping.
+//
+// [AWS Lambda EvenSource Mapping]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html
+func AWSLambdaResourceMappingID(val string) attribute.KeyValue {
+	return AWSLambdaResourceMappingIDKey.String(val)
+}
+
+// AWSLogGroupARNs returns an attribute KeyValue conforming to the
+// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource
+// Name(s) (ARN) of the AWS log group(s).
+func AWSLogGroupARNs(val ...string) attribute.KeyValue {
+	return AWSLogGroupARNsKey.StringSlice(val)
+}
+
+// AWSLogGroupNames returns an attribute KeyValue conforming to the
+// "aws.log.group.names" semantic conventions. It represents the name(s) of the
+// AWS log group(s) an application is writing to.
+func AWSLogGroupNames(val ...string) attribute.KeyValue {
+	return AWSLogGroupNamesKey.StringSlice(val)
+}
+
+// AWSLogStreamARNs returns an attribute KeyValue conforming to the
+// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the
+// AWS log stream(s).
+func AWSLogStreamARNs(val ...string) attribute.KeyValue {
+	return AWSLogStreamARNsKey.StringSlice(val)
+}
+
+// AWSLogStreamNames returns an attribute KeyValue conforming to the
+// "aws.log.stream.names" semantic conventions. It represents the name(s) of the
+// AWS log stream(s) an application is writing to.
+func AWSLogStreamNames(val ...string) attribute.KeyValue {
+	return AWSLogStreamNamesKey.StringSlice(val)
+}
+
+// AWSRequestID returns an attribute KeyValue conforming to the "aws.request_id"
+// semantic conventions. It represents the AWS request ID as returned in the
+// response headers `x-amzn-requestid`, `x-amzn-request-id` or `x-amz-request-id`
+// .
+func AWSRequestID(val string) attribute.KeyValue {
+	return AWSRequestIDKey.String(val)
+}
+
+// AWSS3Bucket returns an attribute KeyValue conforming to the "aws.s3.bucket"
+// semantic conventions. It represents the S3 bucket name the request refers to.
+// Corresponds to the `--bucket` parameter of the [S3 API] operations.
+//
+// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html
+func AWSS3Bucket(val string) attribute.KeyValue {
+	return AWSS3BucketKey.String(val)
+}
+
+// AWSS3CopySource returns an attribute KeyValue conforming to the
+// "aws.s3.copy_source" semantic conventions. It represents the source object (in
+// the form `bucket`/`key`) for the copy operation.
+func AWSS3CopySource(val string) attribute.KeyValue {
+	return AWSS3CopySourceKey.String(val)
+}
+
+// AWSS3Delete returns an attribute KeyValue conforming to the "aws.s3.delete"
+// semantic conventions. It represents the delete request container that
+// specifies the objects to be deleted.
+func AWSS3Delete(val string) attribute.KeyValue {
+	return AWSS3DeleteKey.String(val)
+}
+
+// AWSS3Key returns an attribute KeyValue conforming to the "aws.s3.key" semantic
+// conventions. It represents the S3 object key the request refers to.
+// Corresponds to the `--key` parameter of the [S3 API] operations.
+//
+// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html
+func AWSS3Key(val string) attribute.KeyValue {
+	return AWSS3KeyKey.String(val)
+}
+
+// AWSS3PartNumber returns an attribute KeyValue conforming to the
+// "aws.s3.part_number" semantic conventions. It represents the part number of
+// the part being uploaded in a multipart-upload operation. This is a positive
+// integer between 1 and 10,000.
+func AWSS3PartNumber(val int) attribute.KeyValue {
+	return AWSS3PartNumberKey.Int(val)
+}
+
+// AWSS3UploadID returns an attribute KeyValue conforming to the
+// "aws.s3.upload_id" semantic conventions. It represents the upload ID that
+// identifies the multipart upload.
+func AWSS3UploadID(val string) attribute.KeyValue {
+	return AWSS3UploadIDKey.String(val)
+}
+
+// AWSSecretsmanagerSecretARN returns an attribute KeyValue conforming to the
+// "aws.secretsmanager.secret.arn" semantic conventions. It represents the ARN of
+// the Secret stored in the Secrets Mangger.
+func AWSSecretsmanagerSecretARN(val string) attribute.KeyValue {
+	return AWSSecretsmanagerSecretARNKey.String(val)
+}
+
+// AWSSNSTopicARN returns an attribute KeyValue conforming to the
+// "aws.sns.topic.arn" semantic conventions. It represents the ARN of the AWS SNS
+// Topic. An Amazon SNS [topic] is a logical access point that acts as a
+// communication channel.
+//
+// [topic]: https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html
+func AWSSNSTopicARN(val string) attribute.KeyValue {
+	return AWSSNSTopicARNKey.String(val)
+}
+
+// AWSSQSQueueURL returns an attribute KeyValue conforming to the
+// "aws.sqs.queue.url" semantic conventions. It represents the URL of the AWS SQS
+// Queue. It's a unique identifier for a queue in Amazon Simple Queue Service
+// (SQS) and is used to access the queue and perform actions on it.
+func AWSSQSQueueURL(val string) attribute.KeyValue {
+	return AWSSQSQueueURLKey.String(val)
+}
+
+// AWSStepFunctionsActivityARN returns an attribute KeyValue conforming to the
+// "aws.step_functions.activity.arn" semantic conventions. It represents the ARN
+// of the AWS Step Functions Activity.
+func AWSStepFunctionsActivityARN(val string) attribute.KeyValue {
+	return AWSStepFunctionsActivityARNKey.String(val)
+}
+
+// AWSStepFunctionsStateMachineARN returns an attribute KeyValue conforming to
+// the "aws.step_functions.state_machine.arn" semantic conventions. It represents
+// the ARN of the AWS Step Functions State Machine.
+func AWSStepFunctionsStateMachineARN(val string) attribute.KeyValue {
+	return AWSStepFunctionsStateMachineARNKey.String(val)
+}
+
+// Enum values for aws.ecs.launchtype
+var (
+	// ec2
+	// Stability: development
+	AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2")
+	// fargate
+	// Stability: development
+	AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate")
+)
+
+// Namespace: az
+const (
+	// AzNamespaceKey is the attribute Key conforming to the "az.namespace" semantic
+	// conventions. It represents the [Azure Resource Provider Namespace] as
+	// recognized by the client.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Microsoft.Storage", "Microsoft.KeyVault", "Microsoft.ServiceBus"
+	//
+	// [Azure Resource Provider Namespace]: https://learn.microsoft.com/azure/azure-resource-manager/management/azure-services-resource-providers
+	AzNamespaceKey = attribute.Key("az.namespace")
+
+	// AzServiceRequestIDKey is the attribute Key conforming to the
+	// "az.service_request_id" semantic conventions. It represents the unique
+	// identifier of the service request. It's generated by the Azure service and
+	// returned with the response.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "00000000-0000-0000-0000-000000000000"
+	AzServiceRequestIDKey = attribute.Key("az.service_request_id")
+)
+
+// AzNamespace returns an attribute KeyValue conforming to the "az.namespace"
+// semantic conventions. It represents the [Azure Resource Provider Namespace] as
+// recognized by the client.
+//
+// [Azure Resource Provider Namespace]: https://learn.microsoft.com/azure/azure-resource-manager/management/azure-services-resource-providers
+func AzNamespace(val string) attribute.KeyValue {
+	return AzNamespaceKey.String(val)
+}
+
+// AzServiceRequestID returns an attribute KeyValue conforming to the
+// "az.service_request_id" semantic conventions. It represents the unique
+// identifier of the service request. It's generated by the Azure service and
+// returned with the response.
+func AzServiceRequestID(val string) attribute.KeyValue {
+	return AzServiceRequestIDKey.String(val)
+}
+
+// Namespace: azure
+const (
+	// AzureClientIDKey is the attribute Key conforming to the "azure.client.id"
+	// semantic conventions. It represents the unique identifier of the client
+	// instance.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "3ba4827d-4422-483f-b59f-85b74211c11d", "storage-client-1"
+	AzureClientIDKey = attribute.Key("azure.client.id")
+
+	// AzureCosmosDBConnectionModeKey is the attribute Key conforming to the
+	// "azure.cosmosdb.connection.mode" semantic conventions. It represents the
+	// cosmos client connection mode.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	AzureCosmosDBConnectionModeKey = attribute.Key("azure.cosmosdb.connection.mode")
+
+	// AzureCosmosDBConsistencyLevelKey is the attribute Key conforming to the
+	// "azure.cosmosdb.consistency.level" semantic conventions. It represents the
+	// account or request [consistency level].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Eventual", "ConsistentPrefix", "BoundedStaleness", "Strong",
+	// "Session"
+	//
+	// [consistency level]: https://learn.microsoft.com/azure/cosmos-db/consistency-levels
+	AzureCosmosDBConsistencyLevelKey = attribute.Key("azure.cosmosdb.consistency.level")
+
+	// AzureCosmosDBOperationContactedRegionsKey is the attribute Key conforming to
+	// the "azure.cosmosdb.operation.contacted_regions" semantic conventions. It
+	// represents the list of regions contacted during operation in the order that
+	// they were contacted. If there is more than one region listed, it indicates
+	// that the operation was performed on multiple regions i.e. cross-regional
+	// call.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "North Central US", "Australia East", "Australia Southeast"
+	// Note: Region name matches the format of `displayName` in [Azure Location API]
+	//
+	// [Azure Location API]: https://learn.microsoft.com/rest/api/subscription/subscriptions/list-locations?view=rest-subscription-2021-10-01&tabs=HTTP#location
+	AzureCosmosDBOperationContactedRegionsKey = attribute.Key("azure.cosmosdb.operation.contacted_regions")
+
+	// AzureCosmosDBOperationRequestChargeKey is the attribute Key conforming to the
+	// "azure.cosmosdb.operation.request_charge" semantic conventions. It represents
+	// the number of request units consumed by the operation.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 46.18, 1.0
+	AzureCosmosDBOperationRequestChargeKey = attribute.Key("azure.cosmosdb.operation.request_charge")
+
+	// AzureCosmosDBRequestBodySizeKey is the attribute Key conforming to the
+	// "azure.cosmosdb.request.body.size" semantic conventions. It represents the
+	// request payload size in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	AzureCosmosDBRequestBodySizeKey = attribute.Key("azure.cosmosdb.request.body.size")
+
+	// AzureCosmosDBResponseSubStatusCodeKey is the attribute Key conforming to the
+	// "azure.cosmosdb.response.sub_status_code" semantic conventions. It represents
+	// the cosmos DB sub status code.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1000, 1002
+	AzureCosmosDBResponseSubStatusCodeKey = attribute.Key("azure.cosmosdb.response.sub_status_code")
+)
+
+// AzureClientID returns an attribute KeyValue conforming to the
+// "azure.client.id" semantic conventions. It represents the unique identifier of
+// the client instance.
+func AzureClientID(val string) attribute.KeyValue {
+	return AzureClientIDKey.String(val)
+}
+
+// AzureCosmosDBOperationContactedRegions returns an attribute KeyValue
+// conforming to the "azure.cosmosdb.operation.contacted_regions" semantic
+// conventions. It represents the list of regions contacted during operation in
+// the order that they were contacted. If there is more than one region listed,
+// it indicates that the operation was performed on multiple regions i.e.
+// cross-regional call.
+func AzureCosmosDBOperationContactedRegions(val ...string) attribute.KeyValue {
+	return AzureCosmosDBOperationContactedRegionsKey.StringSlice(val)
+}
+
+// AzureCosmosDBOperationRequestCharge returns an attribute KeyValue conforming
+// to the "azure.cosmosdb.operation.request_charge" semantic conventions. It
+// represents the number of request units consumed by the operation.
+func AzureCosmosDBOperationRequestCharge(val float64) attribute.KeyValue {
+	return AzureCosmosDBOperationRequestChargeKey.Float64(val)
+}
+
+// AzureCosmosDBRequestBodySize returns an attribute KeyValue conforming to the
+// "azure.cosmosdb.request.body.size" semantic conventions. It represents the
+// request payload size in bytes.
+func AzureCosmosDBRequestBodySize(val int) attribute.KeyValue {
+	return AzureCosmosDBRequestBodySizeKey.Int(val)
+}
+
+// AzureCosmosDBResponseSubStatusCode returns an attribute KeyValue conforming to
+// the "azure.cosmosdb.response.sub_status_code" semantic conventions. It
+// represents the cosmos DB sub status code.
+func AzureCosmosDBResponseSubStatusCode(val int) attribute.KeyValue {
+	return AzureCosmosDBResponseSubStatusCodeKey.Int(val)
+}
+
+// Enum values for azure.cosmosdb.connection.mode
+var (
+	// Gateway (HTTP) connection.
+	// Stability: development
+	AzureCosmosDBConnectionModeGateway = AzureCosmosDBConnectionModeKey.String("gateway")
+	// Direct connection.
+	// Stability: development
+	AzureCosmosDBConnectionModeDirect = AzureCosmosDBConnectionModeKey.String("direct")
+)
+
+// Enum values for azure.cosmosdb.consistency.level
+var (
+	// strong
+	// Stability: development
+	AzureCosmosDBConsistencyLevelStrong = AzureCosmosDBConsistencyLevelKey.String("Strong")
+	// bounded_staleness
+	// Stability: development
+	AzureCosmosDBConsistencyLevelBoundedStaleness = AzureCosmosDBConsistencyLevelKey.String("BoundedStaleness")
+	// session
+	// Stability: development
+	AzureCosmosDBConsistencyLevelSession = AzureCosmosDBConsistencyLevelKey.String("Session")
+	// eventual
+	// Stability: development
+	AzureCosmosDBConsistencyLevelEventual = AzureCosmosDBConsistencyLevelKey.String("Eventual")
+	// consistent_prefix
+	// Stability: development
+	AzureCosmosDBConsistencyLevelConsistentPrefix = AzureCosmosDBConsistencyLevelKey.String("ConsistentPrefix")
+)
+
+// Namespace: browser
+const (
+	// BrowserBrandsKey is the attribute Key conforming to the "browser.brands"
+	// semantic conventions. It represents the array of brand name and version
+	// separated by a space.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: " Not A;Brand 99", "Chromium 99", "Chrome 99"
+	// Note: This value is intended to be taken from the [UA client hints API] (
+	// `navigator.userAgentData.brands`).
+	//
+	// [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface
+	BrowserBrandsKey = attribute.Key("browser.brands")
+
+	// BrowserLanguageKey is the attribute Key conforming to the "browser.language"
+	// semantic conventions. It represents the preferred language of the user using
+	// the browser.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "en", "en-US", "fr", "fr-FR"
+	// Note: This value is intended to be taken from the Navigator API
+	// `navigator.language`.
+	BrowserLanguageKey = attribute.Key("browser.language")
+
+	// BrowserMobileKey is the attribute Key conforming to the "browser.mobile"
+	// semantic conventions. It represents a boolean that is true if the browser is
+	// running on a mobile device.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: This value is intended to be taken from the [UA client hints API] (
+	// `navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be
+	// left unset.
+	//
+	// [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface
+	BrowserMobileKey = attribute.Key("browser.mobile")
+
+	// BrowserPlatformKey is the attribute Key conforming to the "browser.platform"
+	// semantic conventions. It represents the platform on which the browser is
+	// running.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Windows", "macOS", "Android"
+	// Note: This value is intended to be taken from the [UA client hints API] (
+	// `navigator.userAgentData.platform`). If unavailable, the legacy
+	// `navigator.platform` API SHOULD NOT be used instead and this attribute SHOULD
+	// be left unset in order for the values to be consistent.
+	// The list of possible values is defined in the
+	// [W3C User-Agent Client Hints specification]. Note that some (but not all) of
+	// these values can overlap with values in the
+	// [`os.type` and `os.name` attributes]. However, for consistency, the values in
+	// the `browser.platform` attribute should capture the exact value that the user
+	// agent provides.
+	//
+	// [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface
+	// [W3C User-Agent Client Hints specification]: https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform
+	// [`os.type` and `os.name` attributes]: ./os.md
+	BrowserPlatformKey = attribute.Key("browser.platform")
+)
+
+// BrowserBrands returns an attribute KeyValue conforming to the "browser.brands"
+// semantic conventions. It represents the array of brand name and version
+// separated by a space.
+func BrowserBrands(val ...string) attribute.KeyValue {
+	return BrowserBrandsKey.StringSlice(val)
+}
+
+// BrowserLanguage returns an attribute KeyValue conforming to the
+// "browser.language" semantic conventions. It represents the preferred language
+// of the user using the browser.
+func BrowserLanguage(val string) attribute.KeyValue {
+	return BrowserLanguageKey.String(val)
+}
+
+// BrowserMobile returns an attribute KeyValue conforming to the "browser.mobile"
+// semantic conventions. It represents a boolean that is true if the browser is
+// running on a mobile device.
+func BrowserMobile(val bool) attribute.KeyValue {
+	return BrowserMobileKey.Bool(val)
+}
+
+// BrowserPlatform returns an attribute KeyValue conforming to the
+// "browser.platform" semantic conventions. It represents the platform on which
+// the browser is running.
+func BrowserPlatform(val string) attribute.KeyValue {
+	return BrowserPlatformKey.String(val)
+}
+
+// Namespace: cassandra
+const (
+	// CassandraConsistencyLevelKey is the attribute Key conforming to the
+	// "cassandra.consistency.level" semantic conventions. It represents the
+	// consistency level of the query. Based on consistency values from [CQL].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [CQL]: https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html
+	CassandraConsistencyLevelKey = attribute.Key("cassandra.consistency.level")
+
+	// CassandraCoordinatorDCKey is the attribute Key conforming to the
+	// "cassandra.coordinator.dc" semantic conventions. It represents the data
+	// center of the coordinating node for a query.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: us-west-2
+	CassandraCoordinatorDCKey = attribute.Key("cassandra.coordinator.dc")
+
+	// CassandraCoordinatorIDKey is the attribute Key conforming to the
+	// "cassandra.coordinator.id" semantic conventions. It represents the ID of the
+	// coordinating node for a query.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: be13faa2-8574-4d71-926d-27f16cf8a7af
+	CassandraCoordinatorIDKey = attribute.Key("cassandra.coordinator.id")
+
+	// CassandraPageSizeKey is the attribute Key conforming to the
+	// "cassandra.page.size" semantic conventions. It represents the fetch size used
+	// for paging, i.e. how many rows will be returned at once.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 5000
+	CassandraPageSizeKey = attribute.Key("cassandra.page.size")
+
+	// CassandraQueryIdempotentKey is the attribute Key conforming to the
+	// "cassandra.query.idempotent" semantic conventions. It represents the whether
+	// or not the query is idempotent.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	CassandraQueryIdempotentKey = attribute.Key("cassandra.query.idempotent")
+
+	// CassandraSpeculativeExecutionCountKey is the attribute Key conforming to the
+	// "cassandra.speculative_execution.count" semantic conventions. It represents
+	// the number of times a query was speculatively executed. Not set or `0` if the
+	// query was not executed speculatively.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0, 2
+	CassandraSpeculativeExecutionCountKey = attribute.Key("cassandra.speculative_execution.count")
+)
+
+// CassandraCoordinatorDC returns an attribute KeyValue conforming to the
+// "cassandra.coordinator.dc" semantic conventions. It represents the data center
+// of the coordinating node for a query.
+func CassandraCoordinatorDC(val string) attribute.KeyValue {
+	return CassandraCoordinatorDCKey.String(val)
+}
+
+// CassandraCoordinatorID returns an attribute KeyValue conforming to the
+// "cassandra.coordinator.id" semantic conventions. It represents the ID of the
+// coordinating node for a query.
+func CassandraCoordinatorID(val string) attribute.KeyValue {
+	return CassandraCoordinatorIDKey.String(val)
+}
+
+// CassandraPageSize returns an attribute KeyValue conforming to the
+// "cassandra.page.size" semantic conventions. It represents the fetch size used
+// for paging, i.e. how many rows will be returned at once.
+func CassandraPageSize(val int) attribute.KeyValue {
+	return CassandraPageSizeKey.Int(val)
+}
+
+// CassandraQueryIdempotent returns an attribute KeyValue conforming to the
+// "cassandra.query.idempotent" semantic conventions. It represents the whether
+// or not the query is idempotent.
+func CassandraQueryIdempotent(val bool) attribute.KeyValue {
+	return CassandraQueryIdempotentKey.Bool(val)
+}
+
+// CassandraSpeculativeExecutionCount returns an attribute KeyValue conforming to
+// the "cassandra.speculative_execution.count" semantic conventions. It
+// represents the number of times a query was speculatively executed. Not set or
+// `0` if the query was not executed speculatively.
+func CassandraSpeculativeExecutionCount(val int) attribute.KeyValue {
+	return CassandraSpeculativeExecutionCountKey.Int(val)
+}
+
+// Enum values for cassandra.consistency.level
+var (
+	// all
+	// Stability: development
+	CassandraConsistencyLevelAll = CassandraConsistencyLevelKey.String("all")
+	// each_quorum
+	// Stability: development
+	CassandraConsistencyLevelEachQuorum = CassandraConsistencyLevelKey.String("each_quorum")
+	// quorum
+	// Stability: development
+	CassandraConsistencyLevelQuorum = CassandraConsistencyLevelKey.String("quorum")
+	// local_quorum
+	// Stability: development
+	CassandraConsistencyLevelLocalQuorum = CassandraConsistencyLevelKey.String("local_quorum")
+	// one
+	// Stability: development
+	CassandraConsistencyLevelOne = CassandraConsistencyLevelKey.String("one")
+	// two
+	// Stability: development
+	CassandraConsistencyLevelTwo = CassandraConsistencyLevelKey.String("two")
+	// three
+	// Stability: development
+	CassandraConsistencyLevelThree = CassandraConsistencyLevelKey.String("three")
+	// local_one
+	// Stability: development
+	CassandraConsistencyLevelLocalOne = CassandraConsistencyLevelKey.String("local_one")
+	// any
+	// Stability: development
+	CassandraConsistencyLevelAny = CassandraConsistencyLevelKey.String("any")
+	// serial
+	// Stability: development
+	CassandraConsistencyLevelSerial = CassandraConsistencyLevelKey.String("serial")
+	// local_serial
+	// Stability: development
+	CassandraConsistencyLevelLocalSerial = CassandraConsistencyLevelKey.String("local_serial")
+)
+
+// Namespace: cicd
+const (
+	// CICDPipelineActionNameKey is the attribute Key conforming to the
+	// "cicd.pipeline.action.name" semantic conventions. It represents the kind of
+	// action a pipeline run is performing.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "BUILD", "RUN", "SYNC"
+	CICDPipelineActionNameKey = attribute.Key("cicd.pipeline.action.name")
+
+	// CICDPipelineNameKey is the attribute Key conforming to the
+	// "cicd.pipeline.name" semantic conventions. It represents the human readable
+	// name of the pipeline within a CI/CD system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Build and Test", "Lint", "Deploy Go Project",
+	// "deploy_to_environment"
+	CICDPipelineNameKey = attribute.Key("cicd.pipeline.name")
+
+	// CICDPipelineResultKey is the attribute Key conforming to the
+	// "cicd.pipeline.result" semantic conventions. It represents the result of a
+	// pipeline run.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "success", "failure", "timeout", "skipped"
+	CICDPipelineResultKey = attribute.Key("cicd.pipeline.result")
+
+	// CICDPipelineRunIDKey is the attribute Key conforming to the
+	// "cicd.pipeline.run.id" semantic conventions. It represents the unique
+	// identifier of a pipeline run within a CI/CD system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "120912"
+	CICDPipelineRunIDKey = attribute.Key("cicd.pipeline.run.id")
+
+	// CICDPipelineRunStateKey is the attribute Key conforming to the
+	// "cicd.pipeline.run.state" semantic conventions. It represents the pipeline
+	// run goes through these states during its lifecycle.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "pending", "executing", "finalizing"
+	CICDPipelineRunStateKey = attribute.Key("cicd.pipeline.run.state")
+
+	// CICDPipelineRunURLFullKey is the attribute Key conforming to the
+	// "cicd.pipeline.run.url.full" semantic conventions. It represents the [URL] of
+	// the pipeline run, providing the complete address in order to locate and
+	// identify the pipeline run.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "https://github.com/open-telemetry/semantic-conventions/actions/runs/9753949763?pr=1075"
+	//
+	// [URL]: https://wikipedia.org/wiki/URL
+	CICDPipelineRunURLFullKey = attribute.Key("cicd.pipeline.run.url.full")
+
+	// CICDPipelineTaskNameKey is the attribute Key conforming to the
+	// "cicd.pipeline.task.name" semantic conventions. It represents the human
+	// readable name of a task within a pipeline. Task here most closely aligns with
+	// a [computing process] in a pipeline. Other terms for tasks include commands,
+	// steps, and procedures.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Run GoLang Linter", "Go Build", "go-test", "deploy_binary"
+	//
+	// [computing process]: https://wikipedia.org/wiki/Pipeline_(computing)
+	CICDPipelineTaskNameKey = attribute.Key("cicd.pipeline.task.name")
+
+	// CICDPipelineTaskRunIDKey is the attribute Key conforming to the
+	// "cicd.pipeline.task.run.id" semantic conventions. It represents the unique
+	// identifier of a task run within a pipeline.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "12097"
+	CICDPipelineTaskRunIDKey = attribute.Key("cicd.pipeline.task.run.id")
+
+	// CICDPipelineTaskRunResultKey is the attribute Key conforming to the
+	// "cicd.pipeline.task.run.result" semantic conventions. It represents the
+	// result of a task run.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "success", "failure", "timeout", "skipped"
+	CICDPipelineTaskRunResultKey = attribute.Key("cicd.pipeline.task.run.result")
+
+	// CICDPipelineTaskRunURLFullKey is the attribute Key conforming to the
+	// "cicd.pipeline.task.run.url.full" semantic conventions. It represents the
+	// [URL] of the pipeline task run, providing the complete address in order to
+	// locate and identify the pipeline task run.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "https://github.com/open-telemetry/semantic-conventions/actions/runs/9753949763/job/26920038674?pr=1075"
+	//
+	// [URL]: https://wikipedia.org/wiki/URL
+	CICDPipelineTaskRunURLFullKey = attribute.Key("cicd.pipeline.task.run.url.full")
+
+	// CICDPipelineTaskTypeKey is the attribute Key conforming to the
+	// "cicd.pipeline.task.type" semantic conventions. It represents the type of the
+	// task within a pipeline.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "build", "test", "deploy"
+	CICDPipelineTaskTypeKey = attribute.Key("cicd.pipeline.task.type")
+
+	// CICDSystemComponentKey is the attribute Key conforming to the
+	// "cicd.system.component" semantic conventions. It represents the name of a
+	// component of the CICD system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "controller", "scheduler", "agent"
+	CICDSystemComponentKey = attribute.Key("cicd.system.component")
+
+	// CICDWorkerIDKey is the attribute Key conforming to the "cicd.worker.id"
+	// semantic conventions. It represents the unique identifier of a worker within
+	// a CICD system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "abc123", "10.0.1.2", "controller"
+	CICDWorkerIDKey = attribute.Key("cicd.worker.id")
+
+	// CICDWorkerNameKey is the attribute Key conforming to the "cicd.worker.name"
+	// semantic conventions. It represents the name of a worker within a CICD
+	// system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "agent-abc", "controller", "Ubuntu LTS"
+	CICDWorkerNameKey = attribute.Key("cicd.worker.name")
+
+	// CICDWorkerStateKey is the attribute Key conforming to the "cicd.worker.state"
+	// semantic conventions. It represents the state of a CICD worker / agent.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "idle", "busy", "down"
+	CICDWorkerStateKey = attribute.Key("cicd.worker.state")
+
+	// CICDWorkerURLFullKey is the attribute Key conforming to the
+	// "cicd.worker.url.full" semantic conventions. It represents the [URL] of the
+	// worker, providing the complete address in order to locate and identify the
+	// worker.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "https://cicd.example.org/worker/abc123"
+	//
+	// [URL]: https://wikipedia.org/wiki/URL
+	CICDWorkerURLFullKey = attribute.Key("cicd.worker.url.full")
+)
+
+// CICDPipelineName returns an attribute KeyValue conforming to the
+// "cicd.pipeline.name" semantic conventions. It represents the human readable
+// name of the pipeline within a CI/CD system.
+func CICDPipelineName(val string) attribute.KeyValue {
+	return CICDPipelineNameKey.String(val)
+}
+
+// CICDPipelineRunID returns an attribute KeyValue conforming to the
+// "cicd.pipeline.run.id" semantic conventions. It represents the unique
+// identifier of a pipeline run within a CI/CD system.
+func CICDPipelineRunID(val string) attribute.KeyValue {
+	return CICDPipelineRunIDKey.String(val)
+}
+
+// CICDPipelineRunURLFull returns an attribute KeyValue conforming to the
+// "cicd.pipeline.run.url.full" semantic conventions. It represents the [URL] of
+// the pipeline run, providing the complete address in order to locate and
+// identify the pipeline run.
+//
+// [URL]: https://wikipedia.org/wiki/URL
+func CICDPipelineRunURLFull(val string) attribute.KeyValue {
+	return CICDPipelineRunURLFullKey.String(val)
+}
+
+// CICDPipelineTaskName returns an attribute KeyValue conforming to the
+// "cicd.pipeline.task.name" semantic conventions. It represents the human
+// readable name of a task within a pipeline. Task here most closely aligns with
+// a [computing process] in a pipeline. Other terms for tasks include commands,
+// steps, and procedures.
+//
+// [computing process]: https://wikipedia.org/wiki/Pipeline_(computing)
+func CICDPipelineTaskName(val string) attribute.KeyValue {
+	return CICDPipelineTaskNameKey.String(val)
+}
+
+// CICDPipelineTaskRunID returns an attribute KeyValue conforming to the
+// "cicd.pipeline.task.run.id" semantic conventions. It represents the unique
+// identifier of a task run within a pipeline.
+func CICDPipelineTaskRunID(val string) attribute.KeyValue {
+	return CICDPipelineTaskRunIDKey.String(val)
+}
+
+// CICDPipelineTaskRunURLFull returns an attribute KeyValue conforming to the
+// "cicd.pipeline.task.run.url.full" semantic conventions. It represents the
+// [URL] of the pipeline task run, providing the complete address in order to
+// locate and identify the pipeline task run.
+//
+// [URL]: https://wikipedia.org/wiki/URL
+func CICDPipelineTaskRunURLFull(val string) attribute.KeyValue {
+	return CICDPipelineTaskRunURLFullKey.String(val)
+}
+
+// CICDSystemComponent returns an attribute KeyValue conforming to the
+// "cicd.system.component" semantic conventions. It represents the name of a
+// component of the CICD system.
+func CICDSystemComponent(val string) attribute.KeyValue {
+	return CICDSystemComponentKey.String(val)
+}
+
+// CICDWorkerID returns an attribute KeyValue conforming to the "cicd.worker.id"
+// semantic conventions. It represents the unique identifier of a worker within a
+// CICD system.
+func CICDWorkerID(val string) attribute.KeyValue {
+	return CICDWorkerIDKey.String(val)
+}
+
+// CICDWorkerName returns an attribute KeyValue conforming to the
+// "cicd.worker.name" semantic conventions. It represents the name of a worker
+// within a CICD system.
+func CICDWorkerName(val string) attribute.KeyValue {
+	return CICDWorkerNameKey.String(val)
+}
+
+// CICDWorkerURLFull returns an attribute KeyValue conforming to the
+// "cicd.worker.url.full" semantic conventions. It represents the [URL] of the
+// worker, providing the complete address in order to locate and identify the
+// worker.
+//
+// [URL]: https://wikipedia.org/wiki/URL
+func CICDWorkerURLFull(val string) attribute.KeyValue {
+	return CICDWorkerURLFullKey.String(val)
+}
+
+// Enum values for cicd.pipeline.action.name
+var (
+	// The pipeline run is executing a build.
+	// Stability: development
+	CICDPipelineActionNameBuild = CICDPipelineActionNameKey.String("BUILD")
+	// The pipeline run is executing.
+	// Stability: development
+	CICDPipelineActionNameRun = CICDPipelineActionNameKey.String("RUN")
+	// The pipeline run is executing a sync.
+	// Stability: development
+	CICDPipelineActionNameSync = CICDPipelineActionNameKey.String("SYNC")
+)
+
+// Enum values for cicd.pipeline.result
+var (
+	// The pipeline run finished successfully.
+	// Stability: development
+	CICDPipelineResultSuccess = CICDPipelineResultKey.String("success")
+	// The pipeline run did not finish successfully, eg. due to a compile error or a
+	// failing test. Such failures are usually detected by non-zero exit codes of
+	// the tools executed in the pipeline run.
+	// Stability: development
+	CICDPipelineResultFailure = CICDPipelineResultKey.String("failure")
+	// The pipeline run failed due to an error in the CICD system, eg. due to the
+	// worker being killed.
+	// Stability: development
+	CICDPipelineResultError = CICDPipelineResultKey.String("error")
+	// A timeout caused the pipeline run to be interrupted.
+	// Stability: development
+	CICDPipelineResultTimeout = CICDPipelineResultKey.String("timeout")
+	// The pipeline run was cancelled, eg. by a user manually cancelling the
+	// pipeline run.
+	// Stability: development
+	CICDPipelineResultCancellation = CICDPipelineResultKey.String("cancellation")
+	// The pipeline run was skipped, eg. due to a precondition not being met.
+	// Stability: development
+	CICDPipelineResultSkip = CICDPipelineResultKey.String("skip")
+)
+
+// Enum values for cicd.pipeline.run.state
+var (
+	// The run pending state spans from the event triggering the pipeline run until
+	// the execution of the run starts (eg. time spent in a queue, provisioning
+	// agents, creating run resources).
+	//
+	// Stability: development
+	CICDPipelineRunStatePending = CICDPipelineRunStateKey.String("pending")
+	// The executing state spans the execution of any run tasks (eg. build, test).
+	// Stability: development
+	CICDPipelineRunStateExecuting = CICDPipelineRunStateKey.String("executing")
+	// The finalizing state spans from when the run has finished executing (eg.
+	// cleanup of run resources).
+	// Stability: development
+	CICDPipelineRunStateFinalizing = CICDPipelineRunStateKey.String("finalizing")
+)
+
+// Enum values for cicd.pipeline.task.run.result
+var (
+	// The task run finished successfully.
+	// Stability: development
+	CICDPipelineTaskRunResultSuccess = CICDPipelineTaskRunResultKey.String("success")
+	// The task run did not finish successfully, eg. due to a compile error or a
+	// failing test. Such failures are usually detected by non-zero exit codes of
+	// the tools executed in the task run.
+	// Stability: development
+	CICDPipelineTaskRunResultFailure = CICDPipelineTaskRunResultKey.String("failure")
+	// The task run failed due to an error in the CICD system, eg. due to the worker
+	// being killed.
+	// Stability: development
+	CICDPipelineTaskRunResultError = CICDPipelineTaskRunResultKey.String("error")
+	// A timeout caused the task run to be interrupted.
+	// Stability: development
+	CICDPipelineTaskRunResultTimeout = CICDPipelineTaskRunResultKey.String("timeout")
+	// The task run was cancelled, eg. by a user manually cancelling the task run.
+	// Stability: development
+	CICDPipelineTaskRunResultCancellation = CICDPipelineTaskRunResultKey.String("cancellation")
+	// The task run was skipped, eg. due to a precondition not being met.
+	// Stability: development
+	CICDPipelineTaskRunResultSkip = CICDPipelineTaskRunResultKey.String("skip")
+)
+
+// Enum values for cicd.pipeline.task.type
+var (
+	// build
+	// Stability: development
+	CICDPipelineTaskTypeBuild = CICDPipelineTaskTypeKey.String("build")
+	// test
+	// Stability: development
+	CICDPipelineTaskTypeTest = CICDPipelineTaskTypeKey.String("test")
+	// deploy
+	// Stability: development
+	CICDPipelineTaskTypeDeploy = CICDPipelineTaskTypeKey.String("deploy")
+)
+
+// Enum values for cicd.worker.state
+var (
+	// The worker is not performing work for the CICD system. It is available to the
+	// CICD system to perform work on (online / idle).
+	// Stability: development
+	CICDWorkerStateAvailable = CICDWorkerStateKey.String("available")
+	// The worker is performing work for the CICD system.
+	// Stability: development
+	CICDWorkerStateBusy = CICDWorkerStateKey.String("busy")
+	// The worker is not available to the CICD system (disconnected / down).
+	// Stability: development
+	CICDWorkerStateOffline = CICDWorkerStateKey.String("offline")
+)
+
+// Namespace: client
+const (
+	// ClientAddressKey is the attribute Key conforming to the "client.address"
+	// semantic conventions. It represents the client address - domain name if
+	// available without reverse DNS lookup; otherwise, IP address or Unix domain
+	// socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "client.example.com", "10.1.2.80", "/tmp/my.sock"
+	// Note: When observed from the server side, and when communicating through an
+	// intermediary, `client.address` SHOULD represent the client address behind any
+	// intermediaries, for example proxies, if it's available.
+	ClientAddressKey = attribute.Key("client.address")
+
+	// ClientPortKey is the attribute Key conforming to the "client.port" semantic
+	// conventions. It represents the client port number.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 65123
+	// Note: When observed from the server side, and when communicating through an
+	// intermediary, `client.port` SHOULD represent the client port behind any
+	// intermediaries, for example proxies, if it's available.
+	ClientPortKey = attribute.Key("client.port")
+)
+
+// ClientAddress returns an attribute KeyValue conforming to the "client.address"
+// semantic conventions. It represents the client address - domain name if
+// available without reverse DNS lookup; otherwise, IP address or Unix domain
+// socket name.
+func ClientAddress(val string) attribute.KeyValue {
+	return ClientAddressKey.String(val)
+}
+
+// ClientPort returns an attribute KeyValue conforming to the "client.port"
+// semantic conventions. It represents the client port number.
+func ClientPort(val int) attribute.KeyValue {
+	return ClientPortKey.Int(val)
+}
+
+// Namespace: cloud
+const (
+	// CloudAccountIDKey is the attribute Key conforming to the "cloud.account.id"
+	// semantic conventions. It represents the cloud account ID the resource is
+	// assigned to.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "111111111111", "opentelemetry"
+	CloudAccountIDKey = attribute.Key("cloud.account.id")
+
+	// CloudAvailabilityZoneKey is the attribute Key conforming to the
+	// "cloud.availability_zone" semantic conventions. It represents the cloud
+	// regions often have multiple, isolated locations known as zones to increase
+	// availability. Availability zone represents the zone where the resource is
+	// running.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "us-east-1c"
+	// Note: Availability zones are called "zones" on Alibaba Cloud and Google
+	// Cloud.
+	CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone")
+
+	// CloudPlatformKey is the attribute Key conforming to the "cloud.platform"
+	// semantic conventions. It represents the cloud platform in use.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: The prefix of the service SHOULD match the one specified in
+	// `cloud.provider`.
+	CloudPlatformKey = attribute.Key("cloud.platform")
+
+	// CloudProviderKey is the attribute Key conforming to the "cloud.provider"
+	// semantic conventions. It represents the name of the cloud provider.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	CloudProviderKey = attribute.Key("cloud.provider")
+
+	// CloudRegionKey is the attribute Key conforming to the "cloud.region" semantic
+	// conventions. It represents the geographical region within a cloud provider.
+	// When associated with a resource, this attribute specifies the region where
+	// the resource operates. When calling services or APIs deployed on a cloud,
+	// this attribute identifies the region where the called destination is
+	// deployed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "us-central1", "us-east-1"
+	// Note: Refer to your provider's docs to see the available regions, for example
+	// [Alibaba Cloud regions], [AWS regions], [Azure regions],
+	// [Google Cloud regions], or [Tencent Cloud regions].
+	//
+	// [Alibaba Cloud regions]: https://www.alibabacloud.com/help/doc-detail/40654.htm
+	// [AWS regions]: https://aws.amazon.com/about-aws/global-infrastructure/regions_az/
+	// [Azure regions]: https://azure.microsoft.com/global-infrastructure/geographies/
+	// [Google Cloud regions]: https://cloud.google.com/about/locations
+	// [Tencent Cloud regions]: https://www.tencentcloud.com/document/product/213/6091
+	CloudRegionKey = attribute.Key("cloud.region")
+
+	// CloudResourceIDKey is the attribute Key conforming to the "cloud.resource_id"
+	// semantic conventions. It represents the cloud provider-specific native
+	// identifier of the monitored cloud resource (e.g. an [ARN] on AWS, a
+	// [fully qualified resource ID] on Azure, a [full resource name] on GCP).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function",
+	// "//run.googleapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID",
+	// "/subscriptions//resourceGroups/
+	// /providers/Microsoft.Web/sites//functions/"
+	// Note: On some cloud providers, it may not be possible to determine the full
+	// ID at startup,
+	// so it may be necessary to set `cloud.resource_id` as a span attribute
+	// instead.
+	//
+	// The exact value to use for `cloud.resource_id` depends on the cloud provider.
+	// The following well-known definitions MUST be used if you set this attribute
+	// and they apply:
+	//
+	//   - **AWS Lambda:** The function [ARN].
+	//     Take care not to use the "invoked ARN" directly but replace any
+	//     [alias suffix]
+	//     with the resolved function version, as the same runtime instance may be
+	//     invocable with
+	//     multiple different aliases.
+	//   - **GCP:** The [URI of the resource]
+	//   - **Azure:** The [Fully Qualified Resource ID] of the invoked function,
+	//     *not* the function app, having the form
+	//
+	//     `/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/`
+	//     .
+	//     This means that a span attribute MUST be used, as an Azure function app
+	//     can host multiple functions that would usually share
+	//     a TracerProvider.
+	//
+	//
+	// [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
+	// [fully qualified resource ID]: https://learn.microsoft.com/rest/api/resources/resources/get-by-id
+	// [full resource name]: https://google.aip.dev/122#full-resource-names
+	// [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
+	// [alias suffix]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html
+	// [URI of the resource]: https://cloud.google.com/iam/docs/full-resource-names
+	// [Fully Qualified Resource ID]: https://docs.microsoft.com/rest/api/resources/resources/get-by-id
+	CloudResourceIDKey = attribute.Key("cloud.resource_id")
+)
+
+// CloudAccountID returns an attribute KeyValue conforming to the
+// "cloud.account.id" semantic conventions. It represents the cloud account ID
+// the resource is assigned to.
+func CloudAccountID(val string) attribute.KeyValue {
+	return CloudAccountIDKey.String(val)
+}
+
+// CloudAvailabilityZone returns an attribute KeyValue conforming to the
+// "cloud.availability_zone" semantic conventions. It represents the cloud
+// regions often have multiple, isolated locations known as zones to increase
+// availability. Availability zone represents the zone where the resource is
+// running.
+func CloudAvailabilityZone(val string) attribute.KeyValue {
+	return CloudAvailabilityZoneKey.String(val)
+}
+
+// CloudRegion returns an attribute KeyValue conforming to the "cloud.region"
+// semantic conventions. It represents the geographical region within a cloud
+// provider. When associated with a resource, this attribute specifies the region
+// where the resource operates. When calling services or APIs deployed on a
+// cloud, this attribute identifies the region where the called destination is
+// deployed.
+func CloudRegion(val string) attribute.KeyValue {
+	return CloudRegionKey.String(val)
+}
+
+// CloudResourceID returns an attribute KeyValue conforming to the
+// "cloud.resource_id" semantic conventions. It represents the cloud
+// provider-specific native identifier of the monitored cloud resource (e.g. an
+// [ARN] on AWS, a [fully qualified resource ID] on Azure, a [full resource name]
+//  on GCP).
+//
+// [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
+// [fully qualified resource ID]: https://learn.microsoft.com/rest/api/resources/resources/get-by-id
+// [full resource name]: https://google.aip.dev/122#full-resource-names
+func CloudResourceID(val string) attribute.KeyValue {
+	return CloudResourceIDKey.String(val)
+}
+
+// Enum values for cloud.platform
+var (
+	// Alibaba Cloud Elastic Compute Service
+	// Stability: development
+	CloudPlatformAlibabaCloudECS = CloudPlatformKey.String("alibaba_cloud_ecs")
+	// Alibaba Cloud Function Compute
+	// Stability: development
+	CloudPlatformAlibabaCloudFC = CloudPlatformKey.String("alibaba_cloud_fc")
+	// Red Hat OpenShift on Alibaba Cloud
+	// Stability: development
+	CloudPlatformAlibabaCloudOpenShift = CloudPlatformKey.String("alibaba_cloud_openshift")
+	// AWS Elastic Compute Cloud
+	// Stability: development
+	CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2")
+	// AWS Elastic Container Service
+	// Stability: development
+	CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs")
+	// AWS Elastic Kubernetes Service
+	// Stability: development
+	CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks")
+	// AWS Lambda
+	// Stability: development
+	CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda")
+	// AWS Elastic Beanstalk
+	// Stability: development
+	CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk")
+	// AWS App Runner
+	// Stability: development
+	CloudPlatformAWSAppRunner = CloudPlatformKey.String("aws_app_runner")
+	// Red Hat OpenShift on AWS (ROSA)
+	// Stability: development
+	CloudPlatformAWSOpenShift = CloudPlatformKey.String("aws_openshift")
+	// Azure Virtual Machines
+	// Stability: development
+	CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm")
+	// Azure Container Apps
+	// Stability: development
+	CloudPlatformAzureContainerApps = CloudPlatformKey.String("azure_container_apps")
+	// Azure Container Instances
+	// Stability: development
+	CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances")
+	// Azure Kubernetes Service
+	// Stability: development
+	CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks")
+	// Azure Functions
+	// Stability: development
+	CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions")
+	// Azure App Service
+	// Stability: development
+	CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service")
+	// Azure Red Hat OpenShift
+	// Stability: development
+	CloudPlatformAzureOpenShift = CloudPlatformKey.String("azure_openshift")
+	// Google Bare Metal Solution (BMS)
+	// Stability: development
+	CloudPlatformGCPBareMetalSolution = CloudPlatformKey.String("gcp_bare_metal_solution")
+	// Google Cloud Compute Engine (GCE)
+	// Stability: development
+	CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine")
+	// Google Cloud Run
+	// Stability: development
+	CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run")
+	// Google Cloud Kubernetes Engine (GKE)
+	// Stability: development
+	CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine")
+	// Google Cloud Functions (GCF)
+	// Stability: development
+	CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions")
+	// Google Cloud App Engine (GAE)
+	// Stability: development
+	CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine")
+	// Red Hat OpenShift on Google Cloud
+	// Stability: development
+	CloudPlatformGCPOpenShift = CloudPlatformKey.String("gcp_openshift")
+	// Red Hat OpenShift on IBM Cloud
+	// Stability: development
+	CloudPlatformIBMCloudOpenShift = CloudPlatformKey.String("ibm_cloud_openshift")
+	// Compute on Oracle Cloud Infrastructure (OCI)
+	// Stability: development
+	CloudPlatformOracleCloudCompute = CloudPlatformKey.String("oracle_cloud_compute")
+	// Kubernetes Engine (OKE) on Oracle Cloud Infrastructure (OCI)
+	// Stability: development
+	CloudPlatformOracleCloudOKE = CloudPlatformKey.String("oracle_cloud_oke")
+	// Tencent Cloud Cloud Virtual Machine (CVM)
+	// Stability: development
+	CloudPlatformTencentCloudCVM = CloudPlatformKey.String("tencent_cloud_cvm")
+	// Tencent Cloud Elastic Kubernetes Service (EKS)
+	// Stability: development
+	CloudPlatformTencentCloudEKS = CloudPlatformKey.String("tencent_cloud_eks")
+	// Tencent Cloud Serverless Cloud Function (SCF)
+	// Stability: development
+	CloudPlatformTencentCloudSCF = CloudPlatformKey.String("tencent_cloud_scf")
+)
+
+// Enum values for cloud.provider
+var (
+	// Alibaba Cloud
+	// Stability: development
+	CloudProviderAlibabaCloud = CloudProviderKey.String("alibaba_cloud")
+	// Amazon Web Services
+	// Stability: development
+	CloudProviderAWS = CloudProviderKey.String("aws")
+	// Microsoft Azure
+	// Stability: development
+	CloudProviderAzure = CloudProviderKey.String("azure")
+	// Google Cloud Platform
+	// Stability: development
+	CloudProviderGCP = CloudProviderKey.String("gcp")
+	// Heroku Platform as a Service
+	// Stability: development
+	CloudProviderHeroku = CloudProviderKey.String("heroku")
+	// IBM Cloud
+	// Stability: development
+	CloudProviderIBMCloud = CloudProviderKey.String("ibm_cloud")
+	// Oracle Cloud Infrastructure (OCI)
+	// Stability: development
+	CloudProviderOracleCloud = CloudProviderKey.String("oracle_cloud")
+	// Tencent Cloud
+	// Stability: development
+	CloudProviderTencentCloud = CloudProviderKey.String("tencent_cloud")
+)
+
+// Namespace: cloudevents
+const (
+	// CloudEventsEventIDKey is the attribute Key conforming to the
+	// "cloudevents.event_id" semantic conventions. It represents the [event_id]
+	// uniquely identifies the event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "123e4567-e89b-12d3-a456-426614174000", "0001"
+	//
+	// [event_id]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id
+	CloudEventsEventIDKey = attribute.Key("cloudevents.event_id")
+
+	// CloudEventsEventSourceKey is the attribute Key conforming to the
+	// "cloudevents.event_source" semantic conventions. It represents the [source]
+	// identifies the context in which an event happened.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "https://github.com/cloudevents", "/cloudevents/spec/pull/123",
+	// "my-service"
+	//
+	// [source]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1
+	CloudEventsEventSourceKey = attribute.Key("cloudevents.event_source")
+
+	// CloudEventsEventSpecVersionKey is the attribute Key conforming to the
+	// "cloudevents.event_spec_version" semantic conventions. It represents the
+	// [version of the CloudEvents specification] which the event uses.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1.0
+	//
+	// [version of the CloudEvents specification]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion
+	CloudEventsEventSpecVersionKey = attribute.Key("cloudevents.event_spec_version")
+
+	// CloudEventsEventSubjectKey is the attribute Key conforming to the
+	// "cloudevents.event_subject" semantic conventions. It represents the [subject]
+	//  of the event in the context of the event producer (identified by source).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: mynewfile.jpg
+	//
+	// [subject]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject
+	CloudEventsEventSubjectKey = attribute.Key("cloudevents.event_subject")
+
+	// CloudEventsEventTypeKey is the attribute Key conforming to the
+	// "cloudevents.event_type" semantic conventions. It represents the [event_type]
+	//  contains a value describing the type of event related to the originating
+	// occurrence.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "com.github.pull_request.opened", "com.example.object.deleted.v2"
+	//
+	// [event_type]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type
+	CloudEventsEventTypeKey = attribute.Key("cloudevents.event_type")
+)
+
+// CloudEventsEventID returns an attribute KeyValue conforming to the
+// "cloudevents.event_id" semantic conventions. It represents the [event_id]
+// uniquely identifies the event.
+//
+// [event_id]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id
+func CloudEventsEventID(val string) attribute.KeyValue {
+	return CloudEventsEventIDKey.String(val)
+}
+
+// CloudEventsEventSource returns an attribute KeyValue conforming to the
+// "cloudevents.event_source" semantic conventions. It represents the [source]
+// identifies the context in which an event happened.
+//
+// [source]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1
+func CloudEventsEventSource(val string) attribute.KeyValue {
+	return CloudEventsEventSourceKey.String(val)
+}
+
+// CloudEventsEventSpecVersion returns an attribute KeyValue conforming to the
+// "cloudevents.event_spec_version" semantic conventions. It represents the
+// [version of the CloudEvents specification] which the event uses.
+//
+// [version of the CloudEvents specification]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion
+func CloudEventsEventSpecVersion(val string) attribute.KeyValue {
+	return CloudEventsEventSpecVersionKey.String(val)
+}
+
+// CloudEventsEventSubject returns an attribute KeyValue conforming to the
+// "cloudevents.event_subject" semantic conventions. It represents the [subject]
+// of the event in the context of the event producer (identified by source).
+//
+// [subject]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject
+func CloudEventsEventSubject(val string) attribute.KeyValue {
+	return CloudEventsEventSubjectKey.String(val)
+}
+
+// CloudEventsEventType returns an attribute KeyValue conforming to the
+// "cloudevents.event_type" semantic conventions. It represents the [event_type]
+// contains a value describing the type of event related to the originating
+// occurrence.
+//
+// [event_type]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type
+func CloudEventsEventType(val string) attribute.KeyValue {
+	return CloudEventsEventTypeKey.String(val)
+}
+
+// Namespace: cloudfoundry
+const (
+	// CloudFoundryAppIDKey is the attribute Key conforming to the
+	// "cloudfoundry.app.id" semantic conventions. It represents the guid of the
+	// application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.application_id`. This is the same value as
+	// reported by `cf app  --guid`.
+	CloudFoundryAppIDKey = attribute.Key("cloudfoundry.app.id")
+
+	// CloudFoundryAppInstanceIDKey is the attribute Key conforming to the
+	// "cloudfoundry.app.instance.id" semantic conventions. It represents the index
+	// of the application instance. 0 when just one instance is active.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0", "1"
+	// Note: CloudFoundry defines the `instance_id` in the [Loggregator v2 envelope]
+	// .
+	// It is used for logs and metrics emitted by CloudFoundry. It is
+	// supposed to contain the application instance index for applications
+	// deployed on the runtime.
+	//
+	// Application instrumentation should use the value from environment
+	// variable `CF_INSTANCE_INDEX`.
+	//
+	// [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope
+	CloudFoundryAppInstanceIDKey = attribute.Key("cloudfoundry.app.instance.id")
+
+	// CloudFoundryAppNameKey is the attribute Key conforming to the
+	// "cloudfoundry.app.name" semantic conventions. It represents the name of the
+	// application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-app-name"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.application_name`. This is the same value
+	// as reported by `cf apps`.
+	CloudFoundryAppNameKey = attribute.Key("cloudfoundry.app.name")
+
+	// CloudFoundryOrgIDKey is the attribute Key conforming to the
+	// "cloudfoundry.org.id" semantic conventions. It represents the guid of the
+	// CloudFoundry org the application is running in.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.org_id`. This is the same value as
+	// reported by `cf org  --guid`.
+	CloudFoundryOrgIDKey = attribute.Key("cloudfoundry.org.id")
+
+	// CloudFoundryOrgNameKey is the attribute Key conforming to the
+	// "cloudfoundry.org.name" semantic conventions. It represents the name of the
+	// CloudFoundry organization the app is running in.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-org-name"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.org_name`. This is the same value as
+	// reported by `cf orgs`.
+	CloudFoundryOrgNameKey = attribute.Key("cloudfoundry.org.name")
+
+	// CloudFoundryProcessIDKey is the attribute Key conforming to the
+	// "cloudfoundry.process.id" semantic conventions. It represents the UID
+	// identifying the process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.process_id`. It is supposed to be equal to
+	// `VCAP_APPLICATION.app_id` for applications deployed to the runtime.
+	// For system components, this could be the actual PID.
+	CloudFoundryProcessIDKey = attribute.Key("cloudfoundry.process.id")
+
+	// CloudFoundryProcessTypeKey is the attribute Key conforming to the
+	// "cloudfoundry.process.type" semantic conventions. It represents the type of
+	// process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "web"
+	// Note: CloudFoundry applications can consist of multiple jobs. Usually the
+	// main process will be of type `web`. There can be additional background
+	// tasks or side-cars with different process types.
+	CloudFoundryProcessTypeKey = attribute.Key("cloudfoundry.process.type")
+
+	// CloudFoundrySpaceIDKey is the attribute Key conforming to the
+	// "cloudfoundry.space.id" semantic conventions. It represents the guid of the
+	// CloudFoundry space the application is running in.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.space_id`. This is the same value as
+	// reported by `cf space  --guid`.
+	CloudFoundrySpaceIDKey = attribute.Key("cloudfoundry.space.id")
+
+	// CloudFoundrySpaceNameKey is the attribute Key conforming to the
+	// "cloudfoundry.space.name" semantic conventions. It represents the name of the
+	// CloudFoundry space the application is running in.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-space-name"
+	// Note: Application instrumentation should use the value from environment
+	// variable `VCAP_APPLICATION.space_name`. This is the same value as
+	// reported by `cf spaces`.
+	CloudFoundrySpaceNameKey = attribute.Key("cloudfoundry.space.name")
+
+	// CloudFoundrySystemIDKey is the attribute Key conforming to the
+	// "cloudfoundry.system.id" semantic conventions. It represents a guid or
+	// another name describing the event source.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "cf/gorouter"
+	// Note: CloudFoundry defines the `source_id` in the [Loggregator v2 envelope].
+	// It is used for logs and metrics emitted by CloudFoundry. It is
+	// supposed to contain the component name, e.g. "gorouter", for
+	// CloudFoundry components.
+	//
+	// When system components are instrumented, values from the
+	// [Bosh spec]
+	// should be used. The `system.id` should be set to
+	// `spec.deployment/spec.name`.
+	//
+	// [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope
+	// [Bosh spec]: https://bosh.io/docs/jobs/#properties-spec
+	CloudFoundrySystemIDKey = attribute.Key("cloudfoundry.system.id")
+
+	// CloudFoundrySystemInstanceIDKey is the attribute Key conforming to the
+	// "cloudfoundry.system.instance.id" semantic conventions. It represents a guid
+	// describing the concrete instance of the event source.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: CloudFoundry defines the `instance_id` in the [Loggregator v2 envelope]
+	// .
+	// It is used for logs and metrics emitted by CloudFoundry. It is
+	// supposed to contain the vm id for CloudFoundry components.
+	//
+	// When system components are instrumented, values from the
+	// [Bosh spec]
+	// should be used. The `system.instance.id` should be set to `spec.id`.
+	//
+	// [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope
+	// [Bosh spec]: https://bosh.io/docs/jobs/#properties-spec
+	CloudFoundrySystemInstanceIDKey = attribute.Key("cloudfoundry.system.instance.id")
+)
+
+// CloudFoundryAppID returns an attribute KeyValue conforming to the
+// "cloudfoundry.app.id" semantic conventions. It represents the guid of the
+// application.
+func CloudFoundryAppID(val string) attribute.KeyValue {
+	return CloudFoundryAppIDKey.String(val)
+}
+
+// CloudFoundryAppInstanceID returns an attribute KeyValue conforming to the
+// "cloudfoundry.app.instance.id" semantic conventions. It represents the index
+// of the application instance. 0 when just one instance is active.
+func CloudFoundryAppInstanceID(val string) attribute.KeyValue {
+	return CloudFoundryAppInstanceIDKey.String(val)
+}
+
+// CloudFoundryAppName returns an attribute KeyValue conforming to the
+// "cloudfoundry.app.name" semantic conventions. It represents the name of the
+// application.
+func CloudFoundryAppName(val string) attribute.KeyValue {
+	return CloudFoundryAppNameKey.String(val)
+}
+
+// CloudFoundryOrgID returns an attribute KeyValue conforming to the
+// "cloudfoundry.org.id" semantic conventions. It represents the guid of the
+// CloudFoundry org the application is running in.
+func CloudFoundryOrgID(val string) attribute.KeyValue {
+	return CloudFoundryOrgIDKey.String(val)
+}
+
+// CloudFoundryOrgName returns an attribute KeyValue conforming to the
+// "cloudfoundry.org.name" semantic conventions. It represents the name of the
+// CloudFoundry organization the app is running in.
+func CloudFoundryOrgName(val string) attribute.KeyValue {
+	return CloudFoundryOrgNameKey.String(val)
+}
+
+// CloudFoundryProcessID returns an attribute KeyValue conforming to the
+// "cloudfoundry.process.id" semantic conventions. It represents the UID
+// identifying the process.
+func CloudFoundryProcessID(val string) attribute.KeyValue {
+	return CloudFoundryProcessIDKey.String(val)
+}
+
+// CloudFoundryProcessType returns an attribute KeyValue conforming to the
+// "cloudfoundry.process.type" semantic conventions. It represents the type of
+// process.
+func CloudFoundryProcessType(val string) attribute.KeyValue {
+	return CloudFoundryProcessTypeKey.String(val)
+}
+
+// CloudFoundrySpaceID returns an attribute KeyValue conforming to the
+// "cloudfoundry.space.id" semantic conventions. It represents the guid of the
+// CloudFoundry space the application is running in.
+func CloudFoundrySpaceID(val string) attribute.KeyValue {
+	return CloudFoundrySpaceIDKey.String(val)
+}
+
+// CloudFoundrySpaceName returns an attribute KeyValue conforming to the
+// "cloudfoundry.space.name" semantic conventions. It represents the name of the
+// CloudFoundry space the application is running in.
+func CloudFoundrySpaceName(val string) attribute.KeyValue {
+	return CloudFoundrySpaceNameKey.String(val)
+}
+
+// CloudFoundrySystemID returns an attribute KeyValue conforming to the
+// "cloudfoundry.system.id" semantic conventions. It represents a guid or another
+// name describing the event source.
+func CloudFoundrySystemID(val string) attribute.KeyValue {
+	return CloudFoundrySystemIDKey.String(val)
+}
+
+// CloudFoundrySystemInstanceID returns an attribute KeyValue conforming to the
+// "cloudfoundry.system.instance.id" semantic conventions. It represents a guid
+// describing the concrete instance of the event source.
+func CloudFoundrySystemInstanceID(val string) attribute.KeyValue {
+	return CloudFoundrySystemInstanceIDKey.String(val)
+}
+
+// Namespace: code
+const (
+	// CodeColumnNumberKey is the attribute Key conforming to the
+	// "code.column.number" semantic conventions. It represents the column number in
+	// `code.file.path` best representing the operation. It SHOULD point within the
+	// code unit named in `code.function.name`. This attribute MUST NOT be used on
+	// the Profile signal since the data is already captured in 'message Line'. This
+	// constraint is imposed to prevent redundancy and maintain data integrity.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	CodeColumnNumberKey = attribute.Key("code.column.number")
+
+	// CodeFilePathKey is the attribute Key conforming to the "code.file.path"
+	// semantic conventions. It represents the source code file name that identifies
+	// the code unit as uniquely as possible (preferably an absolute file path).
+	// This attribute MUST NOT be used on the Profile signal since the data is
+	// already captured in 'message Function'. This constraint is imposed to prevent
+	// redundancy and maintain data integrity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: /usr/local/MyApplication/content_root/app/index.php
+	CodeFilePathKey = attribute.Key("code.file.path")
+
+	// CodeFunctionNameKey is the attribute Key conforming to the
+	// "code.function.name" semantic conventions. It represents the method or
+	// function fully-qualified name without arguments. The value should fit the
+	// natural representation of the language runtime, which is also likely the same
+	// used within `code.stacktrace` attribute value. This attribute MUST NOT be
+	// used on the Profile signal since the data is already captured in 'message
+	// Function'. This constraint is imposed to prevent redundancy and maintain data
+	// integrity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "com.example.MyHttpService.serveRequest",
+	// "GuzzleHttp\Client::transfer", "fopen"
+	// Note: Values and format depends on each language runtime, thus it is
+	// impossible to provide an exhaustive list of examples.
+	// The values are usually the same (or prefixes of) the ones found in native
+	// stack trace representation stored in
+	// `code.stacktrace` without information on arguments.
+	//
+	// Examples:
+	//
+	//   - Java method: `com.example.MyHttpService.serveRequest`
+	//   - Java anonymous class method: `com.mycompany.Main$1.myMethod`
+	//   - Java lambda method:
+	//     `com.mycompany.Main$$Lambda/0x0000748ae4149c00.myMethod`
+	//   - PHP function: `GuzzleHttp\Client::transfer`
+	//   - Go function: `github.com/my/repo/pkg.foo.func5`
+	//   - Elixir: `OpenTelemetry.Ctx.new`
+	//   - Erlang: `opentelemetry_ctx:new`
+	//   - Rust: `playground::my_module::my_cool_func`
+	//   - C function: `fopen`
+	CodeFunctionNameKey = attribute.Key("code.function.name")
+
+	// CodeLineNumberKey is the attribute Key conforming to the "code.line.number"
+	// semantic conventions. It represents the line number in `code.file.path` best
+	// representing the operation. It SHOULD point within the code unit named in
+	// `code.function.name`. This attribute MUST NOT be used on the Profile signal
+	// since the data is already captured in 'message Line'. This constraint is
+	// imposed to prevent redundancy and maintain data integrity.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	CodeLineNumberKey = attribute.Key("code.line.number")
+
+	// CodeStacktraceKey is the attribute Key conforming to the "code.stacktrace"
+	// semantic conventions. It represents a stacktrace as a string in the natural
+	// representation for the language runtime. The representation is identical to
+	// [`exception.stacktrace`]. This attribute MUST NOT be used on the Profile
+	// signal since the data is already captured in 'message Location'. This
+	// constraint is imposed to prevent redundancy and maintain data integrity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at
+	// com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at
+	// com.example.GenerateTrace.main(GenerateTrace.java:5)
+	//
+	// [`exception.stacktrace`]: /docs/exceptions/exceptions-spans.md#stacktrace-representation
+	CodeStacktraceKey = attribute.Key("code.stacktrace")
+)
+
+// CodeColumnNumber returns an attribute KeyValue conforming to the
+// "code.column.number" semantic conventions. It represents the column number in
+// `code.file.path` best representing the operation. It SHOULD point within the
+// code unit named in `code.function.name`. This attribute MUST NOT be used on
+// the Profile signal since the data is already captured in 'message Line'. This
+// constraint is imposed to prevent redundancy and maintain data integrity.
+func CodeColumnNumber(val int) attribute.KeyValue {
+	return CodeColumnNumberKey.Int(val)
+}
+
+// CodeFilePath returns an attribute KeyValue conforming to the "code.file.path"
+// semantic conventions. It represents the source code file name that identifies
+// the code unit as uniquely as possible (preferably an absolute file path). This
+// attribute MUST NOT be used on the Profile signal since the data is already
+// captured in 'message Function'. This constraint is imposed to prevent
+// redundancy and maintain data integrity.
+func CodeFilePath(val string) attribute.KeyValue {
+	return CodeFilePathKey.String(val)
+}
+
+// CodeFunctionName returns an attribute KeyValue conforming to the
+// "code.function.name" semantic conventions. It represents the method or
+// function fully-qualified name without arguments. The value should fit the
+// natural representation of the language runtime, which is also likely the same
+// used within `code.stacktrace` attribute value. This attribute MUST NOT be used
+// on the Profile signal since the data is already captured in 'message
+// Function'. This constraint is imposed to prevent redundancy and maintain data
+// integrity.
+func CodeFunctionName(val string) attribute.KeyValue {
+	return CodeFunctionNameKey.String(val)
+}
+
+// CodeLineNumber returns an attribute KeyValue conforming to the
+// "code.line.number" semantic conventions. It represents the line number in
+// `code.file.path` best representing the operation. It SHOULD point within the
+// code unit named in `code.function.name`. This attribute MUST NOT be used on
+// the Profile signal since the data is already captured in 'message Line'. This
+// constraint is imposed to prevent redundancy and maintain data integrity.
+func CodeLineNumber(val int) attribute.KeyValue {
+	return CodeLineNumberKey.Int(val)
+}
+
+// CodeStacktrace returns an attribute KeyValue conforming to the
+// "code.stacktrace" semantic conventions. It represents a stacktrace as a string
+// in the natural representation for the language runtime. The representation is
+// identical to [`exception.stacktrace`]. This attribute MUST NOT be used on the
+// Profile signal since the data is already captured in 'message Location'. This
+// constraint is imposed to prevent redundancy and maintain data integrity.
+//
+// [`exception.stacktrace`]: /docs/exceptions/exceptions-spans.md#stacktrace-representation
+func CodeStacktrace(val string) attribute.KeyValue {
+	return CodeStacktraceKey.String(val)
+}
+
+// Namespace: container
+const (
+	// ContainerCommandKey is the attribute Key conforming to the
+	// "container.command" semantic conventions. It represents the command used to
+	// run the container (i.e. the command name).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "otelcontribcol"
+	// Note: If using embedded credentials or sensitive data, it is recommended to
+	// remove them to prevent potential leakage.
+	ContainerCommandKey = attribute.Key("container.command")
+
+	// ContainerCommandArgsKey is the attribute Key conforming to the
+	// "container.command_args" semantic conventions. It represents the all the
+	// command arguments (including the command/executable itself) run by the
+	// container.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "otelcontribcol", "--config", "config.yaml"
+	ContainerCommandArgsKey = attribute.Key("container.command_args")
+
+	// ContainerCommandLineKey is the attribute Key conforming to the
+	// "container.command_line" semantic conventions. It represents the full command
+	// run by the container as a single string representing the full command.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "otelcontribcol --config config.yaml"
+	ContainerCommandLineKey = attribute.Key("container.command_line")
+
+	// ContainerCSIPluginNameKey is the attribute Key conforming to the
+	// "container.csi.plugin.name" semantic conventions. It represents the name of
+	// the CSI ([Container Storage Interface]) plugin used by the volume.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "pd.csi.storage.gke.io"
+	// Note: This can sometimes be referred to as a "driver" in CSI implementations.
+	// This should represent the `name` field of the GetPluginInfo RPC.
+	//
+	// [Container Storage Interface]: https://github.com/container-storage-interface/spec
+	ContainerCSIPluginNameKey = attribute.Key("container.csi.plugin.name")
+
+	// ContainerCSIVolumeIDKey is the attribute Key conforming to the
+	// "container.csi.volume.id" semantic conventions. It represents the unique
+	// volume ID returned by the CSI ([Container Storage Interface]) plugin.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "projects/my-gcp-project/zones/my-gcp-zone/disks/my-gcp-disk"
+	// Note: This can sometimes be referred to as a "volume handle" in CSI
+	// implementations. This should represent the `Volume.volume_id` field in CSI
+	// spec.
+	//
+	// [Container Storage Interface]: https://github.com/container-storage-interface/spec
+	ContainerCSIVolumeIDKey = attribute.Key("container.csi.volume.id")
+
+	// ContainerIDKey is the attribute Key conforming to the "container.id" semantic
+	// conventions. It represents the container ID. Usually a UUID, as for example
+	// used to [identify Docker containers]. The UUID might be abbreviated.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "a3bf90e006b2"
+	//
+	// [identify Docker containers]: https://docs.docker.com/engine/containers/run/#container-identification
+	ContainerIDKey = attribute.Key("container.id")
+
+	// ContainerImageIDKey is the attribute Key conforming to the
+	// "container.image.id" semantic conventions. It represents the runtime specific
+	// image identifier. Usually a hash algorithm followed by a UUID.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f"
+	// Note: Docker defines a sha256 of the image id; `container.image.id`
+	// corresponds to the `Image` field from the Docker container inspect [API]
+	// endpoint.
+	// K8s defines a link to the container registry repository with digest
+	// `"imageID": "registry.azurecr.io /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"`
+	// .
+	// The ID is assigned by the container runtime and can vary in different
+	// environments. Consider using `oci.manifest.digest` if it is important to
+	// identify the same image in different environments/runtimes.
+	//
+	// [API]: https://docs.docker.com/engine/api/v1.43/#tag/Container/operation/ContainerInspect
+	ContainerImageIDKey = attribute.Key("container.image.id")
+
+	// ContainerImageNameKey is the attribute Key conforming to the
+	// "container.image.name" semantic conventions. It represents the name of the
+	// image the container was built on.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "gcr.io/opentelemetry/operator"
+	ContainerImageNameKey = attribute.Key("container.image.name")
+
+	// ContainerImageRepoDigestsKey is the attribute Key conforming to the
+	// "container.image.repo_digests" semantic conventions. It represents the repo
+	// digests of the container image as provided by the container runtime.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb",
+	// "internal.registry.example.com:5000/example@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578"
+	// Note: [Docker] and [CRI] report those under the `RepoDigests` field.
+	//
+	// [Docker]: https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect
+	// [CRI]: https://github.com/kubernetes/cri-api/blob/c75ef5b473bbe2d0a4fc92f82235efd665ea8e9f/pkg/apis/runtime/v1/api.proto#L1237-L1238
+	ContainerImageRepoDigestsKey = attribute.Key("container.image.repo_digests")
+
+	// ContainerImageTagsKey is the attribute Key conforming to the
+	// "container.image.tags" semantic conventions. It represents the container
+	// image tags. An example can be found in [Docker Image Inspect]. Should be only
+	// the `` section of the full name for example from
+	// `registry.example.com/my-org/my-image:`.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "v1.27.1", "3.5.7-0"
+	//
+	// [Docker Image Inspect]: https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect
+	ContainerImageTagsKey = attribute.Key("container.image.tags")
+
+	// ContainerNameKey is the attribute Key conforming to the "container.name"
+	// semantic conventions. It represents the container name used by container
+	// runtime.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry-autoconf"
+	ContainerNameKey = attribute.Key("container.name")
+
+	// ContainerRuntimeKey is the attribute Key conforming to the
+	// "container.runtime" semantic conventions. It represents the container runtime
+	// managing this container.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "docker", "containerd", "rkt"
+	ContainerRuntimeKey = attribute.Key("container.runtime")
+)
+
+// ContainerCommand returns an attribute KeyValue conforming to the
+// "container.command" semantic conventions. It represents the command used to
+// run the container (i.e. the command name).
+func ContainerCommand(val string) attribute.KeyValue {
+	return ContainerCommandKey.String(val)
+}
+
+// ContainerCommandArgs returns an attribute KeyValue conforming to the
+// "container.command_args" semantic conventions. It represents the all the
+// command arguments (including the command/executable itself) run by the
+// container.
+func ContainerCommandArgs(val ...string) attribute.KeyValue {
+	return ContainerCommandArgsKey.StringSlice(val)
+}
+
+// ContainerCommandLine returns an attribute KeyValue conforming to the
+// "container.command_line" semantic conventions. It represents the full command
+// run by the container as a single string representing the full command.
+func ContainerCommandLine(val string) attribute.KeyValue {
+	return ContainerCommandLineKey.String(val)
+}
+
+// ContainerCSIPluginName returns an attribute KeyValue conforming to the
+// "container.csi.plugin.name" semantic conventions. It represents the name of
+// the CSI ([Container Storage Interface]) plugin used by the volume.
+//
+// [Container Storage Interface]: https://github.com/container-storage-interface/spec
+func ContainerCSIPluginName(val string) attribute.KeyValue {
+	return ContainerCSIPluginNameKey.String(val)
+}
+
+// ContainerCSIVolumeID returns an attribute KeyValue conforming to the
+// "container.csi.volume.id" semantic conventions. It represents the unique
+// volume ID returned by the CSI ([Container Storage Interface]) plugin.
+//
+// [Container Storage Interface]: https://github.com/container-storage-interface/spec
+func ContainerCSIVolumeID(val string) attribute.KeyValue {
+	return ContainerCSIVolumeIDKey.String(val)
+}
+
+// ContainerID returns an attribute KeyValue conforming to the "container.id"
+// semantic conventions. It represents the container ID. Usually a UUID, as for
+// example used to [identify Docker containers]. The UUID might be abbreviated.
+//
+// [identify Docker containers]: https://docs.docker.com/engine/containers/run/#container-identification
+func ContainerID(val string) attribute.KeyValue {
+	return ContainerIDKey.String(val)
+}
+
+// ContainerImageID returns an attribute KeyValue conforming to the
+// "container.image.id" semantic conventions. It represents the runtime specific
+// image identifier. Usually a hash algorithm followed by a UUID.
+func ContainerImageID(val string) attribute.KeyValue {
+	return ContainerImageIDKey.String(val)
+}
+
+// ContainerImageName returns an attribute KeyValue conforming to the
+// "container.image.name" semantic conventions. It represents the name of the
+// image the container was built on.
+func ContainerImageName(val string) attribute.KeyValue {
+	return ContainerImageNameKey.String(val)
+}
+
+// ContainerImageRepoDigests returns an attribute KeyValue conforming to the
+// "container.image.repo_digests" semantic conventions. It represents the repo
+// digests of the container image as provided by the container runtime.
+func ContainerImageRepoDigests(val ...string) attribute.KeyValue {
+	return ContainerImageRepoDigestsKey.StringSlice(val)
+}
+
+// ContainerImageTags returns an attribute KeyValue conforming to the
+// "container.image.tags" semantic conventions. It represents the container image
+// tags. An example can be found in [Docker Image Inspect]. Should be only the
+// `` section of the full name for example from
+// `registry.example.com/my-org/my-image:`.
+//
+// [Docker Image Inspect]: https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect
+func ContainerImageTags(val ...string) attribute.KeyValue {
+	return ContainerImageTagsKey.StringSlice(val)
+}
+
+// ContainerName returns an attribute KeyValue conforming to the "container.name"
+// semantic conventions. It represents the container name used by container
+// runtime.
+func ContainerName(val string) attribute.KeyValue {
+	return ContainerNameKey.String(val)
+}
+
+// ContainerRuntime returns an attribute KeyValue conforming to the
+// "container.runtime" semantic conventions. It represents the container runtime
+// managing this container.
+func ContainerRuntime(val string) attribute.KeyValue {
+	return ContainerRuntimeKey.String(val)
+}
+
+// Namespace: cpu
+const (
+	// CPULogicalNumberKey is the attribute Key conforming to the
+	// "cpu.logical_number" semantic conventions. It represents the logical CPU
+	// number [0..n-1].
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1
+	CPULogicalNumberKey = attribute.Key("cpu.logical_number")
+
+	// CPUModeKey is the attribute Key conforming to the "cpu.mode" semantic
+	// conventions. It represents the mode of the CPU.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "user", "system"
+	CPUModeKey = attribute.Key("cpu.mode")
+)
+
+// CPULogicalNumber returns an attribute KeyValue conforming to the
+// "cpu.logical_number" semantic conventions. It represents the logical CPU
+// number [0..n-1].
+func CPULogicalNumber(val int) attribute.KeyValue {
+	return CPULogicalNumberKey.Int(val)
+}
+
+// Enum values for cpu.mode
+var (
+	// user
+	// Stability: development
+	CPUModeUser = CPUModeKey.String("user")
+	// system
+	// Stability: development
+	CPUModeSystem = CPUModeKey.String("system")
+	// nice
+	// Stability: development
+	CPUModeNice = CPUModeKey.String("nice")
+	// idle
+	// Stability: development
+	CPUModeIdle = CPUModeKey.String("idle")
+	// iowait
+	// Stability: development
+	CPUModeIOWait = CPUModeKey.String("iowait")
+	// interrupt
+	// Stability: development
+	CPUModeInterrupt = CPUModeKey.String("interrupt")
+	// steal
+	// Stability: development
+	CPUModeSteal = CPUModeKey.String("steal")
+	// kernel
+	// Stability: development
+	CPUModeKernel = CPUModeKey.String("kernel")
+)
+
+// Namespace: db
+const (
+	// DBClientConnectionPoolNameKey is the attribute Key conforming to the
+	// "db.client.connection.pool.name" semantic conventions. It represents the name
+	// of the connection pool; unique within the instrumented application. In case
+	// the connection pool implementation doesn't provide a name, instrumentation
+	// SHOULD use a combination of parameters that would make the name unique, for
+	// example, combining attributes `server.address`, `server.port`, and
+	// `db.namespace`, formatted as `server.address:server.port/db.namespace`.
+	// Instrumentations that generate connection pool name following different
+	// patterns SHOULD document it.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "myDataSource"
+	DBClientConnectionPoolNameKey = attribute.Key("db.client.connection.pool.name")
+
+	// DBClientConnectionStateKey is the attribute Key conforming to the
+	// "db.client.connection.state" semantic conventions. It represents the state of
+	// a connection in the pool.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "idle"
+	DBClientConnectionStateKey = attribute.Key("db.client.connection.state")
+
+	// DBCollectionNameKey is the attribute Key conforming to the
+	// "db.collection.name" semantic conventions. It represents the name of a
+	// collection (table, container) within the database.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "public.users", "customers"
+	// Note: It is RECOMMENDED to capture the value as provided by the application
+	// without attempting to do any case normalization.
+	//
+	// The collection name SHOULD NOT be extracted from `db.query.text`,
+	// when the database system supports query text with multiple collections
+	// in non-batch operations.
+	//
+	// For batch operations, if the individual operations are known to have the same
+	// collection name then that collection name SHOULD be used.
+	DBCollectionNameKey = attribute.Key("db.collection.name")
+
+	// DBNamespaceKey is the attribute Key conforming to the "db.namespace" semantic
+	// conventions. It represents the name of the database, fully qualified within
+	// the server address and port.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "customers", "test.users"
+	// Note: If a database system has multiple namespace components, they SHOULD be
+	// concatenated from the most general to the most specific namespace component,
+	// using `|` as a separator between the components. Any missing components (and
+	// their associated separators) SHOULD be omitted.
+	// Semantic conventions for individual database systems SHOULD document what
+	// `db.namespace` means in the context of that system.
+	// It is RECOMMENDED to capture the value as provided by the application without
+	// attempting to do any case normalization.
+	DBNamespaceKey = attribute.Key("db.namespace")
+
+	// DBOperationBatchSizeKey is the attribute Key conforming to the
+	// "db.operation.batch.size" semantic conventions. It represents the number of
+	// queries included in a batch operation.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 2, 3, 4
+	// Note: Operations are only considered batches when they contain two or more
+	// operations, and so `db.operation.batch.size` SHOULD never be `1`.
+	DBOperationBatchSizeKey = attribute.Key("db.operation.batch.size")
+
+	// DBOperationNameKey is the attribute Key conforming to the "db.operation.name"
+	// semantic conventions. It represents the name of the operation or command
+	// being executed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "findAndModify", "HMSET", "SELECT"
+	// Note: It is RECOMMENDED to capture the value as provided by the application
+	// without attempting to do any case normalization.
+	//
+	// The operation name SHOULD NOT be extracted from `db.query.text`,
+	// when the database system supports query text with multiple operations
+	// in non-batch operations.
+	//
+	// If spaces can occur in the operation name, multiple consecutive spaces
+	// SHOULD be normalized to a single space.
+	//
+	// For batch operations, if the individual operations are known to have the same
+	// operation name
+	// then that operation name SHOULD be used prepended by `BATCH `,
+	// otherwise `db.operation.name` SHOULD be `BATCH` or some other database
+	// system specific term if more applicable.
+	DBOperationNameKey = attribute.Key("db.operation.name")
+
+	// DBQuerySummaryKey is the attribute Key conforming to the "db.query.summary"
+	// semantic conventions. It represents the low cardinality summary of a database
+	// query.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "SELECT wuser_table", "INSERT shipping_details SELECT orders", "get
+	// user by id"
+	// Note: The query summary describes a class of database queries and is useful
+	// as a grouping key, especially when analyzing telemetry for database
+	// calls involving complex queries.
+	//
+	// Summary may be available to the instrumentation through
+	// instrumentation hooks or other means. If it is not available,
+	// instrumentations
+	// that support query parsing SHOULD generate a summary following
+	// [Generating query summary]
+	// section.
+	//
+	// [Generating query summary]: /docs/database/database-spans.md#generating-a-summary-of-the-query
+	DBQuerySummaryKey = attribute.Key("db.query.summary")
+
+	// DBQueryTextKey is the attribute Key conforming to the "db.query.text"
+	// semantic conventions. It represents the database query being executed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "SELECT * FROM wuser_table where username = ?", "SET mykey ?"
+	// Note: For sanitization see [Sanitization of `db.query.text`].
+	// For batch operations, if the individual operations are known to have the same
+	// query text then that query text SHOULD be used, otherwise all of the
+	// individual query texts SHOULD be concatenated with separator `; ` or some
+	// other database system specific separator if more applicable.
+	// Parameterized query text SHOULD NOT be sanitized. Even though parameterized
+	// query text can potentially have sensitive data, by using a parameterized
+	// query the user is giving a strong signal that any sensitive data will be
+	// passed as parameter values, and the benefit to observability of capturing the
+	// static part of the query text by default outweighs the risk.
+	//
+	// [Sanitization of `db.query.text`]: /docs/database/database-spans.md#sanitization-of-dbquerytext
+	DBQueryTextKey = attribute.Key("db.query.text")
+
+	// DBResponseReturnedRowsKey is the attribute Key conforming to the
+	// "db.response.returned_rows" semantic conventions. It represents the number of
+	// rows returned by the operation.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 10, 30, 1000
+	DBResponseReturnedRowsKey = attribute.Key("db.response.returned_rows")
+
+	// DBResponseStatusCodeKey is the attribute Key conforming to the
+	// "db.response.status_code" semantic conventions. It represents the database
+	// response status code.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "102", "ORA-17002", "08P01", "404"
+	// Note: The status code returned by the database. Usually it represents an
+	// error code, but may also represent partial success, warning, or differentiate
+	// between various types of successful outcomes.
+	// Semantic conventions for individual database systems SHOULD document what
+	// `db.response.status_code` means in the context of that system.
+	DBResponseStatusCodeKey = attribute.Key("db.response.status_code")
+
+	// DBStoredProcedureNameKey is the attribute Key conforming to the
+	// "db.stored_procedure.name" semantic conventions. It represents the name of a
+	// stored procedure within the database.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "GetCustomer"
+	// Note: It is RECOMMENDED to capture the value as provided by the application
+	// without attempting to do any case normalization.
+	//
+	// For batch operations, if the individual operations are known to have the same
+	// stored procedure name then that stored procedure name SHOULD be used.
+	DBStoredProcedureNameKey = attribute.Key("db.stored_procedure.name")
+
+	// DBSystemNameKey is the attribute Key conforming to the "db.system.name"
+	// semantic conventions. It represents the database management system (DBMS)
+	// product as identified by the client instrumentation.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples:
+	// Note: The actual DBMS may differ from the one identified by the client. For
+	// example, when using PostgreSQL client libraries to connect to a CockroachDB,
+	// the `db.system.name` is set to `postgresql` based on the instrumentation's
+	// best knowledge.
+	DBSystemNameKey = attribute.Key("db.system.name")
+)
+
+// DBClientConnectionPoolName returns an attribute KeyValue conforming to the
+// "db.client.connection.pool.name" semantic conventions. It represents the name
+// of the connection pool; unique within the instrumented application. In case
+// the connection pool implementation doesn't provide a name, instrumentation
+// SHOULD use a combination of parameters that would make the name unique, for
+// example, combining attributes `server.address`, `server.port`, and
+// `db.namespace`, formatted as `server.address:server.port/db.namespace`.
+// Instrumentations that generate connection pool name following different
+// patterns SHOULD document it.
+func DBClientConnectionPoolName(val string) attribute.KeyValue {
+	return DBClientConnectionPoolNameKey.String(val)
+}
+
+// DBCollectionName returns an attribute KeyValue conforming to the
+// "db.collection.name" semantic conventions. It represents the name of a
+// collection (table, container) within the database.
+func DBCollectionName(val string) attribute.KeyValue {
+	return DBCollectionNameKey.String(val)
+}
+
+// DBNamespace returns an attribute KeyValue conforming to the "db.namespace"
+// semantic conventions. It represents the name of the database, fully qualified
+// within the server address and port.
+func DBNamespace(val string) attribute.KeyValue {
+	return DBNamespaceKey.String(val)
+}
+
+// DBOperationBatchSize returns an attribute KeyValue conforming to the
+// "db.operation.batch.size" semantic conventions. It represents the number of
+// queries included in a batch operation.
+func DBOperationBatchSize(val int) attribute.KeyValue {
+	return DBOperationBatchSizeKey.Int(val)
+}
+
+// DBOperationName returns an attribute KeyValue conforming to the
+// "db.operation.name" semantic conventions. It represents the name of the
+// operation or command being executed.
+func DBOperationName(val string) attribute.KeyValue {
+	return DBOperationNameKey.String(val)
+}
+
+// DBQuerySummary returns an attribute KeyValue conforming to the
+// "db.query.summary" semantic conventions. It represents the low cardinality
+// summary of a database query.
+func DBQuerySummary(val string) attribute.KeyValue {
+	return DBQuerySummaryKey.String(val)
+}
+
+// DBQueryText returns an attribute KeyValue conforming to the "db.query.text"
+// semantic conventions. It represents the database query being executed.
+func DBQueryText(val string) attribute.KeyValue {
+	return DBQueryTextKey.String(val)
+}
+
+// DBResponseReturnedRows returns an attribute KeyValue conforming to the
+// "db.response.returned_rows" semantic conventions. It represents the number of
+// rows returned by the operation.
+func DBResponseReturnedRows(val int) attribute.KeyValue {
+	return DBResponseReturnedRowsKey.Int(val)
+}
+
+// DBResponseStatusCode returns an attribute KeyValue conforming to the
+// "db.response.status_code" semantic conventions. It represents the database
+// response status code.
+func DBResponseStatusCode(val string) attribute.KeyValue {
+	return DBResponseStatusCodeKey.String(val)
+}
+
+// DBStoredProcedureName returns an attribute KeyValue conforming to the
+// "db.stored_procedure.name" semantic conventions. It represents the name of a
+// stored procedure within the database.
+func DBStoredProcedureName(val string) attribute.KeyValue {
+	return DBStoredProcedureNameKey.String(val)
+}
+
+// Enum values for db.client.connection.state
+var (
+	// idle
+	// Stability: development
+	DBClientConnectionStateIdle = DBClientConnectionStateKey.String("idle")
+	// used
+	// Stability: development
+	DBClientConnectionStateUsed = DBClientConnectionStateKey.String("used")
+)
+
+// Enum values for db.system.name
+var (
+	// Some other SQL database. Fallback only.
+	// Stability: development
+	DBSystemNameOtherSQL = DBSystemNameKey.String("other_sql")
+	// [Adabas (Adaptable Database System)]
+	// Stability: development
+	//
+	// [Adabas (Adaptable Database System)]: https://documentation.softwareag.com/?pf=adabas
+	DBSystemNameSoftwareagAdabas = DBSystemNameKey.String("softwareag.adabas")
+	// [Actian Ingres]
+	// Stability: development
+	//
+	// [Actian Ingres]: https://www.actian.com/databases/ingres/
+	DBSystemNameActianIngres = DBSystemNameKey.String("actian.ingres")
+	// [Amazon DynamoDB]
+	// Stability: development
+	//
+	// [Amazon DynamoDB]: https://aws.amazon.com/pm/dynamodb/
+	DBSystemNameAWSDynamoDB = DBSystemNameKey.String("aws.dynamodb")
+	// [Amazon Redshift]
+	// Stability: development
+	//
+	// [Amazon Redshift]: https://aws.amazon.com/redshift/
+	DBSystemNameAWSRedshift = DBSystemNameKey.String("aws.redshift")
+	// [Azure Cosmos DB]
+	// Stability: development
+	//
+	// [Azure Cosmos DB]: https://learn.microsoft.com/azure/cosmos-db
+	DBSystemNameAzureCosmosDB = DBSystemNameKey.String("azure.cosmosdb")
+	// [InterSystems Caché]
+	// Stability: development
+	//
+	// [InterSystems Caché]: https://www.intersystems.com/products/cache/
+	DBSystemNameIntersystemsCache = DBSystemNameKey.String("intersystems.cache")
+	// [Apache Cassandra]
+	// Stability: development
+	//
+	// [Apache Cassandra]: https://cassandra.apache.org/
+	DBSystemNameCassandra = DBSystemNameKey.String("cassandra")
+	// [ClickHouse]
+	// Stability: development
+	//
+	// [ClickHouse]: https://clickhouse.com/
+	DBSystemNameClickHouse = DBSystemNameKey.String("clickhouse")
+	// [CockroachDB]
+	// Stability: development
+	//
+	// [CockroachDB]: https://www.cockroachlabs.com/
+	DBSystemNameCockroachDB = DBSystemNameKey.String("cockroachdb")
+	// [Couchbase]
+	// Stability: development
+	//
+	// [Couchbase]: https://www.couchbase.com/
+	DBSystemNameCouchbase = DBSystemNameKey.String("couchbase")
+	// [Apache CouchDB]
+	// Stability: development
+	//
+	// [Apache CouchDB]: https://couchdb.apache.org/
+	DBSystemNameCouchDB = DBSystemNameKey.String("couchdb")
+	// [Apache Derby]
+	// Stability: development
+	//
+	// [Apache Derby]: https://db.apache.org/derby/
+	DBSystemNameDerby = DBSystemNameKey.String("derby")
+	// [Elasticsearch]
+	// Stability: development
+	//
+	// [Elasticsearch]: https://www.elastic.co/elasticsearch
+	DBSystemNameElasticsearch = DBSystemNameKey.String("elasticsearch")
+	// [Firebird]
+	// Stability: development
+	//
+	// [Firebird]: https://www.firebirdsql.org/
+	DBSystemNameFirebirdSQL = DBSystemNameKey.String("firebirdsql")
+	// [Google Cloud Spanner]
+	// Stability: development
+	//
+	// [Google Cloud Spanner]: https://cloud.google.com/spanner
+	DBSystemNameGCPSpanner = DBSystemNameKey.String("gcp.spanner")
+	// [Apache Geode]
+	// Stability: development
+	//
+	// [Apache Geode]: https://geode.apache.org/
+	DBSystemNameGeode = DBSystemNameKey.String("geode")
+	// [H2 Database]
+	// Stability: development
+	//
+	// [H2 Database]: https://h2database.com/
+	DBSystemNameH2database = DBSystemNameKey.String("h2database")
+	// [Apache HBase]
+	// Stability: development
+	//
+	// [Apache HBase]: https://hbase.apache.org/
+	DBSystemNameHBase = DBSystemNameKey.String("hbase")
+	// [Apache Hive]
+	// Stability: development
+	//
+	// [Apache Hive]: https://hive.apache.org/
+	DBSystemNameHive = DBSystemNameKey.String("hive")
+	// [HyperSQL Database]
+	// Stability: development
+	//
+	// [HyperSQL Database]: https://hsqldb.org/
+	DBSystemNameHSQLDB = DBSystemNameKey.String("hsqldb")
+	// [IBM Db2]
+	// Stability: development
+	//
+	// [IBM Db2]: https://www.ibm.com/db2
+	DBSystemNameIBMDB2 = DBSystemNameKey.String("ibm.db2")
+	// [IBM Informix]
+	// Stability: development
+	//
+	// [IBM Informix]: https://www.ibm.com/products/informix
+	DBSystemNameIBMInformix = DBSystemNameKey.String("ibm.informix")
+	// [IBM Netezza]
+	// Stability: development
+	//
+	// [IBM Netezza]: https://www.ibm.com/products/netezza
+	DBSystemNameIBMNetezza = DBSystemNameKey.String("ibm.netezza")
+	// [InfluxDB]
+	// Stability: development
+	//
+	// [InfluxDB]: https://www.influxdata.com/
+	DBSystemNameInfluxDB = DBSystemNameKey.String("influxdb")
+	// [Instant]
+	// Stability: development
+	//
+	// [Instant]: https://www.instantdb.com/
+	DBSystemNameInstantDB = DBSystemNameKey.String("instantdb")
+	// [MariaDB]
+	// Stability: stable
+	//
+	// [MariaDB]: https://mariadb.org/
+	DBSystemNameMariaDB = DBSystemNameKey.String("mariadb")
+	// [Memcached]
+	// Stability: development
+	//
+	// [Memcached]: https://memcached.org/
+	DBSystemNameMemcached = DBSystemNameKey.String("memcached")
+	// [MongoDB]
+	// Stability: development
+	//
+	// [MongoDB]: https://www.mongodb.com/
+	DBSystemNameMongoDB = DBSystemNameKey.String("mongodb")
+	// [Microsoft SQL Server]
+	// Stability: stable
+	//
+	// [Microsoft SQL Server]: https://www.microsoft.com/sql-server
+	DBSystemNameMicrosoftSQLServer = DBSystemNameKey.String("microsoft.sql_server")
+	// [MySQL]
+	// Stability: stable
+	//
+	// [MySQL]: https://www.mysql.com/
+	DBSystemNameMySQL = DBSystemNameKey.String("mysql")
+	// [Neo4j]
+	// Stability: development
+	//
+	// [Neo4j]: https://neo4j.com/
+	DBSystemNameNeo4j = DBSystemNameKey.String("neo4j")
+	// [OpenSearch]
+	// Stability: development
+	//
+	// [OpenSearch]: https://opensearch.org/
+	DBSystemNameOpenSearch = DBSystemNameKey.String("opensearch")
+	// [Oracle Database]
+	// Stability: development
+	//
+	// [Oracle Database]: https://www.oracle.com/database/
+	DBSystemNameOracleDB = DBSystemNameKey.String("oracle.db")
+	// [PostgreSQL]
+	// Stability: stable
+	//
+	// [PostgreSQL]: https://www.postgresql.org/
+	DBSystemNamePostgreSQL = DBSystemNameKey.String("postgresql")
+	// [Redis]
+	// Stability: development
+	//
+	// [Redis]: https://redis.io/
+	DBSystemNameRedis = DBSystemNameKey.String("redis")
+	// [SAP HANA]
+	// Stability: development
+	//
+	// [SAP HANA]: https://www.sap.com/products/technology-platform/hana/what-is-sap-hana.html
+	DBSystemNameSAPHANA = DBSystemNameKey.String("sap.hana")
+	// [SAP MaxDB]
+	// Stability: development
+	//
+	// [SAP MaxDB]: https://maxdb.sap.com/
+	DBSystemNameSAPMaxDB = DBSystemNameKey.String("sap.maxdb")
+	// [SQLite]
+	// Stability: development
+	//
+	// [SQLite]: https://www.sqlite.org/
+	DBSystemNameSQLite = DBSystemNameKey.String("sqlite")
+	// [Teradata]
+	// Stability: development
+	//
+	// [Teradata]: https://www.teradata.com/
+	DBSystemNameTeradata = DBSystemNameKey.String("teradata")
+	// [Trino]
+	// Stability: development
+	//
+	// [Trino]: https://trino.io/
+	DBSystemNameTrino = DBSystemNameKey.String("trino")
+)
+
+// Namespace: deployment
+const (
+	// DeploymentEnvironmentNameKey is the attribute Key conforming to the
+	// "deployment.environment.name" semantic conventions. It represents the name of
+	// the [deployment environment] (aka deployment tier).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "staging", "production"
+	// Note: `deployment.environment.name` does not affect the uniqueness
+	// constraints defined through
+	// the `service.namespace`, `service.name` and `service.instance.id` resource
+	// attributes.
+	// This implies that resources carrying the following attribute combinations
+	// MUST be
+	// considered to be identifying the same service:
+	//
+	//   - `service.name=frontend`, `deployment.environment.name=production`
+	//   - `service.name=frontend`, `deployment.environment.name=staging`.
+	//
+	//
+	// [deployment environment]: https://wikipedia.org/wiki/Deployment_environment
+	DeploymentEnvironmentNameKey = attribute.Key("deployment.environment.name")
+
+	// DeploymentIDKey is the attribute Key conforming to the "deployment.id"
+	// semantic conventions. It represents the id of the deployment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1208"
+	DeploymentIDKey = attribute.Key("deployment.id")
+
+	// DeploymentNameKey is the attribute Key conforming to the "deployment.name"
+	// semantic conventions. It represents the name of the deployment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "deploy my app", "deploy-frontend"
+	DeploymentNameKey = attribute.Key("deployment.name")
+
+	// DeploymentStatusKey is the attribute Key conforming to the
+	// "deployment.status" semantic conventions. It represents the status of the
+	// deployment.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	DeploymentStatusKey = attribute.Key("deployment.status")
+)
+
+// DeploymentEnvironmentName returns an attribute KeyValue conforming to the
+// "deployment.environment.name" semantic conventions. It represents the name of
+// the [deployment environment] (aka deployment tier).
+//
+// [deployment environment]: https://wikipedia.org/wiki/Deployment_environment
+func DeploymentEnvironmentName(val string) attribute.KeyValue {
+	return DeploymentEnvironmentNameKey.String(val)
+}
+
+// DeploymentID returns an attribute KeyValue conforming to the "deployment.id"
+// semantic conventions. It represents the id of the deployment.
+func DeploymentID(val string) attribute.KeyValue {
+	return DeploymentIDKey.String(val)
+}
+
+// DeploymentName returns an attribute KeyValue conforming to the
+// "deployment.name" semantic conventions. It represents the name of the
+// deployment.
+func DeploymentName(val string) attribute.KeyValue {
+	return DeploymentNameKey.String(val)
+}
+
+// Enum values for deployment.status
+var (
+	// failed
+	// Stability: development
+	DeploymentStatusFailed = DeploymentStatusKey.String("failed")
+	// succeeded
+	// Stability: development
+	DeploymentStatusSucceeded = DeploymentStatusKey.String("succeeded")
+)
+
+// Namespace: destination
+const (
+	// DestinationAddressKey is the attribute Key conforming to the
+	// "destination.address" semantic conventions. It represents the destination
+	// address - domain name if available without reverse DNS lookup; otherwise, IP
+	// address or Unix domain socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "destination.example.com", "10.1.2.80", "/tmp/my.sock"
+	// Note: When observed from the source side, and when communicating through an
+	// intermediary, `destination.address` SHOULD represent the destination address
+	// behind any intermediaries, for example proxies, if it's available.
+	DestinationAddressKey = attribute.Key("destination.address")
+
+	// DestinationPortKey is the attribute Key conforming to the "destination.port"
+	// semantic conventions. It represents the destination port number.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 3389, 2888
+	DestinationPortKey = attribute.Key("destination.port")
+)
+
+// DestinationAddress returns an attribute KeyValue conforming to the
+// "destination.address" semantic conventions. It represents the destination
+// address - domain name if available without reverse DNS lookup; otherwise, IP
+// address or Unix domain socket name.
+func DestinationAddress(val string) attribute.KeyValue {
+	return DestinationAddressKey.String(val)
+}
+
+// DestinationPort returns an attribute KeyValue conforming to the
+// "destination.port" semantic conventions. It represents the destination port
+// number.
+func DestinationPort(val int) attribute.KeyValue {
+	return DestinationPortKey.Int(val)
+}
+
+// Namespace: device
+const (
+	// DeviceIDKey is the attribute Key conforming to the "device.id" semantic
+	// conventions. It represents a unique identifier representing the device.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "123456789012345", "01:23:45:67:89:AB"
+	// Note: Its value SHOULD be identical for all apps on a device and it SHOULD
+	// NOT change if an app is uninstalled and re-installed.
+	// However, it might be resettable by the user for all apps on a device.
+	// Hardware IDs (e.g. vendor-specific serial number, IMEI or MAC address) MAY be
+	// used as values.
+	//
+	// More information about Android identifier best practices can be found [here]
+	// .
+	//
+	// > [!WARNING]> This attribute may contain sensitive (PII) information. Caution
+	// > should be taken when storing personal data or anything which can identify a
+	// > user. GDPR and data protection laws may apply,
+	// > ensure you do your own due diligence.> Due to these reasons, this
+	// > identifier is not recommended for consumer applications and will likely
+	// > result in rejection from both Google Play and App Store.
+	// > However, it may be appropriate for specific enterprise scenarios, such as
+	// > kiosk devices or enterprise-managed devices, with appropriate compliance
+	// > clearance.
+	// > Any instrumentation providing this identifier MUST implement it as an
+	// > opt-in feature.> See [`app.installation.id`]>  for a more
+	// > privacy-preserving alternative.
+	//
+	// [here]: https://developer.android.com/training/articles/user-data-ids
+	// [`app.installation.id`]: /docs/registry/attributes/app.md#app-installation-id
+	DeviceIDKey = attribute.Key("device.id")
+
+	// DeviceManufacturerKey is the attribute Key conforming to the
+	// "device.manufacturer" semantic conventions. It represents the name of the
+	// device manufacturer.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Apple", "Samsung"
+	// Note: The Android OS provides this field via [Build]. iOS apps SHOULD
+	// hardcode the value `Apple`.
+	//
+	// [Build]: https://developer.android.com/reference/android/os/Build#MANUFACTURER
+	DeviceManufacturerKey = attribute.Key("device.manufacturer")
+
+	// DeviceModelIdentifierKey is the attribute Key conforming to the
+	// "device.model.identifier" semantic conventions. It represents the model
+	// identifier for the device.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "iPhone3,4", "SM-G920F"
+	// Note: It's recommended this value represents a machine-readable version of
+	// the model identifier rather than the market or consumer-friendly name of the
+	// device.
+	DeviceModelIdentifierKey = attribute.Key("device.model.identifier")
+
+	// DeviceModelNameKey is the attribute Key conforming to the "device.model.name"
+	// semantic conventions. It represents the marketing name for the device model.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "iPhone 6s Plus", "Samsung Galaxy S6"
+	// Note: It's recommended this value represents a human-readable version of the
+	// device model rather than a machine-readable alternative.
+	DeviceModelNameKey = attribute.Key("device.model.name")
+)
+
+// DeviceID returns an attribute KeyValue conforming to the "device.id" semantic
+// conventions. It represents a unique identifier representing the device.
+func DeviceID(val string) attribute.KeyValue {
+	return DeviceIDKey.String(val)
+}
+
+// DeviceManufacturer returns an attribute KeyValue conforming to the
+// "device.manufacturer" semantic conventions. It represents the name of the
+// device manufacturer.
+func DeviceManufacturer(val string) attribute.KeyValue {
+	return DeviceManufacturerKey.String(val)
+}
+
+// DeviceModelIdentifier returns an attribute KeyValue conforming to the
+// "device.model.identifier" semantic conventions. It represents the model
+// identifier for the device.
+func DeviceModelIdentifier(val string) attribute.KeyValue {
+	return DeviceModelIdentifierKey.String(val)
+}
+
+// DeviceModelName returns an attribute KeyValue conforming to the
+// "device.model.name" semantic conventions. It represents the marketing name for
+// the device model.
+func DeviceModelName(val string) attribute.KeyValue {
+	return DeviceModelNameKey.String(val)
+}
+
+// Namespace: disk
+const (
+	// DiskIODirectionKey is the attribute Key conforming to the "disk.io.direction"
+	// semantic conventions. It represents the disk IO operation direction.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "read"
+	DiskIODirectionKey = attribute.Key("disk.io.direction")
+)
+
+// Enum values for disk.io.direction
+var (
+	// read
+	// Stability: development
+	DiskIODirectionRead = DiskIODirectionKey.String("read")
+	// write
+	// Stability: development
+	DiskIODirectionWrite = DiskIODirectionKey.String("write")
+)
+
+// Namespace: dns
+const (
+	// DNSQuestionNameKey is the attribute Key conforming to the "dns.question.name"
+	// semantic conventions. It represents the name being queried.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "www.example.com", "opentelemetry.io"
+	// Note: If the name field contains non-printable characters (below 32 or above
+	// 126), those characters should be represented as escaped base 10 integers
+	// (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns,
+	// and line feeds should be converted to \t, \r, and \n respectively.
+	DNSQuestionNameKey = attribute.Key("dns.question.name")
+)
+
+// DNSQuestionName returns an attribute KeyValue conforming to the
+// "dns.question.name" semantic conventions. It represents the name being
+// queried.
+func DNSQuestionName(val string) attribute.KeyValue {
+	return DNSQuestionNameKey.String(val)
+}
+
+// Namespace: elasticsearch
+const (
+	// ElasticsearchNodeNameKey is the attribute Key conforming to the
+	// "elasticsearch.node.name" semantic conventions. It represents the represents
+	// the human-readable identifier of the node/instance to which a request was
+	// routed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "instance-0000000001"
+	ElasticsearchNodeNameKey = attribute.Key("elasticsearch.node.name")
+)
+
+// ElasticsearchNodeName returns an attribute KeyValue conforming to the
+// "elasticsearch.node.name" semantic conventions. It represents the represents
+// the human-readable identifier of the node/instance to which a request was
+// routed.
+func ElasticsearchNodeName(val string) attribute.KeyValue {
+	return ElasticsearchNodeNameKey.String(val)
+}
+
+// Namespace: enduser
+const (
+	// EnduserIDKey is the attribute Key conforming to the "enduser.id" semantic
+	// conventions. It represents the unique identifier of an end user in the
+	// system. It maybe a username, email address, or other identifier.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "username"
+	// Note: Unique identifier of an end user in the system.
+	//
+	// > [!Warning]
+	// > This field contains sensitive (PII) information.
+	EnduserIDKey = attribute.Key("enduser.id")
+
+	// EnduserPseudoIDKey is the attribute Key conforming to the "enduser.pseudo.id"
+	// semantic conventions. It represents the pseudonymous identifier of an end
+	// user. This identifier should be a random value that is not directly linked or
+	// associated with the end user's actual identity.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "QdH5CAWJgqVT4rOr0qtumf"
+	// Note: Pseudonymous identifier of an end user.
+	//
+	// > [!Warning]
+	// > This field contains sensitive (linkable PII) information.
+	EnduserPseudoIDKey = attribute.Key("enduser.pseudo.id")
+)
+
+// EnduserID returns an attribute KeyValue conforming to the "enduser.id"
+// semantic conventions. It represents the unique identifier of an end user in
+// the system. It maybe a username, email address, or other identifier.
+func EnduserID(val string) attribute.KeyValue {
+	return EnduserIDKey.String(val)
+}
+
+// EnduserPseudoID returns an attribute KeyValue conforming to the
+// "enduser.pseudo.id" semantic conventions. It represents the pseudonymous
+// identifier of an end user. This identifier should be a random value that is
+// not directly linked or associated with the end user's actual identity.
+func EnduserPseudoID(val string) attribute.KeyValue {
+	return EnduserPseudoIDKey.String(val)
+}
+
+// Namespace: error
+const (
+	// ErrorMessageKey is the attribute Key conforming to the "error.message"
+	// semantic conventions. It represents a message providing more detail about an
+	// error in human-readable form.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Unexpected input type: string", "The user has exceeded their
+	// storage quota"
+	// Note: `error.message` should provide additional context and detail about an
+	// error.
+	// It is NOT RECOMMENDED to duplicate the value of `error.type` in
+	// `error.message`.
+	// It is also NOT RECOMMENDED to duplicate the value of `exception.message` in
+	// `error.message`.
+	//
+	// `error.message` is NOT RECOMMENDED for metrics or spans due to its unbounded
+	// cardinality and overlap with span status.
+	ErrorMessageKey = attribute.Key("error.message")
+
+	// ErrorTypeKey is the attribute Key conforming to the "error.type" semantic
+	// conventions. It represents the describes a class of error the operation ended
+	// with.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "timeout", "java.net.UnknownHostException",
+	// "server_certificate_invalid", "500"
+	// Note: The `error.type` SHOULD be predictable, and SHOULD have low
+	// cardinality.
+	//
+	// When `error.type` is set to a type (e.g., an exception type), its
+	// canonical class name identifying the type within the artifact SHOULD be used.
+	//
+	// Instrumentations SHOULD document the list of errors they report.
+	//
+	// The cardinality of `error.type` within one instrumentation library SHOULD be
+	// low.
+	// Telemetry consumers that aggregate data from multiple instrumentation
+	// libraries and applications
+	// should be prepared for `error.type` to have high cardinality at query time
+	// when no
+	// additional filters are applied.
+	//
+	// If the operation has completed successfully, instrumentations SHOULD NOT set
+	// `error.type`.
+	//
+	// If a specific domain defines its own set of error identifiers (such as HTTP
+	// or gRPC status codes),
+	// it's RECOMMENDED to:
+	//
+	//   - Use a domain-specific attribute
+	//   - Set `error.type` to capture all errors, regardless of whether they are
+	//     defined within the domain-specific set or not.
+	ErrorTypeKey = attribute.Key("error.type")
+)
+
+// ErrorMessage returns an attribute KeyValue conforming to the "error.message"
+// semantic conventions. It represents a message providing more detail about an
+// error in human-readable form.
+func ErrorMessage(val string) attribute.KeyValue {
+	return ErrorMessageKey.String(val)
+}
+
+// Enum values for error.type
+var (
+	// A fallback error value to be used when the instrumentation doesn't define a
+	// custom value.
+	//
+	// Stability: stable
+	ErrorTypeOther = ErrorTypeKey.String("_OTHER")
+)
+
+// Namespace: exception
+const (
+	// ExceptionMessageKey is the attribute Key conforming to the
+	// "exception.message" semantic conventions. It represents the exception
+	// message.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "Division by zero", "Can't convert 'int' object to str implicitly"
+	ExceptionMessageKey = attribute.Key("exception.message")
+
+	// ExceptionStacktraceKey is the attribute Key conforming to the
+	// "exception.stacktrace" semantic conventions. It represents a stacktrace as a
+	// string in the natural representation for the language runtime. The
+	// representation is to be determined and documented by each language SIG.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: Exception in thread "main" java.lang.RuntimeException: Test
+	// exception\n at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at
+	// com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at
+	// com.example.GenerateTrace.main(GenerateTrace.java:5)
+	ExceptionStacktraceKey = attribute.Key("exception.stacktrace")
+
+	// ExceptionTypeKey is the attribute Key conforming to the "exception.type"
+	// semantic conventions. It represents the type of the exception (its
+	// fully-qualified class name, if applicable). The dynamic type of the exception
+	// should be preferred over the static type in languages that support it.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "java.net.ConnectException", "OSError"
+	ExceptionTypeKey = attribute.Key("exception.type")
+)
+
+// ExceptionMessage returns an attribute KeyValue conforming to the
+// "exception.message" semantic conventions. It represents the exception message.
+func ExceptionMessage(val string) attribute.KeyValue {
+	return ExceptionMessageKey.String(val)
+}
+
+// ExceptionStacktrace returns an attribute KeyValue conforming to the
+// "exception.stacktrace" semantic conventions. It represents a stacktrace as a
+// string in the natural representation for the language runtime. The
+// representation is to be determined and documented by each language SIG.
+func ExceptionStacktrace(val string) attribute.KeyValue {
+	return ExceptionStacktraceKey.String(val)
+}
+
+// ExceptionType returns an attribute KeyValue conforming to the "exception.type"
+// semantic conventions. It represents the type of the exception (its
+// fully-qualified class name, if applicable). The dynamic type of the exception
+// should be preferred over the static type in languages that support it.
+func ExceptionType(val string) attribute.KeyValue {
+	return ExceptionTypeKey.String(val)
+}
+
+// Namespace: faas
+const (
+	// FaaSColdstartKey is the attribute Key conforming to the "faas.coldstart"
+	// semantic conventions. It represents a boolean that is true if the serverless
+	// function is executed for the first time (aka cold-start).
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	FaaSColdstartKey = attribute.Key("faas.coldstart")
+
+	// FaaSCronKey is the attribute Key conforming to the "faas.cron" semantic
+	// conventions. It represents a string containing the schedule period as
+	// [Cron Expression].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0/5 * * * ? *
+	//
+	// [Cron Expression]: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm
+	FaaSCronKey = attribute.Key("faas.cron")
+
+	// FaaSDocumentCollectionKey is the attribute Key conforming to the
+	// "faas.document.collection" semantic conventions. It represents the name of
+	// the source on which the triggering operation was performed. For example, in
+	// Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the
+	// database name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "myBucketName", "myDbName"
+	FaaSDocumentCollectionKey = attribute.Key("faas.document.collection")
+
+	// FaaSDocumentNameKey is the attribute Key conforming to the
+	// "faas.document.name" semantic conventions. It represents the document
+	// name/table subjected to the operation. For example, in Cloud Storage or S3 is
+	// the name of the file, and in Cosmos DB the table name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "myFile.txt", "myTableName"
+	FaaSDocumentNameKey = attribute.Key("faas.document.name")
+
+	// FaaSDocumentOperationKey is the attribute Key conforming to the
+	// "faas.document.operation" semantic conventions. It represents the describes
+	// the type of the operation that was performed on the data.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	FaaSDocumentOperationKey = attribute.Key("faas.document.operation")
+
+	// FaaSDocumentTimeKey is the attribute Key conforming to the
+	// "faas.document.time" semantic conventions. It represents a string containing
+	// the time when the data was accessed in the [ISO 8601] format expressed in
+	// [UTC].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 2020-01-23T13:47:06Z
+	//
+	// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html
+	// [UTC]: https://www.w3.org/TR/NOTE-datetime
+	FaaSDocumentTimeKey = attribute.Key("faas.document.time")
+
+	// FaaSInstanceKey is the attribute Key conforming to the "faas.instance"
+	// semantic conventions. It represents the execution environment ID as a string,
+	// that will be potentially reused for other invocations to the same
+	// function/function version.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de"
+	// Note: - **AWS Lambda:** Use the (full) log stream name.
+	FaaSInstanceKey = attribute.Key("faas.instance")
+
+	// FaaSInvocationIDKey is the attribute Key conforming to the
+	// "faas.invocation_id" semantic conventions. It represents the invocation ID of
+	// the current function invocation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: af9d5aa4-a685-4c5f-a22b-444f80b3cc28
+	FaaSInvocationIDKey = attribute.Key("faas.invocation_id")
+
+	// FaaSInvokedNameKey is the attribute Key conforming to the "faas.invoked_name"
+	// semantic conventions. It represents the name of the invoked function.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: my-function
+	// Note: SHOULD be equal to the `faas.name` resource attribute of the invoked
+	// function.
+	FaaSInvokedNameKey = attribute.Key("faas.invoked_name")
+
+	// FaaSInvokedProviderKey is the attribute Key conforming to the
+	// "faas.invoked_provider" semantic conventions. It represents the cloud
+	// provider of the invoked function.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: SHOULD be equal to the `cloud.provider` resource attribute of the
+	// invoked function.
+	FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider")
+
+	// FaaSInvokedRegionKey is the attribute Key conforming to the
+	// "faas.invoked_region" semantic conventions. It represents the cloud region of
+	// the invoked function.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: eu-central-1
+	// Note: SHOULD be equal to the `cloud.region` resource attribute of the invoked
+	// function.
+	FaaSInvokedRegionKey = attribute.Key("faas.invoked_region")
+
+	// FaaSMaxMemoryKey is the attribute Key conforming to the "faas.max_memory"
+	// semantic conventions. It represents the amount of memory available to the
+	// serverless function converted to Bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Note: It's recommended to set this attribute since e.g. too little memory can
+	// easily stop a Java AWS Lambda function from working correctly. On AWS Lambda,
+	// the environment variable `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this
+	// information (which must be multiplied by 1,048,576).
+	FaaSMaxMemoryKey = attribute.Key("faas.max_memory")
+
+	// FaaSNameKey is the attribute Key conforming to the "faas.name" semantic
+	// conventions. It represents the name of the single function that this runtime
+	// instance executes.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-function", "myazurefunctionapp/some-function-name"
+	// Note: This is the name of the function as configured/deployed on the FaaS
+	// platform and is usually different from the name of the callback
+	// function (which may be stored in the
+	// [`code.namespace`/`code.function.name`]
+	// span attributes).
+	//
+	// For some cloud providers, the above definition is ambiguous. The following
+	// definition of function name MUST be used for this attribute
+	// (and consequently the span name) for the listed cloud providers/products:
+	//
+	//   - **Azure:** The full name `/`, i.e., function app name
+	//     followed by a forward slash followed by the function name (this form
+	//     can also be seen in the resource JSON for the function).
+	//     This means that a span attribute MUST be used, as an Azure function
+	//     app can host multiple functions that would usually share
+	//     a TracerProvider (see also the `cloud.resource_id` attribute).
+	//
+	//
+	// [`code.namespace`/`code.function.name`]: /docs/general/attributes.md#source-code-attributes
+	FaaSNameKey = attribute.Key("faas.name")
+
+	// FaaSTimeKey is the attribute Key conforming to the "faas.time" semantic
+	// conventions. It represents a string containing the function invocation time
+	// in the [ISO 8601] format expressed in [UTC].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 2020-01-23T13:47:06Z
+	//
+	// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html
+	// [UTC]: https://www.w3.org/TR/NOTE-datetime
+	FaaSTimeKey = attribute.Key("faas.time")
+
+	// FaaSTriggerKey is the attribute Key conforming to the "faas.trigger" semantic
+	// conventions. It represents the type of the trigger which caused this function
+	// invocation.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	FaaSTriggerKey = attribute.Key("faas.trigger")
+
+	// FaaSVersionKey is the attribute Key conforming to the "faas.version" semantic
+	// conventions. It represents the immutable version of the function being
+	// executed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "26", "pinkfroid-00002"
+	// Note: Depending on the cloud provider and platform, use:
+	//
+	//   - **AWS Lambda:** The [function version]
+	//     (an integer represented as a decimal string).
+	//   - **Google Cloud Run (Services):** The [revision]
+	//     (i.e., the function name plus the revision suffix).
+	//   - **Google Cloud Functions:** The value of the
+	//     [`K_REVISION` environment variable].
+	//   - **Azure Functions:** Not applicable. Do not set this attribute.
+	//
+	//
+	// [function version]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html
+	// [revision]: https://cloud.google.com/run/docs/managing/revisions
+	// [`K_REVISION` environment variable]: https://cloud.google.com/functions/docs/env-var#runtime_environment_variables_set_automatically
+	FaaSVersionKey = attribute.Key("faas.version")
+)
+
+// FaaSColdstart returns an attribute KeyValue conforming to the "faas.coldstart"
+// semantic conventions. It represents a boolean that is true if the serverless
+// function is executed for the first time (aka cold-start).
+func FaaSColdstart(val bool) attribute.KeyValue {
+	return FaaSColdstartKey.Bool(val)
+}
+
+// FaaSCron returns an attribute KeyValue conforming to the "faas.cron" semantic
+// conventions. It represents a string containing the schedule period as
+// [Cron Expression].
+//
+// [Cron Expression]: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm
+func FaaSCron(val string) attribute.KeyValue {
+	return FaaSCronKey.String(val)
+}
+
+// FaaSDocumentCollection returns an attribute KeyValue conforming to the
+// "faas.document.collection" semantic conventions. It represents the name of the
+// source on which the triggering operation was performed. For example, in Cloud
+// Storage or S3 corresponds to the bucket name, and in Cosmos DB to the database
+// name.
+func FaaSDocumentCollection(val string) attribute.KeyValue {
+	return FaaSDocumentCollectionKey.String(val)
+}
+
+// FaaSDocumentName returns an attribute KeyValue conforming to the
+// "faas.document.name" semantic conventions. It represents the document
+// name/table subjected to the operation. For example, in Cloud Storage or S3 is
+// the name of the file, and in Cosmos DB the table name.
+func FaaSDocumentName(val string) attribute.KeyValue {
+	return FaaSDocumentNameKey.String(val)
+}
+
+// FaaSDocumentTime returns an attribute KeyValue conforming to the
+// "faas.document.time" semantic conventions. It represents a string containing
+// the time when the data was accessed in the [ISO 8601] format expressed in
+// [UTC].
+//
+// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html
+// [UTC]: https://www.w3.org/TR/NOTE-datetime
+func FaaSDocumentTime(val string) attribute.KeyValue {
+	return FaaSDocumentTimeKey.String(val)
+}
+
+// FaaSInstance returns an attribute KeyValue conforming to the "faas.instance"
+// semantic conventions. It represents the execution environment ID as a string,
+// that will be potentially reused for other invocations to the same
+// function/function version.
+func FaaSInstance(val string) attribute.KeyValue {
+	return FaaSInstanceKey.String(val)
+}
+
+// FaaSInvocationID returns an attribute KeyValue conforming to the
+// "faas.invocation_id" semantic conventions. It represents the invocation ID of
+// the current function invocation.
+func FaaSInvocationID(val string) attribute.KeyValue {
+	return FaaSInvocationIDKey.String(val)
+}
+
+// FaaSInvokedName returns an attribute KeyValue conforming to the
+// "faas.invoked_name" semantic conventions. It represents the name of the
+// invoked function.
+func FaaSInvokedName(val string) attribute.KeyValue {
+	return FaaSInvokedNameKey.String(val)
+}
+
+// FaaSInvokedRegion returns an attribute KeyValue conforming to the
+// "faas.invoked_region" semantic conventions. It represents the cloud region of
+// the invoked function.
+func FaaSInvokedRegion(val string) attribute.KeyValue {
+	return FaaSInvokedRegionKey.String(val)
+}
+
+// FaaSMaxMemory returns an attribute KeyValue conforming to the
+// "faas.max_memory" semantic conventions. It represents the amount of memory
+// available to the serverless function converted to Bytes.
+func FaaSMaxMemory(val int) attribute.KeyValue {
+	return FaaSMaxMemoryKey.Int(val)
+}
+
+// FaaSName returns an attribute KeyValue conforming to the "faas.name" semantic
+// conventions. It represents the name of the single function that this runtime
+// instance executes.
+func FaaSName(val string) attribute.KeyValue {
+	return FaaSNameKey.String(val)
+}
+
+// FaaSTime returns an attribute KeyValue conforming to the "faas.time" semantic
+// conventions. It represents a string containing the function invocation time in
+// the [ISO 8601] format expressed in [UTC].
+//
+// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html
+// [UTC]: https://www.w3.org/TR/NOTE-datetime
+func FaaSTime(val string) attribute.KeyValue {
+	return FaaSTimeKey.String(val)
+}
+
+// FaaSVersion returns an attribute KeyValue conforming to the "faas.version"
+// semantic conventions. It represents the immutable version of the function
+// being executed.
+func FaaSVersion(val string) attribute.KeyValue {
+	return FaaSVersionKey.String(val)
+}
+
+// Enum values for faas.document.operation
+var (
+	// When a new object is created.
+	// Stability: development
+	FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert")
+	// When an object is modified.
+	// Stability: development
+	FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit")
+	// When an object is deleted.
+	// Stability: development
+	FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete")
+)
+
+// Enum values for faas.invoked_provider
+var (
+	// Alibaba Cloud
+	// Stability: development
+	FaaSInvokedProviderAlibabaCloud = FaaSInvokedProviderKey.String("alibaba_cloud")
+	// Amazon Web Services
+	// Stability: development
+	FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws")
+	// Microsoft Azure
+	// Stability: development
+	FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure")
+	// Google Cloud Platform
+	// Stability: development
+	FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp")
+	// Tencent Cloud
+	// Stability: development
+	FaaSInvokedProviderTencentCloud = FaaSInvokedProviderKey.String("tencent_cloud")
+)
+
+// Enum values for faas.trigger
+var (
+	// A response to some data source operation such as a database or filesystem
+	// read/write
+	// Stability: development
+	FaaSTriggerDatasource = FaaSTriggerKey.String("datasource")
+	// To provide an answer to an inbound HTTP request
+	// Stability: development
+	FaaSTriggerHTTP = FaaSTriggerKey.String("http")
+	// A function is set to be executed when messages are sent to a messaging system
+	// Stability: development
+	FaaSTriggerPubSub = FaaSTriggerKey.String("pubsub")
+	// A function is scheduled to be executed regularly
+	// Stability: development
+	FaaSTriggerTimer = FaaSTriggerKey.String("timer")
+	// If none of the others apply
+	// Stability: development
+	FaaSTriggerOther = FaaSTriggerKey.String("other")
+)
+
+// Namespace: feature_flag
+const (
+	// FeatureFlagContextIDKey is the attribute Key conforming to the
+	// "feature_flag.context.id" semantic conventions. It represents the unique
+	// identifier for the flag evaluation context. For example, the targeting key.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "5157782b-2203-4c80-a857-dbbd5e7761db"
+	FeatureFlagContextIDKey = attribute.Key("feature_flag.context.id")
+
+	// FeatureFlagKeyKey is the attribute Key conforming to the "feature_flag.key"
+	// semantic conventions. It represents the lookup key of the feature flag.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "logo-color"
+	FeatureFlagKeyKey = attribute.Key("feature_flag.key")
+
+	// FeatureFlagProviderNameKey is the attribute Key conforming to the
+	// "feature_flag.provider.name" semantic conventions. It represents the
+	// identifies the feature flag provider.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Flag Manager"
+	FeatureFlagProviderNameKey = attribute.Key("feature_flag.provider.name")
+
+	// FeatureFlagResultReasonKey is the attribute Key conforming to the
+	// "feature_flag.result.reason" semantic conventions. It represents the reason
+	// code which shows how a feature flag value was determined.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "static", "targeting_match", "error", "default"
+	FeatureFlagResultReasonKey = attribute.Key("feature_flag.result.reason")
+
+	// FeatureFlagResultValueKey is the attribute Key conforming to the
+	// "feature_flag.result.value" semantic conventions. It represents the evaluated
+	// value of the feature flag.
+	//
+	// Type: any
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "#ff0000", true, 3
+	// Note: With some feature flag providers, feature flag results can be quite
+	// large or contain private or sensitive details.
+	// Because of this, `feature_flag.result.variant` is often the preferred
+	// attribute if it is available.
+	//
+	// It may be desirable to redact or otherwise limit the size and scope of
+	// `feature_flag.result.value` if possible.
+	// Because the evaluated flag value is unstructured and may be any type, it is
+	// left to the instrumentation author to determine how best to achieve this.
+	FeatureFlagResultValueKey = attribute.Key("feature_flag.result.value")
+
+	// FeatureFlagResultVariantKey is the attribute Key conforming to the
+	// "feature_flag.result.variant" semantic conventions. It represents a semantic
+	// identifier for an evaluated flag value.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "red", "true", "on"
+	// Note: A semantic identifier, commonly referred to as a variant, provides a
+	// means
+	// for referring to a value without including the value itself. This can
+	// provide additional context for understanding the meaning behind a value.
+	// For example, the variant `red` maybe be used for the value `#c05543`.
+	FeatureFlagResultVariantKey = attribute.Key("feature_flag.result.variant")
+
+	// FeatureFlagSetIDKey is the attribute Key conforming to the
+	// "feature_flag.set.id" semantic conventions. It represents the identifier of
+	// the [flag set] to which the feature flag belongs.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "proj-1", "ab98sgs", "service1/dev"
+	//
+	// [flag set]: https://openfeature.dev/specification/glossary/#flag-set
+	FeatureFlagSetIDKey = attribute.Key("feature_flag.set.id")
+
+	// FeatureFlagVersionKey is the attribute Key conforming to the
+	// "feature_flag.version" semantic conventions. It represents the version of the
+	// ruleset used during the evaluation. This may be any stable value which
+	// uniquely identifies the ruleset.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1", "01ABCDEF"
+	FeatureFlagVersionKey = attribute.Key("feature_flag.version")
+)
+
+// FeatureFlagContextID returns an attribute KeyValue conforming to the
+// "feature_flag.context.id" semantic conventions. It represents the unique
+// identifier for the flag evaluation context. For example, the targeting key.
+func FeatureFlagContextID(val string) attribute.KeyValue {
+	return FeatureFlagContextIDKey.String(val)
+}
+
+// FeatureFlagKey returns an attribute KeyValue conforming to the
+// "feature_flag.key" semantic conventions. It represents the lookup key of the
+// feature flag.
+func FeatureFlagKey(val string) attribute.KeyValue {
+	return FeatureFlagKeyKey.String(val)
+}
+
+// FeatureFlagProviderName returns an attribute KeyValue conforming to the
+// "feature_flag.provider.name" semantic conventions. It represents the
+// identifies the feature flag provider.
+func FeatureFlagProviderName(val string) attribute.KeyValue {
+	return FeatureFlagProviderNameKey.String(val)
+}
+
+// FeatureFlagResultVariant returns an attribute KeyValue conforming to the
+// "feature_flag.result.variant" semantic conventions. It represents a semantic
+// identifier for an evaluated flag value.
+func FeatureFlagResultVariant(val string) attribute.KeyValue {
+	return FeatureFlagResultVariantKey.String(val)
+}
+
+// FeatureFlagSetID returns an attribute KeyValue conforming to the
+// "feature_flag.set.id" semantic conventions. It represents the identifier of
+// the [flag set] to which the feature flag belongs.
+//
+// [flag set]: https://openfeature.dev/specification/glossary/#flag-set
+func FeatureFlagSetID(val string) attribute.KeyValue {
+	return FeatureFlagSetIDKey.String(val)
+}
+
+// FeatureFlagVersion returns an attribute KeyValue conforming to the
+// "feature_flag.version" semantic conventions. It represents the version of the
+// ruleset used during the evaluation. This may be any stable value which
+// uniquely identifies the ruleset.
+func FeatureFlagVersion(val string) attribute.KeyValue {
+	return FeatureFlagVersionKey.String(val)
+}
+
+// Enum values for feature_flag.result.reason
+var (
+	// The resolved value is static (no dynamic evaluation).
+	// Stability: development
+	FeatureFlagResultReasonStatic = FeatureFlagResultReasonKey.String("static")
+	// The resolved value fell back to a pre-configured value (no dynamic evaluation
+	// occurred or dynamic evaluation yielded no result).
+	// Stability: development
+	FeatureFlagResultReasonDefault = FeatureFlagResultReasonKey.String("default")
+	// The resolved value was the result of a dynamic evaluation, such as a rule or
+	// specific user-targeting.
+	// Stability: development
+	FeatureFlagResultReasonTargetingMatch = FeatureFlagResultReasonKey.String("targeting_match")
+	// The resolved value was the result of pseudorandom assignment.
+	// Stability: development
+	FeatureFlagResultReasonSplit = FeatureFlagResultReasonKey.String("split")
+	// The resolved value was retrieved from cache.
+	// Stability: development
+	FeatureFlagResultReasonCached = FeatureFlagResultReasonKey.String("cached")
+	// The resolved value was the result of the flag being disabled in the
+	// management system.
+	// Stability: development
+	FeatureFlagResultReasonDisabled = FeatureFlagResultReasonKey.String("disabled")
+	// The reason for the resolved value could not be determined.
+	// Stability: development
+	FeatureFlagResultReasonUnknown = FeatureFlagResultReasonKey.String("unknown")
+	// The resolved value is non-authoritative or possibly out of date
+	// Stability: development
+	FeatureFlagResultReasonStale = FeatureFlagResultReasonKey.String("stale")
+	// The resolved value was the result of an error.
+	// Stability: development
+	FeatureFlagResultReasonError = FeatureFlagResultReasonKey.String("error")
+)
+
+// Namespace: file
+const (
+	// FileAccessedKey is the attribute Key conforming to the "file.accessed"
+	// semantic conventions. It represents the time when the file was last accessed,
+	// in ISO 8601 format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T12:00:00Z"
+	// Note: This attribute might not be supported by some file systems — NFS,
+	// FAT32, in embedded OS, etc.
+	FileAccessedKey = attribute.Key("file.accessed")
+
+	// FileAttributesKey is the attribute Key conforming to the "file.attributes"
+	// semantic conventions. It represents the array of file attributes.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "readonly", "hidden"
+	// Note: Attributes names depend on the OS or file system. Here’s a
+	// non-exhaustive list of values expected for this attribute: `archive`,
+	// `compressed`, `directory`, `encrypted`, `execute`, `hidden`, `immutable`,
+	// `journaled`, `read`, `readonly`, `symbolic link`, `system`, `temporary`,
+	// `write`.
+	FileAttributesKey = attribute.Key("file.attributes")
+
+	// FileChangedKey is the attribute Key conforming to the "file.changed" semantic
+	// conventions. It represents the time when the file attributes or metadata was
+	// last changed, in ISO 8601 format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T12:00:00Z"
+	// Note: `file.changed` captures the time when any of the file's properties or
+	// attributes (including the content) are changed, while `file.modified`
+	// captures the timestamp when the file content is modified.
+	FileChangedKey = attribute.Key("file.changed")
+
+	// FileCreatedKey is the attribute Key conforming to the "file.created" semantic
+	// conventions. It represents the time when the file was created, in ISO 8601
+	// format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T12:00:00Z"
+	// Note: This attribute might not be supported by some file systems — NFS,
+	// FAT32, in embedded OS, etc.
+	FileCreatedKey = attribute.Key("file.created")
+
+	// FileDirectoryKey is the attribute Key conforming to the "file.directory"
+	// semantic conventions. It represents the directory where the file is located.
+	// It should include the drive letter, when appropriate.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/home/user", "C:\Program Files\MyApp"
+	FileDirectoryKey = attribute.Key("file.directory")
+
+	// FileExtensionKey is the attribute Key conforming to the "file.extension"
+	// semantic conventions. It represents the file extension, excluding the leading
+	// dot.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "png", "gz"
+	// Note: When the file name has multiple extensions (example.tar.gz), only the
+	// last one should be captured ("gz", not "tar.gz").
+	FileExtensionKey = attribute.Key("file.extension")
+
+	// FileForkNameKey is the attribute Key conforming to the "file.fork_name"
+	// semantic conventions. It represents the name of the fork. A fork is
+	// additional data associated with a filesystem object.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Zone.Identifer"
+	// Note: On Linux, a resource fork is used to store additional data with a
+	// filesystem object. A file always has at least one fork for the data portion,
+	// and additional forks may exist.
+	// On NTFS, this is analogous to an Alternate Data Stream (ADS), and the default
+	// data stream for a file is just called $DATA. Zone.Identifier is commonly used
+	// by Windows to track contents downloaded from the Internet. An ADS is
+	// typically of the form: C:\path\to\filename.extension:some_fork_name, and
+	// some_fork_name is the value that should populate `fork_name`.
+	// `filename.extension` should populate `file.name`, and `extension` should
+	// populate `file.extension`. The full path, `file.path`, will include the fork
+	// name.
+	FileForkNameKey = attribute.Key("file.fork_name")
+
+	// FileGroupIDKey is the attribute Key conforming to the "file.group.id"
+	// semantic conventions. It represents the primary Group ID (GID) of the file.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1000"
+	FileGroupIDKey = attribute.Key("file.group.id")
+
+	// FileGroupNameKey is the attribute Key conforming to the "file.group.name"
+	// semantic conventions. It represents the primary group name of the file.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "users"
+	FileGroupNameKey = attribute.Key("file.group.name")
+
+	// FileInodeKey is the attribute Key conforming to the "file.inode" semantic
+	// conventions. It represents the inode representing the file in the filesystem.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "256383"
+	FileInodeKey = attribute.Key("file.inode")
+
+	// FileModeKey is the attribute Key conforming to the "file.mode" semantic
+	// conventions. It represents the mode of the file in octal representation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0640"
+	FileModeKey = attribute.Key("file.mode")
+
+	// FileModifiedKey is the attribute Key conforming to the "file.modified"
+	// semantic conventions. It represents the time when the file content was last
+	// modified, in ISO 8601 format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T12:00:00Z"
+	FileModifiedKey = attribute.Key("file.modified")
+
+	// FileNameKey is the attribute Key conforming to the "file.name" semantic
+	// conventions. It represents the name of the file including the extension,
+	// without the directory.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "example.png"
+	FileNameKey = attribute.Key("file.name")
+
+	// FileOwnerIDKey is the attribute Key conforming to the "file.owner.id"
+	// semantic conventions. It represents the user ID (UID) or security identifier
+	// (SID) of the file owner.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1000"
+	FileOwnerIDKey = attribute.Key("file.owner.id")
+
+	// FileOwnerNameKey is the attribute Key conforming to the "file.owner.name"
+	// semantic conventions. It represents the username of the file owner.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "root"
+	FileOwnerNameKey = attribute.Key("file.owner.name")
+
+	// FilePathKey is the attribute Key conforming to the "file.path" semantic
+	// conventions. It represents the full path to the file, including the file
+	// name. It should include the drive letter, when appropriate.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/home/alice/example.png", "C:\Program Files\MyApp\myapp.exe"
+	FilePathKey = attribute.Key("file.path")
+
+	// FileSizeKey is the attribute Key conforming to the "file.size" semantic
+	// conventions. It represents the file size in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	FileSizeKey = attribute.Key("file.size")
+
+	// FileSymbolicLinkTargetPathKey is the attribute Key conforming to the
+	// "file.symbolic_link.target_path" semantic conventions. It represents the path
+	// to the target of a symbolic link.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/usr/bin/python3"
+	// Note: This attribute is only applicable to symbolic links.
+	FileSymbolicLinkTargetPathKey = attribute.Key("file.symbolic_link.target_path")
+)
+
+// FileAccessed returns an attribute KeyValue conforming to the "file.accessed"
+// semantic conventions. It represents the time when the file was last accessed,
+// in ISO 8601 format.
+func FileAccessed(val string) attribute.KeyValue {
+	return FileAccessedKey.String(val)
+}
+
+// FileAttributes returns an attribute KeyValue conforming to the
+// "file.attributes" semantic conventions. It represents the array of file
+// attributes.
+func FileAttributes(val ...string) attribute.KeyValue {
+	return FileAttributesKey.StringSlice(val)
+}
+
+// FileChanged returns an attribute KeyValue conforming to the "file.changed"
+// semantic conventions. It represents the time when the file attributes or
+// metadata was last changed, in ISO 8601 format.
+func FileChanged(val string) attribute.KeyValue {
+	return FileChangedKey.String(val)
+}
+
+// FileCreated returns an attribute KeyValue conforming to the "file.created"
+// semantic conventions. It represents the time when the file was created, in ISO
+// 8601 format.
+func FileCreated(val string) attribute.KeyValue {
+	return FileCreatedKey.String(val)
+}
+
+// FileDirectory returns an attribute KeyValue conforming to the "file.directory"
+// semantic conventions. It represents the directory where the file is located.
+// It should include the drive letter, when appropriate.
+func FileDirectory(val string) attribute.KeyValue {
+	return FileDirectoryKey.String(val)
+}
+
+// FileExtension returns an attribute KeyValue conforming to the "file.extension"
+// semantic conventions. It represents the file extension, excluding the leading
+// dot.
+func FileExtension(val string) attribute.KeyValue {
+	return FileExtensionKey.String(val)
+}
+
+// FileForkName returns an attribute KeyValue conforming to the "file.fork_name"
+// semantic conventions. It represents the name of the fork. A fork is additional
+// data associated with a filesystem object.
+func FileForkName(val string) attribute.KeyValue {
+	return FileForkNameKey.String(val)
+}
+
+// FileGroupID returns an attribute KeyValue conforming to the "file.group.id"
+// semantic conventions. It represents the primary Group ID (GID) of the file.
+func FileGroupID(val string) attribute.KeyValue {
+	return FileGroupIDKey.String(val)
+}
+
+// FileGroupName returns an attribute KeyValue conforming to the
+// "file.group.name" semantic conventions. It represents the primary group name
+// of the file.
+func FileGroupName(val string) attribute.KeyValue {
+	return FileGroupNameKey.String(val)
+}
+
+// FileInode returns an attribute KeyValue conforming to the "file.inode"
+// semantic conventions. It represents the inode representing the file in the
+// filesystem.
+func FileInode(val string) attribute.KeyValue {
+	return FileInodeKey.String(val)
+}
+
+// FileMode returns an attribute KeyValue conforming to the "file.mode" semantic
+// conventions. It represents the mode of the file in octal representation.
+func FileMode(val string) attribute.KeyValue {
+	return FileModeKey.String(val)
+}
+
+// FileModified returns an attribute KeyValue conforming to the "file.modified"
+// semantic conventions. It represents the time when the file content was last
+// modified, in ISO 8601 format.
+func FileModified(val string) attribute.KeyValue {
+	return FileModifiedKey.String(val)
+}
+
+// FileName returns an attribute KeyValue conforming to the "file.name" semantic
+// conventions. It represents the name of the file including the extension,
+// without the directory.
+func FileName(val string) attribute.KeyValue {
+	return FileNameKey.String(val)
+}
+
+// FileOwnerID returns an attribute KeyValue conforming to the "file.owner.id"
+// semantic conventions. It represents the user ID (UID) or security identifier
+// (SID) of the file owner.
+func FileOwnerID(val string) attribute.KeyValue {
+	return FileOwnerIDKey.String(val)
+}
+
+// FileOwnerName returns an attribute KeyValue conforming to the
+// "file.owner.name" semantic conventions. It represents the username of the file
+// owner.
+func FileOwnerName(val string) attribute.KeyValue {
+	return FileOwnerNameKey.String(val)
+}
+
+// FilePath returns an attribute KeyValue conforming to the "file.path" semantic
+// conventions. It represents the full path to the file, including the file name.
+// It should include the drive letter, when appropriate.
+func FilePath(val string) attribute.KeyValue {
+	return FilePathKey.String(val)
+}
+
+// FileSize returns an attribute KeyValue conforming to the "file.size" semantic
+// conventions. It represents the file size in bytes.
+func FileSize(val int) attribute.KeyValue {
+	return FileSizeKey.Int(val)
+}
+
+// FileSymbolicLinkTargetPath returns an attribute KeyValue conforming to the
+// "file.symbolic_link.target_path" semantic conventions. It represents the path
+// to the target of a symbolic link.
+func FileSymbolicLinkTargetPath(val string) attribute.KeyValue {
+	return FileSymbolicLinkTargetPathKey.String(val)
+}
+
+// Namespace: gcp
+const (
+	// GCPAppHubApplicationContainerKey is the attribute Key conforming to the
+	// "gcp.apphub.application.container" semantic conventions. It represents the
+	// container within GCP where the AppHub application is defined.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "projects/my-container-project"
+	GCPAppHubApplicationContainerKey = attribute.Key("gcp.apphub.application.container")
+
+	// GCPAppHubApplicationIDKey is the attribute Key conforming to the
+	// "gcp.apphub.application.id" semantic conventions. It represents the name of
+	// the application as configured in AppHub.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-application"
+	GCPAppHubApplicationIDKey = attribute.Key("gcp.apphub.application.id")
+
+	// GCPAppHubApplicationLocationKey is the attribute Key conforming to the
+	// "gcp.apphub.application.location" semantic conventions. It represents the GCP
+	// zone or region where the application is defined.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "us-central1"
+	GCPAppHubApplicationLocationKey = attribute.Key("gcp.apphub.application.location")
+
+	// GCPAppHubServiceCriticalityTypeKey is the attribute Key conforming to the
+	// "gcp.apphub.service.criticality_type" semantic conventions. It represents the
+	// criticality of a service indicates its importance to the business.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: [See AppHub type enum]
+	//
+	// [See AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type
+	GCPAppHubServiceCriticalityTypeKey = attribute.Key("gcp.apphub.service.criticality_type")
+
+	// GCPAppHubServiceEnvironmentTypeKey is the attribute Key conforming to the
+	// "gcp.apphub.service.environment_type" semantic conventions. It represents the
+	// environment of a service is the stage of a software lifecycle.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: [See AppHub environment type]
+	//
+	// [See AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1
+	GCPAppHubServiceEnvironmentTypeKey = attribute.Key("gcp.apphub.service.environment_type")
+
+	// GCPAppHubServiceIDKey is the attribute Key conforming to the
+	// "gcp.apphub.service.id" semantic conventions. It represents the name of the
+	// service as configured in AppHub.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-service"
+	GCPAppHubServiceIDKey = attribute.Key("gcp.apphub.service.id")
+
+	// GCPAppHubWorkloadCriticalityTypeKey is the attribute Key conforming to the
+	// "gcp.apphub.workload.criticality_type" semantic conventions. It represents
+	// the criticality of a workload indicates its importance to the business.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: [See AppHub type enum]
+	//
+	// [See AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type
+	GCPAppHubWorkloadCriticalityTypeKey = attribute.Key("gcp.apphub.workload.criticality_type")
+
+	// GCPAppHubWorkloadEnvironmentTypeKey is the attribute Key conforming to the
+	// "gcp.apphub.workload.environment_type" semantic conventions. It represents
+	// the environment of a workload is the stage of a software lifecycle.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: [See AppHub environment type]
+	//
+	// [See AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1
+	GCPAppHubWorkloadEnvironmentTypeKey = attribute.Key("gcp.apphub.workload.environment_type")
+
+	// GCPAppHubWorkloadIDKey is the attribute Key conforming to the
+	// "gcp.apphub.workload.id" semantic conventions. It represents the name of the
+	// workload as configured in AppHub.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-workload"
+	GCPAppHubWorkloadIDKey = attribute.Key("gcp.apphub.workload.id")
+
+	// GCPClientServiceKey is the attribute Key conforming to the
+	// "gcp.client.service" semantic conventions. It represents the identifies the
+	// Google Cloud service for which the official client library is intended.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "appengine", "run", "firestore", "alloydb", "spanner"
+	// Note: Intended to be a stable identifier for Google Cloud client libraries
+	// that is uniform across implementation languages. The value should be derived
+	// from the canonical service domain for the service; for example,
+	// 'foo.googleapis.com' should result in a value of 'foo'.
+	GCPClientServiceKey = attribute.Key("gcp.client.service")
+
+	// GCPCloudRunJobExecutionKey is the attribute Key conforming to the
+	// "gcp.cloud_run.job.execution" semantic conventions. It represents the name of
+	// the Cloud Run [execution] being run for the Job, as set by the
+	// [`CLOUD_RUN_EXECUTION`] environment variable.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "job-name-xxxx", "sample-job-mdw84"
+	//
+	// [execution]: https://cloud.google.com/run/docs/managing/job-executions
+	// [`CLOUD_RUN_EXECUTION`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars
+	GCPCloudRunJobExecutionKey = attribute.Key("gcp.cloud_run.job.execution")
+
+	// GCPCloudRunJobTaskIndexKey is the attribute Key conforming to the
+	// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index
+	// for a task within an execution as provided by the [`CLOUD_RUN_TASK_INDEX`]
+	// environment variable.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0, 1
+	//
+	// [`CLOUD_RUN_TASK_INDEX`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars
+	GCPCloudRunJobTaskIndexKey = attribute.Key("gcp.cloud_run.job.task_index")
+
+	// GCPGCEInstanceHostnameKey is the attribute Key conforming to the
+	// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname
+	// of a GCE instance. This is the full value of the default or [custom hostname]
+	// .
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-host1234.example.com",
+	// "sample-vm.us-west1-b.c.my-project.internal"
+	//
+	// [custom hostname]: https://cloud.google.com/compute/docs/instances/custom-hostname-vm
+	GCPGCEInstanceHostnameKey = attribute.Key("gcp.gce.instance.hostname")
+
+	// GCPGCEInstanceNameKey is the attribute Key conforming to the
+	// "gcp.gce.instance.name" semantic conventions. It represents the instance name
+	// of a GCE instance. This is the value provided by `host.name`, the visible
+	// name of the instance in the Cloud Console UI, and the prefix for the default
+	// hostname of the instance as defined by the [default internal DNS name].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "instance-1", "my-vm-name"
+	//
+	// [default internal DNS name]: https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names
+	GCPGCEInstanceNameKey = attribute.Key("gcp.gce.instance.name")
+)
+
+// GCPAppHubApplicationContainer returns an attribute KeyValue conforming to the
+// "gcp.apphub.application.container" semantic conventions. It represents the
+// container within GCP where the AppHub application is defined.
+func GCPAppHubApplicationContainer(val string) attribute.KeyValue {
+	return GCPAppHubApplicationContainerKey.String(val)
+}
+
+// GCPAppHubApplicationID returns an attribute KeyValue conforming to the
+// "gcp.apphub.application.id" semantic conventions. It represents the name of
+// the application as configured in AppHub.
+func GCPAppHubApplicationID(val string) attribute.KeyValue {
+	return GCPAppHubApplicationIDKey.String(val)
+}
+
+// GCPAppHubApplicationLocation returns an attribute KeyValue conforming to the
+// "gcp.apphub.application.location" semantic conventions. It represents the GCP
+// zone or region where the application is defined.
+func GCPAppHubApplicationLocation(val string) attribute.KeyValue {
+	return GCPAppHubApplicationLocationKey.String(val)
+}
+
+// GCPAppHubServiceID returns an attribute KeyValue conforming to the
+// "gcp.apphub.service.id" semantic conventions. It represents the name of the
+// service as configured in AppHub.
+func GCPAppHubServiceID(val string) attribute.KeyValue {
+	return GCPAppHubServiceIDKey.String(val)
+}
+
+// GCPAppHubWorkloadID returns an attribute KeyValue conforming to the
+// "gcp.apphub.workload.id" semantic conventions. It represents the name of the
+// workload as configured in AppHub.
+func GCPAppHubWorkloadID(val string) attribute.KeyValue {
+	return GCPAppHubWorkloadIDKey.String(val)
+}
+
+// GCPClientService returns an attribute KeyValue conforming to the
+// "gcp.client.service" semantic conventions. It represents the identifies the
+// Google Cloud service for which the official client library is intended.
+func GCPClientService(val string) attribute.KeyValue {
+	return GCPClientServiceKey.String(val)
+}
+
+// GCPCloudRunJobExecution returns an attribute KeyValue conforming to the
+// "gcp.cloud_run.job.execution" semantic conventions. It represents the name of
+// the Cloud Run [execution] being run for the Job, as set by the
+// [`CLOUD_RUN_EXECUTION`] environment variable.
+//
+// [execution]: https://cloud.google.com/run/docs/managing/job-executions
+// [`CLOUD_RUN_EXECUTION`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars
+func GCPCloudRunJobExecution(val string) attribute.KeyValue {
+	return GCPCloudRunJobExecutionKey.String(val)
+}
+
+// GCPCloudRunJobTaskIndex returns an attribute KeyValue conforming to the
+// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index
+// for a task within an execution as provided by the [`CLOUD_RUN_TASK_INDEX`]
+// environment variable.
+//
+// [`CLOUD_RUN_TASK_INDEX`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars
+func GCPCloudRunJobTaskIndex(val int) attribute.KeyValue {
+	return GCPCloudRunJobTaskIndexKey.Int(val)
+}
+
+// GCPGCEInstanceHostname returns an attribute KeyValue conforming to the
+// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname
+// of a GCE instance. This is the full value of the default or [custom hostname]
+// .
+//
+// [custom hostname]: https://cloud.google.com/compute/docs/instances/custom-hostname-vm
+func GCPGCEInstanceHostname(val string) attribute.KeyValue {
+	return GCPGCEInstanceHostnameKey.String(val)
+}
+
+// GCPGCEInstanceName returns an attribute KeyValue conforming to the
+// "gcp.gce.instance.name" semantic conventions. It represents the instance name
+// of a GCE instance. This is the value provided by `host.name`, the visible name
+// of the instance in the Cloud Console UI, and the prefix for the default
+// hostname of the instance as defined by the [default internal DNS name].
+//
+// [default internal DNS name]: https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names
+func GCPGCEInstanceName(val string) attribute.KeyValue {
+	return GCPGCEInstanceNameKey.String(val)
+}
+
+// Enum values for gcp.apphub.service.criticality_type
+var (
+	// Mission critical service.
+	// Stability: development
+	GCPAppHubServiceCriticalityTypeMissionCritical = GCPAppHubServiceCriticalityTypeKey.String("MISSION_CRITICAL")
+	// High impact.
+	// Stability: development
+	GCPAppHubServiceCriticalityTypeHigh = GCPAppHubServiceCriticalityTypeKey.String("HIGH")
+	// Medium impact.
+	// Stability: development
+	GCPAppHubServiceCriticalityTypeMedium = GCPAppHubServiceCriticalityTypeKey.String("MEDIUM")
+	// Low impact.
+	// Stability: development
+	GCPAppHubServiceCriticalityTypeLow = GCPAppHubServiceCriticalityTypeKey.String("LOW")
+)
+
+// Enum values for gcp.apphub.service.environment_type
+var (
+	// Production environment.
+	// Stability: development
+	GCPAppHubServiceEnvironmentTypeProduction = GCPAppHubServiceEnvironmentTypeKey.String("PRODUCTION")
+	// Staging environment.
+	// Stability: development
+	GCPAppHubServiceEnvironmentTypeStaging = GCPAppHubServiceEnvironmentTypeKey.String("STAGING")
+	// Test environment.
+	// Stability: development
+	GCPAppHubServiceEnvironmentTypeTest = GCPAppHubServiceEnvironmentTypeKey.String("TEST")
+	// Development environment.
+	// Stability: development
+	GCPAppHubServiceEnvironmentTypeDevelopment = GCPAppHubServiceEnvironmentTypeKey.String("DEVELOPMENT")
+)
+
+// Enum values for gcp.apphub.workload.criticality_type
+var (
+	// Mission critical service.
+	// Stability: development
+	GCPAppHubWorkloadCriticalityTypeMissionCritical = GCPAppHubWorkloadCriticalityTypeKey.String("MISSION_CRITICAL")
+	// High impact.
+	// Stability: development
+	GCPAppHubWorkloadCriticalityTypeHigh = GCPAppHubWorkloadCriticalityTypeKey.String("HIGH")
+	// Medium impact.
+	// Stability: development
+	GCPAppHubWorkloadCriticalityTypeMedium = GCPAppHubWorkloadCriticalityTypeKey.String("MEDIUM")
+	// Low impact.
+	// Stability: development
+	GCPAppHubWorkloadCriticalityTypeLow = GCPAppHubWorkloadCriticalityTypeKey.String("LOW")
+)
+
+// Enum values for gcp.apphub.workload.environment_type
+var (
+	// Production environment.
+	// Stability: development
+	GCPAppHubWorkloadEnvironmentTypeProduction = GCPAppHubWorkloadEnvironmentTypeKey.String("PRODUCTION")
+	// Staging environment.
+	// Stability: development
+	GCPAppHubWorkloadEnvironmentTypeStaging = GCPAppHubWorkloadEnvironmentTypeKey.String("STAGING")
+	// Test environment.
+	// Stability: development
+	GCPAppHubWorkloadEnvironmentTypeTest = GCPAppHubWorkloadEnvironmentTypeKey.String("TEST")
+	// Development environment.
+	// Stability: development
+	GCPAppHubWorkloadEnvironmentTypeDevelopment = GCPAppHubWorkloadEnvironmentTypeKey.String("DEVELOPMENT")
+)
+
+// Namespace: gen_ai
+const (
+	// GenAIAgentDescriptionKey is the attribute Key conforming to the
+	// "gen_ai.agent.description" semantic conventions. It represents the free-form
+	// description of the GenAI agent provided by the application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Helps with math problems", "Generates fiction stories"
+	GenAIAgentDescriptionKey = attribute.Key("gen_ai.agent.description")
+
+	// GenAIAgentIDKey is the attribute Key conforming to the "gen_ai.agent.id"
+	// semantic conventions. It represents the unique identifier of the GenAI agent.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "asst_5j66UpCpwteGg4YSxUnt7lPY"
+	GenAIAgentIDKey = attribute.Key("gen_ai.agent.id")
+
+	// GenAIAgentNameKey is the attribute Key conforming to the "gen_ai.agent.name"
+	// semantic conventions. It represents the human-readable name of the GenAI
+	// agent provided by the application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Math Tutor", "Fiction Writer"
+	GenAIAgentNameKey = attribute.Key("gen_ai.agent.name")
+
+	// GenAIConversationIDKey is the attribute Key conforming to the
+	// "gen_ai.conversation.id" semantic conventions. It represents the unique
+	// identifier for a conversation (session, thread), used to store and correlate
+	// messages within this conversation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "conv_5j66UpCpwteGg4YSxUnt7lPY"
+	GenAIConversationIDKey = attribute.Key("gen_ai.conversation.id")
+
+	// GenAIDataSourceIDKey is the attribute Key conforming to the
+	// "gen_ai.data_source.id" semantic conventions. It represents the data source
+	// identifier.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "H7STPQYOND"
+	// Note: Data sources are used by AI agents and RAG applications to store
+	// grounding data. A data source may be an external database, object store,
+	// document collection, website, or any other storage system used by the GenAI
+	// agent or application. The `gen_ai.data_source.id` SHOULD match the identifier
+	// used by the GenAI system rather than a name specific to the external storage,
+	// such as a database or object store. Semantic conventions referencing
+	// `gen_ai.data_source.id` MAY also leverage additional attributes, such as
+	// `db.*`, to further identify and describe the data source.
+	GenAIDataSourceIDKey = attribute.Key("gen_ai.data_source.id")
+
+	// GenAIOpenAIRequestServiceTierKey is the attribute Key conforming to the
+	// "gen_ai.openai.request.service_tier" semantic conventions. It represents the
+	// service tier requested. May be a specific tier, default, or auto.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "auto", "default"
+	GenAIOpenAIRequestServiceTierKey = attribute.Key("gen_ai.openai.request.service_tier")
+
+	// GenAIOpenAIResponseServiceTierKey is the attribute Key conforming to the
+	// "gen_ai.openai.response.service_tier" semantic conventions. It represents the
+	// service tier used for the response.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "scale", "default"
+	GenAIOpenAIResponseServiceTierKey = attribute.Key("gen_ai.openai.response.service_tier")
+
+	// GenAIOpenAIResponseSystemFingerprintKey is the attribute Key conforming to
+	// the "gen_ai.openai.response.system_fingerprint" semantic conventions. It
+	// represents a fingerprint to track any eventual change in the Generative AI
+	// environment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "fp_44709d6fcb"
+	GenAIOpenAIResponseSystemFingerprintKey = attribute.Key("gen_ai.openai.response.system_fingerprint")
+
+	// GenAIOperationNameKey is the attribute Key conforming to the
+	// "gen_ai.operation.name" semantic conventions. It represents the name of the
+	// operation being performed.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: If one of the predefined values applies, but specific system uses a
+	// different name it's RECOMMENDED to document it in the semantic conventions
+	// for specific GenAI system and use system-specific name in the
+	// instrumentation. If a different name is not documented, instrumentation
+	// libraries SHOULD use applicable predefined value.
+	GenAIOperationNameKey = attribute.Key("gen_ai.operation.name")
+
+	// GenAIOutputTypeKey is the attribute Key conforming to the
+	// "gen_ai.output.type" semantic conventions. It represents the represents the
+	// content type requested by the client.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: This attribute SHOULD be used when the client requests output of a
+	// specific type. The model may return zero or more outputs of this type.
+	// This attribute specifies the output modality and not the actual output
+	// format. For example, if an image is requested, the actual output could be a
+	// URL pointing to an image file.
+	// Additional output format details may be recorded in the future in the
+	// `gen_ai.output.{type}.*` attributes.
+	GenAIOutputTypeKey = attribute.Key("gen_ai.output.type")
+
+	// GenAIRequestChoiceCountKey is the attribute Key conforming to the
+	// "gen_ai.request.choice.count" semantic conventions. It represents the target
+	// number of candidate completions to return.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 3
+	GenAIRequestChoiceCountKey = attribute.Key("gen_ai.request.choice.count")
+
+	// GenAIRequestEncodingFormatsKey is the attribute Key conforming to the
+	// "gen_ai.request.encoding_formats" semantic conventions. It represents the
+	// encoding formats requested in an embeddings operation, if specified.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "base64"], ["float", "binary"
+	// Note: In some GenAI systems the encoding formats are called embedding types.
+	// Also, some GenAI systems only accept a single format per request.
+	GenAIRequestEncodingFormatsKey = attribute.Key("gen_ai.request.encoding_formats")
+
+	// GenAIRequestFrequencyPenaltyKey is the attribute Key conforming to the
+	// "gen_ai.request.frequency_penalty" semantic conventions. It represents the
+	// frequency penalty setting for the GenAI request.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0.1
+	GenAIRequestFrequencyPenaltyKey = attribute.Key("gen_ai.request.frequency_penalty")
+
+	// GenAIRequestMaxTokensKey is the attribute Key conforming to the
+	// "gen_ai.request.max_tokens" semantic conventions. It represents the maximum
+	// number of tokens the model generates for a request.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 100
+	GenAIRequestMaxTokensKey = attribute.Key("gen_ai.request.max_tokens")
+
+	// GenAIRequestModelKey is the attribute Key conforming to the
+	// "gen_ai.request.model" semantic conventions. It represents the name of the
+	// GenAI model a request is being made to.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: gpt-4
+	GenAIRequestModelKey = attribute.Key("gen_ai.request.model")
+
+	// GenAIRequestPresencePenaltyKey is the attribute Key conforming to the
+	// "gen_ai.request.presence_penalty" semantic conventions. It represents the
+	// presence penalty setting for the GenAI request.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0.1
+	GenAIRequestPresencePenaltyKey = attribute.Key("gen_ai.request.presence_penalty")
+
+	// GenAIRequestSeedKey is the attribute Key conforming to the
+	// "gen_ai.request.seed" semantic conventions. It represents the requests with
+	// same seed value more likely to return same result.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 100
+	GenAIRequestSeedKey = attribute.Key("gen_ai.request.seed")
+
+	// GenAIRequestStopSequencesKey is the attribute Key conforming to the
+	// "gen_ai.request.stop_sequences" semantic conventions. It represents the list
+	// of sequences that the model will use to stop generating further tokens.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "forest", "lived"
+	GenAIRequestStopSequencesKey = attribute.Key("gen_ai.request.stop_sequences")
+
+	// GenAIRequestTemperatureKey is the attribute Key conforming to the
+	// "gen_ai.request.temperature" semantic conventions. It represents the
+	// temperature setting for the GenAI request.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0.0
+	GenAIRequestTemperatureKey = attribute.Key("gen_ai.request.temperature")
+
+	// GenAIRequestTopKKey is the attribute Key conforming to the
+	// "gen_ai.request.top_k" semantic conventions. It represents the top_k sampling
+	// setting for the GenAI request.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1.0
+	GenAIRequestTopKKey = attribute.Key("gen_ai.request.top_k")
+
+	// GenAIRequestTopPKey is the attribute Key conforming to the
+	// "gen_ai.request.top_p" semantic conventions. It represents the top_p sampling
+	// setting for the GenAI request.
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1.0
+	GenAIRequestTopPKey = attribute.Key("gen_ai.request.top_p")
+
+	// GenAIResponseFinishReasonsKey is the attribute Key conforming to the
+	// "gen_ai.response.finish_reasons" semantic conventions. It represents the
+	// array of reasons the model stopped generating tokens, corresponding to each
+	// generation received.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "stop"], ["stop", "length"
+	GenAIResponseFinishReasonsKey = attribute.Key("gen_ai.response.finish_reasons")
+
+	// GenAIResponseIDKey is the attribute Key conforming to the
+	// "gen_ai.response.id" semantic conventions. It represents the unique
+	// identifier for the completion.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "chatcmpl-123"
+	GenAIResponseIDKey = attribute.Key("gen_ai.response.id")
+
+	// GenAIResponseModelKey is the attribute Key conforming to the
+	// "gen_ai.response.model" semantic conventions. It represents the name of the
+	// model that generated the response.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "gpt-4-0613"
+	GenAIResponseModelKey = attribute.Key("gen_ai.response.model")
+
+	// GenAISystemKey is the attribute Key conforming to the "gen_ai.system"
+	// semantic conventions. It represents the Generative AI product as identified
+	// by the client or server instrumentation.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: openai
+	// Note: The `gen_ai.system` describes a family of GenAI models with specific
+	// model identified
+	// by `gen_ai.request.model` and `gen_ai.response.model` attributes.
+	//
+	// The actual GenAI product may differ from the one identified by the client.
+	// Multiple systems, including Azure OpenAI and Gemini, are accessible by OpenAI
+	// client
+	// libraries. In such cases, the `gen_ai.system` is set to `openai` based on the
+	// instrumentation's best knowledge, instead of the actual system. The
+	// `server.address`
+	// attribute may help identify the actual system in use for `openai`.
+	//
+	// For custom model, a custom friendly name SHOULD be used.
+	// If none of these options apply, the `gen_ai.system` SHOULD be set to `_OTHER`
+	// .
+	GenAISystemKey = attribute.Key("gen_ai.system")
+
+	// GenAITokenTypeKey is the attribute Key conforming to the "gen_ai.token.type"
+	// semantic conventions. It represents the type of token being counted.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "input", "output"
+	GenAITokenTypeKey = attribute.Key("gen_ai.token.type")
+
+	// GenAIToolCallIDKey is the attribute Key conforming to the
+	// "gen_ai.tool.call.id" semantic conventions. It represents the tool call
+	// identifier.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "call_mszuSIzqtI65i1wAUOE8w5H4"
+	GenAIToolCallIDKey = attribute.Key("gen_ai.tool.call.id")
+
+	// GenAIToolDescriptionKey is the attribute Key conforming to the
+	// "gen_ai.tool.description" semantic conventions. It represents the tool
+	// description.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Multiply two numbers"
+	GenAIToolDescriptionKey = attribute.Key("gen_ai.tool.description")
+
+	// GenAIToolNameKey is the attribute Key conforming to the "gen_ai.tool.name"
+	// semantic conventions. It represents the name of the tool utilized by the
+	// agent.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Flights"
+	GenAIToolNameKey = attribute.Key("gen_ai.tool.name")
+
+	// GenAIToolTypeKey is the attribute Key conforming to the "gen_ai.tool.type"
+	// semantic conventions. It represents the type of the tool utilized by the
+	// agent.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "function", "extension", "datastore"
+	// Note: Extension: A tool executed on the agent-side to directly call external
+	// APIs, bridging the gap between the agent and real-world systems.
+	// Agent-side operations involve actions that are performed by the agent on the
+	// server or within the agent's controlled environment.
+	// Function: A tool executed on the client-side, where the agent generates
+	// parameters for a predefined function, and the client executes the logic.
+	// Client-side operations are actions taken on the user's end or within the
+	// client application.
+	// Datastore: A tool used by the agent to access and query structured or
+	// unstructured external data for retrieval-augmented tasks or knowledge
+	// updates.
+	GenAIToolTypeKey = attribute.Key("gen_ai.tool.type")
+
+	// GenAIUsageInputTokensKey is the attribute Key conforming to the
+	// "gen_ai.usage.input_tokens" semantic conventions. It represents the number of
+	// tokens used in the GenAI input (prompt).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 100
+	GenAIUsageInputTokensKey = attribute.Key("gen_ai.usage.input_tokens")
+
+	// GenAIUsageOutputTokensKey is the attribute Key conforming to the
+	// "gen_ai.usage.output_tokens" semantic conventions. It represents the number
+	// of tokens used in the GenAI response (completion).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 180
+	GenAIUsageOutputTokensKey = attribute.Key("gen_ai.usage.output_tokens")
+)
+
+// GenAIAgentDescription returns an attribute KeyValue conforming to the
+// "gen_ai.agent.description" semantic conventions. It represents the free-form
+// description of the GenAI agent provided by the application.
+func GenAIAgentDescription(val string) attribute.KeyValue {
+	return GenAIAgentDescriptionKey.String(val)
+}
+
+// GenAIAgentID returns an attribute KeyValue conforming to the "gen_ai.agent.id"
+// semantic conventions. It represents the unique identifier of the GenAI agent.
+func GenAIAgentID(val string) attribute.KeyValue {
+	return GenAIAgentIDKey.String(val)
+}
+
+// GenAIAgentName returns an attribute KeyValue conforming to the
+// "gen_ai.agent.name" semantic conventions. It represents the human-readable
+// name of the GenAI agent provided by the application.
+func GenAIAgentName(val string) attribute.KeyValue {
+	return GenAIAgentNameKey.String(val)
+}
+
+// GenAIConversationID returns an attribute KeyValue conforming to the
+// "gen_ai.conversation.id" semantic conventions. It represents the unique
+// identifier for a conversation (session, thread), used to store and correlate
+// messages within this conversation.
+func GenAIConversationID(val string) attribute.KeyValue {
+	return GenAIConversationIDKey.String(val)
+}
+
+// GenAIDataSourceID returns an attribute KeyValue conforming to the
+// "gen_ai.data_source.id" semantic conventions. It represents the data source
+// identifier.
+func GenAIDataSourceID(val string) attribute.KeyValue {
+	return GenAIDataSourceIDKey.String(val)
+}
+
+// GenAIOpenAIResponseServiceTier returns an attribute KeyValue conforming to the
+// "gen_ai.openai.response.service_tier" semantic conventions. It represents the
+// service tier used for the response.
+func GenAIOpenAIResponseServiceTier(val string) attribute.KeyValue {
+	return GenAIOpenAIResponseServiceTierKey.String(val)
+}
+
+// GenAIOpenAIResponseSystemFingerprint returns an attribute KeyValue conforming
+// to the "gen_ai.openai.response.system_fingerprint" semantic conventions. It
+// represents a fingerprint to track any eventual change in the Generative AI
+// environment.
+func GenAIOpenAIResponseSystemFingerprint(val string) attribute.KeyValue {
+	return GenAIOpenAIResponseSystemFingerprintKey.String(val)
+}
+
+// GenAIRequestChoiceCount returns an attribute KeyValue conforming to the
+// "gen_ai.request.choice.count" semantic conventions. It represents the target
+// number of candidate completions to return.
+func GenAIRequestChoiceCount(val int) attribute.KeyValue {
+	return GenAIRequestChoiceCountKey.Int(val)
+}
+
+// GenAIRequestEncodingFormats returns an attribute KeyValue conforming to the
+// "gen_ai.request.encoding_formats" semantic conventions. It represents the
+// encoding formats requested in an embeddings operation, if specified.
+func GenAIRequestEncodingFormats(val ...string) attribute.KeyValue {
+	return GenAIRequestEncodingFormatsKey.StringSlice(val)
+}
+
+// GenAIRequestFrequencyPenalty returns an attribute KeyValue conforming to the
+// "gen_ai.request.frequency_penalty" semantic conventions. It represents the
+// frequency penalty setting for the GenAI request.
+func GenAIRequestFrequencyPenalty(val float64) attribute.KeyValue {
+	return GenAIRequestFrequencyPenaltyKey.Float64(val)
+}
+
+// GenAIRequestMaxTokens returns an attribute KeyValue conforming to the
+// "gen_ai.request.max_tokens" semantic conventions. It represents the maximum
+// number of tokens the model generates for a request.
+func GenAIRequestMaxTokens(val int) attribute.KeyValue {
+	return GenAIRequestMaxTokensKey.Int(val)
+}
+
+// GenAIRequestModel returns an attribute KeyValue conforming to the
+// "gen_ai.request.model" semantic conventions. It represents the name of the
+// GenAI model a request is being made to.
+func GenAIRequestModel(val string) attribute.KeyValue {
+	return GenAIRequestModelKey.String(val)
+}
+
+// GenAIRequestPresencePenalty returns an attribute KeyValue conforming to the
+// "gen_ai.request.presence_penalty" semantic conventions. It represents the
+// presence penalty setting for the GenAI request.
+func GenAIRequestPresencePenalty(val float64) attribute.KeyValue {
+	return GenAIRequestPresencePenaltyKey.Float64(val)
+}
+
+// GenAIRequestSeed returns an attribute KeyValue conforming to the
+// "gen_ai.request.seed" semantic conventions. It represents the requests with
+// same seed value more likely to return same result.
+func GenAIRequestSeed(val int) attribute.KeyValue {
+	return GenAIRequestSeedKey.Int(val)
+}
+
+// GenAIRequestStopSequences returns an attribute KeyValue conforming to the
+// "gen_ai.request.stop_sequences" semantic conventions. It represents the list
+// of sequences that the model will use to stop generating further tokens.
+func GenAIRequestStopSequences(val ...string) attribute.KeyValue {
+	return GenAIRequestStopSequencesKey.StringSlice(val)
+}
+
+// GenAIRequestTemperature returns an attribute KeyValue conforming to the
+// "gen_ai.request.temperature" semantic conventions. It represents the
+// temperature setting for the GenAI request.
+func GenAIRequestTemperature(val float64) attribute.KeyValue {
+	return GenAIRequestTemperatureKey.Float64(val)
+}
+
+// GenAIRequestTopK returns an attribute KeyValue conforming to the
+// "gen_ai.request.top_k" semantic conventions. It represents the top_k sampling
+// setting for the GenAI request.
+func GenAIRequestTopK(val float64) attribute.KeyValue {
+	return GenAIRequestTopKKey.Float64(val)
+}
+
+// GenAIRequestTopP returns an attribute KeyValue conforming to the
+// "gen_ai.request.top_p" semantic conventions. It represents the top_p sampling
+// setting for the GenAI request.
+func GenAIRequestTopP(val float64) attribute.KeyValue {
+	return GenAIRequestTopPKey.Float64(val)
+}
+
+// GenAIResponseFinishReasons returns an attribute KeyValue conforming to the
+// "gen_ai.response.finish_reasons" semantic conventions. It represents the array
+// of reasons the model stopped generating tokens, corresponding to each
+// generation received.
+func GenAIResponseFinishReasons(val ...string) attribute.KeyValue {
+	return GenAIResponseFinishReasonsKey.StringSlice(val)
+}
+
+// GenAIResponseID returns an attribute KeyValue conforming to the
+// "gen_ai.response.id" semantic conventions. It represents the unique identifier
+// for the completion.
+func GenAIResponseID(val string) attribute.KeyValue {
+	return GenAIResponseIDKey.String(val)
+}
+
+// GenAIResponseModel returns an attribute KeyValue conforming to the
+// "gen_ai.response.model" semantic conventions. It represents the name of the
+// model that generated the response.
+func GenAIResponseModel(val string) attribute.KeyValue {
+	return GenAIResponseModelKey.String(val)
+}
+
+// GenAIToolCallID returns an attribute KeyValue conforming to the
+// "gen_ai.tool.call.id" semantic conventions. It represents the tool call
+// identifier.
+func GenAIToolCallID(val string) attribute.KeyValue {
+	return GenAIToolCallIDKey.String(val)
+}
+
+// GenAIToolDescription returns an attribute KeyValue conforming to the
+// "gen_ai.tool.description" semantic conventions. It represents the tool
+// description.
+func GenAIToolDescription(val string) attribute.KeyValue {
+	return GenAIToolDescriptionKey.String(val)
+}
+
+// GenAIToolName returns an attribute KeyValue conforming to the
+// "gen_ai.tool.name" semantic conventions. It represents the name of the tool
+// utilized by the agent.
+func GenAIToolName(val string) attribute.KeyValue {
+	return GenAIToolNameKey.String(val)
+}
+
+// GenAIToolType returns an attribute KeyValue conforming to the
+// "gen_ai.tool.type" semantic conventions. It represents the type of the tool
+// utilized by the agent.
+func GenAIToolType(val string) attribute.KeyValue {
+	return GenAIToolTypeKey.String(val)
+}
+
+// GenAIUsageInputTokens returns an attribute KeyValue conforming to the
+// "gen_ai.usage.input_tokens" semantic conventions. It represents the number of
+// tokens used in the GenAI input (prompt).
+func GenAIUsageInputTokens(val int) attribute.KeyValue {
+	return GenAIUsageInputTokensKey.Int(val)
+}
+
+// GenAIUsageOutputTokens returns an attribute KeyValue conforming to the
+// "gen_ai.usage.output_tokens" semantic conventions. It represents the number of
+// tokens used in the GenAI response (completion).
+func GenAIUsageOutputTokens(val int) attribute.KeyValue {
+	return GenAIUsageOutputTokensKey.Int(val)
+}
+
+// Enum values for gen_ai.openai.request.service_tier
+var (
+	// The system will utilize scale tier credits until they are exhausted.
+	// Stability: development
+	GenAIOpenAIRequestServiceTierAuto = GenAIOpenAIRequestServiceTierKey.String("auto")
+	// The system will utilize the default scale tier.
+	// Stability: development
+	GenAIOpenAIRequestServiceTierDefault = GenAIOpenAIRequestServiceTierKey.String("default")
+)
+
+// Enum values for gen_ai.operation.name
+var (
+	// Chat completion operation such as [OpenAI Chat API]
+	// Stability: development
+	//
+	// [OpenAI Chat API]: https://platform.openai.com/docs/api-reference/chat
+	GenAIOperationNameChat = GenAIOperationNameKey.String("chat")
+	// Multimodal content generation operation such as [Gemini Generate Content]
+	// Stability: development
+	//
+	// [Gemini Generate Content]: https://ai.google.dev/api/generate-content
+	GenAIOperationNameGenerateContent = GenAIOperationNameKey.String("generate_content")
+	// Text completions operation such as [OpenAI Completions API (Legacy)]
+	// Stability: development
+	//
+	// [OpenAI Completions API (Legacy)]: https://platform.openai.com/docs/api-reference/completions
+	GenAIOperationNameTextCompletion = GenAIOperationNameKey.String("text_completion")
+	// Embeddings operation such as [OpenAI Create embeddings API]
+	// Stability: development
+	//
+	// [OpenAI Create embeddings API]: https://platform.openai.com/docs/api-reference/embeddings/create
+	GenAIOperationNameEmbeddings = GenAIOperationNameKey.String("embeddings")
+	// Create GenAI agent
+	// Stability: development
+	GenAIOperationNameCreateAgent = GenAIOperationNameKey.String("create_agent")
+	// Invoke GenAI agent
+	// Stability: development
+	GenAIOperationNameInvokeAgent = GenAIOperationNameKey.String("invoke_agent")
+	// Execute a tool
+	// Stability: development
+	GenAIOperationNameExecuteTool = GenAIOperationNameKey.String("execute_tool")
+)
+
+// Enum values for gen_ai.output.type
+var (
+	// Plain text
+	// Stability: development
+	GenAIOutputTypeText = GenAIOutputTypeKey.String("text")
+	// JSON object with known or unknown schema
+	// Stability: development
+	GenAIOutputTypeJSON = GenAIOutputTypeKey.String("json")
+	// Image
+	// Stability: development
+	GenAIOutputTypeImage = GenAIOutputTypeKey.String("image")
+	// Speech
+	// Stability: development
+	GenAIOutputTypeSpeech = GenAIOutputTypeKey.String("speech")
+)
+
+// Enum values for gen_ai.system
+var (
+	// OpenAI
+	// Stability: development
+	GenAISystemOpenAI = GenAISystemKey.String("openai")
+	// Any Google generative AI endpoint
+	// Stability: development
+	GenAISystemGCPGenAI = GenAISystemKey.String("gcp.gen_ai")
+	// Vertex AI
+	// Stability: development
+	GenAISystemGCPVertexAI = GenAISystemKey.String("gcp.vertex_ai")
+	// Gemini
+	// Stability: development
+	GenAISystemGCPGemini = GenAISystemKey.String("gcp.gemini")
+	// Deprecated: Use 'gcp.vertex_ai' instead.
+	GenAISystemVertexAI = GenAISystemKey.String("vertex_ai")
+	// Deprecated: Use 'gcp.gemini' instead.
+	GenAISystemGemini = GenAISystemKey.String("gemini")
+	// Anthropic
+	// Stability: development
+	GenAISystemAnthropic = GenAISystemKey.String("anthropic")
+	// Cohere
+	// Stability: development
+	GenAISystemCohere = GenAISystemKey.String("cohere")
+	// Azure AI Inference
+	// Stability: development
+	GenAISystemAzAIInference = GenAISystemKey.String("az.ai.inference")
+	// Azure OpenAI
+	// Stability: development
+	GenAISystemAzAIOpenAI = GenAISystemKey.String("az.ai.openai")
+	// IBM Watsonx AI
+	// Stability: development
+	GenAISystemIBMWatsonxAI = GenAISystemKey.String("ibm.watsonx.ai")
+	// AWS Bedrock
+	// Stability: development
+	GenAISystemAWSBedrock = GenAISystemKey.String("aws.bedrock")
+	// Perplexity
+	// Stability: development
+	GenAISystemPerplexity = GenAISystemKey.String("perplexity")
+	// xAI
+	// Stability: development
+	GenAISystemXai = GenAISystemKey.String("xai")
+	// DeepSeek
+	// Stability: development
+	GenAISystemDeepseek = GenAISystemKey.String("deepseek")
+	// Groq
+	// Stability: development
+	GenAISystemGroq = GenAISystemKey.String("groq")
+	// Mistral AI
+	// Stability: development
+	GenAISystemMistralAI = GenAISystemKey.String("mistral_ai")
+)
+
+// Enum values for gen_ai.token.type
+var (
+	// Input tokens (prompt, input, etc.)
+	// Stability: development
+	GenAITokenTypeInput = GenAITokenTypeKey.String("input")
+	// Deprecated: Replaced by `output`.
+	GenAITokenTypeCompletion = GenAITokenTypeKey.String("output")
+	// Output tokens (completion, response, etc.)
+	// Stability: development
+	GenAITokenTypeOutput = GenAITokenTypeKey.String("output")
+)
+
+// Namespace: geo
+const (
+	// GeoContinentCodeKey is the attribute Key conforming to the
+	// "geo.continent.code" semantic conventions. It represents the two-letter code
+	// representing continent’s name.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	GeoContinentCodeKey = attribute.Key("geo.continent.code")
+
+	// GeoCountryISOCodeKey is the attribute Key conforming to the
+	// "geo.country.iso_code" semantic conventions. It represents the two-letter ISO
+	// Country Code ([ISO 3166-1 alpha2]).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CA"
+	//
+	// [ISO 3166-1 alpha2]: https://wikipedia.org/wiki/ISO_3166-1#Codes
+	GeoCountryISOCodeKey = attribute.Key("geo.country.iso_code")
+
+	// GeoLocalityNameKey is the attribute Key conforming to the "geo.locality.name"
+	// semantic conventions. It represents the locality name. Represents the name of
+	// a city, town, village, or similar populated place.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Montreal", "Berlin"
+	GeoLocalityNameKey = attribute.Key("geo.locality.name")
+
+	// GeoLocationLatKey is the attribute Key conforming to the "geo.location.lat"
+	// semantic conventions. It represents the latitude of the geo location in
+	// [WGS84].
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 45.505918
+	//
+	// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84
+	GeoLocationLatKey = attribute.Key("geo.location.lat")
+
+	// GeoLocationLonKey is the attribute Key conforming to the "geo.location.lon"
+	// semantic conventions. It represents the longitude of the geo location in
+	// [WGS84].
+	//
+	// Type: double
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: -73.61483
+	//
+	// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84
+	GeoLocationLonKey = attribute.Key("geo.location.lon")
+
+	// GeoPostalCodeKey is the attribute Key conforming to the "geo.postal_code"
+	// semantic conventions. It represents the postal code associated with the
+	// location. Values appropriate for this field may also be known as a postcode
+	// or ZIP code and will vary widely from country to country.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "94040"
+	GeoPostalCodeKey = attribute.Key("geo.postal_code")
+
+	// GeoRegionISOCodeKey is the attribute Key conforming to the
+	// "geo.region.iso_code" semantic conventions. It represents the region ISO code
+	// ([ISO 3166-2]).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CA-QC"
+	//
+	// [ISO 3166-2]: https://wikipedia.org/wiki/ISO_3166-2
+	GeoRegionISOCodeKey = attribute.Key("geo.region.iso_code")
+)
+
+// GeoCountryISOCode returns an attribute KeyValue conforming to the
+// "geo.country.iso_code" semantic conventions. It represents the two-letter ISO
+// Country Code ([ISO 3166-1 alpha2]).
+//
+// [ISO 3166-1 alpha2]: https://wikipedia.org/wiki/ISO_3166-1#Codes
+func GeoCountryISOCode(val string) attribute.KeyValue {
+	return GeoCountryISOCodeKey.String(val)
+}
+
+// GeoLocalityName returns an attribute KeyValue conforming to the
+// "geo.locality.name" semantic conventions. It represents the locality name.
+// Represents the name of a city, town, village, or similar populated place.
+func GeoLocalityName(val string) attribute.KeyValue {
+	return GeoLocalityNameKey.String(val)
+}
+
+// GeoLocationLat returns an attribute KeyValue conforming to the
+// "geo.location.lat" semantic conventions. It represents the latitude of the geo
+// location in [WGS84].
+//
+// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84
+func GeoLocationLat(val float64) attribute.KeyValue {
+	return GeoLocationLatKey.Float64(val)
+}
+
+// GeoLocationLon returns an attribute KeyValue conforming to the
+// "geo.location.lon" semantic conventions. It represents the longitude of the
+// geo location in [WGS84].
+//
+// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84
+func GeoLocationLon(val float64) attribute.KeyValue {
+	return GeoLocationLonKey.Float64(val)
+}
+
+// GeoPostalCode returns an attribute KeyValue conforming to the
+// "geo.postal_code" semantic conventions. It represents the postal code
+// associated with the location. Values appropriate for this field may also be
+// known as a postcode or ZIP code and will vary widely from country to country.
+func GeoPostalCode(val string) attribute.KeyValue {
+	return GeoPostalCodeKey.String(val)
+}
+
+// GeoRegionISOCode returns an attribute KeyValue conforming to the
+// "geo.region.iso_code" semantic conventions. It represents the region ISO code
+// ([ISO 3166-2]).
+//
+// [ISO 3166-2]: https://wikipedia.org/wiki/ISO_3166-2
+func GeoRegionISOCode(val string) attribute.KeyValue {
+	return GeoRegionISOCodeKey.String(val)
+}
+
+// Enum values for geo.continent.code
+var (
+	// Africa
+	// Stability: development
+	GeoContinentCodeAf = GeoContinentCodeKey.String("AF")
+	// Antarctica
+	// Stability: development
+	GeoContinentCodeAn = GeoContinentCodeKey.String("AN")
+	// Asia
+	// Stability: development
+	GeoContinentCodeAs = GeoContinentCodeKey.String("AS")
+	// Europe
+	// Stability: development
+	GeoContinentCodeEu = GeoContinentCodeKey.String("EU")
+	// North America
+	// Stability: development
+	GeoContinentCodeNa = GeoContinentCodeKey.String("NA")
+	// Oceania
+	// Stability: development
+	GeoContinentCodeOc = GeoContinentCodeKey.String("OC")
+	// South America
+	// Stability: development
+	GeoContinentCodeSa = GeoContinentCodeKey.String("SA")
+)
+
+// Namespace: go
+const (
+	// GoMemoryTypeKey is the attribute Key conforming to the "go.memory.type"
+	// semantic conventions. It represents the type of memory.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "other", "stack"
+	GoMemoryTypeKey = attribute.Key("go.memory.type")
+)
+
+// Enum values for go.memory.type
+var (
+	// Memory allocated from the heap that is reserved for stack space, whether or
+	// not it is currently in-use.
+	// Stability: development
+	GoMemoryTypeStack = GoMemoryTypeKey.String("stack")
+	// Memory used by the Go runtime, excluding other categories of memory usage
+	// described in this enumeration.
+	// Stability: development
+	GoMemoryTypeOther = GoMemoryTypeKey.String("other")
+)
+
+// Namespace: graphql
+const (
+	// GraphQLDocumentKey is the attribute Key conforming to the "graphql.document"
+	// semantic conventions. It represents the GraphQL document being executed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: query findBookById { bookById(id: ?) { name } }
+	// Note: The value may be sanitized to exclude sensitive information.
+	GraphQLDocumentKey = attribute.Key("graphql.document")
+
+	// GraphQLOperationNameKey is the attribute Key conforming to the
+	// "graphql.operation.name" semantic conventions. It represents the name of the
+	// operation being executed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: findBookById
+	GraphQLOperationNameKey = attribute.Key("graphql.operation.name")
+
+	// GraphQLOperationTypeKey is the attribute Key conforming to the
+	// "graphql.operation.type" semantic conventions. It represents the type of the
+	// operation being executed.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "query", "mutation", "subscription"
+	GraphQLOperationTypeKey = attribute.Key("graphql.operation.type")
+)
+
+// GraphQLDocument returns an attribute KeyValue conforming to the
+// "graphql.document" semantic conventions. It represents the GraphQL document
+// being executed.
+func GraphQLDocument(val string) attribute.KeyValue {
+	return GraphQLDocumentKey.String(val)
+}
+
+// GraphQLOperationName returns an attribute KeyValue conforming to the
+// "graphql.operation.name" semantic conventions. It represents the name of the
+// operation being executed.
+func GraphQLOperationName(val string) attribute.KeyValue {
+	return GraphQLOperationNameKey.String(val)
+}
+
+// Enum values for graphql.operation.type
+var (
+	// GraphQL query
+	// Stability: development
+	GraphQLOperationTypeQuery = GraphQLOperationTypeKey.String("query")
+	// GraphQL mutation
+	// Stability: development
+	GraphQLOperationTypeMutation = GraphQLOperationTypeKey.String("mutation")
+	// GraphQL subscription
+	// Stability: development
+	GraphQLOperationTypeSubscription = GraphQLOperationTypeKey.String("subscription")
+)
+
+// Namespace: heroku
+const (
+	// HerokuAppIDKey is the attribute Key conforming to the "heroku.app.id"
+	// semantic conventions. It represents the unique identifier for the
+	// application.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2daa2797-e42b-4624-9322-ec3f968df4da"
+	HerokuAppIDKey = attribute.Key("heroku.app.id")
+
+	// HerokuReleaseCommitKey is the attribute Key conforming to the
+	// "heroku.release.commit" semantic conventions. It represents the commit hash
+	// for the current release.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "e6134959463efd8966b20e75b913cafe3f5ec"
+	HerokuReleaseCommitKey = attribute.Key("heroku.release.commit")
+
+	// HerokuReleaseCreationTimestampKey is the attribute Key conforming to the
+	// "heroku.release.creation_timestamp" semantic conventions. It represents the
+	// time and date the release was created.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2022-10-23T18:00:42Z"
+	HerokuReleaseCreationTimestampKey = attribute.Key("heroku.release.creation_timestamp")
+)
+
+// HerokuAppID returns an attribute KeyValue conforming to the "heroku.app.id"
+// semantic conventions. It represents the unique identifier for the application.
+func HerokuAppID(val string) attribute.KeyValue {
+	return HerokuAppIDKey.String(val)
+}
+
+// HerokuReleaseCommit returns an attribute KeyValue conforming to the
+// "heroku.release.commit" semantic conventions. It represents the commit hash
+// for the current release.
+func HerokuReleaseCommit(val string) attribute.KeyValue {
+	return HerokuReleaseCommitKey.String(val)
+}
+
+// HerokuReleaseCreationTimestamp returns an attribute KeyValue conforming to the
+// "heroku.release.creation_timestamp" semantic conventions. It represents the
+// time and date the release was created.
+func HerokuReleaseCreationTimestamp(val string) attribute.KeyValue {
+	return HerokuReleaseCreationTimestampKey.String(val)
+}
+
+// Namespace: host
+const (
+	// HostArchKey is the attribute Key conforming to the "host.arch" semantic
+	// conventions. It represents the CPU architecture the host system is running
+	// on.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	HostArchKey = attribute.Key("host.arch")
+
+	// HostCPUCacheL2SizeKey is the attribute Key conforming to the
+	// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of
+	// level 2 memory cache available to the processor (in Bytes).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 12288000
+	HostCPUCacheL2SizeKey = attribute.Key("host.cpu.cache.l2.size")
+
+	// HostCPUFamilyKey is the attribute Key conforming to the "host.cpu.family"
+	// semantic conventions. It represents the family or generation of the CPU.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "6", "PA-RISC 1.1e"
+	HostCPUFamilyKey = attribute.Key("host.cpu.family")
+
+	// HostCPUModelIDKey is the attribute Key conforming to the "host.cpu.model.id"
+	// semantic conventions. It represents the model identifier. It provides more
+	// granular information about the CPU, distinguishing it from other CPUs within
+	// the same family.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "6", "9000/778/B180L"
+	HostCPUModelIDKey = attribute.Key("host.cpu.model.id")
+
+	// HostCPUModelNameKey is the attribute Key conforming to the
+	// "host.cpu.model.name" semantic conventions. It represents the model
+	// designation of the processor.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz"
+	HostCPUModelNameKey = attribute.Key("host.cpu.model.name")
+
+	// HostCPUSteppingKey is the attribute Key conforming to the "host.cpu.stepping"
+	// semantic conventions. It represents the stepping or core revisions.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1", "r1p1"
+	HostCPUSteppingKey = attribute.Key("host.cpu.stepping")
+
+	// HostCPUVendorIDKey is the attribute Key conforming to the
+	// "host.cpu.vendor.id" semantic conventions. It represents the processor
+	// manufacturer identifier. A maximum 12-character string.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "GenuineIntel"
+	// Note: [CPUID] command returns the vendor ID string in EBX, EDX and ECX
+	// registers. Writing these to memory in this order results in a 12-character
+	// string.
+	//
+	// [CPUID]: https://wiki.osdev.org/CPUID
+	HostCPUVendorIDKey = attribute.Key("host.cpu.vendor.id")
+
+	// HostIDKey is the attribute Key conforming to the "host.id" semantic
+	// conventions. It represents the unique host ID. For Cloud, this must be the
+	// instance_id assigned by the cloud provider. For non-containerized systems,
+	// this should be the `machine-id`. See the table below for the sources to use
+	// to determine the `machine-id` based on operating system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "fdbf79e8af94cb7f9e8df36789187052"
+	HostIDKey = attribute.Key("host.id")
+
+	// HostImageIDKey is the attribute Key conforming to the "host.image.id"
+	// semantic conventions. It represents the VM image ID or host OS image ID. For
+	// Cloud, this value is from the provider.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "ami-07b06b442921831e5"
+	HostImageIDKey = attribute.Key("host.image.id")
+
+	// HostImageNameKey is the attribute Key conforming to the "host.image.name"
+	// semantic conventions. It represents the name of the VM image or OS install
+	// the host was instantiated from.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "infra-ami-eks-worker-node-7d4ec78312", "CentOS-8-x86_64-1905"
+	HostImageNameKey = attribute.Key("host.image.name")
+
+	// HostImageVersionKey is the attribute Key conforming to the
+	// "host.image.version" semantic conventions. It represents the version string
+	// of the VM image or host OS as defined in [Version Attributes].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0.1"
+	//
+	// [Version Attributes]: /docs/resource/README.md#version-attributes
+	HostImageVersionKey = attribute.Key("host.image.version")
+
+	// HostIPKey is the attribute Key conforming to the "host.ip" semantic
+	// conventions. It represents the available IP addresses of the host, excluding
+	// loopback interfaces.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "192.168.1.140", "fe80::abc2:4a28:737a:609e"
+	// Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6
+	// addresses MUST be specified in the [RFC 5952] format.
+	//
+	// [RFC 5952]: https://www.rfc-editor.org/rfc/rfc5952.html
+	HostIPKey = attribute.Key("host.ip")
+
+	// HostMacKey is the attribute Key conforming to the "host.mac" semantic
+	// conventions. It represents the available MAC addresses of the host, excluding
+	// loopback interfaces.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "AC-DE-48-23-45-67", "AC-DE-48-23-45-67-01-9F"
+	// Note: MAC Addresses MUST be represented in [IEEE RA hexadecimal form]: as
+	// hyphen-separated octets in uppercase hexadecimal form from most to least
+	// significant.
+	//
+	// [IEEE RA hexadecimal form]: https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf
+	HostMacKey = attribute.Key("host.mac")
+
+	// HostNameKey is the attribute Key conforming to the "host.name" semantic
+	// conventions. It represents the name of the host. On Unix systems, it may
+	// contain what the hostname command returns, or the fully qualified hostname,
+	// or another name specified by the user.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry-test"
+	HostNameKey = attribute.Key("host.name")
+
+	// HostTypeKey is the attribute Key conforming to the "host.type" semantic
+	// conventions. It represents the type of host. For Cloud, this must be the
+	// machine type.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "n1-standard-1"
+	HostTypeKey = attribute.Key("host.type")
+)
+
+// HostCPUCacheL2Size returns an attribute KeyValue conforming to the
+// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of
+// level 2 memory cache available to the processor (in Bytes).
+func HostCPUCacheL2Size(val int) attribute.KeyValue {
+	return HostCPUCacheL2SizeKey.Int(val)
+}
+
+// HostCPUFamily returns an attribute KeyValue conforming to the
+// "host.cpu.family" semantic conventions. It represents the family or generation
+// of the CPU.
+func HostCPUFamily(val string) attribute.KeyValue {
+	return HostCPUFamilyKey.String(val)
+}
+
+// HostCPUModelID returns an attribute KeyValue conforming to the
+// "host.cpu.model.id" semantic conventions. It represents the model identifier.
+// It provides more granular information about the CPU, distinguishing it from
+// other CPUs within the same family.
+func HostCPUModelID(val string) attribute.KeyValue {
+	return HostCPUModelIDKey.String(val)
+}
+
+// HostCPUModelName returns an attribute KeyValue conforming to the
+// "host.cpu.model.name" semantic conventions. It represents the model
+// designation of the processor.
+func HostCPUModelName(val string) attribute.KeyValue {
+	return HostCPUModelNameKey.String(val)
+}
+
+// HostCPUStepping returns an attribute KeyValue conforming to the
+// "host.cpu.stepping" semantic conventions. It represents the stepping or core
+// revisions.
+func HostCPUStepping(val string) attribute.KeyValue {
+	return HostCPUSteppingKey.String(val)
+}
+
+// HostCPUVendorID returns an attribute KeyValue conforming to the
+// "host.cpu.vendor.id" semantic conventions. It represents the processor
+// manufacturer identifier. A maximum 12-character string.
+func HostCPUVendorID(val string) attribute.KeyValue {
+	return HostCPUVendorIDKey.String(val)
+}
+
+// HostID returns an attribute KeyValue conforming to the "host.id" semantic
+// conventions. It represents the unique host ID. For Cloud, this must be the
+// instance_id assigned by the cloud provider. For non-containerized systems,
+// this should be the `machine-id`. See the table below for the sources to use to
+// determine the `machine-id` based on operating system.
+func HostID(val string) attribute.KeyValue {
+	return HostIDKey.String(val)
+}
+
+// HostImageID returns an attribute KeyValue conforming to the "host.image.id"
+// semantic conventions. It represents the VM image ID or host OS image ID. For
+// Cloud, this value is from the provider.
+func HostImageID(val string) attribute.KeyValue {
+	return HostImageIDKey.String(val)
+}
+
+// HostImageName returns an attribute KeyValue conforming to the
+// "host.image.name" semantic conventions. It represents the name of the VM image
+// or OS install the host was instantiated from.
+func HostImageName(val string) attribute.KeyValue {
+	return HostImageNameKey.String(val)
+}
+
+// HostImageVersion returns an attribute KeyValue conforming to the
+// "host.image.version" semantic conventions. It represents the version string of
+// the VM image or host OS as defined in [Version Attributes].
+//
+// [Version Attributes]: /docs/resource/README.md#version-attributes
+func HostImageVersion(val string) attribute.KeyValue {
+	return HostImageVersionKey.String(val)
+}
+
+// HostIP returns an attribute KeyValue conforming to the "host.ip" semantic
+// conventions. It represents the available IP addresses of the host, excluding
+// loopback interfaces.
+func HostIP(val ...string) attribute.KeyValue {
+	return HostIPKey.StringSlice(val)
+}
+
+// HostMac returns an attribute KeyValue conforming to the "host.mac" semantic
+// conventions. It represents the available MAC addresses of the host, excluding
+// loopback interfaces.
+func HostMac(val ...string) attribute.KeyValue {
+	return HostMacKey.StringSlice(val)
+}
+
+// HostName returns an attribute KeyValue conforming to the "host.name" semantic
+// conventions. It represents the name of the host. On Unix systems, it may
+// contain what the hostname command returns, or the fully qualified hostname, or
+// another name specified by the user.
+func HostName(val string) attribute.KeyValue {
+	return HostNameKey.String(val)
+}
+
+// HostType returns an attribute KeyValue conforming to the "host.type" semantic
+// conventions. It represents the type of host. For Cloud, this must be the
+// machine type.
+func HostType(val string) attribute.KeyValue {
+	return HostTypeKey.String(val)
+}
+
+// Enum values for host.arch
+var (
+	// AMD64
+	// Stability: development
+	HostArchAMD64 = HostArchKey.String("amd64")
+	// ARM32
+	// Stability: development
+	HostArchARM32 = HostArchKey.String("arm32")
+	// ARM64
+	// Stability: development
+	HostArchARM64 = HostArchKey.String("arm64")
+	// Itanium
+	// Stability: development
+	HostArchIA64 = HostArchKey.String("ia64")
+	// 32-bit PowerPC
+	// Stability: development
+	HostArchPPC32 = HostArchKey.String("ppc32")
+	// 64-bit PowerPC
+	// Stability: development
+	HostArchPPC64 = HostArchKey.String("ppc64")
+	// IBM z/Architecture
+	// Stability: development
+	HostArchS390x = HostArchKey.String("s390x")
+	// 32-bit x86
+	// Stability: development
+	HostArchX86 = HostArchKey.String("x86")
+)
+
+// Namespace: http
+const (
+	// HTTPConnectionStateKey is the attribute Key conforming to the
+	// "http.connection.state" semantic conventions. It represents the state of the
+	// HTTP connection in the HTTP connection pool.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "active", "idle"
+	HTTPConnectionStateKey = attribute.Key("http.connection.state")
+
+	// HTTPRequestBodySizeKey is the attribute Key conforming to the
+	// "http.request.body.size" semantic conventions. It represents the size of the
+	// request payload body in bytes. This is the number of bytes transferred
+	// excluding headers and is often, but not always, present as the
+	// [Content-Length] header. For requests using transport encoding, this should
+	// be the compressed size.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length
+	HTTPRequestBodySizeKey = attribute.Key("http.request.body.size")
+
+	// HTTPRequestMethodKey is the attribute Key conforming to the
+	// "http.request.method" semantic conventions. It represents the HTTP request
+	// method.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "GET", "POST", "HEAD"
+	// Note: HTTP request method value SHOULD be "known" to the instrumentation.
+	// By default, this convention defines "known" methods as the ones listed in
+	// [RFC9110]
+	// and the PATCH method defined in [RFC5789].
+	//
+	// If the HTTP request method is not known to instrumentation, it MUST set the
+	// `http.request.method` attribute to `_OTHER`.
+	//
+	// If the HTTP instrumentation could end up converting valid HTTP request
+	// methods to `_OTHER`, then it MUST provide a way to override
+	// the list of known HTTP methods. If this override is done via environment
+	// variable, then the environment variable MUST be named
+	// OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of
+	// case-sensitive known HTTP methods
+	// (this list MUST be a full override of the default known method, it is not a
+	// list of known methods in addition to the defaults).
+	//
+	// HTTP method names are case-sensitive and `http.request.method` attribute
+	// value MUST match a known HTTP method name exactly.
+	// Instrumentations for specific web frameworks that consider HTTP methods to be
+	// case insensitive, SHOULD populate a canonical equivalent.
+	// Tracing instrumentations that do so, MUST also set
+	// `http.request.method_original` to the original value.
+	//
+	// [RFC9110]: https://www.rfc-editor.org/rfc/rfc9110.html#name-methods
+	// [RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html
+	HTTPRequestMethodKey = attribute.Key("http.request.method")
+
+	// HTTPRequestMethodOriginalKey is the attribute Key conforming to the
+	// "http.request.method_original" semantic conventions. It represents the
+	// original HTTP method sent by the client in the request line.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "GeT", "ACL", "foo"
+	HTTPRequestMethodOriginalKey = attribute.Key("http.request.method_original")
+
+	// HTTPRequestResendCountKey is the attribute Key conforming to the
+	// "http.request.resend_count" semantic conventions. It represents the ordinal
+	// number of request resending attempt (for any reason, including redirects).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Note: The resend count SHOULD be updated each time an HTTP request gets
+	// resent by the client, regardless of what was the cause of the resending (e.g.
+	// redirection, authorization failure, 503 Server Unavailable, network issues,
+	// or any other).
+	HTTPRequestResendCountKey = attribute.Key("http.request.resend_count")
+
+	// HTTPRequestSizeKey is the attribute Key conforming to the "http.request.size"
+	// semantic conventions. It represents the total size of the request in bytes.
+	// This should be the total number of bytes sent over the wire, including the
+	// request line (HTTP/1.1), framing (HTTP/2 and HTTP/3), headers, and request
+	// body if any.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	HTTPRequestSizeKey = attribute.Key("http.request.size")
+
+	// HTTPResponseBodySizeKey is the attribute Key conforming to the
+	// "http.response.body.size" semantic conventions. It represents the size of the
+	// response payload body in bytes. This is the number of bytes transferred
+	// excluding headers and is often, but not always, present as the
+	// [Content-Length] header. For requests using transport encoding, this should
+	// be the compressed size.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length
+	HTTPResponseBodySizeKey = attribute.Key("http.response.body.size")
+
+	// HTTPResponseSizeKey is the attribute Key conforming to the
+	// "http.response.size" semantic conventions. It represents the total size of
+	// the response in bytes. This should be the total number of bytes sent over the
+	// wire, including the status line (HTTP/1.1), framing (HTTP/2 and HTTP/3),
+	// headers, and response body and trailers if any.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	HTTPResponseSizeKey = attribute.Key("http.response.size")
+
+	// HTTPResponseStatusCodeKey is the attribute Key conforming to the
+	// "http.response.status_code" semantic conventions. It represents the
+	// [HTTP response status code].
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 200
+	//
+	// [HTTP response status code]: https://tools.ietf.org/html/rfc7231#section-6
+	HTTPResponseStatusCodeKey = attribute.Key("http.response.status_code")
+
+	// HTTPRouteKey is the attribute Key conforming to the "http.route" semantic
+	// conventions. It represents the matched route, that is, the path template in
+	// the format used by the respective server framework.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "/users/:userID?", "{controller}/{action}/{id?}"
+	// Note: MUST NOT be populated when this is not supported by the HTTP server
+	// framework as the route attribute should have low-cardinality and the URI path
+	// can NOT substitute it.
+	// SHOULD include the [application root] if there is one.
+	//
+	// [application root]: /docs/http/http-spans.md#http-server-definitions
+	HTTPRouteKey = attribute.Key("http.route")
+)
+
+// HTTPRequestBodySize returns an attribute KeyValue conforming to the
+// "http.request.body.size" semantic conventions. It represents the size of the
+// request payload body in bytes. This is the number of bytes transferred
+// excluding headers and is often, but not always, present as the
+// [Content-Length] header. For requests using transport encoding, this should be
+// the compressed size.
+//
+// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length
+func HTTPRequestBodySize(val int) attribute.KeyValue {
+	return HTTPRequestBodySizeKey.Int(val)
+}
+
+// HTTPRequestMethodOriginal returns an attribute KeyValue conforming to the
+// "http.request.method_original" semantic conventions. It represents the
+// original HTTP method sent by the client in the request line.
+func HTTPRequestMethodOriginal(val string) attribute.KeyValue {
+	return HTTPRequestMethodOriginalKey.String(val)
+}
+
+// HTTPRequestResendCount returns an attribute KeyValue conforming to the
+// "http.request.resend_count" semantic conventions. It represents the ordinal
+// number of request resending attempt (for any reason, including redirects).
+func HTTPRequestResendCount(val int) attribute.KeyValue {
+	return HTTPRequestResendCountKey.Int(val)
+}
+
+// HTTPRequestSize returns an attribute KeyValue conforming to the
+// "http.request.size" semantic conventions. It represents the total size of the
+// request in bytes. This should be the total number of bytes sent over the wire,
+// including the request line (HTTP/1.1), framing (HTTP/2 and HTTP/3), headers,
+// and request body if any.
+func HTTPRequestSize(val int) attribute.KeyValue {
+	return HTTPRequestSizeKey.Int(val)
+}
+
+// HTTPResponseBodySize returns an attribute KeyValue conforming to the
+// "http.response.body.size" semantic conventions. It represents the size of the
+// response payload body in bytes. This is the number of bytes transferred
+// excluding headers and is often, but not always, present as the
+// [Content-Length] header. For requests using transport encoding, this should be
+// the compressed size.
+//
+// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length
+func HTTPResponseBodySize(val int) attribute.KeyValue {
+	return HTTPResponseBodySizeKey.Int(val)
+}
+
+// HTTPResponseSize returns an attribute KeyValue conforming to the
+// "http.response.size" semantic conventions. It represents the total size of the
+// response in bytes. This should be the total number of bytes sent over the
+// wire, including the status line (HTTP/1.1), framing (HTTP/2 and HTTP/3),
+// headers, and response body and trailers if any.
+func HTTPResponseSize(val int) attribute.KeyValue {
+	return HTTPResponseSizeKey.Int(val)
+}
+
+// HTTPResponseStatusCode returns an attribute KeyValue conforming to the
+// "http.response.status_code" semantic conventions. It represents the
+// [HTTP response status code].
+//
+// [HTTP response status code]: https://tools.ietf.org/html/rfc7231#section-6
+func HTTPResponseStatusCode(val int) attribute.KeyValue {
+	return HTTPResponseStatusCodeKey.Int(val)
+}
+
+// HTTPRoute returns an attribute KeyValue conforming to the "http.route"
+// semantic conventions. It represents the matched route, that is, the path
+// template in the format used by the respective server framework.
+func HTTPRoute(val string) attribute.KeyValue {
+	return HTTPRouteKey.String(val)
+}
+
+// Enum values for http.connection.state
+var (
+	// active state.
+	// Stability: development
+	HTTPConnectionStateActive = HTTPConnectionStateKey.String("active")
+	// idle state.
+	// Stability: development
+	HTTPConnectionStateIdle = HTTPConnectionStateKey.String("idle")
+)
+
+// Enum values for http.request.method
+var (
+	// CONNECT method.
+	// Stability: stable
+	HTTPRequestMethodConnect = HTTPRequestMethodKey.String("CONNECT")
+	// DELETE method.
+	// Stability: stable
+	HTTPRequestMethodDelete = HTTPRequestMethodKey.String("DELETE")
+	// GET method.
+	// Stability: stable
+	HTTPRequestMethodGet = HTTPRequestMethodKey.String("GET")
+	// HEAD method.
+	// Stability: stable
+	HTTPRequestMethodHead = HTTPRequestMethodKey.String("HEAD")
+	// OPTIONS method.
+	// Stability: stable
+	HTTPRequestMethodOptions = HTTPRequestMethodKey.String("OPTIONS")
+	// PATCH method.
+	// Stability: stable
+	HTTPRequestMethodPatch = HTTPRequestMethodKey.String("PATCH")
+	// POST method.
+	// Stability: stable
+	HTTPRequestMethodPost = HTTPRequestMethodKey.String("POST")
+	// PUT method.
+	// Stability: stable
+	HTTPRequestMethodPut = HTTPRequestMethodKey.String("PUT")
+	// TRACE method.
+	// Stability: stable
+	HTTPRequestMethodTrace = HTTPRequestMethodKey.String("TRACE")
+	// Any HTTP method that the instrumentation has no prior knowledge of.
+	// Stability: stable
+	HTTPRequestMethodOther = HTTPRequestMethodKey.String("_OTHER")
+)
+
+// Namespace: hw
+const (
+	// HwIDKey is the attribute Key conforming to the "hw.id" semantic conventions.
+	// It represents an identifier for the hardware component, unique within the
+	// monitored host.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "win32battery_battery_testsysa33_1"
+	HwIDKey = attribute.Key("hw.id")
+
+	// HwNameKey is the attribute Key conforming to the "hw.name" semantic
+	// conventions. It represents an easily-recognizable name for the hardware
+	// component.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "eth0"
+	HwNameKey = attribute.Key("hw.name")
+
+	// HwParentKey is the attribute Key conforming to the "hw.parent" semantic
+	// conventions. It represents the unique identifier of the parent component
+	// (typically the `hw.id` attribute of the enclosure, or disk controller).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "dellStorage_perc_0"
+	HwParentKey = attribute.Key("hw.parent")
+
+	// HwStateKey is the attribute Key conforming to the "hw.state" semantic
+	// conventions. It represents the current state of the component.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	HwStateKey = attribute.Key("hw.state")
+
+	// HwTypeKey is the attribute Key conforming to the "hw.type" semantic
+	// conventions. It represents the type of the component.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: Describes the category of the hardware component for which `hw.state`
+	// is being reported. For example, `hw.type=temperature` along with
+	// `hw.state=degraded` would indicate that the temperature of the hardware
+	// component has been reported as `degraded`.
+	HwTypeKey = attribute.Key("hw.type")
+)
+
+// HwID returns an attribute KeyValue conforming to the "hw.id" semantic
+// conventions. It represents an identifier for the hardware component, unique
+// within the monitored host.
+func HwID(val string) attribute.KeyValue {
+	return HwIDKey.String(val)
+}
+
+// HwName returns an attribute KeyValue conforming to the "hw.name" semantic
+// conventions. It represents an easily-recognizable name for the hardware
+// component.
+func HwName(val string) attribute.KeyValue {
+	return HwNameKey.String(val)
+}
+
+// HwParent returns an attribute KeyValue conforming to the "hw.parent" semantic
+// conventions. It represents the unique identifier of the parent component
+// (typically the `hw.id` attribute of the enclosure, or disk controller).
+func HwParent(val string) attribute.KeyValue {
+	return HwParentKey.String(val)
+}
+
+// Enum values for hw.state
+var (
+	// Ok
+	// Stability: development
+	HwStateOk = HwStateKey.String("ok")
+	// Degraded
+	// Stability: development
+	HwStateDegraded = HwStateKey.String("degraded")
+	// Failed
+	// Stability: development
+	HwStateFailed = HwStateKey.String("failed")
+)
+
+// Enum values for hw.type
+var (
+	// Battery
+	// Stability: development
+	HwTypeBattery = HwTypeKey.String("battery")
+	// CPU
+	// Stability: development
+	HwTypeCPU = HwTypeKey.String("cpu")
+	// Disk controller
+	// Stability: development
+	HwTypeDiskController = HwTypeKey.String("disk_controller")
+	// Enclosure
+	// Stability: development
+	HwTypeEnclosure = HwTypeKey.String("enclosure")
+	// Fan
+	// Stability: development
+	HwTypeFan = HwTypeKey.String("fan")
+	// GPU
+	// Stability: development
+	HwTypeGpu = HwTypeKey.String("gpu")
+	// Logical disk
+	// Stability: development
+	HwTypeLogicalDisk = HwTypeKey.String("logical_disk")
+	// Memory
+	// Stability: development
+	HwTypeMemory = HwTypeKey.String("memory")
+	// Network
+	// Stability: development
+	HwTypeNetwork = HwTypeKey.String("network")
+	// Physical disk
+	// Stability: development
+	HwTypePhysicalDisk = HwTypeKey.String("physical_disk")
+	// Power supply
+	// Stability: development
+	HwTypePowerSupply = HwTypeKey.String("power_supply")
+	// Tape drive
+	// Stability: development
+	HwTypeTapeDrive = HwTypeKey.String("tape_drive")
+	// Temperature
+	// Stability: development
+	HwTypeTemperature = HwTypeKey.String("temperature")
+	// Voltage
+	// Stability: development
+	HwTypeVoltage = HwTypeKey.String("voltage")
+)
+
+// Namespace: ios
+const (
+	// IOSAppStateKey is the attribute Key conforming to the "ios.app.state"
+	// semantic conventions. It represents the this attribute represents the state
+	// of the application.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: The iOS lifecycle states are defined in the
+	// [UIApplicationDelegate documentation], and from which the `OS terminology`
+	// column values are derived.
+	//
+	// [UIApplicationDelegate documentation]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
+	IOSAppStateKey = attribute.Key("ios.app.state")
+)
+
+// Enum values for ios.app.state
+var (
+	// The app has become `active`. Associated with UIKit notification
+	// `applicationDidBecomeActive`.
+	//
+	// Stability: development
+	IOSAppStateActive = IOSAppStateKey.String("active")
+	// The app is now `inactive`. Associated with UIKit notification
+	// `applicationWillResignActive`.
+	//
+	// Stability: development
+	IOSAppStateInactive = IOSAppStateKey.String("inactive")
+	// The app is now in the background. This value is associated with UIKit
+	// notification `applicationDidEnterBackground`.
+	//
+	// Stability: development
+	IOSAppStateBackground = IOSAppStateKey.String("background")
+	// The app is now in the foreground. This value is associated with UIKit
+	// notification `applicationWillEnterForeground`.
+	//
+	// Stability: development
+	IOSAppStateForeground = IOSAppStateKey.String("foreground")
+	// The app is about to terminate. Associated with UIKit notification
+	// `applicationWillTerminate`.
+	//
+	// Stability: development
+	IOSAppStateTerminate = IOSAppStateKey.String("terminate")
+)
+
+// Namespace: k8s
+const (
+	// K8SClusterNameKey is the attribute Key conforming to the "k8s.cluster.name"
+	// semantic conventions. It represents the name of the cluster.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry-cluster"
+	K8SClusterNameKey = attribute.Key("k8s.cluster.name")
+
+	// K8SClusterUIDKey is the attribute Key conforming to the "k8s.cluster.uid"
+	// semantic conventions. It represents a pseudo-ID for the cluster, set to the
+	// UID of the `kube-system` namespace.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d"
+	// Note: K8s doesn't have support for obtaining a cluster ID. If this is ever
+	// added, we will recommend collecting the `k8s.cluster.uid` through the
+	// official APIs. In the meantime, we are able to use the `uid` of the
+	// `kube-system` namespace as a proxy for cluster ID. Read on for the
+	// rationale.
+	//
+	// Every object created in a K8s cluster is assigned a distinct UID. The
+	// `kube-system` namespace is used by Kubernetes itself and will exist
+	// for the lifetime of the cluster. Using the `uid` of the `kube-system`
+	// namespace is a reasonable proxy for the K8s ClusterID as it will only
+	// change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are
+	// UUIDs as standardized by
+	// [ISO/IEC 9834-8 and ITU-T X.667].
+	// Which states:
+	//
+	// > If generated according to one of the mechanisms defined in Rec.
+	// > ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be
+	// > different from all other UUIDs generated before 3603 A.D., or is
+	// > extremely likely to be different (depending on the mechanism chosen).
+	//
+	// Therefore, UIDs between clusters should be extremely unlikely to
+	// conflict.
+	//
+	// [ISO/IEC 9834-8 and ITU-T X.667]: https://www.itu.int/ITU-T/studygroups/com17/oid.html
+	K8SClusterUIDKey = attribute.Key("k8s.cluster.uid")
+
+	// K8SContainerNameKey is the attribute Key conforming to the
+	// "k8s.container.name" semantic conventions. It represents the name of the
+	// Container from Pod specification, must be unique within a Pod. Container
+	// runtime usually uses different globally unique name (`container.name`).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "redis"
+	K8SContainerNameKey = attribute.Key("k8s.container.name")
+
+	// K8SContainerRestartCountKey is the attribute Key conforming to the
+	// "k8s.container.restart_count" semantic conventions. It represents the number
+	// of times the container was restarted. This attribute can be used to identify
+	// a particular container (running or stopped) within a container spec.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	K8SContainerRestartCountKey = attribute.Key("k8s.container.restart_count")
+
+	// K8SContainerStatusLastTerminatedReasonKey is the attribute Key conforming to
+	// the "k8s.container.status.last_terminated_reason" semantic conventions. It
+	// represents the last terminated reason of the Container.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Evicted", "Error"
+	K8SContainerStatusLastTerminatedReasonKey = attribute.Key("k8s.container.status.last_terminated_reason")
+
+	// K8SCronJobNameKey is the attribute Key conforming to the "k8s.cronjob.name"
+	// semantic conventions. It represents the name of the CronJob.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SCronJobNameKey = attribute.Key("k8s.cronjob.name")
+
+	// K8SCronJobUIDKey is the attribute Key conforming to the "k8s.cronjob.uid"
+	// semantic conventions. It represents the UID of the CronJob.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid")
+
+	// K8SDaemonSetNameKey is the attribute Key conforming to the
+	// "k8s.daemonset.name" semantic conventions. It represents the name of the
+	// DaemonSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SDaemonSetNameKey = attribute.Key("k8s.daemonset.name")
+
+	// K8SDaemonSetUIDKey is the attribute Key conforming to the "k8s.daemonset.uid"
+	// semantic conventions. It represents the UID of the DaemonSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SDaemonSetUIDKey = attribute.Key("k8s.daemonset.uid")
+
+	// K8SDeploymentNameKey is the attribute Key conforming to the
+	// "k8s.deployment.name" semantic conventions. It represents the name of the
+	// Deployment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SDeploymentNameKey = attribute.Key("k8s.deployment.name")
+
+	// K8SDeploymentUIDKey is the attribute Key conforming to the
+	// "k8s.deployment.uid" semantic conventions. It represents the UID of the
+	// Deployment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid")
+
+	// K8SHPANameKey is the attribute Key conforming to the "k8s.hpa.name" semantic
+	// conventions. It represents the name of the horizontal pod autoscaler.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SHPANameKey = attribute.Key("k8s.hpa.name")
+
+	// K8SHPAUIDKey is the attribute Key conforming to the "k8s.hpa.uid" semantic
+	// conventions. It represents the UID of the horizontal pod autoscaler.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SHPAUIDKey = attribute.Key("k8s.hpa.uid")
+
+	// K8SJobNameKey is the attribute Key conforming to the "k8s.job.name" semantic
+	// conventions. It represents the name of the Job.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SJobNameKey = attribute.Key("k8s.job.name")
+
+	// K8SJobUIDKey is the attribute Key conforming to the "k8s.job.uid" semantic
+	// conventions. It represents the UID of the Job.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SJobUIDKey = attribute.Key("k8s.job.uid")
+
+	// K8SNamespaceNameKey is the attribute Key conforming to the
+	// "k8s.namespace.name" semantic conventions. It represents the name of the
+	// namespace that the pod is running in.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "default"
+	K8SNamespaceNameKey = attribute.Key("k8s.namespace.name")
+
+	// K8SNamespacePhaseKey is the attribute Key conforming to the
+	// "k8s.namespace.phase" semantic conventions. It represents the phase of the
+	// K8s namespace.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "active", "terminating"
+	// Note: This attribute aligns with the `phase` field of the
+	// [K8s NamespaceStatus]
+	//
+	// [K8s NamespaceStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#namespacestatus-v1-core
+	K8SNamespacePhaseKey = attribute.Key("k8s.namespace.phase")
+
+	// K8SNodeNameKey is the attribute Key conforming to the "k8s.node.name"
+	// semantic conventions. It represents the name of the Node.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "node-1"
+	K8SNodeNameKey = attribute.Key("k8s.node.name")
+
+	// K8SNodeUIDKey is the attribute Key conforming to the "k8s.node.uid" semantic
+	// conventions. It represents the UID of the Node.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2"
+	K8SNodeUIDKey = attribute.Key("k8s.node.uid")
+
+	// K8SPodNameKey is the attribute Key conforming to the "k8s.pod.name" semantic
+	// conventions. It represents the name of the Pod.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry-pod-autoconf"
+	K8SPodNameKey = attribute.Key("k8s.pod.name")
+
+	// K8SPodUIDKey is the attribute Key conforming to the "k8s.pod.uid" semantic
+	// conventions. It represents the UID of the Pod.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SPodUIDKey = attribute.Key("k8s.pod.uid")
+
+	// K8SReplicaSetNameKey is the attribute Key conforming to the
+	// "k8s.replicaset.name" semantic conventions. It represents the name of the
+	// ReplicaSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SReplicaSetNameKey = attribute.Key("k8s.replicaset.name")
+
+	// K8SReplicaSetUIDKey is the attribute Key conforming to the
+	// "k8s.replicaset.uid" semantic conventions. It represents the UID of the
+	// ReplicaSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SReplicaSetUIDKey = attribute.Key("k8s.replicaset.uid")
+
+	// K8SReplicationControllerNameKey is the attribute Key conforming to the
+	// "k8s.replicationcontroller.name" semantic conventions. It represents the name
+	// of the replication controller.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SReplicationControllerNameKey = attribute.Key("k8s.replicationcontroller.name")
+
+	// K8SReplicationControllerUIDKey is the attribute Key conforming to the
+	// "k8s.replicationcontroller.uid" semantic conventions. It represents the UID
+	// of the replication controller.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SReplicationControllerUIDKey = attribute.Key("k8s.replicationcontroller.uid")
+
+	// K8SResourceQuotaNameKey is the attribute Key conforming to the
+	// "k8s.resourcequota.name" semantic conventions. It represents the name of the
+	// resource quota.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SResourceQuotaNameKey = attribute.Key("k8s.resourcequota.name")
+
+	// K8SResourceQuotaUIDKey is the attribute Key conforming to the
+	// "k8s.resourcequota.uid" semantic conventions. It represents the UID of the
+	// resource quota.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SResourceQuotaUIDKey = attribute.Key("k8s.resourcequota.uid")
+
+	// K8SStatefulSetNameKey is the attribute Key conforming to the
+	// "k8s.statefulset.name" semantic conventions. It represents the name of the
+	// StatefulSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "opentelemetry"
+	K8SStatefulSetNameKey = attribute.Key("k8s.statefulset.name")
+
+	// K8SStatefulSetUIDKey is the attribute Key conforming to the
+	// "k8s.statefulset.uid" semantic conventions. It represents the UID of the
+	// StatefulSet.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff"
+	K8SStatefulSetUIDKey = attribute.Key("k8s.statefulset.uid")
+
+	// K8SVolumeNameKey is the attribute Key conforming to the "k8s.volume.name"
+	// semantic conventions. It represents the name of the K8s volume.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "volume0"
+	K8SVolumeNameKey = attribute.Key("k8s.volume.name")
+
+	// K8SVolumeTypeKey is the attribute Key conforming to the "k8s.volume.type"
+	// semantic conventions. It represents the type of the K8s volume.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "emptyDir", "persistentVolumeClaim"
+	K8SVolumeTypeKey = attribute.Key("k8s.volume.type")
+)
+
+// K8SClusterName returns an attribute KeyValue conforming to the
+// "k8s.cluster.name" semantic conventions. It represents the name of the
+// cluster.
+func K8SClusterName(val string) attribute.KeyValue {
+	return K8SClusterNameKey.String(val)
+}
+
+// K8SClusterUID returns an attribute KeyValue conforming to the
+// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for the
+// cluster, set to the UID of the `kube-system` namespace.
+func K8SClusterUID(val string) attribute.KeyValue {
+	return K8SClusterUIDKey.String(val)
+}
+
+// K8SContainerName returns an attribute KeyValue conforming to the
+// "k8s.container.name" semantic conventions. It represents the name of the
+// Container from Pod specification, must be unique within a Pod. Container
+// runtime usually uses different globally unique name (`container.name`).
+func K8SContainerName(val string) attribute.KeyValue {
+	return K8SContainerNameKey.String(val)
+}
+
+// K8SContainerRestartCount returns an attribute KeyValue conforming to the
+// "k8s.container.restart_count" semantic conventions. It represents the number
+// of times the container was restarted. This attribute can be used to identify a
+// particular container (running or stopped) within a container spec.
+func K8SContainerRestartCount(val int) attribute.KeyValue {
+	return K8SContainerRestartCountKey.Int(val)
+}
+
+// K8SContainerStatusLastTerminatedReason returns an attribute KeyValue
+// conforming to the "k8s.container.status.last_terminated_reason" semantic
+// conventions. It represents the last terminated reason of the Container.
+func K8SContainerStatusLastTerminatedReason(val string) attribute.KeyValue {
+	return K8SContainerStatusLastTerminatedReasonKey.String(val)
+}
+
+// K8SCronJobName returns an attribute KeyValue conforming to the
+// "k8s.cronjob.name" semantic conventions. It represents the name of the
+// CronJob.
+func K8SCronJobName(val string) attribute.KeyValue {
+	return K8SCronJobNameKey.String(val)
+}
+
+// K8SCronJobUID returns an attribute KeyValue conforming to the
+// "k8s.cronjob.uid" semantic conventions. It represents the UID of the CronJob.
+func K8SCronJobUID(val string) attribute.KeyValue {
+	return K8SCronJobUIDKey.String(val)
+}
+
+// K8SDaemonSetName returns an attribute KeyValue conforming to the
+// "k8s.daemonset.name" semantic conventions. It represents the name of the
+// DaemonSet.
+func K8SDaemonSetName(val string) attribute.KeyValue {
+	return K8SDaemonSetNameKey.String(val)
+}
+
+// K8SDaemonSetUID returns an attribute KeyValue conforming to the
+// "k8s.daemonset.uid" semantic conventions. It represents the UID of the
+// DaemonSet.
+func K8SDaemonSetUID(val string) attribute.KeyValue {
+	return K8SDaemonSetUIDKey.String(val)
+}
+
+// K8SDeploymentName returns an attribute KeyValue conforming to the
+// "k8s.deployment.name" semantic conventions. It represents the name of the
+// Deployment.
+func K8SDeploymentName(val string) attribute.KeyValue {
+	return K8SDeploymentNameKey.String(val)
+}
+
+// K8SDeploymentUID returns an attribute KeyValue conforming to the
+// "k8s.deployment.uid" semantic conventions. It represents the UID of the
+// Deployment.
+func K8SDeploymentUID(val string) attribute.KeyValue {
+	return K8SDeploymentUIDKey.String(val)
+}
+
+// K8SHPAName returns an attribute KeyValue conforming to the "k8s.hpa.name"
+// semantic conventions. It represents the name of the horizontal pod autoscaler.
+func K8SHPAName(val string) attribute.KeyValue {
+	return K8SHPANameKey.String(val)
+}
+
+// K8SHPAUID returns an attribute KeyValue conforming to the "k8s.hpa.uid"
+// semantic conventions. It represents the UID of the horizontal pod autoscaler.
+func K8SHPAUID(val string) attribute.KeyValue {
+	return K8SHPAUIDKey.String(val)
+}
+
+// K8SJobName returns an attribute KeyValue conforming to the "k8s.job.name"
+// semantic conventions. It represents the name of the Job.
+func K8SJobName(val string) attribute.KeyValue {
+	return K8SJobNameKey.String(val)
+}
+
+// K8SJobUID returns an attribute KeyValue conforming to the "k8s.job.uid"
+// semantic conventions. It represents the UID of the Job.
+func K8SJobUID(val string) attribute.KeyValue {
+	return K8SJobUIDKey.String(val)
+}
+
+// K8SNamespaceName returns an attribute KeyValue conforming to the
+// "k8s.namespace.name" semantic conventions. It represents the name of the
+// namespace that the pod is running in.
+func K8SNamespaceName(val string) attribute.KeyValue {
+	return K8SNamespaceNameKey.String(val)
+}
+
+// K8SNodeName returns an attribute KeyValue conforming to the "k8s.node.name"
+// semantic conventions. It represents the name of the Node.
+func K8SNodeName(val string) attribute.KeyValue {
+	return K8SNodeNameKey.String(val)
+}
+
+// K8SNodeUID returns an attribute KeyValue conforming to the "k8s.node.uid"
+// semantic conventions. It represents the UID of the Node.
+func K8SNodeUID(val string) attribute.KeyValue {
+	return K8SNodeUIDKey.String(val)
+}
+
+// K8SPodName returns an attribute KeyValue conforming to the "k8s.pod.name"
+// semantic conventions. It represents the name of the Pod.
+func K8SPodName(val string) attribute.KeyValue {
+	return K8SPodNameKey.String(val)
+}
+
+// K8SPodUID returns an attribute KeyValue conforming to the "k8s.pod.uid"
+// semantic conventions. It represents the UID of the Pod.
+func K8SPodUID(val string) attribute.KeyValue {
+	return K8SPodUIDKey.String(val)
+}
+
+// K8SReplicaSetName returns an attribute KeyValue conforming to the
+// "k8s.replicaset.name" semantic conventions. It represents the name of the
+// ReplicaSet.
+func K8SReplicaSetName(val string) attribute.KeyValue {
+	return K8SReplicaSetNameKey.String(val)
+}
+
+// K8SReplicaSetUID returns an attribute KeyValue conforming to the
+// "k8s.replicaset.uid" semantic conventions. It represents the UID of the
+// ReplicaSet.
+func K8SReplicaSetUID(val string) attribute.KeyValue {
+	return K8SReplicaSetUIDKey.String(val)
+}
+
+// K8SReplicationControllerName returns an attribute KeyValue conforming to the
+// "k8s.replicationcontroller.name" semantic conventions. It represents the name
+// of the replication controller.
+func K8SReplicationControllerName(val string) attribute.KeyValue {
+	return K8SReplicationControllerNameKey.String(val)
+}
+
+// K8SReplicationControllerUID returns an attribute KeyValue conforming to the
+// "k8s.replicationcontroller.uid" semantic conventions. It represents the UID of
+// the replication controller.
+func K8SReplicationControllerUID(val string) attribute.KeyValue {
+	return K8SReplicationControllerUIDKey.String(val)
+}
+
+// K8SResourceQuotaName returns an attribute KeyValue conforming to the
+// "k8s.resourcequota.name" semantic conventions. It represents the name of the
+// resource quota.
+func K8SResourceQuotaName(val string) attribute.KeyValue {
+	return K8SResourceQuotaNameKey.String(val)
+}
+
+// K8SResourceQuotaUID returns an attribute KeyValue conforming to the
+// "k8s.resourcequota.uid" semantic conventions. It represents the UID of the
+// resource quota.
+func K8SResourceQuotaUID(val string) attribute.KeyValue {
+	return K8SResourceQuotaUIDKey.String(val)
+}
+
+// K8SStatefulSetName returns an attribute KeyValue conforming to the
+// "k8s.statefulset.name" semantic conventions. It represents the name of the
+// StatefulSet.
+func K8SStatefulSetName(val string) attribute.KeyValue {
+	return K8SStatefulSetNameKey.String(val)
+}
+
+// K8SStatefulSetUID returns an attribute KeyValue conforming to the
+// "k8s.statefulset.uid" semantic conventions. It represents the UID of the
+// StatefulSet.
+func K8SStatefulSetUID(val string) attribute.KeyValue {
+	return K8SStatefulSetUIDKey.String(val)
+}
+
+// K8SVolumeName returns an attribute KeyValue conforming to the
+// "k8s.volume.name" semantic conventions. It represents the name of the K8s
+// volume.
+func K8SVolumeName(val string) attribute.KeyValue {
+	return K8SVolumeNameKey.String(val)
+}
+
+// Enum values for k8s.namespace.phase
+var (
+	// Active namespace phase as described by [K8s API]
+	// Stability: development
+	//
+	// [K8s API]: https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase
+	K8SNamespacePhaseActive = K8SNamespacePhaseKey.String("active")
+	// Terminating namespace phase as described by [K8s API]
+	// Stability: development
+	//
+	// [K8s API]: https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase
+	K8SNamespacePhaseTerminating = K8SNamespacePhaseKey.String("terminating")
+)
+
+// Enum values for k8s.volume.type
+var (
+	// A [persistentVolumeClaim] volume
+	// Stability: development
+	//
+	// [persistentVolumeClaim]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim
+	K8SVolumeTypePersistentVolumeClaim = K8SVolumeTypeKey.String("persistentVolumeClaim")
+	// A [configMap] volume
+	// Stability: development
+	//
+	// [configMap]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap
+	K8SVolumeTypeConfigMap = K8SVolumeTypeKey.String("configMap")
+	// A [downwardAPI] volume
+	// Stability: development
+	//
+	// [downwardAPI]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi
+	K8SVolumeTypeDownwardAPI = K8SVolumeTypeKey.String("downwardAPI")
+	// An [emptyDir] volume
+	// Stability: development
+	//
+	// [emptyDir]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir
+	K8SVolumeTypeEmptyDir = K8SVolumeTypeKey.String("emptyDir")
+	// A [secret] volume
+	// Stability: development
+	//
+	// [secret]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#secret
+	K8SVolumeTypeSecret = K8SVolumeTypeKey.String("secret")
+	// A [local] volume
+	// Stability: development
+	//
+	// [local]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#local
+	K8SVolumeTypeLocal = K8SVolumeTypeKey.String("local")
+)
+
+// Namespace: linux
+const (
+	// LinuxMemorySlabStateKey is the attribute Key conforming to the
+	// "linux.memory.slab.state" semantic conventions. It represents the Linux Slab
+	// memory state.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "reclaimable", "unreclaimable"
+	LinuxMemorySlabStateKey = attribute.Key("linux.memory.slab.state")
+)
+
+// Enum values for linux.memory.slab.state
+var (
+	// reclaimable
+	// Stability: development
+	LinuxMemorySlabStateReclaimable = LinuxMemorySlabStateKey.String("reclaimable")
+	// unreclaimable
+	// Stability: development
+	LinuxMemorySlabStateUnreclaimable = LinuxMemorySlabStateKey.String("unreclaimable")
+)
+
+// Namespace: log
+const (
+	// LogFileNameKey is the attribute Key conforming to the "log.file.name"
+	// semantic conventions. It represents the basename of the file.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "audit.log"
+	LogFileNameKey = attribute.Key("log.file.name")
+
+	// LogFileNameResolvedKey is the attribute Key conforming to the
+	// "log.file.name_resolved" semantic conventions. It represents the basename of
+	// the file, with symlinks resolved.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "uuid.log"
+	LogFileNameResolvedKey = attribute.Key("log.file.name_resolved")
+
+	// LogFilePathKey is the attribute Key conforming to the "log.file.path"
+	// semantic conventions. It represents the full path to the file.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/var/log/mysql/audit.log"
+	LogFilePathKey = attribute.Key("log.file.path")
+
+	// LogFilePathResolvedKey is the attribute Key conforming to the
+	// "log.file.path_resolved" semantic conventions. It represents the full path to
+	// the file, with symlinks resolved.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/var/lib/docker/uuid.log"
+	LogFilePathResolvedKey = attribute.Key("log.file.path_resolved")
+
+	// LogIostreamKey is the attribute Key conforming to the "log.iostream" semantic
+	// conventions. It represents the stream associated with the log. See below for
+	// a list of well-known values.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	LogIostreamKey = attribute.Key("log.iostream")
+
+	// LogRecordOriginalKey is the attribute Key conforming to the
+	// "log.record.original" semantic conventions. It represents the complete
+	// original Log Record.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "77 <86>1 2015-08-06T21:58:59.694Z 192.168.2.133 inactive - - -
+	// Something happened", "[INFO] 8/3/24 12:34:56 Something happened"
+	// Note: This value MAY be added when processing a Log Record which was
+	// originally transmitted as a string or equivalent data type AND the Body field
+	// of the Log Record does not contain the same value. (e.g. a syslog or a log
+	// record read from a file.)
+	LogRecordOriginalKey = attribute.Key("log.record.original")
+
+	// LogRecordUIDKey is the attribute Key conforming to the "log.record.uid"
+	// semantic conventions. It represents a unique identifier for the Log Record.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "01ARZ3NDEKTSV4RRFFQ69G5FAV"
+	// Note: If an id is provided, other log records with the same id will be
+	// considered duplicates and can be removed safely. This means, that two
+	// distinguishable log records MUST have different values.
+	// The id MAY be an
+	// [Universally Unique Lexicographically Sortable Identifier (ULID)], but other
+	// identifiers (e.g. UUID) may be used as needed.
+	//
+	// [Universally Unique Lexicographically Sortable Identifier (ULID)]: https://github.com/ulid/spec
+	LogRecordUIDKey = attribute.Key("log.record.uid")
+)
+
+// LogFileName returns an attribute KeyValue conforming to the "log.file.name"
+// semantic conventions. It represents the basename of the file.
+func LogFileName(val string) attribute.KeyValue {
+	return LogFileNameKey.String(val)
+}
+
+// LogFileNameResolved returns an attribute KeyValue conforming to the
+// "log.file.name_resolved" semantic conventions. It represents the basename of
+// the file, with symlinks resolved.
+func LogFileNameResolved(val string) attribute.KeyValue {
+	return LogFileNameResolvedKey.String(val)
+}
+
+// LogFilePath returns an attribute KeyValue conforming to the "log.file.path"
+// semantic conventions. It represents the full path to the file.
+func LogFilePath(val string) attribute.KeyValue {
+	return LogFilePathKey.String(val)
+}
+
+// LogFilePathResolved returns an attribute KeyValue conforming to the
+// "log.file.path_resolved" semantic conventions. It represents the full path to
+// the file, with symlinks resolved.
+func LogFilePathResolved(val string) attribute.KeyValue {
+	return LogFilePathResolvedKey.String(val)
+}
+
+// LogRecordOriginal returns an attribute KeyValue conforming to the
+// "log.record.original" semantic conventions. It represents the complete
+// original Log Record.
+func LogRecordOriginal(val string) attribute.KeyValue {
+	return LogRecordOriginalKey.String(val)
+}
+
+// LogRecordUID returns an attribute KeyValue conforming to the "log.record.uid"
+// semantic conventions. It represents a unique identifier for the Log Record.
+func LogRecordUID(val string) attribute.KeyValue {
+	return LogRecordUIDKey.String(val)
+}
+
+// Enum values for log.iostream
+var (
+	// Logs from stdout stream
+	// Stability: development
+	LogIostreamStdout = LogIostreamKey.String("stdout")
+	// Events from stderr stream
+	// Stability: development
+	LogIostreamStderr = LogIostreamKey.String("stderr")
+)
+
+// Namespace: messaging
+const (
+	// MessagingBatchMessageCountKey is the attribute Key conforming to the
+	// "messaging.batch.message_count" semantic conventions. It represents the
+	// number of messages sent, received, or processed in the scope of the batching
+	// operation.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 0, 1, 2
+	// Note: Instrumentations SHOULD NOT set `messaging.batch.message_count` on
+	// spans that operate with a single message. When a messaging client library
+	// supports both batch and single-message API for the same operation,
+	// instrumentations SHOULD use `messaging.batch.message_count` for batching APIs
+	// and SHOULD NOT use it for single-message APIs.
+	MessagingBatchMessageCountKey = attribute.Key("messaging.batch.message_count")
+
+	// MessagingClientIDKey is the attribute Key conforming to the
+	// "messaging.client.id" semantic conventions. It represents a unique identifier
+	// for the client that consumes or produces a message.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "client-5", "myhost@8742@s8083jm"
+	MessagingClientIDKey = attribute.Key("messaging.client.id")
+
+	// MessagingConsumerGroupNameKey is the attribute Key conforming to the
+	// "messaging.consumer.group.name" semantic conventions. It represents the name
+	// of the consumer group with which a consumer is associated.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-group", "indexer"
+	// Note: Semantic conventions for individual messaging systems SHOULD document
+	// whether `messaging.consumer.group.name` is applicable and what it means in
+	// the context of that system.
+	MessagingConsumerGroupNameKey = attribute.Key("messaging.consumer.group.name")
+
+	// MessagingDestinationAnonymousKey is the attribute Key conforming to the
+	// "messaging.destination.anonymous" semantic conventions. It represents a
+	// boolean that is true if the message destination is anonymous (could be
+	// unnamed or have auto-generated name).
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	MessagingDestinationAnonymousKey = attribute.Key("messaging.destination.anonymous")
+
+	// MessagingDestinationNameKey is the attribute Key conforming to the
+	// "messaging.destination.name" semantic conventions. It represents the message
+	// destination name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "MyQueue", "MyTopic"
+	// Note: Destination name SHOULD uniquely identify a specific queue, topic or
+	// other entity within the broker. If
+	// the broker doesn't have such notion, the destination name SHOULD uniquely
+	// identify the broker.
+	MessagingDestinationNameKey = attribute.Key("messaging.destination.name")
+
+	// MessagingDestinationPartitionIDKey is the attribute Key conforming to the
+	// "messaging.destination.partition.id" semantic conventions. It represents the
+	// identifier of the partition messages are sent to or received from, unique
+	// within the `messaging.destination.name`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1
+	MessagingDestinationPartitionIDKey = attribute.Key("messaging.destination.partition.id")
+
+	// MessagingDestinationSubscriptionNameKey is the attribute Key conforming to
+	// the "messaging.destination.subscription.name" semantic conventions. It
+	// represents the name of the destination subscription from which a message is
+	// consumed.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "subscription-a"
+	// Note: Semantic conventions for individual messaging systems SHOULD document
+	// whether `messaging.destination.subscription.name` is applicable and what it
+	// means in the context of that system.
+	MessagingDestinationSubscriptionNameKey = attribute.Key("messaging.destination.subscription.name")
+
+	// MessagingDestinationTemplateKey is the attribute Key conforming to the
+	// "messaging.destination.template" semantic conventions. It represents the low
+	// cardinality representation of the messaging destination name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/customers/{customerId}"
+	// Note: Destination names could be constructed from templates. An example would
+	// be a destination name involving a user name or product id. Although the
+	// destination name in this case is of high cardinality, the underlying template
+	// is of low cardinality and can be effectively used for grouping and
+	// aggregation.
+	MessagingDestinationTemplateKey = attribute.Key("messaging.destination.template")
+
+	// MessagingDestinationTemporaryKey is the attribute Key conforming to the
+	// "messaging.destination.temporary" semantic conventions. It represents a
+	// boolean that is true if the message destination is temporary and might not
+	// exist anymore after messages are processed.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	MessagingDestinationTemporaryKey = attribute.Key("messaging.destination.temporary")
+
+	// MessagingEventHubsMessageEnqueuedTimeKey is the attribute Key conforming to
+	// the "messaging.eventhubs.message.enqueued_time" semantic conventions. It
+	// represents the UTC epoch seconds at which the message has been accepted and
+	// stored in the entity.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingEventHubsMessageEnqueuedTimeKey = attribute.Key("messaging.eventhubs.message.enqueued_time")
+
+	// MessagingGCPPubSubMessageAckDeadlineKey is the attribute Key conforming to
+	// the "messaging.gcp_pubsub.message.ack_deadline" semantic conventions. It
+	// represents the ack deadline in seconds set for the modify ack deadline
+	// request.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingGCPPubSubMessageAckDeadlineKey = attribute.Key("messaging.gcp_pubsub.message.ack_deadline")
+
+	// MessagingGCPPubSubMessageAckIDKey is the attribute Key conforming to the
+	// "messaging.gcp_pubsub.message.ack_id" semantic conventions. It represents the
+	// ack id for a given message.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: ack_id
+	MessagingGCPPubSubMessageAckIDKey = attribute.Key("messaging.gcp_pubsub.message.ack_id")
+
+	// MessagingGCPPubSubMessageDeliveryAttemptKey is the attribute Key conforming
+	// to the "messaging.gcp_pubsub.message.delivery_attempt" semantic conventions.
+	// It represents the delivery attempt for a given message.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingGCPPubSubMessageDeliveryAttemptKey = attribute.Key("messaging.gcp_pubsub.message.delivery_attempt")
+
+	// MessagingGCPPubSubMessageOrderingKeyKey is the attribute Key conforming to
+	// the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. It
+	// represents the ordering key for a given message. If the attribute is not
+	// present, the message does not have an ordering key.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: ordering_key
+	MessagingGCPPubSubMessageOrderingKeyKey = attribute.Key("messaging.gcp_pubsub.message.ordering_key")
+
+	// MessagingKafkaMessageKeyKey is the attribute Key conforming to the
+	// "messaging.kafka.message.key" semantic conventions. It represents the message
+	// keys in Kafka are used for grouping alike messages to ensure they're
+	// processed on the same partition. They differ from `messaging.message.id` in
+	// that they're not unique. If the key is `null`, the attribute MUST NOT be set.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: myKey
+	// Note: If the key type is not string, it's string representation has to be
+	// supplied for the attribute. If the key has no unambiguous, canonical string
+	// form, don't include its value.
+	MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message.key")
+
+	// MessagingKafkaMessageTombstoneKey is the attribute Key conforming to the
+	// "messaging.kafka.message.tombstone" semantic conventions. It represents a
+	// boolean that is true if the message is a tombstone.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	MessagingKafkaMessageTombstoneKey = attribute.Key("messaging.kafka.message.tombstone")
+
+	// MessagingKafkaOffsetKey is the attribute Key conforming to the
+	// "messaging.kafka.offset" semantic conventions. It represents the offset of a
+	// record in the corresponding Kafka partition.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingKafkaOffsetKey = attribute.Key("messaging.kafka.offset")
+
+	// MessagingMessageBodySizeKey is the attribute Key conforming to the
+	// "messaging.message.body.size" semantic conventions. It represents the size of
+	// the message body in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Note: This can refer to both the compressed or uncompressed body size. If
+	// both sizes are known, the uncompressed
+	// body size should be used.
+	MessagingMessageBodySizeKey = attribute.Key("messaging.message.body.size")
+
+	// MessagingMessageConversationIDKey is the attribute Key conforming to the
+	// "messaging.message.conversation_id" semantic conventions. It represents the
+	// conversation ID identifying the conversation to which the message belongs,
+	// represented as a string. Sometimes called "Correlation ID".
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: MyConversationId
+	MessagingMessageConversationIDKey = attribute.Key("messaging.message.conversation_id")
+
+	// MessagingMessageEnvelopeSizeKey is the attribute Key conforming to the
+	// "messaging.message.envelope.size" semantic conventions. It represents the
+	// size of the message body and metadata in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Note: This can refer to both the compressed or uncompressed size. If both
+	// sizes are known, the uncompressed
+	// size should be used.
+	MessagingMessageEnvelopeSizeKey = attribute.Key("messaging.message.envelope.size")
+
+	// MessagingMessageIDKey is the attribute Key conforming to the
+	// "messaging.message.id" semantic conventions. It represents a value used by
+	// the messaging system as an identifier for the message, represented as a
+	// string.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 452a7c7c7c7048c2f887f61572b18fc2
+	MessagingMessageIDKey = attribute.Key("messaging.message.id")
+
+	// MessagingOperationNameKey is the attribute Key conforming to the
+	// "messaging.operation.name" semantic conventions. It represents the
+	// system-specific name of the messaging operation.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "ack", "nack", "send"
+	MessagingOperationNameKey = attribute.Key("messaging.operation.name")
+
+	// MessagingOperationTypeKey is the attribute Key conforming to the
+	// "messaging.operation.type" semantic conventions. It represents a string
+	// identifying the type of the messaging operation.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: If a custom value is used, it MUST be of low cardinality.
+	MessagingOperationTypeKey = attribute.Key("messaging.operation.type")
+
+	// MessagingRabbitMQDestinationRoutingKeyKey is the attribute Key conforming to
+	// the "messaging.rabbitmq.destination.routing_key" semantic conventions. It
+	// represents the rabbitMQ message routing key.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: myKey
+	MessagingRabbitMQDestinationRoutingKeyKey = attribute.Key("messaging.rabbitmq.destination.routing_key")
+
+	// MessagingRabbitMQMessageDeliveryTagKey is the attribute Key conforming to the
+	// "messaging.rabbitmq.message.delivery_tag" semantic conventions. It represents
+	// the rabbitMQ message delivery tag.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingRabbitMQMessageDeliveryTagKey = attribute.Key("messaging.rabbitmq.message.delivery_tag")
+
+	// MessagingRocketMQConsumptionModelKey is the attribute Key conforming to the
+	// "messaging.rocketmq.consumption_model" semantic conventions. It represents
+	// the model of message consumption. This only applies to consumer spans.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	MessagingRocketMQConsumptionModelKey = attribute.Key("messaging.rocketmq.consumption_model")
+
+	// MessagingRocketMQMessageDelayTimeLevelKey is the attribute Key conforming to
+	// the "messaging.rocketmq.message.delay_time_level" semantic conventions. It
+	// represents the delay time level for delay message, which determines the
+	// message delay time.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingRocketMQMessageDelayTimeLevelKey = attribute.Key("messaging.rocketmq.message.delay_time_level")
+
+	// MessagingRocketMQMessageDeliveryTimestampKey is the attribute Key conforming
+	// to the "messaging.rocketmq.message.delivery_timestamp" semantic conventions.
+	// It represents the timestamp in milliseconds that the delay message is
+	// expected to be delivered to consumer.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingRocketMQMessageDeliveryTimestampKey = attribute.Key("messaging.rocketmq.message.delivery_timestamp")
+
+	// MessagingRocketMQMessageGroupKey is the attribute Key conforming to the
+	// "messaging.rocketmq.message.group" semantic conventions. It represents the it
+	// is essential for FIFO message. Messages that belong to the same message group
+	// are always processed one by one within the same consumer group.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: myMessageGroup
+	MessagingRocketMQMessageGroupKey = attribute.Key("messaging.rocketmq.message.group")
+
+	// MessagingRocketMQMessageKeysKey is the attribute Key conforming to the
+	// "messaging.rocketmq.message.keys" semantic conventions. It represents the
+	// key(s) of message, another way to mark message besides message id.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "keyA", "keyB"
+	MessagingRocketMQMessageKeysKey = attribute.Key("messaging.rocketmq.message.keys")
+
+	// MessagingRocketMQMessageTagKey is the attribute Key conforming to the
+	// "messaging.rocketmq.message.tag" semantic conventions. It represents the
+	// secondary classifier of message besides topic.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: tagA
+	MessagingRocketMQMessageTagKey = attribute.Key("messaging.rocketmq.message.tag")
+
+	// MessagingRocketMQMessageTypeKey is the attribute Key conforming to the
+	// "messaging.rocketmq.message.type" semantic conventions. It represents the
+	// type of message.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	MessagingRocketMQMessageTypeKey = attribute.Key("messaging.rocketmq.message.type")
+
+	// MessagingRocketMQNamespaceKey is the attribute Key conforming to the
+	// "messaging.rocketmq.namespace" semantic conventions. It represents the
+	// namespace of RocketMQ resources, resources in different namespaces are
+	// individual.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: myNamespace
+	MessagingRocketMQNamespaceKey = attribute.Key("messaging.rocketmq.namespace")
+
+	// MessagingServiceBusDispositionStatusKey is the attribute Key conforming to
+	// the "messaging.servicebus.disposition_status" semantic conventions. It
+	// represents the describes the [settlement type].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [settlement type]: https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock
+	MessagingServiceBusDispositionStatusKey = attribute.Key("messaging.servicebus.disposition_status")
+
+	// MessagingServiceBusMessageDeliveryCountKey is the attribute Key conforming to
+	// the "messaging.servicebus.message.delivery_count" semantic conventions. It
+	// represents the number of deliveries that have been attempted for this
+	// message.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingServiceBusMessageDeliveryCountKey = attribute.Key("messaging.servicebus.message.delivery_count")
+
+	// MessagingServiceBusMessageEnqueuedTimeKey is the attribute Key conforming to
+	// the "messaging.servicebus.message.enqueued_time" semantic conventions. It
+	// represents the UTC epoch seconds at which the message has been accepted and
+	// stored in the entity.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	MessagingServiceBusMessageEnqueuedTimeKey = attribute.Key("messaging.servicebus.message.enqueued_time")
+
+	// MessagingSystemKey is the attribute Key conforming to the "messaging.system"
+	// semantic conventions. It represents the messaging system as identified by the
+	// client instrumentation.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: The actual messaging system may differ from the one known by the
+	// client. For example, when using Kafka client libraries to communicate with
+	// Azure Event Hubs, the `messaging.system` is set to `kafka` based on the
+	// instrumentation's best knowledge.
+	MessagingSystemKey = attribute.Key("messaging.system")
+)
+
+// MessagingBatchMessageCount returns an attribute KeyValue conforming to the
+// "messaging.batch.message_count" semantic conventions. It represents the number
+// of messages sent, received, or processed in the scope of the batching
+// operation.
+func MessagingBatchMessageCount(val int) attribute.KeyValue {
+	return MessagingBatchMessageCountKey.Int(val)
+}
+
+// MessagingClientID returns an attribute KeyValue conforming to the
+// "messaging.client.id" semantic conventions. It represents a unique identifier
+// for the client that consumes or produces a message.
+func MessagingClientID(val string) attribute.KeyValue {
+	return MessagingClientIDKey.String(val)
+}
+
+// MessagingConsumerGroupName returns an attribute KeyValue conforming to the
+// "messaging.consumer.group.name" semantic conventions. It represents the name
+// of the consumer group with which a consumer is associated.
+func MessagingConsumerGroupName(val string) attribute.KeyValue {
+	return MessagingConsumerGroupNameKey.String(val)
+}
+
+// MessagingDestinationAnonymous returns an attribute KeyValue conforming to the
+// "messaging.destination.anonymous" semantic conventions. It represents a
+// boolean that is true if the message destination is anonymous (could be unnamed
+// or have auto-generated name).
+func MessagingDestinationAnonymous(val bool) attribute.KeyValue {
+	return MessagingDestinationAnonymousKey.Bool(val)
+}
+
+// MessagingDestinationName returns an attribute KeyValue conforming to the
+// "messaging.destination.name" semantic conventions. It represents the message
+// destination name.
+func MessagingDestinationName(val string) attribute.KeyValue {
+	return MessagingDestinationNameKey.String(val)
+}
+
+// MessagingDestinationPartitionID returns an attribute KeyValue conforming to
+// the "messaging.destination.partition.id" semantic conventions. It represents
+// the identifier of the partition messages are sent to or received from, unique
+// within the `messaging.destination.name`.
+func MessagingDestinationPartitionID(val string) attribute.KeyValue {
+	return MessagingDestinationPartitionIDKey.String(val)
+}
+
+// MessagingDestinationSubscriptionName returns an attribute KeyValue conforming
+// to the "messaging.destination.subscription.name" semantic conventions. It
+// represents the name of the destination subscription from which a message is
+// consumed.
+func MessagingDestinationSubscriptionName(val string) attribute.KeyValue {
+	return MessagingDestinationSubscriptionNameKey.String(val)
+}
+
+// MessagingDestinationTemplate returns an attribute KeyValue conforming to the
+// "messaging.destination.template" semantic conventions. It represents the low
+// cardinality representation of the messaging destination name.
+func MessagingDestinationTemplate(val string) attribute.KeyValue {
+	return MessagingDestinationTemplateKey.String(val)
+}
+
+// MessagingDestinationTemporary returns an attribute KeyValue conforming to the
+// "messaging.destination.temporary" semantic conventions. It represents a
+// boolean that is true if the message destination is temporary and might not
+// exist anymore after messages are processed.
+func MessagingDestinationTemporary(val bool) attribute.KeyValue {
+	return MessagingDestinationTemporaryKey.Bool(val)
+}
+
+// MessagingEventHubsMessageEnqueuedTime returns an attribute KeyValue conforming
+// to the "messaging.eventhubs.message.enqueued_time" semantic conventions. It
+// represents the UTC epoch seconds at which the message has been accepted and
+// stored in the entity.
+func MessagingEventHubsMessageEnqueuedTime(val int) attribute.KeyValue {
+	return MessagingEventHubsMessageEnqueuedTimeKey.Int(val)
+}
+
+// MessagingGCPPubSubMessageAckDeadline returns an attribute KeyValue conforming
+// to the "messaging.gcp_pubsub.message.ack_deadline" semantic conventions. It
+// represents the ack deadline in seconds set for the modify ack deadline
+// request.
+func MessagingGCPPubSubMessageAckDeadline(val int) attribute.KeyValue {
+	return MessagingGCPPubSubMessageAckDeadlineKey.Int(val)
+}
+
+// MessagingGCPPubSubMessageAckID returns an attribute KeyValue conforming to the
+// "messaging.gcp_pubsub.message.ack_id" semantic conventions. It represents the
+// ack id for a given message.
+func MessagingGCPPubSubMessageAckID(val string) attribute.KeyValue {
+	return MessagingGCPPubSubMessageAckIDKey.String(val)
+}
+
+// MessagingGCPPubSubMessageDeliveryAttempt returns an attribute KeyValue
+// conforming to the "messaging.gcp_pubsub.message.delivery_attempt" semantic
+// conventions. It represents the delivery attempt for a given message.
+func MessagingGCPPubSubMessageDeliveryAttempt(val int) attribute.KeyValue {
+	return MessagingGCPPubSubMessageDeliveryAttemptKey.Int(val)
+}
+
+// MessagingGCPPubSubMessageOrderingKey returns an attribute KeyValue conforming
+// to the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. It
+// represents the ordering key for a given message. If the attribute is not
+// present, the message does not have an ordering key.
+func MessagingGCPPubSubMessageOrderingKey(val string) attribute.KeyValue {
+	return MessagingGCPPubSubMessageOrderingKeyKey.String(val)
+}
+
+// MessagingKafkaMessageKey returns an attribute KeyValue conforming to the
+// "messaging.kafka.message.key" semantic conventions. It represents the message
+// keys in Kafka are used for grouping alike messages to ensure they're processed
+// on the same partition. They differ from `messaging.message.id` in that they're
+// not unique. If the key is `null`, the attribute MUST NOT be set.
+func MessagingKafkaMessageKey(val string) attribute.KeyValue {
+	return MessagingKafkaMessageKeyKey.String(val)
+}
+
+// MessagingKafkaMessageTombstone returns an attribute KeyValue conforming to the
+// "messaging.kafka.message.tombstone" semantic conventions. It represents a
+// boolean that is true if the message is a tombstone.
+func MessagingKafkaMessageTombstone(val bool) attribute.KeyValue {
+	return MessagingKafkaMessageTombstoneKey.Bool(val)
+}
+
+// MessagingKafkaOffset returns an attribute KeyValue conforming to the
+// "messaging.kafka.offset" semantic conventions. It represents the offset of a
+// record in the corresponding Kafka partition.
+func MessagingKafkaOffset(val int) attribute.KeyValue {
+	return MessagingKafkaOffsetKey.Int(val)
+}
+
+// MessagingMessageBodySize returns an attribute KeyValue conforming to the
+// "messaging.message.body.size" semantic conventions. It represents the size of
+// the message body in bytes.
+func MessagingMessageBodySize(val int) attribute.KeyValue {
+	return MessagingMessageBodySizeKey.Int(val)
+}
+
+// MessagingMessageConversationID returns an attribute KeyValue conforming to the
+// "messaging.message.conversation_id" semantic conventions. It represents the
+// conversation ID identifying the conversation to which the message belongs,
+// represented as a string. Sometimes called "Correlation ID".
+func MessagingMessageConversationID(val string) attribute.KeyValue {
+	return MessagingMessageConversationIDKey.String(val)
+}
+
+// MessagingMessageEnvelopeSize returns an attribute KeyValue conforming to the
+// "messaging.message.envelope.size" semantic conventions. It represents the size
+// of the message body and metadata in bytes.
+func MessagingMessageEnvelopeSize(val int) attribute.KeyValue {
+	return MessagingMessageEnvelopeSizeKey.Int(val)
+}
+
+// MessagingMessageID returns an attribute KeyValue conforming to the
+// "messaging.message.id" semantic conventions. It represents a value used by the
+// messaging system as an identifier for the message, represented as a string.
+func MessagingMessageID(val string) attribute.KeyValue {
+	return MessagingMessageIDKey.String(val)
+}
+
+// MessagingOperationName returns an attribute KeyValue conforming to the
+// "messaging.operation.name" semantic conventions. It represents the
+// system-specific name of the messaging operation.
+func MessagingOperationName(val string) attribute.KeyValue {
+	return MessagingOperationNameKey.String(val)
+}
+
+// MessagingRabbitMQDestinationRoutingKey returns an attribute KeyValue
+// conforming to the "messaging.rabbitmq.destination.routing_key" semantic
+// conventions. It represents the rabbitMQ message routing key.
+func MessagingRabbitMQDestinationRoutingKey(val string) attribute.KeyValue {
+	return MessagingRabbitMQDestinationRoutingKeyKey.String(val)
+}
+
+// MessagingRabbitMQMessageDeliveryTag returns an attribute KeyValue conforming
+// to the "messaging.rabbitmq.message.delivery_tag" semantic conventions. It
+// represents the rabbitMQ message delivery tag.
+func MessagingRabbitMQMessageDeliveryTag(val int) attribute.KeyValue {
+	return MessagingRabbitMQMessageDeliveryTagKey.Int(val)
+}
+
+// MessagingRocketMQMessageDelayTimeLevel returns an attribute KeyValue
+// conforming to the "messaging.rocketmq.message.delay_time_level" semantic
+// conventions. It represents the delay time level for delay message, which
+// determines the message delay time.
+func MessagingRocketMQMessageDelayTimeLevel(val int) attribute.KeyValue {
+	return MessagingRocketMQMessageDelayTimeLevelKey.Int(val)
+}
+
+// MessagingRocketMQMessageDeliveryTimestamp returns an attribute KeyValue
+// conforming to the "messaging.rocketmq.message.delivery_timestamp" semantic
+// conventions. It represents the timestamp in milliseconds that the delay
+// message is expected to be delivered to consumer.
+func MessagingRocketMQMessageDeliveryTimestamp(val int) attribute.KeyValue {
+	return MessagingRocketMQMessageDeliveryTimestampKey.Int(val)
+}
+
+// MessagingRocketMQMessageGroup returns an attribute KeyValue conforming to the
+// "messaging.rocketmq.message.group" semantic conventions. It represents the it
+// is essential for FIFO message. Messages that belong to the same message group
+// are always processed one by one within the same consumer group.
+func MessagingRocketMQMessageGroup(val string) attribute.KeyValue {
+	return MessagingRocketMQMessageGroupKey.String(val)
+}
+
+// MessagingRocketMQMessageKeys returns an attribute KeyValue conforming to the
+// "messaging.rocketmq.message.keys" semantic conventions. It represents the
+// key(s) of message, another way to mark message besides message id.
+func MessagingRocketMQMessageKeys(val ...string) attribute.KeyValue {
+	return MessagingRocketMQMessageKeysKey.StringSlice(val)
+}
+
+// MessagingRocketMQMessageTag returns an attribute KeyValue conforming to the
+// "messaging.rocketmq.message.tag" semantic conventions. It represents the
+// secondary classifier of message besides topic.
+func MessagingRocketMQMessageTag(val string) attribute.KeyValue {
+	return MessagingRocketMQMessageTagKey.String(val)
+}
+
+// MessagingRocketMQNamespace returns an attribute KeyValue conforming to the
+// "messaging.rocketmq.namespace" semantic conventions. It represents the
+// namespace of RocketMQ resources, resources in different namespaces are
+// individual.
+func MessagingRocketMQNamespace(val string) attribute.KeyValue {
+	return MessagingRocketMQNamespaceKey.String(val)
+}
+
+// MessagingServiceBusMessageDeliveryCount returns an attribute KeyValue
+// conforming to the "messaging.servicebus.message.delivery_count" semantic
+// conventions. It represents the number of deliveries that have been attempted
+// for this message.
+func MessagingServiceBusMessageDeliveryCount(val int) attribute.KeyValue {
+	return MessagingServiceBusMessageDeliveryCountKey.Int(val)
+}
+
+// MessagingServiceBusMessageEnqueuedTime returns an attribute KeyValue
+// conforming to the "messaging.servicebus.message.enqueued_time" semantic
+// conventions. It represents the UTC epoch seconds at which the message has been
+// accepted and stored in the entity.
+func MessagingServiceBusMessageEnqueuedTime(val int) attribute.KeyValue {
+	return MessagingServiceBusMessageEnqueuedTimeKey.Int(val)
+}
+
+// Enum values for messaging.operation.type
+var (
+	// A message is created. "Create" spans always refer to a single message and are
+	// used to provide a unique creation context for messages in batch sending
+	// scenarios.
+	//
+	// Stability: development
+	MessagingOperationTypeCreate = MessagingOperationTypeKey.String("create")
+	// One or more messages are provided for sending to an intermediary. If a single
+	// message is sent, the context of the "Send" span can be used as the creation
+	// context and no "Create" span needs to be created.
+	//
+	// Stability: development
+	MessagingOperationTypeSend = MessagingOperationTypeKey.String("send")
+	// One or more messages are requested by a consumer. This operation refers to
+	// pull-based scenarios, where consumers explicitly call methods of messaging
+	// SDKs to receive messages.
+	//
+	// Stability: development
+	MessagingOperationTypeReceive = MessagingOperationTypeKey.String("receive")
+	// One or more messages are processed by a consumer.
+	//
+	// Stability: development
+	MessagingOperationTypeProcess = MessagingOperationTypeKey.String("process")
+	// One or more messages are settled.
+	//
+	// Stability: development
+	MessagingOperationTypeSettle = MessagingOperationTypeKey.String("settle")
+	// Deprecated: Replaced by `process`.
+	MessagingOperationTypeDeliver = MessagingOperationTypeKey.String("deliver")
+	// Deprecated: Replaced by `send`.
+	MessagingOperationTypePublish = MessagingOperationTypeKey.String("publish")
+)
+
+// Enum values for messaging.rocketmq.consumption_model
+var (
+	// Clustering consumption model
+	// Stability: development
+	MessagingRocketMQConsumptionModelClustering = MessagingRocketMQConsumptionModelKey.String("clustering")
+	// Broadcasting consumption model
+	// Stability: development
+	MessagingRocketMQConsumptionModelBroadcasting = MessagingRocketMQConsumptionModelKey.String("broadcasting")
+)
+
+// Enum values for messaging.rocketmq.message.type
+var (
+	// Normal message
+	// Stability: development
+	MessagingRocketMQMessageTypeNormal = MessagingRocketMQMessageTypeKey.String("normal")
+	// FIFO message
+	// Stability: development
+	MessagingRocketMQMessageTypeFifo = MessagingRocketMQMessageTypeKey.String("fifo")
+	// Delay message
+	// Stability: development
+	MessagingRocketMQMessageTypeDelay = MessagingRocketMQMessageTypeKey.String("delay")
+	// Transaction message
+	// Stability: development
+	MessagingRocketMQMessageTypeTransaction = MessagingRocketMQMessageTypeKey.String("transaction")
+)
+
+// Enum values for messaging.servicebus.disposition_status
+var (
+	// Message is completed
+	// Stability: development
+	MessagingServiceBusDispositionStatusComplete = MessagingServiceBusDispositionStatusKey.String("complete")
+	// Message is abandoned
+	// Stability: development
+	MessagingServiceBusDispositionStatusAbandon = MessagingServiceBusDispositionStatusKey.String("abandon")
+	// Message is sent to dead letter queue
+	// Stability: development
+	MessagingServiceBusDispositionStatusDeadLetter = MessagingServiceBusDispositionStatusKey.String("dead_letter")
+	// Message is deferred
+	// Stability: development
+	MessagingServiceBusDispositionStatusDefer = MessagingServiceBusDispositionStatusKey.String("defer")
+)
+
+// Enum values for messaging.system
+var (
+	// Apache ActiveMQ
+	// Stability: development
+	MessagingSystemActiveMQ = MessagingSystemKey.String("activemq")
+	// Amazon Simple Queue Service (SQS)
+	// Stability: development
+	MessagingSystemAWSSQS = MessagingSystemKey.String("aws_sqs")
+	// Azure Event Grid
+	// Stability: development
+	MessagingSystemEventGrid = MessagingSystemKey.String("eventgrid")
+	// Azure Event Hubs
+	// Stability: development
+	MessagingSystemEventHubs = MessagingSystemKey.String("eventhubs")
+	// Azure Service Bus
+	// Stability: development
+	MessagingSystemServiceBus = MessagingSystemKey.String("servicebus")
+	// Google Cloud Pub/Sub
+	// Stability: development
+	MessagingSystemGCPPubSub = MessagingSystemKey.String("gcp_pubsub")
+	// Java Message Service
+	// Stability: development
+	MessagingSystemJMS = MessagingSystemKey.String("jms")
+	// Apache Kafka
+	// Stability: development
+	MessagingSystemKafka = MessagingSystemKey.String("kafka")
+	// RabbitMQ
+	// Stability: development
+	MessagingSystemRabbitMQ = MessagingSystemKey.String("rabbitmq")
+	// Apache RocketMQ
+	// Stability: development
+	MessagingSystemRocketMQ = MessagingSystemKey.String("rocketmq")
+	// Apache Pulsar
+	// Stability: development
+	MessagingSystemPulsar = MessagingSystemKey.String("pulsar")
+)
+
+// Namespace: network
+const (
+	// NetworkCarrierICCKey is the attribute Key conforming to the
+	// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1
+	// alpha-2 2-character country code associated with the mobile carrier network.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: DE
+	NetworkCarrierICCKey = attribute.Key("network.carrier.icc")
+
+	// NetworkCarrierMCCKey is the attribute Key conforming to the
+	// "network.carrier.mcc" semantic conventions. It represents the mobile carrier
+	// country code.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 310
+	NetworkCarrierMCCKey = attribute.Key("network.carrier.mcc")
+
+	// NetworkCarrierMNCKey is the attribute Key conforming to the
+	// "network.carrier.mnc" semantic conventions. It represents the mobile carrier
+	// network code.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 001
+	NetworkCarrierMNCKey = attribute.Key("network.carrier.mnc")
+
+	// NetworkCarrierNameKey is the attribute Key conforming to the
+	// "network.carrier.name" semantic conventions. It represents the name of the
+	// mobile carrier.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: sprint
+	NetworkCarrierNameKey = attribute.Key("network.carrier.name")
+
+	// NetworkConnectionStateKey is the attribute Key conforming to the
+	// "network.connection.state" semantic conventions. It represents the state of
+	// network connection.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "close_wait"
+	// Note: Connection states are defined as part of the [rfc9293]
+	//
+	// [rfc9293]: https://datatracker.ietf.org/doc/html/rfc9293#section-3.3.2
+	NetworkConnectionStateKey = attribute.Key("network.connection.state")
+
+	// NetworkConnectionSubtypeKey is the attribute Key conforming to the
+	// "network.connection.subtype" semantic conventions. It represents the this
+	// describes more details regarding the connection.type. It may be the type of
+	// cell technology connection, but it could be used for describing details about
+	// a wifi connection.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: LTE
+	NetworkConnectionSubtypeKey = attribute.Key("network.connection.subtype")
+
+	// NetworkConnectionTypeKey is the attribute Key conforming to the
+	// "network.connection.type" semantic conventions. It represents the internet
+	// connection type.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: wifi
+	NetworkConnectionTypeKey = attribute.Key("network.connection.type")
+
+	// NetworkInterfaceNameKey is the attribute Key conforming to the
+	// "network.interface.name" semantic conventions. It represents the network
+	// interface name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "lo", "eth0"
+	NetworkInterfaceNameKey = attribute.Key("network.interface.name")
+
+	// NetworkIODirectionKey is the attribute Key conforming to the
+	// "network.io.direction" semantic conventions. It represents the network IO
+	// operation direction.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "transmit"
+	NetworkIODirectionKey = attribute.Key("network.io.direction")
+
+	// NetworkLocalAddressKey is the attribute Key conforming to the
+	// "network.local.address" semantic conventions. It represents the local address
+	// of the network connection - IP address or Unix domain socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "10.1.2.80", "/tmp/my.sock"
+	NetworkLocalAddressKey = attribute.Key("network.local.address")
+
+	// NetworkLocalPortKey is the attribute Key conforming to the
+	// "network.local.port" semantic conventions. It represents the local port
+	// number of the network connection.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 65123
+	NetworkLocalPortKey = attribute.Key("network.local.port")
+
+	// NetworkPeerAddressKey is the attribute Key conforming to the
+	// "network.peer.address" semantic conventions. It represents the peer address
+	// of the network connection - IP address or Unix domain socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "10.1.2.80", "/tmp/my.sock"
+	NetworkPeerAddressKey = attribute.Key("network.peer.address")
+
+	// NetworkPeerPortKey is the attribute Key conforming to the "network.peer.port"
+	// semantic conventions. It represents the peer port number of the network
+	// connection.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 65123
+	NetworkPeerPortKey = attribute.Key("network.peer.port")
+
+	// NetworkProtocolNameKey is the attribute Key conforming to the
+	// "network.protocol.name" semantic conventions. It represents the
+	// [OSI application layer] or non-OSI equivalent.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "amqp", "http", "mqtt"
+	// Note: The value SHOULD be normalized to lowercase.
+	//
+	// [OSI application layer]: https://wikipedia.org/wiki/Application_layer
+	NetworkProtocolNameKey = attribute.Key("network.protocol.name")
+
+	// NetworkProtocolVersionKey is the attribute Key conforming to the
+	// "network.protocol.version" semantic conventions. It represents the actual
+	// version of the protocol used for network communication.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "1.1", "2"
+	// Note: If protocol version is subject to negotiation (for example using [ALPN]
+	// ), this attribute SHOULD be set to the negotiated version. If the actual
+	// protocol version is not known, this attribute SHOULD NOT be set.
+	//
+	// [ALPN]: https://www.rfc-editor.org/rfc/rfc7301.html
+	NetworkProtocolVersionKey = attribute.Key("network.protocol.version")
+
+	// NetworkTransportKey is the attribute Key conforming to the
+	// "network.transport" semantic conventions. It represents the
+	// [OSI transport layer] or [inter-process communication method].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "tcp", "udp"
+	// Note: The value SHOULD be normalized to lowercase.
+	//
+	// Consider always setting the transport when setting a port number, since
+	// a port number is ambiguous without knowing the transport. For example
+	// different processes could be listening on TCP port 12345 and UDP port 12345.
+	//
+	// [OSI transport layer]: https://wikipedia.org/wiki/Transport_layer
+	// [inter-process communication method]: https://wikipedia.org/wiki/Inter-process_communication
+	NetworkTransportKey = attribute.Key("network.transport")
+
+	// NetworkTypeKey is the attribute Key conforming to the "network.type" semantic
+	// conventions. It represents the [OSI network layer] or non-OSI equivalent.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "ipv4", "ipv6"
+	// Note: The value SHOULD be normalized to lowercase.
+	//
+	// [OSI network layer]: https://wikipedia.org/wiki/Network_layer
+	NetworkTypeKey = attribute.Key("network.type")
+)
+
+// NetworkCarrierICC returns an attribute KeyValue conforming to the
+// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1
+// alpha-2 2-character country code associated with the mobile carrier network.
+func NetworkCarrierICC(val string) attribute.KeyValue {
+	return NetworkCarrierICCKey.String(val)
+}
+
+// NetworkCarrierMCC returns an attribute KeyValue conforming to the
+// "network.carrier.mcc" semantic conventions. It represents the mobile carrier
+// country code.
+func NetworkCarrierMCC(val string) attribute.KeyValue {
+	return NetworkCarrierMCCKey.String(val)
+}
+
+// NetworkCarrierMNC returns an attribute KeyValue conforming to the
+// "network.carrier.mnc" semantic conventions. It represents the mobile carrier
+// network code.
+func NetworkCarrierMNC(val string) attribute.KeyValue {
+	return NetworkCarrierMNCKey.String(val)
+}
+
+// NetworkCarrierName returns an attribute KeyValue conforming to the
+// "network.carrier.name" semantic conventions. It represents the name of the
+// mobile carrier.
+func NetworkCarrierName(val string) attribute.KeyValue {
+	return NetworkCarrierNameKey.String(val)
+}
+
+// NetworkInterfaceName returns an attribute KeyValue conforming to the
+// "network.interface.name" semantic conventions. It represents the network
+// interface name.
+func NetworkInterfaceName(val string) attribute.KeyValue {
+	return NetworkInterfaceNameKey.String(val)
+}
+
+// NetworkLocalAddress returns an attribute KeyValue conforming to the
+// "network.local.address" semantic conventions. It represents the local address
+// of the network connection - IP address or Unix domain socket name.
+func NetworkLocalAddress(val string) attribute.KeyValue {
+	return NetworkLocalAddressKey.String(val)
+}
+
+// NetworkLocalPort returns an attribute KeyValue conforming to the
+// "network.local.port" semantic conventions. It represents the local port number
+// of the network connection.
+func NetworkLocalPort(val int) attribute.KeyValue {
+	return NetworkLocalPortKey.Int(val)
+}
+
+// NetworkPeerAddress returns an attribute KeyValue conforming to the
+// "network.peer.address" semantic conventions. It represents the peer address of
+// the network connection - IP address or Unix domain socket name.
+func NetworkPeerAddress(val string) attribute.KeyValue {
+	return NetworkPeerAddressKey.String(val)
+}
+
+// NetworkPeerPort returns an attribute KeyValue conforming to the
+// "network.peer.port" semantic conventions. It represents the peer port number
+// of the network connection.
+func NetworkPeerPort(val int) attribute.KeyValue {
+	return NetworkPeerPortKey.Int(val)
+}
+
+// NetworkProtocolName returns an attribute KeyValue conforming to the
+// "network.protocol.name" semantic conventions. It represents the
+// [OSI application layer] or non-OSI equivalent.
+//
+// [OSI application layer]: https://wikipedia.org/wiki/Application_layer
+func NetworkProtocolName(val string) attribute.KeyValue {
+	return NetworkProtocolNameKey.String(val)
+}
+
+// NetworkProtocolVersion returns an attribute KeyValue conforming to the
+// "network.protocol.version" semantic conventions. It represents the actual
+// version of the protocol used for network communication.
+func NetworkProtocolVersion(val string) attribute.KeyValue {
+	return NetworkProtocolVersionKey.String(val)
+}
+
+// Enum values for network.connection.state
+var (
+	// closed
+	// Stability: development
+	NetworkConnectionStateClosed = NetworkConnectionStateKey.String("closed")
+	// close_wait
+	// Stability: development
+	NetworkConnectionStateCloseWait = NetworkConnectionStateKey.String("close_wait")
+	// closing
+	// Stability: development
+	NetworkConnectionStateClosing = NetworkConnectionStateKey.String("closing")
+	// established
+	// Stability: development
+	NetworkConnectionStateEstablished = NetworkConnectionStateKey.String("established")
+	// fin_wait_1
+	// Stability: development
+	NetworkConnectionStateFinWait1 = NetworkConnectionStateKey.String("fin_wait_1")
+	// fin_wait_2
+	// Stability: development
+	NetworkConnectionStateFinWait2 = NetworkConnectionStateKey.String("fin_wait_2")
+	// last_ack
+	// Stability: development
+	NetworkConnectionStateLastAck = NetworkConnectionStateKey.String("last_ack")
+	// listen
+	// Stability: development
+	NetworkConnectionStateListen = NetworkConnectionStateKey.String("listen")
+	// syn_received
+	// Stability: development
+	NetworkConnectionStateSynReceived = NetworkConnectionStateKey.String("syn_received")
+	// syn_sent
+	// Stability: development
+	NetworkConnectionStateSynSent = NetworkConnectionStateKey.String("syn_sent")
+	// time_wait
+	// Stability: development
+	NetworkConnectionStateTimeWait = NetworkConnectionStateKey.String("time_wait")
+)
+
+// Enum values for network.connection.subtype
+var (
+	// GPRS
+	// Stability: development
+	NetworkConnectionSubtypeGprs = NetworkConnectionSubtypeKey.String("gprs")
+	// EDGE
+	// Stability: development
+	NetworkConnectionSubtypeEdge = NetworkConnectionSubtypeKey.String("edge")
+	// UMTS
+	// Stability: development
+	NetworkConnectionSubtypeUmts = NetworkConnectionSubtypeKey.String("umts")
+	// CDMA
+	// Stability: development
+	NetworkConnectionSubtypeCdma = NetworkConnectionSubtypeKey.String("cdma")
+	// EVDO Rel. 0
+	// Stability: development
+	NetworkConnectionSubtypeEvdo0 = NetworkConnectionSubtypeKey.String("evdo_0")
+	// EVDO Rev. A
+	// Stability: development
+	NetworkConnectionSubtypeEvdoA = NetworkConnectionSubtypeKey.String("evdo_a")
+	// CDMA2000 1XRTT
+	// Stability: development
+	NetworkConnectionSubtypeCdma20001xrtt = NetworkConnectionSubtypeKey.String("cdma2000_1xrtt")
+	// HSDPA
+	// Stability: development
+	NetworkConnectionSubtypeHsdpa = NetworkConnectionSubtypeKey.String("hsdpa")
+	// HSUPA
+	// Stability: development
+	NetworkConnectionSubtypeHsupa = NetworkConnectionSubtypeKey.String("hsupa")
+	// HSPA
+	// Stability: development
+	NetworkConnectionSubtypeHspa = NetworkConnectionSubtypeKey.String("hspa")
+	// IDEN
+	// Stability: development
+	NetworkConnectionSubtypeIden = NetworkConnectionSubtypeKey.String("iden")
+	// EVDO Rev. B
+	// Stability: development
+	NetworkConnectionSubtypeEvdoB = NetworkConnectionSubtypeKey.String("evdo_b")
+	// LTE
+	// Stability: development
+	NetworkConnectionSubtypeLte = NetworkConnectionSubtypeKey.String("lte")
+	// EHRPD
+	// Stability: development
+	NetworkConnectionSubtypeEhrpd = NetworkConnectionSubtypeKey.String("ehrpd")
+	// HSPAP
+	// Stability: development
+	NetworkConnectionSubtypeHspap = NetworkConnectionSubtypeKey.String("hspap")
+	// GSM
+	// Stability: development
+	NetworkConnectionSubtypeGsm = NetworkConnectionSubtypeKey.String("gsm")
+	// TD-SCDMA
+	// Stability: development
+	NetworkConnectionSubtypeTdScdma = NetworkConnectionSubtypeKey.String("td_scdma")
+	// IWLAN
+	// Stability: development
+	NetworkConnectionSubtypeIwlan = NetworkConnectionSubtypeKey.String("iwlan")
+	// 5G NR (New Radio)
+	// Stability: development
+	NetworkConnectionSubtypeNr = NetworkConnectionSubtypeKey.String("nr")
+	// 5G NRNSA (New Radio Non-Standalone)
+	// Stability: development
+	NetworkConnectionSubtypeNrnsa = NetworkConnectionSubtypeKey.String("nrnsa")
+	// LTE CA
+	// Stability: development
+	NetworkConnectionSubtypeLteCa = NetworkConnectionSubtypeKey.String("lte_ca")
+)
+
+// Enum values for network.connection.type
+var (
+	// wifi
+	// Stability: development
+	NetworkConnectionTypeWifi = NetworkConnectionTypeKey.String("wifi")
+	// wired
+	// Stability: development
+	NetworkConnectionTypeWired = NetworkConnectionTypeKey.String("wired")
+	// cell
+	// Stability: development
+	NetworkConnectionTypeCell = NetworkConnectionTypeKey.String("cell")
+	// unavailable
+	// Stability: development
+	NetworkConnectionTypeUnavailable = NetworkConnectionTypeKey.String("unavailable")
+	// unknown
+	// Stability: development
+	NetworkConnectionTypeUnknown = NetworkConnectionTypeKey.String("unknown")
+)
+
+// Enum values for network.io.direction
+var (
+	// transmit
+	// Stability: development
+	NetworkIODirectionTransmit = NetworkIODirectionKey.String("transmit")
+	// receive
+	// Stability: development
+	NetworkIODirectionReceive = NetworkIODirectionKey.String("receive")
+)
+
+// Enum values for network.transport
+var (
+	// TCP
+	// Stability: stable
+	NetworkTransportTCP = NetworkTransportKey.String("tcp")
+	// UDP
+	// Stability: stable
+	NetworkTransportUDP = NetworkTransportKey.String("udp")
+	// Named or anonymous pipe.
+	// Stability: stable
+	NetworkTransportPipe = NetworkTransportKey.String("pipe")
+	// Unix domain socket
+	// Stability: stable
+	NetworkTransportUnix = NetworkTransportKey.String("unix")
+	// QUIC
+	// Stability: stable
+	NetworkTransportQUIC = NetworkTransportKey.String("quic")
+)
+
+// Enum values for network.type
+var (
+	// IPv4
+	// Stability: stable
+	NetworkTypeIPv4 = NetworkTypeKey.String("ipv4")
+	// IPv6
+	// Stability: stable
+	NetworkTypeIPv6 = NetworkTypeKey.String("ipv6")
+)
+
+// Namespace: oci
+const (
+	// OCIManifestDigestKey is the attribute Key conforming to the
+	// "oci.manifest.digest" semantic conventions. It represents the digest of the
+	// OCI image manifest. For container images specifically is the digest by which
+	// the container image is known.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4"
+	// Note: Follows [OCI Image Manifest Specification], and specifically the
+	// [Digest property].
+	// An example can be found in [Example Image Manifest].
+	//
+	// [OCI Image Manifest Specification]: https://github.com/opencontainers/image-spec/blob/main/manifest.md
+	// [Digest property]: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests
+	// [Example Image Manifest]: https://github.com/opencontainers/image-spec/blob/main/manifest.md#example-image-manifest
+	OCIManifestDigestKey = attribute.Key("oci.manifest.digest")
+)
+
+// OCIManifestDigest returns an attribute KeyValue conforming to the
+// "oci.manifest.digest" semantic conventions. It represents the digest of the
+// OCI image manifest. For container images specifically is the digest by which
+// the container image is known.
+func OCIManifestDigest(val string) attribute.KeyValue {
+	return OCIManifestDigestKey.String(val)
+}
+
+// Namespace: opentracing
+const (
+	// OpenTracingRefTypeKey is the attribute Key conforming to the
+	// "opentracing.ref_type" semantic conventions. It represents the parent-child
+	// Reference type.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: The causal relationship between a child Span and a parent Span.
+	OpenTracingRefTypeKey = attribute.Key("opentracing.ref_type")
+)
+
+// Enum values for opentracing.ref_type
+var (
+	// The parent Span depends on the child Span in some capacity
+	// Stability: development
+	OpenTracingRefTypeChildOf = OpenTracingRefTypeKey.String("child_of")
+	// The parent Span doesn't depend in any way on the result of the child Span
+	// Stability: development
+	OpenTracingRefTypeFollowsFrom = OpenTracingRefTypeKey.String("follows_from")
+)
+
+// Namespace: os
+const (
+	// OSBuildIDKey is the attribute Key conforming to the "os.build_id" semantic
+	// conventions. It represents the unique identifier for a particular build or
+	// compilation of the operating system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "TQ3C.230805.001.B2", "20E247", "22621"
+	OSBuildIDKey = attribute.Key("os.build_id")
+
+	// OSDescriptionKey is the attribute Key conforming to the "os.description"
+	// semantic conventions. It represents the human readable (not intended to be
+	// parsed) OS version information, like e.g. reported by `ver` or
+	// `lsb_release -a` commands.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Microsoft Windows [Version 10.0.18363.778]", "Ubuntu 18.04.1 LTS"
+	OSDescriptionKey = attribute.Key("os.description")
+
+	// OSNameKey is the attribute Key conforming to the "os.name" semantic
+	// conventions. It represents the human readable operating system name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "iOS", "Android", "Ubuntu"
+	OSNameKey = attribute.Key("os.name")
+
+	// OSTypeKey is the attribute Key conforming to the "os.type" semantic
+	// conventions. It represents the operating system type.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	OSTypeKey = attribute.Key("os.type")
+
+	// OSVersionKey is the attribute Key conforming to the "os.version" semantic
+	// conventions. It represents the version string of the operating system as
+	// defined in [Version Attributes].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "14.2.1", "18.04.1"
+	//
+	// [Version Attributes]: /docs/resource/README.md#version-attributes
+	OSVersionKey = attribute.Key("os.version")
+)
+
+// OSBuildID returns an attribute KeyValue conforming to the "os.build_id"
+// semantic conventions. It represents the unique identifier for a particular
+// build or compilation of the operating system.
+func OSBuildID(val string) attribute.KeyValue {
+	return OSBuildIDKey.String(val)
+}
+
+// OSDescription returns an attribute KeyValue conforming to the "os.description"
+// semantic conventions. It represents the human readable (not intended to be
+// parsed) OS version information, like e.g. reported by `ver` or
+// `lsb_release -a` commands.
+func OSDescription(val string) attribute.KeyValue {
+	return OSDescriptionKey.String(val)
+}
+
+// OSName returns an attribute KeyValue conforming to the "os.name" semantic
+// conventions. It represents the human readable operating system name.
+func OSName(val string) attribute.KeyValue {
+	return OSNameKey.String(val)
+}
+
+// OSVersion returns an attribute KeyValue conforming to the "os.version"
+// semantic conventions. It represents the version string of the operating system
+// as defined in [Version Attributes].
+//
+// [Version Attributes]: /docs/resource/README.md#version-attributes
+func OSVersion(val string) attribute.KeyValue {
+	return OSVersionKey.String(val)
+}
+
+// Enum values for os.type
+var (
+	// Microsoft Windows
+	// Stability: development
+	OSTypeWindows = OSTypeKey.String("windows")
+	// Linux
+	// Stability: development
+	OSTypeLinux = OSTypeKey.String("linux")
+	// Apple Darwin
+	// Stability: development
+	OSTypeDarwin = OSTypeKey.String("darwin")
+	// FreeBSD
+	// Stability: development
+	OSTypeFreeBSD = OSTypeKey.String("freebsd")
+	// NetBSD
+	// Stability: development
+	OSTypeNetBSD = OSTypeKey.String("netbsd")
+	// OpenBSD
+	// Stability: development
+	OSTypeOpenBSD = OSTypeKey.String("openbsd")
+	// DragonFly BSD
+	// Stability: development
+	OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd")
+	// HP-UX (Hewlett Packard Unix)
+	// Stability: development
+	OSTypeHPUX = OSTypeKey.String("hpux")
+	// AIX (Advanced Interactive eXecutive)
+	// Stability: development
+	OSTypeAIX = OSTypeKey.String("aix")
+	// SunOS, Oracle Solaris
+	// Stability: development
+	OSTypeSolaris = OSTypeKey.String("solaris")
+	// IBM z/OS
+	// Stability: development
+	OSTypeZOS = OSTypeKey.String("z_os")
+)
+
+// Namespace: otel
+const (
+	// OTelComponentNameKey is the attribute Key conforming to the
+	// "otel.component.name" semantic conventions. It represents a name uniquely
+	// identifying the instance of the OpenTelemetry component within its containing
+	// SDK instance.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "otlp_grpc_span_exporter/0", "custom-name"
+	// Note: Implementations SHOULD ensure a low cardinality for this attribute,
+	// even across application or SDK restarts.
+	// E.g. implementations MUST NOT use UUIDs as values for this attribute.
+	//
+	// Implementations MAY achieve these goals by following a
+	// `/` pattern, e.g.
+	// `batching_span_processor/0`.
+	// Hereby `otel.component.type` refers to the corresponding attribute value of
+	// the component.
+	//
+	// The value of `instance-counter` MAY be automatically assigned by the
+	// component and uniqueness within the enclosing SDK instance MUST be
+	// guaranteed.
+	// For example, `` MAY be implemented by using a monotonically
+	// increasing counter (starting with `0`), which is incremented every time an
+	// instance of the given component type is started.
+	//
+	// With this implementation, for example the first Batching Span Processor would
+	// have `batching_span_processor/0`
+	// as `otel.component.name`, the second one `batching_span_processor/1` and so
+	// on.
+	// These values will therefore be reused in the case of an application restart.
+	OTelComponentNameKey = attribute.Key("otel.component.name")
+
+	// OTelComponentTypeKey is the attribute Key conforming to the
+	// "otel.component.type" semantic conventions. It represents a name identifying
+	// the type of the OpenTelemetry component.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "batching_span_processor", "com.example.MySpanExporter"
+	// Note: If none of the standardized values apply, implementations SHOULD use
+	// the language-defined name of the type.
+	// E.g. for Java the fully qualified classname SHOULD be used in this case.
+	OTelComponentTypeKey = attribute.Key("otel.component.type")
+
+	// OTelScopeNameKey is the attribute Key conforming to the "otel.scope.name"
+	// semantic conventions. It represents the name of the instrumentation scope - (
+	// `InstrumentationScope.Name` in OTLP).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "io.opentelemetry.contrib.mongodb"
+	OTelScopeNameKey = attribute.Key("otel.scope.name")
+
+	// OTelScopeVersionKey is the attribute Key conforming to the
+	// "otel.scope.version" semantic conventions. It represents the version of the
+	// instrumentation scope - (`InstrumentationScope.Version` in OTLP).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "1.0.0"
+	OTelScopeVersionKey = attribute.Key("otel.scope.version")
+
+	// OTelSpanSamplingResultKey is the attribute Key conforming to the
+	// "otel.span.sampling_result" semantic conventions. It represents the result
+	// value of the sampler for this span.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	OTelSpanSamplingResultKey = attribute.Key("otel.span.sampling_result")
+
+	// OTelStatusCodeKey is the attribute Key conforming to the "otel.status_code"
+	// semantic conventions. It represents the name of the code, either "OK" or
+	// "ERROR". MUST NOT be set if the status code is UNSET.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples:
+	OTelStatusCodeKey = attribute.Key("otel.status_code")
+
+	// OTelStatusDescriptionKey is the attribute Key conforming to the
+	// "otel.status_description" semantic conventions. It represents the description
+	// of the Status if it has a value, otherwise not set.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "resource not found"
+	OTelStatusDescriptionKey = attribute.Key("otel.status_description")
+)
+
+// OTelComponentName returns an attribute KeyValue conforming to the
+// "otel.component.name" semantic conventions. It represents a name uniquely
+// identifying the instance of the OpenTelemetry component within its containing
+// SDK instance.
+func OTelComponentName(val string) attribute.KeyValue {
+	return OTelComponentNameKey.String(val)
+}
+
+// OTelScopeName returns an attribute KeyValue conforming to the
+// "otel.scope.name" semantic conventions. It represents the name of the
+// instrumentation scope - (`InstrumentationScope.Name` in OTLP).
+func OTelScopeName(val string) attribute.KeyValue {
+	return OTelScopeNameKey.String(val)
+}
+
+// OTelScopeVersion returns an attribute KeyValue conforming to the
+// "otel.scope.version" semantic conventions. It represents the version of the
+// instrumentation scope - (`InstrumentationScope.Version` in OTLP).
+func OTelScopeVersion(val string) attribute.KeyValue {
+	return OTelScopeVersionKey.String(val)
+}
+
+// OTelStatusDescription returns an attribute KeyValue conforming to the
+// "otel.status_description" semantic conventions. It represents the description
+// of the Status if it has a value, otherwise not set.
+func OTelStatusDescription(val string) attribute.KeyValue {
+	return OTelStatusDescriptionKey.String(val)
+}
+
+// Enum values for otel.component.type
+var (
+	// The builtin SDK batching span processor
+	//
+	// Stability: development
+	OTelComponentTypeBatchingSpanProcessor = OTelComponentTypeKey.String("batching_span_processor")
+	// The builtin SDK simple span processor
+	//
+	// Stability: development
+	OTelComponentTypeSimpleSpanProcessor = OTelComponentTypeKey.String("simple_span_processor")
+	// The builtin SDK batching log record processor
+	//
+	// Stability: development
+	OTelComponentTypeBatchingLogProcessor = OTelComponentTypeKey.String("batching_log_processor")
+	// The builtin SDK simple log record processor
+	//
+	// Stability: development
+	OTelComponentTypeSimpleLogProcessor = OTelComponentTypeKey.String("simple_log_processor")
+	// OTLP span exporter over gRPC with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpGRPCSpanExporter = OTelComponentTypeKey.String("otlp_grpc_span_exporter")
+	// OTLP span exporter over HTTP with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPSpanExporter = OTelComponentTypeKey.String("otlp_http_span_exporter")
+	// OTLP span exporter over HTTP with JSON serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPJSONSpanExporter = OTelComponentTypeKey.String("otlp_http_json_span_exporter")
+	// OTLP log record exporter over gRPC with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpGRPCLogExporter = OTelComponentTypeKey.String("otlp_grpc_log_exporter")
+	// OTLP log record exporter over HTTP with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPLogExporter = OTelComponentTypeKey.String("otlp_http_log_exporter")
+	// OTLP log record exporter over HTTP with JSON serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPJSONLogExporter = OTelComponentTypeKey.String("otlp_http_json_log_exporter")
+	// The builtin SDK periodically exporting metric reader
+	//
+	// Stability: development
+	OTelComponentTypePeriodicMetricReader = OTelComponentTypeKey.String("periodic_metric_reader")
+	// OTLP metric exporter over gRPC with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpGRPCMetricExporter = OTelComponentTypeKey.String("otlp_grpc_metric_exporter")
+	// OTLP metric exporter over HTTP with protobuf serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPMetricExporter = OTelComponentTypeKey.String("otlp_http_metric_exporter")
+	// OTLP metric exporter over HTTP with JSON serialization
+	//
+	// Stability: development
+	OTelComponentTypeOtlpHTTPJSONMetricExporter = OTelComponentTypeKey.String("otlp_http_json_metric_exporter")
+)
+
+// Enum values for otel.span.sampling_result
+var (
+	// The span is not sampled and not recording
+	// Stability: development
+	OTelSpanSamplingResultDrop = OTelSpanSamplingResultKey.String("DROP")
+	// The span is not sampled, but recording
+	// Stability: development
+	OTelSpanSamplingResultRecordOnly = OTelSpanSamplingResultKey.String("RECORD_ONLY")
+	// The span is sampled and recording
+	// Stability: development
+	OTelSpanSamplingResultRecordAndSample = OTelSpanSamplingResultKey.String("RECORD_AND_SAMPLE")
+)
+
+// Enum values for otel.status_code
+var (
+	// The operation has been validated by an Application developer or Operator to
+	// have completed successfully.
+	// Stability: stable
+	OTelStatusCodeOk = OTelStatusCodeKey.String("OK")
+	// The operation contains an error.
+	// Stability: stable
+	OTelStatusCodeError = OTelStatusCodeKey.String("ERROR")
+)
+
+// Namespace: peer
+const (
+	// PeerServiceKey is the attribute Key conforming to the "peer.service" semantic
+	// conventions. It represents the [`service.name`] of the remote service. SHOULD
+	// be equal to the actual `service.name` resource attribute of the remote
+	// service if any.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: AuthTokenCache
+	//
+	// [`service.name`]: /docs/resource/README.md#service
+	PeerServiceKey = attribute.Key("peer.service")
+)
+
+// PeerService returns an attribute KeyValue conforming to the "peer.service"
+// semantic conventions. It represents the [`service.name`] of the remote
+// service. SHOULD be equal to the actual `service.name` resource attribute of
+// the remote service if any.
+//
+// [`service.name`]: /docs/resource/README.md#service
+func PeerService(val string) attribute.KeyValue {
+	return PeerServiceKey.String(val)
+}
+
+// Namespace: process
+const (
+	// ProcessArgsCountKey is the attribute Key conforming to the
+	// "process.args_count" semantic conventions. It represents the length of the
+	// process.command_args array.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 4
+	// Note: This field can be useful for querying or performing bucket analysis on
+	// how many arguments were provided to start a process. More arguments may be an
+	// indication of suspicious activity.
+	ProcessArgsCountKey = attribute.Key("process.args_count")
+
+	// ProcessCommandKey is the attribute Key conforming to the "process.command"
+	// semantic conventions. It represents the command used to launch the process
+	// (i.e. the command name). On Linux based systems, can be set to the zeroth
+	// string in `proc/[pid]/cmdline`. On Windows, can be set to the first parameter
+	// extracted from `GetCommandLineW`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "cmd/otelcol"
+	ProcessCommandKey = attribute.Key("process.command")
+
+	// ProcessCommandArgsKey is the attribute Key conforming to the
+	// "process.command_args" semantic conventions. It represents the all the
+	// command arguments (including the command/executable itself) as received by
+	// the process. On Linux-based systems (and some other Unixoid systems
+	// supporting procfs), can be set according to the list of null-delimited
+	// strings extracted from `proc/[pid]/cmdline`. For libc-based executables, this
+	// would be the full argv vector passed to `main`. SHOULD NOT be collected by
+	// default unless there is sanitization that excludes sensitive data.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "cmd/otecol", "--config=config.yaml"
+	ProcessCommandArgsKey = attribute.Key("process.command_args")
+
+	// ProcessCommandLineKey is the attribute Key conforming to the
+	// "process.command_line" semantic conventions. It represents the full command
+	// used to launch the process as a single string representing the full command.
+	// On Windows, can be set to the result of `GetCommandLineW`. Do not set this if
+	// you have to assemble it just for monitoring; use `process.command_args`
+	// instead. SHOULD NOT be collected by default unless there is sanitization that
+	// excludes sensitive data.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "C:\cmd\otecol --config="my directory\config.yaml""
+	ProcessCommandLineKey = attribute.Key("process.command_line")
+
+	// ProcessContextSwitchTypeKey is the attribute Key conforming to the
+	// "process.context_switch_type" semantic conventions. It represents the
+	// specifies whether the context switches for this data point were voluntary or
+	// involuntary.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	ProcessContextSwitchTypeKey = attribute.Key("process.context_switch_type")
+
+	// ProcessCreationTimeKey is the attribute Key conforming to the
+	// "process.creation.time" semantic conventions. It represents the date and time
+	// the process was created, in ISO 8601 format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2023-11-21T09:25:34.853Z"
+	ProcessCreationTimeKey = attribute.Key("process.creation.time")
+
+	// ProcessExecutableBuildIDGNUKey is the attribute Key conforming to the
+	// "process.executable.build_id.gnu" semantic conventions. It represents the GNU
+	// build ID as found in the `.note.gnu.build-id` ELF section (hex string).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "c89b11207f6479603b0d49bf291c092c2b719293"
+	ProcessExecutableBuildIDGNUKey = attribute.Key("process.executable.build_id.gnu")
+
+	// ProcessExecutableBuildIDGoKey is the attribute Key conforming to the
+	// "process.executable.build_id.go" semantic conventions. It represents the Go
+	// build ID as retrieved by `go tool buildid `.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "foh3mEXu7BLZjsN9pOwG/kATcXlYVCDEFouRMQed_/WwRFB1hPo9LBkekthSPG/x8hMC8emW2cCjXD0_1aY"
+	ProcessExecutableBuildIDGoKey = attribute.Key("process.executable.build_id.go")
+
+	// ProcessExecutableBuildIDHtlhashKey is the attribute Key conforming to the
+	// "process.executable.build_id.htlhash" semantic conventions. It represents the
+	// profiling specific build ID for executables. See the OTel specification for
+	// Profiles for more information.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "600DCAFE4A110000F2BF38C493F5FB92"
+	ProcessExecutableBuildIDHtlhashKey = attribute.Key("process.executable.build_id.htlhash")
+
+	// ProcessExecutableNameKey is the attribute Key conforming to the
+	// "process.executable.name" semantic conventions. It represents the name of the
+	// process executable. On Linux based systems, this SHOULD be set to the base
+	// name of the target of `/proc/[pid]/exe`. On Windows, this SHOULD be set to
+	// the base name of `GetProcessImageFileNameW`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "otelcol"
+	ProcessExecutableNameKey = attribute.Key("process.executable.name")
+
+	// ProcessExecutablePathKey is the attribute Key conforming to the
+	// "process.executable.path" semantic conventions. It represents the full path
+	// to the process executable. On Linux based systems, can be set to the target
+	// of `proc/[pid]/exe`. On Windows, can be set to the result of
+	// `GetProcessImageFileNameW`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/usr/bin/cmd/otelcol"
+	ProcessExecutablePathKey = attribute.Key("process.executable.path")
+
+	// ProcessExitCodeKey is the attribute Key conforming to the "process.exit.code"
+	// semantic conventions. It represents the exit code of the process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 127
+	ProcessExitCodeKey = attribute.Key("process.exit.code")
+
+	// ProcessExitTimeKey is the attribute Key conforming to the "process.exit.time"
+	// semantic conventions. It represents the date and time the process exited, in
+	// ISO 8601 format.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2023-11-21T09:26:12.315Z"
+	ProcessExitTimeKey = attribute.Key("process.exit.time")
+
+	// ProcessGroupLeaderPIDKey is the attribute Key conforming to the
+	// "process.group_leader.pid" semantic conventions. It represents the PID of the
+	// process's group leader. This is also the process group ID (PGID) of the
+	// process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 23
+	ProcessGroupLeaderPIDKey = attribute.Key("process.group_leader.pid")
+
+	// ProcessInteractiveKey is the attribute Key conforming to the
+	// "process.interactive" semantic conventions. It represents the whether the
+	// process is connected to an interactive shell.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	ProcessInteractiveKey = attribute.Key("process.interactive")
+
+	// ProcessLinuxCgroupKey is the attribute Key conforming to the
+	// "process.linux.cgroup" semantic conventions. It represents the control group
+	// associated with the process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1:name=systemd:/user.slice/user-1000.slice/session-3.scope",
+	// "0::/user.slice/user-1000.slice/user@1000.service/tmux-spawn-0267755b-4639-4a27-90ed-f19f88e53748.scope"
+	// Note: Control groups (cgroups) are a kernel feature used to organize and
+	// manage process resources. This attribute provides the path(s) to the
+	// cgroup(s) associated with the process, which should match the contents of the
+	// [/proc/[PID]/cgroup] file.
+	//
+	// [/proc/[PID]/cgroup]: https://man7.org/linux/man-pages/man7/cgroups.7.html
+	ProcessLinuxCgroupKey = attribute.Key("process.linux.cgroup")
+
+	// ProcessOwnerKey is the attribute Key conforming to the "process.owner"
+	// semantic conventions. It represents the username of the user that owns the
+	// process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "root"
+	ProcessOwnerKey = attribute.Key("process.owner")
+
+	// ProcessPagingFaultTypeKey is the attribute Key conforming to the
+	// "process.paging.fault_type" semantic conventions. It represents the type of
+	// page fault for this data point. Type `major` is for major/hard page faults,
+	// and `minor` is for minor/soft page faults.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	ProcessPagingFaultTypeKey = attribute.Key("process.paging.fault_type")
+
+	// ProcessParentPIDKey is the attribute Key conforming to the
+	// "process.parent_pid" semantic conventions. It represents the parent Process
+	// identifier (PPID).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 111
+	ProcessParentPIDKey = attribute.Key("process.parent_pid")
+
+	// ProcessPIDKey is the attribute Key conforming to the "process.pid" semantic
+	// conventions. It represents the process identifier (PID).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1234
+	ProcessPIDKey = attribute.Key("process.pid")
+
+	// ProcessRealUserIDKey is the attribute Key conforming to the
+	// "process.real_user.id" semantic conventions. It represents the real user ID
+	// (RUID) of the process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1000
+	ProcessRealUserIDKey = attribute.Key("process.real_user.id")
+
+	// ProcessRealUserNameKey is the attribute Key conforming to the
+	// "process.real_user.name" semantic conventions. It represents the username of
+	// the real user of the process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "operator"
+	ProcessRealUserNameKey = attribute.Key("process.real_user.name")
+
+	// ProcessRuntimeDescriptionKey is the attribute Key conforming to the
+	// "process.runtime.description" semantic conventions. It represents an
+	// additional description about the runtime of the process, for example a
+	// specific vendor customization of the runtime environment.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0
+	ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description")
+
+	// ProcessRuntimeNameKey is the attribute Key conforming to the
+	// "process.runtime.name" semantic conventions. It represents the name of the
+	// runtime of this process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "OpenJDK Runtime Environment"
+	ProcessRuntimeNameKey = attribute.Key("process.runtime.name")
+
+	// ProcessRuntimeVersionKey is the attribute Key conforming to the
+	// "process.runtime.version" semantic conventions. It represents the version of
+	// the runtime of this process, as returned by the runtime without modification.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 14.0.2
+	ProcessRuntimeVersionKey = attribute.Key("process.runtime.version")
+
+	// ProcessSavedUserIDKey is the attribute Key conforming to the
+	// "process.saved_user.id" semantic conventions. It represents the saved user ID
+	// (SUID) of the process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1002
+	ProcessSavedUserIDKey = attribute.Key("process.saved_user.id")
+
+	// ProcessSavedUserNameKey is the attribute Key conforming to the
+	// "process.saved_user.name" semantic conventions. It represents the username of
+	// the saved user.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "operator"
+	ProcessSavedUserNameKey = attribute.Key("process.saved_user.name")
+
+	// ProcessSessionLeaderPIDKey is the attribute Key conforming to the
+	// "process.session_leader.pid" semantic conventions. It represents the PID of
+	// the process's session leader. This is also the session ID (SID) of the
+	// process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 14
+	ProcessSessionLeaderPIDKey = attribute.Key("process.session_leader.pid")
+
+	// ProcessTitleKey is the attribute Key conforming to the "process.title"
+	// semantic conventions. It represents the process title (proctitle).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "cat /etc/hostname", "xfce4-session", "bash"
+	// Note: In many Unix-like systems, process title (proctitle), is the string
+	// that represents the name or command line of a running process, displayed by
+	// system monitoring tools like ps, top, and htop.
+	ProcessTitleKey = attribute.Key("process.title")
+
+	// ProcessUserIDKey is the attribute Key conforming to the "process.user.id"
+	// semantic conventions. It represents the effective user ID (EUID) of the
+	// process.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1001
+	ProcessUserIDKey = attribute.Key("process.user.id")
+
+	// ProcessUserNameKey is the attribute Key conforming to the "process.user.name"
+	// semantic conventions. It represents the username of the effective user of the
+	// process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "root"
+	ProcessUserNameKey = attribute.Key("process.user.name")
+
+	// ProcessVpidKey is the attribute Key conforming to the "process.vpid" semantic
+	// conventions. It represents the virtual process identifier.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 12
+	// Note: The process ID within a PID namespace. This is not necessarily unique
+	// across all processes on the host but it is unique within the process
+	// namespace that the process exists within.
+	ProcessVpidKey = attribute.Key("process.vpid")
+
+	// ProcessWorkingDirectoryKey is the attribute Key conforming to the
+	// "process.working_directory" semantic conventions. It represents the working
+	// directory of the process.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/root"
+	ProcessWorkingDirectoryKey = attribute.Key("process.working_directory")
+)
+
+// ProcessArgsCount returns an attribute KeyValue conforming to the
+// "process.args_count" semantic conventions. It represents the length of the
+// process.command_args array.
+func ProcessArgsCount(val int) attribute.KeyValue {
+	return ProcessArgsCountKey.Int(val)
+}
+
+// ProcessCommand returns an attribute KeyValue conforming to the
+// "process.command" semantic conventions. It represents the command used to
+// launch the process (i.e. the command name). On Linux based systems, can be set
+// to the zeroth string in `proc/[pid]/cmdline`. On Windows, can be set to the
+// first parameter extracted from `GetCommandLineW`.
+func ProcessCommand(val string) attribute.KeyValue {
+	return ProcessCommandKey.String(val)
+}
+
+// ProcessCommandArgs returns an attribute KeyValue conforming to the
+// "process.command_args" semantic conventions. It represents the all the command
+// arguments (including the command/executable itself) as received by the
+// process. On Linux-based systems (and some other Unixoid systems supporting
+// procfs), can be set according to the list of null-delimited strings extracted
+// from `proc/[pid]/cmdline`. For libc-based executables, this would be the full
+// argv vector passed to `main`. SHOULD NOT be collected by default unless there
+// is sanitization that excludes sensitive data.
+func ProcessCommandArgs(val ...string) attribute.KeyValue {
+	return ProcessCommandArgsKey.StringSlice(val)
+}
+
+// ProcessCommandLine returns an attribute KeyValue conforming to the
+// "process.command_line" semantic conventions. It represents the full command
+// used to launch the process as a single string representing the full command.
+// On Windows, can be set to the result of `GetCommandLineW`. Do not set this if
+// you have to assemble it just for monitoring; use `process.command_args`
+// instead. SHOULD NOT be collected by default unless there is sanitization that
+// excludes sensitive data.
+func ProcessCommandLine(val string) attribute.KeyValue {
+	return ProcessCommandLineKey.String(val)
+}
+
+// ProcessCreationTime returns an attribute KeyValue conforming to the
+// "process.creation.time" semantic conventions. It represents the date and time
+// the process was created, in ISO 8601 format.
+func ProcessCreationTime(val string) attribute.KeyValue {
+	return ProcessCreationTimeKey.String(val)
+}
+
+// ProcessExecutableBuildIDGNU returns an attribute KeyValue conforming to the
+// "process.executable.build_id.gnu" semantic conventions. It represents the GNU
+// build ID as found in the `.note.gnu.build-id` ELF section (hex string).
+func ProcessExecutableBuildIDGNU(val string) attribute.KeyValue {
+	return ProcessExecutableBuildIDGNUKey.String(val)
+}
+
+// ProcessExecutableBuildIDGo returns an attribute KeyValue conforming to the
+// "process.executable.build_id.go" semantic conventions. It represents the Go
+// build ID as retrieved by `go tool buildid `.
+func ProcessExecutableBuildIDGo(val string) attribute.KeyValue {
+	return ProcessExecutableBuildIDGoKey.String(val)
+}
+
+// ProcessExecutableBuildIDHtlhash returns an attribute KeyValue conforming to
+// the "process.executable.build_id.htlhash" semantic conventions. It represents
+// the profiling specific build ID for executables. See the OTel specification
+// for Profiles for more information.
+func ProcessExecutableBuildIDHtlhash(val string) attribute.KeyValue {
+	return ProcessExecutableBuildIDHtlhashKey.String(val)
+}
+
+// ProcessExecutableName returns an attribute KeyValue conforming to the
+// "process.executable.name" semantic conventions. It represents the name of the
+// process executable. On Linux based systems, this SHOULD be set to the base
+// name of the target of `/proc/[pid]/exe`. On Windows, this SHOULD be set to the
+// base name of `GetProcessImageFileNameW`.
+func ProcessExecutableName(val string) attribute.KeyValue {
+	return ProcessExecutableNameKey.String(val)
+}
+
+// ProcessExecutablePath returns an attribute KeyValue conforming to the
+// "process.executable.path" semantic conventions. It represents the full path to
+// the process executable. On Linux based systems, can be set to the target of
+// `proc/[pid]/exe`. On Windows, can be set to the result of
+// `GetProcessImageFileNameW`.
+func ProcessExecutablePath(val string) attribute.KeyValue {
+	return ProcessExecutablePathKey.String(val)
+}
+
+// ProcessExitCode returns an attribute KeyValue conforming to the
+// "process.exit.code" semantic conventions. It represents the exit code of the
+// process.
+func ProcessExitCode(val int) attribute.KeyValue {
+	return ProcessExitCodeKey.Int(val)
+}
+
+// ProcessExitTime returns an attribute KeyValue conforming to the
+// "process.exit.time" semantic conventions. It represents the date and time the
+// process exited, in ISO 8601 format.
+func ProcessExitTime(val string) attribute.KeyValue {
+	return ProcessExitTimeKey.String(val)
+}
+
+// ProcessGroupLeaderPID returns an attribute KeyValue conforming to the
+// "process.group_leader.pid" semantic conventions. It represents the PID of the
+// process's group leader. This is also the process group ID (PGID) of the
+// process.
+func ProcessGroupLeaderPID(val int) attribute.KeyValue {
+	return ProcessGroupLeaderPIDKey.Int(val)
+}
+
+// ProcessInteractive returns an attribute KeyValue conforming to the
+// "process.interactive" semantic conventions. It represents the whether the
+// process is connected to an interactive shell.
+func ProcessInteractive(val bool) attribute.KeyValue {
+	return ProcessInteractiveKey.Bool(val)
+}
+
+// ProcessLinuxCgroup returns an attribute KeyValue conforming to the
+// "process.linux.cgroup" semantic conventions. It represents the control group
+// associated with the process.
+func ProcessLinuxCgroup(val string) attribute.KeyValue {
+	return ProcessLinuxCgroupKey.String(val)
+}
+
+// ProcessOwner returns an attribute KeyValue conforming to the "process.owner"
+// semantic conventions. It represents the username of the user that owns the
+// process.
+func ProcessOwner(val string) attribute.KeyValue {
+	return ProcessOwnerKey.String(val)
+}
+
+// ProcessParentPID returns an attribute KeyValue conforming to the
+// "process.parent_pid" semantic conventions. It represents the parent Process
+// identifier (PPID).
+func ProcessParentPID(val int) attribute.KeyValue {
+	return ProcessParentPIDKey.Int(val)
+}
+
+// ProcessPID returns an attribute KeyValue conforming to the "process.pid"
+// semantic conventions. It represents the process identifier (PID).
+func ProcessPID(val int) attribute.KeyValue {
+	return ProcessPIDKey.Int(val)
+}
+
+// ProcessRealUserID returns an attribute KeyValue conforming to the
+// "process.real_user.id" semantic conventions. It represents the real user ID
+// (RUID) of the process.
+func ProcessRealUserID(val int) attribute.KeyValue {
+	return ProcessRealUserIDKey.Int(val)
+}
+
+// ProcessRealUserName returns an attribute KeyValue conforming to the
+// "process.real_user.name" semantic conventions. It represents the username of
+// the real user of the process.
+func ProcessRealUserName(val string) attribute.KeyValue {
+	return ProcessRealUserNameKey.String(val)
+}
+
+// ProcessRuntimeDescription returns an attribute KeyValue conforming to the
+// "process.runtime.description" semantic conventions. It represents an
+// additional description about the runtime of the process, for example a
+// specific vendor customization of the runtime environment.
+func ProcessRuntimeDescription(val string) attribute.KeyValue {
+	return ProcessRuntimeDescriptionKey.String(val)
+}
+
+// ProcessRuntimeName returns an attribute KeyValue conforming to the
+// "process.runtime.name" semantic conventions. It represents the name of the
+// runtime of this process.
+func ProcessRuntimeName(val string) attribute.KeyValue {
+	return ProcessRuntimeNameKey.String(val)
+}
+
+// ProcessRuntimeVersion returns an attribute KeyValue conforming to the
+// "process.runtime.version" semantic conventions. It represents the version of
+// the runtime of this process, as returned by the runtime without modification.
+func ProcessRuntimeVersion(val string) attribute.KeyValue {
+	return ProcessRuntimeVersionKey.String(val)
+}
+
+// ProcessSavedUserID returns an attribute KeyValue conforming to the
+// "process.saved_user.id" semantic conventions. It represents the saved user ID
+// (SUID) of the process.
+func ProcessSavedUserID(val int) attribute.KeyValue {
+	return ProcessSavedUserIDKey.Int(val)
+}
+
+// ProcessSavedUserName returns an attribute KeyValue conforming to the
+// "process.saved_user.name" semantic conventions. It represents the username of
+// the saved user.
+func ProcessSavedUserName(val string) attribute.KeyValue {
+	return ProcessSavedUserNameKey.String(val)
+}
+
+// ProcessSessionLeaderPID returns an attribute KeyValue conforming to the
+// "process.session_leader.pid" semantic conventions. It represents the PID of
+// the process's session leader. This is also the session ID (SID) of the
+// process.
+func ProcessSessionLeaderPID(val int) attribute.KeyValue {
+	return ProcessSessionLeaderPIDKey.Int(val)
+}
+
+// ProcessTitle returns an attribute KeyValue conforming to the "process.title"
+// semantic conventions. It represents the process title (proctitle).
+func ProcessTitle(val string) attribute.KeyValue {
+	return ProcessTitleKey.String(val)
+}
+
+// ProcessUserID returns an attribute KeyValue conforming to the
+// "process.user.id" semantic conventions. It represents the effective user ID
+// (EUID) of the process.
+func ProcessUserID(val int) attribute.KeyValue {
+	return ProcessUserIDKey.Int(val)
+}
+
+// ProcessUserName returns an attribute KeyValue conforming to the
+// "process.user.name" semantic conventions. It represents the username of the
+// effective user of the process.
+func ProcessUserName(val string) attribute.KeyValue {
+	return ProcessUserNameKey.String(val)
+}
+
+// ProcessVpid returns an attribute KeyValue conforming to the "process.vpid"
+// semantic conventions. It represents the virtual process identifier.
+func ProcessVpid(val int) attribute.KeyValue {
+	return ProcessVpidKey.Int(val)
+}
+
+// ProcessWorkingDirectory returns an attribute KeyValue conforming to the
+// "process.working_directory" semantic conventions. It represents the working
+// directory of the process.
+func ProcessWorkingDirectory(val string) attribute.KeyValue {
+	return ProcessWorkingDirectoryKey.String(val)
+}
+
+// Enum values for process.context_switch_type
+var (
+	// voluntary
+	// Stability: development
+	ProcessContextSwitchTypeVoluntary = ProcessContextSwitchTypeKey.String("voluntary")
+	// involuntary
+	// Stability: development
+	ProcessContextSwitchTypeInvoluntary = ProcessContextSwitchTypeKey.String("involuntary")
+)
+
+// Enum values for process.paging.fault_type
+var (
+	// major
+	// Stability: development
+	ProcessPagingFaultTypeMajor = ProcessPagingFaultTypeKey.String("major")
+	// minor
+	// Stability: development
+	ProcessPagingFaultTypeMinor = ProcessPagingFaultTypeKey.String("minor")
+)
+
+// Namespace: profile
+const (
+	// ProfileFrameTypeKey is the attribute Key conforming to the
+	// "profile.frame.type" semantic conventions. It represents the describes the
+	// interpreter or compiler of a single frame.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "cpython"
+	ProfileFrameTypeKey = attribute.Key("profile.frame.type")
+)
+
+// Enum values for profile.frame.type
+var (
+	// [.NET]
+	//
+	// Stability: development
+	//
+	// [.NET]: https://wikipedia.org/wiki/.NET
+	ProfileFrameTypeDotnet = ProfileFrameTypeKey.String("dotnet")
+	// [JVM]
+	//
+	// Stability: development
+	//
+	// [JVM]: https://wikipedia.org/wiki/Java_virtual_machine
+	ProfileFrameTypeJVM = ProfileFrameTypeKey.String("jvm")
+	// [Kernel]
+	//
+	// Stability: development
+	//
+	// [Kernel]: https://wikipedia.org/wiki/Kernel_(operating_system)
+	ProfileFrameTypeKernel = ProfileFrameTypeKey.String("kernel")
+	// Can be one of but not limited to [C], [C++], [Go] or [Rust]. If possible, a
+	// more precise value MUST be used.
+	//
+	// Stability: development
+	//
+	// [C]: https://wikipedia.org/wiki/C_(programming_language)
+	// [C++]: https://wikipedia.org/wiki/C%2B%2B
+	// [Go]: https://wikipedia.org/wiki/Go_(programming_language)
+	// [Rust]: https://wikipedia.org/wiki/Rust_(programming_language)
+	ProfileFrameTypeNative = ProfileFrameTypeKey.String("native")
+	// [Perl]
+	//
+	// Stability: development
+	//
+	// [Perl]: https://wikipedia.org/wiki/Perl
+	ProfileFrameTypePerl = ProfileFrameTypeKey.String("perl")
+	// [PHP]
+	//
+	// Stability: development
+	//
+	// [PHP]: https://wikipedia.org/wiki/PHP
+	ProfileFrameTypePHP = ProfileFrameTypeKey.String("php")
+	// [Python]
+	//
+	// Stability: development
+	//
+	// [Python]: https://wikipedia.org/wiki/Python_(programming_language)
+	ProfileFrameTypeCpython = ProfileFrameTypeKey.String("cpython")
+	// [Ruby]
+	//
+	// Stability: development
+	//
+	// [Ruby]: https://wikipedia.org/wiki/Ruby_(programming_language)
+	ProfileFrameTypeRuby = ProfileFrameTypeKey.String("ruby")
+	// [V8JS]
+	//
+	// Stability: development
+	//
+	// [V8JS]: https://wikipedia.org/wiki/V8_(JavaScript_engine)
+	ProfileFrameTypeV8JS = ProfileFrameTypeKey.String("v8js")
+	// [Erlang]
+	//
+	// Stability: development
+	//
+	// [Erlang]: https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine)
+	ProfileFrameTypeBeam = ProfileFrameTypeKey.String("beam")
+	// [Go],
+	//
+	// Stability: development
+	//
+	// [Go]: https://wikipedia.org/wiki/Go_(programming_language)
+	ProfileFrameTypeGo = ProfileFrameTypeKey.String("go")
+	// [Rust]
+	//
+	// Stability: development
+	//
+	// [Rust]: https://wikipedia.org/wiki/Rust_(programming_language)
+	ProfileFrameTypeRust = ProfileFrameTypeKey.String("rust")
+)
+
+// Namespace: rpc
+const (
+	// RPCConnectRPCErrorCodeKey is the attribute Key conforming to the
+	// "rpc.connect_rpc.error_code" semantic conventions. It represents the
+	// [error codes] of the Connect request. Error codes are always string values.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [error codes]: https://connectrpc.com//docs/protocol/#error-codes
+	RPCConnectRPCErrorCodeKey = attribute.Key("rpc.connect_rpc.error_code")
+
+	// RPCGRPCStatusCodeKey is the attribute Key conforming to the
+	// "rpc.grpc.status_code" semantic conventions. It represents the
+	// [numeric status code] of the gRPC request.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [numeric status code]: https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md
+	RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
+
+	// RPCJSONRPCErrorCodeKey is the attribute Key conforming to the
+	// "rpc.jsonrpc.error_code" semantic conventions. It represents the `error.code`
+	//  property of response if it is an error response.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: -32700, 100
+	RPCJSONRPCErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code")
+
+	// RPCJSONRPCErrorMessageKey is the attribute Key conforming to the
+	// "rpc.jsonrpc.error_message" semantic conventions. It represents the
+	// `error.message` property of response if it is an error response.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Parse error", "User already exists"
+	RPCJSONRPCErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message")
+
+	// RPCJSONRPCRequestIDKey is the attribute Key conforming to the
+	// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id`
+	// property of request or response. Since protocol allows id to be int, string,
+	// `null` or missing (for notifications), value is expected to be cast to string
+	// for simplicity. Use empty string in case of `null` value. Omit entirely if
+	// this is a notification.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "10", "request-7", ""
+	RPCJSONRPCRequestIDKey = attribute.Key("rpc.jsonrpc.request_id")
+
+	// RPCJSONRPCVersionKey is the attribute Key conforming to the
+	// "rpc.jsonrpc.version" semantic conventions. It represents the protocol
+	// version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0
+	// doesn't specify this, the value can be omitted.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2.0", "1.0"
+	RPCJSONRPCVersionKey = attribute.Key("rpc.jsonrpc.version")
+
+	// RPCMessageCompressedSizeKey is the attribute Key conforming to the
+	// "rpc.message.compressed_size" semantic conventions. It represents the
+	// compressed size of the message in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	RPCMessageCompressedSizeKey = attribute.Key("rpc.message.compressed_size")
+
+	// RPCMessageIDKey is the attribute Key conforming to the "rpc.message.id"
+	// semantic conventions. It MUST be calculated as two different counters
+	// starting from `1` one for sent messages and one for received message..
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: This way we guarantee that the values will be consistent between
+	// different implementations.
+	RPCMessageIDKey = attribute.Key("rpc.message.id")
+
+	// RPCMessageTypeKey is the attribute Key conforming to the "rpc.message.type"
+	// semantic conventions. It represents the whether this is a received or sent
+	// message.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	RPCMessageTypeKey = attribute.Key("rpc.message.type")
+
+	// RPCMessageUncompressedSizeKey is the attribute Key conforming to the
+	// "rpc.message.uncompressed_size" semantic conventions. It represents the
+	// uncompressed size of the message in bytes.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	RPCMessageUncompressedSizeKey = attribute.Key("rpc.message.uncompressed_size")
+
+	// RPCMethodKey is the attribute Key conforming to the "rpc.method" semantic
+	// conventions. It represents the name of the (logical) method being called,
+	// must be equal to the $method part in the span name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: exampleMethod
+	// Note: This is the logical name of the method from the RPC interface
+	// perspective, which can be different from the name of any implementing
+	// method/function. The `code.function.name` attribute may be used to store the
+	// latter (e.g., method actually executing the call on the server side, RPC
+	// client stub method on the client side).
+	RPCMethodKey = attribute.Key("rpc.method")
+
+	// RPCServiceKey is the attribute Key conforming to the "rpc.service" semantic
+	// conventions. It represents the full (logical) name of the service being
+	// called, including its package name, if applicable.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: myservice.EchoService
+	// Note: This is the logical name of the service from the RPC interface
+	// perspective, which can be different from the name of any implementing class.
+	// The `code.namespace` attribute may be used to store the latter (despite the
+	// attribute name, it may include a class name; e.g., class with method actually
+	// executing the call on the server side, RPC client stub class on the client
+	// side).
+	RPCServiceKey = attribute.Key("rpc.service")
+
+	// RPCSystemKey is the attribute Key conforming to the "rpc.system" semantic
+	// conventions. It represents a string identifying the remoting system. See
+	// below for a list of well-known identifiers.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	RPCSystemKey = attribute.Key("rpc.system")
+)
+
+// RPCJSONRPCErrorCode returns an attribute KeyValue conforming to the
+// "rpc.jsonrpc.error_code" semantic conventions. It represents the `error.code`
+// property of response if it is an error response.
+func RPCJSONRPCErrorCode(val int) attribute.KeyValue {
+	return RPCJSONRPCErrorCodeKey.Int(val)
+}
+
+// RPCJSONRPCErrorMessage returns an attribute KeyValue conforming to the
+// "rpc.jsonrpc.error_message" semantic conventions. It represents the
+// `error.message` property of response if it is an error response.
+func RPCJSONRPCErrorMessage(val string) attribute.KeyValue {
+	return RPCJSONRPCErrorMessageKey.String(val)
+}
+
+// RPCJSONRPCRequestID returns an attribute KeyValue conforming to the
+// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id` property
+// of request or response. Since protocol allows id to be int, string, `null` or
+// missing (for notifications), value is expected to be cast to string for
+// simplicity. Use empty string in case of `null` value. Omit entirely if this is
+// a notification.
+func RPCJSONRPCRequestID(val string) attribute.KeyValue {
+	return RPCJSONRPCRequestIDKey.String(val)
+}
+
+// RPCJSONRPCVersion returns an attribute KeyValue conforming to the
+// "rpc.jsonrpc.version" semantic conventions. It represents the protocol version
+// as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 doesn't
+// specify this, the value can be omitted.
+func RPCJSONRPCVersion(val string) attribute.KeyValue {
+	return RPCJSONRPCVersionKey.String(val)
+}
+
+// RPCMessageCompressedSize returns an attribute KeyValue conforming to the
+// "rpc.message.compressed_size" semantic conventions. It represents the
+// compressed size of the message in bytes.
+func RPCMessageCompressedSize(val int) attribute.KeyValue {
+	return RPCMessageCompressedSizeKey.Int(val)
+}
+
+// RPCMessageID returns an attribute KeyValue conforming to the "rpc.message.id"
+// semantic conventions. It MUST be calculated as two different counters starting
+// from `1` one for sent messages and one for received message..
+func RPCMessageID(val int) attribute.KeyValue {
+	return RPCMessageIDKey.Int(val)
+}
+
+// RPCMessageUncompressedSize returns an attribute KeyValue conforming to the
+// "rpc.message.uncompressed_size" semantic conventions. It represents the
+// uncompressed size of the message in bytes.
+func RPCMessageUncompressedSize(val int) attribute.KeyValue {
+	return RPCMessageUncompressedSizeKey.Int(val)
+}
+
+// RPCMethod returns an attribute KeyValue conforming to the "rpc.method"
+// semantic conventions. It represents the name of the (logical) method being
+// called, must be equal to the $method part in the span name.
+func RPCMethod(val string) attribute.KeyValue {
+	return RPCMethodKey.String(val)
+}
+
+// RPCService returns an attribute KeyValue conforming to the "rpc.service"
+// semantic conventions. It represents the full (logical) name of the service
+// being called, including its package name, if applicable.
+func RPCService(val string) attribute.KeyValue {
+	return RPCServiceKey.String(val)
+}
+
+// Enum values for rpc.connect_rpc.error_code
+var (
+	// cancelled
+	// Stability: development
+	RPCConnectRPCErrorCodeCancelled = RPCConnectRPCErrorCodeKey.String("cancelled")
+	// unknown
+	// Stability: development
+	RPCConnectRPCErrorCodeUnknown = RPCConnectRPCErrorCodeKey.String("unknown")
+	// invalid_argument
+	// Stability: development
+	RPCConnectRPCErrorCodeInvalidArgument = RPCConnectRPCErrorCodeKey.String("invalid_argument")
+	// deadline_exceeded
+	// Stability: development
+	RPCConnectRPCErrorCodeDeadlineExceeded = RPCConnectRPCErrorCodeKey.String("deadline_exceeded")
+	// not_found
+	// Stability: development
+	RPCConnectRPCErrorCodeNotFound = RPCConnectRPCErrorCodeKey.String("not_found")
+	// already_exists
+	// Stability: development
+	RPCConnectRPCErrorCodeAlreadyExists = RPCConnectRPCErrorCodeKey.String("already_exists")
+	// permission_denied
+	// Stability: development
+	RPCConnectRPCErrorCodePermissionDenied = RPCConnectRPCErrorCodeKey.String("permission_denied")
+	// resource_exhausted
+	// Stability: development
+	RPCConnectRPCErrorCodeResourceExhausted = RPCConnectRPCErrorCodeKey.String("resource_exhausted")
+	// failed_precondition
+	// Stability: development
+	RPCConnectRPCErrorCodeFailedPrecondition = RPCConnectRPCErrorCodeKey.String("failed_precondition")
+	// aborted
+	// Stability: development
+	RPCConnectRPCErrorCodeAborted = RPCConnectRPCErrorCodeKey.String("aborted")
+	// out_of_range
+	// Stability: development
+	RPCConnectRPCErrorCodeOutOfRange = RPCConnectRPCErrorCodeKey.String("out_of_range")
+	// unimplemented
+	// Stability: development
+	RPCConnectRPCErrorCodeUnimplemented = RPCConnectRPCErrorCodeKey.String("unimplemented")
+	// internal
+	// Stability: development
+	RPCConnectRPCErrorCodeInternal = RPCConnectRPCErrorCodeKey.String("internal")
+	// unavailable
+	// Stability: development
+	RPCConnectRPCErrorCodeUnavailable = RPCConnectRPCErrorCodeKey.String("unavailable")
+	// data_loss
+	// Stability: development
+	RPCConnectRPCErrorCodeDataLoss = RPCConnectRPCErrorCodeKey.String("data_loss")
+	// unauthenticated
+	// Stability: development
+	RPCConnectRPCErrorCodeUnauthenticated = RPCConnectRPCErrorCodeKey.String("unauthenticated")
+)
+
+// Enum values for rpc.grpc.status_code
+var (
+	// OK
+	// Stability: development
+	RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0)
+	// CANCELLED
+	// Stability: development
+	RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1)
+	// UNKNOWN
+	// Stability: development
+	RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2)
+	// INVALID_ARGUMENT
+	// Stability: development
+	RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3)
+	// DEADLINE_EXCEEDED
+	// Stability: development
+	RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4)
+	// NOT_FOUND
+	// Stability: development
+	RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5)
+	// ALREADY_EXISTS
+	// Stability: development
+	RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6)
+	// PERMISSION_DENIED
+	// Stability: development
+	RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7)
+	// RESOURCE_EXHAUSTED
+	// Stability: development
+	RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8)
+	// FAILED_PRECONDITION
+	// Stability: development
+	RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9)
+	// ABORTED
+	// Stability: development
+	RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10)
+	// OUT_OF_RANGE
+	// Stability: development
+	RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11)
+	// UNIMPLEMENTED
+	// Stability: development
+	RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12)
+	// INTERNAL
+	// Stability: development
+	RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13)
+	// UNAVAILABLE
+	// Stability: development
+	RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14)
+	// DATA_LOSS
+	// Stability: development
+	RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15)
+	// UNAUTHENTICATED
+	// Stability: development
+	RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16)
+)
+
+// Enum values for rpc.message.type
+var (
+	// sent
+	// Stability: development
+	RPCMessageTypeSent = RPCMessageTypeKey.String("SENT")
+	// received
+	// Stability: development
+	RPCMessageTypeReceived = RPCMessageTypeKey.String("RECEIVED")
+)
+
+// Enum values for rpc.system
+var (
+	// gRPC
+	// Stability: development
+	RPCSystemGRPC = RPCSystemKey.String("grpc")
+	// Java RMI
+	// Stability: development
+	RPCSystemJavaRmi = RPCSystemKey.String("java_rmi")
+	// .NET WCF
+	// Stability: development
+	RPCSystemDotnetWcf = RPCSystemKey.String("dotnet_wcf")
+	// Apache Dubbo
+	// Stability: development
+	RPCSystemApacheDubbo = RPCSystemKey.String("apache_dubbo")
+	// Connect RPC
+	// Stability: development
+	RPCSystemConnectRPC = RPCSystemKey.String("connect_rpc")
+)
+
+// Namespace: security_rule
+const (
+	// SecurityRuleCategoryKey is the attribute Key conforming to the
+	// "security_rule.category" semantic conventions. It represents a categorization
+	// value keyword used by the entity using the rule for detection of this event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Attempted Information Leak"
+	SecurityRuleCategoryKey = attribute.Key("security_rule.category")
+
+	// SecurityRuleDescriptionKey is the attribute Key conforming to the
+	// "security_rule.description" semantic conventions. It represents the
+	// description of the rule generating the event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Block requests to public DNS over HTTPS / TLS protocols"
+	SecurityRuleDescriptionKey = attribute.Key("security_rule.description")
+
+	// SecurityRuleLicenseKey is the attribute Key conforming to the
+	// "security_rule.license" semantic conventions. It represents the name of the
+	// license under which the rule used to generate this event is made available.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Apache 2.0"
+	SecurityRuleLicenseKey = attribute.Key("security_rule.license")
+
+	// SecurityRuleNameKey is the attribute Key conforming to the
+	// "security_rule.name" semantic conventions. It represents the name of the rule
+	// or signature generating the event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "BLOCK_DNS_over_TLS"
+	SecurityRuleNameKey = attribute.Key("security_rule.name")
+
+	// SecurityRuleReferenceKey is the attribute Key conforming to the
+	// "security_rule.reference" semantic conventions. It represents the reference
+	// URL to additional information about the rule used to generate this event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "https://en.wikipedia.org/wiki/DNS_over_TLS"
+	// Note: The URL can point to the vendor’s documentation about the rule. If
+	// that’s not available, it can also be a link to a more general page
+	// describing this type of alert.
+	SecurityRuleReferenceKey = attribute.Key("security_rule.reference")
+
+	// SecurityRuleRulesetNameKey is the attribute Key conforming to the
+	// "security_rule.ruleset.name" semantic conventions. It represents the name of
+	// the ruleset, policy, group, or parent category in which the rule used to
+	// generate this event is a member.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Standard_Protocol_Filters"
+	SecurityRuleRulesetNameKey = attribute.Key("security_rule.ruleset.name")
+
+	// SecurityRuleUUIDKey is the attribute Key conforming to the
+	// "security_rule.uuid" semantic conventions. It represents a rule ID that is
+	// unique within the scope of a set or group of agents, observers, or other
+	// entities using the rule for detection of this event.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "550e8400-e29b-41d4-a716-446655440000", "1100110011"
+	SecurityRuleUUIDKey = attribute.Key("security_rule.uuid")
+
+	// SecurityRuleVersionKey is the attribute Key conforming to the
+	// "security_rule.version" semantic conventions. It represents the version /
+	// revision of the rule being used for analysis.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1.0.0"
+	SecurityRuleVersionKey = attribute.Key("security_rule.version")
+)
+
+// SecurityRuleCategory returns an attribute KeyValue conforming to the
+// "security_rule.category" semantic conventions. It represents a categorization
+// value keyword used by the entity using the rule for detection of this event.
+func SecurityRuleCategory(val string) attribute.KeyValue {
+	return SecurityRuleCategoryKey.String(val)
+}
+
+// SecurityRuleDescription returns an attribute KeyValue conforming to the
+// "security_rule.description" semantic conventions. It represents the
+// description of the rule generating the event.
+func SecurityRuleDescription(val string) attribute.KeyValue {
+	return SecurityRuleDescriptionKey.String(val)
+}
+
+// SecurityRuleLicense returns an attribute KeyValue conforming to the
+// "security_rule.license" semantic conventions. It represents the name of the
+// license under which the rule used to generate this event is made available.
+func SecurityRuleLicense(val string) attribute.KeyValue {
+	return SecurityRuleLicenseKey.String(val)
+}
+
+// SecurityRuleName returns an attribute KeyValue conforming to the
+// "security_rule.name" semantic conventions. It represents the name of the rule
+// or signature generating the event.
+func SecurityRuleName(val string) attribute.KeyValue {
+	return SecurityRuleNameKey.String(val)
+}
+
+// SecurityRuleReference returns an attribute KeyValue conforming to the
+// "security_rule.reference" semantic conventions. It represents the reference
+// URL to additional information about the rule used to generate this event.
+func SecurityRuleReference(val string) attribute.KeyValue {
+	return SecurityRuleReferenceKey.String(val)
+}
+
+// SecurityRuleRulesetName returns an attribute KeyValue conforming to the
+// "security_rule.ruleset.name" semantic conventions. It represents the name of
+// the ruleset, policy, group, or parent category in which the rule used to
+// generate this event is a member.
+func SecurityRuleRulesetName(val string) attribute.KeyValue {
+	return SecurityRuleRulesetNameKey.String(val)
+}
+
+// SecurityRuleUUID returns an attribute KeyValue conforming to the
+// "security_rule.uuid" semantic conventions. It represents a rule ID that is
+// unique within the scope of a set or group of agents, observers, or other
+// entities using the rule for detection of this event.
+func SecurityRuleUUID(val string) attribute.KeyValue {
+	return SecurityRuleUUIDKey.String(val)
+}
+
+// SecurityRuleVersion returns an attribute KeyValue conforming to the
+// "security_rule.version" semantic conventions. It represents the version /
+// revision of the rule being used for analysis.
+func SecurityRuleVersion(val string) attribute.KeyValue {
+	return SecurityRuleVersionKey.String(val)
+}
+
+// Namespace: server
+const (
+	// ServerAddressKey is the attribute Key conforming to the "server.address"
+	// semantic conventions. It represents the server domain name if available
+	// without reverse DNS lookup; otherwise, IP address or Unix domain socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "example.com", "10.1.2.80", "/tmp/my.sock"
+	// Note: When observed from the client side, and when communicating through an
+	// intermediary, `server.address` SHOULD represent the server address behind any
+	// intermediaries, for example proxies, if it's available.
+	ServerAddressKey = attribute.Key("server.address")
+
+	// ServerPortKey is the attribute Key conforming to the "server.port" semantic
+	// conventions. It represents the server port number.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: 80, 8080, 443
+	// Note: When observed from the client side, and when communicating through an
+	// intermediary, `server.port` SHOULD represent the server port behind any
+	// intermediaries, for example proxies, if it's available.
+	ServerPortKey = attribute.Key("server.port")
+)
+
+// ServerAddress returns an attribute KeyValue conforming to the "server.address"
+// semantic conventions. It represents the server domain name if available
+// without reverse DNS lookup; otherwise, IP address or Unix domain socket name.
+func ServerAddress(val string) attribute.KeyValue {
+	return ServerAddressKey.String(val)
+}
+
+// ServerPort returns an attribute KeyValue conforming to the "server.port"
+// semantic conventions. It represents the server port number.
+func ServerPort(val int) attribute.KeyValue {
+	return ServerPortKey.Int(val)
+}
+
+// Namespace: service
+const (
+	// ServiceInstanceIDKey is the attribute Key conforming to the
+	// "service.instance.id" semantic conventions. It represents the string ID of
+	// the service instance.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "627cc493-f310-47de-96bd-71410b7dec09"
+	// Note: MUST be unique for each instance of the same
+	// `service.namespace,service.name` pair (in other words
+	// `service.namespace,service.name,service.instance.id` triplet MUST be globally
+	// unique). The ID helps to
+	// distinguish instances of the same service that exist at the same time (e.g.
+	// instances of a horizontally scaled
+	// service).
+	//
+	// Implementations, such as SDKs, are recommended to generate a random Version 1
+	// or Version 4 [RFC
+	// 4122] UUID, but are free to use an inherent unique ID as
+	// the source of
+	// this value if stability is desirable. In that case, the ID SHOULD be used as
+	// source of a UUID Version 5 and
+	// SHOULD use the following UUID as the namespace:
+	// `4d63009a-8d0f-11ee-aad7-4c796ed8e320`.
+	//
+	// UUIDs are typically recommended, as only an opaque value for the purposes of
+	// identifying a service instance is
+	// needed. Similar to what can be seen in the man page for the
+	// [`/etc/machine-id`] file, the underlying
+	// data, such as pod name and namespace should be treated as confidential, being
+	// the user's choice to expose it
+	// or not via another resource attribute.
+	//
+	// For applications running behind an application server (like unicorn), we do
+	// not recommend using one identifier
+	// for all processes participating in the application. Instead, it's recommended
+	// each division (e.g. a worker
+	// thread in unicorn) to have its own instance.id.
+	//
+	// It's not recommended for a Collector to set `service.instance.id` if it can't
+	// unambiguously determine the
+	// service instance that is generating that telemetry. For instance, creating an
+	// UUID based on `pod.name` will
+	// likely be wrong, as the Collector might not know from which container within
+	// that pod the telemetry originated.
+	// However, Collectors can set the `service.instance.id` if they can
+	// unambiguously determine the service instance
+	// for that telemetry. This is typically the case for scraping receivers, as
+	// they know the target address and
+	// port.
+	//
+	// [RFC
+	// 4122]: https://www.ietf.org/rfc/rfc4122.txt
+	// [`/etc/machine-id`]: https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
+	ServiceInstanceIDKey = attribute.Key("service.instance.id")
+
+	// ServiceNameKey is the attribute Key conforming to the "service.name" semantic
+	// conventions. It represents the logical name of the service.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "shoppingcart"
+	// Note: MUST be the same for all instances of horizontally scaled services. If
+	// the value was not specified, SDKs MUST fallback to `unknown_service:`
+	// concatenated with [`process.executable.name`], e.g. `unknown_service:bash`.
+	// If `process.executable.name` is not available, the value MUST be set to
+	// `unknown_service`.
+	//
+	// [`process.executable.name`]: process.md
+	ServiceNameKey = attribute.Key("service.name")
+
+	// ServiceNamespaceKey is the attribute Key conforming to the
+	// "service.namespace" semantic conventions. It represents a namespace for
+	// `service.name`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Shop"
+	// Note: A string value having a meaning that helps to distinguish a group of
+	// services, for example the team name that owns a group of services.
+	// `service.name` is expected to be unique within the same namespace. If
+	// `service.namespace` is not specified in the Resource then `service.name` is
+	// expected to be unique for all services that have no explicit namespace
+	// defined (so the empty/unspecified namespace is simply one more valid
+	// namespace). Zero-length namespace string is assumed equal to unspecified
+	// namespace.
+	ServiceNamespaceKey = attribute.Key("service.namespace")
+
+	// ServiceVersionKey is the attribute Key conforming to the "service.version"
+	// semantic conventions. It represents the version string of the service API or
+	// implementation. The format is not defined by these conventions.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "2.0.0", "a01dbef8a"
+	ServiceVersionKey = attribute.Key("service.version")
+)
+
+// ServiceInstanceID returns an attribute KeyValue conforming to the
+// "service.instance.id" semantic conventions. It represents the string ID of the
+// service instance.
+func ServiceInstanceID(val string) attribute.KeyValue {
+	return ServiceInstanceIDKey.String(val)
+}
+
+// ServiceName returns an attribute KeyValue conforming to the "service.name"
+// semantic conventions. It represents the logical name of the service.
+func ServiceName(val string) attribute.KeyValue {
+	return ServiceNameKey.String(val)
+}
+
+// ServiceNamespace returns an attribute KeyValue conforming to the
+// "service.namespace" semantic conventions. It represents a namespace for
+// `service.name`.
+func ServiceNamespace(val string) attribute.KeyValue {
+	return ServiceNamespaceKey.String(val)
+}
+
+// ServiceVersion returns an attribute KeyValue conforming to the
+// "service.version" semantic conventions. It represents the version string of
+// the service API or implementation. The format is not defined by these
+// conventions.
+func ServiceVersion(val string) attribute.KeyValue {
+	return ServiceVersionKey.String(val)
+}
+
+// Namespace: session
+const (
+	// SessionIDKey is the attribute Key conforming to the "session.id" semantic
+	// conventions. It represents a unique id to identify a session.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 00112233-4455-6677-8899-aabbccddeeff
+	SessionIDKey = attribute.Key("session.id")
+
+	// SessionPreviousIDKey is the attribute Key conforming to the
+	// "session.previous_id" semantic conventions. It represents the previous
+	// `session.id` for this user, when known.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 00112233-4455-6677-8899-aabbccddeeff
+	SessionPreviousIDKey = attribute.Key("session.previous_id")
+)
+
+// SessionID returns an attribute KeyValue conforming to the "session.id"
+// semantic conventions. It represents a unique id to identify a session.
+func SessionID(val string) attribute.KeyValue {
+	return SessionIDKey.String(val)
+}
+
+// SessionPreviousID returns an attribute KeyValue conforming to the
+// "session.previous_id" semantic conventions. It represents the previous
+// `session.id` for this user, when known.
+func SessionPreviousID(val string) attribute.KeyValue {
+	return SessionPreviousIDKey.String(val)
+}
+
+// Namespace: signalr
+const (
+	// SignalRConnectionStatusKey is the attribute Key conforming to the
+	// "signalr.connection.status" semantic conventions. It represents the signalR
+	// HTTP connection closure status.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "app_shutdown", "timeout"
+	SignalRConnectionStatusKey = attribute.Key("signalr.connection.status")
+
+	// SignalRTransportKey is the attribute Key conforming to the
+	// "signalr.transport" semantic conventions. It represents the
+	// [SignalR transport type].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "web_sockets", "long_polling"
+	//
+	// [SignalR transport type]: https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md
+	SignalRTransportKey = attribute.Key("signalr.transport")
+)
+
+// Enum values for signalr.connection.status
+var (
+	// The connection was closed normally.
+	// Stability: stable
+	SignalRConnectionStatusNormalClosure = SignalRConnectionStatusKey.String("normal_closure")
+	// The connection was closed due to a timeout.
+	// Stability: stable
+	SignalRConnectionStatusTimeout = SignalRConnectionStatusKey.String("timeout")
+	// The connection was closed because the app is shutting down.
+	// Stability: stable
+	SignalRConnectionStatusAppShutdown = SignalRConnectionStatusKey.String("app_shutdown")
+)
+
+// Enum values for signalr.transport
+var (
+	// ServerSentEvents protocol
+	// Stability: stable
+	SignalRTransportServerSentEvents = SignalRTransportKey.String("server_sent_events")
+	// LongPolling protocol
+	// Stability: stable
+	SignalRTransportLongPolling = SignalRTransportKey.String("long_polling")
+	// WebSockets protocol
+	// Stability: stable
+	SignalRTransportWebSockets = SignalRTransportKey.String("web_sockets")
+)
+
+// Namespace: source
+const (
+	// SourceAddressKey is the attribute Key conforming to the "source.address"
+	// semantic conventions. It represents the source address - domain name if
+	// available without reverse DNS lookup; otherwise, IP address or Unix domain
+	// socket name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "source.example.com", "10.1.2.80", "/tmp/my.sock"
+	// Note: When observed from the destination side, and when communicating through
+	// an intermediary, `source.address` SHOULD represent the source address behind
+	// any intermediaries, for example proxies, if it's available.
+	SourceAddressKey = attribute.Key("source.address")
+
+	// SourcePortKey is the attribute Key conforming to the "source.port" semantic
+	// conventions. It represents the source port number.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 3389, 2888
+	SourcePortKey = attribute.Key("source.port")
+)
+
+// SourceAddress returns an attribute KeyValue conforming to the "source.address"
+// semantic conventions. It represents the source address - domain name if
+// available without reverse DNS lookup; otherwise, IP address or Unix domain
+// socket name.
+func SourceAddress(val string) attribute.KeyValue {
+	return SourceAddressKey.String(val)
+}
+
+// SourcePort returns an attribute KeyValue conforming to the "source.port"
+// semantic conventions. It represents the source port number.
+func SourcePort(val int) attribute.KeyValue {
+	return SourcePortKey.Int(val)
+}
+
+// Namespace: system
+const (
+	// SystemCPULogicalNumberKey is the attribute Key conforming to the
+	// "system.cpu.logical_number" semantic conventions. It represents the
+	// deprecated, use `cpu.logical_number` instead.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 1
+	SystemCPULogicalNumberKey = attribute.Key("system.cpu.logical_number")
+
+	// SystemDeviceKey is the attribute Key conforming to the "system.device"
+	// semantic conventions. It represents the device identifier.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "(identifier)"
+	SystemDeviceKey = attribute.Key("system.device")
+
+	// SystemFilesystemModeKey is the attribute Key conforming to the
+	// "system.filesystem.mode" semantic conventions. It represents the filesystem
+	// mode.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "rw, ro"
+	SystemFilesystemModeKey = attribute.Key("system.filesystem.mode")
+
+	// SystemFilesystemMountpointKey is the attribute Key conforming to the
+	// "system.filesystem.mountpoint" semantic conventions. It represents the
+	// filesystem mount path.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/mnt/data"
+	SystemFilesystemMountpointKey = attribute.Key("system.filesystem.mountpoint")
+
+	// SystemFilesystemStateKey is the attribute Key conforming to the
+	// "system.filesystem.state" semantic conventions. It represents the filesystem
+	// state.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "used"
+	SystemFilesystemStateKey = attribute.Key("system.filesystem.state")
+
+	// SystemFilesystemTypeKey is the attribute Key conforming to the
+	// "system.filesystem.type" semantic conventions. It represents the filesystem
+	// type.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "ext4"
+	SystemFilesystemTypeKey = attribute.Key("system.filesystem.type")
+
+	// SystemMemoryStateKey is the attribute Key conforming to the
+	// "system.memory.state" semantic conventions. It represents the memory state.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "free", "cached"
+	SystemMemoryStateKey = attribute.Key("system.memory.state")
+
+	// SystemPagingDirectionKey is the attribute Key conforming to the
+	// "system.paging.direction" semantic conventions. It represents the paging
+	// access direction.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "in"
+	SystemPagingDirectionKey = attribute.Key("system.paging.direction")
+
+	// SystemPagingStateKey is the attribute Key conforming to the
+	// "system.paging.state" semantic conventions. It represents the memory paging
+	// state.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "free"
+	SystemPagingStateKey = attribute.Key("system.paging.state")
+
+	// SystemPagingTypeKey is the attribute Key conforming to the
+	// "system.paging.type" semantic conventions. It represents the memory paging
+	// type.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "minor"
+	SystemPagingTypeKey = attribute.Key("system.paging.type")
+
+	// SystemProcessStatusKey is the attribute Key conforming to the
+	// "system.process.status" semantic conventions. It represents the process
+	// state, e.g., [Linux Process State Codes].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "running"
+	//
+	// [Linux Process State Codes]: https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES
+	SystemProcessStatusKey = attribute.Key("system.process.status")
+)
+
+// SystemCPULogicalNumber returns an attribute KeyValue conforming to the
+// "system.cpu.logical_number" semantic conventions. It represents the
+// deprecated, use `cpu.logical_number` instead.
+func SystemCPULogicalNumber(val int) attribute.KeyValue {
+	return SystemCPULogicalNumberKey.Int(val)
+}
+
+// SystemDevice returns an attribute KeyValue conforming to the "system.device"
+// semantic conventions. It represents the device identifier.
+func SystemDevice(val string) attribute.KeyValue {
+	return SystemDeviceKey.String(val)
+}
+
+// SystemFilesystemMode returns an attribute KeyValue conforming to the
+// "system.filesystem.mode" semantic conventions. It represents the filesystem
+// mode.
+func SystemFilesystemMode(val string) attribute.KeyValue {
+	return SystemFilesystemModeKey.String(val)
+}
+
+// SystemFilesystemMountpoint returns an attribute KeyValue conforming to the
+// "system.filesystem.mountpoint" semantic conventions. It represents the
+// filesystem mount path.
+func SystemFilesystemMountpoint(val string) attribute.KeyValue {
+	return SystemFilesystemMountpointKey.String(val)
+}
+
+// Enum values for system.filesystem.state
+var (
+	// used
+	// Stability: development
+	SystemFilesystemStateUsed = SystemFilesystemStateKey.String("used")
+	// free
+	// Stability: development
+	SystemFilesystemStateFree = SystemFilesystemStateKey.String("free")
+	// reserved
+	// Stability: development
+	SystemFilesystemStateReserved = SystemFilesystemStateKey.String("reserved")
+)
+
+// Enum values for system.filesystem.type
+var (
+	// fat32
+	// Stability: development
+	SystemFilesystemTypeFat32 = SystemFilesystemTypeKey.String("fat32")
+	// exfat
+	// Stability: development
+	SystemFilesystemTypeExfat = SystemFilesystemTypeKey.String("exfat")
+	// ntfs
+	// Stability: development
+	SystemFilesystemTypeNtfs = SystemFilesystemTypeKey.String("ntfs")
+	// refs
+	// Stability: development
+	SystemFilesystemTypeRefs = SystemFilesystemTypeKey.String("refs")
+	// hfsplus
+	// Stability: development
+	SystemFilesystemTypeHfsplus = SystemFilesystemTypeKey.String("hfsplus")
+	// ext4
+	// Stability: development
+	SystemFilesystemTypeExt4 = SystemFilesystemTypeKey.String("ext4")
+)
+
+// Enum values for system.memory.state
+var (
+	// used
+	// Stability: development
+	SystemMemoryStateUsed = SystemMemoryStateKey.String("used")
+	// free
+	// Stability: development
+	SystemMemoryStateFree = SystemMemoryStateKey.String("free")
+	// Deprecated: Removed, report shared memory usage with
+	// `metric.system.memory.shared` metric.
+	SystemMemoryStateShared = SystemMemoryStateKey.String("shared")
+	// buffers
+	// Stability: development
+	SystemMemoryStateBuffers = SystemMemoryStateKey.String("buffers")
+	// cached
+	// Stability: development
+	SystemMemoryStateCached = SystemMemoryStateKey.String("cached")
+)
+
+// Enum values for system.paging.direction
+var (
+	// in
+	// Stability: development
+	SystemPagingDirectionIn = SystemPagingDirectionKey.String("in")
+	// out
+	// Stability: development
+	SystemPagingDirectionOut = SystemPagingDirectionKey.String("out")
+)
+
+// Enum values for system.paging.state
+var (
+	// used
+	// Stability: development
+	SystemPagingStateUsed = SystemPagingStateKey.String("used")
+	// free
+	// Stability: development
+	SystemPagingStateFree = SystemPagingStateKey.String("free")
+)
+
+// Enum values for system.paging.type
+var (
+	// major
+	// Stability: development
+	SystemPagingTypeMajor = SystemPagingTypeKey.String("major")
+	// minor
+	// Stability: development
+	SystemPagingTypeMinor = SystemPagingTypeKey.String("minor")
+)
+
+// Enum values for system.process.status
+var (
+	// running
+	// Stability: development
+	SystemProcessStatusRunning = SystemProcessStatusKey.String("running")
+	// sleeping
+	// Stability: development
+	SystemProcessStatusSleeping = SystemProcessStatusKey.String("sleeping")
+	// stopped
+	// Stability: development
+	SystemProcessStatusStopped = SystemProcessStatusKey.String("stopped")
+	// defunct
+	// Stability: development
+	SystemProcessStatusDefunct = SystemProcessStatusKey.String("defunct")
+)
+
+// Namespace: telemetry
+const (
+	// TelemetryDistroNameKey is the attribute Key conforming to the
+	// "telemetry.distro.name" semantic conventions. It represents the name of the
+	// auto instrumentation agent or distribution, if used.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "parts-unlimited-java"
+	// Note: Official auto instrumentation agents and distributions SHOULD set the
+	// `telemetry.distro.name` attribute to
+	// a string starting with `opentelemetry-`, e.g.
+	// `opentelemetry-java-instrumentation`.
+	TelemetryDistroNameKey = attribute.Key("telemetry.distro.name")
+
+	// TelemetryDistroVersionKey is the attribute Key conforming to the
+	// "telemetry.distro.version" semantic conventions. It represents the version
+	// string of the auto instrumentation agent or distribution, if used.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1.2.3"
+	TelemetryDistroVersionKey = attribute.Key("telemetry.distro.version")
+
+	// TelemetrySDKLanguageKey is the attribute Key conforming to the
+	// "telemetry.sdk.language" semantic conventions. It represents the language of
+	// the telemetry SDK.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples:
+	TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language")
+
+	// TelemetrySDKNameKey is the attribute Key conforming to the
+	// "telemetry.sdk.name" semantic conventions. It represents the name of the
+	// telemetry SDK as defined above.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "opentelemetry"
+	// Note: The OpenTelemetry SDK MUST set the `telemetry.sdk.name` attribute to
+	// `opentelemetry`.
+	// If another SDK, like a fork or a vendor-provided implementation, is used,
+	// this SDK MUST set the
+	// `telemetry.sdk.name` attribute to the fully-qualified class or module name of
+	// this SDK's main entry point
+	// or another suitable identifier depending on the language.
+	// The identifier `opentelemetry` is reserved and MUST NOT be used in this case.
+	// All custom identifiers SHOULD be stable across different versions of an
+	// implementation.
+	TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name")
+
+	// TelemetrySDKVersionKey is the attribute Key conforming to the
+	// "telemetry.sdk.version" semantic conventions. It represents the version
+	// string of the telemetry SDK.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "1.2.3"
+	TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version")
+)
+
+// TelemetryDistroName returns an attribute KeyValue conforming to the
+// "telemetry.distro.name" semantic conventions. It represents the name of the
+// auto instrumentation agent or distribution, if used.
+func TelemetryDistroName(val string) attribute.KeyValue {
+	return TelemetryDistroNameKey.String(val)
+}
+
+// TelemetryDistroVersion returns an attribute KeyValue conforming to the
+// "telemetry.distro.version" semantic conventions. It represents the version
+// string of the auto instrumentation agent or distribution, if used.
+func TelemetryDistroVersion(val string) attribute.KeyValue {
+	return TelemetryDistroVersionKey.String(val)
+}
+
+// TelemetrySDKName returns an attribute KeyValue conforming to the
+// "telemetry.sdk.name" semantic conventions. It represents the name of the
+// telemetry SDK as defined above.
+func TelemetrySDKName(val string) attribute.KeyValue {
+	return TelemetrySDKNameKey.String(val)
+}
+
+// TelemetrySDKVersion returns an attribute KeyValue conforming to the
+// "telemetry.sdk.version" semantic conventions. It represents the version string
+// of the telemetry SDK.
+func TelemetrySDKVersion(val string) attribute.KeyValue {
+	return TelemetrySDKVersionKey.String(val)
+}
+
+// Enum values for telemetry.sdk.language
+var (
+	// cpp
+	// Stability: stable
+	TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp")
+	// dotnet
+	// Stability: stable
+	TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet")
+	// erlang
+	// Stability: stable
+	TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang")
+	// go
+	// Stability: stable
+	TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go")
+	// java
+	// Stability: stable
+	TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java")
+	// nodejs
+	// Stability: stable
+	TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs")
+	// php
+	// Stability: stable
+	TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php")
+	// python
+	// Stability: stable
+	TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python")
+	// ruby
+	// Stability: stable
+	TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby")
+	// rust
+	// Stability: stable
+	TelemetrySDKLanguageRust = TelemetrySDKLanguageKey.String("rust")
+	// swift
+	// Stability: stable
+	TelemetrySDKLanguageSwift = TelemetrySDKLanguageKey.String("swift")
+	// webjs
+	// Stability: stable
+	TelemetrySDKLanguageWebJS = TelemetrySDKLanguageKey.String("webjs")
+)
+
+// Namespace: test
+const (
+	// TestCaseNameKey is the attribute Key conforming to the "test.case.name"
+	// semantic conventions. It represents the fully qualified human readable name
+	// of the [test case].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "org.example.TestCase1.test1", "example/tests/TestCase1.test1",
+	// "ExampleTestCase1_test1"
+	//
+	// [test case]: https://wikipedia.org/wiki/Test_case
+	TestCaseNameKey = attribute.Key("test.case.name")
+
+	// TestCaseResultStatusKey is the attribute Key conforming to the
+	// "test.case.result.status" semantic conventions. It represents the status of
+	// the actual test case result from test execution.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "pass", "fail"
+	TestCaseResultStatusKey = attribute.Key("test.case.result.status")
+
+	// TestSuiteNameKey is the attribute Key conforming to the "test.suite.name"
+	// semantic conventions. It represents the human readable name of a [test suite]
+	// .
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "TestSuite1"
+	//
+	// [test suite]: https://wikipedia.org/wiki/Test_suite
+	TestSuiteNameKey = attribute.Key("test.suite.name")
+
+	// TestSuiteRunStatusKey is the attribute Key conforming to the
+	// "test.suite.run.status" semantic conventions. It represents the status of the
+	// test suite run.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "success", "failure", "skipped", "aborted", "timed_out",
+	// "in_progress"
+	TestSuiteRunStatusKey = attribute.Key("test.suite.run.status")
+)
+
+// TestCaseName returns an attribute KeyValue conforming to the "test.case.name"
+// semantic conventions. It represents the fully qualified human readable name of
+// the [test case].
+//
+// [test case]: https://wikipedia.org/wiki/Test_case
+func TestCaseName(val string) attribute.KeyValue {
+	return TestCaseNameKey.String(val)
+}
+
+// TestSuiteName returns an attribute KeyValue conforming to the
+// "test.suite.name" semantic conventions. It represents the human readable name
+// of a [test suite].
+//
+// [test suite]: https://wikipedia.org/wiki/Test_suite
+func TestSuiteName(val string) attribute.KeyValue {
+	return TestSuiteNameKey.String(val)
+}
+
+// Enum values for test.case.result.status
+var (
+	// pass
+	// Stability: development
+	TestCaseResultStatusPass = TestCaseResultStatusKey.String("pass")
+	// fail
+	// Stability: development
+	TestCaseResultStatusFail = TestCaseResultStatusKey.String("fail")
+)
+
+// Enum values for test.suite.run.status
+var (
+	// success
+	// Stability: development
+	TestSuiteRunStatusSuccess = TestSuiteRunStatusKey.String("success")
+	// failure
+	// Stability: development
+	TestSuiteRunStatusFailure = TestSuiteRunStatusKey.String("failure")
+	// skipped
+	// Stability: development
+	TestSuiteRunStatusSkipped = TestSuiteRunStatusKey.String("skipped")
+	// aborted
+	// Stability: development
+	TestSuiteRunStatusAborted = TestSuiteRunStatusKey.String("aborted")
+	// timed_out
+	// Stability: development
+	TestSuiteRunStatusTimedOut = TestSuiteRunStatusKey.String("timed_out")
+	// in_progress
+	// Stability: development
+	TestSuiteRunStatusInProgress = TestSuiteRunStatusKey.String("in_progress")
+)
+
+// Namespace: thread
+const (
+	// ThreadIDKey is the attribute Key conforming to the "thread.id" semantic
+	// conventions. It represents the current "managed" thread ID (as opposed to OS
+	// thread ID).
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	ThreadIDKey = attribute.Key("thread.id")
+
+	// ThreadNameKey is the attribute Key conforming to the "thread.name" semantic
+	// conventions. It represents the current thread name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: main
+	ThreadNameKey = attribute.Key("thread.name")
+)
+
+// ThreadID returns an attribute KeyValue conforming to the "thread.id" semantic
+// conventions. It represents the current "managed" thread ID (as opposed to OS
+// thread ID).
+func ThreadID(val int) attribute.KeyValue {
+	return ThreadIDKey.Int(val)
+}
+
+// ThreadName returns an attribute KeyValue conforming to the "thread.name"
+// semantic conventions. It represents the current thread name.
+func ThreadName(val string) attribute.KeyValue {
+	return ThreadNameKey.String(val)
+}
+
+// Namespace: tls
+const (
+	// TLSCipherKey is the attribute Key conforming to the "tls.cipher" semantic
+	// conventions. It represents the string indicating the [cipher] used during the
+	// current connection.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+	// "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
+	// Note: The values allowed for `tls.cipher` MUST be one of the `Descriptions`
+	// of the [registered TLS Cipher Suits].
+	//
+	// [cipher]: https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5
+	// [registered TLS Cipher Suits]: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4
+	TLSCipherKey = attribute.Key("tls.cipher")
+
+	// TLSClientCertificateKey is the attribute Key conforming to the
+	// "tls.client.certificate" semantic conventions. It represents the PEM-encoded
+	// stand-alone certificate offered by the client. This is usually
+	// mutually-exclusive of `client.certificate_chain` since this value also exists
+	// in that list.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "MII..."
+	TLSClientCertificateKey = attribute.Key("tls.client.certificate")
+
+	// TLSClientCertificateChainKey is the attribute Key conforming to the
+	// "tls.client.certificate_chain" semantic conventions. It represents the array
+	// of PEM-encoded certificates that make up the certificate chain offered by the
+	// client. This is usually mutually-exclusive of `client.certificate` since that
+	// value should be the first certificate in the chain.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "MII...", "MI..."
+	TLSClientCertificateChainKey = attribute.Key("tls.client.certificate_chain")
+
+	// TLSClientHashMd5Key is the attribute Key conforming to the
+	// "tls.client.hash.md5" semantic conventions. It represents the certificate
+	// fingerprint using the MD5 digest of DER-encoded version of certificate
+	// offered by the client. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC"
+	TLSClientHashMd5Key = attribute.Key("tls.client.hash.md5")
+
+	// TLSClientHashSha1Key is the attribute Key conforming to the
+	// "tls.client.hash.sha1" semantic conventions. It represents the certificate
+	// fingerprint using the SHA1 digest of DER-encoded version of certificate
+	// offered by the client. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "9E393D93138888D288266C2D915214D1D1CCEB2A"
+	TLSClientHashSha1Key = attribute.Key("tls.client.hash.sha1")
+
+	// TLSClientHashSha256Key is the attribute Key conforming to the
+	// "tls.client.hash.sha256" semantic conventions. It represents the certificate
+	// fingerprint using the SHA256 digest of DER-encoded version of certificate
+	// offered by the client. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0"
+	TLSClientHashSha256Key = attribute.Key("tls.client.hash.sha256")
+
+	// TLSClientIssuerKey is the attribute Key conforming to the "tls.client.issuer"
+	// semantic conventions. It represents the distinguished name of [subject] of
+	// the issuer of the x.509 certificate presented by the client.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com"
+	//
+	// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
+	TLSClientIssuerKey = attribute.Key("tls.client.issuer")
+
+	// TLSClientJa3Key is the attribute Key conforming to the "tls.client.ja3"
+	// semantic conventions. It represents a hash that identifies clients based on
+	// how they perform an SSL/TLS handshake.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "d4e5b18d6b55c71272893221c96ba240"
+	TLSClientJa3Key = attribute.Key("tls.client.ja3")
+
+	// TLSClientNotAfterKey is the attribute Key conforming to the
+	// "tls.client.not_after" semantic conventions. It represents the date/Time
+	// indicating when client certificate is no longer considered valid.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T00:00:00.000Z"
+	TLSClientNotAfterKey = attribute.Key("tls.client.not_after")
+
+	// TLSClientNotBeforeKey is the attribute Key conforming to the
+	// "tls.client.not_before" semantic conventions. It represents the date/Time
+	// indicating when client certificate is first considered valid.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1970-01-01T00:00:00.000Z"
+	TLSClientNotBeforeKey = attribute.Key("tls.client.not_before")
+
+	// TLSClientSubjectKey is the attribute Key conforming to the
+	// "tls.client.subject" semantic conventions. It represents the distinguished
+	// name of subject of the x.509 certificate presented by the client.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CN=myclient, OU=Documentation Team, DC=example, DC=com"
+	TLSClientSubjectKey = attribute.Key("tls.client.subject")
+
+	// TLSClientSupportedCiphersKey is the attribute Key conforming to the
+	// "tls.client.supported_ciphers" semantic conventions. It represents the array
+	// of ciphers offered by the client during the client hello.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+	// "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
+	TLSClientSupportedCiphersKey = attribute.Key("tls.client.supported_ciphers")
+
+	// TLSCurveKey is the attribute Key conforming to the "tls.curve" semantic
+	// conventions. It represents the string indicating the curve used for the given
+	// cipher, when applicable.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "secp256r1"
+	TLSCurveKey = attribute.Key("tls.curve")
+
+	// TLSEstablishedKey is the attribute Key conforming to the "tls.established"
+	// semantic conventions. It represents the boolean flag indicating if the TLS
+	// negotiation was successful and transitioned to an encrypted tunnel.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: true
+	TLSEstablishedKey = attribute.Key("tls.established")
+
+	// TLSNextProtocolKey is the attribute Key conforming to the "tls.next_protocol"
+	// semantic conventions. It represents the string indicating the protocol being
+	// tunneled. Per the values in the [IANA registry], this string should be lower
+	// case.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "http/1.1"
+	//
+	// [IANA registry]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
+	TLSNextProtocolKey = attribute.Key("tls.next_protocol")
+
+	// TLSProtocolNameKey is the attribute Key conforming to the "tls.protocol.name"
+	// semantic conventions. It represents the normalized lowercase protocol name
+	// parsed from original string of the negotiated [SSL/TLS protocol version].
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	//
+	// [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values
+	TLSProtocolNameKey = attribute.Key("tls.protocol.name")
+
+	// TLSProtocolVersionKey is the attribute Key conforming to the
+	// "tls.protocol.version" semantic conventions. It represents the numeric part
+	// of the version parsed from the original string of the negotiated
+	// [SSL/TLS protocol version].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1.2", "3"
+	//
+	// [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values
+	TLSProtocolVersionKey = attribute.Key("tls.protocol.version")
+
+	// TLSResumedKey is the attribute Key conforming to the "tls.resumed" semantic
+	// conventions. It represents the boolean flag indicating if this TLS connection
+	// was resumed from an existing TLS negotiation.
+	//
+	// Type: boolean
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: true
+	TLSResumedKey = attribute.Key("tls.resumed")
+
+	// TLSServerCertificateKey is the attribute Key conforming to the
+	// "tls.server.certificate" semantic conventions. It represents the PEM-encoded
+	// stand-alone certificate offered by the server. This is usually
+	// mutually-exclusive of `server.certificate_chain` since this value also exists
+	// in that list.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "MII..."
+	TLSServerCertificateKey = attribute.Key("tls.server.certificate")
+
+	// TLSServerCertificateChainKey is the attribute Key conforming to the
+	// "tls.server.certificate_chain" semantic conventions. It represents the array
+	// of PEM-encoded certificates that make up the certificate chain offered by the
+	// server. This is usually mutually-exclusive of `server.certificate` since that
+	// value should be the first certificate in the chain.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "MII...", "MI..."
+	TLSServerCertificateChainKey = attribute.Key("tls.server.certificate_chain")
+
+	// TLSServerHashMd5Key is the attribute Key conforming to the
+	// "tls.server.hash.md5" semantic conventions. It represents the certificate
+	// fingerprint using the MD5 digest of DER-encoded version of certificate
+	// offered by the server. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC"
+	TLSServerHashMd5Key = attribute.Key("tls.server.hash.md5")
+
+	// TLSServerHashSha1Key is the attribute Key conforming to the
+	// "tls.server.hash.sha1" semantic conventions. It represents the certificate
+	// fingerprint using the SHA1 digest of DER-encoded version of certificate
+	// offered by the server. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "9E393D93138888D288266C2D915214D1D1CCEB2A"
+	TLSServerHashSha1Key = attribute.Key("tls.server.hash.sha1")
+
+	// TLSServerHashSha256Key is the attribute Key conforming to the
+	// "tls.server.hash.sha256" semantic conventions. It represents the certificate
+	// fingerprint using the SHA256 digest of DER-encoded version of certificate
+	// offered by the server. For consistency with other hash values, this value
+	// should be formatted as an uppercase hash.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0"
+	TLSServerHashSha256Key = attribute.Key("tls.server.hash.sha256")
+
+	// TLSServerIssuerKey is the attribute Key conforming to the "tls.server.issuer"
+	// semantic conventions. It represents the distinguished name of [subject] of
+	// the issuer of the x.509 certificate presented by the client.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com"
+	//
+	// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
+	TLSServerIssuerKey = attribute.Key("tls.server.issuer")
+
+	// TLSServerJa3sKey is the attribute Key conforming to the "tls.server.ja3s"
+	// semantic conventions. It represents a hash that identifies servers based on
+	// how they perform an SSL/TLS handshake.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "d4e5b18d6b55c71272893221c96ba240"
+	TLSServerJa3sKey = attribute.Key("tls.server.ja3s")
+
+	// TLSServerNotAfterKey is the attribute Key conforming to the
+	// "tls.server.not_after" semantic conventions. It represents the date/Time
+	// indicating when server certificate is no longer considered valid.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "2021-01-01T00:00:00.000Z"
+	TLSServerNotAfterKey = attribute.Key("tls.server.not_after")
+
+	// TLSServerNotBeforeKey is the attribute Key conforming to the
+	// "tls.server.not_before" semantic conventions. It represents the date/Time
+	// indicating when server certificate is first considered valid.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "1970-01-01T00:00:00.000Z"
+	TLSServerNotBeforeKey = attribute.Key("tls.server.not_before")
+
+	// TLSServerSubjectKey is the attribute Key conforming to the
+	// "tls.server.subject" semantic conventions. It represents the distinguished
+	// name of subject of the x.509 certificate presented by the server.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "CN=myserver, OU=Documentation Team, DC=example, DC=com"
+	TLSServerSubjectKey = attribute.Key("tls.server.subject")
+)
+
+// TLSCipher returns an attribute KeyValue conforming to the "tls.cipher"
+// semantic conventions. It represents the string indicating the [cipher] used
+// during the current connection.
+//
+// [cipher]: https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5
+func TLSCipher(val string) attribute.KeyValue {
+	return TLSCipherKey.String(val)
+}
+
+// TLSClientCertificate returns an attribute KeyValue conforming to the
+// "tls.client.certificate" semantic conventions. It represents the PEM-encoded
+// stand-alone certificate offered by the client. This is usually
+// mutually-exclusive of `client.certificate_chain` since this value also exists
+// in that list.
+func TLSClientCertificate(val string) attribute.KeyValue {
+	return TLSClientCertificateKey.String(val)
+}
+
+// TLSClientCertificateChain returns an attribute KeyValue conforming to the
+// "tls.client.certificate_chain" semantic conventions. It represents the array
+// of PEM-encoded certificates that make up the certificate chain offered by the
+// client. This is usually mutually-exclusive of `client.certificate` since that
+// value should be the first certificate in the chain.
+func TLSClientCertificateChain(val ...string) attribute.KeyValue {
+	return TLSClientCertificateChainKey.StringSlice(val)
+}
+
+// TLSClientHashMd5 returns an attribute KeyValue conforming to the
+// "tls.client.hash.md5" semantic conventions. It represents the certificate
+// fingerprint using the MD5 digest of DER-encoded version of certificate offered
+// by the client. For consistency with other hash values, this value should be
+// formatted as an uppercase hash.
+func TLSClientHashMd5(val string) attribute.KeyValue {
+	return TLSClientHashMd5Key.String(val)
+}
+
+// TLSClientHashSha1 returns an attribute KeyValue conforming to the
+// "tls.client.hash.sha1" semantic conventions. It represents the certificate
+// fingerprint using the SHA1 digest of DER-encoded version of certificate
+// offered by the client. For consistency with other hash values, this value
+// should be formatted as an uppercase hash.
+func TLSClientHashSha1(val string) attribute.KeyValue {
+	return TLSClientHashSha1Key.String(val)
+}
+
+// TLSClientHashSha256 returns an attribute KeyValue conforming to the
+// "tls.client.hash.sha256" semantic conventions. It represents the certificate
+// fingerprint using the SHA256 digest of DER-encoded version of certificate
+// offered by the client. For consistency with other hash values, this value
+// should be formatted as an uppercase hash.
+func TLSClientHashSha256(val string) attribute.KeyValue {
+	return TLSClientHashSha256Key.String(val)
+}
+
+// TLSClientIssuer returns an attribute KeyValue conforming to the
+// "tls.client.issuer" semantic conventions. It represents the distinguished name
+// of [subject] of the issuer of the x.509 certificate presented by the client.
+//
+// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
+func TLSClientIssuer(val string) attribute.KeyValue {
+	return TLSClientIssuerKey.String(val)
+}
+
+// TLSClientJa3 returns an attribute KeyValue conforming to the "tls.client.ja3"
+// semantic conventions. It represents a hash that identifies clients based on
+// how they perform an SSL/TLS handshake.
+func TLSClientJa3(val string) attribute.KeyValue {
+	return TLSClientJa3Key.String(val)
+}
+
+// TLSClientNotAfter returns an attribute KeyValue conforming to the
+// "tls.client.not_after" semantic conventions. It represents the date/Time
+// indicating when client certificate is no longer considered valid.
+func TLSClientNotAfter(val string) attribute.KeyValue {
+	return TLSClientNotAfterKey.String(val)
+}
+
+// TLSClientNotBefore returns an attribute KeyValue conforming to the
+// "tls.client.not_before" semantic conventions. It represents the date/Time
+// indicating when client certificate is first considered valid.
+func TLSClientNotBefore(val string) attribute.KeyValue {
+	return TLSClientNotBeforeKey.String(val)
+}
+
+// TLSClientSubject returns an attribute KeyValue conforming to the
+// "tls.client.subject" semantic conventions. It represents the distinguished
+// name of subject of the x.509 certificate presented by the client.
+func TLSClientSubject(val string) attribute.KeyValue {
+	return TLSClientSubjectKey.String(val)
+}
+
+// TLSClientSupportedCiphers returns an attribute KeyValue conforming to the
+// "tls.client.supported_ciphers" semantic conventions. It represents the array
+// of ciphers offered by the client during the client hello.
+func TLSClientSupportedCiphers(val ...string) attribute.KeyValue {
+	return TLSClientSupportedCiphersKey.StringSlice(val)
+}
+
+// TLSCurve returns an attribute KeyValue conforming to the "tls.curve" semantic
+// conventions. It represents the string indicating the curve used for the given
+// cipher, when applicable.
+func TLSCurve(val string) attribute.KeyValue {
+	return TLSCurveKey.String(val)
+}
+
+// TLSEstablished returns an attribute KeyValue conforming to the
+// "tls.established" semantic conventions. It represents the boolean flag
+// indicating if the TLS negotiation was successful and transitioned to an
+// encrypted tunnel.
+func TLSEstablished(val bool) attribute.KeyValue {
+	return TLSEstablishedKey.Bool(val)
+}
+
+// TLSNextProtocol returns an attribute KeyValue conforming to the
+// "tls.next_protocol" semantic conventions. It represents the string indicating
+// the protocol being tunneled. Per the values in the [IANA registry], this
+// string should be lower case.
+//
+// [IANA registry]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
+func TLSNextProtocol(val string) attribute.KeyValue {
+	return TLSNextProtocolKey.String(val)
+}
+
+// TLSProtocolVersion returns an attribute KeyValue conforming to the
+// "tls.protocol.version" semantic conventions. It represents the numeric part of
+// the version parsed from the original string of the negotiated
+// [SSL/TLS protocol version].
+//
+// [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values
+func TLSProtocolVersion(val string) attribute.KeyValue {
+	return TLSProtocolVersionKey.String(val)
+}
+
+// TLSResumed returns an attribute KeyValue conforming to the "tls.resumed"
+// semantic conventions. It represents the boolean flag indicating if this TLS
+// connection was resumed from an existing TLS negotiation.
+func TLSResumed(val bool) attribute.KeyValue {
+	return TLSResumedKey.Bool(val)
+}
+
+// TLSServerCertificate returns an attribute KeyValue conforming to the
+// "tls.server.certificate" semantic conventions. It represents the PEM-encoded
+// stand-alone certificate offered by the server. This is usually
+// mutually-exclusive of `server.certificate_chain` since this value also exists
+// in that list.
+func TLSServerCertificate(val string) attribute.KeyValue {
+	return TLSServerCertificateKey.String(val)
+}
+
+// TLSServerCertificateChain returns an attribute KeyValue conforming to the
+// "tls.server.certificate_chain" semantic conventions. It represents the array
+// of PEM-encoded certificates that make up the certificate chain offered by the
+// server. This is usually mutually-exclusive of `server.certificate` since that
+// value should be the first certificate in the chain.
+func TLSServerCertificateChain(val ...string) attribute.KeyValue {
+	return TLSServerCertificateChainKey.StringSlice(val)
+}
+
+// TLSServerHashMd5 returns an attribute KeyValue conforming to the
+// "tls.server.hash.md5" semantic conventions. It represents the certificate
+// fingerprint using the MD5 digest of DER-encoded version of certificate offered
+// by the server. For consistency with other hash values, this value should be
+// formatted as an uppercase hash.
+func TLSServerHashMd5(val string) attribute.KeyValue {
+	return TLSServerHashMd5Key.String(val)
+}
+
+// TLSServerHashSha1 returns an attribute KeyValue conforming to the
+// "tls.server.hash.sha1" semantic conventions. It represents the certificate
+// fingerprint using the SHA1 digest of DER-encoded version of certificate
+// offered by the server. For consistency with other hash values, this value
+// should be formatted as an uppercase hash.
+func TLSServerHashSha1(val string) attribute.KeyValue {
+	return TLSServerHashSha1Key.String(val)
+}
+
+// TLSServerHashSha256 returns an attribute KeyValue conforming to the
+// "tls.server.hash.sha256" semantic conventions. It represents the certificate
+// fingerprint using the SHA256 digest of DER-encoded version of certificate
+// offered by the server. For consistency with other hash values, this value
+// should be formatted as an uppercase hash.
+func TLSServerHashSha256(val string) attribute.KeyValue {
+	return TLSServerHashSha256Key.String(val)
+}
+
+// TLSServerIssuer returns an attribute KeyValue conforming to the
+// "tls.server.issuer" semantic conventions. It represents the distinguished name
+// of [subject] of the issuer of the x.509 certificate presented by the client.
+//
+// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
+func TLSServerIssuer(val string) attribute.KeyValue {
+	return TLSServerIssuerKey.String(val)
+}
+
+// TLSServerJa3s returns an attribute KeyValue conforming to the
+// "tls.server.ja3s" semantic conventions. It represents a hash that identifies
+// servers based on how they perform an SSL/TLS handshake.
+func TLSServerJa3s(val string) attribute.KeyValue {
+	return TLSServerJa3sKey.String(val)
+}
+
+// TLSServerNotAfter returns an attribute KeyValue conforming to the
+// "tls.server.not_after" semantic conventions. It represents the date/Time
+// indicating when server certificate is no longer considered valid.
+func TLSServerNotAfter(val string) attribute.KeyValue {
+	return TLSServerNotAfterKey.String(val)
+}
+
+// TLSServerNotBefore returns an attribute KeyValue conforming to the
+// "tls.server.not_before" semantic conventions. It represents the date/Time
+// indicating when server certificate is first considered valid.
+func TLSServerNotBefore(val string) attribute.KeyValue {
+	return TLSServerNotBeforeKey.String(val)
+}
+
+// TLSServerSubject returns an attribute KeyValue conforming to the
+// "tls.server.subject" semantic conventions. It represents the distinguished
+// name of subject of the x.509 certificate presented by the server.
+func TLSServerSubject(val string) attribute.KeyValue {
+	return TLSServerSubjectKey.String(val)
+}
+
+// Enum values for tls.protocol.name
+var (
+	// ssl
+	// Stability: development
+	TLSProtocolNameSsl = TLSProtocolNameKey.String("ssl")
+	// tls
+	// Stability: development
+	TLSProtocolNameTLS = TLSProtocolNameKey.String("tls")
+)
+
+// Namespace: url
+const (
+	// URLDomainKey is the attribute Key conforming to the "url.domain" semantic
+	// conventions. It represents the domain extracted from the `url.full`, such as
+	// "opentelemetry.io".
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "www.foo.bar", "opentelemetry.io", "3.12.167.2",
+	// "[1080:0:0:0:8:800:200C:417A]"
+	// Note: In some cases a URL may refer to an IP and/or port directly, without a
+	// domain name. In this case, the IP address would go to the domain field. If
+	// the URL contains a [literal IPv6 address] enclosed by `[` and `]`, the `[`
+	// and `]` characters should also be captured in the domain field.
+	//
+	// [literal IPv6 address]: https://www.rfc-editor.org/rfc/rfc2732#section-2
+	URLDomainKey = attribute.Key("url.domain")
+
+	// URLExtensionKey is the attribute Key conforming to the "url.extension"
+	// semantic conventions. It represents the file extension extracted from the
+	// `url.full`, excluding the leading dot.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "png", "gz"
+	// Note: The file extension is only set if it exists, as not every url has a
+	// file extension. When the file name has multiple extensions `example.tar.gz`,
+	// only the last one should be captured `gz`, not `tar.gz`.
+	URLExtensionKey = attribute.Key("url.extension")
+
+	// URLFragmentKey is the attribute Key conforming to the "url.fragment" semantic
+	// conventions. It represents the [URI fragment] component.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "SemConv"
+	//
+	// [URI fragment]: https://www.rfc-editor.org/rfc/rfc3986#section-3.5
+	URLFragmentKey = attribute.Key("url.fragment")
+
+	// URLFullKey is the attribute Key conforming to the "url.full" semantic
+	// conventions. It represents the absolute URL describing a network resource
+	// according to [RFC3986].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "https://www.foo.bar/search?q=OpenTelemetry#SemConv", "//localhost"
+	// Note: For network calls, URL usually has
+	// `scheme://host[:port][path][?query][#fragment]` format, where the fragment
+	// is not transmitted over HTTP, but if it is known, it SHOULD be included
+	// nevertheless.
+	//
+	// `url.full` MUST NOT contain credentials passed via URL in form of
+	// `https://username:password@www.example.com/`.
+	// In such case username and password SHOULD be redacted and attribute's value
+	// SHOULD be `https://REDACTED:REDACTED@www.example.com/`.
+	//
+	// `url.full` SHOULD capture the absolute URL when it is available (or can be
+	// reconstructed).
+	//
+	// Sensitive content provided in `url.full` SHOULD be scrubbed when
+	// instrumentations can identify it.
+	//
+	//
+	// Query string values for the following keys SHOULD be redacted by default and
+	// replaced by the
+	// value `REDACTED`:
+	//
+	//   - [`AWSAccessKeyId`]
+	//   - [`Signature`]
+	//   - [`sig`]
+	//   - [`X-Goog-Signature`]
+	//
+	// This list is subject to change over time.
+	//
+	// When a query string value is redacted, the query string key SHOULD still be
+	// preserved, e.g.
+	// `https://www.example.com/path?color=blue&sig=REDACTED`.
+	//
+	// [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986
+	// [`AWSAccessKeyId`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
+	// [`Signature`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
+	// [`sig`]: https://learn.microsoft.com/azure/storage/common/storage-sas-overview#sas-token
+	// [`X-Goog-Signature`]: https://cloud.google.com/storage/docs/access-control/signed-urls
+	URLFullKey = attribute.Key("url.full")
+
+	// URLOriginalKey is the attribute Key conforming to the "url.original" semantic
+	// conventions. It represents the unmodified original URL as seen in the event
+	// source.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "https://www.foo.bar/search?q=OpenTelemetry#SemConv",
+	// "search?q=OpenTelemetry"
+	// Note: In network monitoring, the observed URL may be a full URL, whereas in
+	// access logs, the URL is often just represented as a path. This field is meant
+	// to represent the URL as it was observed, complete or not.
+	// `url.original` might contain credentials passed via URL in form of
+	// `https://username:password@www.example.com/`. In such case password and
+	// username SHOULD NOT be redacted and attribute's value SHOULD remain the same.
+	URLOriginalKey = attribute.Key("url.original")
+
+	// URLPathKey is the attribute Key conforming to the "url.path" semantic
+	// conventions. It represents the [URI path] component.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "/search"
+	// Note: Sensitive content provided in `url.path` SHOULD be scrubbed when
+	// instrumentations can identify it.
+	//
+	// [URI path]: https://www.rfc-editor.org/rfc/rfc3986#section-3.3
+	URLPathKey = attribute.Key("url.path")
+
+	// URLPortKey is the attribute Key conforming to the "url.port" semantic
+	// conventions. It represents the port extracted from the `url.full`.
+	//
+	// Type: int
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: 443
+	URLPortKey = attribute.Key("url.port")
+
+	// URLQueryKey is the attribute Key conforming to the "url.query" semantic
+	// conventions. It represents the [URI query] component.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "q=OpenTelemetry"
+	// Note: Sensitive content provided in `url.query` SHOULD be scrubbed when
+	// instrumentations can identify it.
+	//
+	//
+	// Query string values for the following keys SHOULD be redacted by default and
+	// replaced by the value `REDACTED`:
+	//
+	//   - [`AWSAccessKeyId`]
+	//   - [`Signature`]
+	//   - [`sig`]
+	//   - [`X-Goog-Signature`]
+	//
+	// This list is subject to change over time.
+	//
+	// When a query string value is redacted, the query string key SHOULD still be
+	// preserved, e.g.
+	// `q=OpenTelemetry&sig=REDACTED`.
+	//
+	// [URI query]: https://www.rfc-editor.org/rfc/rfc3986#section-3.4
+	// [`AWSAccessKeyId`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
+	// [`Signature`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
+	// [`sig`]: https://learn.microsoft.com/azure/storage/common/storage-sas-overview#sas-token
+	// [`X-Goog-Signature`]: https://cloud.google.com/storage/docs/access-control/signed-urls
+	URLQueryKey = attribute.Key("url.query")
+
+	// URLRegisteredDomainKey is the attribute Key conforming to the
+	// "url.registered_domain" semantic conventions. It represents the highest
+	// registered url domain, stripped of the subdomain.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "example.com", "foo.co.uk"
+	// Note: This value can be determined precisely with the [public suffix list].
+	// For example, the registered domain for `foo.example.com` is `example.com`.
+	// Trying to approximate this by simply taking the last two labels will not work
+	// well for TLDs such as `co.uk`.
+	//
+	// [public suffix list]: https://publicsuffix.org/
+	URLRegisteredDomainKey = attribute.Key("url.registered_domain")
+
+	// URLSchemeKey is the attribute Key conforming to the "url.scheme" semantic
+	// conventions. It represents the [URI scheme] component identifying the used
+	// protocol.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "https", "ftp", "telnet"
+	//
+	// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1
+	URLSchemeKey = attribute.Key("url.scheme")
+
+	// URLSubdomainKey is the attribute Key conforming to the "url.subdomain"
+	// semantic conventions. It represents the subdomain portion of a fully
+	// qualified domain name includes all of the names except the host name under
+	// the registered_domain. In a partially qualified domain, or if the
+	// qualification level of the full name cannot be determined, subdomain contains
+	// all of the names below the registered domain.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "east", "sub2.sub1"
+	// Note: The subdomain portion of `www.east.mydomain.co.uk` is `east`. If the
+	// domain has multiple levels of subdomain, such as `sub2.sub1.example.com`, the
+	// subdomain field should contain `sub2.sub1`, with no trailing period.
+	URLSubdomainKey = attribute.Key("url.subdomain")
+
+	// URLTemplateKey is the attribute Key conforming to the "url.template" semantic
+	// conventions. It represents the low-cardinality template of an
+	// [absolute path reference].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "/users/{id}", "/users/:id", "/users?id={id}"
+	//
+	// [absolute path reference]: https://www.rfc-editor.org/rfc/rfc3986#section-4.2
+	URLTemplateKey = attribute.Key("url.template")
+
+	// URLTopLevelDomainKey is the attribute Key conforming to the
+	// "url.top_level_domain" semantic conventions. It represents the effective top
+	// level domain (eTLD), also known as the domain suffix, is the last part of the
+	// domain name. For example, the top level domain for example.com is `com`.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "com", "co.uk"
+	// Note: This value can be determined precisely with the [public suffix list].
+	//
+	// [public suffix list]: https://publicsuffix.org/
+	URLTopLevelDomainKey = attribute.Key("url.top_level_domain")
+)
+
+// URLDomain returns an attribute KeyValue conforming to the "url.domain"
+// semantic conventions. It represents the domain extracted from the `url.full`,
+// such as "opentelemetry.io".
+func URLDomain(val string) attribute.KeyValue {
+	return URLDomainKey.String(val)
+}
+
+// URLExtension returns an attribute KeyValue conforming to the "url.extension"
+// semantic conventions. It represents the file extension extracted from the
+// `url.full`, excluding the leading dot.
+func URLExtension(val string) attribute.KeyValue {
+	return URLExtensionKey.String(val)
+}
+
+// URLFragment returns an attribute KeyValue conforming to the "url.fragment"
+// semantic conventions. It represents the [URI fragment] component.
+//
+// [URI fragment]: https://www.rfc-editor.org/rfc/rfc3986#section-3.5
+func URLFragment(val string) attribute.KeyValue {
+	return URLFragmentKey.String(val)
+}
+
+// URLFull returns an attribute KeyValue conforming to the "url.full" semantic
+// conventions. It represents the absolute URL describing a network resource
+// according to [RFC3986].
+//
+// [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986
+func URLFull(val string) attribute.KeyValue {
+	return URLFullKey.String(val)
+}
+
+// URLOriginal returns an attribute KeyValue conforming to the "url.original"
+// semantic conventions. It represents the unmodified original URL as seen in the
+// event source.
+func URLOriginal(val string) attribute.KeyValue {
+	return URLOriginalKey.String(val)
+}
+
+// URLPath returns an attribute KeyValue conforming to the "url.path" semantic
+// conventions. It represents the [URI path] component.
+//
+// [URI path]: https://www.rfc-editor.org/rfc/rfc3986#section-3.3
+func URLPath(val string) attribute.KeyValue {
+	return URLPathKey.String(val)
+}
+
+// URLPort returns an attribute KeyValue conforming to the "url.port" semantic
+// conventions. It represents the port extracted from the `url.full`.
+func URLPort(val int) attribute.KeyValue {
+	return URLPortKey.Int(val)
+}
+
+// URLQuery returns an attribute KeyValue conforming to the "url.query" semantic
+// conventions. It represents the [URI query] component.
+//
+// [URI query]: https://www.rfc-editor.org/rfc/rfc3986#section-3.4
+func URLQuery(val string) attribute.KeyValue {
+	return URLQueryKey.String(val)
+}
+
+// URLRegisteredDomain returns an attribute KeyValue conforming to the
+// "url.registered_domain" semantic conventions. It represents the highest
+// registered url domain, stripped of the subdomain.
+func URLRegisteredDomain(val string) attribute.KeyValue {
+	return URLRegisteredDomainKey.String(val)
+}
+
+// URLScheme returns an attribute KeyValue conforming to the "url.scheme"
+// semantic conventions. It represents the [URI scheme] component identifying the
+// used protocol.
+//
+// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1
+func URLScheme(val string) attribute.KeyValue {
+	return URLSchemeKey.String(val)
+}
+
+// URLSubdomain returns an attribute KeyValue conforming to the "url.subdomain"
+// semantic conventions. It represents the subdomain portion of a fully qualified
+// domain name includes all of the names except the host name under the
+// registered_domain. In a partially qualified domain, or if the qualification
+// level of the full name cannot be determined, subdomain contains all of the
+// names below the registered domain.
+func URLSubdomain(val string) attribute.KeyValue {
+	return URLSubdomainKey.String(val)
+}
+
+// URLTemplate returns an attribute KeyValue conforming to the "url.template"
+// semantic conventions. It represents the low-cardinality template of an
+// [absolute path reference].
+//
+// [absolute path reference]: https://www.rfc-editor.org/rfc/rfc3986#section-4.2
+func URLTemplate(val string) attribute.KeyValue {
+	return URLTemplateKey.String(val)
+}
+
+// URLTopLevelDomain returns an attribute KeyValue conforming to the
+// "url.top_level_domain" semantic conventions. It represents the effective top
+// level domain (eTLD), also known as the domain suffix, is the last part of the
+// domain name. For example, the top level domain for example.com is `com`.
+func URLTopLevelDomain(val string) attribute.KeyValue {
+	return URLTopLevelDomainKey.String(val)
+}
+
+// Namespace: user
+const (
+	// UserEmailKey is the attribute Key conforming to the "user.email" semantic
+	// conventions. It represents the user email address.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "a.einstein@example.com"
+	UserEmailKey = attribute.Key("user.email")
+
+	// UserFullNameKey is the attribute Key conforming to the "user.full_name"
+	// semantic conventions. It represents the user's full name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Albert Einstein"
+	UserFullNameKey = attribute.Key("user.full_name")
+
+	// UserHashKey is the attribute Key conforming to the "user.hash" semantic
+	// conventions. It represents the unique user hash to correlate information for
+	// a user in anonymized form.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "364fc68eaf4c8acec74a4e52d7d1feaa"
+	// Note: Useful if `user.id` or `user.name` contain confidential information and
+	// cannot be used.
+	UserHashKey = attribute.Key("user.hash")
+
+	// UserIDKey is the attribute Key conforming to the "user.id" semantic
+	// conventions. It represents the unique identifier of the user.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "S-1-5-21-202424912787-2692429404-2351956786-1000"
+	UserIDKey = attribute.Key("user.id")
+
+	// UserNameKey is the attribute Key conforming to the "user.name" semantic
+	// conventions. It represents the short name or login/username of the user.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "a.einstein"
+	UserNameKey = attribute.Key("user.name")
+
+	// UserRolesKey is the attribute Key conforming to the "user.roles" semantic
+	// conventions. It represents the array of user roles at the time of the event.
+	//
+	// Type: string[]
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "admin", "reporting_user"
+	UserRolesKey = attribute.Key("user.roles")
+)
+
+// UserEmail returns an attribute KeyValue conforming to the "user.email"
+// semantic conventions. It represents the user email address.
+func UserEmail(val string) attribute.KeyValue {
+	return UserEmailKey.String(val)
+}
+
+// UserFullName returns an attribute KeyValue conforming to the "user.full_name"
+// semantic conventions. It represents the user's full name.
+func UserFullName(val string) attribute.KeyValue {
+	return UserFullNameKey.String(val)
+}
+
+// UserHash returns an attribute KeyValue conforming to the "user.hash" semantic
+// conventions. It represents the unique user hash to correlate information for a
+// user in anonymized form.
+func UserHash(val string) attribute.KeyValue {
+	return UserHashKey.String(val)
+}
+
+// UserID returns an attribute KeyValue conforming to the "user.id" semantic
+// conventions. It represents the unique identifier of the user.
+func UserID(val string) attribute.KeyValue {
+	return UserIDKey.String(val)
+}
+
+// UserName returns an attribute KeyValue conforming to the "user.name" semantic
+// conventions. It represents the short name or login/username of the user.
+func UserName(val string) attribute.KeyValue {
+	return UserNameKey.String(val)
+}
+
+// UserRoles returns an attribute KeyValue conforming to the "user.roles"
+// semantic conventions. It represents the array of user roles at the time of the
+// event.
+func UserRoles(val ...string) attribute.KeyValue {
+	return UserRolesKey.StringSlice(val)
+}
+
+// Namespace: user_agent
+const (
+	// UserAgentNameKey is the attribute Key conforming to the "user_agent.name"
+	// semantic conventions. It represents the name of the user-agent extracted from
+	// original. Usually refers to the browser's name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Safari", "YourApp"
+	// Note: [Example] of extracting browser's name from original string. In the
+	// case of using a user-agent for non-browser products, such as microservices
+	// with multiple names/versions inside the `user_agent.original`, the most
+	// significant name SHOULD be selected. In such a scenario it should align with
+	// `user_agent.version`
+	//
+	// [Example]: https://www.whatsmyua.info
+	UserAgentNameKey = attribute.Key("user_agent.name")
+
+	// UserAgentOriginalKey is the attribute Key conforming to the
+	// "user_agent.original" semantic conventions. It represents the value of the
+	// [HTTP User-Agent] header sent by the client.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Stable
+	//
+	// Examples: "CERN-LineMode/2.15 libwww/2.17b3", "Mozilla/5.0 (iPhone; CPU
+	// iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)
+	// Version/14.1.2 Mobile/15E148 Safari/604.1", "YourApp/1.0.0
+	// grpc-java-okhttp/1.27.2"
+	//
+	// [HTTP User-Agent]: https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent
+	UserAgentOriginalKey = attribute.Key("user_agent.original")
+
+	// UserAgentOSNameKey is the attribute Key conforming to the
+	// "user_agent.os.name" semantic conventions. It represents the human readable
+	// operating system name.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "iOS", "Android", "Ubuntu"
+	// Note: For mapping user agent strings to OS names, libraries such as
+	// [ua-parser] can be utilized.
+	//
+	// [ua-parser]: https://github.com/ua-parser
+	UserAgentOSNameKey = attribute.Key("user_agent.os.name")
+
+	// UserAgentOSVersionKey is the attribute Key conforming to the
+	// "user_agent.os.version" semantic conventions. It represents the version
+	// string of the operating system as defined in [Version Attributes].
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "14.2.1", "18.04.1"
+	// Note: For mapping user agent strings to OS versions, libraries such as
+	// [ua-parser] can be utilized.
+	//
+	// [Version Attributes]: /docs/resource/README.md#version-attributes
+	// [ua-parser]: https://github.com/ua-parser
+	UserAgentOSVersionKey = attribute.Key("user_agent.os.version")
+
+	// UserAgentSyntheticTypeKey is the attribute Key conforming to the
+	// "user_agent.synthetic.type" semantic conventions. It represents the specifies
+	// the category of synthetic traffic, such as tests or bots.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// Note: This attribute MAY be derived from the contents of the
+	// `user_agent.original` attribute. Components that populate the attribute are
+	// responsible for determining what they consider to be synthetic bot or test
+	// traffic. This attribute can either be set for self-identification purposes,
+	// or on telemetry detected to be generated as a result of a synthetic request.
+	// This attribute is useful for distinguishing between genuine client traffic
+	// and synthetic traffic generated by bots or tests.
+	UserAgentSyntheticTypeKey = attribute.Key("user_agent.synthetic.type")
+
+	// UserAgentVersionKey is the attribute Key conforming to the
+	// "user_agent.version" semantic conventions. It represents the version of the
+	// user-agent extracted from original. Usually refers to the browser's version.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "14.1.2", "1.0.0"
+	// Note: [Example] of extracting browser's version from original string. In the
+	// case of using a user-agent for non-browser products, such as microservices
+	// with multiple names/versions inside the `user_agent.original`, the most
+	// significant version SHOULD be selected. In such a scenario it should align
+	// with `user_agent.name`
+	//
+	// [Example]: https://www.whatsmyua.info
+	UserAgentVersionKey = attribute.Key("user_agent.version")
+)
+
+// UserAgentName returns an attribute KeyValue conforming to the
+// "user_agent.name" semantic conventions. It represents the name of the
+// user-agent extracted from original. Usually refers to the browser's name.
+func UserAgentName(val string) attribute.KeyValue {
+	return UserAgentNameKey.String(val)
+}
+
+// UserAgentOriginal returns an attribute KeyValue conforming to the
+// "user_agent.original" semantic conventions. It represents the value of the
+// [HTTP User-Agent] header sent by the client.
+//
+// [HTTP User-Agent]: https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent
+func UserAgentOriginal(val string) attribute.KeyValue {
+	return UserAgentOriginalKey.String(val)
+}
+
+// UserAgentOSName returns an attribute KeyValue conforming to the
+// "user_agent.os.name" semantic conventions. It represents the human readable
+// operating system name.
+func UserAgentOSName(val string) attribute.KeyValue {
+	return UserAgentOSNameKey.String(val)
+}
+
+// UserAgentOSVersion returns an attribute KeyValue conforming to the
+// "user_agent.os.version" semantic conventions. It represents the version string
+// of the operating system as defined in [Version Attributes].
+//
+// [Version Attributes]: /docs/resource/README.md#version-attributes
+func UserAgentOSVersion(val string) attribute.KeyValue {
+	return UserAgentOSVersionKey.String(val)
+}
+
+// UserAgentVersion returns an attribute KeyValue conforming to the
+// "user_agent.version" semantic conventions. It represents the version of the
+// user-agent extracted from original. Usually refers to the browser's version.
+func UserAgentVersion(val string) attribute.KeyValue {
+	return UserAgentVersionKey.String(val)
+}
+
+// Enum values for user_agent.synthetic.type
+var (
+	// Bot source.
+	// Stability: development
+	UserAgentSyntheticTypeBot = UserAgentSyntheticTypeKey.String("bot")
+	// Synthetic test source.
+	// Stability: development
+	UserAgentSyntheticTypeTest = UserAgentSyntheticTypeKey.String("test")
+)
+
+// Namespace: vcs
+const (
+	// VCSChangeIDKey is the attribute Key conforming to the "vcs.change.id"
+	// semantic conventions. It represents the ID of the change (pull request/merge
+	// request/changelist) if applicable. This is usually a unique (within
+	// repository) identifier generated by the VCS system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "123"
+	VCSChangeIDKey = attribute.Key("vcs.change.id")
+
+	// VCSChangeStateKey is the attribute Key conforming to the "vcs.change.state"
+	// semantic conventions. It represents the state of the change (pull
+	// request/merge request/changelist).
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "open", "closed", "merged"
+	VCSChangeStateKey = attribute.Key("vcs.change.state")
+
+	// VCSChangeTitleKey is the attribute Key conforming to the "vcs.change.title"
+	// semantic conventions. It represents the human readable title of the change
+	// (pull request/merge request/changelist). This title is often a brief summary
+	// of the change and may get merged in to a ref as the commit summary.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "Fixes broken thing", "feat: add my new feature", "[chore] update
+	// dependency"
+	VCSChangeTitleKey = attribute.Key("vcs.change.title")
+
+	// VCSLineChangeTypeKey is the attribute Key conforming to the
+	// "vcs.line_change.type" semantic conventions. It represents the type of line
+	// change being measured on a branch or change.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "added", "removed"
+	VCSLineChangeTypeKey = attribute.Key("vcs.line_change.type")
+
+	// VCSOwnerNameKey is the attribute Key conforming to the "vcs.owner.name"
+	// semantic conventions. It represents the group owner within the version
+	// control system.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-org", "myteam", "business-unit"
+	VCSOwnerNameKey = attribute.Key("vcs.owner.name")
+
+	// VCSProviderNameKey is the attribute Key conforming to the "vcs.provider.name"
+	// semantic conventions. It represents the name of the version control system
+	// provider.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "github", "gitlab", "gitea", "bitbucket"
+	VCSProviderNameKey = attribute.Key("vcs.provider.name")
+
+	// VCSRefBaseNameKey is the attribute Key conforming to the "vcs.ref.base.name"
+	// semantic conventions. It represents the name of the [reference] such as
+	// **branch** or **tag** in the repository.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-feature-branch", "tag-1-test"
+	// Note: `base` refers to the starting point of a change. For example, `main`
+	// would be the base reference of type branch if you've created a new
+	// reference of type branch from it and created new commits.
+	//
+	// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+	VCSRefBaseNameKey = attribute.Key("vcs.ref.base.name")
+
+	// VCSRefBaseRevisionKey is the attribute Key conforming to the
+	// "vcs.ref.base.revision" semantic conventions. It represents the revision,
+	// literally [revised version], The revision most often refers to a commit
+	// object in Git, or a revision number in SVN.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "9d59409acf479dfa0df1aa568182e43e43df8bbe28d60fcf2bc52e30068802cc",
+	// "main", "123", "HEAD"
+	// Note: `base` refers to the starting point of a change. For example, `main`
+	// would be the base reference of type branch if you've created a new
+	// reference of type branch from it and created new commits. The
+	// revision can be a full [hash value (see
+	// glossary)],
+	// of the recorded change to a ref within a repository pointing to a
+	// commit [commit] object. It does
+	// not necessarily have to be a hash; it can simply define a [revision
+	// number]
+	// which is an integer that is monotonically increasing. In cases where
+	// it is identical to the `ref.base.name`, it SHOULD still be included.
+	// It is up to the implementer to decide which value to set as the
+	// revision based on the VCS system and situational context.
+	//
+	// [revised version]: https://www.merriam-webster.com/dictionary/revision
+	// [hash value (see
+	// glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+	// [commit]: https://git-scm.com/docs/git-commit
+	// [revision
+	// number]: https://svnbook.red-bean.com/en/1.7/svn.tour.revs.specifiers.html
+	VCSRefBaseRevisionKey = attribute.Key("vcs.ref.base.revision")
+
+	// VCSRefBaseTypeKey is the attribute Key conforming to the "vcs.ref.base.type"
+	// semantic conventions. It represents the type of the [reference] in the
+	// repository.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "branch", "tag"
+	// Note: `base` refers to the starting point of a change. For example, `main`
+	// would be the base reference of type branch if you've created a new
+	// reference of type branch from it and created new commits.
+	//
+	// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+	VCSRefBaseTypeKey = attribute.Key("vcs.ref.base.type")
+
+	// VCSRefHeadNameKey is the attribute Key conforming to the "vcs.ref.head.name"
+	// semantic conventions. It represents the name of the [reference] such as
+	// **branch** or **tag** in the repository.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "my-feature-branch", "tag-1-test"
+	// Note: `head` refers to where you are right now; the current reference at a
+	// given time.
+	//
+	// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+	VCSRefHeadNameKey = attribute.Key("vcs.ref.head.name")
+
+	// VCSRefHeadRevisionKey is the attribute Key conforming to the
+	// "vcs.ref.head.revision" semantic conventions. It represents the revision,
+	// literally [revised version], The revision most often refers to a commit
+	// object in Git, or a revision number in SVN.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "9d59409acf479dfa0df1aa568182e43e43df8bbe28d60fcf2bc52e30068802cc",
+	// "main", "123", "HEAD"
+	// Note: `head` refers to where you are right now; the current reference at a
+	// given time.The revision can be a full [hash value (see
+	// glossary)],
+	// of the recorded change to a ref within a repository pointing to a
+	// commit [commit] object. It does
+	// not necessarily have to be a hash; it can simply define a [revision
+	// number]
+	// which is an integer that is monotonically increasing. In cases where
+	// it is identical to the `ref.head.name`, it SHOULD still be included.
+	// It is up to the implementer to decide which value to set as the
+	// revision based on the VCS system and situational context.
+	//
+	// [revised version]: https://www.merriam-webster.com/dictionary/revision
+	// [hash value (see
+	// glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+	// [commit]: https://git-scm.com/docs/git-commit
+	// [revision
+	// number]: https://svnbook.red-bean.com/en/1.7/svn.tour.revs.specifiers.html
+	VCSRefHeadRevisionKey = attribute.Key("vcs.ref.head.revision")
+
+	// VCSRefHeadTypeKey is the attribute Key conforming to the "vcs.ref.head.type"
+	// semantic conventions. It represents the type of the [reference] in the
+	// repository.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "branch", "tag"
+	// Note: `head` refers to where you are right now; the current reference at a
+	// given time.
+	//
+	// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+	VCSRefHeadTypeKey = attribute.Key("vcs.ref.head.type")
+
+	// VCSRefTypeKey is the attribute Key conforming to the "vcs.ref.type" semantic
+	// conventions. It represents the type of the [reference] in the repository.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "branch", "tag"
+	//
+	// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+	VCSRefTypeKey = attribute.Key("vcs.ref.type")
+
+	// VCSRepositoryNameKey is the attribute Key conforming to the
+	// "vcs.repository.name" semantic conventions. It represents the human readable
+	// name of the repository. It SHOULD NOT include any additional identifier like
+	// Group/SubGroup in GitLab or organization in GitHub.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "semantic-conventions", "my-cool-repo"
+	// Note: Due to it only being the name, it can clash with forks of the same
+	// repository if collecting telemetry across multiple orgs or groups in
+	// the same backends.
+	VCSRepositoryNameKey = attribute.Key("vcs.repository.name")
+
+	// VCSRepositoryURLFullKey is the attribute Key conforming to the
+	// "vcs.repository.url.full" semantic conventions. It represents the
+	// [canonical URL] of the repository providing the complete HTTP(S) address in
+	// order to locate and identify the repository through a browser.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples:
+	// "https://github.com/opentelemetry/open-telemetry-collector-contrib",
+	// "https://gitlab.com/my-org/my-project/my-projects-project/repo"
+	// Note: In Git Version Control Systems, the canonical URL SHOULD NOT include
+	// the `.git` extension.
+	//
+	// [canonical URL]: https://support.google.com/webmasters/answer/10347851?hl=en#:~:text=A%20canonical%20URL%20is%20the,Google%20chooses%20one%20as%20canonical.
+	VCSRepositoryURLFullKey = attribute.Key("vcs.repository.url.full")
+
+	// VCSRevisionDeltaDirectionKey is the attribute Key conforming to the
+	// "vcs.revision_delta.direction" semantic conventions. It represents the type
+	// of revision comparison.
+	//
+	// Type: Enum
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "ahead", "behind"
+	VCSRevisionDeltaDirectionKey = attribute.Key("vcs.revision_delta.direction")
+)
+
+// VCSChangeID returns an attribute KeyValue conforming to the "vcs.change.id"
+// semantic conventions. It represents the ID of the change (pull request/merge
+// request/changelist) if applicable. This is usually a unique (within
+// repository) identifier generated by the VCS system.
+func VCSChangeID(val string) attribute.KeyValue {
+	return VCSChangeIDKey.String(val)
+}
+
+// VCSChangeTitle returns an attribute KeyValue conforming to the
+// "vcs.change.title" semantic conventions. It represents the human readable
+// title of the change (pull request/merge request/changelist). This title is
+// often a brief summary of the change and may get merged in to a ref as the
+// commit summary.
+func VCSChangeTitle(val string) attribute.KeyValue {
+	return VCSChangeTitleKey.String(val)
+}
+
+// VCSOwnerName returns an attribute KeyValue conforming to the "vcs.owner.name"
+// semantic conventions. It represents the group owner within the version control
+// system.
+func VCSOwnerName(val string) attribute.KeyValue {
+	return VCSOwnerNameKey.String(val)
+}
+
+// VCSRefBaseName returns an attribute KeyValue conforming to the
+// "vcs.ref.base.name" semantic conventions. It represents the name of the
+// [reference] such as **branch** or **tag** in the repository.
+//
+// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+func VCSRefBaseName(val string) attribute.KeyValue {
+	return VCSRefBaseNameKey.String(val)
+}
+
+// VCSRefBaseRevision returns an attribute KeyValue conforming to the
+// "vcs.ref.base.revision" semantic conventions. It represents the revision,
+// literally [revised version], The revision most often refers to a commit object
+// in Git, or a revision number in SVN.
+//
+// [revised version]: https://www.merriam-webster.com/dictionary/revision
+func VCSRefBaseRevision(val string) attribute.KeyValue {
+	return VCSRefBaseRevisionKey.String(val)
+}
+
+// VCSRefHeadName returns an attribute KeyValue conforming to the
+// "vcs.ref.head.name" semantic conventions. It represents the name of the
+// [reference] such as **branch** or **tag** in the repository.
+//
+// [reference]: https://git-scm.com/docs/gitglossary#def_ref
+func VCSRefHeadName(val string) attribute.KeyValue {
+	return VCSRefHeadNameKey.String(val)
+}
+
+// VCSRefHeadRevision returns an attribute KeyValue conforming to the
+// "vcs.ref.head.revision" semantic conventions. It represents the revision,
+// literally [revised version], The revision most often refers to a commit object
+// in Git, or a revision number in SVN.
+//
+// [revised version]: https://www.merriam-webster.com/dictionary/revision
+func VCSRefHeadRevision(val string) attribute.KeyValue {
+	return VCSRefHeadRevisionKey.String(val)
+}
+
+// VCSRepositoryName returns an attribute KeyValue conforming to the
+// "vcs.repository.name" semantic conventions. It represents the human readable
+// name of the repository. It SHOULD NOT include any additional identifier like
+// Group/SubGroup in GitLab or organization in GitHub.
+func VCSRepositoryName(val string) attribute.KeyValue {
+	return VCSRepositoryNameKey.String(val)
+}
+
+// VCSRepositoryURLFull returns an attribute KeyValue conforming to the
+// "vcs.repository.url.full" semantic conventions. It represents the
+// [canonical URL] of the repository providing the complete HTTP(S) address in
+// order to locate and identify the repository through a browser.
+//
+// [canonical URL]: https://support.google.com/webmasters/answer/10347851?hl=en#:~:text=A%20canonical%20URL%20is%20the,Google%20chooses%20one%20as%20canonical.
+func VCSRepositoryURLFull(val string) attribute.KeyValue {
+	return VCSRepositoryURLFullKey.String(val)
+}
+
+// Enum values for vcs.change.state
+var (
+	// Open means the change is currently active and under review. It hasn't been
+	// merged into the target branch yet, and it's still possible to make changes or
+	// add comments.
+	// Stability: development
+	VCSChangeStateOpen = VCSChangeStateKey.String("open")
+	// WIP (work-in-progress, draft) means the change is still in progress and not
+	// yet ready for a full review. It might still undergo significant changes.
+	// Stability: development
+	VCSChangeStateWip = VCSChangeStateKey.String("wip")
+	// Closed means the merge request has been closed without merging. This can
+	// happen for various reasons, such as the changes being deemed unnecessary, the
+	// issue being resolved in another way, or the author deciding to withdraw the
+	// request.
+	// Stability: development
+	VCSChangeStateClosed = VCSChangeStateKey.String("closed")
+	// Merged indicates that the change has been successfully integrated into the
+	// target codebase.
+	// Stability: development
+	VCSChangeStateMerged = VCSChangeStateKey.String("merged")
+)
+
+// Enum values for vcs.line_change.type
+var (
+	// How many lines were added.
+	// Stability: development
+	VCSLineChangeTypeAdded = VCSLineChangeTypeKey.String("added")
+	// How many lines were removed.
+	// Stability: development
+	VCSLineChangeTypeRemoved = VCSLineChangeTypeKey.String("removed")
+)
+
+// Enum values for vcs.provider.name
+var (
+	// [GitHub]
+	// Stability: development
+	//
+	// [GitHub]: https://github.com
+	VCSProviderNameGithub = VCSProviderNameKey.String("github")
+	// [GitLab]
+	// Stability: development
+	//
+	// [GitLab]: https://gitlab.com
+	VCSProviderNameGitlab = VCSProviderNameKey.String("gitlab")
+	// Deprecated: Replaced by `gitea`.
+	VCSProviderNameGittea = VCSProviderNameKey.String("gittea")
+	// [Gitea]
+	// Stability: development
+	//
+	// [Gitea]: https://gitea.io
+	VCSProviderNameGitea = VCSProviderNameKey.String("gitea")
+	// [Bitbucket]
+	// Stability: development
+	//
+	// [Bitbucket]: https://bitbucket.org
+	VCSProviderNameBitbucket = VCSProviderNameKey.String("bitbucket")
+)
+
+// Enum values for vcs.ref.base.type
+var (
+	// [branch]
+	// Stability: development
+	//
+	// [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch
+	VCSRefBaseTypeBranch = VCSRefBaseTypeKey.String("branch")
+	// [tag]
+	// Stability: development
+	//
+	// [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag
+	VCSRefBaseTypeTag = VCSRefBaseTypeKey.String("tag")
+)
+
+// Enum values for vcs.ref.head.type
+var (
+	// [branch]
+	// Stability: development
+	//
+	// [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch
+	VCSRefHeadTypeBranch = VCSRefHeadTypeKey.String("branch")
+	// [tag]
+	// Stability: development
+	//
+	// [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag
+	VCSRefHeadTypeTag = VCSRefHeadTypeKey.String("tag")
+)
+
+// Enum values for vcs.ref.type
+var (
+	// [branch]
+	// Stability: development
+	//
+	// [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch
+	VCSRefTypeBranch = VCSRefTypeKey.String("branch")
+	// [tag]
+	// Stability: development
+	//
+	// [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag
+	VCSRefTypeTag = VCSRefTypeKey.String("tag")
+)
+
+// Enum values for vcs.revision_delta.direction
+var (
+	// How many revisions the change is behind the target ref.
+	// Stability: development
+	VCSRevisionDeltaDirectionBehind = VCSRevisionDeltaDirectionKey.String("behind")
+	// How many revisions the change is ahead of the target ref.
+	// Stability: development
+	VCSRevisionDeltaDirectionAhead = VCSRevisionDeltaDirectionKey.String("ahead")
+)
+
+// Namespace: webengine
+const (
+	// WebEngineDescriptionKey is the attribute Key conforming to the
+	// "webengine.description" semantic conventions. It represents the additional
+	// description of the web engine (e.g. detailed version and edition
+	// information).
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) -
+	// 2.2.2.Final"
+	WebEngineDescriptionKey = attribute.Key("webengine.description")
+
+	// WebEngineNameKey is the attribute Key conforming to the "webengine.name"
+	// semantic conventions. It represents the name of the web engine.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "WildFly"
+	WebEngineNameKey = attribute.Key("webengine.name")
+
+	// WebEngineVersionKey is the attribute Key conforming to the
+	// "webengine.version" semantic conventions. It represents the version of the
+	// web engine.
+	//
+	// Type: string
+	// RequirementLevel: Recommended
+	// Stability: Development
+	//
+	// Examples: "21.0.0"
+	WebEngineVersionKey = attribute.Key("webengine.version")
+)
+
+// WebEngineDescription returns an attribute KeyValue conforming to the
+// "webengine.description" semantic conventions. It represents the additional
+// description of the web engine (e.g. detailed version and edition information).
+func WebEngineDescription(val string) attribute.KeyValue {
+	return WebEngineDescriptionKey.String(val)
+}
+
+// WebEngineName returns an attribute KeyValue conforming to the "webengine.name"
+// semantic conventions. It represents the name of the web engine.
+func WebEngineName(val string) attribute.KeyValue {
+	return WebEngineNameKey.String(val)
+}
+
+// WebEngineVersion returns an attribute KeyValue conforming to the
+// "webengine.version" semantic conventions. It represents the version of the web
+// engine.
+func WebEngineVersion(val string) attribute.KeyValue {
+	return WebEngineVersionKey.String(val)
+}
\ No newline at end of file
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/doc.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/doc.go
new file mode 100644
index 00000000..2c5c7ebd
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/doc.go
@@ -0,0 +1,9 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+// Package semconv implements OpenTelemetry semantic conventions.
+//
+// OpenTelemetry semantic conventions are agreed standardized naming
+// patterns for OpenTelemetry things. This package represents the v1.34.0
+// version of the OpenTelemetry semantic conventions.
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/exception.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/exception.go
new file mode 100644
index 00000000..88a998f1
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/exception.go
@@ -0,0 +1,9 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
+
+const (
+	// ExceptionEventName is the name of the Span event representing an exception.
+	ExceptionEventName = "exception"
+)
diff --git a/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/schema.go b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/schema.go
new file mode 100644
index 00000000..3c23d459
--- /dev/null
+++ b/history-api/vendor/go.opentelemetry.io/otel/semconv/v1.34.0/schema.go
@@ -0,0 +1,9 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
+
+// SchemaURL is the schema URL that matches the version of the semantic conventions
+// that this package defines. Semconv packages starting from v1.4.0 must declare
+// non-empty schema URL in the form https://opentelemetry.io/schemas/
+const SchemaURL = "https://opentelemetry.io/schemas/1.34.0"
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/auto.go b/history-api/vendor/go.opentelemetry.io/otel/trace/auto.go
index 7e291002..f3aa3981 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/auto.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/auto.go
@@ -20,7 +20,7 @@ import (
 
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/codes"
-	semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
+	semconv "go.opentelemetry.io/otel/semconv/v1.34.0"
 	"go.opentelemetry.io/otel/trace/embedded"
 	"go.opentelemetry.io/otel/trace/internal/telemetry"
 )
@@ -57,14 +57,15 @@ type autoTracer struct {
 var _ Tracer = autoTracer{}
 
 func (t autoTracer) Start(ctx context.Context, name string, opts ...SpanStartOption) (context.Context, Span) {
-	var psc SpanContext
+	var psc, sc SpanContext
 	sampled := true
 	span := new(autoSpan)
 
 	// Ask eBPF for sampling decision and span context info.
-	t.start(ctx, span, &psc, &sampled, &span.spanContext)
+	t.start(ctx, span, &psc, &sampled, &sc)
 
 	span.sampled.Store(sampled)
+	span.spanContext = sc
 
 	ctx = ContextWithSpan(ctx, span)
 
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go
index 3c5e1cdb..e7ca62c6 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go
@@ -251,13 +251,20 @@ func (s *Span) UnmarshalJSON(data []byte) error {
 type SpanFlags int32
 
 const (
+	// SpanFlagsTraceFlagsMask is a mask for trace-flags.
+	//
 	// Bits 0-7 are used for trace flags.
 	SpanFlagsTraceFlagsMask SpanFlags = 255
-	// Bits 8 and 9 are used to indicate that the parent span or link span is remote.
-	// Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known.
-	// Bit 9 (`IS_REMOTE`) indicates whether the span or link is remote.
+	// SpanFlagsContextHasIsRemoteMask is a mask for HAS_IS_REMOTE status.
+	//
+	// Bits 8 and 9 are used to indicate that the parent span or link span is
+	// remote. Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known.
 	SpanFlagsContextHasIsRemoteMask SpanFlags = 256
-	// SpanFlagsContextHasIsRemoteMask indicates the Span is remote.
+	// SpanFlagsContextIsRemoteMask is a mask for IS_REMOTE status.
+	//
+	// Bits 8 and 9 are used to indicate that the parent span or link span is
+	// remote. Bit 9 (`IS_REMOTE`) indicates whether the span or link is
+	// remote.
 	SpanFlagsContextIsRemoteMask SpanFlags = 512
 )
 
@@ -266,27 +273,31 @@ const (
 type SpanKind int32
 
 const (
-	// Indicates that the span represents an internal operation within an application,
-	// as opposed to an operation happening at the boundaries. Default value.
+	// SpanKindInternal indicates that the span represents an internal
+	// operation within an application, as opposed to an operation happening at
+	// the boundaries.
 	SpanKindInternal SpanKind = 1
-	// Indicates that the span covers server-side handling of an RPC or other
-	// remote network request.
+	// SpanKindServer indicates that the span covers server-side handling of an
+	// RPC or other remote network request.
 	SpanKindServer SpanKind = 2
-	// Indicates that the span describes a request to some remote service.
+	// SpanKindClient indicates that the span describes a request to some
+	// remote service.
 	SpanKindClient SpanKind = 3
-	// Indicates that the span describes a producer sending a message to a broker.
-	// Unlike CLIENT and SERVER, there is often no direct critical path latency relationship
-	// between producer and consumer spans. A PRODUCER span ends when the message was accepted
-	// by the broker while the logical processing of the message might span a much longer time.
+	// SpanKindProducer indicates that the span describes a producer sending a
+	// message to a broker. Unlike SpanKindClient and SpanKindServer, there is
+	// often no direct critical path latency relationship between producer and
+	// consumer spans. A SpanKindProducer span ends when the message was
+	// accepted by the broker while the logical processing of the message might
+	// span a much longer time.
 	SpanKindProducer SpanKind = 4
-	// Indicates that the span describes consumer receiving a message from a broker.
-	// Like the PRODUCER kind, there is often no direct critical path latency relationship
-	// between producer and consumer spans.
+	// SpanKindConsumer indicates that the span describes a consumer receiving
+	// a message from a broker. Like SpanKindProducer, there is often no direct
+	// critical path latency relationship between producer and consumer spans.
 	SpanKindConsumer SpanKind = 5
 )
 
-// Event is a time-stamped annotation of the span, consisting of user-supplied
-// text description and key-value pairs.
+// SpanEvent is a time-stamped annotation of the span, consisting of
+// user-supplied text description and key-value pairs.
 type SpanEvent struct {
 	// time_unix_nano is the time the event occurred.
 	Time time.Time `json:"timeUnixNano,omitempty"`
@@ -369,10 +380,11 @@ func (se *SpanEvent) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-// A pointer from the current span to another span in the same trace or in a
-// different trace. For example, this can be used in batching operations,
-// where a single batch handler processes multiple requests from different
-// traces or when the handler receives a request from a different project.
+// SpanLink is a reference from the current span to another span in the same
+// trace or in a different trace. For example, this can be used in batching
+// operations, where a single batch handler processes multiple requests from
+// different traces or when the handler receives a request from a different
+// project.
 type SpanLink struct {
 	// A unique identifier of a trace that this linked span is part of. The ID is a
 	// 16-byte array.
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go
index 1d013a8f..1039bf40 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go
@@ -3,17 +3,19 @@
 
 package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry"
 
+// StatusCode is the status of a Span.
+//
 // For the semantics of status codes see
 // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status
 type StatusCode int32
 
 const (
-	// The default status.
+	// StatusCodeUnset is the default status.
 	StatusCodeUnset StatusCode = 0
-	// The Span has been validated by an Application developer or Operator to
-	// have completed successfully.
+	// StatusCodeOK is used when the Span has been validated by an Application
+	// developer or Operator to have completed successfully.
 	StatusCodeOK StatusCode = 1
-	// The Span contains an error.
+	// StatusCodeError is used when the Span contains an error.
 	StatusCodeError StatusCode = 2
 )
 
@@ -30,7 +32,7 @@ func (s StatusCode) String() string {
 	return ""
 }
 
-// The Status type defines a logical error model that is suitable for different
+// Status defines a logical error model that is suitable for different
 // programming environments, including REST APIs and RPC APIs.
 type Status struct {
 	// A developer-facing human readable error message.
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go
index b0394070..e5f10767 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go
@@ -71,7 +71,7 @@ func (td *Traces) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-// A collection of ScopeSpans from a Resource.
+// ResourceSpans is a collection of ScopeSpans from a Resource.
 type ResourceSpans struct {
 	// The resource for the spans in this message.
 	// If this field is not set then no resource info is known.
@@ -128,7 +128,7 @@ func (rs *ResourceSpans) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-// A collection of Spans produced by an InstrumentationScope.
+// ScopeSpans is a collection of Spans produced by an InstrumentationScope.
 type ScopeSpans struct {
 	// The instrumentation scope information for the spans in this message.
 	// Semantically when InstrumentationScope isn't set, it is equivalent with
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go
index 7251492d..ae9ce102 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go
@@ -316,7 +316,7 @@ func (v Value) String() string {
 	case ValueKindBool:
 		return strconv.FormatBool(v.asBool())
 	case ValueKindBytes:
-		return fmt.Sprint(v.asBytes())
+		return string(v.asBytes())
 	case ValueKindMap:
 		return fmt.Sprint(v.asMap())
 	case ValueKindSlice:
diff --git a/history-api/vendor/go.opentelemetry.io/otel/trace/noop.go b/history-api/vendor/go.opentelemetry.io/otel/trace/noop.go
index c8b1ae5d..0f56e4db 100644
--- a/history-api/vendor/go.opentelemetry.io/otel/trace/noop.go
+++ b/history-api/vendor/go.opentelemetry.io/otel/trace/noop.go
@@ -95,6 +95,8 @@ var autoInstEnabled = new(bool)
 // tracerProvider return a noopTracerProvider if autoEnabled is false,
 // otherwise it will return a TracerProvider from the sdk package used in
 // auto-instrumentation.
+//
+//go:noinline
 func (noopSpan) tracerProvider(autoEnabled *bool) TracerProvider {
 	if *autoEnabled {
 		return newAutoTracerProvider()
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/LICENSE b/history-api/vendor/go.yaml.in/yaml/v3/LICENSE
new file mode 100644
index 00000000..2683e4bb
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/LICENSE
@@ -0,0 +1,50 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
+
+    apic.go emitterc.go parserc.go readerc.go scannerc.go
+    writerc.go yamlh.go yamlprivateh.go
+
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/NOTICE b/history-api/vendor/go.yaml.in/yaml/v3/NOTICE
new file mode 100644
index 00000000..866d74a7
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/README.md b/history-api/vendor/go.yaml.in/yaml/v3/README.md
new file mode 100644
index 00000000..15a85a63
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/README.md
@@ -0,0 +1,171 @@
+go.yaml.in/yaml
+===============
+
+YAML Support for the Go Language
+
+
+## Introduction
+
+The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode
+and decode [YAML](https://yaml.org/) values.
+
+It was originally developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go
+port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to
+parse and generate YAML data quickly and reliably.
+
+
+## Project Status
+
+This project started as a fork of the extremely popular [go-yaml](
+https://github.com/go-yaml/yaml/)
+project, and is being maintained by the official [YAML organization](
+https://github.com/yaml/).
+
+The YAML team took over ongoing maintenance and development of the project after
+discussion with go-yaml's author, @niemeyer, following his decision to
+[label the project repository as "unmaintained"](
+https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025.
+
+We have put together a team of dedicated maintainers including representatives
+of go-yaml's most important downstream projects.
+
+We will strive to earn the trust of the various go-yaml forks to switch back to
+this repository as their upstream.
+
+Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you
+would like to contribute or be involved.
+
+
+## Compatibility
+
+The `yaml` package supports most of YAML 1.2, but preserves some behavior from
+1.1 for backwards compatibility.
+
+Specifically, v3 of the `yaml` package:
+
+* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being
+  decoded into a typed bool value.
+  Otherwise they behave as a string.
+  Booleans in YAML 1.2 are `true`/`false` only.
+* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than
+  `0o777` as specified in YAML 1.2, because most parsers still use the old
+  format.
+  Octals in the `0o777` format are supported though, so new files work.
+* Does not support base-60 floats.
+  These are gone from YAML 1.2, and were actually never supported by this
+  package as it's clearly a poor choice.
+
+
+## Installation and Usage
+
+The import path for the package is *go.yaml.in/yaml/v3*.
+
+To install it, run:
+
+```bash
+go get go.yaml.in/yaml/v3
+```
+
+
+## API Documentation
+
+See: 
+
+
+## API Stability
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](
+https://gopkg.in).
+
+
+## Example
+
+```go
+package main
+
+import (
+	"fmt"
+	"log"
+
+	"go.yaml.in/yaml/v3"
+)
+
+var data = `
+a: Easy!
+b:
+  c: 2
+  d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+	A string
+	B struct {
+		RenamedC int   `yaml:"c"`
+		D	[]int `yaml:",flow"`
+	}
+}
+
+func main() {
+	t := T{}
+
+	err := yaml.Unmarshal([]byte(data), &t)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- t:\n%v\n\n", t)
+
+	d, err := yaml.Marshal(&t)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+	m := make(map[interface{}]interface{})
+
+	err = yaml.Unmarshal([]byte(data), &m)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- m:\n%v\n\n", m)
+
+	d, err = yaml.Marshal(&m)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+  c: 2
+  d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+  c: 2
+  d:
+  - 3
+  - 4
+```
+
+
+## License
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/apic.go b/history-api/vendor/go.yaml.in/yaml/v3/apic.go
new file mode 100644
index 00000000..05fd305d
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/apic.go
@@ -0,0 +1,747 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+	//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+	// Check if we can move the queue at the beginning of the buffer.
+	if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+		if parser.tokens_head != len(parser.tokens) {
+			copy(parser.tokens, parser.tokens[parser.tokens_head:])
+		}
+		parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+		parser.tokens_head = 0
+	}
+	parser.tokens = append(parser.tokens, *token)
+	if pos < 0 {
+		return
+	}
+	copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+	parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+	*parser = yaml_parser_t{
+		raw_buffer: make([]byte, 0, input_raw_buffer_size),
+		buffer:     make([]byte, 0, input_buffer_size),
+	}
+	return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+	*parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+	if parser.input_pos == len(parser.input) {
+		return 0, io.EOF
+	}
+	n = copy(buffer, parser.input[parser.input_pos:])
+	parser.input_pos += n
+	return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+	return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+	if parser.read_handler != nil {
+		panic("must set the input source only once")
+	}
+	parser.read_handler = yaml_string_read_handler
+	parser.input = input
+	parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+	if parser.read_handler != nil {
+		panic("must set the input source only once")
+	}
+	parser.read_handler = yaml_reader_read_handler
+	parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+	if parser.encoding != yaml_ANY_ENCODING {
+		panic("must set the encoding only once")
+	}
+	parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+	*emitter = yaml_emitter_t{
+		buffer:     make([]byte, output_buffer_size),
+		raw_buffer: make([]byte, 0, output_raw_buffer_size),
+		states:     make([]yaml_emitter_state_t, 0, initial_stack_size),
+		events:     make([]yaml_event_t, 0, initial_queue_size),
+		best_width: -1,
+	}
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+	*emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+	*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+	return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+	_, err := emitter.output_writer.Write(buffer)
+	return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+	if emitter.write_handler != nil {
+		panic("must set the output target only once")
+	}
+	emitter.write_handler = yaml_string_write_handler
+	emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+	if emitter.write_handler != nil {
+		panic("must set the output target only once")
+	}
+	emitter.write_handler = yaml_writer_write_handler
+	emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+	if emitter.encoding != yaml_ANY_ENCODING {
+		panic("must set the output encoding only once")
+	}
+	emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+	emitter.canonical = canonical
+}
+
+// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+	if indent < 2 || indent > 9 {
+		indent = 2
+	}
+	emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+	if width < 0 {
+		width = -1
+	}
+	emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+	emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+	emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+//    assert(token);  // Non-NULL token object expected.
+//
+//    switch (token.type)
+//    {
+//        case YAML_TAG_DIRECTIVE_TOKEN:
+//            yaml_free(token.data.tag_directive.handle);
+//            yaml_free(token.data.tag_directive.prefix);
+//            break;
+//
+//        case YAML_ALIAS_TOKEN:
+//            yaml_free(token.data.alias.value);
+//            break;
+//
+//        case YAML_ANCHOR_TOKEN:
+//            yaml_free(token.data.anchor.value);
+//            break;
+//
+//        case YAML_TAG_TOKEN:
+//            yaml_free(token.data.tag.handle);
+//            yaml_free(token.data.tag.suffix);
+//            break;
+//
+//        case YAML_SCALAR_TOKEN:
+//            yaml_free(token.data.scalar.value);
+//            break;
+//
+//        default:
+//            break;
+//    }
+//
+//    memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+//    yaml_char_t *end = start+length;
+//    yaml_char_t *pointer = start;
+//
+//    while (pointer < end) {
+//        unsigned char octet;
+//        unsigned int width;
+//        unsigned int value;
+//        size_t k;
+//
+//        octet = pointer[0];
+//        width = (octet & 0x80) == 0x00 ? 1 :
+//                (octet & 0xE0) == 0xC0 ? 2 :
+//                (octet & 0xF0) == 0xE0 ? 3 :
+//                (octet & 0xF8) == 0xF0 ? 4 : 0;
+//        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+//                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+//                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+//                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+//        if (!width) return 0;
+//        if (pointer+width > end) return 0;
+//        for (k = 1; k < width; k ++) {
+//            octet = pointer[k];
+//            if ((octet & 0xC0) != 0x80) return 0;
+//            value = (value << 6) + (octet & 0x3F);
+//        }
+//        if (!((width == 1) ||
+//            (width == 2 && value >= 0x80) ||
+//            (width == 3 && value >= 0x800) ||
+//            (width == 4 && value >= 0x10000))) return 0;
+//
+//        pointer += width;
+//    }
+//
+//    return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+	*event = yaml_event_t{
+		typ:      yaml_STREAM_START_EVENT,
+		encoding: encoding,
+	}
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+	*event = yaml_event_t{
+		typ: yaml_STREAM_END_EVENT,
+	}
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+	event *yaml_event_t,
+	version_directive *yaml_version_directive_t,
+	tag_directives []yaml_tag_directive_t,
+	implicit bool,
+) {
+	*event = yaml_event_t{
+		typ:               yaml_DOCUMENT_START_EVENT,
+		version_directive: version_directive,
+		tag_directives:    tag_directives,
+		implicit:          implicit,
+	}
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+	*event = yaml_event_t{
+		typ:      yaml_DOCUMENT_END_EVENT,
+		implicit: implicit,
+	}
+}
+
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+	*event = yaml_event_t{
+		typ:    yaml_ALIAS_EVENT,
+		anchor: anchor,
+	}
+	return true
+}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+	*event = yaml_event_t{
+		typ:             yaml_SCALAR_EVENT,
+		anchor:          anchor,
+		tag:             tag,
+		value:           value,
+		implicit:        plain_implicit,
+		quoted_implicit: quoted_implicit,
+		style:           yaml_style_t(style),
+	}
+	return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+	*event = yaml_event_t{
+		typ:      yaml_SEQUENCE_START_EVENT,
+		anchor:   anchor,
+		tag:      tag,
+		implicit: implicit,
+		style:    yaml_style_t(style),
+	}
+	return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+	*event = yaml_event_t{
+		typ: yaml_SEQUENCE_END_EVENT,
+	}
+	return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+	*event = yaml_event_t{
+		typ:      yaml_MAPPING_START_EVENT,
+		anchor:   anchor,
+		tag:      tag,
+		implicit: implicit,
+		style:    yaml_style_t(style),
+	}
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+	*event = yaml_event_t{
+		typ: yaml_MAPPING_END_EVENT,
+	}
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+	*event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+//        version_directive *yaml_version_directive_t,
+//        tag_directives_start *yaml_tag_directive_t,
+//        tag_directives_end *yaml_tag_directive_t,
+//        start_implicit int, end_implicit int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    struct {
+//        start *yaml_node_t
+//        end *yaml_node_t
+//        top *yaml_node_t
+//    } nodes = { NULL, NULL, NULL }
+//    version_directive_copy *yaml_version_directive_t = NULL
+//    struct {
+//        start *yaml_tag_directive_t
+//        end *yaml_tag_directive_t
+//        top *yaml_tag_directive_t
+//    } tag_directives_copy = { NULL, NULL, NULL }
+//    value yaml_tag_directive_t = { NULL, NULL }
+//    mark yaml_mark_t = { 0, 0, 0 }
+//
+//    assert(document) // Non-NULL document object is expected.
+//    assert((tag_directives_start && tag_directives_end) ||
+//            (tag_directives_start == tag_directives_end))
+//                            // Valid tag directives are expected.
+//
+//    if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+//    if (version_directive) {
+//        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+//        if (!version_directive_copy) goto error
+//        version_directive_copy.major = version_directive.major
+//        version_directive_copy.minor = version_directive.minor
+//    }
+//
+//    if (tag_directives_start != tag_directives_end) {
+//        tag_directive *yaml_tag_directive_t
+//        if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+//            goto error
+//        for (tag_directive = tag_directives_start
+//                tag_directive != tag_directives_end; tag_directive ++) {
+//            assert(tag_directive.handle)
+//            assert(tag_directive.prefix)
+//            if (!yaml_check_utf8(tag_directive.handle,
+//                        strlen((char *)tag_directive.handle)))
+//                goto error
+//            if (!yaml_check_utf8(tag_directive.prefix,
+//                        strlen((char *)tag_directive.prefix)))
+//                goto error
+//            value.handle = yaml_strdup(tag_directive.handle)
+//            value.prefix = yaml_strdup(tag_directive.prefix)
+//            if (!value.handle || !value.prefix) goto error
+//            if (!PUSH(&context, tag_directives_copy, value))
+//                goto error
+//            value.handle = NULL
+//            value.prefix = NULL
+//        }
+//    }
+//
+//    DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+//            tag_directives_copy.start, tag_directives_copy.top,
+//            start_implicit, end_implicit, mark, mark)
+//
+//    return 1
+//
+//error:
+//    STACK_DEL(&context, nodes)
+//    yaml_free(version_directive_copy)
+//    while (!STACK_EMPTY(&context, tag_directives_copy)) {
+//        value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+//        yaml_free(value.handle)
+//        yaml_free(value.prefix)
+//    }
+//    STACK_DEL(&context, tag_directives_copy)
+//    yaml_free(value.handle)
+//    yaml_free(value.prefix)
+//
+//    return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    tag_directive *yaml_tag_directive_t
+//
+//    context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    while (!STACK_EMPTY(&context, document.nodes)) {
+//        node yaml_node_t = POP(&context, document.nodes)
+//        yaml_free(node.tag)
+//        switch (node.type) {
+//            case YAML_SCALAR_NODE:
+//                yaml_free(node.data.scalar.value)
+//                break
+//            case YAML_SEQUENCE_NODE:
+//                STACK_DEL(&context, node.data.sequence.items)
+//                break
+//            case YAML_MAPPING_NODE:
+//                STACK_DEL(&context, node.data.mapping.pairs)
+//                break
+//            default:
+//                assert(0) // Should not happen.
+//        }
+//    }
+//    STACK_DEL(&context, document.nodes)
+//
+//    yaml_free(document.version_directive)
+//    for (tag_directive = document.tag_directives.start
+//            tag_directive != document.tag_directives.end
+//            tag_directive++) {
+//        yaml_free(tag_directive.handle)
+//        yaml_free(tag_directive.prefix)
+//    }
+//    yaml_free(document.tag_directives.start)
+//
+//    memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+//        return document.nodes.start + index - 1
+//    }
+//    return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (document.nodes.top != document.nodes.start) {
+//        return document.nodes.start
+//    }
+//    return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+//        tag *yaml_char_t, value *yaml_char_t, length int,
+//        style yaml_scalar_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    value_copy *yaml_char_t = NULL
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//    assert(value) // Non-NULL value is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (length < 0) {
+//        length = strlen((char *)value)
+//    }
+//
+//    if (!yaml_check_utf8(value, length)) goto error
+//    value_copy = yaml_malloc(length+1)
+//    if (!value_copy) goto error
+//    memcpy(value_copy, value, length)
+//    value_copy[length] = '\0'
+//
+//    SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    yaml_free(tag_copy)
+//    yaml_free(value_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+//        tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    struct {
+//        start *yaml_node_item_t
+//        end *yaml_node_item_t
+//        top *yaml_node_item_t
+//    } items = { NULL, NULL, NULL }
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+//    SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+//            style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    STACK_DEL(&context, items)
+//    yaml_free(tag_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+//        tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    struct {
+//        start *yaml_node_pair_t
+//        end *yaml_node_pair_t
+//        top *yaml_node_pair_t
+//    } pairs = { NULL, NULL, NULL }
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+//    MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+//            style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    STACK_DEL(&context, pairs)
+//    yaml_free(tag_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+//        sequence int, item int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//
+//    assert(document) // Non-NULL document is required.
+//    assert(sequence > 0
+//            && document.nodes.start + sequence <= document.nodes.top)
+//                            // Valid sequence id is required.
+//    assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+//                            // A sequence node is required.
+//    assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+//                            // Valid item id is required.
+//
+//    if (!PUSH(&context,
+//                document.nodes.start[sequence-1].data.sequence.items, item))
+//        return 0
+//
+//    return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+//        mapping int, key int, value int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//
+//    pair yaml_node_pair_t
+//
+//    assert(document) // Non-NULL document is required.
+//    assert(mapping > 0
+//            && document.nodes.start + mapping <= document.nodes.top)
+//                            // Valid mapping id is required.
+//    assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+//                            // A mapping node is required.
+//    assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+//                            // Valid key id is required.
+//    assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+//                            // Valid value id is required.
+//
+//    pair.key = key
+//    pair.value = value
+//
+//    if (!PUSH(&context,
+//                document.nodes.start[mapping-1].data.mapping.pairs, pair))
+//        return 0
+//
+//    return 1
+//}
+//
+//
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/decode.go b/history-api/vendor/go.yaml.in/yaml/v3/decode.go
new file mode 100644
index 00000000..02e2b17b
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/decode.go
@@ -0,0 +1,1018 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding"
+	"encoding/base64"
+	"fmt"
+	"io"
+	"math"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+	parser   yaml_parser_t
+	event    yaml_event_t
+	doc      *Node
+	anchors  map[string]*Node
+	doneInit bool
+	textless bool
+}
+
+func newParser(b []byte) *parser {
+	p := parser{}
+	if !yaml_parser_initialize(&p.parser) {
+		panic("failed to initialize YAML emitter")
+	}
+	if len(b) == 0 {
+		b = []byte{'\n'}
+	}
+	yaml_parser_set_input_string(&p.parser, b)
+	return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+	p := parser{}
+	if !yaml_parser_initialize(&p.parser) {
+		panic("failed to initialize YAML emitter")
+	}
+	yaml_parser_set_input_reader(&p.parser, r)
+	return &p
+}
+
+func (p *parser) init() {
+	if p.doneInit {
+		return
+	}
+	p.anchors = make(map[string]*Node)
+	p.expect(yaml_STREAM_START_EVENT)
+	p.doneInit = true
+}
+
+func (p *parser) destroy() {
+	if p.event.typ != yaml_NO_EVENT {
+		yaml_event_delete(&p.event)
+	}
+	yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+	if p.event.typ == yaml_NO_EVENT {
+		if !yaml_parser_parse(&p.parser, &p.event) {
+			p.fail()
+		}
+	}
+	if p.event.typ == yaml_STREAM_END_EVENT {
+		failf("attempted to go past the end of stream; corrupted value?")
+	}
+	if p.event.typ != e {
+		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+		p.fail()
+	}
+	yaml_event_delete(&p.event)
+	p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+	if p.event.typ != yaml_NO_EVENT {
+		return p.event.typ
+	}
+	// It's curious choice from the underlying API to generally return a
+	// positive result on success, but on this case return true in an error
+	// scenario. This was the source of bugs in the past (issue #666).
+	if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
+		p.fail()
+	}
+	return p.event.typ
+}
+
+func (p *parser) fail() {
+	var where string
+	var line int
+	if p.parser.context_mark.line != 0 {
+		line = p.parser.context_mark.line
+		// Scanner errors don't iterate line before returning error
+		if p.parser.error == yaml_SCANNER_ERROR {
+			line++
+		}
+	} else if p.parser.problem_mark.line != 0 {
+		line = p.parser.problem_mark.line
+		// Scanner errors don't iterate line before returning error
+		if p.parser.error == yaml_SCANNER_ERROR {
+			line++
+		}
+	}
+	if line != 0 {
+		where = "line " + strconv.Itoa(line) + ": "
+	}
+	var msg string
+	if len(p.parser.problem) > 0 {
+		msg = p.parser.problem
+	} else {
+		msg = "unknown problem parsing YAML content"
+	}
+	failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *Node, anchor []byte) {
+	if anchor != nil {
+		n.Anchor = string(anchor)
+		p.anchors[n.Anchor] = n
+	}
+}
+
+func (p *parser) parse() *Node {
+	p.init()
+	switch p.peek() {
+	case yaml_SCALAR_EVENT:
+		return p.scalar()
+	case yaml_ALIAS_EVENT:
+		return p.alias()
+	case yaml_MAPPING_START_EVENT:
+		return p.mapping()
+	case yaml_SEQUENCE_START_EVENT:
+		return p.sequence()
+	case yaml_DOCUMENT_START_EVENT:
+		return p.document()
+	case yaml_STREAM_END_EVENT:
+		// Happens when attempting to decode an empty buffer.
+		return nil
+	case yaml_TAIL_COMMENT_EVENT:
+		panic("internal error: unexpected tail comment event (please report)")
+	default:
+		panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
+	}
+}
+
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+	var style Style
+	if tag != "" && tag != "!" {
+		tag = shortTag(tag)
+		style = TaggedStyle
+	} else if defaultTag != "" {
+		tag = defaultTag
+	} else if kind == ScalarNode {
+		tag, _ = resolve("", value)
+	}
+	n := &Node{
+		Kind:  kind,
+		Tag:   tag,
+		Value: value,
+		Style: style,
+	}
+	if !p.textless {
+		n.Line = p.event.start_mark.line + 1
+		n.Column = p.event.start_mark.column + 1
+		n.HeadComment = string(p.event.head_comment)
+		n.LineComment = string(p.event.line_comment)
+		n.FootComment = string(p.event.foot_comment)
+	}
+	return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+	child := p.parse()
+	parent.Content = append(parent.Content, child)
+	return child
+}
+
+func (p *parser) document() *Node {
+	n := p.node(DocumentNode, "", "", "")
+	p.doc = n
+	p.expect(yaml_DOCUMENT_START_EVENT)
+	p.parseChild(n)
+	if p.peek() == yaml_DOCUMENT_END_EVENT {
+		n.FootComment = string(p.event.foot_comment)
+	}
+	p.expect(yaml_DOCUMENT_END_EVENT)
+	return n
+}
+
+func (p *parser) alias() *Node {
+	n := p.node(AliasNode, "", "", string(p.event.anchor))
+	n.Alias = p.anchors[n.Value]
+	if n.Alias == nil {
+		failf("unknown anchor '%s' referenced", n.Value)
+	}
+	p.expect(yaml_ALIAS_EVENT)
+	return n
+}
+
+func (p *parser) scalar() *Node {
+	var parsedStyle = p.event.scalar_style()
+	var nodeStyle Style
+	switch {
+	case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+		nodeStyle = DoubleQuotedStyle
+	case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+		nodeStyle = SingleQuotedStyle
+	case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+		nodeStyle = LiteralStyle
+	case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+		nodeStyle = FoldedStyle
+	}
+	var nodeValue = string(p.event.value)
+	var nodeTag = string(p.event.tag)
+	var defaultTag string
+	if nodeStyle == 0 {
+		if nodeValue == "<<" {
+			defaultTag = mergeTag
+		}
+	} else {
+		defaultTag = strTag
+	}
+	n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+	n.Style |= nodeStyle
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_SCALAR_EVENT)
+	return n
+}
+
+func (p *parser) sequence() *Node {
+	n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+	if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+		n.Style |= FlowStyle
+	}
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_SEQUENCE_START_EVENT)
+	for p.peek() != yaml_SEQUENCE_END_EVENT {
+		p.parseChild(n)
+	}
+	n.LineComment = string(p.event.line_comment)
+	n.FootComment = string(p.event.foot_comment)
+	p.expect(yaml_SEQUENCE_END_EVENT)
+	return n
+}
+
+func (p *parser) mapping() *Node {
+	n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+	block := true
+	if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+		block = false
+		n.Style |= FlowStyle
+	}
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_MAPPING_START_EVENT)
+	for p.peek() != yaml_MAPPING_END_EVENT {
+		k := p.parseChild(n)
+		if block && k.FootComment != "" {
+			// Must be a foot comment for the prior value when being dedented.
+			if len(n.Content) > 2 {
+				n.Content[len(n.Content)-3].FootComment = k.FootComment
+				k.FootComment = ""
+			}
+		}
+		v := p.parseChild(n)
+		if k.FootComment == "" && v.FootComment != "" {
+			k.FootComment = v.FootComment
+			v.FootComment = ""
+		}
+		if p.peek() == yaml_TAIL_COMMENT_EVENT {
+			if k.FootComment == "" {
+				k.FootComment = string(p.event.foot_comment)
+			}
+			p.expect(yaml_TAIL_COMMENT_EVENT)
+		}
+	}
+	n.LineComment = string(p.event.line_comment)
+	n.FootComment = string(p.event.foot_comment)
+	if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+		n.Content[len(n.Content)-2].FootComment = n.FootComment
+		n.FootComment = ""
+	}
+	p.expect(yaml_MAPPING_END_EVENT)
+	return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+	doc     *Node
+	aliases map[*Node]bool
+	terrors []string
+
+	stringMapType  reflect.Type
+	generalMapType reflect.Type
+
+	knownFields bool
+	uniqueKeys  bool
+	decodeCount int
+	aliasCount  int
+	aliasDepth  int
+
+	mergedFields map[interface{}]bool
+}
+
+var (
+	nodeType       = reflect.TypeOf(Node{})
+	durationType   = reflect.TypeOf(time.Duration(0))
+	stringMapType  = reflect.TypeOf(map[string]interface{}{})
+	generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+	ifaceType      = generalMapType.Elem()
+	timeType       = reflect.TypeOf(time.Time{})
+	ptrTimeType    = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder() *decoder {
+	d := &decoder{
+		stringMapType:  stringMapType,
+		generalMapType: generalMapType,
+		uniqueKeys:     true,
+	}
+	d.aliases = make(map[*Node]bool)
+	return d
+}
+
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+	if n.Tag != "" {
+		tag = n.Tag
+	}
+	value := n.Value
+	if tag != seqTag && tag != mapTag {
+		if len(value) > 10 {
+			value = " `" + value[:7] + "...`"
+		} else {
+			value = " `" + value + "`"
+		}
+	}
+	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+	err := u.UnmarshalYAML(n)
+	if e, ok := err.(*TypeError); ok {
+		d.terrors = append(d.terrors, e.Errors...)
+		return false
+	}
+	if err != nil {
+		fail(err)
+	}
+	return true
+}
+
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
+	terrlen := len(d.terrors)
+	err := u.UnmarshalYAML(func(v interface{}) (err error) {
+		defer handleErr(&err)
+		d.unmarshal(n, reflect.ValueOf(v))
+		if len(d.terrors) > terrlen {
+			issues := d.terrors[terrlen:]
+			d.terrors = d.terrors[:terrlen]
+			return &TypeError{issues}
+		}
+		return nil
+	})
+	if e, ok := err.(*TypeError); ok {
+		d.terrors = append(d.terrors, e.Errors...)
+		return false
+	}
+	if err != nil {
+		fail(err)
+	}
+	return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+	if n.ShortTag() == nullTag {
+		return out, false, false
+	}
+	again := true
+	for again {
+		again = false
+		if out.Kind() == reflect.Ptr {
+			if out.IsNil() {
+				out.Set(reflect.New(out.Type().Elem()))
+			}
+			out = out.Elem()
+			again = true
+		}
+		if out.CanAddr() {
+			outi := out.Addr().Interface()
+			if u, ok := outi.(Unmarshaler); ok {
+				good = d.callUnmarshaler(n, u)
+				return out, true, good
+			}
+			if u, ok := outi.(obsoleteUnmarshaler); ok {
+				good = d.callObsoleteUnmarshaler(n, u)
+				return out, true, good
+			}
+		}
+	}
+	return out, false, false
+}
+
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+	if n.ShortTag() == nullTag {
+		return reflect.Value{}
+	}
+	for _, num := range index {
+		for {
+			if v.Kind() == reflect.Ptr {
+				if v.IsNil() {
+					v.Set(reflect.New(v.Type().Elem()))
+				}
+				v = v.Elem()
+				continue
+			}
+			break
+		}
+		v = v.Field(num)
+	}
+	return v
+}
+
+const (
+	// 400,000 decode operations is ~500kb of dense object declarations, or
+	// ~5kb of dense object declarations with 10000% alias expansion
+	alias_ratio_range_low = 400000
+
+	// 4,000,000 decode operations is ~5MB of dense object declarations, or
+	// ~4.5MB of dense object declarations with 10% alias expansion
+	alias_ratio_range_high = 4000000
+
+	// alias_ratio_range is the range over which we scale allowed alias ratios
+	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+	switch {
+	case decodeCount <= alias_ratio_range_low:
+		// allow 99% to come from alias expansion for small-to-medium documents
+		return 0.99
+	case decodeCount >= alias_ratio_range_high:
+		// allow 10% to come from alias expansion for very large documents
+		return 0.10
+	default:
+		// scale smoothly from 99% down to 10% over the range.
+		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+		return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+	}
+}
+
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
+	d.decodeCount++
+	if d.aliasDepth > 0 {
+		d.aliasCount++
+	}
+	if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+		failf("document contains excessive aliasing")
+	}
+	if out.Type() == nodeType {
+		out.Set(reflect.ValueOf(n).Elem())
+		return true
+	}
+	switch n.Kind {
+	case DocumentNode:
+		return d.document(n, out)
+	case AliasNode:
+		return d.alias(n, out)
+	}
+	out, unmarshaled, good := d.prepare(n, out)
+	if unmarshaled {
+		return good
+	}
+	switch n.Kind {
+	case ScalarNode:
+		good = d.scalar(n, out)
+	case MappingNode:
+		good = d.mapping(n, out)
+	case SequenceNode:
+		good = d.sequence(n, out)
+	case 0:
+		if n.IsZero() {
+			return d.null(out)
+		}
+		fallthrough
+	default:
+		failf("cannot decode node with unknown kind %d", n.Kind)
+	}
+	return good
+}
+
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+	if len(n.Content) == 1 {
+		d.doc = n
+		d.unmarshal(n.Content[0], out)
+		return true
+	}
+	return false
+}
+
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
+	if d.aliases[n] {
+		// TODO this could actually be allowed in some circumstances.
+		failf("anchor '%s' value contains itself", n.Value)
+	}
+	d.aliases[n] = true
+	d.aliasDepth++
+	good = d.unmarshal(n.Alias, out)
+	d.aliasDepth--
+	delete(d.aliases, n)
+	return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+	for _, k := range out.MapKeys() {
+		out.SetMapIndex(k, zeroValue)
+	}
+}
+
+func (d *decoder) null(out reflect.Value) bool {
+	if out.CanAddr() {
+		switch out.Kind() {
+		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+			out.Set(reflect.Zero(out.Type()))
+			return true
+		}
+	}
+	return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
+	var tag string
+	var resolved interface{}
+	if n.indicatedString() {
+		tag = strTag
+		resolved = n.Value
+	} else {
+		tag, resolved = resolve(n.Tag, n.Value)
+		if tag == binaryTag {
+			data, err := base64.StdEncoding.DecodeString(resolved.(string))
+			if err != nil {
+				failf("!!binary value contains invalid base64 data")
+			}
+			resolved = string(data)
+		}
+	}
+	if resolved == nil {
+		return d.null(out)
+	}
+	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+		// We've resolved to exactly the type we want, so use that.
+		out.Set(resolvedv)
+		return true
+	}
+	// Perhaps we can use the value as a TextUnmarshaler to
+	// set its value.
+	if out.CanAddr() {
+		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+		if ok {
+			var text []byte
+			if tag == binaryTag {
+				text = []byte(resolved.(string))
+			} else {
+				// We let any value be unmarshaled into TextUnmarshaler.
+				// That might be more lax than we'd like, but the
+				// TextUnmarshaler itself should bowl out any dubious values.
+				text = []byte(n.Value)
+			}
+			err := u.UnmarshalText(text)
+			if err != nil {
+				fail(err)
+			}
+			return true
+		}
+	}
+	switch out.Kind() {
+	case reflect.String:
+		if tag == binaryTag {
+			out.SetString(resolved.(string))
+			return true
+		}
+		out.SetString(n.Value)
+		return true
+	case reflect.Interface:
+		out.Set(reflect.ValueOf(resolved))
+		return true
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		// This used to work in v2, but it's very unfriendly.
+		isDuration := out.Type() == durationType
+
+		switch resolved := resolved.(type) {
+		case int:
+			if !isDuration && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case int64:
+			if !isDuration && !out.OverflowInt(resolved) {
+				out.SetInt(resolved)
+				return true
+			}
+		case uint64:
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case float64:
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case string:
+			if out.Type() == durationType {
+				d, err := time.ParseDuration(resolved)
+				if err == nil {
+					out.SetInt(int64(d))
+					return true
+				}
+			}
+		}
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		switch resolved := resolved.(type) {
+		case int:
+			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case int64:
+			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case uint64:
+			if !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case float64:
+			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		}
+	case reflect.Bool:
+		switch resolved := resolved.(type) {
+		case bool:
+			out.SetBool(resolved)
+			return true
+		case string:
+			// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+			// It only works if explicitly attempting to unmarshal into a typed bool value.
+			switch resolved {
+			case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+				out.SetBool(true)
+				return true
+			case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+				out.SetBool(false)
+				return true
+			}
+		}
+	case reflect.Float32, reflect.Float64:
+		switch resolved := resolved.(type) {
+		case int:
+			out.SetFloat(float64(resolved))
+			return true
+		case int64:
+			out.SetFloat(float64(resolved))
+			return true
+		case uint64:
+			out.SetFloat(float64(resolved))
+			return true
+		case float64:
+			out.SetFloat(resolved)
+			return true
+		}
+	case reflect.Struct:
+		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+			out.Set(resolvedv)
+			return true
+		}
+	case reflect.Ptr:
+		panic("yaml internal error: please report the issue")
+	}
+	d.terror(n, tag, out)
+	return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+	v := reflect.ValueOf(i)
+	sv := reflect.New(v.Type()).Elem()
+	sv.Set(v)
+	return sv
+}
+
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+	l := len(n.Content)
+
+	var iface reflect.Value
+	switch out.Kind() {
+	case reflect.Slice:
+		out.Set(reflect.MakeSlice(out.Type(), l, l))
+	case reflect.Array:
+		if l != out.Len() {
+			failf("invalid array: want %d elements but got %d", out.Len(), l)
+		}
+	case reflect.Interface:
+		// No type hints. Will have to use a generic sequence.
+		iface = out
+		out = settableValueOf(make([]interface{}, l))
+	default:
+		d.terror(n, seqTag, out)
+		return false
+	}
+	et := out.Type().Elem()
+
+	j := 0
+	for i := 0; i < l; i++ {
+		e := reflect.New(et).Elem()
+		if ok := d.unmarshal(n.Content[i], e); ok {
+			out.Index(j).Set(e)
+			j++
+		}
+	}
+	if out.Kind() != reflect.Array {
+		out.Set(out.Slice(0, j))
+	}
+	if iface.IsValid() {
+		iface.Set(out)
+	}
+	return true
+}
+
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+	l := len(n.Content)
+	if d.uniqueKeys {
+		nerrs := len(d.terrors)
+		for i := 0; i < l; i += 2 {
+			ni := n.Content[i]
+			for j := i + 2; j < l; j += 2 {
+				nj := n.Content[j]
+				if ni.Kind == nj.Kind && ni.Value == nj.Value {
+					d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+				}
+			}
+		}
+		if len(d.terrors) > nerrs {
+			return false
+		}
+	}
+	switch out.Kind() {
+	case reflect.Struct:
+		return d.mappingStruct(n, out)
+	case reflect.Map:
+		// okay
+	case reflect.Interface:
+		iface := out
+		if isStringMap(n) {
+			out = reflect.MakeMap(d.stringMapType)
+		} else {
+			out = reflect.MakeMap(d.generalMapType)
+		}
+		iface.Set(out)
+	default:
+		d.terror(n, mapTag, out)
+		return false
+	}
+
+	outt := out.Type()
+	kt := outt.Key()
+	et := outt.Elem()
+
+	stringMapType := d.stringMapType
+	generalMapType := d.generalMapType
+	if outt.Elem() == ifaceType {
+		if outt.Key().Kind() == reflect.String {
+			d.stringMapType = outt
+		} else if outt.Key() == ifaceType {
+			d.generalMapType = outt
+		}
+	}
+
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+
+	var mergeNode *Node
+
+	mapIsNew := false
+	if out.IsNil() {
+		out.Set(reflect.MakeMap(outt))
+		mapIsNew = true
+	}
+	for i := 0; i < l; i += 2 {
+		if isMerge(n.Content[i]) {
+			mergeNode = n.Content[i+1]
+			continue
+		}
+		k := reflect.New(kt).Elem()
+		if d.unmarshal(n.Content[i], k) {
+			if mergedFields != nil {
+				ki := k.Interface()
+				if d.getPossiblyUnhashableKey(mergedFields, ki) {
+					continue
+				}
+				d.setPossiblyUnhashableKey(mergedFields, ki, true)
+			}
+			kkind := k.Kind()
+			if kkind == reflect.Interface {
+				kkind = k.Elem().Kind()
+			}
+			if kkind == reflect.Map || kkind == reflect.Slice {
+				failf("invalid map key: %#v", k.Interface())
+			}
+			e := reflect.New(et).Elem()
+			if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+				out.SetMapIndex(k, e)
+			}
+		}
+	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
+
+	d.stringMapType = stringMapType
+	d.generalMapType = generalMapType
+	return true
+}
+
+func isStringMap(n *Node) bool {
+	if n.Kind != MappingNode {
+		return false
+	}
+	l := len(n.Content)
+	for i := 0; i < l; i += 2 {
+		shortTag := n.Content[i].ShortTag()
+		if shortTag != strTag && shortTag != mergeTag {
+			return false
+		}
+	}
+	return true
+}
+
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
+	sinfo, err := getStructInfo(out.Type())
+	if err != nil {
+		panic(err)
+	}
+
+	var inlineMap reflect.Value
+	var elemType reflect.Type
+	if sinfo.InlineMap != -1 {
+		inlineMap = out.Field(sinfo.InlineMap)
+		elemType = inlineMap.Type().Elem()
+	}
+
+	for _, index := range sinfo.InlineUnmarshalers {
+		field := d.fieldByIndex(n, out, index)
+		d.prepare(n, field)
+	}
+
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+	var mergeNode *Node
+	var doneFields []bool
+	if d.uniqueKeys {
+		doneFields = make([]bool, len(sinfo.FieldsList))
+	}
+	name := settableValueOf("")
+	l := len(n.Content)
+	for i := 0; i < l; i += 2 {
+		ni := n.Content[i]
+		if isMerge(ni) {
+			mergeNode = n.Content[i+1]
+			continue
+		}
+		if !d.unmarshal(ni, name) {
+			continue
+		}
+		sname := name.String()
+		if mergedFields != nil {
+			if mergedFields[sname] {
+				continue
+			}
+			mergedFields[sname] = true
+		}
+		if info, ok := sinfo.FieldsMap[sname]; ok {
+			if d.uniqueKeys {
+				if doneFields[info.Id] {
+					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
+					continue
+				}
+				doneFields[info.Id] = true
+			}
+			var field reflect.Value
+			if info.Inline == nil {
+				field = out.Field(info.Num)
+			} else {
+				field = d.fieldByIndex(n, out, info.Inline)
+			}
+			d.unmarshal(n.Content[i+1], field)
+		} else if sinfo.InlineMap != -1 {
+			if inlineMap.IsNil() {
+				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+			}
+			value := reflect.New(elemType).Elem()
+			d.unmarshal(n.Content[i+1], value)
+			inlineMap.SetMapIndex(name, value)
+		} else if d.knownFields {
+			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
+		}
+	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
+	return true
+}
+
+func failWantMap() {
+	failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) setPossiblyUnhashableKey(m map[interface{}]bool, key interface{}, value bool) {
+	defer func() {
+		if err := recover(); err != nil {
+			failf("%v", err)
+		}
+	}()
+	m[key] = value
+}
+
+func (d *decoder) getPossiblyUnhashableKey(m map[interface{}]bool, key interface{}) bool {
+	defer func() {
+		if err := recover(); err != nil {
+			failf("%v", err)
+		}
+	}()
+	return m[key]
+}
+
+func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
+	mergedFields := d.mergedFields
+	if mergedFields == nil {
+		d.mergedFields = make(map[interface{}]bool)
+		for i := 0; i < len(parent.Content); i += 2 {
+			k := reflect.New(ifaceType).Elem()
+			if d.unmarshal(parent.Content[i], k) {
+				d.setPossiblyUnhashableKey(d.mergedFields, k.Interface(), true)
+			}
+		}
+	}
+
+	switch merge.Kind {
+	case MappingNode:
+		d.unmarshal(merge, out)
+	case AliasNode:
+		if merge.Alias != nil && merge.Alias.Kind != MappingNode {
+			failWantMap()
+		}
+		d.unmarshal(merge, out)
+	case SequenceNode:
+		for i := 0; i < len(merge.Content); i++ {
+			ni := merge.Content[i]
+			if ni.Kind == AliasNode {
+				if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+					failWantMap()
+				}
+			} else if ni.Kind != MappingNode {
+				failWantMap()
+			}
+			d.unmarshal(ni, out)
+		}
+	default:
+		failWantMap()
+	}
+
+	d.mergedFields = mergedFields
+}
+
+func isMerge(n *Node) bool {
+	return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/emitterc.go b/history-api/vendor/go.yaml.in/yaml/v3/emitterc.go
new file mode 100644
index 00000000..ab4e03ba
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/emitterc.go
@@ -0,0 +1,2054 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) {
+		return yaml_emitter_flush(emitter)
+	}
+	return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	emitter.buffer[emitter.buffer_pos] = value
+	emitter.buffer_pos++
+	emitter.column++
+	return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	switch emitter.line_break {
+	case yaml_CR_BREAK:
+		emitter.buffer[emitter.buffer_pos] = '\r'
+		emitter.buffer_pos += 1
+	case yaml_LN_BREAK:
+		emitter.buffer[emitter.buffer_pos] = '\n'
+		emitter.buffer_pos += 1
+	case yaml_CRLN_BREAK:
+		emitter.buffer[emitter.buffer_pos+0] = '\r'
+		emitter.buffer[emitter.buffer_pos+1] = '\n'
+		emitter.buffer_pos += 2
+	default:
+		panic("unknown line break setting")
+	}
+	if emitter.column == 0 {
+		emitter.space_above = true
+	}
+	emitter.column = 0
+	emitter.line++
+	// [Go] Do this here and below and drop from everywhere else (see commented lines).
+	emitter.indention = true
+	return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	p := emitter.buffer_pos
+	w := width(s[*i])
+	switch w {
+	case 4:
+		emitter.buffer[p+3] = s[*i+3]
+		fallthrough
+	case 3:
+		emitter.buffer[p+2] = s[*i+2]
+		fallthrough
+	case 2:
+		emitter.buffer[p+1] = s[*i+1]
+		fallthrough
+	case 1:
+		emitter.buffer[p+0] = s[*i+0]
+	default:
+		panic("unknown character width")
+	}
+	emitter.column++
+	emitter.buffer_pos += w
+	*i += w
+	return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+	for i := 0; i < len(s); {
+		if !write(emitter, s, &i) {
+			return false
+		}
+	}
+	return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+	if s[*i] == '\n' {
+		if !put_break(emitter) {
+			return false
+		}
+		*i++
+	} else {
+		if !write(emitter, s, i) {
+			return false
+		}
+		if emitter.column == 0 {
+			emitter.space_above = true
+		}
+		emitter.column = 0
+		emitter.line++
+		// [Go] Do this here and above and drop from everywhere else (see commented lines).
+		emitter.indention = true
+	}
+	return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+	emitter.error = yaml_EMITTER_ERROR
+	emitter.problem = problem
+	return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	emitter.events = append(emitter.events, *event)
+	for !yaml_emitter_need_more_events(emitter) {
+		event := &emitter.events[emitter.events_head]
+		if !yaml_emitter_analyze_event(emitter, event) {
+			return false
+		}
+		if !yaml_emitter_state_machine(emitter, event) {
+			return false
+		}
+		yaml_event_delete(event)
+		emitter.events_head++
+	}
+	return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+//   - 1 event for DOCUMENT-START
+//   - 2 events for SEQUENCE-START
+//   - 3 events for MAPPING-START
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+	if emitter.events_head == len(emitter.events) {
+		return true
+	}
+	var accumulate int
+	switch emitter.events[emitter.events_head].typ {
+	case yaml_DOCUMENT_START_EVENT:
+		accumulate = 1
+		break
+	case yaml_SEQUENCE_START_EVENT:
+		accumulate = 2
+		break
+	case yaml_MAPPING_START_EVENT:
+		accumulate = 3
+		break
+	default:
+		return false
+	}
+	if len(emitter.events)-emitter.events_head > accumulate {
+		return false
+	}
+	var level int
+	for i := emitter.events_head; i < len(emitter.events); i++ {
+		switch emitter.events[i].typ {
+		case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+			level++
+		case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+			level--
+		}
+		if level == 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+	for i := 0; i < len(emitter.tag_directives); i++ {
+		if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+			if allow_duplicates {
+				return true
+			}
+			return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+		}
+	}
+
+	// [Go] Do we actually need to copy this given garbage collection
+	// and the lack of deallocating destructors?
+	tag_copy := yaml_tag_directive_t{
+		handle: make([]byte, len(value.handle)),
+		prefix: make([]byte, len(value.prefix)),
+	}
+	copy(tag_copy.handle, value.handle)
+	copy(tag_copy.prefix, value.prefix)
+	emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+	return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent_compact(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool {
+	emitter.indents = append(emitter.indents, emitter.indent)
+	if emitter.indent < 0 {
+		if flow {
+			emitter.indent = emitter.best_indent
+		} else {
+			emitter.indent = 0
+		}
+	} else if !indentless {
+		// [Go] This was changed so that indentations are more regular.
+		if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+			// The first indent inside a sequence will just skip the "- " indicator.
+			emitter.indent += 2
+		} else {
+			// Everything else aligns to the chosen indentation.
+			emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent)
+			if compact_seq {
+				// The value compact_seq passed in is almost always set to `false` when this function is called,
+				// except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we
+				// are increasing the indent to account for sequence nodes, which will be correct because we need to
+				// subtract 2 to account for the - at the beginning of the sequence node.
+				emitter.indent = emitter.indent - 2
+			}
+		}
+	}
+	return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	switch emitter.state {
+	default:
+	case yaml_EMIT_STREAM_START_STATE:
+		return yaml_emitter_emit_stream_start(emitter, event)
+
+	case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+		return yaml_emitter_emit_document_start(emitter, event, true)
+
+	case yaml_EMIT_DOCUMENT_START_STATE:
+		return yaml_emitter_emit_document_start(emitter, event, false)
+
+	case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+		return yaml_emitter_emit_document_content(emitter, event)
+
+	case yaml_EMIT_DOCUMENT_END_STATE:
+		return yaml_emitter_emit_document_end(emitter, event)
+
+	case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+	case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
+
+	case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
+
+	case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+	case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
+
+	case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
+
+	case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+		return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+	case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+		return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+		return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+		return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+		return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+		return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+		return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+	case yaml_EMIT_END_STATE:
+		return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+	}
+	panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if event.typ != yaml_STREAM_START_EVENT {
+		return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+	}
+	if emitter.encoding == yaml_ANY_ENCODING {
+		emitter.encoding = event.encoding
+		if emitter.encoding == yaml_ANY_ENCODING {
+			emitter.encoding = yaml_UTF8_ENCODING
+		}
+	}
+	if emitter.best_indent < 2 || emitter.best_indent > 9 {
+		emitter.best_indent = 2
+	}
+	if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+		emitter.best_width = 80
+	}
+	if emitter.best_width < 0 {
+		emitter.best_width = 1<<31 - 1
+	}
+	if emitter.line_break == yaml_ANY_BREAK {
+		emitter.line_break = yaml_LN_BREAK
+	}
+
+	emitter.indent = -1
+	emitter.line = 0
+	emitter.column = 0
+	emitter.whitespace = true
+	emitter.indention = true
+	emitter.space_above = true
+	emitter.foot_indent = -1
+
+	if emitter.encoding != yaml_UTF8_ENCODING {
+		if !yaml_emitter_write_bom(emitter) {
+			return false
+		}
+	}
+	emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+	return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+	if event.typ == yaml_DOCUMENT_START_EVENT {
+
+		if event.version_directive != nil {
+			if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+				return false
+			}
+		}
+
+		for i := 0; i < len(event.tag_directives); i++ {
+			tag_directive := &event.tag_directives[i]
+			if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+				return false
+			}
+			if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+				return false
+			}
+		}
+
+		for i := 0; i < len(default_tag_directives); i++ {
+			tag_directive := &default_tag_directives[i]
+			if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+				return false
+			}
+		}
+
+		implicit := event.implicit
+		if !first || emitter.canonical {
+			implicit = false
+		}
+
+		if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+
+		if event.version_directive != nil {
+			implicit = false
+			if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+
+		if len(event.tag_directives) > 0 {
+			implicit = false
+			for i := 0; i < len(event.tag_directives); i++ {
+				tag_directive := &event.tag_directives[i]
+				if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+					return false
+				}
+				if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+					return false
+				}
+				if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+					return false
+				}
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+		}
+
+		if yaml_emitter_check_empty_document(emitter) {
+			implicit = false
+		}
+		if !implicit {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+			if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+				return false
+			}
+			if emitter.canonical || true {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+		}
+
+		if len(emitter.head_comment) > 0 {
+			if !yaml_emitter_process_head_comment(emitter) {
+				return false
+			}
+			if !put_break(emitter) {
+				return false
+			}
+		}
+
+		emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+		return true
+	}
+
+	if event.typ == yaml_STREAM_END_EVENT {
+		if emitter.open_ended {
+			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_flush(emitter) {
+			return false
+		}
+		emitter.state = yaml_EMIT_END_STATE
+		return true
+	}
+
+	return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// yaml_emitter_increase_indent preserves the original signature and delegates to
+// yaml_emitter_increase_indent_compact without compact-sequence indentation
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+	return yaml_emitter_increase_indent_compact(emitter, flow, indentless, false)
+}
+
+// yaml_emitter_process_line_comment preserves the original signature and delegates to
+// yaml_emitter_process_line_comment_linebreak passing false for linebreak
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+	return yaml_emitter_process_line_comment_linebreak(emitter, false)
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if event.typ != yaml_DOCUMENT_END_EVENT {
+		return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+	}
+	// [Go] Force document foot separation.
+	emitter.foot_indent = 0
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	emitter.foot_indent = -1
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !event.implicit {
+		// [Go] Allocate the slice elsewhere.
+		if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+			return false
+		}
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+	if !yaml_emitter_flush(emitter) {
+		return false
+	}
+	emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+	emitter.tag_directives = emitter.tag_directives[:0]
+	return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+	if first {
+		if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+			return false
+		}
+		if !yaml_emitter_increase_indent(emitter, true, false) {
+			return false
+		}
+		emitter.flow_level++
+	}
+
+	if event.typ == yaml_SEQUENCE_END_EVENT {
+		if emitter.canonical && !first && !trail {
+			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+				return false
+			}
+		}
+		emitter.flow_level--
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		if emitter.column == 0 || emitter.canonical && !first {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+			return false
+		}
+		if !yaml_emitter_process_line_comment(emitter) {
+			return false
+		}
+		if !yaml_emitter_process_foot_comment(emitter) {
+			return false
+		}
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+
+		return true
+	}
+
+	if !first && !trail {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if emitter.column == 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if emitter.canonical || emitter.column > emitter.best_width {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+	} else {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+	}
+	if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+		return false
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+	if first {
+		if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+			return false
+		}
+		if !yaml_emitter_increase_indent(emitter, true, false) {
+			return false
+		}
+		emitter.flow_level++
+	}
+
+	if event.typ == yaml_MAPPING_END_EVENT {
+		if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+				return false
+			}
+		}
+		if !yaml_emitter_process_head_comment(emitter) {
+			return false
+		}
+		emitter.flow_level--
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		if emitter.canonical && !first {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+			return false
+		}
+		if !yaml_emitter_process_line_comment(emitter) {
+			return false
+		}
+		if !yaml_emitter_process_foot_comment(emitter) {
+			return false
+		}
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+
+	if !first && !trail {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+
+	if emitter.column == 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if emitter.canonical || emitter.column > emitter.best_width {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+	if simple {
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+			return false
+		}
+	} else {
+		if emitter.canonical || emitter.column > emitter.best_width {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+			return false
+		}
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+	} else {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+	}
+	if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+		return false
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+	if first {
+		// emitter.mapping context tells us if we are currently in a mapping context.
+		// emiiter.column tells us which column we are in in the yaml output. 0 is the first char of the column.
+		// emitter.indentation tells us if the last character was an indentation character.
+		// emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements.
+		// So, `seq` means that we are in a mapping context, and we are either at the first char of the column or
+		//  the last character was not an indentation character, and we consider '- ' part of the indentation
+		//  for sequence elements.
+		seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
+			emitter.compact_sequence_indent
+		if !yaml_emitter_increase_indent_compact(emitter, false, false, seq) {
+			return false
+		}
+	}
+	if event.typ == yaml_SEQUENCE_END_EVENT {
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+	if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+	if first {
+		if !yaml_emitter_increase_indent(emitter, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if event.typ == yaml_MAPPING_END_EVENT {
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if len(emitter.line_comment) > 0 {
+		// [Go] A line comment was provided for the key. That's unusual as the
+		//      scanner associates line comments with the value. Either way,
+		//      save the line comment and render it appropriately later.
+		emitter.key_line_comment = emitter.line_comment
+		emitter.line_comment = nil
+	}
+	if yaml_emitter_check_simple_key(emitter) {
+		emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+	if simple {
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+			return false
+		}
+	} else {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+			return false
+		}
+	}
+	if len(emitter.key_line_comment) > 0 {
+		// [Go] Line comments are generally associated with the value, but when there's
+		//      no value on the same line as a mapping key they end up attached to the
+		//      key itself.
+		if event.typ == yaml_SCALAR_EVENT {
+			if len(emitter.line_comment) == 0 {
+				// A scalar is coming and it has no line comments by itself yet,
+				// so just let it handle the line comment as usual. If it has a
+				// line comment, we can't have both so the one from the key is lost.
+				emitter.line_comment = emitter.key_line_comment
+				emitter.key_line_comment = nil
+			}
+		} else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+			// An indented block follows, so write the comment right now.
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+			if !yaml_emitter_process_line_comment(emitter) {
+				return false
+			}
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+		}
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+	if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+	root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+	emitter.root_context = root
+	emitter.sequence_context = sequence
+	emitter.mapping_context = mapping
+	emitter.simple_key_context = simple_key
+
+	switch event.typ {
+	case yaml_ALIAS_EVENT:
+		return yaml_emitter_emit_alias(emitter, event)
+	case yaml_SCALAR_EVENT:
+		return yaml_emitter_emit_scalar(emitter, event)
+	case yaml_SEQUENCE_START_EVENT:
+		return yaml_emitter_emit_sequence_start(emitter, event)
+	case yaml_MAPPING_START_EVENT:
+		return yaml_emitter_emit_mapping_start(emitter, event)
+	default:
+		return yaml_emitter_set_emitter_error(emitter,
+			fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+	}
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	emitter.state = emitter.states[len(emitter.states)-1]
+	emitter.states = emitter.states[:len(emitter.states)-1]
+	return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_select_scalar_style(emitter, event) {
+		return false
+	}
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if !yaml_emitter_increase_indent(emitter, true, false) {
+		return false
+	}
+	if !yaml_emitter_process_scalar(emitter) {
+		return false
+	}
+	emitter.indent = emitter.indents[len(emitter.indents)-1]
+	emitter.indents = emitter.indents[:len(emitter.indents)-1]
+	emitter.state = emitter.states[len(emitter.states)-1]
+	emitter.states = emitter.states[:len(emitter.states)-1]
+	return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+		yaml_emitter_check_empty_sequence(emitter) {
+		emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+	} else {
+		emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+	}
+	return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+		yaml_emitter_check_empty_mapping(emitter) {
+		emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+	} else {
+		emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+	}
+	return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+	return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+	if len(emitter.events)-emitter.events_head < 2 {
+		return false
+	}
+	return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+		emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+	if len(emitter.events)-emitter.events_head < 2 {
+		return false
+	}
+	return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+		emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+	length := 0
+	switch emitter.events[emitter.events_head].typ {
+	case yaml_ALIAS_EVENT:
+		length += len(emitter.anchor_data.anchor)
+	case yaml_SCALAR_EVENT:
+		if emitter.scalar_data.multiline {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix) +
+			len(emitter.scalar_data.value)
+	case yaml_SEQUENCE_START_EVENT:
+		if !yaml_emitter_check_empty_sequence(emitter) {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix)
+	case yaml_MAPPING_START_EVENT:
+		if !yaml_emitter_check_empty_mapping(emitter) {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix)
+	default:
+		return false
+	}
+	return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+	no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+	if no_tag && !event.implicit && !event.quoted_implicit {
+		return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+	}
+
+	style := event.scalar_style()
+	if style == yaml_ANY_SCALAR_STYLE {
+		style = yaml_PLAIN_SCALAR_STYLE
+	}
+	if emitter.canonical {
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	if emitter.simple_key_context && emitter.scalar_data.multiline {
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+
+	if style == yaml_PLAIN_SCALAR_STYLE {
+		if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+			emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+		if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+		if no_tag && !event.implicit {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+	}
+	if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+		if !emitter.scalar_data.single_quoted_allowed {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+	}
+	if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+		if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+	}
+
+	if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+		emitter.tag_data.handle = []byte{'!'}
+	}
+	emitter.scalar_data.style = style
+	return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+	if emitter.anchor_data.anchor == nil {
+		return true
+	}
+	c := []byte{'&'}
+	if emitter.anchor_data.alias {
+		c[0] = '*'
+	}
+	if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+		return false
+	}
+	return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+	if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+		return true
+	}
+	if len(emitter.tag_data.handle) > 0 {
+		if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+			return false
+		}
+		if len(emitter.tag_data.suffix) > 0 {
+			if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+				return false
+			}
+		}
+	} else {
+		// [Go] Allocate these slices elsewhere.
+		if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+			return false
+		}
+		if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+			return false
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+			return false
+		}
+	}
+	return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+	switch emitter.scalar_data.style {
+	case yaml_PLAIN_SCALAR_STYLE:
+		return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+		return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+		return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_LITERAL_SCALAR_STYLE:
+		return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+	case yaml_FOLDED_SCALAR_STYLE:
+		return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+	}
+	panic("unknown scalar style")
+}
+
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+	if len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+		if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+			return false
+		}
+		emitter.tail_comment = emitter.tail_comment[:0]
+		emitter.foot_indent = emitter.indent
+		if emitter.foot_indent < 0 {
+			emitter.foot_indent = 0
+		}
+	}
+
+	if len(emitter.head_comment) == 0 {
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+		return false
+	}
+	emitter.head_comment = emitter.head_comment[:0]
+	return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment_linebreak(emitter *yaml_emitter_t, linebreak bool) bool {
+	if len(emitter.line_comment) == 0 {
+		// The next 3 lines are needed to resolve an issue with leading newlines
+		// See https://github.com/go-yaml/yaml/issues/755
+		// When linebreak is set to true, put_break will be called and will add
+		// the needed newline.
+		if linebreak && !put_break(emitter) {
+			return false
+		}
+		return true
+	}
+	if !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+		return false
+	}
+	emitter.line_comment = emitter.line_comment[:0]
+	return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+	if len(emitter.foot_comment) == 0 {
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+		return false
+	}
+	emitter.foot_comment = emitter.foot_comment[:0]
+	emitter.foot_indent = emitter.indent
+	if emitter.foot_indent < 0 {
+		emitter.foot_indent = 0
+	}
+	return true
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+	if version_directive.major != 1 || version_directive.minor != 1 {
+		return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+	}
+	return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+	handle := tag_directive.handle
+	prefix := tag_directive.prefix
+	if len(handle) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+	}
+	if handle[0] != '!' {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+	}
+	if handle[len(handle)-1] != '!' {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+	}
+	for i := 1; i < len(handle)-1; i += width(handle[i]) {
+		if !is_alpha(handle, i) {
+			return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+		}
+	}
+	if len(prefix) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+	}
+	return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+	if len(anchor) == 0 {
+		problem := "anchor value must not be empty"
+		if alias {
+			problem = "alias value must not be empty"
+		}
+		return yaml_emitter_set_emitter_error(emitter, problem)
+	}
+	for i := 0; i < len(anchor); i += width(anchor[i]) {
+		if !is_alpha(anchor, i) {
+			problem := "anchor value must contain alphanumerical characters only"
+			if alias {
+				problem = "alias value must contain alphanumerical characters only"
+			}
+			return yaml_emitter_set_emitter_error(emitter, problem)
+		}
+	}
+	emitter.anchor_data.anchor = anchor
+	emitter.anchor_data.alias = alias
+	return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+	if len(tag) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+	}
+	for i := 0; i < len(emitter.tag_directives); i++ {
+		tag_directive := &emitter.tag_directives[i]
+		if bytes.HasPrefix(tag, tag_directive.prefix) {
+			emitter.tag_data.handle = tag_directive.handle
+			emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+			return true
+		}
+	}
+	emitter.tag_data.suffix = tag
+	return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	var (
+		block_indicators   = false
+		flow_indicators    = false
+		line_breaks        = false
+		special_characters = false
+		tab_characters     = false
+
+		leading_space  = false
+		leading_break  = false
+		trailing_space = false
+		trailing_break = false
+		break_space    = false
+		space_break    = false
+
+		preceded_by_whitespace = false
+		followed_by_whitespace = false
+		previous_space         = false
+		previous_break         = false
+	)
+
+	emitter.scalar_data.value = value
+
+	if len(value) == 0 {
+		emitter.scalar_data.multiline = false
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = true
+		emitter.scalar_data.single_quoted_allowed = true
+		emitter.scalar_data.block_allowed = false
+		return true
+	}
+
+	if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+		block_indicators = true
+		flow_indicators = true
+	}
+
+	preceded_by_whitespace = true
+	for i, w := 0, 0; i < len(value); i += w {
+		w = width(value[i])
+		followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+		if i == 0 {
+			switch value[i] {
+			case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+				flow_indicators = true
+				block_indicators = true
+			case '?', ':':
+				flow_indicators = true
+				if followed_by_whitespace {
+					block_indicators = true
+				}
+			case '-':
+				if followed_by_whitespace {
+					flow_indicators = true
+					block_indicators = true
+				}
+			}
+		} else {
+			switch value[i] {
+			case ',', '?', '[', ']', '{', '}':
+				flow_indicators = true
+			case ':':
+				flow_indicators = true
+				if followed_by_whitespace {
+					block_indicators = true
+				}
+			case '#':
+				if preceded_by_whitespace {
+					flow_indicators = true
+					block_indicators = true
+				}
+			}
+		}
+
+		if value[i] == '\t' {
+			tab_characters = true
+		} else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+			special_characters = true
+		}
+		if is_space(value, i) {
+			if i == 0 {
+				leading_space = true
+			}
+			if i+width(value[i]) == len(value) {
+				trailing_space = true
+			}
+			if previous_break {
+				break_space = true
+			}
+			previous_space = true
+			previous_break = false
+		} else if is_break(value, i) {
+			line_breaks = true
+			if i == 0 {
+				leading_break = true
+			}
+			if i+width(value[i]) == len(value) {
+				trailing_break = true
+			}
+			if previous_space {
+				space_break = true
+			}
+			previous_space = false
+			previous_break = true
+		} else {
+			previous_space = false
+			previous_break = false
+		}
+
+		// [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+		preceded_by_whitespace = is_blankz(value, i)
+	}
+
+	emitter.scalar_data.multiline = line_breaks
+	emitter.scalar_data.flow_plain_allowed = true
+	emitter.scalar_data.block_plain_allowed = true
+	emitter.scalar_data.single_quoted_allowed = true
+	emitter.scalar_data.block_allowed = true
+
+	if leading_space || leading_break || trailing_space || trailing_break {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	if trailing_space {
+		emitter.scalar_data.block_allowed = false
+	}
+	if break_space {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+		emitter.scalar_data.single_quoted_allowed = false
+	}
+	if space_break || tab_characters || special_characters {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+		emitter.scalar_data.single_quoted_allowed = false
+	}
+	if space_break || special_characters {
+		emitter.scalar_data.block_allowed = false
+	}
+	if line_breaks {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	if flow_indicators {
+		emitter.scalar_data.flow_plain_allowed = false
+	}
+	if block_indicators {
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+	emitter.anchor_data.anchor = nil
+	emitter.tag_data.handle = nil
+	emitter.tag_data.suffix = nil
+	emitter.scalar_data.value = nil
+
+	if len(event.head_comment) > 0 {
+		emitter.head_comment = event.head_comment
+	}
+	if len(event.line_comment) > 0 {
+		emitter.line_comment = event.line_comment
+	}
+	if len(event.foot_comment) > 0 {
+		emitter.foot_comment = event.foot_comment
+	}
+	if len(event.tail_comment) > 0 {
+		emitter.tail_comment = event.tail_comment
+	}
+
+	switch event.typ {
+	case yaml_ALIAS_EVENT:
+		if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+			return false
+		}
+
+	case yaml_SCALAR_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+		if !yaml_emitter_analyze_scalar(emitter, event.value) {
+			return false
+		}
+
+	case yaml_SEQUENCE_START_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+
+	case yaml_MAPPING_START_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+	if !flush(emitter) {
+		return false
+	}
+	pos := emitter.buffer_pos
+	emitter.buffer[pos+0] = '\xEF'
+	emitter.buffer[pos+1] = '\xBB'
+	emitter.buffer[pos+2] = '\xBF'
+	emitter.buffer_pos += 3
+	return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+	indent := emitter.indent
+	if indent < 0 {
+		indent = 0
+	}
+	if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+		if !put_break(emitter) {
+			return false
+		}
+	}
+	if emitter.foot_indent == indent {
+		if !put_break(emitter) {
+			return false
+		}
+	}
+	for emitter.column < indent {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	emitter.whitespace = true
+	//emitter.indention = true
+	emitter.space_above = false
+	emitter.foot_indent = -1
+	return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+	if need_whitespace && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !write_all(emitter, indicator) {
+		return false
+	}
+	emitter.whitespace = is_whitespace
+	emitter.indention = (emitter.indention && is_indention)
+	emitter.open_ended = false
+	return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+	if !write_all(emitter, value) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+	if !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !write_all(emitter, value) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+	if need_whitespace && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	for i := 0; i < len(value); {
+		var must_write bool
+		switch value[i] {
+		case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+			must_write = true
+		default:
+			must_write = is_alpha(value, i)
+		}
+		if must_write {
+			if !write(emitter, value, &i) {
+				return false
+			}
+		} else {
+			w := width(value[i])
+			for k := 0; k < w; k++ {
+				octet := value[i]
+				i++
+				if !put(emitter, '%') {
+					return false
+				}
+
+				c := octet >> 4
+				if c < 10 {
+					c += '0'
+				} else {
+					c += 'A' - 10
+				}
+				if !put(emitter, c) {
+					return false
+				}
+
+				c = octet & 0x0f
+				if c < 10 {
+					c += '0'
+				} else {
+					c += 'A' - 10
+				}
+				if !put(emitter, c) {
+					return false
+				}
+			}
+		}
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+	if len(value) > 0 && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+
+	spaces := false
+	breaks := false
+	for i := 0; i < len(value); {
+		if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			spaces = true
+		} else if is_break(value, i) {
+			if !breaks && value[i] == '\n' {
+				if !put_break(emitter) {
+					return false
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			spaces = false
+			breaks = false
+		}
+	}
+
+	if len(value) > 0 {
+		emitter.whitespace = false
+	}
+	emitter.indention = false
+	if emitter.root_context {
+		emitter.open_ended = true
+	}
+
+	return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+		return false
+	}
+
+	spaces := false
+	breaks := false
+	for i := 0; i < len(value); {
+		if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			spaces = true
+		} else if is_break(value, i) {
+			if !breaks && value[i] == '\n' {
+				if !put_break(emitter) {
+					return false
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if value[i] == '\'' {
+				if !put(emitter, '\'') {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			spaces = false
+			breaks = false
+		}
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+	spaces := false
+	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+		return false
+	}
+
+	for i := 0; i < len(value); {
+		if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+			is_bom(value, i) || is_break(value, i) ||
+			value[i] == '"' || value[i] == '\\' {
+
+			octet := value[i]
+
+			var w int
+			var v rune
+			switch {
+			case octet&0x80 == 0x00:
+				w, v = 1, rune(octet&0x7F)
+			case octet&0xE0 == 0xC0:
+				w, v = 2, rune(octet&0x1F)
+			case octet&0xF0 == 0xE0:
+				w, v = 3, rune(octet&0x0F)
+			case octet&0xF8 == 0xF0:
+				w, v = 4, rune(octet&0x07)
+			}
+			for k := 1; k < w; k++ {
+				octet = value[i+k]
+				v = (v << 6) + (rune(octet) & 0x3F)
+			}
+			i += w
+
+			if !put(emitter, '\\') {
+				return false
+			}
+
+			var ok bool
+			switch v {
+			case 0x00:
+				ok = put(emitter, '0')
+			case 0x07:
+				ok = put(emitter, 'a')
+			case 0x08:
+				ok = put(emitter, 'b')
+			case 0x09:
+				ok = put(emitter, 't')
+			case 0x0A:
+				ok = put(emitter, 'n')
+			case 0x0b:
+				ok = put(emitter, 'v')
+			case 0x0c:
+				ok = put(emitter, 'f')
+			case 0x0d:
+				ok = put(emitter, 'r')
+			case 0x1b:
+				ok = put(emitter, 'e')
+			case 0x22:
+				ok = put(emitter, '"')
+			case 0x5c:
+				ok = put(emitter, '\\')
+			case 0x85:
+				ok = put(emitter, 'N')
+			case 0xA0:
+				ok = put(emitter, '_')
+			case 0x2028:
+				ok = put(emitter, 'L')
+			case 0x2029:
+				ok = put(emitter, 'P')
+			default:
+				if v <= 0xFF {
+					ok = put(emitter, 'x')
+					w = 2
+				} else if v <= 0xFFFF {
+					ok = put(emitter, 'u')
+					w = 4
+				} else {
+					ok = put(emitter, 'U')
+					w = 8
+				}
+				for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+					digit := byte((v >> uint(k)) & 0x0F)
+					if digit < 10 {
+						ok = put(emitter, digit+'0')
+					} else {
+						ok = put(emitter, digit+'A'-10)
+					}
+				}
+			}
+			if !ok {
+				return false
+			}
+			spaces = false
+		} else if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				if is_space(value, i+1) {
+					if !put(emitter, '\\') {
+						return false
+					}
+				}
+				i += width(value[i])
+			} else if !write(emitter, value, &i) {
+				return false
+			}
+			spaces = true
+		} else {
+			if !write(emitter, value, &i) {
+				return false
+			}
+			spaces = false
+		}
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+	if is_space(value, 0) || is_break(value, 0) {
+		indent_hint := []byte{'0' + byte(emitter.best_indent)}
+		if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+			return false
+		}
+	}
+
+	emitter.open_ended = false
+
+	var chomp_hint [1]byte
+	if len(value) == 0 {
+		chomp_hint[0] = '-'
+	} else {
+		i := len(value) - 1
+		for value[i]&0xC0 == 0x80 {
+			i--
+		}
+		if !is_break(value, i) {
+			chomp_hint[0] = '-'
+		} else if i == 0 {
+			chomp_hint[0] = '+'
+			emitter.open_ended = true
+		} else {
+			i--
+			for value[i]&0xC0 == 0x80 {
+				i--
+			}
+			if is_break(value, i) {
+				chomp_hint[0] = '+'
+				emitter.open_ended = true
+			}
+		}
+	}
+	if chomp_hint[0] != 0 {
+		if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+			return false
+		}
+	}
+	return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
+		return false
+	}
+	//emitter.indention = true
+	emitter.whitespace = true
+	breaks := true
+	for i := 0; i < len(value); {
+		if is_break(value, i) {
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+
+	return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
+		return false
+	}
+
+	//emitter.indention = true
+	emitter.whitespace = true
+
+	breaks := true
+	leading_spaces := true
+	for i := 0; i < len(value); {
+		if is_break(value, i) {
+			if !breaks && !leading_spaces && value[i] == '\n' {
+				k := 0
+				for is_break(value, k) {
+					k += width(value[k])
+				}
+				if !is_blankz(value, k) {
+					if !put_break(emitter) {
+						return false
+					}
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				leading_spaces = is_blank(value, i)
+			}
+			if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+	return true
+}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+	breaks := false
+	pound := false
+	for i := 0; i < len(comment); {
+		if is_break(comment, i) {
+			if !write_break(emitter, comment, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+			pound = false
+		} else {
+			if breaks && !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+			if !pound {
+				if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+					return false
+				}
+				pound = true
+			}
+			if !write(emitter, comment, &i) {
+				return false
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+	if !breaks && !put_break(emitter) {
+		return false
+	}
+
+	emitter.whitespace = true
+	//emitter.indention = true
+	return true
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/encode.go b/history-api/vendor/go.yaml.in/yaml/v3/encode.go
new file mode 100644
index 00000000..de9e72a3
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding"
+	"fmt"
+	"io"
+	"reflect"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+type encoder struct {
+	emitter  yaml_emitter_t
+	event    yaml_event_t
+	out      []byte
+	flow     bool
+	indent   int
+	doneInit bool
+}
+
+func newEncoder() *encoder {
+	e := &encoder{}
+	yaml_emitter_initialize(&e.emitter)
+	yaml_emitter_set_output_string(&e.emitter, &e.out)
+	yaml_emitter_set_unicode(&e.emitter, true)
+	return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+	e := &encoder{}
+	yaml_emitter_initialize(&e.emitter)
+	yaml_emitter_set_output_writer(&e.emitter, w)
+	yaml_emitter_set_unicode(&e.emitter, true)
+	return e
+}
+
+func (e *encoder) init() {
+	if e.doneInit {
+		return
+	}
+	if e.indent == 0 {
+		e.indent = 4
+	}
+	e.emitter.best_indent = e.indent
+	yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+	e.emit()
+	e.doneInit = true
+}
+
+func (e *encoder) finish() {
+	e.emitter.open_ended = false
+	yaml_stream_end_event_initialize(&e.event)
+	e.emit()
+}
+
+func (e *encoder) destroy() {
+	yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+	// This will internally delete the e.event value.
+	e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+	if !ok {
+		msg := e.emitter.problem
+		if msg == "" {
+			msg = "unknown problem generating YAML content"
+		}
+		failf("%s", msg)
+	}
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+	e.init()
+	var node *Node
+	if in.IsValid() {
+		node, _ = in.Interface().(*Node)
+	}
+	if node != nil && node.Kind == DocumentNode {
+		e.nodev(in)
+	} else {
+		yaml_document_start_event_initialize(&e.event, nil, nil, true)
+		e.emit()
+		e.marshal(tag, in)
+		yaml_document_end_event_initialize(&e.event, true)
+		e.emit()
+	}
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+	tag = shortTag(tag)
+	if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+		e.nilv()
+		return
+	}
+	iface := in.Interface()
+	switch value := iface.(type) {
+	case *Node:
+		e.nodev(in)
+		return
+	case Node:
+		if !in.CanAddr() {
+			var n = reflect.New(in.Type()).Elem()
+			n.Set(in)
+			in = n
+		}
+		e.nodev(in.Addr())
+		return
+	case time.Time:
+		e.timev(tag, in)
+		return
+	case *time.Time:
+		e.timev(tag, in.Elem())
+		return
+	case time.Duration:
+		e.stringv(tag, reflect.ValueOf(value.String()))
+		return
+	case Marshaler:
+		v, err := value.MarshalYAML()
+		if err != nil {
+			fail(err)
+		}
+		if v == nil {
+			e.nilv()
+			return
+		}
+		e.marshal(tag, reflect.ValueOf(v))
+		return
+	case encoding.TextMarshaler:
+		text, err := value.MarshalText()
+		if err != nil {
+			fail(err)
+		}
+		in = reflect.ValueOf(string(text))
+	case nil:
+		e.nilv()
+		return
+	}
+	switch in.Kind() {
+	case reflect.Interface:
+		e.marshal(tag, in.Elem())
+	case reflect.Map:
+		e.mapv(tag, in)
+	case reflect.Ptr:
+		e.marshal(tag, in.Elem())
+	case reflect.Struct:
+		e.structv(tag, in)
+	case reflect.Slice, reflect.Array:
+		e.slicev(tag, in)
+	case reflect.String:
+		e.stringv(tag, in)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		e.intv(tag, in)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		e.uintv(tag, in)
+	case reflect.Float32, reflect.Float64:
+		e.floatv(tag, in)
+	case reflect.Bool:
+		e.boolv(tag, in)
+	default:
+		panic("cannot marshal type: " + in.Type().String())
+	}
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+	e.mappingv(tag, func() {
+		keys := keyList(in.MapKeys())
+		sort.Sort(keys)
+		for _, k := range keys {
+			e.marshal("", k)
+			e.marshal("", in.MapIndex(k))
+		}
+	})
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+	for _, num := range index {
+		for {
+			if v.Kind() == reflect.Ptr {
+				if v.IsNil() {
+					return reflect.Value{}
+				}
+				v = v.Elem()
+				continue
+			}
+			break
+		}
+		v = v.Field(num)
+	}
+	return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+	sinfo, err := getStructInfo(in.Type())
+	if err != nil {
+		panic(err)
+	}
+	e.mappingv(tag, func() {
+		for _, info := range sinfo.FieldsList {
+			var value reflect.Value
+			if info.Inline == nil {
+				value = in.Field(info.Num)
+			} else {
+				value = e.fieldByIndex(in, info.Inline)
+				if !value.IsValid() {
+					continue
+				}
+			}
+			if info.OmitEmpty && isZero(value) {
+				continue
+			}
+			e.marshal("", reflect.ValueOf(info.Key))
+			e.flow = info.Flow
+			e.marshal("", value)
+		}
+		if sinfo.InlineMap >= 0 {
+			m := in.Field(sinfo.InlineMap)
+			if m.Len() > 0 {
+				e.flow = false
+				keys := keyList(m.MapKeys())
+				sort.Sort(keys)
+				for _, k := range keys {
+					if _, found := sinfo.FieldsMap[k.String()]; found {
+						panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+					}
+					e.marshal("", k)
+					e.flow = false
+					e.marshal("", m.MapIndex(k))
+				}
+			}
+		}
+	})
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+	implicit := tag == ""
+	style := yaml_BLOCK_MAPPING_STYLE
+	if e.flow {
+		e.flow = false
+		style = yaml_FLOW_MAPPING_STYLE
+	}
+	yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+	e.emit()
+	f()
+	yaml_mapping_end_event_initialize(&e.event)
+	e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+	implicit := tag == ""
+	style := yaml_BLOCK_SEQUENCE_STYLE
+	if e.flow {
+		e.flow = false
+		style = yaml_FLOW_SEQUENCE_STYLE
+	}
+	e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+	e.emit()
+	n := in.Len()
+	for i := 0; i < n; i++ {
+		e.marshal("", in.Index(i))
+	}
+	e.must(yaml_sequence_end_event_initialize(&e.event))
+	e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+	// Fast path.
+	if s == "" {
+		return false
+	}
+	c := s[0]
+	if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+		return false
+	}
+	// Do the full match.
+	return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+	switch s {
+	case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+		"n", "N", "no", "No", "NO", "off", "Off", "OFF":
+		return true
+	default:
+		return false
+	}
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+	var style yaml_scalar_style_t
+	s := in.String()
+	canUsePlain := true
+	switch {
+	case !utf8.ValidString(s):
+		if tag == binaryTag {
+			failf("explicitly tagged !!binary data must be base64-encoded")
+		}
+		if tag != "" {
+			failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+		}
+		// It can't be encoded directly as YAML so use a binary tag
+		// and encode it as base64.
+		tag = binaryTag
+		s = encodeBase64(s)
+	case tag == "":
+		// Check to see if it would resolve to a specific
+		// tag when encoded unquoted. If it doesn't,
+		// there's no need to quote it.
+		rtag, _ := resolve("", s)
+		canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+	}
+	// Note: it's possible for user code to emit invalid YAML
+	// if they explicitly specify a tag and a string containing
+	// text that's incompatible with that tag.
+	switch {
+	case strings.Contains(s, "\n"):
+		if e.flow {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		} else {
+			style = yaml_LITERAL_SCALAR_STYLE
+		}
+	case canUsePlain:
+		style = yaml_PLAIN_SCALAR_STYLE
+	default:
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+	var s string
+	if in.Bool() {
+		s = "true"
+	} else {
+		s = "false"
+	}
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+	s := strconv.FormatInt(in.Int(), 10)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+	s := strconv.FormatUint(in.Uint(), 10)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+	t := in.Interface().(time.Time)
+	s := t.Format(time.RFC3339Nano)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+	// Issue #352: When formatting, use the precision of the underlying value
+	precision := 64
+	if in.Kind() == reflect.Float32 {
+		precision = 32
+	}
+
+	s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+	switch s {
+	case "+Inf":
+		s = ".inf"
+	case "-Inf":
+		s = "-.inf"
+	case "NaN":
+		s = ".nan"
+	}
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+	e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+	// TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+	implicit := tag == ""
+	if !implicit {
+		tag = longTag(tag)
+	}
+	e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+	e.event.head_comment = head
+	e.event.line_comment = line
+	e.event.foot_comment = foot
+	e.event.tail_comment = tail
+	e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+	e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+	// Zero nodes behave as nil.
+	if node.Kind == 0 && node.IsZero() {
+		e.nilv()
+		return
+	}
+
+	// If the tag was not explicitly requested, and dropping it won't change the
+	// implicit tag of the value, don't include it in the presentation.
+	var tag = node.Tag
+	var stag = shortTag(tag)
+	var forceQuoting bool
+	if tag != "" && node.Style&TaggedStyle == 0 {
+		if node.Kind == ScalarNode {
+			if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+				tag = ""
+			} else {
+				rtag, _ := resolve("", node.Value)
+				if rtag == stag {
+					tag = ""
+				} else if stag == strTag {
+					tag = ""
+					forceQuoting = true
+				}
+			}
+		} else {
+			var rtag string
+			switch node.Kind {
+			case MappingNode:
+				rtag = mapTag
+			case SequenceNode:
+				rtag = seqTag
+			}
+			if rtag == stag {
+				tag = ""
+			}
+		}
+	}
+
+	switch node.Kind {
+	case DocumentNode:
+		yaml_document_start_event_initialize(&e.event, nil, nil, true)
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+		for _, node := range node.Content {
+			e.node(node, "")
+		}
+		yaml_document_end_event_initialize(&e.event, true)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case SequenceNode:
+		style := yaml_BLOCK_SEQUENCE_STYLE
+		if node.Style&FlowStyle != 0 {
+			style = yaml_FLOW_SEQUENCE_STYLE
+		}
+		e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+		for _, node := range node.Content {
+			e.node(node, "")
+		}
+		e.must(yaml_sequence_end_event_initialize(&e.event))
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case MappingNode:
+		style := yaml_BLOCK_MAPPING_STYLE
+		if node.Style&FlowStyle != 0 {
+			style = yaml_FLOW_MAPPING_STYLE
+		}
+		yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+		e.event.tail_comment = []byte(tail)
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+
+		// The tail logic below moves the foot comment of prior keys to the following key,
+		// since the value for each key may be a nested structure and the foot needs to be
+		// processed only the entirety of the value is streamed. The last tail is processed
+		// with the mapping end event.
+		var tail string
+		for i := 0; i+1 < len(node.Content); i += 2 {
+			k := node.Content[i]
+			foot := k.FootComment
+			if foot != "" {
+				kopy := *k
+				kopy.FootComment = ""
+				k = &kopy
+			}
+			e.node(k, tail)
+			tail = foot
+
+			v := node.Content[i+1]
+			e.node(v, "")
+		}
+
+		yaml_mapping_end_event_initialize(&e.event)
+		e.event.tail_comment = []byte(tail)
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case AliasNode:
+		yaml_alias_event_initialize(&e.event, []byte(node.Value))
+		e.event.head_comment = []byte(node.HeadComment)
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case ScalarNode:
+		value := node.Value
+		if !utf8.ValidString(value) {
+			if stag == binaryTag {
+				failf("explicitly tagged !!binary data must be base64-encoded")
+			}
+			if stag != "" {
+				failf("cannot marshal invalid UTF-8 data as %s", stag)
+			}
+			// It can't be encoded directly as YAML so use a binary tag
+			// and encode it as base64.
+			tag = binaryTag
+			value = encodeBase64(value)
+		}
+
+		style := yaml_PLAIN_SCALAR_STYLE
+		switch {
+		case node.Style&DoubleQuotedStyle != 0:
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		case node.Style&SingleQuotedStyle != 0:
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		case node.Style&LiteralStyle != 0:
+			style = yaml_LITERAL_SCALAR_STYLE
+		case node.Style&FoldedStyle != 0:
+			style = yaml_FOLDED_SCALAR_STYLE
+		case strings.Contains(value, "\n"):
+			style = yaml_LITERAL_SCALAR_STYLE
+		case forceQuoting:
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+
+		e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+	default:
+		failf("cannot encode node with unknown kind %d", node.Kind)
+	}
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/parserc.go b/history-api/vendor/go.yaml.in/yaml/v3/parserc.go
new file mode 100644
index 00000000..25fe8236
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/parserc.go
@@ -0,0 +1,1274 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document    ::= block_node DOCUMENT-END*
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence    ::=
+//                          ALIAS
+//                          | properties (block_content | indentless_block_sequence)?
+//                          | block_content
+//                          | indentless_block_sequence
+// block_node           ::= ALIAS
+//                          | properties block_content?
+//                          | block_content
+// flow_node            ::= ALIAS
+//                          | properties flow_content?
+//                          | flow_content
+// properties           ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content        ::= block_collection | flow_collection | SCALAR
+// flow_content         ::= flow_collection | SCALAR
+// block_collection     ::= block_sequence | block_mapping
+// flow_collection      ::= flow_sequence | flow_mapping
+// block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
+// block_mapping        ::= BLOCK-MAPPING_START
+//                          ((KEY block_node_or_indentless_sequence?)?
+//                          (VALUE block_node_or_indentless_sequence?)?)*
+//                          BLOCK-END
+// flow_sequence        ::= FLOW-SEQUENCE-START
+//                          (flow_sequence_entry FLOW-ENTRY)*
+//                          flow_sequence_entry?
+//                          FLOW-SEQUENCE-END
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping         ::= FLOW-MAPPING-START
+//                          (flow_mapping_entry FLOW-ENTRY)*
+//                          flow_mapping_entry?
+//                          FLOW-MAPPING-END
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+	if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+		token := &parser.tokens[parser.tokens_head]
+		yaml_parser_unfold_comments(parser, token)
+		return token
+	}
+	return nil
+}
+
+// yaml_parser_unfold_comments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
+	for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
+		comment := &parser.comments[parser.comments_head]
+		if len(comment.head) > 0 {
+			if token.typ == yaml_BLOCK_END_TOKEN {
+				// No heads on ends, so keep comment.head for a follow up token.
+				break
+			}
+			if len(parser.head_comment) > 0 {
+				parser.head_comment = append(parser.head_comment, '\n')
+			}
+			parser.head_comment = append(parser.head_comment, comment.head...)
+		}
+		if len(comment.foot) > 0 {
+			if len(parser.foot_comment) > 0 {
+				parser.foot_comment = append(parser.foot_comment, '\n')
+			}
+			parser.foot_comment = append(parser.foot_comment, comment.foot...)
+		}
+		if len(comment.line) > 0 {
+			if len(parser.line_comment) > 0 {
+				parser.line_comment = append(parser.line_comment, '\n')
+			}
+			parser.line_comment = append(parser.line_comment, comment.line...)
+		}
+		*comment = yaml_comment_t{}
+		parser.comments_head++
+	}
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+	parser.token_available = false
+	parser.tokens_parsed++
+	parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+	parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+	// Erase the event object.
+	*event = yaml_event_t{}
+
+	// No events after the end of the stream or error.
+	if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+		return true
+	}
+
+	// Generate the next event.
+	return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+	parser.error = yaml_PARSER_ERROR
+	parser.problem = problem
+	parser.problem_mark = problem_mark
+	return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+	parser.error = yaml_PARSER_ERROR
+	parser.context = context
+	parser.context_mark = context_mark
+	parser.problem = problem
+	parser.problem_mark = problem_mark
+	return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+	//trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+	switch parser.state {
+	case yaml_PARSE_STREAM_START_STATE:
+		return yaml_parser_parse_stream_start(parser, event)
+
+	case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+		return yaml_parser_parse_document_start(parser, event, true)
+
+	case yaml_PARSE_DOCUMENT_START_STATE:
+		return yaml_parser_parse_document_start(parser, event, false)
+
+	case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+		return yaml_parser_parse_document_content(parser, event)
+
+	case yaml_PARSE_DOCUMENT_END_STATE:
+		return yaml_parser_parse_document_end(parser, event)
+
+	case yaml_PARSE_BLOCK_NODE_STATE:
+		return yaml_parser_parse_node(parser, event, true, false)
+
+	case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+		return yaml_parser_parse_node(parser, event, true, true)
+
+	case yaml_PARSE_FLOW_NODE_STATE:
+		return yaml_parser_parse_node(parser, event, false, false)
+
+	case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+		return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+	case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+	case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+	case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+	case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+		return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+	case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_block_mapping_value(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+		return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+	case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+		return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+	case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+		return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+	case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+	case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+		return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+	default:
+		panic("invalid parser state")
+	}
+}
+
+// Parse the production:
+// stream   ::= STREAM-START implicit_document? explicit_document* STREAM-END
+//
+//	************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_STREAM_START_TOKEN {
+		return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark)
+	}
+	parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+	*event = yaml_event_t{
+		typ:        yaml_STREAM_START_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+		encoding:   token.encoding,
+	}
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// implicit_document    ::= block_node DOCUMENT-END*
+//
+//	*
+//
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+//	*************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	// Parse extra document end indicators.
+	if !implicit {
+		for token.typ == yaml_DOCUMENT_END_TOKEN {
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	}
+
+	if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+		token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+		token.typ != yaml_DOCUMENT_START_TOKEN &&
+		token.typ != yaml_STREAM_END_TOKEN {
+		// Parse an implicit document.
+		if !yaml_parser_process_directives(parser, nil, nil) {
+			return false
+		}
+		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+		parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+		var head_comment []byte
+		if len(parser.head_comment) > 0 {
+			// [Go] Scan the header comment backwards, and if an empty line is found, break
+			//      the header so the part before the last empty line goes into the
+			//      document header, while the bottom of it goes into a follow up event.
+			for i := len(parser.head_comment) - 1; i > 0; i-- {
+				if parser.head_comment[i] == '\n' {
+					if i == len(parser.head_comment)-1 {
+						head_comment = parser.head_comment[:i]
+						parser.head_comment = parser.head_comment[i+1:]
+						break
+					} else if parser.head_comment[i-1] == '\n' {
+						head_comment = parser.head_comment[:i-1]
+						parser.head_comment = parser.head_comment[i+1:]
+						break
+					}
+				}
+			}
+		}
+
+		*event = yaml_event_t{
+			typ:        yaml_DOCUMENT_START_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+
+			head_comment: head_comment,
+		}
+
+	} else if token.typ != yaml_STREAM_END_TOKEN {
+		// Parse an explicit document.
+		var version_directive *yaml_version_directive_t
+		var tag_directives []yaml_tag_directive_t
+		start_mark := token.start_mark
+		if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+			return false
+		}
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_DOCUMENT_START_TOKEN {
+			yaml_parser_set_parser_error(parser,
+				"did not find expected ", token.start_mark)
+			return false
+		}
+		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+		parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+		end_mark := token.end_mark
+
+		*event = yaml_event_t{
+			typ:               yaml_DOCUMENT_START_EVENT,
+			start_mark:        start_mark,
+			end_mark:          end_mark,
+			version_directive: version_directive,
+			tag_directives:    tag_directives,
+			implicit:          false,
+		}
+		skip_token(parser)
+
+	} else {
+		// Parse the stream end.
+		parser.state = yaml_PARSE_END_STATE
+		*event = yaml_event_t{
+			typ:        yaml_STREAM_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+		skip_token(parser)
+	}
+
+	return true
+}
+
+// Parse the productions:
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+//	***********
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+		token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+		token.typ == yaml_DOCUMENT_START_TOKEN ||
+		token.typ == yaml_DOCUMENT_END_TOKEN ||
+		token.typ == yaml_STREAM_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		return yaml_parser_process_empty_scalar(parser, event,
+			token.start_mark)
+	}
+	return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document    ::= block_node DOCUMENT-END*
+//
+//	*************
+//
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	start_mark := token.start_mark
+	end_mark := token.start_mark
+
+	implicit := true
+	if token.typ == yaml_DOCUMENT_END_TOKEN {
+		end_mark = token.end_mark
+		skip_token(parser)
+		implicit = false
+	}
+
+	parser.tag_directives = parser.tag_directives[:0]
+
+	parser.state = yaml_PARSE_DOCUMENT_START_STATE
+	*event = yaml_event_t{
+		typ:        yaml_DOCUMENT_END_EVENT,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		implicit:   implicit,
+	}
+	yaml_parser_set_event_comments(parser, event)
+	if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
+		event.foot_comment = event.head_comment
+		event.head_comment = nil
+	}
+	return true
+}
+
+func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
+	event.head_comment = parser.head_comment
+	event.line_comment = parser.line_comment
+	event.foot_comment = parser.foot_comment
+	parser.head_comment = nil
+	parser.line_comment = nil
+	parser.foot_comment = nil
+	parser.tail_comment = nil
+	parser.stem_comment = nil
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence    ::=
+//
+//	ALIAS
+//	*****
+//	| properties (block_content | indentless_block_sequence)?
+//	  **********  *
+//	| block_content | indentless_block_sequence
+//	  *
+//
+// block_node           ::= ALIAS
+//
+//	*****
+//	| properties block_content?
+//	  ********** *
+//	| block_content
+//	  *
+//
+// flow_node            ::= ALIAS
+//
+//	*****
+//	| properties flow_content?
+//	  ********** *
+//	| flow_content
+//	  *
+//
+// properties           ::= TAG ANCHOR? | ANCHOR TAG?
+//
+//	*************************
+//
+// block_content        ::= block_collection | flow_collection | SCALAR
+//
+//	******
+//
+// flow_content         ::= flow_collection | SCALAR
+//
+//	******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+	//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_ALIAS_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		*event = yaml_event_t{
+			typ:        yaml_ALIAS_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+			anchor:     token.value,
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+
+	start_mark := token.start_mark
+	end_mark := token.start_mark
+
+	var tag_token bool
+	var tag_handle, tag_suffix, anchor []byte
+	var tag_mark yaml_mark_t
+	if token.typ == yaml_ANCHOR_TOKEN {
+		anchor = token.value
+		start_mark = token.start_mark
+		end_mark = token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ == yaml_TAG_TOKEN {
+			tag_token = true
+			tag_handle = token.value
+			tag_suffix = token.suffix
+			tag_mark = token.start_mark
+			end_mark = token.end_mark
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	} else if token.typ == yaml_TAG_TOKEN {
+		tag_token = true
+		tag_handle = token.value
+		tag_suffix = token.suffix
+		start_mark = token.start_mark
+		tag_mark = token.start_mark
+		end_mark = token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ == yaml_ANCHOR_TOKEN {
+			anchor = token.value
+			end_mark = token.end_mark
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	}
+
+	var tag []byte
+	if tag_token {
+		if len(tag_handle) == 0 {
+			tag = tag_suffix
+			tag_suffix = nil
+		} else {
+			for i := range parser.tag_directives {
+				if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+					tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+					tag = append(tag, tag_suffix...)
+					break
+				}
+			}
+			if len(tag) == 0 {
+				yaml_parser_set_parser_error_context(parser,
+					"while parsing a node", start_mark,
+					"found undefined tag handle", tag_mark)
+				return false
+			}
+		}
+	}
+
+	implicit := len(tag) == 0
+	if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+		}
+		return true
+	}
+	if token.typ == yaml_SCALAR_TOKEN {
+		var plain_implicit, quoted_implicit bool
+		end_mark = token.end_mark
+		if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+			plain_implicit = true
+		} else if len(tag) == 0 {
+			quoted_implicit = true
+		}
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+
+		*event = yaml_event_t{
+			typ:             yaml_SCALAR_EVENT,
+			start_mark:      start_mark,
+			end_mark:        end_mark,
+			anchor:          anchor,
+			tag:             tag,
+			value:           token.value,
+			implicit:        plain_implicit,
+			quoted_implicit: quoted_implicit,
+			style:           yaml_style_t(token.style),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+	if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+		// [Go] Some of the events below can be merged as they differ only on style.
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		return true
+	}
+	if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		return true
+	}
+	if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+		}
+		if parser.stem_comment != nil {
+			event.head_comment = parser.stem_comment
+			parser.stem_comment = nil
+		}
+		return true
+	}
+	if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+		}
+		if parser.stem_comment != nil {
+			event.head_comment = parser.stem_comment
+			parser.stem_comment = nil
+		}
+		return true
+	}
+	if len(anchor) > 0 || len(tag) > 0 {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+
+		*event = yaml_event_t{
+			typ:             yaml_SCALAR_EVENT,
+			start_mark:      start_mark,
+			end_mark:        end_mark,
+			anchor:          anchor,
+			tag:             tag,
+			implicit:        implicit,
+			quoted_implicit: false,
+			style:           yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+		}
+		return true
+	}
+
+	context := "while parsing a flow node"
+	if block {
+		context = "while parsing a block node"
+	}
+	yaml_parser_set_parser_error_context(parser, context, start_mark,
+		"did not find expected node content", token.start_mark)
+	return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+//
+//	********************  *********** *             *********
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		mark := token.end_mark
+		prior_head_len := len(parser.head_comment)
+		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, true, false)
+		} else {
+			parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+			return yaml_parser_process_empty_scalar(parser, event, mark)
+		}
+	}
+	if token.typ == yaml_BLOCK_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		parser.marks = parser.marks[:len(parser.marks)-1]
+
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+
+		skip_token(parser)
+		return true
+	}
+
+	context_mark := parser.marks[len(parser.marks)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	return yaml_parser_set_parser_error_context(parser,
+		"while parsing a block collection", context_mark,
+		"did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
+//
+//	*********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		mark := token.end_mark
+		prior_head_len := len(parser.head_comment)
+		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+			token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, true, false)
+		}
+		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, mark)
+	}
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+
+	*event = yaml_event_t{
+		typ:        yaml_SEQUENCE_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.start_mark, // [Go] Shouldn't this be token.end_mark?
+	}
+	return true
+}
+
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+	if stem_len == 0 {
+		return
+	}
+
+	token := peek_token(parser)
+	if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+		return
+	}
+
+	parser.stem_comment = parser.head_comment[:stem_len]
+	if len(parser.head_comment) == stem_len {
+		parser.head_comment = nil
+	} else {
+		// Copy suffix to prevent very strange bugs if someone ever appends
+		// further bytes to the prefix in the stem_comment slice above.
+		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+	}
+}
+
+// Parse the productions:
+// block_mapping        ::= BLOCK-MAPPING_START
+//
+//	*******************
+//	((KEY block_node_or_indentless_sequence?)?
+//	  *** *
+//	(VALUE block_node_or_indentless_sequence?)?)*
+//
+//	BLOCK-END
+//	*********
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	// [Go] A tail comment was left from the prior mapping value processed. Emit an event
+	//      as it needs to be processed with that value and not the following key.
+	if len(parser.tail_comment) > 0 {
+		*event = yaml_event_t{
+			typ:          yaml_TAIL_COMMENT_EVENT,
+			start_mark:   token.start_mark,
+			end_mark:     token.end_mark,
+			foot_comment: parser.tail_comment,
+		}
+		parser.tail_comment = nil
+		return true
+	}
+
+	if token.typ == yaml_KEY_TOKEN {
+		mark := token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+			return yaml_parser_parse_node(parser, event, true, true)
+		} else {
+			parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+			return yaml_parser_process_empty_scalar(parser, event, mark)
+		}
+	} else if token.typ == yaml_BLOCK_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		parser.marks = parser.marks[:len(parser.marks)-1]
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+
+	context_mark := parser.marks[len(parser.marks)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	return yaml_parser_set_parser_error_context(parser,
+		"while parsing a block mapping", context_mark,
+		"did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping        ::= BLOCK-MAPPING_START
+//
+//	((KEY block_node_or_indentless_sequence?)?
+//
+//	(VALUE block_node_or_indentless_sequence?)?)*
+//	 ***** *
+//	BLOCK-END
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		mark := token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+			return yaml_parser_parse_node(parser, event, true, true)
+		}
+		parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, mark)
+	}
+	parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence        ::= FLOW-SEQUENCE-START
+//
+//	*******************
+//	(flow_sequence_entry FLOW-ENTRY)*
+//	 *                   **********
+//	flow_sequence_entry?
+//	*
+//	FLOW-SEQUENCE-END
+//	*****************
+//
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+		if !first {
+			if token.typ == yaml_FLOW_ENTRY_TOKEN {
+				skip_token(parser)
+				token = peek_token(parser)
+				if token == nil {
+					return false
+				}
+			} else {
+				context_mark := parser.marks[len(parser.marks)-1]
+				parser.marks = parser.marks[:len(parser.marks)-1]
+				return yaml_parser_set_parser_error_context(parser,
+					"while parsing a flow sequence", context_mark,
+					"did not find expected ',' or ']'", token.start_mark)
+			}
+		}
+
+		if token.typ == yaml_KEY_TOKEN {
+			parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+			*event = yaml_event_t{
+				typ:        yaml_MAPPING_START_EVENT,
+				start_mark: token.start_mark,
+				end_mark:   token.end_mark,
+				implicit:   true,
+				style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+			}
+			skip_token(parser)
+			return true
+		} else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+
+	*event = yaml_event_t{
+		typ:        yaml_SEQUENCE_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+	}
+	yaml_parser_set_event_comments(parser, event)
+
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*** *
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_VALUE_TOKEN &&
+		token.typ != yaml_FLOW_ENTRY_TOKEN &&
+		token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+		parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+		return yaml_parser_parse_node(parser, event, false, false)
+	}
+	mark := token.end_mark
+	skip_token(parser)
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+	return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	***** *
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		skip_token(parser)
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+	*event = yaml_event_t{
+		typ:        yaml_MAPPING_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.start_mark, // [Go] Shouldn't this be end_mark?
+	}
+	return true
+}
+
+// Parse the productions:
+// flow_mapping         ::= FLOW-MAPPING-START
+//
+//	******************
+//	(flow_mapping_entry FLOW-ENTRY)*
+//	 *                  **********
+//	flow_mapping_entry?
+//	******************
+//	FLOW-MAPPING-END
+//	****************
+//
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//   - *** *
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+		if !first {
+			if token.typ == yaml_FLOW_ENTRY_TOKEN {
+				skip_token(parser)
+				token = peek_token(parser)
+				if token == nil {
+					return false
+				}
+			} else {
+				context_mark := parser.marks[len(parser.marks)-1]
+				parser.marks = parser.marks[:len(parser.marks)-1]
+				return yaml_parser_set_parser_error_context(parser,
+					"while parsing a flow mapping", context_mark,
+					"did not find expected ',' or '}'", token.start_mark)
+			}
+		}
+
+		if token.typ == yaml_KEY_TOKEN {
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+			if token.typ != yaml_VALUE_TOKEN &&
+				token.typ != yaml_FLOW_ENTRY_TOKEN &&
+				token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+				parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+				return yaml_parser_parse_node(parser, event, false, false)
+			} else {
+				parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+				return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+			}
+		} else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	*event = yaml_event_t{
+		typ:        yaml_MAPPING_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+	}
+	yaml_parser_set_event_comments(parser, event)
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//   - ***** *
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if empty {
+		parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+	parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+	*event = yaml_event_t{
+		typ:        yaml_SCALAR_EVENT,
+		start_mark: mark,
+		end_mark:   mark,
+		value:      nil, // Empty
+		implicit:   true,
+		style:      yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+	}
+	return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+	{[]byte("!"), []byte("!")},
+	{[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+	version_directive_ref **yaml_version_directive_t,
+	tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+	var version_directive *yaml_version_directive_t
+	var tag_directives []yaml_tag_directive_t
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+		if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+			if version_directive != nil {
+				yaml_parser_set_parser_error(parser,
+					"found duplicate %YAML directive", token.start_mark)
+				return false
+			}
+			if token.major != 1 || token.minor != 1 {
+				yaml_parser_set_parser_error(parser,
+					"found incompatible YAML document", token.start_mark)
+				return false
+			}
+			version_directive = &yaml_version_directive_t{
+				major: token.major,
+				minor: token.minor,
+			}
+		} else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+			value := yaml_tag_directive_t{
+				handle: token.value,
+				prefix: token.prefix,
+			}
+			if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+				return false
+			}
+			tag_directives = append(tag_directives, value)
+		}
+
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+	}
+
+	for i := range default_tag_directives {
+		if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+			return false
+		}
+	}
+
+	if version_directive_ref != nil {
+		*version_directive_ref = version_directive
+	}
+	if tag_directives_ref != nil {
+		*tag_directives_ref = tag_directives
+	}
+	return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+	for i := range parser.tag_directives {
+		if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+			if allow_duplicates {
+				return true
+			}
+			return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+		}
+	}
+
+	// [Go] I suspect the copy is unnecessary. This was likely done
+	// because there was no way to track ownership of the data.
+	value_copy := yaml_tag_directive_t{
+		handle: make([]byte, len(value.handle)),
+		prefix: make([]byte, len(value.prefix)),
+	}
+	copy(value_copy.handle, value.handle)
+	copy(value_copy.prefix, value.prefix)
+	parser.tag_directives = append(parser.tag_directives, value_copy)
+	return true
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/readerc.go b/history-api/vendor/go.yaml.in/yaml/v3/readerc.go
new file mode 100644
index 00000000..56af2453
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/readerc.go
@@ -0,0 +1,434 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+	parser.error = yaml_READER_ERROR
+	parser.problem = problem
+	parser.problem_offset = offset
+	parser.problem_value = value
+	return false
+}
+
+// Byte order marks.
+const (
+	bom_UTF8    = "\xef\xbb\xbf"
+	bom_UTF16LE = "\xff\xfe"
+	bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+	// Ensure that we had enough bytes in the raw buffer.
+	for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+		if !yaml_parser_update_raw_buffer(parser) {
+			return false
+		}
+	}
+
+	// Determine the encoding.
+	buf := parser.raw_buffer
+	pos := parser.raw_buffer_pos
+	avail := len(buf) - pos
+	if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+		parser.encoding = yaml_UTF16LE_ENCODING
+		parser.raw_buffer_pos += 2
+		parser.offset += 2
+	} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+		parser.encoding = yaml_UTF16BE_ENCODING
+		parser.raw_buffer_pos += 2
+		parser.offset += 2
+	} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+		parser.encoding = yaml_UTF8_ENCODING
+		parser.raw_buffer_pos += 3
+		parser.offset += 3
+	} else {
+		parser.encoding = yaml_UTF8_ENCODING
+	}
+	return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+	size_read := 0
+
+	// Return if the raw buffer is full.
+	if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+		return true
+	}
+
+	// Return on EOF.
+	if parser.eof {
+		return true
+	}
+
+	// Move the remaining bytes in the raw buffer to the beginning.
+	if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+		copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+	}
+	parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+	parser.raw_buffer_pos = 0
+
+	// Call the read handler to fill the buffer.
+	size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+	parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+	if err == io.EOF {
+		parser.eof = true
+	} else if err != nil {
+		return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+	}
+	return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+	if parser.read_handler == nil {
+		panic("read handler must be set")
+	}
+
+	// [Go] This function was changed to guarantee the requested length size at EOF.
+	// The fact we need to do this is pretty awful, but the description above implies
+	// for that to be the case, and there are tests
+
+	// If the EOF flag is set and the raw buffer is empty, do nothing.
+	if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+		// [Go] ACTUALLY! Read the documentation of this function above.
+		// This is just broken. To return true, we need to have the
+		// given length in the buffer. Not doing that means every single
+		// check that calls this function to make sure the buffer has a
+		// given length is Go) panicking; or C) accessing invalid memory.
+		//return true
+	}
+
+	// Return if the buffer contains enough characters.
+	if parser.unread >= length {
+		return true
+	}
+
+	// Determine the input encoding if it is not known yet.
+	if parser.encoding == yaml_ANY_ENCODING {
+		if !yaml_parser_determine_encoding(parser) {
+			return false
+		}
+	}
+
+	// Move the unread characters to the beginning of the buffer.
+	buffer_len := len(parser.buffer)
+	if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+		copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+		buffer_len -= parser.buffer_pos
+		parser.buffer_pos = 0
+	} else if parser.buffer_pos == buffer_len {
+		buffer_len = 0
+		parser.buffer_pos = 0
+	}
+
+	// Open the whole buffer for writing, and cut it before returning.
+	parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+	// Fill the buffer until it has enough characters.
+	first := true
+	for parser.unread < length {
+
+		// Fill the raw buffer if necessary.
+		if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+			if !yaml_parser_update_raw_buffer(parser) {
+				parser.buffer = parser.buffer[:buffer_len]
+				return false
+			}
+		}
+		first = false
+
+		// Decode the raw buffer.
+	inner:
+		for parser.raw_buffer_pos != len(parser.raw_buffer) {
+			var value rune
+			var width int
+
+			raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+			// Decode the next character.
+			switch parser.encoding {
+			case yaml_UTF8_ENCODING:
+				// Decode a UTF-8 character.  Check RFC 3629
+				// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+				//
+				// The following table (taken from the RFC) is used for
+				// decoding.
+				//
+				//    Char. number range |        UTF-8 octet sequence
+				//      (hexadecimal)    |              (binary)
+				//   --------------------+------------------------------------
+				//   0000 0000-0000 007F | 0xxxxxxx
+				//   0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+				//   0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+				//   0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+				//
+				// Additionally, the characters in the range 0xD800-0xDFFF
+				// are prohibited as they are reserved for use with UTF-16
+				// surrogate pairs.
+
+				// Determine the length of the UTF-8 sequence.
+				octet := parser.raw_buffer[parser.raw_buffer_pos]
+				switch {
+				case octet&0x80 == 0x00:
+					width = 1
+				case octet&0xE0 == 0xC0:
+					width = 2
+				case octet&0xF0 == 0xE0:
+					width = 3
+				case octet&0xF8 == 0xF0:
+					width = 4
+				default:
+					// The leading octet is invalid.
+					return yaml_parser_set_reader_error(parser,
+						"invalid leading UTF-8 octet",
+						parser.offset, int(octet))
+				}
+
+				// Check if the raw buffer contains an incomplete character.
+				if width > raw_unread {
+					if parser.eof {
+						return yaml_parser_set_reader_error(parser,
+							"incomplete UTF-8 octet sequence",
+							parser.offset, -1)
+					}
+					break inner
+				}
+
+				// Decode the leading octet.
+				switch {
+				case octet&0x80 == 0x00:
+					value = rune(octet & 0x7F)
+				case octet&0xE0 == 0xC0:
+					value = rune(octet & 0x1F)
+				case octet&0xF0 == 0xE0:
+					value = rune(octet & 0x0F)
+				case octet&0xF8 == 0xF0:
+					value = rune(octet & 0x07)
+				default:
+					value = 0
+				}
+
+				// Check and decode the trailing octets.
+				for k := 1; k < width; k++ {
+					octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+					// Check if the octet is valid.
+					if (octet & 0xC0) != 0x80 {
+						return yaml_parser_set_reader_error(parser,
+							"invalid trailing UTF-8 octet",
+							parser.offset+k, int(octet))
+					}
+
+					// Decode the octet.
+					value = (value << 6) + rune(octet&0x3F)
+				}
+
+				// Check the length of the sequence against the value.
+				switch {
+				case width == 1:
+				case width == 2 && value >= 0x80:
+				case width == 3 && value >= 0x800:
+				case width == 4 && value >= 0x10000:
+				default:
+					return yaml_parser_set_reader_error(parser,
+						"invalid length of a UTF-8 sequence",
+						parser.offset, -1)
+				}
+
+				// Check the range of the value.
+				if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+					return yaml_parser_set_reader_error(parser,
+						"invalid Unicode character",
+						parser.offset, int(value))
+				}
+
+			case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+				var low, high int
+				if parser.encoding == yaml_UTF16LE_ENCODING {
+					low, high = 0, 1
+				} else {
+					low, high = 1, 0
+				}
+
+				// The UTF-16 encoding is not as simple as one might
+				// naively think.  Check RFC 2781
+				// (http://www.ietf.org/rfc/rfc2781.txt).
+				//
+				// Normally, two subsequent bytes describe a Unicode
+				// character.  However a special technique (called a
+				// surrogate pair) is used for specifying character
+				// values larger than 0xFFFF.
+				//
+				// A surrogate pair consists of two pseudo-characters:
+				//      high surrogate area (0xD800-0xDBFF)
+				//      low surrogate area (0xDC00-0xDFFF)
+				//
+				// The following formulas are used for decoding
+				// and encoding characters using surrogate pairs:
+				//
+				//  U  = U' + 0x10000   (0x01 00 00 <= U <= 0x10 FF FF)
+				//  U' = yyyyyyyyyyxxxxxxxxxx   (0 <= U' <= 0x0F FF FF)
+				//  W1 = 110110yyyyyyyyyy
+				//  W2 = 110111xxxxxxxxxx
+				//
+				// where U is the character value, W1 is the high surrogate
+				// area, W2 is the low surrogate area.
+
+				// Check for incomplete UTF-16 character.
+				if raw_unread < 2 {
+					if parser.eof {
+						return yaml_parser_set_reader_error(parser,
+							"incomplete UTF-16 character",
+							parser.offset, -1)
+					}
+					break inner
+				}
+
+				// Get the character.
+				value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+					(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+				// Check for unexpected low surrogate area.
+				if value&0xFC00 == 0xDC00 {
+					return yaml_parser_set_reader_error(parser,
+						"unexpected low surrogate area",
+						parser.offset, int(value))
+				}
+
+				// Check for a high surrogate area.
+				if value&0xFC00 == 0xD800 {
+					width = 4
+
+					// Check for incomplete surrogate pair.
+					if raw_unread < 4 {
+						if parser.eof {
+							return yaml_parser_set_reader_error(parser,
+								"incomplete UTF-16 surrogate pair",
+								parser.offset, -1)
+						}
+						break inner
+					}
+
+					// Get the next character.
+					value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+						(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+					// Check for a low surrogate area.
+					if value2&0xFC00 != 0xDC00 {
+						return yaml_parser_set_reader_error(parser,
+							"expected low surrogate area",
+							parser.offset+2, int(value2))
+					}
+
+					// Generate the value of the surrogate pair.
+					value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+				} else {
+					width = 2
+				}
+
+			default:
+				panic("impossible")
+			}
+
+			// Check if the character is in the allowed range:
+			//      #x9 | #xA | #xD | [#x20-#x7E]               (8 bit)
+			//      | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD]    (16 bit)
+			//      | [#x10000-#x10FFFF]                        (32 bit)
+			switch {
+			case value == 0x09:
+			case value == 0x0A:
+			case value == 0x0D:
+			case value >= 0x20 && value <= 0x7E:
+			case value == 0x85:
+			case value >= 0xA0 && value <= 0xD7FF:
+			case value >= 0xE000 && value <= 0xFFFD:
+			case value >= 0x10000 && value <= 0x10FFFF:
+			default:
+				return yaml_parser_set_reader_error(parser,
+					"control characters are not allowed",
+					parser.offset, int(value))
+			}
+
+			// Move the raw pointers.
+			parser.raw_buffer_pos += width
+			parser.offset += width
+
+			// Finally put the character into the buffer.
+			if value <= 0x7F {
+				// 0000 0000-0000 007F . 0xxxxxxx
+				parser.buffer[buffer_len+0] = byte(value)
+				buffer_len += 1
+			} else if value <= 0x7FF {
+				// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+				parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+				buffer_len += 2
+			} else if value <= 0xFFFF {
+				// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+				parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+				parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+				buffer_len += 3
+			} else {
+				// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+				parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+				parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+				parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+				buffer_len += 4
+			}
+
+			parser.unread++
+		}
+
+		// On EOF, put NUL into the buffer and return.
+		if parser.eof {
+			parser.buffer[buffer_len] = 0
+			buffer_len++
+			parser.unread++
+			break
+		}
+	}
+	// [Go] Read the documentation of this function above. To return true,
+	// we need to have the given length in the buffer. Not doing that means
+	// every single check that calls this function to make sure the buffer
+	// has a given length is Go) panicking; or C) accessing invalid memory.
+	// This happens here due to the EOF above breaking early.
+	for buffer_len < length {
+		parser.buffer[buffer_len] = 0
+		buffer_len++
+	}
+	parser.buffer = parser.buffer[:buffer_len]
+	return true
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/resolve.go b/history-api/vendor/go.yaml.in/yaml/v3/resolve.go
new file mode 100644
index 00000000..64ae8880
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/resolve.go
@@ -0,0 +1,326 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding/base64"
+	"math"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type resolveMapItem struct {
+	value interface{}
+	tag   string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+	t := resolveTable
+	t[int('+')] = 'S' // Sign
+	t[int('-')] = 'S'
+	for _, c := range "0123456789" {
+		t[int(c)] = 'D' // Digit
+	}
+	for _, c := range "yYnNtTfFoO~" {
+		t[int(c)] = 'M' // In map
+	}
+	t[int('.')] = '.' // Float (potentially in map)
+
+	var resolveMapList = []struct {
+		v   interface{}
+		tag string
+		l   []string
+	}{
+		{true, boolTag, []string{"true", "True", "TRUE"}},
+		{false, boolTag, []string{"false", "False", "FALSE"}},
+		{nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+		{math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+		{math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+		{math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+		{math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+		{"<<", mergeTag, []string{"<<"}},
+	}
+
+	m := resolveMap
+	for _, item := range resolveMapList {
+		for _, s := range item.l {
+			m[s] = resolveMapItem{item.v, item.tag}
+		}
+	}
+}
+
+const (
+	nullTag      = "!!null"
+	boolTag      = "!!bool"
+	strTag       = "!!str"
+	intTag       = "!!int"
+	floatTag     = "!!float"
+	timestampTag = "!!timestamp"
+	seqTag       = "!!seq"
+	mapTag       = "!!map"
+	binaryTag    = "!!binary"
+	mergeTag     = "!!merge"
+)
+
+var longTags = make(map[string]string)
+var shortTags = make(map[string]string)
+
+func init() {
+	for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+		ltag := longTag(stag)
+		longTags[stag] = ltag
+		shortTags[ltag] = stag
+	}
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+	if strings.HasPrefix(tag, longTagPrefix) {
+		if stag, ok := shortTags[tag]; ok {
+			return stag
+		}
+		return "!!" + tag[len(longTagPrefix):]
+	}
+	return tag
+}
+
+func longTag(tag string) string {
+	if strings.HasPrefix(tag, "!!") {
+		if ltag, ok := longTags[tag]; ok {
+			return ltag
+		}
+		return longTagPrefix + tag[2:]
+	}
+	return tag
+}
+
+func resolvableTag(tag string) bool {
+	switch tag {
+	case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
+		return true
+	}
+	return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+	tag = shortTag(tag)
+	if !resolvableTag(tag) {
+		return tag, in
+	}
+
+	defer func() {
+		switch tag {
+		case "", rtag, strTag, binaryTag:
+			return
+		case floatTag:
+			if rtag == intTag {
+				switch v := out.(type) {
+				case int64:
+					rtag = floatTag
+					out = float64(v)
+					return
+				case int:
+					rtag = floatTag
+					out = float64(v)
+					return
+				}
+			}
+		}
+		failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+	}()
+
+	// Any data is accepted as a !!str or !!binary.
+	// Otherwise, the prefix is enough of a hint about what it might be.
+	hint := byte('N')
+	if in != "" {
+		hint = resolveTable[in[0]]
+	}
+	if hint != 0 && tag != strTag && tag != binaryTag {
+		// Handle things we can lookup in a map.
+		if item, ok := resolveMap[in]; ok {
+			return item.tag, item.value
+		}
+
+		// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+		// are purposefully unsupported here. They're still quoted on
+		// the way out for compatibility with other parser, though.
+
+		switch hint {
+		case 'M':
+			// We've already checked the map above.
+
+		case '.':
+			// Not in the map, so maybe a normal float.
+			floatv, err := strconv.ParseFloat(in, 64)
+			if err == nil {
+				return floatTag, floatv
+			}
+
+		case 'D', 'S':
+			// Int, float, or timestamp.
+			// Only try values as a timestamp if the value is unquoted or there's an explicit
+			// !!timestamp tag.
+			if tag == "" || tag == timestampTag {
+				t, ok := parseTimestamp(in)
+				if ok {
+					return timestampTag, t
+				}
+			}
+
+			plain := strings.Replace(in, "_", "", -1)
+			intv, err := strconv.ParseInt(plain, 0, 64)
+			if err == nil {
+				if intv == int64(int(intv)) {
+					return intTag, int(intv)
+				} else {
+					return intTag, intv
+				}
+			}
+			uintv, err := strconv.ParseUint(plain, 0, 64)
+			if err == nil {
+				return intTag, uintv
+			}
+			if yamlStyleFloat.MatchString(plain) {
+				floatv, err := strconv.ParseFloat(plain, 64)
+				if err == nil {
+					return floatTag, floatv
+				}
+			}
+			if strings.HasPrefix(plain, "0b") {
+				intv, err := strconv.ParseInt(plain[2:], 2, 64)
+				if err == nil {
+					if intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+				uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+				if err == nil {
+					return intTag, uintv
+				}
+			} else if strings.HasPrefix(plain, "-0b") {
+				intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
+				if err == nil {
+					if true || intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+			}
+			// Octals as introduced in version 1.2 of the spec.
+			// Octals from the 1.1 spec, spelled as 0777, are still
+			// decoded by default in v3 as well for compatibility.
+			// May be dropped in v4 depending on how usage evolves.
+			if strings.HasPrefix(plain, "0o") {
+				intv, err := strconv.ParseInt(plain[2:], 8, 64)
+				if err == nil {
+					if intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+				uintv, err := strconv.ParseUint(plain[2:], 8, 64)
+				if err == nil {
+					return intTag, uintv
+				}
+			} else if strings.HasPrefix(plain, "-0o") {
+				intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
+				if err == nil {
+					if true || intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+			}
+		default:
+			panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
+		}
+	}
+	return strTag, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+	const lineLen = 70
+	encLen := base64.StdEncoding.EncodedLen(len(s))
+	lines := encLen/lineLen + 1
+	buf := make([]byte, encLen*2+lines)
+	in := buf[0:encLen]
+	out := buf[encLen:]
+	base64.StdEncoding.Encode(in, []byte(s))
+	k := 0
+	for i := 0; i < len(in); i += lineLen {
+		j := i + lineLen
+		if j > len(in) {
+			j = len(in)
+		}
+		k += copy(out[k:], in[i:j])
+		if lines > 1 {
+			out[k] = '\n'
+			k++
+		}
+	}
+	return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+	"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+	"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+	"2006-1-2 15:4:5.999999999",       // space separated with no time zone
+	"2006-1-2",                        // date only
+	// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+	// from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+	// TODO write code to check all the formats supported by
+	// http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+	// Quick check: all date formats start with YYYY-.
+	i := 0
+	for ; i < len(s); i++ {
+		if c := s[i]; c < '0' || c > '9' {
+			break
+		}
+	}
+	if i != 4 || i == len(s) || s[i] != '-' {
+		return time.Time{}, false
+	}
+	for _, format := range allowedTimestampFormats {
+		if t, err := time.Parse(format, s); err == nil {
+			return t, true
+		}
+	}
+	return time.Time{}, false
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/scannerc.go b/history-api/vendor/go.yaml.in/yaml/v3/scannerc.go
new file mode 100644
index 00000000..30b1f089
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/scannerc.go
@@ -0,0 +1,3040 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html).  We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward.  The issues are "block collection start" and
+// "simple keys".  Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented.  We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+//      STREAM-START(encoding)          # The stream start.
+//      STREAM-END                      # The stream end.
+//      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
+//      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
+//      DOCUMENT-START                  # '---'
+//      DOCUMENT-END                    # '...'
+//      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
+//      BLOCK-MAPPING-START             # sequence or a block mapping.
+//      BLOCK-END                       # Indentation decrease.
+//      FLOW-SEQUENCE-START             # '['
+//      FLOW-SEQUENCE-END               # ']'
+//      BLOCK-SEQUENCE-START            # '{'
+//      BLOCK-SEQUENCE-END              # '}'
+//      BLOCK-ENTRY                     # '-'
+//      FLOW-ENTRY                      # ','
+//      KEY                             # '?' or nothing (simple keys).
+//      VALUE                           # ':'
+//      ALIAS(anchor)                   # '*anchor'
+//      ANCHOR(anchor)                  # '&anchor'
+//      TAG(handle,suffix)              # '!handle!suffix'
+//      SCALAR(value,style)             # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+//      STREAM-START(encoding)
+//      STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+//      VERSION-DIRECTIVE(major,minor)
+//      TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+//      %YAML   1.1
+//      %TAG    !   !foo
+//      %TAG    !yaml!  tag:yaml.org,2002:
+//      ---
+//
+// The correspoding sequence of tokens:
+//
+//      STREAM-START(utf-8)
+//      VERSION-DIRECTIVE(1,1)
+//      TAG-DIRECTIVE("!","!foo")
+//      TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+//      DOCUMENT-START
+//      STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+//      DOCUMENT-START
+//      DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+//      1. An implicit document:
+//
+//          'a scalar'
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          SCALAR("a scalar",single-quoted)
+//          STREAM-END
+//
+//      2. An explicit document:
+//
+//          ---
+//          'a scalar'
+//          ...
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          DOCUMENT-START
+//          SCALAR("a scalar",single-quoted)
+//          DOCUMENT-END
+//          STREAM-END
+//
+//      3. Several documents in a stream:
+//
+//          'a scalar'
+//          ---
+//          'another scalar'
+//          ---
+//          'yet another scalar'
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          SCALAR("a scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("another scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("yet another scalar",single-quoted)
+//          STREAM-END
+//
+// We have already introduced the SCALAR token above.  The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+//      ALIAS(anchor)
+//      ANCHOR(anchor)
+//      TAG(handle,suffix)
+//      SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+//      1. A recursive sequence:
+//
+//          &A [ *A ]
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          ANCHOR("A")
+//          FLOW-SEQUENCE-START
+//          ALIAS("A")
+//          FLOW-SEQUENCE-END
+//          STREAM-END
+//
+//      2. A tagged scalar:
+//
+//          !!float "3.14"  # A good approximation.
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          TAG("!!","float")
+//          SCALAR("3.14",double-quoted)
+//          STREAM-END
+//
+//      3. Various scalar styles:
+//
+//          --- # Implicit empty plain scalars do not produce tokens.
+//          --- a plain scalar
+//          --- 'a single-quoted scalar'
+//          --- "a double-quoted scalar"
+//          --- |-
+//            a literal scalar
+//          --- >-
+//            a folded
+//            scalar
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          DOCUMENT-START
+//          DOCUMENT-START
+//          SCALAR("a plain scalar",plain)
+//          DOCUMENT-START
+//          SCALAR("a single-quoted scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("a double-quoted scalar",double-quoted)
+//          DOCUMENT-START
+//          SCALAR("a literal scalar",literal)
+//          DOCUMENT-START
+//          SCALAR("a folded scalar",folded)
+//          STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+//      FLOW-SEQUENCE-START
+//      FLOW-SEQUENCE-END
+//      FLOW-MAPPING-START
+//      FLOW-MAPPING-END
+//      FLOW-ENTRY
+//      KEY
+//      VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly.  FLOW-ENTRY represent the ',' indicator.  Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+//      1. A flow sequence:
+//
+//          [item 1, item 2, item 3]
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          FLOW-SEQUENCE-START
+//          SCALAR("item 1",plain)
+//          FLOW-ENTRY
+//          SCALAR("item 2",plain)
+//          FLOW-ENTRY
+//          SCALAR("item 3",plain)
+//          FLOW-SEQUENCE-END
+//          STREAM-END
+//
+//      2. A flow mapping:
+//
+//          {
+//              a simple key: a value,  # Note that the KEY token is produced.
+//              ? a complex key: another value,
+//          }
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          FLOW-MAPPING-START
+//          KEY
+//          SCALAR("a simple key",plain)
+//          VALUE
+//          SCALAR("a value",plain)
+//          FLOW-ENTRY
+//          KEY
+//          SCALAR("a complex key",plain)
+//          VALUE
+//          SCALAR("another value",plain)
+//          FLOW-ENTRY
+//          FLOW-MAPPING-END
+//          STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator.  Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+//      BLOCK-SEQUENCE-START
+//      BLOCK-MAPPING-START
+//      BLOCK-END
+//      BLOCK-ENTRY
+//      KEY
+//      VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python).  However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+//      1. Block sequences:
+//
+//          - item 1
+//          - item 2
+//          -
+//            - item 3.1
+//            - item 3.2
+//          -
+//            key 1: value 1
+//            key 2: value 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-ENTRY
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 3.1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 3.2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+//      2. Block mappings:
+//
+//          a simple key: a value   # The KEY token is produced here.
+//          ? a complex key
+//          : another value
+//          a mapping:
+//            key 1: value 1
+//            key 2: value 2
+//          a sequence:
+//            - item 1
+//            - item 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("a simple key",plain)
+//          VALUE
+//          SCALAR("a value",plain)
+//          KEY
+//          SCALAR("a complex key",plain)
+//          VALUE
+//          SCALAR("another value",plain)
+//          KEY
+//          SCALAR("a mapping",plain)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          KEY
+//          SCALAR("a sequence",plain)
+//          VALUE
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line.  If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line.  The following examples
+// illustrate this case:
+//
+//      1. Collections in a sequence:
+//
+//          - - item 1
+//            - item 2
+//          - key 1: value 1
+//            key 2: value 2
+//          - ? complex key
+//            : complex value
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("complex key")
+//          VALUE
+//          SCALAR("complex value")
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+//      2. Collections in a mapping:
+//
+//          ? a sequence
+//          : - item 1
+//            - item 2
+//          ? a mapping
+//          : key 1: value 1
+//            key 2: value 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("a sequence",plain)
+//          VALUE
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          KEY
+//          SCALAR("a mapping",plain)
+//          VALUE
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping.  In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+//      key:
+//      - item 1    # BLOCK-SEQUENCE-START is NOT produced here.
+//      - item 2
+//
+// Tokens:
+//
+//      STREAM-START(utf-8)
+//      BLOCK-MAPPING-START
+//      KEY
+//      SCALAR("key",plain)
+//      VALUE
+//      BLOCK-ENTRY
+//      SCALAR("item 1",plain)
+//      BLOCK-ENTRY
+//      SCALAR("item 2",plain)
+//      BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+	// [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+	return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		parser.newlines = 0
+	}
+	parser.mark.index++
+	parser.mark.column++
+	parser.unread--
+	parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+	if is_crlf(parser.buffer, parser.buffer_pos) {
+		parser.mark.index += 2
+		parser.mark.column = 0
+		parser.mark.line++
+		parser.unread -= 2
+		parser.buffer_pos += 2
+		parser.newlines++
+	} else if is_break(parser.buffer, parser.buffer_pos) {
+		parser.mark.index++
+		parser.mark.column = 0
+		parser.mark.line++
+		parser.unread--
+		parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+		parser.newlines++
+	}
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		parser.newlines = 0
+	}
+	w := width(parser.buffer[parser.buffer_pos])
+	if w == 0 {
+		panic("invalid character sequence")
+	}
+	if len(s) == 0 {
+		s = make([]byte, 0, 32)
+	}
+	if w == 1 && len(s)+w <= cap(s) {
+		s = s[:len(s)+1]
+		s[len(s)-1] = parser.buffer[parser.buffer_pos]
+		parser.buffer_pos++
+	} else {
+		s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+		parser.buffer_pos += w
+	}
+	parser.mark.index++
+	parser.mark.column++
+	parser.unread--
+	return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+	buf := parser.buffer
+	pos := parser.buffer_pos
+	switch {
+	case buf[pos] == '\r' && buf[pos+1] == '\n':
+		// CR LF . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 2
+		parser.mark.index++
+		parser.unread--
+	case buf[pos] == '\r' || buf[pos] == '\n':
+		// CR|LF . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 1
+	case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+		// NEL . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 2
+	case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+		// LS|PS . LS|PS
+		s = append(s, buf[parser.buffer_pos:pos+3]...)
+		parser.buffer_pos += 3
+	default:
+		return s
+	}
+	parser.mark.index++
+	parser.mark.column = 0
+	parser.mark.line++
+	parser.unread--
+	parser.newlines++
+	return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+	// Erase the token object.
+	*token = yaml_token_t{} // [Go] Is this necessary?
+
+	// No tokens after STREAM-END or error.
+	if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+		return true
+	}
+
+	// Ensure that the tokens queue contains enough tokens.
+	if !parser.token_available {
+		if !yaml_parser_fetch_more_tokens(parser) {
+			return false
+		}
+	}
+
+	// Fetch the next token from the queue.
+	*token = parser.tokens[parser.tokens_head]
+	parser.tokens_head++
+	parser.tokens_parsed++
+	parser.token_available = false
+
+	if token.typ == yaml_STREAM_END_TOKEN {
+		parser.stream_end_produced = true
+	}
+	return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+	parser.error = yaml_SCANNER_ERROR
+	parser.context = context
+	parser.context_mark = context_mark
+	parser.problem = problem
+	parser.problem_mark = parser.mark
+	return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+	context := "while parsing a tag"
+	if directive {
+		context = "while parsing a %TAG directive"
+	}
+	return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+	pargs := append([]interface{}{"+++"}, args...)
+	fmt.Println(pargs...)
+	pargs = append([]interface{}{"---"}, args...)
+	return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+	// While we need more tokens to fetch, do it.
+	for {
+		// [Go] The comment parsing logic requires a lookahead of two tokens
+		// so that foot comments may be parsed in time of associating them
+		// with the tokens that are parsed before them, and also for line
+		// comments to be transformed into head comments in some edge cases.
+		if parser.tokens_head < len(parser.tokens)-2 {
+			// If a potential simple key is at the head position, we need to fetch
+			// the next token to disambiguate it.
+			head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
+			if !ok {
+				break
+			} else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
+				return false
+			} else if !valid {
+				break
+			}
+		}
+		// Fetch the next token.
+		if !yaml_parser_fetch_next_token(parser) {
+			return false
+		}
+	}
+
+	parser.token_available = true
+	return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
+	// Ensure that the buffer is initialized.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// Check if we just started scanning.  Fetch STREAM-START then.
+	if !parser.stream_start_produced {
+		return yaml_parser_fetch_stream_start(parser)
+	}
+
+	scan_mark := parser.mark
+
+	// Eat whitespaces and comments until we reach the next token.
+	if !yaml_parser_scan_to_next_token(parser) {
+		return false
+	}
+
+	// [Go] While unrolling indents, transform the head comments of prior
+	// indentation levels observed after scan_start into foot comments at
+	// the respective indexes.
+
+	// Check the indentation level against the current column.
+	if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
+		return false
+	}
+
+	// Ensure that the buffer contains at least 4 characters.  4 is the length
+	// of the longest indicators ('--- ' and '... ').
+	if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+		return false
+	}
+
+	// Is it the end of the stream?
+	if is_z(parser.buffer, parser.buffer_pos) {
+		return yaml_parser_fetch_stream_end(parser)
+	}
+
+	// Is it a directive?
+	if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+		return yaml_parser_fetch_directive(parser)
+	}
+
+	buf := parser.buffer
+	pos := parser.buffer_pos
+
+	// Is it the document start indicator?
+	if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+		return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+	}
+
+	// Is it the document end indicator?
+	if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+		return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+	}
+
+	comment_mark := parser.mark
+	if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+		// Associate any following comments with the prior token.
+		comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
+	}
+	defer func() {
+		if !ok {
+			return
+		}
+		if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+			// Sequence indicators alone have no line comments. It becomes
+			// a head comment for whatever follows.
+			return
+		}
+		if !yaml_parser_scan_line_comment(parser, comment_mark) {
+			ok = false
+			return
+		}
+	}()
+
+	// Is it the flow sequence start indicator?
+	if buf[pos] == '[' {
+		return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+	}
+
+	// Is it the flow mapping start indicator?
+	if parser.buffer[parser.buffer_pos] == '{' {
+		return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+	}
+
+	// Is it the flow sequence end indicator?
+	if parser.buffer[parser.buffer_pos] == ']' {
+		return yaml_parser_fetch_flow_collection_end(parser,
+			yaml_FLOW_SEQUENCE_END_TOKEN)
+	}
+
+	// Is it the flow mapping end indicator?
+	if parser.buffer[parser.buffer_pos] == '}' {
+		return yaml_parser_fetch_flow_collection_end(parser,
+			yaml_FLOW_MAPPING_END_TOKEN)
+	}
+
+	// Is it the flow entry indicator?
+	if parser.buffer[parser.buffer_pos] == ',' {
+		return yaml_parser_fetch_flow_entry(parser)
+	}
+
+	// Is it the block entry indicator?
+	if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+		return yaml_parser_fetch_block_entry(parser)
+	}
+
+	// Is it the key indicator?
+	if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_key(parser)
+	}
+
+	// Is it the value indicator?
+	if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_value(parser)
+	}
+
+	// Is it an alias?
+	if parser.buffer[parser.buffer_pos] == '*' {
+		return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+	}
+
+	// Is it an anchor?
+	if parser.buffer[parser.buffer_pos] == '&' {
+		return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+	}
+
+	// Is it a tag?
+	if parser.buffer[parser.buffer_pos] == '!' {
+		return yaml_parser_fetch_tag(parser)
+	}
+
+	// Is it a literal scalar?
+	if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+		return yaml_parser_fetch_block_scalar(parser, true)
+	}
+
+	// Is it a folded scalar?
+	if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+		return yaml_parser_fetch_block_scalar(parser, false)
+	}
+
+	// Is it a single-quoted scalar?
+	if parser.buffer[parser.buffer_pos] == '\'' {
+		return yaml_parser_fetch_flow_scalar(parser, true)
+	}
+
+	// Is it a double-quoted scalar?
+	if parser.buffer[parser.buffer_pos] == '"' {
+		return yaml_parser_fetch_flow_scalar(parser, false)
+	}
+
+	// Is it a plain scalar?
+	//
+	// A plain scalar may start with any non-blank characters except
+	//
+	//      '-', '?', ':', ',', '[', ']', '{', '}',
+	//      '#', '&', '*', '!', '|', '>', '\'', '\"',
+	//      '%', '@', '`'.
+	//
+	// In the block context (and, for the '-' indicator, in the flow context
+	// too), it may also start with the characters
+	//
+	//      '-', '?', ':'
+	//
+	// if it is followed by a non-space character.
+	//
+	// The last rule is more restrictive than the specification requires.
+	// [Go] TODO Make this logic more reasonable.
+	//switch parser.buffer[parser.buffer_pos] {
+	//case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+	//}
+	if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+		parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+		parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+		parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+		parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+		parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+		parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+		parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+		parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+		parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+		(parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+		(parser.flow_level == 0 &&
+			(parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+			!is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_plain_scalar(parser)
+	}
+
+	// If we don't determine the token type so far, it is an error.
+	return yaml_parser_set_scanner_error(parser,
+		"while scanning for the next token", parser.mark,
+		"found character that cannot start any token")
+}
+
+func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
+	if !simple_key.possible {
+		return false, true
+	}
+
+	// The 1.2 specification says:
+	//
+	//     "If the ? indicator is omitted, parsing needs to see past the
+	//     implicit key to recognize it as such. To limit the amount of
+	//     lookahead required, the “:” indicator must appear at most 1024
+	//     Unicode characters beyond the start of the key. In addition, the key
+	//     is restricted to a single line."
+	//
+	if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
+		// Check if the potential simple key to be removed is required.
+		if simple_key.required {
+			return false, yaml_parser_set_scanner_error(parser,
+				"while scanning a simple key", simple_key.mark,
+				"could not find expected ':'")
+		}
+		simple_key.possible = false
+		return false, true
+	}
+	return true, true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+	// A simple key is required at the current position if the scanner is in
+	// the block context and the current column coincides with the indentation
+	// level.
+
+	required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+	//
+	// If the current position may start a simple key, save it.
+	//
+	if parser.simple_key_allowed {
+		simple_key := yaml_simple_key_t{
+			possible:     true,
+			required:     required,
+			token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+			mark:         parser.mark,
+		}
+
+		if !yaml_parser_remove_simple_key(parser) {
+			return false
+		}
+		parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+		parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
+	}
+	return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+	i := len(parser.simple_keys) - 1
+	if parser.simple_keys[i].possible {
+		// If the key is required, it is an error.
+		if parser.simple_keys[i].required {
+			return yaml_parser_set_scanner_error(parser,
+				"while scanning a simple key", parser.simple_keys[i].mark,
+				"could not find expected ':'")
+		}
+		// Remove the key from the stack.
+		parser.simple_keys[i].possible = false
+		delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
+	}
+	return true
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+	// Reset the simple key on the next level.
+	parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
+		possible:     false,
+		required:     false,
+		token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+		mark:         parser.mark,
+	})
+
+	// Increase the flow level.
+	parser.flow_level++
+	if parser.flow_level > max_flow_level {
+		return yaml_parser_set_scanner_error(parser,
+			"while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+			fmt.Sprintf("exceeded max depth of %d", max_flow_level))
+	}
+	return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+	if parser.flow_level > 0 {
+		parser.flow_level--
+		last := len(parser.simple_keys) - 1
+		delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
+		parser.simple_keys = parser.simple_keys[:last]
+	}
+	return true
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level.  In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+	// In the flow context, do nothing.
+	if parser.flow_level > 0 {
+		return true
+	}
+
+	if parser.indent < column {
+		// Push the current indentation level to the stack and set the new
+		// indentation level.
+		parser.indents = append(parser.indents, parser.indent)
+		parser.indent = column
+		if len(parser.indents) > max_indents {
+			return yaml_parser_set_scanner_error(parser,
+				"while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+				fmt.Sprintf("exceeded max depth of %d", max_indents))
+		}
+
+		// Create a token and insert it into the queue.
+		token := yaml_token_t{
+			typ:        typ,
+			start_mark: mark,
+			end_mark:   mark,
+		}
+		if number > -1 {
+			number -= parser.tokens_parsed
+		}
+		yaml_insert_token(parser, number, &token)
+	}
+	return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column.  For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
+	// In the flow context, do nothing.
+	if parser.flow_level > 0 {
+		return true
+	}
+
+	block_mark := scan_mark
+	block_mark.index--
+
+	// Loop through the indentation levels in the stack.
+	for parser.indent > column {
+
+		// [Go] Reposition the end token before potential following
+		//      foot comments of parent blocks. For that, search
+		//      backwards for recent comments that were at the same
+		//      indent as the block that is ending now.
+		stop_index := block_mark.index
+		for i := len(parser.comments) - 1; i >= 0; i-- {
+			comment := &parser.comments[i]
+
+			if comment.end_mark.index < stop_index {
+				// Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+				// If requested indent column is < 0, then the document is over and everything else
+				// is a foot anyway.
+				break
+			}
+			if comment.start_mark.column == parser.indent+1 {
+				// This is a good match. But maybe there's a former comment
+				// at that same indent level, so keep searching.
+				block_mark = comment.start_mark
+			}
+
+			// While the end of the former comment matches with
+			// the start of the following one, we know there's
+			// nothing in between and scanning is still safe.
+			stop_index = comment.scan_mark.index
+		}
+
+		// Create a token and append it to the queue.
+		token := yaml_token_t{
+			typ:        yaml_BLOCK_END_TOKEN,
+			start_mark: block_mark,
+			end_mark:   block_mark,
+		}
+		yaml_insert_token(parser, -1, &token)
+
+		// Pop the indentation level.
+		parser.indent = parser.indents[len(parser.indents)-1]
+		parser.indents = parser.indents[:len(parser.indents)-1]
+	}
+	return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+	// Set the initial indentation.
+	parser.indent = -1
+
+	// Initialize the simple key stack.
+	parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+	parser.simple_keys_by_tok = make(map[int]int)
+
+	// A simple key is allowed at the beginning of the stream.
+	parser.simple_key_allowed = true
+
+	// We have started.
+	parser.stream_start_produced = true
+
+	// Create the STREAM-START token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_STREAM_START_TOKEN,
+		start_mark: parser.mark,
+		end_mark:   parser.mark,
+		encoding:   parser.encoding,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+	// Force new line.
+	if parser.mark.column != 0 {
+		parser.mark.column = 0
+		parser.mark.line++
+	}
+
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Create the STREAM-END token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_STREAM_END_TOKEN,
+		start_mark: parser.mark,
+		end_mark:   parser.mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+	token := yaml_token_t{}
+	if !yaml_parser_scan_directive(parser, &token) {
+		return false
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Consume the token.
+	start_mark := parser.mark
+
+	skip(parser)
+	skip(parser)
+	skip(parser)
+
+	end_mark := parser.mark
+
+	// Create the DOCUMENT-START or DOCUMENT-END token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+
+	// The indicators '[' and '{' may start a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// Increase the flow level.
+	if !yaml_parser_increase_flow_level(parser) {
+		return false
+	}
+
+	// A simple key may follow the indicators '[' and '{'.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// Reset any potential simple key on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Decrease the flow level.
+	if !yaml_parser_decrease_flow_level(parser) {
+		return false
+	}
+
+	// No simple keys after the indicators ']' and '}'.
+	parser.simple_key_allowed = false
+
+	// Consume the token.
+
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after ','.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-ENTRY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_FLOW_ENTRY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+	// Check if the scanner is in the block context.
+	if parser.flow_level == 0 {
+		// Check if we are allowed to start a new entry.
+		if !parser.simple_key_allowed {
+			return yaml_parser_set_scanner_error(parser, "", parser.mark,
+				"block sequence entries are not allowed in this context")
+		}
+		// Add the BLOCK-SEQUENCE-START token if needed.
+		if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+			return false
+		}
+	} else {
+		// It is an error for the '-' indicator to occur in the flow context,
+		// but we let the Parser detect and report about it because the Parser
+		// is able to point to the context.
+	}
+
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after '-'.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the BLOCK-ENTRY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_BLOCK_ENTRY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+	// In the block context, additional checks are required.
+	if parser.flow_level == 0 {
+		// Check if we are allowed to start a new key (not nessesary simple).
+		if !parser.simple_key_allowed {
+			return yaml_parser_set_scanner_error(parser, "", parser.mark,
+				"mapping keys are not allowed in this context")
+		}
+		// Add the BLOCK-MAPPING-START token if needed.
+		if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+			return false
+		}
+	}
+
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after '?' in the block context.
+	parser.simple_key_allowed = parser.flow_level == 0
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the KEY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_KEY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+	simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+	// Have we found a simple key?
+	if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
+		return false
+
+	} else if valid {
+
+		// Create the KEY token and insert it into the queue.
+		token := yaml_token_t{
+			typ:        yaml_KEY_TOKEN,
+			start_mark: simple_key.mark,
+			end_mark:   simple_key.mark,
+		}
+		yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+		// In the block context, we may need to add the BLOCK-MAPPING-START token.
+		if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+			simple_key.token_number,
+			yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+			return false
+		}
+
+		// Remove the simple key.
+		simple_key.possible = false
+		delete(parser.simple_keys_by_tok, simple_key.token_number)
+
+		// A simple key cannot follow another simple key.
+		parser.simple_key_allowed = false
+
+	} else {
+		// The ':' indicator follows a complex key.
+
+		// In the block context, extra checks are required.
+		if parser.flow_level == 0 {
+
+			// Check if we are allowed to start a complex value.
+			if !parser.simple_key_allowed {
+				return yaml_parser_set_scanner_error(parser, "", parser.mark,
+					"mapping values are not allowed in this context")
+			}
+
+			// Add the BLOCK-MAPPING-START token if needed.
+			if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+				return false
+			}
+		}
+
+		// Simple keys after ':' are allowed in the block context.
+		parser.simple_key_allowed = parser.flow_level == 0
+	}
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the VALUE token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_VALUE_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// An anchor or an alias could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow an anchor or an alias.
+	parser.simple_key_allowed = false
+
+	// Create the ALIAS or ANCHOR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_anchor(parser, &token, typ) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+	// A tag could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a tag.
+	parser.simple_key_allowed = false
+
+	// Create the TAG token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_tag(parser, &token) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+	// Remove any potential simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// A simple key may follow a block scalar.
+	parser.simple_key_allowed = true
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+	// A plain scalar could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a flow scalar.
+	parser.simple_key_allowed = false
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+	// A plain scalar could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a flow scalar.
+	parser.simple_key_allowed = false
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_plain_scalar(parser, &token) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+	scan_mark := parser.mark
+
+	// Until the next token is not found.
+	for {
+		// Allow the BOM mark to start a line.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+		}
+
+		// Eat whitespaces.
+		// Tabs are allowed:
+		//  - in the flow context
+		//  - in the block context, but not at the beginning of the line or
+		//  after '-', '?', or ':' (complex value).
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Check if we just had a line comment under a sequence entry that
+		// looks more like a header to the following content. Similar to this:
+		//
+		// - # The comment
+		//   - Some data
+		//
+		// If so, transform the line comment to a head comment and reposition.
+		if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+			tokenA := parser.tokens[len(parser.tokens)-2]
+			tokenB := parser.tokens[len(parser.tokens)-1]
+			comment := &parser.comments[len(parser.comments)-1]
+			if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
+				// If it was in the prior line, reposition so it becomes a
+				// header of the follow up token. Otherwise, keep it in place
+				// so it becomes a header of the former.
+				comment.head = comment.line
+				comment.line = nil
+				if comment.start_mark.line == parser.mark.line-1 {
+					comment.token_mark = parser.mark
+				}
+			}
+		}
+
+		// Eat a comment until a line break.
+		if parser.buffer[parser.buffer_pos] == '#' {
+			if !yaml_parser_scan_comments(parser, scan_mark) {
+				return false
+			}
+		}
+
+		// If it is a line break, eat it.
+		if is_break(parser.buffer, parser.buffer_pos) {
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+			skip_line(parser)
+
+			// In the block context, a new line may start a simple key.
+			if parser.flow_level == 0 {
+				parser.simple_key_allowed = true
+			}
+		} else {
+			break // We have found a token.
+		}
+	}
+
+	return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+//
+//	%YAML    1.1    # a comment \n
+//	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+	// Eat '%'.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Scan the directive name.
+	var name []byte
+	if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+		return false
+	}
+
+	// Is it a YAML directive?
+	if bytes.Equal(name, []byte("YAML")) {
+		// Scan the VERSION directive value.
+		var major, minor int8
+		if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+			return false
+		}
+		end_mark := parser.mark
+
+		// Create a VERSION-DIRECTIVE token.
+		*token = yaml_token_t{
+			typ:        yaml_VERSION_DIRECTIVE_TOKEN,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			major:      major,
+			minor:      minor,
+		}
+
+		// Is it a TAG directive?
+	} else if bytes.Equal(name, []byte("TAG")) {
+		// Scan the TAG directive value.
+		var handle, prefix []byte
+		if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+			return false
+		}
+		end_mark := parser.mark
+
+		// Create a TAG-DIRECTIVE token.
+		*token = yaml_token_t{
+			typ:        yaml_TAG_DIRECTIVE_TOKEN,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			value:      handle,
+			prefix:     prefix,
+		}
+
+		// Unknown directive.
+	} else {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "found unknown directive name")
+		return false
+	}
+
+	// Eat the rest of the line including any comments.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	if parser.buffer[parser.buffer_pos] == '#' {
+		// [Go] Discard this inline comment for the time being.
+		//if !yaml_parser_scan_line_comment(parser, start_mark) {
+		//	return false
+		//}
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+	}
+
+	// Check if we are at the end of the line.
+	if !is_breakz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "did not find expected comment or line break")
+		return false
+	}
+
+	// Eat a line break.
+	if is_break(parser.buffer, parser.buffer_pos) {
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		skip_line(parser)
+	}
+
+	return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	 ^^^^
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	 ^^^
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+	// Consume the directive name.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	var s []byte
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the name is empty.
+	if len(s) == 0 {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "could not find expected directive name")
+		return false
+	}
+
+	// Check for an blank character after the name.
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "found unexpected non-alphabetical character")
+		return false
+	}
+	*name = s
+	return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	     ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+	// Eat whitespaces.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Consume the major version number.
+	if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+		return false
+	}
+
+	// Eat '.'.
+	if parser.buffer[parser.buffer_pos] != '.' {
+		return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+			start_mark, "did not find expected digit or '.' character")
+	}
+
+	skip(parser)
+
+	// Consume the minor version number.
+	if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+		return false
+	}
+	return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	        ^
+//	%YAML   1.1     # a comment \n
+//	          ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+	// Repeat while the next character is digit.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	var value, length int8
+	for is_digit(parser.buffer, parser.buffer_pos) {
+		// Check if the number is too long.
+		length++
+		if length > max_number_length {
+			return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+				start_mark, "found extremely long version number")
+		}
+		value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the number was present.
+	if length == 0 {
+		return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+			start_mark, "did not find expected version number")
+	}
+	*number = value
+	return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+//
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+	var handle_value, prefix_value []byte
+
+	// Eat whitespaces.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Scan a handle.
+	if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+		return false
+	}
+
+	// Expect a whitespace.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+			start_mark, "did not find expected whitespace")
+		return false
+	}
+
+	// Eat whitespaces.
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Scan a prefix.
+	if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+		return false
+	}
+
+	// Expect a whitespace or line break.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+			start_mark, "did not find expected whitespace or line break")
+		return false
+	}
+
+	*handle = handle_value
+	*prefix = prefix_value
+	return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+	var s []byte
+
+	// Eat the indicator character.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Consume the value.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	end_mark := parser.mark
+
+	/*
+	 * Check if length of the anchor is greater than 0 and it is followed by
+	 * a whitespace character or one of the indicators:
+	 *
+	 *      '?', ':', ',', ']', '}', '%', '@', '`'.
+	 */
+
+	if len(s) == 0 ||
+		!(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+			parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+			parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+			parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+			parser.buffer[parser.buffer_pos] == '`') {
+		context := "while scanning an alias"
+		if typ == yaml_ANCHOR_TOKEN {
+			context = "while scanning an anchor"
+		}
+		yaml_parser_set_scanner_error(parser, context, start_mark,
+			"did not find expected alphabetic or numeric character")
+		return false
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+	}
+
+	return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+	var handle, suffix []byte
+
+	start_mark := parser.mark
+
+	// Check if the tag is in the canonical form.
+	if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+		return false
+	}
+
+	if parser.buffer[parser.buffer_pos+1] == '<' {
+		// Keep the handle as ''
+
+		// Eat '!<'
+		skip(parser)
+		skip(parser)
+
+		// Consume the tag value.
+		if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+			return false
+		}
+
+		// Check for '>' and eat it.
+		if parser.buffer[parser.buffer_pos] != '>' {
+			yaml_parser_set_scanner_error(parser, "while scanning a tag",
+				start_mark, "did not find the expected '>'")
+			return false
+		}
+
+		skip(parser)
+	} else {
+		// The tag has either the '!suffix' or the '!handle!suffix' form.
+
+		// First, try to scan a handle.
+		if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+			return false
+		}
+
+		// Check if it is, indeed, handle.
+		if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+			// Scan the suffix now.
+			if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+				return false
+			}
+		} else {
+			// It wasn't a handle after all.  Scan the rest of the tag.
+			if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+				return false
+			}
+
+			// Set the handle to '!'.
+			handle = []byte{'!'}
+
+			// A special case: the '!' tag.  Set the handle to '' and the
+			// suffix to '!'.
+			if len(suffix) == 0 {
+				handle, suffix = suffix, handle
+			}
+		}
+	}
+
+	// Check the character which ends the tag.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a tag",
+			start_mark, "did not find expected whitespace or line break")
+		return false
+	}
+
+	end_mark := parser.mark
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_TAG_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      handle,
+		suffix:     suffix,
+	}
+	return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+	// Check the initial '!' character.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if parser.buffer[parser.buffer_pos] != '!' {
+		yaml_parser_set_scanner_tag_error(parser, directive,
+			start_mark, "did not find expected '!'")
+		return false
+	}
+
+	var s []byte
+
+	// Copy the '!' character.
+	s = read(parser, s)
+
+	// Copy all subsequent alphabetical and numerical characters.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the trailing character is '!' and copy it.
+	if parser.buffer[parser.buffer_pos] == '!' {
+		s = read(parser, s)
+	} else {
+		// It's either the '!' tag or not really a tag handle.  If it's a %TAG
+		// directive, it's an error.  If it's a tag token, it must be a part of URI.
+		if directive && string(s) != "!" {
+			yaml_parser_set_scanner_tag_error(parser, directive,
+				start_mark, "did not find expected '!'")
+			return false
+		}
+	}
+
+	*handle = s
+	return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+	//size_t length = head ? strlen((char *)head) : 0
+	var s []byte
+	hasTag := len(head) > 0
+
+	// Copy the head if needed.
+	//
+	// Note that we don't copy the leading '!' character.
+	if len(head) > 1 {
+		s = append(s, head[1:]...)
+	}
+
+	// Scan the tag.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// The set of characters that may appear in URI is as follows:
+	//
+	//      '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+	//      '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+	//      '%'.
+	// [Go] TODO Convert this into more reasonable logic.
+	for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+		parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+		parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+		parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+		parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+		parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+		parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+		parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+		parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+		parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+		parser.buffer[parser.buffer_pos] == '%' {
+		// Check if it is a URI-escape sequence.
+		if parser.buffer[parser.buffer_pos] == '%' {
+			if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+				return false
+			}
+		} else {
+			s = read(parser, s)
+		}
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		hasTag = true
+	}
+
+	if !hasTag {
+		yaml_parser_set_scanner_tag_error(parser, directive,
+			start_mark, "did not find expected tag URI")
+		return false
+	}
+	*uri = s
+	return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+	// Decode the required number of characters.
+	w := 1024
+	for w > 0 {
+		// Check for a URI-escaped octet.
+		if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+			return false
+		}
+
+		if !(parser.buffer[parser.buffer_pos] == '%' &&
+			is_hex(parser.buffer, parser.buffer_pos+1) &&
+			is_hex(parser.buffer, parser.buffer_pos+2)) {
+			return yaml_parser_set_scanner_tag_error(parser, directive,
+				start_mark, "did not find URI escaped octet")
+		}
+
+		// Get the octet.
+		octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+		// If it is the leading octet, determine the length of the UTF-8 sequence.
+		if w == 1024 {
+			w = width(octet)
+			if w == 0 {
+				return yaml_parser_set_scanner_tag_error(parser, directive,
+					start_mark, "found an incorrect leading UTF-8 octet")
+			}
+		} else {
+			// Check if the trailing octet is correct.
+			if octet&0xC0 != 0x80 {
+				return yaml_parser_set_scanner_tag_error(parser, directive,
+					start_mark, "found an incorrect trailing UTF-8 octet")
+			}
+		}
+
+		// Copy the octet and move the pointers.
+		*s = append(*s, octet)
+		skip(parser)
+		skip(parser)
+		skip(parser)
+		w--
+	}
+	return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+	// Eat the indicator '|' or '>'.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Scan the additional block scalar indicators.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// Check for a chomping indicator.
+	var chomping, increment int
+	if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+		// Set the chomping method and eat the indicator.
+		if parser.buffer[parser.buffer_pos] == '+' {
+			chomping = +1
+		} else {
+			chomping = -1
+		}
+		skip(parser)
+
+		// Check for an indentation indicator.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if is_digit(parser.buffer, parser.buffer_pos) {
+			// Check that the indentation is greater than 0.
+			if parser.buffer[parser.buffer_pos] == '0' {
+				yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+					start_mark, "found an indentation indicator equal to 0")
+				return false
+			}
+
+			// Get the indentation level and eat the indicator.
+			increment = as_digit(parser.buffer, parser.buffer_pos)
+			skip(parser)
+		}
+
+	} else if is_digit(parser.buffer, parser.buffer_pos) {
+		// Do the same as above, but in the opposite order.
+
+		if parser.buffer[parser.buffer_pos] == '0' {
+			yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+				start_mark, "found an indentation indicator equal to 0")
+			return false
+		}
+		increment = as_digit(parser.buffer, parser.buffer_pos)
+		skip(parser)
+
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+			if parser.buffer[parser.buffer_pos] == '+' {
+				chomping = +1
+			} else {
+				chomping = -1
+			}
+			skip(parser)
+		}
+	}
+
+	// Eat whitespaces and comments to the end of the line.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+	if parser.buffer[parser.buffer_pos] == '#' {
+		if !yaml_parser_scan_line_comment(parser, start_mark) {
+			return false
+		}
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+	}
+
+	// Check if we are at the end of the line.
+	if !is_breakz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+			start_mark, "did not find expected comment or line break")
+		return false
+	}
+
+	// Eat a line break.
+	if is_break(parser.buffer, parser.buffer_pos) {
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		skip_line(parser)
+	}
+
+	end_mark := parser.mark
+
+	// Set the indentation level if it was specified.
+	var indent int
+	if increment > 0 {
+		if parser.indent >= 0 {
+			indent = parser.indent + increment
+		} else {
+			indent = increment
+		}
+	}
+
+	// Scan the leading line breaks and determine the indentation level if needed.
+	var s, leading_break, trailing_breaks []byte
+	if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+		return false
+	}
+
+	// Scan the block scalar content.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	var leading_blank, trailing_blank bool
+	for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+		// We are at the beginning of a non-empty line.
+
+		// Is it a trailing whitespace?
+		trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+		// Check if we need to fold the leading line break.
+		if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+			// Do we need to join the lines by space?
+			if len(trailing_breaks) == 0 {
+				s = append(s, ' ')
+			}
+		} else {
+			s = append(s, leading_break...)
+		}
+		leading_break = leading_break[:0]
+
+		// Append the remaining line breaks.
+		s = append(s, trailing_breaks...)
+		trailing_breaks = trailing_breaks[:0]
+
+		// Is it a leading whitespace?
+		leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+		// Consume the current line.
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			s = read(parser, s)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Consume the line break.
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+
+		leading_break = read_line(parser, leading_break)
+
+		// Eat the following indentation spaces and line breaks.
+		if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+			return false
+		}
+	}
+
+	// Chomp the tail.
+	if chomping != -1 {
+		s = append(s, leading_break...)
+	}
+	if chomping == 1 {
+		s = append(s, trailing_breaks...)
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_LITERAL_SCALAR_STYLE,
+	}
+	if !literal {
+		token.style = yaml_FOLDED_SCALAR_STYLE
+	}
+	return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar.  Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+	*end_mark = parser.mark
+
+	// Eat the indentation spaces and line breaks.
+	max_indent := 0
+	for {
+		// Eat the indentation spaces.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+		if parser.mark.column > max_indent {
+			max_indent = parser.mark.column
+		}
+
+		// Check for a tab character messing the indentation.
+		if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+			return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+				start_mark, "found a tab character where an indentation space is expected")
+		}
+
+		// Have we found a non-empty line?
+		if !is_break(parser.buffer, parser.buffer_pos) {
+			break
+		}
+
+		// Consume the line break.
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		// [Go] Should really be returning breaks instead.
+		*breaks = read_line(parser, *breaks)
+		*end_mark = parser.mark
+	}
+
+	// Determine the indentation level if needed.
+	if *indent == 0 {
+		*indent = max_indent
+		if *indent < parser.indent+1 {
+			*indent = parser.indent + 1
+		}
+		if *indent < 1 {
+			*indent = 1
+		}
+	}
+	return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+	// Eat the left quote.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Consume the content of the quoted scalar.
+	var s, leading_break, trailing_breaks, whitespaces []byte
+	for {
+		// Check that there are no document indicators at the beginning of the line.
+		if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+			return false
+		}
+
+		if parser.mark.column == 0 &&
+			((parser.buffer[parser.buffer_pos+0] == '-' &&
+				parser.buffer[parser.buffer_pos+1] == '-' &&
+				parser.buffer[parser.buffer_pos+2] == '-') ||
+				(parser.buffer[parser.buffer_pos+0] == '.' &&
+					parser.buffer[parser.buffer_pos+1] == '.' &&
+					parser.buffer[parser.buffer_pos+2] == '.')) &&
+			is_blankz(parser.buffer, parser.buffer_pos+3) {
+			yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+				start_mark, "found unexpected document indicator")
+			return false
+		}
+
+		// Check for EOF.
+		if is_z(parser.buffer, parser.buffer_pos) {
+			yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+				start_mark, "found unexpected end of stream")
+			return false
+		}
+
+		// Consume non-blank characters.
+		leading_blanks := false
+		for !is_blankz(parser.buffer, parser.buffer_pos) {
+			if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+				// Is is an escaped single quote.
+				s = append(s, '\'')
+				skip(parser)
+				skip(parser)
+
+			} else if single && parser.buffer[parser.buffer_pos] == '\'' {
+				// It is a right single quote.
+				break
+			} else if !single && parser.buffer[parser.buffer_pos] == '"' {
+				// It is a right double quote.
+				break
+
+			} else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+				// It is an escaped line break.
+				if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+					return false
+				}
+				skip(parser)
+				skip_line(parser)
+				leading_blanks = true
+				break
+
+			} else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+				// It is an escape sequence.
+				code_length := 0
+
+				// Check the escape character.
+				switch parser.buffer[parser.buffer_pos+1] {
+				case '0':
+					s = append(s, 0)
+				case 'a':
+					s = append(s, '\x07')
+				case 'b':
+					s = append(s, '\x08')
+				case 't', '\t':
+					s = append(s, '\x09')
+				case 'n':
+					s = append(s, '\x0A')
+				case 'v':
+					s = append(s, '\x0B')
+				case 'f':
+					s = append(s, '\x0C')
+				case 'r':
+					s = append(s, '\x0D')
+				case 'e':
+					s = append(s, '\x1B')
+				case ' ':
+					s = append(s, '\x20')
+				case '"':
+					s = append(s, '"')
+				case '\'':
+					s = append(s, '\'')
+				case '\\':
+					s = append(s, '\\')
+				case 'N': // NEL (#x85)
+					s = append(s, '\xC2')
+					s = append(s, '\x85')
+				case '_': // #xA0
+					s = append(s, '\xC2')
+					s = append(s, '\xA0')
+				case 'L': // LS (#x2028)
+					s = append(s, '\xE2')
+					s = append(s, '\x80')
+					s = append(s, '\xA8')
+				case 'P': // PS (#x2029)
+					s = append(s, '\xE2')
+					s = append(s, '\x80')
+					s = append(s, '\xA9')
+				case 'x':
+					code_length = 2
+				case 'u':
+					code_length = 4
+				case 'U':
+					code_length = 8
+				default:
+					yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+						start_mark, "found unknown escape character")
+					return false
+				}
+
+				skip(parser)
+				skip(parser)
+
+				// Consume an arbitrary escape code.
+				if code_length > 0 {
+					var value int
+
+					// Scan the character value.
+					if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+						return false
+					}
+					for k := 0; k < code_length; k++ {
+						if !is_hex(parser.buffer, parser.buffer_pos+k) {
+							yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+								start_mark, "did not find expected hexdecimal number")
+							return false
+						}
+						value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+					}
+
+					// Check the value and write the character.
+					if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+						yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+							start_mark, "found invalid Unicode character escape code")
+						return false
+					}
+					if value <= 0x7F {
+						s = append(s, byte(value))
+					} else if value <= 0x7FF {
+						s = append(s, byte(0xC0+(value>>6)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					} else if value <= 0xFFFF {
+						s = append(s, byte(0xE0+(value>>12)))
+						s = append(s, byte(0x80+((value>>6)&0x3F)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					} else {
+						s = append(s, byte(0xF0+(value>>18)))
+						s = append(s, byte(0x80+((value>>12)&0x3F)))
+						s = append(s, byte(0x80+((value>>6)&0x3F)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					}
+
+					// Advance the pointer.
+					for k := 0; k < code_length; k++ {
+						skip(parser)
+					}
+				}
+			} else {
+				// It is a non-escaped non-blank character.
+				s = read(parser, s)
+			}
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+		}
+
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		// Check if we are at the end of the scalar.
+		if single {
+			if parser.buffer[parser.buffer_pos] == '\'' {
+				break
+			}
+		} else {
+			if parser.buffer[parser.buffer_pos] == '"' {
+				break
+			}
+		}
+
+		// Consume blank characters.
+		for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+			if is_blank(parser.buffer, parser.buffer_pos) {
+				// Consume a space or a tab character.
+				if !leading_blanks {
+					whitespaces = read(parser, whitespaces)
+				} else {
+					skip(parser)
+				}
+			} else {
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+
+				// Check if it is a first line break.
+				if !leading_blanks {
+					whitespaces = whitespaces[:0]
+					leading_break = read_line(parser, leading_break)
+					leading_blanks = true
+				} else {
+					trailing_breaks = read_line(parser, trailing_breaks)
+				}
+			}
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Join the whitespaces or fold line breaks.
+		if leading_blanks {
+			// Do we need to fold line breaks?
+			if len(leading_break) > 0 && leading_break[0] == '\n' {
+				if len(trailing_breaks) == 0 {
+					s = append(s, ' ')
+				} else {
+					s = append(s, trailing_breaks...)
+				}
+			} else {
+				s = append(s, leading_break...)
+				s = append(s, trailing_breaks...)
+			}
+			trailing_breaks = trailing_breaks[:0]
+			leading_break = leading_break[:0]
+		} else {
+			s = append(s, whitespaces...)
+			whitespaces = whitespaces[:0]
+		}
+	}
+
+	// Eat the right quote.
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_SINGLE_QUOTED_SCALAR_STYLE,
+	}
+	if !single {
+		token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+	var s, leading_break, trailing_breaks, whitespaces []byte
+	var leading_blanks bool
+	var indent = parser.indent + 1
+
+	start_mark := parser.mark
+	end_mark := parser.mark
+
+	// Consume the content of the plain scalar.
+	for {
+		// Check for a document indicator.
+		if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+			return false
+		}
+		if parser.mark.column == 0 &&
+			((parser.buffer[parser.buffer_pos+0] == '-' &&
+				parser.buffer[parser.buffer_pos+1] == '-' &&
+				parser.buffer[parser.buffer_pos+2] == '-') ||
+				(parser.buffer[parser.buffer_pos+0] == '.' &&
+					parser.buffer[parser.buffer_pos+1] == '.' &&
+					parser.buffer[parser.buffer_pos+2] == '.')) &&
+			is_blankz(parser.buffer, parser.buffer_pos+3) {
+			break
+		}
+
+		// Check for a comment.
+		if parser.buffer[parser.buffer_pos] == '#' {
+			break
+		}
+
+		// Consume non-blank characters.
+		for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+			// Check for indicators that may end a plain scalar.
+			if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+				(parser.flow_level > 0 &&
+					(parser.buffer[parser.buffer_pos] == ',' ||
+						parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+						parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+						parser.buffer[parser.buffer_pos] == '}')) {
+				break
+			}
+
+			// Check if we need to join whitespaces and breaks.
+			if leading_blanks || len(whitespaces) > 0 {
+				if leading_blanks {
+					// Do we need to fold line breaks?
+					if leading_break[0] == '\n' {
+						if len(trailing_breaks) == 0 {
+							s = append(s, ' ')
+						} else {
+							s = append(s, trailing_breaks...)
+						}
+					} else {
+						s = append(s, leading_break...)
+						s = append(s, trailing_breaks...)
+					}
+					trailing_breaks = trailing_breaks[:0]
+					leading_break = leading_break[:0]
+					leading_blanks = false
+				} else {
+					s = append(s, whitespaces...)
+					whitespaces = whitespaces[:0]
+				}
+			}
+
+			// Copy the character.
+			s = read(parser, s)
+
+			end_mark = parser.mark
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+		}
+
+		// Is it the end?
+		if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+			break
+		}
+
+		// Consume blank characters.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+			if is_blank(parser.buffer, parser.buffer_pos) {
+
+				// Check for tab characters that abuse indentation.
+				if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+					yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+						start_mark, "found a tab character that violates indentation")
+					return false
+				}
+
+				// Consume a space or a tab character.
+				if !leading_blanks {
+					whitespaces = read(parser, whitespaces)
+				} else {
+					skip(parser)
+				}
+			} else {
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+
+				// Check if it is a first line break.
+				if !leading_blanks {
+					whitespaces = whitespaces[:0]
+					leading_break = read_line(parser, leading_break)
+					leading_blanks = true
+				} else {
+					trailing_breaks = read_line(parser, trailing_breaks)
+				}
+			}
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Check indentation level.
+		if parser.flow_level == 0 && parser.mark.column < indent {
+			break
+		}
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_PLAIN_SCALAR_STYLE,
+	}
+
+	// Note that we change the 'simple_key_allowed' flag.
+	if leading_blanks {
+		parser.simple_key_allowed = true
+	}
+	return true
+}
+
+func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
+	if parser.newlines > 0 {
+		return true
+	}
+
+	var start_mark yaml_mark_t
+	var text []byte
+
+	for peek := 0; peek < 512; peek++ {
+		if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+			break
+		}
+		if is_blank(parser.buffer, parser.buffer_pos+peek) {
+			continue
+		}
+		if parser.buffer[parser.buffer_pos+peek] == '#' {
+			seen := parser.mark.index + peek
+			for {
+				if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+					return false
+				}
+				if is_breakz(parser.buffer, parser.buffer_pos) {
+					if parser.mark.index >= seen {
+						break
+					}
+					if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+						return false
+					}
+					skip_line(parser)
+				} else if parser.mark.index >= seen {
+					if len(text) == 0 {
+						start_mark = parser.mark
+					}
+					text = read(parser, text)
+				} else {
+					skip(parser)
+				}
+			}
+		}
+		break
+	}
+	if len(text) > 0 {
+		parser.comments = append(parser.comments, yaml_comment_t{
+			token_mark: token_mark,
+			start_mark: start_mark,
+			line:       text,
+		})
+	}
+	return true
+}
+
+func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
+	token := parser.tokens[len(parser.tokens)-1]
+
+	if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+		token = parser.tokens[len(parser.tokens)-2]
+	}
+
+	var token_mark = token.start_mark
+	var start_mark yaml_mark_t
+	var next_indent = parser.indent
+	if next_indent < 0 {
+		next_indent = 0
+	}
+
+	var recent_empty = false
+	var first_empty = parser.newlines <= 1
+
+	var line = parser.mark.line
+	var column = parser.mark.column
+
+	var text []byte
+
+	// The foot line is the place where a comment must start to
+	// still be considered as a foot of the prior content.
+	// If there's some content in the currently parsed line, then
+	// the foot is the line below it.
+	var foot_line = -1
+	if scan_mark.line > 0 {
+		foot_line = parser.mark.line - parser.newlines + 1
+		if parser.newlines == 0 && parser.mark.column > 1 {
+			foot_line++
+		}
+	}
+
+	var peek = 0
+	for ; peek < 512; peek++ {
+		if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+			break
+		}
+		column++
+		if is_blank(parser.buffer, parser.buffer_pos+peek) {
+			continue
+		}
+		c := parser.buffer[parser.buffer_pos+peek]
+		var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+		if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
+			// Got line break or terminator.
+			if close_flow || !recent_empty {
+				if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
+					// This is the first empty line and there were no empty lines before,
+					// so this initial part of the comment is a foot of the prior token
+					// instead of being a head for the following one. Split it up.
+					// Alternatively, this might also be the last comment inside a flow
+					// scope, so it must be a footer.
+					if len(text) > 0 {
+						if start_mark.column-1 < next_indent {
+							// If dedented it's unrelated to the prior token.
+							token_mark = start_mark
+						}
+						parser.comments = append(parser.comments, yaml_comment_t{
+							scan_mark:  scan_mark,
+							token_mark: token_mark,
+							start_mark: start_mark,
+							end_mark:   yaml_mark_t{parser.mark.index + peek, line, column},
+							foot:       text,
+						})
+						scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+						token_mark = scan_mark
+						text = nil
+					}
+				} else {
+					if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+						text = append(text, '\n')
+					}
+				}
+			}
+			if !is_break(parser.buffer, parser.buffer_pos+peek) {
+				break
+			}
+			first_empty = false
+			recent_empty = true
+			column = 0
+			line++
+			continue
+		}
+
+		if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
+			// The comment at the different indentation is a foot of the
+			// preceding data rather than a head of the upcoming one.
+			parser.comments = append(parser.comments, yaml_comment_t{
+				scan_mark:  scan_mark,
+				token_mark: token_mark,
+				start_mark: start_mark,
+				end_mark:   yaml_mark_t{parser.mark.index + peek, line, column},
+				foot:       text,
+			})
+			scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+			token_mark = scan_mark
+			text = nil
+		}
+
+		if parser.buffer[parser.buffer_pos+peek] != '#' {
+			break
+		}
+
+		if len(text) == 0 {
+			start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+		} else {
+			text = append(text, '\n')
+		}
+
+		recent_empty = false
+
+		// Consume until after the consumed comment line.
+		seen := parser.mark.index + peek
+		for {
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+			if is_breakz(parser.buffer, parser.buffer_pos) {
+				if parser.mark.index >= seen {
+					break
+				}
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+				skip_line(parser)
+			} else if parser.mark.index >= seen {
+				text = read(parser, text)
+			} else {
+				skip(parser)
+			}
+		}
+
+		peek = 0
+		column = 0
+		line = parser.mark.line
+		next_indent = parser.indent
+		if next_indent < 0 {
+			next_indent = 0
+		}
+	}
+
+	if len(text) > 0 {
+		parser.comments = append(parser.comments, yaml_comment_t{
+			scan_mark:  scan_mark,
+			token_mark: start_mark,
+			start_mark: start_mark,
+			end_mark:   yaml_mark_t{parser.mark.index + peek - 1, line, column},
+			head:       text,
+		})
+	}
+	return true
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/sorter.go b/history-api/vendor/go.yaml.in/yaml/v3/sorter.go
new file mode 100644
index 00000000..9210ece7
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/sorter.go
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"reflect"
+	"unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int      { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+	a := l[i]
+	b := l[j]
+	ak := a.Kind()
+	bk := b.Kind()
+	for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+		a = a.Elem()
+		ak = a.Kind()
+	}
+	for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+		b = b.Elem()
+		bk = b.Kind()
+	}
+	af, aok := keyFloat(a)
+	bf, bok := keyFloat(b)
+	if aok && bok {
+		if af != bf {
+			return af < bf
+		}
+		if ak != bk {
+			return ak < bk
+		}
+		return numLess(a, b)
+	}
+	if ak != reflect.String || bk != reflect.String {
+		return ak < bk
+	}
+	ar, br := []rune(a.String()), []rune(b.String())
+	digits := false
+	for i := 0; i < len(ar) && i < len(br); i++ {
+		if ar[i] == br[i] {
+			digits = unicode.IsDigit(ar[i])
+			continue
+		}
+		al := unicode.IsLetter(ar[i])
+		bl := unicode.IsLetter(br[i])
+		if al && bl {
+			return ar[i] < br[i]
+		}
+		if al || bl {
+			if digits {
+				return al
+			} else {
+				return bl
+			}
+		}
+		var ai, bi int
+		var an, bn int64
+		if ar[i] == '0' || br[i] == '0' {
+			for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+				if ar[j] != '0' {
+					an = 1
+					bn = 1
+					break
+				}
+			}
+		}
+		for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+			an = an*10 + int64(ar[ai]-'0')
+		}
+		for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+			bn = bn*10 + int64(br[bi]-'0')
+		}
+		if an != bn {
+			return an < bn
+		}
+		if ai != bi {
+			return ai < bi
+		}
+		return ar[i] < br[i]
+	}
+	return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+	switch v.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return float64(v.Int()), true
+	case reflect.Float32, reflect.Float64:
+		return v.Float(), true
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return float64(v.Uint()), true
+	case reflect.Bool:
+		if v.Bool() {
+			return 1, true
+		}
+		return 0, true
+	}
+	return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+	switch a.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return a.Int() < b.Int()
+	case reflect.Float32, reflect.Float64:
+		return a.Float() < b.Float()
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return a.Uint() < b.Uint()
+	case reflect.Bool:
+		return !a.Bool() && b.Bool()
+	}
+	panic("not a number")
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/writerc.go b/history-api/vendor/go.yaml.in/yaml/v3/writerc.go
new file mode 100644
index 00000000..266d0b09
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/writerc.go
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+	emitter.error = yaml_WRITER_ERROR
+	emitter.problem = problem
+	return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+	if emitter.write_handler == nil {
+		panic("write handler not set")
+	}
+
+	// Check if the buffer is empty.
+	if emitter.buffer_pos == 0 {
+		return true
+	}
+
+	if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+		return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+	}
+	emitter.buffer_pos = 0
+	return true
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/yaml.go b/history-api/vendor/go.yaml.in/yaml/v3/yaml.go
new file mode 100644
index 00000000..0b101cd2
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/yaml.go
@@ -0,0 +1,703 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+//	https://github.com/yaml/go-yaml
+package yaml
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"sync"
+	"unicode/utf8"
+)
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document.
+type Unmarshaler interface {
+	UnmarshalYAML(value *Node) error
+}
+
+type obsoleteUnmarshaler interface {
+	UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+	MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+//	type T struct {
+//	    F int `yaml:"a,omitempty"`
+//	    B int
+//	}
+//	var t T
+//	yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+func Unmarshal(in []byte, out interface{}) (err error) {
+	return unmarshal(in, out, false)
+}
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+	parser      *parser
+	knownFields bool
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{
+		parser: newParserFromReader(r),
+	}
+}
+
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+	dec.knownFields = enable
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+	d := newDecoder()
+	d.knownFields = dec.knownFields
+	defer handleErr(&err)
+	node := dec.parser.parse()
+	if node == nil {
+		return io.EOF
+	}
+	out := reflect.ValueOf(v)
+	if out.Kind() == reflect.Ptr && !out.IsNil() {
+		out = out.Elem()
+	}
+	d.unmarshal(node, out)
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v interface{}) (err error) {
+	d := newDecoder()
+	defer handleErr(&err)
+	out := reflect.ValueOf(v)
+	if out.Kind() == reflect.Ptr && !out.IsNil() {
+		out = out.Elem()
+	}
+	d.unmarshal(n, out)
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+	defer handleErr(&err)
+	d := newDecoder()
+	p := newParser(in)
+	defer p.destroy()
+	node := p.parse()
+	if node != nil {
+		v := reflect.ValueOf(out)
+		if v.Kind() == reflect.Ptr && !v.IsNil() {
+			v = v.Elem()
+		}
+		d.unmarshal(node, v)
+	}
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+//	`(...) yaml:"[][,[,]]" (...)`
+//
+// The following flags are currently supported:
+//
+//	omitempty    Only include the field if it's not set to the zero
+//	             value for the type or to empty slices or maps.
+//	             Zero valued structs will be omitted if all their public
+//	             fields are zero, unless they implement an IsZero
+//	             method (see the IsZeroer interface type), in which
+//	             case the field will be excluded if IsZero returns true.
+//
+//	flow         Marshal using a flow style (useful for structs,
+//	             sequences and maps).
+//
+//	inline       Inline the field, which must be a struct or a map,
+//	             causing all of its fields or keys to be processed as if
+//	             they were part of the outer struct. For maps, keys must
+//	             not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+//	type T struct {
+//	    F int `yaml:"a,omitempty"`
+//	    B int
+//	}
+//	yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+//	yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+func Marshal(in interface{}) (out []byte, err error) {
+	defer handleErr(&err)
+	e := newEncoder()
+	defer e.destroy()
+	e.marshalDoc("", reflect.ValueOf(in))
+	e.finish()
+	out = e.out
+	return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+	encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+	return &Encoder{
+		encoder: newEncoderWithWriter(w),
+	}
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+	defer handleErr(&err)
+	e.encoder.marshalDoc("", reflect.ValueOf(v))
+	return nil
+}
+
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+	defer handleErr(&err)
+	e := newEncoder()
+	defer e.destroy()
+	e.marshalDoc("", reflect.ValueOf(v))
+	e.finish()
+	p := newParser(e.out)
+	p.textless = true
+	defer p.destroy()
+	doc := p.parse()
+	*n = *doc.Content[0]
+	return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+	if spaces < 0 {
+		panic("yaml: cannot indent to a negative number of spaces")
+	}
+	e.encoder.indent = spaces
+}
+
+// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
+func (e *Encoder) CompactSeqIndent() {
+	e.encoder.emitter.compact_sequence_indent = true
+}
+
+// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
+func (e *Encoder) DefaultSeqIndent() {
+	e.encoder.emitter.compact_sequence_indent = false
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+	defer handleErr(&err)
+	e.encoder.finish()
+	return nil
+}
+
+func handleErr(err *error) {
+	if v := recover(); v != nil {
+		if e, ok := v.(yamlError); ok {
+			*err = e.err
+		} else {
+			panic(v)
+		}
+	}
+}
+
+type yamlError struct {
+	err error
+}
+
+func fail(err error) {
+	panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+	panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+	Errors []string
+}
+
+func (e *TypeError) Error() string {
+	return fmt.Sprintf("yaml: unmarshal errors:\n  %s", strings.Join(e.Errors, "\n  "))
+}
+
+type Kind uint32
+
+const (
+	DocumentNode Kind = 1 << iota
+	SequenceNode
+	MappingNode
+	ScalarNode
+	AliasNode
+)
+
+type Style uint32
+
+const (
+	TaggedStyle Style = 1 << iota
+	DoubleQuotedStyle
+	SingleQuotedStyle
+	LiteralStyle
+	FoldedStyle
+	FlowStyle
+)
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+//	var person struct {
+//	        Name    string
+//	        Address yaml.Node
+//	}
+//	err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+//	var person Node
+//	err := yaml.Unmarshal(data, &person)
+type Node struct {
+	// Kind defines whether the node is a document, a mapping, a sequence,
+	// a scalar value, or an alias to another node. The specific data type of
+	// scalar nodes may be obtained via the ShortTag and LongTag methods.
+	Kind Kind
+
+	// Style allows customizing the apperance of the node in the tree.
+	Style Style
+
+	// Tag holds the YAML tag defining the data type for the value.
+	// When decoding, this field will always be set to the resolved tag,
+	// even when it wasn't explicitly provided in the YAML content.
+	// When encoding, if this field is unset the value type will be
+	// implied from the node properties, and if it is set, it will only
+	// be serialized into the representation if TaggedStyle is used or
+	// the implicit tag diverges from the provided one.
+	Tag string
+
+	// Value holds the unescaped and unquoted represenation of the value.
+	Value string
+
+	// Anchor holds the anchor name for this node, which allows aliases to point to it.
+	Anchor string
+
+	// Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+	Alias *Node
+
+	// Content holds contained nodes for documents, mappings, and sequences.
+	Content []*Node
+
+	// HeadComment holds any comments in the lines preceding the node and
+	// not separated by an empty line.
+	HeadComment string
+
+	// LineComment holds any comments at the end of the line where the node is in.
+	LineComment string
+
+	// FootComment holds any comments following the node and before empty lines.
+	FootComment string
+
+	// Line and Column hold the node position in the decoded YAML text.
+	// These fields are not respected when encoding the node.
+	Line   int
+	Column int
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+	return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+		n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+	return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+	if n.indicatedString() {
+		return strTag
+	}
+	if n.Tag == "" || n.Tag == "!" {
+		switch n.Kind {
+		case MappingNode:
+			return mapTag
+		case SequenceNode:
+			return seqTag
+		case AliasNode:
+			if n.Alias != nil {
+				return n.Alias.ShortTag()
+			}
+		case ScalarNode:
+			tag, _ := resolve("", n.Value)
+			return tag
+		case 0:
+			// Special case to make the zero value convenient.
+			if n.IsZero() {
+				return nullTag
+			}
+		}
+		return ""
+	}
+	return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+	return n.Kind == ScalarNode &&
+		(shortTag(n.Tag) == strTag ||
+			(n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+	n.Kind = ScalarNode
+	if utf8.ValidString(s) {
+		n.Value = s
+		n.Tag = strTag
+	} else {
+		n.Value = encodeBase64(s)
+		n.Tag = binaryTag
+	}
+	if strings.Contains(n.Value, "\n") {
+		n.Style = LiteralStyle
+	}
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+	FieldsMap  map[string]fieldInfo
+	FieldsList []fieldInfo
+
+	// InlineMap is the number of the field in the struct that
+	// contains an ,inline map, or -1 if there's none.
+	InlineMap int
+
+	// InlineUnmarshalers holds indexes to inlined fields that
+	// contain unmarshaler values.
+	InlineUnmarshalers [][]int
+}
+
+type fieldInfo struct {
+	Key       string
+	Num       int
+	OmitEmpty bool
+	Flow      bool
+	// Id holds the unique field identifier, so we can cheaply
+	// check for field duplicates without maintaining an extra map.
+	Id int
+
+	// Inline holds the field index if the field is part of an inlined struct.
+	Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+var unmarshalerType reflect.Type
+
+func init() {
+	var v Unmarshaler
+	unmarshalerType = reflect.ValueOf(&v).Elem().Type()
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+	fieldMapMutex.RLock()
+	sinfo, found := structMap[st]
+	fieldMapMutex.RUnlock()
+	if found {
+		return sinfo, nil
+	}
+
+	n := st.NumField()
+	fieldsMap := make(map[string]fieldInfo)
+	fieldsList := make([]fieldInfo, 0, n)
+	inlineMap := -1
+	inlineUnmarshalers := [][]int(nil)
+	for i := 0; i != n; i++ {
+		field := st.Field(i)
+		if field.PkgPath != "" && !field.Anonymous {
+			continue // Private field
+		}
+
+		info := fieldInfo{Num: i}
+
+		tag := field.Tag.Get("yaml")
+		if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+			tag = string(field.Tag)
+		}
+		if tag == "-" {
+			continue
+		}
+
+		inline := false
+		fields := strings.Split(tag, ",")
+		if len(fields) > 1 {
+			for _, flag := range fields[1:] {
+				switch flag {
+				case "omitempty":
+					info.OmitEmpty = true
+				case "flow":
+					info.Flow = true
+				case "inline":
+					inline = true
+				default:
+					return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
+				}
+			}
+			tag = fields[0]
+		}
+
+		if inline {
+			switch field.Type.Kind() {
+			case reflect.Map:
+				if inlineMap >= 0 {
+					return nil, errors.New("multiple ,inline maps in struct " + st.String())
+				}
+				if field.Type.Key() != reflect.TypeOf("") {
+					return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+				}
+				inlineMap = info.Num
+			case reflect.Struct, reflect.Ptr:
+				ftype := field.Type
+				for ftype.Kind() == reflect.Ptr {
+					ftype = ftype.Elem()
+				}
+				if ftype.Kind() != reflect.Struct {
+					return nil, errors.New("option ,inline may only be used on a struct or map field")
+				}
+				if reflect.PtrTo(ftype).Implements(unmarshalerType) {
+					inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+				} else {
+					sinfo, err := getStructInfo(ftype)
+					if err != nil {
+						return nil, err
+					}
+					for _, index := range sinfo.InlineUnmarshalers {
+						inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
+					}
+					for _, finfo := range sinfo.FieldsList {
+						if _, found := fieldsMap[finfo.Key]; found {
+							msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+							return nil, errors.New(msg)
+						}
+						if finfo.Inline == nil {
+							finfo.Inline = []int{i, finfo.Num}
+						} else {
+							finfo.Inline = append([]int{i}, finfo.Inline...)
+						}
+						finfo.Id = len(fieldsList)
+						fieldsMap[finfo.Key] = finfo
+						fieldsList = append(fieldsList, finfo)
+					}
+				}
+			default:
+				return nil, errors.New("option ,inline may only be used on a struct or map field")
+			}
+			continue
+		}
+
+		if tag != "" {
+			info.Key = tag
+		} else {
+			info.Key = strings.ToLower(field.Name)
+		}
+
+		if _, found = fieldsMap[info.Key]; found {
+			msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+			return nil, errors.New(msg)
+		}
+
+		info.Id = len(fieldsList)
+		fieldsList = append(fieldsList, info)
+		fieldsMap[info.Key] = info
+	}
+
+	sinfo = &structInfo{
+		FieldsMap:          fieldsMap,
+		FieldsList:         fieldsList,
+		InlineMap:          inlineMap,
+		InlineUnmarshalers: inlineUnmarshalers,
+	}
+
+	fieldMapMutex.Lock()
+	structMap[st] = sinfo
+	fieldMapMutex.Unlock()
+	return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+	IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+	kind := v.Kind()
+	if z, ok := v.Interface().(IsZeroer); ok {
+		if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+			return true
+		}
+		return z.IsZero()
+	}
+	switch kind {
+	case reflect.String:
+		return len(v.String()) == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	case reflect.Slice:
+		return v.Len() == 0
+	case reflect.Map:
+		return v.Len() == 0
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Struct:
+		vt := v.Type()
+		for i := v.NumField() - 1; i >= 0; i-- {
+			if vt.Field(i).PkgPath != "" {
+				continue // Private field
+			}
+			if !isZero(v.Field(i)) {
+				return false
+			}
+		}
+		return true
+	}
+	return false
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/yamlh.go b/history-api/vendor/go.yaml.in/yaml/v3/yamlh.go
new file mode 100644
index 00000000..f59aa40f
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/yamlh.go
@@ -0,0 +1,811 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"fmt"
+	"io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+	major int8 // The major version number.
+	minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+	handle []byte // The tag handle.
+	prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+	// Let the parser choose the encoding.
+	yaml_ANY_ENCODING yaml_encoding_t = iota
+
+	yaml_UTF8_ENCODING    // The default UTF-8 encoding.
+	yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+	yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+	// Let the parser choose the break type.
+	yaml_ANY_BREAK yaml_break_t = iota
+
+	yaml_CR_BREAK   // Use CR for line breaks (Mac style).
+	yaml_LN_BREAK   // Use LN for line breaks (Unix style).
+	yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+	// No error is produced.
+	yaml_NO_ERROR yaml_error_type_t = iota
+
+	yaml_MEMORY_ERROR   // Cannot allocate or reallocate a block of memory.
+	yaml_READER_ERROR   // Cannot read or decode the input stream.
+	yaml_SCANNER_ERROR  // Cannot scan the input stream.
+	yaml_PARSER_ERROR   // Cannot parse the input stream.
+	yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+	yaml_WRITER_ERROR   // Cannot write to the output stream.
+	yaml_EMITTER_ERROR  // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+	index  int // The position index.
+	line   int // The position line.
+	column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
+
+	yaml_PLAIN_SCALAR_STYLE         yaml_scalar_style_t = 1 << iota // The plain scalar style.
+	yaml_SINGLE_QUOTED_SCALAR_STYLE                                 // The single-quoted scalar style.
+	yaml_DOUBLE_QUOTED_SCALAR_STYLE                                 // The double-quoted scalar style.
+	yaml_LITERAL_SCALAR_STYLE                                       // The literal scalar style.
+	yaml_FOLDED_SCALAR_STYLE                                        // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+	yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+	yaml_FLOW_SEQUENCE_STYLE  // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+	yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+	yaml_FLOW_MAPPING_STYLE  // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+	// An empty token.
+	yaml_NO_TOKEN yaml_token_type_t = iota
+
+	yaml_STREAM_START_TOKEN // A STREAM-START token.
+	yaml_STREAM_END_TOKEN   // A STREAM-END token.
+
+	yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+	yaml_TAG_DIRECTIVE_TOKEN     // A TAG-DIRECTIVE token.
+	yaml_DOCUMENT_START_TOKEN    // A DOCUMENT-START token.
+	yaml_DOCUMENT_END_TOKEN      // A DOCUMENT-END token.
+
+	yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+	yaml_BLOCK_MAPPING_START_TOKEN  // A BLOCK-SEQUENCE-END token.
+	yaml_BLOCK_END_TOKEN            // A BLOCK-END token.
+
+	yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+	yaml_FLOW_SEQUENCE_END_TOKEN   // A FLOW-SEQUENCE-END token.
+	yaml_FLOW_MAPPING_START_TOKEN  // A FLOW-MAPPING-START token.
+	yaml_FLOW_MAPPING_END_TOKEN    // A FLOW-MAPPING-END token.
+
+	yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+	yaml_FLOW_ENTRY_TOKEN  // A FLOW-ENTRY token.
+	yaml_KEY_TOKEN         // A KEY token.
+	yaml_VALUE_TOKEN       // A VALUE token.
+
+	yaml_ALIAS_TOKEN  // An ALIAS token.
+	yaml_ANCHOR_TOKEN // An ANCHOR token.
+	yaml_TAG_TOKEN    // A TAG token.
+	yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+	switch tt {
+	case yaml_NO_TOKEN:
+		return "yaml_NO_TOKEN"
+	case yaml_STREAM_START_TOKEN:
+		return "yaml_STREAM_START_TOKEN"
+	case yaml_STREAM_END_TOKEN:
+		return "yaml_STREAM_END_TOKEN"
+	case yaml_VERSION_DIRECTIVE_TOKEN:
+		return "yaml_VERSION_DIRECTIVE_TOKEN"
+	case yaml_TAG_DIRECTIVE_TOKEN:
+		return "yaml_TAG_DIRECTIVE_TOKEN"
+	case yaml_DOCUMENT_START_TOKEN:
+		return "yaml_DOCUMENT_START_TOKEN"
+	case yaml_DOCUMENT_END_TOKEN:
+		return "yaml_DOCUMENT_END_TOKEN"
+	case yaml_BLOCK_SEQUENCE_START_TOKEN:
+		return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+	case yaml_BLOCK_MAPPING_START_TOKEN:
+		return "yaml_BLOCK_MAPPING_START_TOKEN"
+	case yaml_BLOCK_END_TOKEN:
+		return "yaml_BLOCK_END_TOKEN"
+	case yaml_FLOW_SEQUENCE_START_TOKEN:
+		return "yaml_FLOW_SEQUENCE_START_TOKEN"
+	case yaml_FLOW_SEQUENCE_END_TOKEN:
+		return "yaml_FLOW_SEQUENCE_END_TOKEN"
+	case yaml_FLOW_MAPPING_START_TOKEN:
+		return "yaml_FLOW_MAPPING_START_TOKEN"
+	case yaml_FLOW_MAPPING_END_TOKEN:
+		return "yaml_FLOW_MAPPING_END_TOKEN"
+	case yaml_BLOCK_ENTRY_TOKEN:
+		return "yaml_BLOCK_ENTRY_TOKEN"
+	case yaml_FLOW_ENTRY_TOKEN:
+		return "yaml_FLOW_ENTRY_TOKEN"
+	case yaml_KEY_TOKEN:
+		return "yaml_KEY_TOKEN"
+	case yaml_VALUE_TOKEN:
+		return "yaml_VALUE_TOKEN"
+	case yaml_ALIAS_TOKEN:
+		return "yaml_ALIAS_TOKEN"
+	case yaml_ANCHOR_TOKEN:
+		return "yaml_ANCHOR_TOKEN"
+	case yaml_TAG_TOKEN:
+		return "yaml_TAG_TOKEN"
+	case yaml_SCALAR_TOKEN:
+		return "yaml_SCALAR_TOKEN"
+	}
+	return ""
+}
+
+// The token structure.
+type yaml_token_t struct {
+	// The token type.
+	typ yaml_token_type_t
+
+	// The start/end of the token.
+	start_mark, end_mark yaml_mark_t
+
+	// The stream encoding (for yaml_STREAM_START_TOKEN).
+	encoding yaml_encoding_t
+
+	// The alias/anchor/scalar value or tag/tag directive handle
+	// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+	value []byte
+
+	// The tag suffix (for yaml_TAG_TOKEN).
+	suffix []byte
+
+	// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+	prefix []byte
+
+	// The scalar style (for yaml_SCALAR_TOKEN).
+	style yaml_scalar_style_t
+
+	// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+	major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+	// An empty event.
+	yaml_NO_EVENT yaml_event_type_t = iota
+
+	yaml_STREAM_START_EVENT   // A STREAM-START event.
+	yaml_STREAM_END_EVENT     // A STREAM-END event.
+	yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+	yaml_DOCUMENT_END_EVENT   // A DOCUMENT-END event.
+	yaml_ALIAS_EVENT          // An ALIAS event.
+	yaml_SCALAR_EVENT         // A SCALAR event.
+	yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+	yaml_SEQUENCE_END_EVENT   // A SEQUENCE-END event.
+	yaml_MAPPING_START_EVENT  // A MAPPING-START event.
+	yaml_MAPPING_END_EVENT    // A MAPPING-END event.
+	yaml_TAIL_COMMENT_EVENT
+)
+
+var eventStrings = []string{
+	yaml_NO_EVENT:             "none",
+	yaml_STREAM_START_EVENT:   "stream start",
+	yaml_STREAM_END_EVENT:     "stream end",
+	yaml_DOCUMENT_START_EVENT: "document start",
+	yaml_DOCUMENT_END_EVENT:   "document end",
+	yaml_ALIAS_EVENT:          "alias",
+	yaml_SCALAR_EVENT:         "scalar",
+	yaml_SEQUENCE_START_EVENT: "sequence start",
+	yaml_SEQUENCE_END_EVENT:   "sequence end",
+	yaml_MAPPING_START_EVENT:  "mapping start",
+	yaml_MAPPING_END_EVENT:    "mapping end",
+	yaml_TAIL_COMMENT_EVENT:   "tail comment",
+}
+
+func (e yaml_event_type_t) String() string {
+	if e < 0 || int(e) >= len(eventStrings) {
+		return fmt.Sprintf("unknown event %d", e)
+	}
+	return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+	// The event type.
+	typ yaml_event_type_t
+
+	// The start and end of the event.
+	start_mark, end_mark yaml_mark_t
+
+	// The document encoding (for yaml_STREAM_START_EVENT).
+	encoding yaml_encoding_t
+
+	// The version directive (for yaml_DOCUMENT_START_EVENT).
+	version_directive *yaml_version_directive_t
+
+	// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+	tag_directives []yaml_tag_directive_t
+
+	// The comments
+	head_comment []byte
+	line_comment []byte
+	foot_comment []byte
+	tail_comment []byte
+
+	// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+	anchor []byte
+
+	// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+	tag []byte
+
+	// The scalar value (for yaml_SCALAR_EVENT).
+	value []byte
+
+	// Is the document start/end indicator implicit, or the tag optional?
+	// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+	implicit bool
+
+	// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+	quoted_implicit bool
+
+	// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+	style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t     { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t   { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+	yaml_NULL_TAG      = "tag:yaml.org,2002:null"      // The tag !!null with the only possible value: null.
+	yaml_BOOL_TAG      = "tag:yaml.org,2002:bool"      // The tag !!bool with the values: true and false.
+	yaml_STR_TAG       = "tag:yaml.org,2002:str"       // The tag !!str for string values.
+	yaml_INT_TAG       = "tag:yaml.org,2002:int"       // The tag !!int for integer values.
+	yaml_FLOAT_TAG     = "tag:yaml.org,2002:float"     // The tag !!float for float values.
+	yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+	yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+	yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+	// Not in original libyaml.
+	yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+	yaml_MERGE_TAG  = "tag:yaml.org,2002:merge"
+
+	yaml_DEFAULT_SCALAR_TAG   = yaml_STR_TAG // The default scalar tag is !!str.
+	yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+	yaml_DEFAULT_MAPPING_TAG  = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+	// An empty node.
+	yaml_NO_NODE yaml_node_type_t = iota
+
+	yaml_SCALAR_NODE   // A scalar node.
+	yaml_SEQUENCE_NODE // A sequence node.
+	yaml_MAPPING_NODE  // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+	key   int // The key of the element.
+	value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+	typ yaml_node_type_t // The node type.
+	tag []byte           // The node tag.
+
+	// The node data.
+
+	// The scalar parameters (for yaml_SCALAR_NODE).
+	scalar struct {
+		value  []byte              // The scalar value.
+		length int                 // The length of the scalar value.
+		style  yaml_scalar_style_t // The scalar style.
+	}
+
+	// The sequence parameters (for YAML_SEQUENCE_NODE).
+	sequence struct {
+		items_data []yaml_node_item_t    // The stack of sequence items.
+		style      yaml_sequence_style_t // The sequence style.
+	}
+
+	// The mapping parameters (for yaml_MAPPING_NODE).
+	mapping struct {
+		pairs_data  []yaml_node_pair_t   // The stack of mapping pairs (key, value).
+		pairs_start *yaml_node_pair_t    // The beginning of the stack.
+		pairs_end   *yaml_node_pair_t    // The end of the stack.
+		pairs_top   *yaml_node_pair_t    // The top of the stack.
+		style       yaml_mapping_style_t // The mapping style.
+	}
+
+	start_mark yaml_mark_t // The beginning of the node.
+	end_mark   yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+	// The document nodes.
+	nodes []yaml_node_t
+
+	// The version directive.
+	version_directive *yaml_version_directive_t
+
+	// The list of tag directives.
+	tag_directives_data  []yaml_tag_directive_t
+	tag_directives_start int // The beginning of the tag directives list.
+	tag_directives_end   int // The end of the tag directives list.
+
+	start_implicit int // Is the document start indicator implicit?
+	end_implicit   int // Is the document end indicator implicit?
+
+	// The start/end of the document.
+	start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out]   data        A pointer to an application data specified by
+//
+//	yaml_parser_set_input().
+//
+// [out]      buffer      The buffer to write the data from the source.
+// [in]       size        The size of the buffer.
+// [out]      size_read   The actual number of bytes read from the source.
+//
+// On success, the handler should return 1.  If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+	possible     bool        // Is a simple key possible?
+	required     bool        // Is a simple key required?
+	token_number int         // The number of the token.
+	mark         yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+	yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+	yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE           // Expect the beginning of an implicit document.
+	yaml_PARSE_DOCUMENT_START_STATE                    // Expect DOCUMENT-START.
+	yaml_PARSE_DOCUMENT_CONTENT_STATE                  // Expect the content of a document.
+	yaml_PARSE_DOCUMENT_END_STATE                      // Expect DOCUMENT-END.
+	yaml_PARSE_BLOCK_NODE_STATE                        // Expect a block node.
+	yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+	yaml_PARSE_FLOW_NODE_STATE                         // Expect a flow node.
+	yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE        // Expect the first entry of a block sequence.
+	yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE              // Expect an entry of a block sequence.
+	yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE         // Expect an entry of an indentless sequence.
+	yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE           // Expect the first key of a block mapping.
+	yaml_PARSE_BLOCK_MAPPING_KEY_STATE                 // Expect a block mapping key.
+	yaml_PARSE_BLOCK_MAPPING_VALUE_STATE               // Expect a block mapping value.
+	yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE         // Expect the first entry of a flow sequence.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE               // Expect an entry of a flow sequence.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE   // Expect a key of an ordered mapping.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE   // Expect the and of an ordered mapping entry.
+	yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE            // Expect the first key of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_KEY_STATE                  // Expect a key of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_VALUE_STATE                // Expect a value of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE          // Expect an empty value of a flow mapping.
+	yaml_PARSE_END_STATE                               // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+	switch ps {
+	case yaml_PARSE_STREAM_START_STATE:
+		return "yaml_PARSE_STREAM_START_STATE"
+	case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+		return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+	case yaml_PARSE_DOCUMENT_START_STATE:
+		return "yaml_PARSE_DOCUMENT_START_STATE"
+	case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+		return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+	case yaml_PARSE_DOCUMENT_END_STATE:
+		return "yaml_PARSE_DOCUMENT_END_STATE"
+	case yaml_PARSE_BLOCK_NODE_STATE:
+		return "yaml_PARSE_BLOCK_NODE_STATE"
+	case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+		return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+	case yaml_PARSE_FLOW_NODE_STATE:
+		return "yaml_PARSE_FLOW_NODE_STATE"
+	case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+		return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+	case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+	case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+	case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+	case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+	case yaml_PARSE_END_STATE:
+		return "yaml_PARSE_END_STATE"
+	}
+	return ""
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+	anchor []byte      // The anchor.
+	index  int         // The node id.
+	mark   yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+	// Error handling
+
+	error yaml_error_type_t // Error type.
+
+	problem string // Error description.
+
+	// The byte about which the problem occurred.
+	problem_offset int
+	problem_value  int
+	problem_mark   yaml_mark_t
+
+	// The error context.
+	context      string
+	context_mark yaml_mark_t
+
+	// Reader stuff
+
+	read_handler yaml_read_handler_t // Read handler.
+
+	input_reader io.Reader // File input data.
+	input        []byte    // String input data.
+	input_pos    int
+
+	eof bool // EOF flag
+
+	buffer     []byte // The working buffer.
+	buffer_pos int    // The current position of the buffer.
+
+	unread int // The number of unread characters in the buffer.
+
+	newlines int // The number of line breaks since last non-break/non-blank character
+
+	raw_buffer     []byte // The raw buffer.
+	raw_buffer_pos int    // The current position of the buffer.
+
+	encoding yaml_encoding_t // The input encoding.
+
+	offset int         // The offset of the current position (in bytes).
+	mark   yaml_mark_t // The mark of the current position.
+
+	// Comments
+
+	head_comment []byte // The current head comments
+	line_comment []byte // The current line comments
+	foot_comment []byte // The current foot comments
+	tail_comment []byte // Foot comment that happens at the end of a block.
+	stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+	comments      []yaml_comment_t // The folded comments for all parsed tokens
+	comments_head int
+
+	// Scanner stuff
+
+	stream_start_produced bool // Have we started to scan the input stream?
+	stream_end_produced   bool // Have we reached the end of the input stream?
+
+	flow_level int // The number of unclosed '[' and '{' indicators.
+
+	tokens          []yaml_token_t // The tokens queue.
+	tokens_head     int            // The head of the tokens queue.
+	tokens_parsed   int            // The number of tokens fetched from the queue.
+	token_available bool           // Does the tokens queue contain a token ready for dequeueing.
+
+	indent  int   // The current indentation level.
+	indents []int // The indentation levels stack.
+
+	simple_key_allowed bool                // May a simple key occur at the current position?
+	simple_keys        []yaml_simple_key_t // The stack of simple keys.
+	simple_keys_by_tok map[int]int         // possible simple_key indexes indexed by token_number
+
+	// Parser stuff
+
+	state          yaml_parser_state_t    // The current parser state.
+	states         []yaml_parser_state_t  // The parser states stack.
+	marks          []yaml_mark_t          // The stack of marks.
+	tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+	// Dumper stuff
+
+	aliases []yaml_alias_data_t // The alias data.
+
+	document *yaml_document_t // The currently parsed document.
+}
+
+type yaml_comment_t struct {
+	scan_mark  yaml_mark_t // Position where scanning for comments started
+	token_mark yaml_mark_t // Position after which tokens will be associated with this comment
+	start_mark yaml_mark_t // Position of '#' comment mark
+	end_mark   yaml_mark_t // Position where comment terminated
+
+	head []byte
+	line []byte
+	foot []byte
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output.  The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out]   data        A pointer to an application data specified by
+//
+//	yaml_emitter_set_output().
+//
+// @param[in]       buffer      The buffer with bytes to be written.
+// @param[in]       size        The size of the buffer.
+//
+// @returns On success, the handler should return @c 1.  If the handler failed,
+// the returned value should be @c 0.
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+	// Expect STREAM-START.
+	yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+	yaml_EMIT_FIRST_DOCUMENT_START_STATE       // Expect the first DOCUMENT-START or STREAM-END.
+	yaml_EMIT_DOCUMENT_START_STATE             // Expect DOCUMENT-START or STREAM-END.
+	yaml_EMIT_DOCUMENT_CONTENT_STATE           // Expect the content of a document.
+	yaml_EMIT_DOCUMENT_END_STATE               // Expect DOCUMENT-END.
+	yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE   // Expect the first item of a flow sequence.
+	yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE   // Expect the next item of a flow sequence, with the comma already written out
+	yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE         // Expect an item of a flow sequence.
+	yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE     // Expect the first key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE     // Expect the next key of a flow mapping, with the comma already written out
+	yaml_EMIT_FLOW_MAPPING_KEY_STATE           // Expect a key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE  // Expect a value for a simple key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_VALUE_STATE         // Expect a value of a flow mapping.
+	yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE  // Expect the first item of a block sequence.
+	yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE        // Expect an item of a block sequence.
+	yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE    // Expect the first key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_KEY_STATE          // Expect the key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_VALUE_STATE        // Expect a value of a block mapping.
+	yaml_EMIT_END_STATE                        // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal.  Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+	// Error handling
+
+	error   yaml_error_type_t // Error type.
+	problem string            // Error description.
+
+	// Writer stuff
+
+	write_handler yaml_write_handler_t // Write handler.
+
+	output_buffer *[]byte   // String output data.
+	output_writer io.Writer // File output data.
+
+	buffer     []byte // The working buffer.
+	buffer_pos int    // The current position of the buffer.
+
+	raw_buffer     []byte // The raw buffer.
+	raw_buffer_pos int    // The current position of the buffer.
+
+	encoding yaml_encoding_t // The stream encoding.
+
+	// Emitter stuff
+
+	canonical   bool         // If the output is in the canonical style?
+	best_indent int          // The number of indentation spaces.
+	best_width  int          // The preferred width of the output lines.
+	unicode     bool         // Allow unescaped non-ASCII characters?
+	line_break  yaml_break_t // The preferred line break.
+
+	state  yaml_emitter_state_t   // The current emitter state.
+	states []yaml_emitter_state_t // The stack of states.
+
+	events      []yaml_event_t // The event queue.
+	events_head int            // The head of the event queue.
+
+	indents []int // The stack of indentation levels.
+
+	tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+	indent int // The current indentation level.
+
+	compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements?
+
+	flow_level int // The current flow level.
+
+	root_context       bool // Is it the document root context?
+	sequence_context   bool // Is it a sequence context?
+	mapping_context    bool // Is it a mapping context?
+	simple_key_context bool // Is it a simple mapping key context?
+
+	line       int  // The current line.
+	column     int  // The current column.
+	whitespace bool // If the last character was a whitespace?
+	indention  bool // If the last character was an indentation character (' ', '-', '?', ':')?
+	open_ended bool // If an explicit document end is required?
+
+	space_above bool // Is there's an empty line above?
+	foot_indent int  // The indent used to write the foot comment above, or -1 if none.
+
+	// Anchor analysis.
+	anchor_data struct {
+		anchor []byte // The anchor value.
+		alias  bool   // Is it an alias?
+	}
+
+	// Tag analysis.
+	tag_data struct {
+		handle []byte // The tag handle.
+		suffix []byte // The tag suffix.
+	}
+
+	// Scalar analysis.
+	scalar_data struct {
+		value                 []byte              // The scalar value.
+		multiline             bool                // Does the scalar contain line breaks?
+		flow_plain_allowed    bool                // Can the scalar be expessed in the flow plain style?
+		block_plain_allowed   bool                // Can the scalar be expressed in the block plain style?
+		single_quoted_allowed bool                // Can the scalar be expressed in the single quoted style?
+		block_allowed         bool                // Can the scalar be expressed in the literal or folded styles?
+		style                 yaml_scalar_style_t // The output style.
+	}
+
+	// Comments
+	head_comment []byte
+	line_comment []byte
+	foot_comment []byte
+	tail_comment []byte
+
+	key_line_comment []byte
+
+	// Dumper stuff
+
+	opened bool // If the stream was already opened?
+	closed bool // If the stream was already closed?
+
+	// The information associated with the document nodes.
+	anchors *struct {
+		references int  // The number of references.
+		anchor     int  // The anchor id.
+		serialized bool // If the node has been emitted?
+	}
+
+	last_anchor_id int // The last assigned anchor id.
+
+	document *yaml_document_t // The currently emitted document.
+}
diff --git a/history-api/vendor/go.yaml.in/yaml/v3/yamlprivateh.go b/history-api/vendor/go.yaml.in/yaml/v3/yamlprivateh.go
new file mode 100644
index 00000000..dea1ba96
--- /dev/null
+++ b/history-api/vendor/go.yaml.in/yaml/v3/yamlprivateh.go
@@ -0,0 +1,198 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+const (
+	// The size of the input raw buffer.
+	input_raw_buffer_size = 512
+
+	// The size of the input buffer.
+	// It should be possible to decode the whole raw buffer.
+	input_buffer_size = input_raw_buffer_size * 3
+
+	// The size of the output buffer.
+	output_buffer_size = 128
+
+	// The size of the output raw buffer.
+	// It should be possible to encode the whole output buffer.
+	output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+	// The size of other stacks and queues.
+	initial_stack_size  = 16
+	initial_queue_size  = 16
+	initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+	return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+	bi := b[i]
+	if bi >= 'A' && bi <= 'F' {
+		return int(bi) - 'A' + 10
+	}
+	if bi >= 'a' && bi <= 'f' {
+		return int(bi) - 'a' + 10
+	}
+	return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+	return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+	return ((b[i] == 0x0A) || // . == #x0A
+		(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+		(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+		(b[i] > 0xC2 && b[i] < 0xED) ||
+		(b[i] == 0xED && b[i+1] < 0xA0) ||
+		(b[i] == 0xEE) ||
+		(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+			!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+			!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+	return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+	return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+	return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+	return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+	//return is_space(b, i) || is_tab(b, i)
+	return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+	return (b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+	return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+	//return is_break(b, i) || is_z(b, i)
+	return (
+	// is_break:
+	b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		// is_z:
+		b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+	//return is_space(b, i) || is_breakz(b, i)
+	return (
+	// is_space:
+	b[i] == ' ' ||
+		// is_breakz:
+		b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+	//return is_blank(b, i) || is_breakz(b, i)
+	return (
+	// is_blank:
+	b[i] == ' ' || b[i] == '\t' ||
+		// is_breakz:
+		b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+	// Don't replace these by a switch without first
+	// confirming that it is being inlined.
+	if b&0x80 == 0x00 {
+		return 1
+	}
+	if b&0xE0 == 0xC0 {
+		return 2
+	}
+	if b&0xF0 == 0xE0 {
+		return 3
+	}
+	if b&0xF8 == 0xF0 {
+		return 4
+	}
+	return 0
+
+}
diff --git a/history-api/vendor/golang.org/x/exp/constraints/constraints.go b/history-api/vendor/golang.org/x/exp/constraints/constraints.go
deleted file mode 100644
index 2c033dff..00000000
--- a/history-api/vendor/golang.org/x/exp/constraints/constraints.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package constraints defines a set of useful constraints to be used
-// with type parameters.
-package constraints
-
-// Signed is a constraint that permits any signed integer type.
-// If future releases of Go add new predeclared signed integer types,
-// this constraint will be modified to include them.
-type Signed interface {
-	~int | ~int8 | ~int16 | ~int32 | ~int64
-}
-
-// Unsigned is a constraint that permits any unsigned integer type.
-// If future releases of Go add new predeclared unsigned integer types,
-// this constraint will be modified to include them.
-type Unsigned interface {
-	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
-// Integer is a constraint that permits any integer type.
-// If future releases of Go add new predeclared integer types,
-// this constraint will be modified to include them.
-type Integer interface {
-	Signed | Unsigned
-}
-
-// Float is a constraint that permits any floating-point type.
-// If future releases of Go add new predeclared floating-point types,
-// this constraint will be modified to include them.
-type Float interface {
-	~float32 | ~float64
-}
-
-// Complex is a constraint that permits any complex numeric type.
-// If future releases of Go add new predeclared complex numeric types,
-// this constraint will be modified to include them.
-type Complex interface {
-	~complex64 | ~complex128
-}
-
-// Ordered is a constraint that permits any ordered type: any type
-// that supports the operators < <= >= >.
-// If future releases of Go add new ordered types,
-// this constraint will be modified to include them.
-type Ordered interface {
-	Integer | Float | ~string
-}
diff --git a/history-api/vendor/golang.org/x/exp/slices/cmp.go b/history-api/vendor/golang.org/x/exp/slices/cmp.go
deleted file mode 100644
index fbf1934a..00000000
--- a/history-api/vendor/golang.org/x/exp/slices/cmp.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-import "golang.org/x/exp/constraints"
-
-// min is a version of the predeclared function from the Go 1.21 release.
-func min[T constraints.Ordered](a, b T) T {
-	if a < b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// max is a version of the predeclared function from the Go 1.21 release.
-func max[T constraints.Ordered](a, b T) T {
-	if a > b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// cmpLess is a copy of cmp.Less from the Go 1.21 release.
-func cmpLess[T constraints.Ordered](x, y T) bool {
-	return (isNaN(x) && !isNaN(y)) || x < y
-}
-
-// cmpCompare is a copy of cmp.Compare from the Go 1.21 release.
-func cmpCompare[T constraints.Ordered](x, y T) int {
-	xNaN := isNaN(x)
-	yNaN := isNaN(y)
-	if xNaN && yNaN {
-		return 0
-	}
-	if xNaN || x < y {
-		return -1
-	}
-	if yNaN || x > y {
-		return +1
-	}
-	return 0
-}
diff --git a/history-api/vendor/golang.org/x/exp/slices/slices.go b/history-api/vendor/golang.org/x/exp/slices/slices.go
deleted file mode 100644
index 46ceac34..00000000
--- a/history-api/vendor/golang.org/x/exp/slices/slices.go
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package slices defines various functions useful with slices of any type.
-package slices
-
-import (
-	"unsafe"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Equal reports whether two slices are equal: the same length and all
-// elements equal. If the lengths are different, Equal returns false.
-// Otherwise, the elements are compared in increasing index order, and the
-// comparison stops at the first unequal pair.
-// Floating point NaNs are not considered equal.
-func Equal[S ~[]E, E comparable](s1, s2 S) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i := range s1 {
-		if s1[i] != s2[i] {
-			return false
-		}
-	}
-	return true
-}
-
-// EqualFunc reports whether two slices are equal using an equality
-// function on each pair of elements. If the lengths are different,
-// EqualFunc returns false. Otherwise, the elements are compared in
-// increasing index order, and the comparison stops at the first index
-// for which eq returns false.
-func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i, v1 := range s1 {
-		v2 := s2[i]
-		if !eq(v1, v2) {
-			return false
-		}
-	}
-	return true
-}
-
-// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
-// of elements. The elements are compared sequentially, starting at index 0,
-// until one element is not equal to the other.
-// The result of comparing the first non-matching elements is returned.
-// If both slices are equal until one of them ends, the shorter slice is
-// considered less than the longer one.
-// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
-func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmpCompare(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// CompareFunc is like [Compare] but uses a custom comparison function on each
-// pair of elements.
-// The result is the first non-zero result of cmp; if cmp always
-// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
-// and +1 if len(s1) > len(s2).
-func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmp(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// Index returns the index of the first occurrence of v in s,
-// or -1 if not present.
-func Index[S ~[]E, E comparable](s S, v E) int {
-	for i := range s {
-		if v == s[i] {
-			return i
-		}
-	}
-	return -1
-}
-
-// IndexFunc returns the first index i satisfying f(s[i]),
-// or -1 if none do.
-func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
-	for i := range s {
-		if f(s[i]) {
-			return i
-		}
-	}
-	return -1
-}
-
-// Contains reports whether v is present in s.
-func Contains[S ~[]E, E comparable](s S, v E) bool {
-	return Index(s, v) >= 0
-}
-
-// ContainsFunc reports whether at least one
-// element e of s satisfies f(e).
-func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
-	return IndexFunc(s, f) >= 0
-}
-
-// Insert inserts the values v... into s at index i,
-// returning the modified slice.
-// The elements at s[i:] are shifted up to make room.
-// In the returned slice r, r[i] == v[0],
-// and r[i+len(v)] == value originally at r[i].
-// Insert panics if i is out of range.
-// This function is O(len(s) + len(v)).
-func Insert[S ~[]E, E any](s S, i int, v ...E) S {
-	m := len(v)
-	if m == 0 {
-		return s
-	}
-	n := len(s)
-	if i == n {
-		return append(s, v...)
-	}
-	if n+m > cap(s) {
-		// Use append rather than make so that we bump the size of
-		// the slice up to the next storage class.
-		// This is what Grow does but we don't call Grow because
-		// that might copy the values twice.
-		s2 := append(s[:i], make(S, n+m-i)...)
-		copy(s2[i:], v)
-		copy(s2[i+m:], s[i:])
-		return s2
-	}
-	s = s[:n+m]
-
-	// before:
-	// s: aaaaaaaabbbbccccccccdddd
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// after:
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	//
-	// a are the values that don't move in s.
-	// v are the values copied in from v.
-	// b and c are the values from s that are shifted up in index.
-	// d are the values that get overwritten, never to be seen again.
-
-	if !overlaps(v, s[i+m:]) {
-		// Easy case - v does not overlap either the c or d regions.
-		// (It might be in some of a or b, or elsewhere entirely.)
-		// The data we copy up doesn't write to v at all, so just do it.
-
-		copy(s[i+m:], s[i:])
-
-		// Now we have
-		// s: aaaaaaaabbbbbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// Note the b values are duplicated.
-
-		copy(s[i:], v)
-
-		// Now we have
-		// s: aaaaaaaavvvvbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// That's the result we want.
-		return s
-	}
-
-	// The hard case - v overlaps c or d. We can't just shift up
-	// the data because we'd move or clobber the values we're trying
-	// to insert.
-	// So instead, write v on top of d, then rotate.
-	copy(s[n:], v)
-
-	// Now we have
-	// s: aaaaaaaabbbbccccccccvvvv
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-
-	rotateRight(s[i:], m)
-
-	// Now we have
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// That's the result we want.
-	return s
-}
-
-// clearSlice sets all elements up to the length of s to the zero value of E.
-// We may use the builtin clear func instead, and remove clearSlice, when upgrading
-// to Go 1.21+.
-func clearSlice[S ~[]E, E any](s S) {
-	var zero E
-	for i := range s {
-		s[i] = zero
-	}
-}
-
-// Delete removes the elements s[i:j] from s, returning the modified slice.
-// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
-// Delete is O(len(s)-i), so if many items must be deleted, it is better to
-// make a single call deleting them all together than to delete one at a time.
-// Delete zeroes the elements s[len(s)-(j-i):len(s)].
-func Delete[S ~[]E, E any](s S, i, j int) S {
-	_ = s[i:j:len(s)] // bounds check
-
-	if i == j {
-		return s
-	}
-
-	oldlen := len(s)
-	s = append(s[:i], s[j:]...)
-	clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
-	return s
-}
-
-// DeleteFunc removes any elements from s for which del returns true,
-// returning the modified slice.
-// DeleteFunc zeroes the elements between the new length and the original length.
-func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
-	i := IndexFunc(s, del)
-	if i == -1 {
-		return s
-	}
-	// Don't start copying elements until we find one to delete.
-	for j := i + 1; j < len(s); j++ {
-		if v := s[j]; !del(v) {
-			s[i] = v
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Replace replaces the elements s[i:j] by the given v, and returns the
-// modified slice. Replace panics if s[i:j] is not a valid slice of s.
-// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
-func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
-	_ = s[i:j] // verify that i:j is a valid subslice
-
-	if i == j {
-		return Insert(s, i, v...)
-	}
-	if j == len(s) {
-		return append(s[:i], v...)
-	}
-
-	tot := len(s[:i]) + len(v) + len(s[j:])
-	if tot > cap(s) {
-		// Too big to fit, allocate and copy over.
-		s2 := append(s[:i], make(S, tot-i)...) // See Insert
-		copy(s2[i:], v)
-		copy(s2[i+len(v):], s[j:])
-		return s2
-	}
-
-	r := s[:tot]
-
-	if i+len(v) <= j {
-		// Easy, as v fits in the deleted portion.
-		copy(r[i:], v)
-		if i+len(v) != j {
-			copy(r[i+len(v):], s[j:])
-		}
-		clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
-		return r
-	}
-
-	// We are expanding (v is bigger than j-i).
-	// The situation is something like this:
-	// (example has i=4,j=8,len(s)=16,len(v)=6)
-	// s: aaaaxxxxbbbbbbbbyy
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	// a: prefix of s
-	// x: deleted range
-	// b: more of s
-	// y: area to expand into
-
-	if !overlaps(r[i+len(v):], v) {
-		// Easy, as v is not clobbered by the first copy.
-		copy(r[i+len(v):], s[j:])
-		copy(r[i:], v)
-		return r
-	}
-
-	// This is a situation where we don't have a single place to which
-	// we can copy v. Parts of it need to go to two different places.
-	// We want to copy the prefix of v into y and the suffix into x, then
-	// rotate |y| spots to the right.
-	//
-	//        v[2:]      v[:2]
-	//         |           |
-	// s: aaaavvvvbbbbbbbbvv
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	//
-	// If either of those two destinations don't alias v, then we're good.
-	y := len(v) - (j - i) // length of y portion
-
-	if !overlaps(r[i:j], v) {
-		copy(r[i:j], v[y:])
-		copy(r[len(s):], v[:y])
-		rotateRight(r[i:], y)
-		return r
-	}
-	if !overlaps(r[len(s):], v) {
-		copy(r[len(s):], v[:y])
-		copy(r[i:j], v[y:])
-		rotateRight(r[i:], y)
-		return r
-	}
-
-	// Now we know that v overlaps both x and y.
-	// That means that the entirety of b is *inside* v.
-	// So we don't need to preserve b at all; instead we
-	// can copy v first, then copy the b part of v out of
-	// v to the right destination.
-	k := startIdx(v, s[j:])
-	copy(r[i:], v)
-	copy(r[i+len(v):], r[i+k:])
-	return r
-}
-
-// Clone returns a copy of the slice.
-// The elements are copied using assignment, so this is a shallow clone.
-func Clone[S ~[]E, E any](s S) S {
-	// Preserve nil in case it matters.
-	if s == nil {
-		return nil
-	}
-	return append(S([]E{}), s...)
-}
-
-// Compact replaces consecutive runs of equal elements with a single copy.
-// This is like the uniq command found on Unix.
-// Compact modifies the contents of the slice s and returns the modified slice,
-// which may have a smaller length.
-// Compact zeroes the elements between the new length and the original length.
-func Compact[S ~[]E, E comparable](s S) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if s[k] != s[k-1] {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// CompactFunc is like [Compact] but uses an equality function to compare elements.
-// For runs of elements that compare equal, CompactFunc keeps the first one.
-// CompactFunc zeroes the elements between the new length and the original length.
-func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if !eq(s[k], s[k-1]) {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Grow increases the slice's capacity, if necessary, to guarantee space for
-// another n elements. After Grow(n), at least n elements can be appended
-// to the slice without another allocation. If n is negative or too large to
-// allocate the memory, Grow panics.
-func Grow[S ~[]E, E any](s S, n int) S {
-	if n < 0 {
-		panic("cannot be negative")
-	}
-	if n -= cap(s) - len(s); n > 0 {
-		// TODO(https://go.dev/issue/53888): Make using []E instead of S
-		// to workaround a compiler bug where the runtime.growslice optimization
-		// does not take effect. Revert when the compiler is fixed.
-		s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)]
-	}
-	return s
-}
-
-// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
-func Clip[S ~[]E, E any](s S) S {
-	return s[:len(s):len(s)]
-}
-
-// Rotation algorithm explanation:
-//
-// rotate left by 2
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join first parts
-//   89234567 01
-// recursively rotate first left part by 2
-//   23456789 01
-// join at the end
-//   2345678901
-//
-// rotate left by 8
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join last parts
-//   89 23456701
-// recursively rotate second part left by 6
-//   89 01234567
-// join at the end
-//   8901234567
-
-// TODO: There are other rotate algorithms.
-// This algorithm has the desirable property that it moves each element exactly twice.
-// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes.
-// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
-
-// rotateLeft rotates b left by n spaces.
-// s_final[i] = s_orig[i+r], wrapping around.
-func rotateLeft[E any](s []E, r int) {
-	for r != 0 && r != len(s) {
-		if r*2 <= len(s) {
-			swap(s[:r], s[len(s)-r:])
-			s = s[:len(s)-r]
-		} else {
-			swap(s[:len(s)-r], s[r:])
-			s, r = s[len(s)-r:], r*2-len(s)
-		}
-	}
-}
-func rotateRight[E any](s []E, r int) {
-	rotateLeft(s, len(s)-r)
-}
-
-// swap swaps the contents of x and y. x and y must be equal length and disjoint.
-func swap[E any](x, y []E) {
-	for i := 0; i < len(x); i++ {
-		x[i], y[i] = y[i], x[i]
-	}
-}
-
-// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
-func overlaps[E any](a, b []E) bool {
-	if len(a) == 0 || len(b) == 0 {
-		return false
-	}
-	elemSize := unsafe.Sizeof(a[0])
-	if elemSize == 0 {
-		return false
-	}
-	// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
-	// Also see crypto/internal/alias/alias.go:AnyOverlap
-	return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
-		uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
-}
-
-// startIdx returns the index in haystack where the needle starts.
-// prerequisite: the needle must be aliased entirely inside the haystack.
-func startIdx[E any](haystack, needle []E) int {
-	p := &needle[0]
-	for i := range haystack {
-		if p == &haystack[i] {
-			return i
-		}
-	}
-	// TODO: what if the overlap is by a non-integral number of Es?
-	panic("needle not found")
-}
-
-// Reverse reverses the elements of the slice in place.
-func Reverse[S ~[]E, E any](s S) {
-	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
-		s[i], s[j] = s[j], s[i]
-	}
-}
diff --git a/history-api/vendor/golang.org/x/exp/slices/sort.go b/history-api/vendor/golang.org/x/exp/slices/sort.go
deleted file mode 100644
index f58bbc7b..00000000
--- a/history-api/vendor/golang.org/x/exp/slices/sort.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp
-
-package slices
-
-import (
-	"math/bits"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Sort sorts a slice of any ordered type in ascending order.
-// When sorting floating-point numbers, NaNs are ordered before other values.
-func Sort[S ~[]E, E constraints.Ordered](x S) {
-	n := len(x)
-	pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
-}
-
-// SortFunc sorts the slice x in ascending order as determined by the cmp
-// function. This sort is not guaranteed to be stable.
-// cmp(a, b) should return a negative number when a < b, a positive number when
-// a > b and zero when a == b or when a is not comparable to b in the sense
-// of the formal definition of Strict Weak Ordering.
-//
-// SortFunc requires that cmp is a strict weak ordering.
-// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
-// To indicate 'uncomparable', return 0 from the function.
-func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	n := len(x)
-	pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
-}
-
-// SortStableFunc sorts the slice x while keeping the original order of equal
-// elements, using cmp to compare elements in the same way as [SortFunc].
-func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	stableCmpFunc(x, len(x), cmp)
-}
-
-// IsSorted reports whether x is sorted in ascending order.
-func IsSorted[S ~[]E, E constraints.Ordered](x S) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmpLess(x[i], x[i-1]) {
-			return false
-		}
-	}
-	return true
-}
-
-// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
-// comparison function as defined by [SortFunc].
-func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmp(x[i], x[i-1]) < 0 {
-			return false
-		}
-	}
-	return true
-}
-
-// Min returns the minimal value in x. It panics if x is empty.
-// For floating-point numbers, Min propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Min[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Min: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = min(m, x[i])
-	}
-	return m
-}
-
-// MinFunc returns the minimal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one minimal element
-// according to the cmp function, MinFunc returns the first one.
-func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MinFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) < 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// Max returns the maximal value in x. It panics if x is empty.
-// For floating-point E, Max propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Max[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Max: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = max(m, x[i])
-	}
-	return m
-}
-
-// MaxFunc returns the maximal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one maximal element
-// according to the cmp function, MaxFunc returns the first one.
-func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MaxFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) > 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// BinarySearch searches for target in a sorted slice and returns the position
-// where target is found, or the position where target would appear in the
-// sort order; it also returns a bool saying whether the target is really found
-// in the slice. The slice must be sorted in increasing order.
-func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) {
-	// Inlining is faster than calling BinarySearchFunc with a lambda.
-	n := len(x)
-	// Define x[-1] < target and x[n] >= target.
-	// Invariant: x[i-1] < target, x[j] >= target.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmpLess(x[h], target) {
-			i = h + 1 // preserves x[i-1] < target
-		} else {
-			j = h // preserves x[j] >= target
-		}
-	}
-	// i == j, x[i-1] < target, and x[j] (= x[i]) >= target  =>  answer is i.
-	return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
-}
-
-// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
-// function. The slice must be sorted in increasing order, where "increasing"
-// is defined by cmp. cmp should return 0 if the slice element matches
-// the target, a negative number if the slice element precedes the target,
-// or a positive number if the slice element follows the target.
-// cmp must implement the same ordering as the slice, such that if
-// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
-func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
-	n := len(x)
-	// Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 .
-	// Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmp(x[h], target) < 0 {
-			i = h + 1 // preserves cmp(x[i - 1], target) < 0
-		} else {
-			j = h // preserves cmp(x[j], target) >= 0
-		}
-	}
-	// i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0  =>  answer is i.
-	return i, i < n && cmp(x[i], target) == 0
-}
-
-type sortedHint int // hint for pdqsort when choosing the pivot
-
-const (
-	unknownHint sortedHint = iota
-	increasingHint
-	decreasingHint
-)
-
-// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
-type xorshift uint64
-
-func (r *xorshift) Next() uint64 {
-	*r ^= *r << 13
-	*r ^= *r >> 17
-	*r ^= *r << 5
-	return uint64(*r)
-}
-
-func nextPowerOfTwo(length int) uint {
-	return 1 << bits.Len(uint(length))
-}
-
-// isNaN reports whether x is a NaN without requiring the math package.
-// This will always return false if T is not floating-point.
-func isNaN[T constraints.Ordered](x T) bool {
-	return x != x
-}
diff --git a/history-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/history-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go
deleted file mode 100644
index 06f2c7a2..00000000
--- a/history-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go
+++ /dev/null
@@ -1,479 +0,0 @@
-// Code generated by gen_sort_variants.go; DO NOT EDIT.
-
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-// insertionSortCmpFunc sorts data[a:b] using insertion sort.
-func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	for i := a + 1; i < b; i++ {
-		for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
-			data[j], data[j-1] = data[j-1], data[j]
-		}
-	}
-}
-
-// siftDownCmpFunc implements the heap property on data[lo:hi].
-// first is an offset into the array where the root of the heap lies.
-func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
-	root := lo
-	for {
-		child := 2*root + 1
-		if child >= hi {
-			break
-		}
-		if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
-			child++
-		}
-		if !(cmp(data[first+root], data[first+child]) < 0) {
-			return
-		}
-		data[first+root], data[first+child] = data[first+child], data[first+root]
-		root = child
-	}
-}
-
-func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	first := a
-	lo := 0
-	hi := b - a
-
-	// Build heap with greatest element at top.
-	for i := (hi - 1) / 2; i >= 0; i-- {
-		siftDownCmpFunc(data, i, hi, first, cmp)
-	}
-
-	// Pop elements, largest first, into end of data.
-	for i := hi - 1; i >= 0; i-- {
-		data[first], data[first+i] = data[first+i], data[first]
-		siftDownCmpFunc(data, lo, i, first, cmp)
-	}
-}
-
-// pdqsortCmpFunc sorts data[a:b].
-// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
-// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
-// C++ implementation: https://github.com/orlp/pdqsort
-// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
-// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
-func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
-	const maxInsertion = 12
-
-	var (
-		wasBalanced    = true // whether the last partitioning was reasonably balanced
-		wasPartitioned = true // whether the slice was already partitioned
-	)
-
-	for {
-		length := b - a
-
-		if length <= maxInsertion {
-			insertionSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// Fall back to heapsort if too many bad choices were made.
-		if limit == 0 {
-			heapSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// If the last partitioning was imbalanced, we need to breaking patterns.
-		if !wasBalanced {
-			breakPatternsCmpFunc(data, a, b, cmp)
-			limit--
-		}
-
-		pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
-		if hint == decreasingHint {
-			reverseRangeCmpFunc(data, a, b, cmp)
-			// The chosen pivot was pivot-a elements after the start of the array.
-			// After reversing it is pivot-a elements before the end of the array.
-			// The idea came from Rust's implementation.
-			pivot = (b - 1) - (pivot - a)
-			hint = increasingHint
-		}
-
-		// The slice is likely already sorted.
-		if wasBalanced && wasPartitioned && hint == increasingHint {
-			if partialInsertionSortCmpFunc(data, a, b, cmp) {
-				return
-			}
-		}
-
-		// Probably the slice contains many duplicate elements, partition the slice into
-		// elements equal to and elements greater than the pivot.
-		if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
-			mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
-			a = mid
-			continue
-		}
-
-		mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
-		wasPartitioned = alreadyPartitioned
-
-		leftLen, rightLen := mid-a, b-mid
-		balanceThreshold := length / 8
-		if leftLen < rightLen {
-			wasBalanced = leftLen >= balanceThreshold
-			pdqsortCmpFunc(data, a, mid, limit, cmp)
-			a = mid + 1
-		} else {
-			wasBalanced = rightLen >= balanceThreshold
-			pdqsortCmpFunc(data, mid+1, b, limit, cmp)
-			b = mid
-		}
-	}
-}
-
-// partitionCmpFunc does one quicksort partition.
-// Let p = data[pivot]
-// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/history-api/vendor/golang.org/x/exp/slices/zsortordered.go b/history-api/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c39..00000000 --- a/history-api/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/history-api/vendor/golang.org/x/exp/slog/attr.go b/history-api/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/history-api/vendor/golang.org/x/exp/slog/doc.go b/history-api/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf867..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/history-api/vendor/golang.org/x/exp/slog/handler.go b/history-api/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb8..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/history-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/history-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/history-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/history-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/history-api/vendor/golang.org/x/exp/slog/json_handler.go b/history-api/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada86..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/history-api/vendor/golang.org/x/exp/slog/level.go b/history-api/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0a..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/history-api/vendor/golang.org/x/exp/slog/logger.go b/history-api/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec993..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/history-api/vendor/golang.org/x/exp/slog/noplog.bench b/history-api/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/history-api/vendor/golang.org/x/exp/slog/record.go b/history-api/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/history-api/vendor/golang.org/x/exp/slog/text_handler.go b/history-api/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b71..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/history-api/vendor/golang.org/x/exp/slog/value.go b/history-api/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46f..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/history-api/vendor/golang.org/x/exp/slog/value_119.go b/history-api/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d732..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/history-api/vendor/golang.org/x/exp/slog/value_120.go b/history-api/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c093..00000000 --- a/history-api/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/history-api/vendor/golang.org/x/net/http2/frame.go b/history-api/vendor/golang.org/x/net/http2/frame.go index 97bd8b06..db3264da 100644 --- a/history-api/vendor/golang.org/x/net/http2/frame.go +++ b/history-api/vendor/golang.org/x/net/http2/frame.go @@ -39,7 +39,7 @@ const ( FrameContinuation FrameType = 0x9 ) -var frameName = map[FrameType]string{ +var frameNames = [...]string{ FrameData: "DATA", FrameHeaders: "HEADERS", FramePriority: "PRIORITY", @@ -53,10 +53,10 @@ var frameName = map[FrameType]string{ } func (t FrameType) String() string { - if s, ok := frameName[t]; ok { - return s + if int(t) < len(frameNames) { + return frameNames[t] } - return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) + return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t) } // Flags is a bitmask of HTTP/2 flags. @@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{ // might be 0). type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) -var frameParsers = map[FrameType]frameParser{ +var frameParsers = [...]frameParser{ FrameData: parseDataFrame, FrameHeaders: parseHeadersFrame, FramePriority: parsePriorityFrame, @@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{ } func typeFrameParser(t FrameType) frameParser { - if f := frameParsers[t]; f != nil { - return f + if int(t) < len(frameParsers) { + return frameParsers[t] } return parseUnknownFrame } @@ -509,7 +509,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { } if fh.Length > fr.maxReadSize { if fh == invalidHTTP1LookingFrameHeader() { - return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge) } return nil, ErrFrameTooLarge } diff --git a/history-api/vendor/golang.org/x/net/http2/http2.go b/history-api/vendor/golang.org/x/net/http2/http2.go index 6c18ea23..ea5ae629 100644 --- a/history-api/vendor/golang.org/x/net/http2/http2.go +++ b/history-api/vendor/golang.org/x/net/http2/http2.go @@ -11,8 +11,6 @@ // requires Go 1.6 or later) // // See https://http2.github.io/ for more information on HTTP/2. -// -// See https://http2.golang.org/ for a test server running this code. package http2 // import "golang.org/x/net/http2" import ( diff --git a/history-api/vendor/golang.org/x/net/trace/events.go b/history-api/vendor/golang.org/x/net/trace/events.go index c646a695..3aaffdd1 100644 --- a/history-api/vendor/golang.org/x/net/trace/events.go +++ b/history-api/vendor/golang.org/x/net/trace/events.go @@ -508,7 +508,7 @@ const eventsHTML = ` {{$el.When}} {{$el.ElapsedTime}} - {{$el.Title}} + {{$el.Title}} {{if $.Expanded}} diff --git a/history-api/vendor/golang.org/x/sync/errgroup/errgroup.go b/history-api/vendor/golang.org/x/sync/errgroup/errgroup.go index cb6bb9ad..1d8cffae 100644 --- a/history-api/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/history-api/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -12,8 +12,6 @@ package errgroup import ( "context" "fmt" - "runtime" - "runtime/debug" "sync" ) @@ -33,10 +31,6 @@ type Group struct { errOnce sync.Once err error - - mu sync.Mutex - panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked. - abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit). } func (g *Group) done() { @@ -56,22 +50,13 @@ func WithContext(ctx context.Context) (*Group, context.Context) { return &Group{cancel: cancel}, ctx } -// Wait blocks until all function calls from the Go method have returned -// normally, then returns the first non-nil error (if any) from them. -// -// If any of the calls panics, Wait panics with a [PanicValue]; -// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit. +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. func (g *Group) Wait() error { g.wg.Wait() if g.cancel != nil { g.cancel(g.err) } - if g.panicValue != nil { - panic(g.panicValue) - } - if g.abnormal { - runtime.Goexit() - } return g.err } @@ -81,53 +66,31 @@ func (g *Group) Wait() error { // It blocks until the new goroutine can be added without the number of // goroutines in the group exceeding the configured limit. // -// The first goroutine in the group that returns a non-nil error, panics, or -// invokes [runtime.Goexit] will cancel the associated Context, if any. +// The first goroutine in the group that returns a non-nil error will +// cancel the associated Context, if any. The error will be returned +// by Wait. func (g *Group) Go(f func() error) { if g.sem != nil { g.sem <- token{} } - g.add(f) -} - -func (g *Group) add(f func() error) { g.wg.Add(1) go func() { defer g.done() - normalReturn := false - defer func() { - if normalReturn { - return - } - v := recover() - g.mu.Lock() - defer g.mu.Unlock() - if !g.abnormal { - if g.cancel != nil { - g.cancel(g.err) - } - g.abnormal = true - } - if v != nil && g.panicValue == nil { - switch v := v.(type) { - case error: - g.panicValue = PanicError{ - Recovered: v, - Stack: debug.Stack(), - } - default: - g.panicValue = PanicValue{ - Recovered: v, - Stack: debug.Stack(), - } - } - } - }() - err := f() - normalReturn = true - if err != nil { + // It is tempting to propagate panics from f() + // up to the goroutine that calls Wait, but + // it creates more problems than it solves: + // - it delays panics arbitrarily, + // making bugs harder to detect; + // - it turns f's panic stack into a mere value, + // hiding it from crash-monitoring tools; + // - it risks deadlocks that hide the panic entirely, + // if f's panic leaves the program in a state + // that prevents the Wait call from being reached. + // See #53757, #74275, #74304, #74306. + + if err := f(); err != nil { g.errOnce.Do(func() { g.err = err if g.cancel != nil { @@ -152,7 +115,19 @@ func (g *Group) TryGo(f func() error) bool { } } - g.add(f) + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() return true } @@ -174,34 +149,3 @@ func (g *Group) SetLimit(n int) { } g.sem = make(chan token, n) } - -// PanicError wraps an error recovered from an unhandled panic -// when calling a function passed to Go or TryGo. -type PanicError struct { - Recovered error - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicError) Error() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} - -func (p PanicError) Unwrap() error { return p.Recovered } - -// PanicValue wraps a value that does not implement the error interface, -// recovered from an unhandled panic when calling a function passed to Go or -// TryGo. -type PanicValue struct { - Recovered any - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicValue) String() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} diff --git a/history-api/vendor/golang.org/x/sys/unix/mkerrors.sh b/history-api/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c..d1c8b264 100644 --- a/history-api/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/history-api/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/history-api/vendor/golang.org/x/sys/unix/syscall_darwin.go b/history-api/vendor/golang.org/x/sys/unix/syscall_darwin.go index 798f61ad..7838ca5d 100644 --- a/history-api/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/history-api/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,14 +602,9 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) const minIovec = 8 func Readv(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = readv(fd, iovecs) @@ -618,9 +613,6 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { } func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = preadv(fd, iovecs, offset) @@ -629,10 +621,6 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -644,10 +632,6 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -707,45 +691,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } } -func darwinMajorMinPatch() (maj, min, patch int, err error) { - var un Utsname - err = Uname(&un) - if err != nil { - return - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range un.Release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return 0, 0, 0, ENOTSUP - } - case b == 0: - break Loop - default: - return 0, 0, 0, ENOTSUP - } - } - if c != 2 { - return 0, 0, 0, ENOTSUP - } - return mmp[0], mmp[1], mmp[2], nil -} - -func darwinKernelVersionMin(maj, min, patch int) bool { - actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() - if err != nil { - return false - } - return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) -} - +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux.go index 4f432bfe..b6db27d9 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -319,6 +319,7 @@ const ( AUDIT_INTEGRITY_POLICY_RULE = 0x70f AUDIT_INTEGRITY_RULE = 0x70d AUDIT_INTEGRITY_STATUS = 0x70a + AUDIT_INTEGRITY_USERSPACE = 0x710 AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f AUDIT_IPE_ACCESS = 0x58c @@ -327,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -491,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -527,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -554,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -843,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2023-03-01)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x30 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -936,11 +942,10 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 + ETHTOOL_FAMILY_NAME = "ethtool" + ETHTOOL_FAMILY_VERSION = 0x1 ETHTOOL_FEC_AUTO = 0x2 ETHTOOL_FEC_BASER = 0x10 ETHTOOL_FEC_LLRS = 0x20 @@ -1203,13 +1208,18 @@ const ( FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 FAN_EPIDFD = -0x2 + FAN_ERRNO_BITS = 0x8 + FAN_ERRNO_MASK = 0xff + FAN_ERRNO_SHIFT = 0x18 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 + FAN_EVENT_INFO_TYPE_RANGE = 0x6 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_FS_ERROR = 0x8000 @@ -1224,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1240,6 +1253,7 @@ const ( FAN_OPEN_EXEC = 0x1000 FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 + FAN_PRE_ACCESS = 0x100000 FAN_Q_OVERFLOW = 0x4000 FAN_RENAME = 0x10000000 FAN_REPORT_DFID_NAME = 0xc00 @@ -1247,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1266,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1574,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1625,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1687,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1809,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2485,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2644,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2724,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2787,7 +2813,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1e + RTA_MAX = 0x1f RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -2864,10 +2890,12 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELANYCAST = 0x3d RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELLINKPROP = 0x6d RTM_DELMDB = 0x55 + RTM_DELMULTICAST = 0x39 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 @@ -2917,11 +2945,13 @@ const ( RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 + RTM_NEWANYCAST = 0x3c RTM_NEWCACHEREPORT = 0x60 RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWLINKPROP = 0x6c RTM_NEWMDB = 0x54 + RTM_NEWMULTICAST = 0x38 RTM_NEWNDUSEROPT = 0x44 RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 @@ -2970,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -2987,11 +3018,12 @@ const ( RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 RWF_ATOMIC = 0x40 + RWF_DONTCACHE = 0x80 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x7f + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3271,6 +3303,7 @@ const ( STATX_BTIME = 0x800 STATX_CTIME = 0x80 STATX_DIOALIGN = 0x2000 + STATX_DIO_READ_ALIGN = 0x20000 STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 @@ -3322,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xe + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3392,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3503,6 +3534,7 @@ const ( TP_STATUS_WRONG_FORMAT = 0x4 TRACEFS_MAGIC = 0x74726163 TS_COMM_LEN = 0x20 + UBI_IOCECNFO = 0xc01c6f06 UDF_SUPER_MAGIC = 0x15013346 UDP_CORK = 0x1 UDP_ENCAP = 0x64 @@ -3515,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3559,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3673,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 75207613..1c37f9fb 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -372,6 +374,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c68acda5..6f54d34a 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -373,6 +375,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index a8c607ab..783ec5c1 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -378,6 +380,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 18563dd8..ca83d3ba 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 22912cda..607e611c 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -365,6 +367,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 29344eb3..b9cb5bd3 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 20d51fb9..65b078a6 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 321b6090..5298a303 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 9bacdf1e..7bc557c8 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c2242726..152399bb 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -426,6 +428,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 6270c8ee..1a1ce240 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 9966c194..4231a1fb 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 848e5fcc..21c0e952 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -362,6 +364,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 669b2adb..f00d1cd7 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -434,6 +436,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 4834e575..bc8d539e 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 @@ -473,6 +475,7 @@ const ( SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff3..aca56ee4 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb45069..2ea1ef58 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e50297..d22c8af3 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec5..5ee264ae 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a..f9f03ebf 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a33..87c2118e 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b99622..391ad102 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9..56561577 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc..0482b52e 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfb..71806f08 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b4463650..e35a7105 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c1..2aea4767 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 84053916..6c9bb4e5 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790..680bc991 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f..620f2710 100644 --- a/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux.go index a46abe64..cd236443 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,10 @@ type Statx_t struct { Atomic_write_unit_min uint32 Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 _ [1]uint32 - _ [9]uint64 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2226,8 +2229,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -2314,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2594,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -3802,7 +3813,16 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2d + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3842,7 +3862,17 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -3949,7 +3979,12 @@ const ( ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb ETHTOOL_A_RINGS_CQE_SIZE = 0xc ETHTOOL_A_RINGS_TX_PUSH = 0xd - ETHTOOL_A_RINGS_MAX = 0x10 + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 ETHTOOL_A_CHANNELS_UNSPEC = 0x0 ETHTOOL_A_CHANNELS_HEADER = 0x1 ETHTOOL_A_CHANNELS_RX_MAX = 0x2 @@ -4015,7 +4050,9 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x6 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4101,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4613,6 +4663,7 @@ const ( NL80211_ATTR_AKM_SUITES = 0x4c NL80211_ATTR_AP_ISOLATE = 0x60 NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a NL80211_ATTR_AUTH_DATA = 0x9c NL80211_ATTR_AUTH_TYPE = 0x35 NL80211_ATTR_BANDS = 0xef @@ -4623,6 +4674,7 @@ const ( NL80211_ATTR_BSS_BASIC_RATES = 0x24 NL80211_ATTR_BSS = 0x2f NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 NL80211_ATTR_BSS_HT_OPMODE = 0x6d NL80211_ATTR_BSSID = 0xf5 NL80211_ATTR_BSS_SELECT = 0xe3 @@ -4682,6 +4734,7 @@ const ( NL80211_ATTR_DTIM_PERIOD = 0xd NL80211_ATTR_DURATION = 0x57 NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 NL80211_ATTR_EML_CAPABILITY = 0x13d NL80211_ATTR_EXT_CAPA = 0xa9 NL80211_ATTR_EXT_CAPA_MASK = 0xaa @@ -4717,6 +4770,7 @@ const ( NL80211_ATTR_HIDDEN_SSID = 0x7e NL80211_ATTR_HT_CAPABILITY = 0x1f NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 NL80211_ATTR_IE_ASSOC_RESP = 0x80 NL80211_ATTR_IE = 0x2a NL80211_ATTR_IE_PROBE_RESP = 0x7f @@ -4747,9 +4801,10 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14d + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 NL80211_ATTR_MAX_MATCH_SETS = 0x85 NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 @@ -4774,9 +4829,12 @@ const ( NL80211_ATTR_MGMT_SUBTYPE = 0x29 NL80211_ATTR_MLD_ADDR = 0x13a NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 NL80211_ATTR_MLO_LINK_ID = 0x139 NL80211_ATTR_MLO_LINKS = 0x138 NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 NL80211_ATTR_MNTR_FLAGS = 0x17 NL80211_ATTR_MPATH_INFO = 0x1b NL80211_ATTR_MPATH_NEXT_HOP = 0x1a @@ -4809,12 +4867,14 @@ const ( NL80211_ATTR_PORT_AUTHORIZED = 0x103 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 NL80211_ATTR_PREV_BSSID = 0x4f NL80211_ATTR_PRIVACY = 0x46 NL80211_ATTR_PROBE_RESP = 0x91 NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 NL80211_ATTR_PROTOCOL_FEATURES = 0xad NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 NL80211_ATTR_QOS_MAP = 0xc7 NL80211_ATTR_RADAR_BACKGROUND = 0x134 NL80211_ATTR_RADAR_EVENT = 0xa8 @@ -4943,7 +5003,9 @@ const ( NL80211_ATTR_WIPHY_FREQ = 0x26 NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 @@ -4978,6 +5040,8 @@ const ( NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 NL80211_BAND_ATTR_MAX = 0xd NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc NL80211_BAND_ATTR_VHT_CAPA = 0x8 NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 @@ -5001,6 +5065,10 @@ const ( NL80211_BSS_BEACON_INTERVAL = 0x4 NL80211_BSS_BEACON_TSF = 0xd NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 NL80211_BSS_CAPABILITY = 0x5 NL80211_BSS_CHAIN_SIGNAL = 0x13 NL80211_BSS_CHAN_WIDTH_10 = 0x1 @@ -5032,6 +5100,9 @@ const ( NL80211_BSS_STATUS = 0x9 NL80211_BSS_STATUS_IBSS_JOINED = 0x2 NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 NL80211_CHAN_HT20 = 0x1 NL80211_CHAN_HT40MINUS = 0x2 NL80211_CHAN_HT40PLUS = 0x3 @@ -5117,7 +5188,8 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9b + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5161,6 +5233,7 @@ const ( NL80211_CMD_SET_COALESCE = 0x65 NL80211_CMD_SET_CQM = 0x3f NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 NL80211_CMD_SET_INTERFACE = 0x6 NL80211_CMD_SET_KEY = 0xa NL80211_CMD_SET_MAC_ACL = 0x5d @@ -5180,6 +5253,7 @@ const ( NL80211_CMD_SET_SAR_SPECS = 0x8c NL80211_CMD_SET_STATION = 0x12 NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 NL80211_CMD_SET_WDS_PEER = 0x42 NL80211_CMD_SET_WIPHY = 0x2 @@ -5247,6 +5321,7 @@ const ( NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 @@ -5262,6 +5337,7 @@ const ( NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 @@ -5281,9 +5357,12 @@ const ( NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c NL80211_EXT_FEATURE_RRM = 0x1 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 @@ -5295,8 +5374,10 @@ const ( NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f NL80211_EXT_FEATURE_SECURE_RTT = 0x38 NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 NL80211_EXT_FEATURE_TXQS = 0x1c NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 @@ -5343,7 +5424,10 @@ const ( NL80211_FREQUENCY_ATTR_2MHZ = 0x16 NL80211_FREQUENCY_ATTR_4MHZ = 0x17 NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 NL80211_FREQUENCY_ATTR_DISABLED = 0x2 @@ -5351,12 +5435,14 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b NL80211_FREQUENCY_ATTR_NO_HE = 0x13 @@ -5364,8 +5450,11 @@ const ( NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_OFFSET = 0x14 NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c NL80211_FREQUENCY_ATTR_RADAR = 0x5 NL80211_FREQUENCY_ATTR_WMM = 0x12 NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 @@ -5430,6 +5519,7 @@ const ( NL80211_IFTYPE_STATION = 0x2 NL80211_IFTYPE_UNSPECIFIED = 0x0 NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 NL80211_KCK_EXT_LEN = 0x18 NL80211_KCK_LEN = 0x10 NL80211_KEK_EXT_LEN = 0x20 @@ -5458,9 +5548,10 @@ const ( NL80211_MAX_SUPP_HT_RATES = 0x4d NL80211_MAX_SUPP_RATES = 0x20 NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 @@ -5703,11 +5794,16 @@ const ( NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c NL80211_RATE_INFO_BITRATE32 = 0x5 NL80211_RATE_INFO_BITRATE = 0x1 NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 @@ -5753,6 +5849,8 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 NL80211_RATE_INFO_SHORT_GI = 0x4 NL80211_RATE_INFO_VHT_MCS = 0x6 NL80211_RATE_INFO_VHT_NSS = 0x7 @@ -5770,14 +5868,19 @@ const ( NL80211_REKEY_DATA_KEK = 0x1 NL80211_REKEY_DATA_REPLAY_CTR = 0x3 NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 NL80211_RRF_AUTO_BW = 0x800 NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 NL80211_RRF_GO_CONCURRENT = 0x1000 NL80211_RRF_IR_CONCURRENT = 0x1000 NL80211_RRF_NO_160MHZ = 0x10000 NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 NL80211_RRF_NO_80MHZ = 0x8000 NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 NL80211_RRF_NO_HE = 0x20000 NL80211_RRF_NO_HT40 = 0x6000 NL80211_RRF_NO_HT40MINUS = 0x2000 @@ -5788,7 +5891,10 @@ const ( NL80211_RRF_NO_IR = 0x80 NL80211_RRF_NO_OFDM = 0x1 NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 NL80211_RRF_PTMP_ONLY = 0x40 NL80211_RRF_PTP_ONLY = 0x20 NL80211_RXMGMT_FLAG_ANSWERED = 0x1 @@ -5849,6 +5955,7 @@ const ( NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 NL80211_STA_FLAG_TDLS_PEER = 0x6 NL80211_STA_FLAG_WME = 0x3 NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 @@ -6007,6 +6114,13 @@ const ( NL80211_VHT_CAPABILITY_LEN = 0xc NL80211_VHT_NSS_MAX = 0x8 NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 NL80211_WMMR_AIFSN = 0x3 NL80211_WMMR_CW_MAX = 0x2 NL80211_WMMR_CW_MIN = 0x1 @@ -6038,6 +6152,7 @@ const ( NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fd402da4..485f2d3a 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -338,6 +338,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index eb7a5e18..ecbd1ad8 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -351,6 +351,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index d78ac108..02f0463a 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -329,6 +329,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index cd06d47f..6f4d400d 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -330,6 +330,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2f28fe26..cd532cfa 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -331,6 +331,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 71d6cac2..41336208 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8596d453..eaa37eb7 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index cd60ea18..98ae6a1e 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b0ae420c..cae19615 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 83597287..6ce3b4e0 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,7 +285,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -341,6 +341,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 69eb6a5c..c7429c6a 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5f583cb6..4bf4baf4 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index ad05b51a..e9709d70 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -358,6 +358,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cf3ce900..fb44268c 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -353,6 +353,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 590b5673..9c38265c 100644 --- a/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/history-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -335,6 +335,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/history-api/vendor/golang.org/x/telemetry/.dockerignore b/history-api/vendor/golang.org/x/telemetry/.dockerignore new file mode 100644 index 00000000..416ae44a --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.dockerignore @@ -0,0 +1,17 @@ +.git +.localstorage +node_modules +devtools +.eslint* +.gitignore +.prettier* +.stylelint* +CONTRIBUTING.md +LICENSE +npm +npx +package-lock.json +package.json +PATENTS +README.md +tsconfig.json \ No newline at end of file diff --git a/history-api/vendor/golang.org/x/telemetry/.eslintrc.json b/history-api/vendor/golang.org/x/telemetry/.eslintrc.json new file mode 100644 index 00000000..ba5e242b --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "root": true, + "ignorePatterns": ["*.min.js"] +} diff --git a/history-api/vendor/golang.org/x/telemetry/.gitattributes b/history-api/vendor/golang.org/x/telemetry/.gitattributes new file mode 100644 index 00000000..f529a114 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.gitattributes @@ -0,0 +1,14 @@ +# Treat all files in the repo as binary, with no git magic updating +# line endings. This produces predictable results in different environments. +# +# Windows users contributing to Go will need to use a modern version +# of git and editors capable of LF line endings. +# +# Windows .bat files are known to have multiple bugs when run with LF +# endings. So if they are checked in with CRLF endings, there should +# be a test like the one in test/winbatch.go in the go repository. +# (See golang.org/issue/37791.) +# +# See golang.org/issue/9281. + +* -text diff --git a/history-api/vendor/golang.org/x/telemetry/.gitignore b/history-api/vendor/golang.org/x/telemetry/.gitignore new file mode 100644 index 00000000..46770c48 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.gitignore @@ -0,0 +1,2 @@ +node_modules +.localstorage \ No newline at end of file diff --git a/history-api/vendor/golang.org/x/telemetry/.prettierrc.json b/history-api/vendor/golang.org/x/telemetry/.prettierrc.json new file mode 100644 index 00000000..91c0b944 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.prettierrc.json @@ -0,0 +1 @@ +{"proseWrap": "always"} diff --git a/history-api/vendor/golang.org/x/telemetry/.stylelintrc.json b/history-api/vendor/golang.org/x/telemetry/.stylelintrc.json new file mode 100644 index 00000000..adccf47b --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/.stylelintrc.json @@ -0,0 +1,11 @@ +{ + "extends": ["stylelint-config-standard"], + "rules": { + "declaration-property-value-allowed-list": { + "/color/": ["/^var\\(--/", "transparent"] + }, + "unit-disallowed-list": ["px"], + "selector-class-pattern": "^[a-zA-Z\\-]+$" + }, + "ignoreFiles": ["**/*.min.css"] +} diff --git a/history-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md b/history-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md new file mode 100644 index 00000000..e913373f --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these +five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the +[golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead +of the issue tracker. The gophers there will answer or ask you to file an issue +if you've tripped over a bug. + +## Contributing code + +Please read the +[Contribution Guidelines](https://golang.org/doc/contribute.html) before sending +patches. + +Unless otherwise noted, the Go source files are distributed under the BSD-style +license found in the LICENSE file. diff --git a/history-api/vendor/golang.org/x/exp/LICENSE b/history-api/vendor/golang.org/x/telemetry/LICENSE similarity index 100% rename from history-api/vendor/golang.org/x/exp/LICENSE rename to history-api/vendor/golang.org/x/telemetry/LICENSE diff --git a/history-api/vendor/golang.org/x/exp/PATENTS b/history-api/vendor/golang.org/x/telemetry/PATENTS similarity index 100% rename from history-api/vendor/golang.org/x/exp/PATENTS rename to history-api/vendor/golang.org/x/telemetry/PATENTS diff --git a/history-api/vendor/golang.org/x/telemetry/README.md b/history-api/vendor/golang.org/x/telemetry/README.md new file mode 100644 index 00000000..81a15749 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/README.md @@ -0,0 +1,62 @@ +# Go Telemetry + +This repository holds the Go Telemetry server code and libraries, used for +hosting [telemetry.go.dev](https://telemetry.go.dev) and instrumenting Go +toolchain programs with opt-in telemetry. + +**Warning**: this repository is intended for use only in tools maintained by +the Go team, including tools in the Go distribution and auxiliary tools like +[gopls](https://pkg.go.dev/golang.org/x/tools/gopls) or +[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck). There are +no compatibility guarantees for any of the packages here: public APIs will +change in breaking ways as the telemetry integration is refined. + +## Notable Packages + +- The [x/telemetry/counter](https://pkg.go.dev/golang.org/x/telemetry/counter) + package provides a library for instrumenting programs with counters and stack + reports. +- The [x/telemetry/upload](https://pkg.go.dev/golang.org/x/telemetry/upload) + package provides a hook for Go toolchain programs to upload telemetry data, + if the user has opted in to telemetry uploading. +- The [x/telemetry/cmd/gotelemetry](https://pkg.go.dev/pkg/golang.org/x/telemetry/cmd/gotelemetry) + command is used for managing telemetry data and configuration. +- The [x/telemetry/config](https://pkg.go.dev/pkg/golang.org/x/telemetry/config) + package defines the subset of telemetry data that has been approved for + uploading by the telemetry proposal process. +- The [x/telemetry/godev](https://pkg.go.dev/pkg/golang.org/x/telemetry/godev) directory defines + the services running at [telemetry.go.dev](https://telemetry.go.dev). + +## Contributing + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/telemetry. + +The main issue tracker for the telemetry repository is located at +https://go.dev/issues. Prefix your issue with "x/telemetry:" in +the subject line, so it is easy to find. + +### Linting & Formatting + +This repository uses [eslint](https://eslint.org/) to format TS files, +[stylelint](https://stylelint.io/) to format CSS files, and +[prettier](https://prettier.io/) to format TS, CSS, Markdown, and YAML files. + +See the style guides: + +- [TypeScript](https://google.github.io/styleguide/tsguide.html) +- [CSS](https://go.dev/wiki/CSSStyleGuide) + +It is encouraged that all TS and CSS code be run through formatters before +submitting a change. However, it is not a strict requirement enforced by CI. + +### Installing npm Dependencies: + +1. Install [docker](https://docs.docker.com/get-docker/) +2. Run `./npm install` + +### Run ESLint, Stylelint, & Prettier + + ./npm run all diff --git a/history-api/vendor/golang.org/x/telemetry/counter/counter.go b/history-api/vendor/golang.org/x/telemetry/counter/counter.go new file mode 100644 index 00000000..fe2d0f69 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/counter/counter.go @@ -0,0 +1,146 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +// The implementation of this package and tests are located in +// internal/counter, which can be shared with the upload package. +// TODO(hyangah): use of type aliases prevents nice documentation +// rendering in go doc or pkgsite. Fix this either by avoiding +// type aliasing or restructuring the internal/counter package. +import ( + "flag" + "path" + "runtime/debug" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// Inc increments the counter with the given name. +func Inc(name string) { + New(name).Inc() +} + +// Add adds n to the counter with the given name. +func Add(name string, n int64) { + New(name).Add(n) +} + +// New returns a counter with the given name. +// New can be called in global initializers and will be compiled down to +// linker-initialized data. That is, calling New to initialize a global +// has no cost at program startup. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func New(name string) *Counter { + // Note: not calling DefaultFile.New in order to keep this + // function something the compiler can inline and convert + // into static data initializations, with no init-time footprint. + // TODO(hyangah): is it trivial enough for the compiler to inline? + return counter.New(name) +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter = counter.Counter + +// A StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter = counter.StackCounter + +// NewStack returns a new stack counter with the given name and depth. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func NewStack(name string, depth int) *StackCounter { + return counter.NewStack(name, depth) +} + +// Open prepares telemetry counters for recording to the file system. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Open should only be called from short-lived processes such as command line +// tools. If your process is long-running, use [OpenAndRotate]. +func Open() { + counter.Open(false) +} + +// OpenAndRotate is like [Open], but also schedules a rotation of the counter +// file when it expires. +// +// See golang/go#68497 for background on why [OpenAndRotate] is a separate API. +// +// TODO(rfindley): refactor Open and OpenAndRotate for Go 1.24. +func OpenAndRotate() { + counter.Open(true) +} + +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open(false) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +// +// For instance, CountFlags("gopls/flag:", *flag.CommandLine) +func CountFlags(prefix string, fs flag.FlagSet) { + fs.Visit(func(f *flag.Flag) { + New(prefix + f.Name).Inc() + }) +} + +// CountCommandLineFlags creates a counter for every flag +// that is set in the default flag.CommandLine FlagSet using +// the counter name binaryName+"/flag:"+flagName where +// binaryName is the base name of the Path embedded in the +// binary's build info. If the binary does not have embedded build +// info, the "flag:"+flagName counter will be incremented. +// +// CountCommandLineFlags must be called after flags are parsed +// with flag.Parse. +// +// For instance, if the -S flag is passed to cmd/compile and +// CountCommandLineFlags is called after flags are parsed, +// the "compile/flag:S" counter will be incremented. +func CountCommandLineFlags() { + prefix := "flag:" + if buildInfo, ok := debug.ReadBuildInfo(); ok && buildInfo.Path != "" { + prefix = path.Base(buildInfo.Path) + "/" + prefix + } + CountFlags(prefix, *flag.CommandLine) +} diff --git a/history-api/vendor/golang.org/x/telemetry/counter/doc.go b/history-api/vendor/golang.org/x/telemetry/counter/doc.go new file mode 100644 index 00000000..639e9ea3 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/counter/doc.go @@ -0,0 +1,58 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package counter implements a simple counter system for collecting +// totally public telemetry data. +// +// There are two kinds of counters, basic counters and stack counters. +// Basic counters are created by [New]. +// Stack counters are created by [NewStack]. +// Both are incremented by calling Inc(). +// +// Basic counters are very cheap. Stack counters are more expensive, as they +// require parsing the stack. (Stack counters are implemented as basic counters +// whose names are the concatenation of the name and the stack trace. There is +// an upper limit on the size of this name, about 4K bytes. If the name is too +// long the stack will be truncated and "truncated" appended.) +// +// When counter files expire they are turned into reports by the upload +// package. The first time any counter file is created for a user, a random day +// of the week is selected on which counter files will expire. For the first +// week, that day is more than 7 days (but not more than two weeks) in the +// future. After that the counter files expire weekly on the same day of the +// week. +// +// # Counter Naming +// +// Counter names passed to [New] and [NewStack] should follow these +// conventions: +// +// - Names cannot contain whitespace or newlines. +// +// - Names must be valid unicode, with no unprintable characters. +// +// - Names may contain at most one ':'. In the counter "foo:bar", we refer to +// "foo" as the "chart name" and "bar" as the "bucket name". +// +// - The '/' character should partition counter names into a hierarchy. The +// root of this hierarchy should identify the logical entity that "owns" +// the counter. This could be an application, such as "gopls" in the case +// of "gopls/client:vscode", or a shared library, such as "crash" in the +// case of the "crash/crash" counter owned by the crashmonitor library. If +// the entity name itself contains a '/', that's ok: "cmd/go/flag" is fine. +// +// - Words should be '-' separated, as in "gopls/completion/errors-latency" +// +// - Histograms should use bucket names identifying upper bounds with '<'. +// For example given two counters "gopls/completion/latency:<50ms" and +// "gopls/completion/latency:<100ms", the "<100ms" bucket counts events +// with latency in the half-open interval [50ms, 100ms). +// +// # Debugging +// +// The GODEBUG environment variable can enable printing of additional debug +// information for counters. Adding GODEBUG=countertrace=1 to the environment +// of a process using counters causes the x/telemetry/counter package to log +// counter information to stderr. +package counter diff --git a/history-api/vendor/golang.org/x/telemetry/dir.go b/history-api/vendor/golang.org/x/telemetry/dir.go new file mode 100644 index 00000000..5931669e --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/dir.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Dir returns the telemetry directory. +func Dir() string { + return telemetry.Default.Dir() +} diff --git a/history-api/vendor/golang.org/x/telemetry/doc.go b/history-api/vendor/golang.org/x/telemetry/doc.go new file mode 100644 index 00000000..073f40d2 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/doc.go @@ -0,0 +1 @@ +package telemetry diff --git a/history-api/vendor/golang.org/x/telemetry/internal/config/config.go b/history-api/vendor/golang.org/x/telemetry/internal/config/config.go new file mode 100644 index 00000000..533a889c --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/config/config.go @@ -0,0 +1,140 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package config provides methods for loading and querying a +// telemetry upload config file. +package config + +import ( + "encoding/json" + "os" + "strings" + + "golang.org/x/telemetry/internal/telemetry" +) + +// Config is a wrapper around telemetry.UploadConfig that provides some +// convenience methods for checking the contents of a report. +type Config struct { + *telemetry.UploadConfig + program map[string]bool + goos map[string]bool + goarch map[string]bool + goversion map[string]bool + pgversion map[pgkey]bool + pgcounter map[pgkey]bool + pgcounterprefix map[pgkey]bool + pgstack map[pgkey]bool + rate map[pgkey]float64 +} + +type pgkey struct { + program, key string +} + +func ReadConfig(file string) (*Config, error) { + data, err := os.ReadFile(file) + if err != nil { + return nil, err + } + var cfg telemetry.UploadConfig + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + return NewConfig(&cfg), nil +} + +func NewConfig(cfg *telemetry.UploadConfig) *Config { + ucfg := Config{UploadConfig: cfg} + ucfg.goos = set(ucfg.GOOS) + ucfg.goarch = set(ucfg.GOARCH) + ucfg.goversion = set(ucfg.GoVersion) + ucfg.program = make(map[string]bool, len(ucfg.Programs)) + ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.rate = make(map[pgkey]float64) + for _, p := range ucfg.Programs { + ucfg.program[p.Name] = true + for _, v := range p.Versions { + ucfg.pgversion[pgkey{p.Name, v}] = true + } + for _, c := range p.Counters { + for _, e := range Expand(c.Name) { + ucfg.pgcounter[pgkey{p.Name, e}] = true + ucfg.rate[pgkey{p.Name, e}] = c.Rate + } + prefix, _, found := strings.Cut(c.Name, ":") + if found { + ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true + } + } + for _, s := range p.Stacks { + ucfg.pgstack[pgkey{p.Name, s.Name}] = true + ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate + } + } + return &ucfg +} + +func (r *Config) HasProgram(s string) bool { + return r.program[s] +} + +func (r *Config) HasGOOS(s string) bool { + return r.goos[s] +} + +func (r *Config) HasGOARCH(s string) bool { + return r.goarch[s] +} + +func (r *Config) HasGoVersion(s string) bool { + return r.goversion[s] +} + +func (r *Config) HasVersion(program, version string) bool { + return r.pgversion[pgkey{program, version}] +} + +func (r *Config) HasCounter(program, counter string) bool { + return r.pgcounter[pgkey{program, counter}] +} + +func (r *Config) HasCounterPrefix(program, prefix string) bool { + return r.pgcounterprefix[pgkey{program, prefix}] +} + +func (r *Config) HasStack(program, stack string) bool { + return r.pgstack[pgkey{program, stack}] +} + +func (r *Config) Rate(program, name string) float64 { + return r.rate[pgkey{program, name}] +} + +func set(slice []string) map[string]bool { + s := make(map[string]bool, len(slice)) + for _, v := range slice { + s[v] = true + } + return s +} + +// Expand takes a counter defined with buckets and expands it into distinct +// strings for each bucket. +func Expand(counter string) []string { + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { + buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",") + for _, b := range buckets { + counters = append(counters, prefix+b) + } + } else { + counters = append(counters, prefix) + } + return counters +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/configstore/download.go b/history-api/vendor/golang.org/x/telemetry/internal/configstore/download.go new file mode 100644 index 00000000..e60ab7e9 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/configstore/download.go @@ -0,0 +1,86 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package configstore abstracts interaction with the telemetry config server. +// Telemetry config (golang.org/x/telemetry/config) is distributed as a go +// module containing go.mod and config.json. Programs that upload collected +// counters download the latest config using `go mod download`. This provides +// verification of downloaded configuration and cacheability. +package configstore + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync/atomic" + + "golang.org/x/telemetry/internal/telemetry" +) + +const ( + ModulePath = "golang.org/x/telemetry/config" + configFileName = "config.json" +) + +// needNoConsole is used on windows to set the windows.CREATE_NO_WINDOW +// creation flag. +var needNoConsole = func(cmd *exec.Cmd) {} + +var downloads int64 + +// Downloads reports, for testing purposes, the number of times [Download] has +// been called. +func Downloads() int64 { + return atomic.LoadInt64(&downloads) +} + +// Download fetches the requested telemetry UploadConfig using "go mod +// download". If envOverlay is provided, it is appended to the environment used +// for invoking the go command. +// +// The second result is the canonical version of the requested configuration. +func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) { + atomic.AddInt64(&downloads, 1) + + if version == "" { + version = "latest" + } + modVer := ModulePath + "@" + version + var stdout, stderr bytes.Buffer + cmd := exec.Command("go", "mod", "download", "-json", modVer) + needNoConsole(cmd) + cmd.Env = append(os.Environ(), envOverlay...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + var info struct { + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err == nil && info.Error != "" { + return nil, "", fmt.Errorf("failed to download config module: %v", info.Error) + } + return nil, "", fmt.Errorf("failed to download config module: %w\n%s", err, &stderr) + } + + var info struct { + Dir string + Version string + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err != nil || info.Dir == "" { + return nil, "", fmt.Errorf("failed to download config module (invalid JSON): %w", err) + } + data, err := os.ReadFile(filepath.Join(info.Dir, configFileName)) + if err != nil { + return nil, "", fmt.Errorf("invalid config module: %w", err) + } + cfg := new(telemetry.UploadConfig) + if err := json.Unmarshal(data, cfg); err != nil { + return nil, "", fmt.Errorf("invalid config: %w", err) + } + return cfg, info.Version, nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go b/history-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go new file mode 100644 index 00000000..1368de19 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package configstore + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + needNoConsole = needNoConsoleWindows +} + +func needNoConsoleWindows(cmd *exec.Cmd) { + // The uploader main process is likely a daemonized process with no console. + // (see x/telemetry/start_windows.go) The console creation behavior when + // a parent is a console process without console is not clearly documented + // but empirically we observed the new console is created and attached to the + // subprocess in the default setup. + // + // Ensure no new console is attached to the subprocess by setting CREATE_NO_WINDOW. + // https://learn.microsoft.com/en-us/windows/console/creation-of-a-console + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.CREATE_NO_WINDOW, + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/counter/counter.go b/history-api/vendor/golang.org/x/telemetry/internal/counter/counter.go new file mode 100644 index 00000000..c08115e5 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/counter/counter.go @@ -0,0 +1,401 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal/counter implements the internals of the public counter package. +// In addition to the public API, this package also includes APIs to parse and +// manage the counter files, needed by the upload package. +package counter + +import ( + "fmt" + "os" + "runtime" + "strings" + "sync/atomic" +) + +var ( + // Note: not using internal/godebug, so that internal/godebug can use + // internal/counter. + debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") + CrashOnBugs = false // for testing; if set, exit on fatal log messages +) + +// debugPrintf formats a debug message if GODEBUG=countertrace=1. +func debugPrintf(format string, args ...any) { + if debugCounter { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter: "+format, args...) + } +} + +// debugFatalf logs a fatal error if GODEBUG=countertrace=1. +func debugFatalf(format string, args ...any) { + if debugCounter || CrashOnBugs { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter bug: "+format, args...) + os.Exit(1) + } +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter struct { + name string + file *file + + next atomic.Pointer[Counter] + state counterState + ptr counterPtr +} + +func (c *Counter) Name() string { + return c.name +} + +type counterPtr struct { + m *mappedFile + count *atomic.Uint64 +} + +type counterState struct { + bits atomic.Uint64 +} + +func (s *counterState) load() counterStateBits { + return counterStateBits(s.bits.Load()) +} + +func (s *counterState) update(old *counterStateBits, new counterStateBits) bool { + if s.bits.CompareAndSwap(uint64(*old), uint64(new)) { + *old = new + return true + } + return false +} + +type counterStateBits uint64 + +const ( + stateReaders counterStateBits = 1<<30 - 1 + stateLocked counterStateBits = stateReaders + stateHavePtr counterStateBits = 1 << 30 + stateExtraShift = 31 + stateExtra counterStateBits = 1<<64 - 1<> stateExtraShift } + +func (b counterStateBits) incReader() counterStateBits { return b + 1 } +func (b counterStateBits) decReader() counterStateBits { return b - 1 } +func (b counterStateBits) setLocked() counterStateBits { return b | stateLocked } +func (b counterStateBits) clearLocked() counterStateBits { return b &^ stateLocked } +func (b counterStateBits) setHavePtr() counterStateBits { return b | stateHavePtr } +func (b counterStateBits) clearHavePtr() counterStateBits { return b &^ stateHavePtr } +func (b counterStateBits) clearExtra() counterStateBits { return b &^ stateExtra } +func (b counterStateBits) addExtra(n uint64) counterStateBits { + const maxExtra = uint64(stateExtra) >> stateExtraShift // 0x1ffffffff + x := b.extra() + if x+n < x || x+n > maxExtra { + x = maxExtra + } else { + x += n + } + return b.clearExtra() | counterStateBits(x)< count=%d\n", c.name, extra, sum) + } + + // Took care of refreshing ptr and flushing extra. + // Now we can release the lock, unless of course + // another goroutine cleared havePtr or added to extra, + // in which case we go around again. + if !c.state.update(&state, state.clearLocked()) { + continue + } + debugPrintf("releaseLock %s: unlocked\n", c.name) + return + } +} + +// add wraps the atomic.Uint64.Add operation to handle integer overflow. +func (c *Counter) add(n uint64) uint64 { + count := c.ptr.count + for { + old := count.Load() + sum := old + n + if sum < old { + sum = ^uint64(0) + } + if count.CompareAndSwap(old, sum) { + runtime.KeepAlive(c.ptr.m) + return sum + } + } +} + +func (c *Counter) invalidate() { + for { + state := c.state.load() + if !state.havePtr() { + debugPrintf("invalidate %s: no ptr\n", c.name) + return + } + if c.state.update(&state, state.clearHavePtr()) { + debugPrintf("invalidate %s: cleared havePtr\n", c.name) + return + } + } +} + +func (c *Counter) refresh() { + for { + state := c.state.load() + if state.havePtr() || state.readers() > 0 || state.extra() == 0 { + debugPrintf("refresh %s: havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + return + } + if c.state.update(&state, state.setLocked()) { + debugPrintf("refresh %s: locked havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + c.releaseLock(state) + return + } + } +} + +// Read reads the given counter. +// This is the implementation of x/telemetry/counter/countertest.ReadCounter. +func Read(c *Counter) (uint64, error) { + if c.file.current.Load() == nil { + return c.state.load().extra(), nil + } + pf, err := readFile(c.file) + if err != nil { + return 0, err + } + v, ok := pf.Count[DecodeStack(c.Name())] + if !ok { + return v, fmt.Errorf("not found:%q", DecodeStack(c.Name())) + } + return v, nil +} + +func readFile(f *file) (*File, error) { + if f == nil { + debugPrintf("No file") + return nil, fmt.Errorf("counter is not initialized - was Open called?") + } + + // Note: don't call f.rotate here as this will enqueue a follow-up rotation. + f.rotate1() + + if f.err != nil { + return nil, fmt.Errorf("failed to rotate mapped file - %v", f.err) + } + current := f.current.Load() + if current == nil { + return nil, fmt.Errorf("counter has no mapped file") + } + name := current.f.Name() + data, err := ReadMapped(name) + if err != nil { + return nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, fmt.Errorf("failed to parse: %v", err) + } + return pf, nil +} + +// ReadFile reads the counters and stack counters from the given file. +// This is the implementation of x/telemetry/counter/countertest.ReadFile. +func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) { + // TODO: Document the format of the stackCounters names. + + data, err := ReadMapped(name) + if err != nil { + return nil, nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse: %v", err) + } + counters = make(map[string]uint64) + stackCounters = make(map[string]uint64) + for k, v := range pf.Count { + if IsStackCounter(k) { + stackCounters[DecodeStack(k)] = v + } else { + counters[k] = v + } + } + return counters, stackCounters, nil +} + +// ReadMapped reads the contents of the given file by memory mapping. +// +// This avoids file synchronization issues. +func ReadMapped(name string) ([]byte, error) { + f, err := os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + mapping, err := memmap(f) + if err != nil { + return nil, err + } + data := make([]byte, fi.Size()) + copy(data, mapping.Data) + munmap(mapping) + return data, nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/counter/file.go b/history-api/vendor/golang.org/x/telemetry/internal/counter/file.go new file mode 100644 index 00000000..872a6f6a --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -0,0 +1,814 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "errors" + "fmt" + "math/rand" + "os" + "path" + "path/filepath" + "runtime" + "runtime/debug" + "sync" + "sync/atomic" + "time" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" + "golang.org/x/telemetry/internal/telemetry" +) + +// A file is a counter file. +type file struct { + // Linked list of all known counters. + // (Linked list insertion is easy to make lock-free, + // and we don't want the initial counters incremented + // by a program to cause significant contention.) + counters atomic.Pointer[Counter] // head of list + end Counter // list ends at &end instead of nil + + mu sync.Mutex + buildInfo *debug.BuildInfo + timeBegin, timeEnd time.Time + err error + // current holds the current file mapping, which may change when the file is + // rotated or extended. + // + // current may be read without holding mu, but may be nil. + // + // The cleanup logic for file mappings is complicated, because invalidating + // counter pointers is reentrant: [file.invalidateCounters] may call + // [file.lookup], which acquires mu. Therefore, writing current must be done + // as follows: + // 1. record the previous value of current + // 2. Store a new value in current + // 3. unlock mu + // 4. call invalidateCounters + // 5. close the previous mapped value from (1) + // TODO(rfindley): simplify + current atomic.Pointer[mappedFile] +} + +var defaultFile file + +// register ensures that the counter c is registered with the file. +func (f *file) register(c *Counter) { + debugPrintf("register %s %p\n", c.Name(), c) + + // If counter is not registered with file, register it. + // Doing this lazily avoids init-time work + // as well as any execution cost at all for counters + // that are not used in a given program. + wroteNext := false + for wroteNext || c.next.Load() == nil { + head := f.counters.Load() + next := head + if next == nil { + next = &f.end + } + debugPrintf("register %s next %p\n", c.Name(), next) + if !wroteNext { + if !c.next.CompareAndSwap(nil, next) { + debugPrintf("register %s cas failed %p\n", c.Name(), c.next.Load()) + continue + } + wroteNext = true + } else { + c.next.Store(next) + } + if f.counters.CompareAndSwap(head, c) { + debugPrintf("registered %s %p\n", c.Name(), f.counters.Load()) + return + } + debugPrintf("register %s cas2 failed %p %p\n", c.Name(), f.counters.Load(), head) + } +} + +// invalidateCounters marks as invalid all the pointers +// held by f's counters and then refreshes them. +// +// invalidateCounters cannot be called while holding f.mu, +// because a counter refresh may call f.lookup. +func (f *file) invalidateCounters() { + // Mark every counter as needing to refresh its count pointer. + if head := f.counters.Load(); head != nil { + for c := head; c != &f.end; c = c.next.Load() { + c.invalidate() + } + for c := head; c != &f.end; c = c.next.Load() { + c.refresh() + } + } +} + +// lookup looks up the counter with the given name in the file, +// allocating it if needed, and returns a pointer to the atomic.Uint64 +// containing the counter data. +// If the file has not been opened yet, lookup returns nil. +func (f *file) lookup(name string) counterPtr { + current := f.current.Load() + if current == nil { + debugPrintf("lookup %s - no mapped file\n", name) + return counterPtr{} + } + ptr := f.newCounter(name) + if ptr == nil { + return counterPtr{} + } + return counterPtr{current, ptr} +} + +// ErrDisabled is the error returned when telemetry is disabled. +var ErrDisabled = errors.New("counter: disabled as Go telemetry is off") + +var ( + errNoBuildInfo = errors.New("counter: missing build info") + errCorrupt = errors.New("counter: corrupt counter file") +) + +// weekEnd returns the day of the week on which uploads occur (and therefore +// counters expire). +// +// Reads the weekends file, creating one if none exists. +func weekEnd() (time.Weekday, error) { + // If there is no 'weekends' file create it and initialize it + // to a random day of the week. There is a short interval for + // a race. + weekends := filepath.Join(telemetry.Default.LocalDir(), "weekends") + day := fmt.Sprintf("%d\n", rand.Intn(7)) + if _, err := os.ReadFile(weekends); err != nil { + if err := os.MkdirAll(telemetry.Default.LocalDir(), 0777); err != nil { + debugPrintf("%v: could not create telemetry.LocalDir %s", err, telemetry.Default.LocalDir()) + return 0, err + } + if err = os.WriteFile(weekends, []byte(day), 0666); err != nil { + return 0, err + } + } + + // race is over, read the file + buf, err := os.ReadFile(weekends) + // There is no reasonable way of recovering from errors + // so we just fail + if err != nil { + return 0, err + } + buf = bytes.TrimSpace(buf) + if len(buf) == 0 { + return 0, fmt.Errorf("empty weekends file") + } + weekend := time.Weekday(buf[0] - '0') // 0 is Sunday + // paranoia to make sure the value is legal + weekend %= 7 + if weekend < 0 { + weekend += 7 + } + return weekend, nil +} + +// rotate checks to see whether the file f needs to be rotated, +// meaning to start a new counter file with a different date in the name. +// rotate is also used to open the file initially, meaning f.current can be nil. +// In general rotate should be called just once for each file. +// rotate will arrange a timer to call itself again when necessary. +func (f *file) rotate() { + expiry := f.rotate1() + if !expiry.IsZero() { + delay := time.Until(expiry) + // Some tests set CounterTime to a time in the past, causing delay to be + // negative. Avoid infinite loops by delaying at least a short interval. + // + // TODO(rfindley): instead, just also mock AfterFunc. + const minDelay = 1 * time.Minute + if delay < minDelay { + delay = minDelay + } + // TODO(rsc): Does this do the right thing for laptops closing? + time.AfterFunc(delay, f.rotate) + } +} + +func nop() {} + +// CounterTime returns the current UTC time. +// Mutable for testing. +var CounterTime = func() time.Time { + return time.Now().UTC() +} + +// counterSpan returns the current time span for a counter file, as determined +// by [CounterTime] and the [weekEnd]. +func counterSpan() (begin, end time.Time, _ error) { + year, month, day := CounterTime().Date() + begin = time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + // files always begin today, but expire on the next day of the week + // from the 'weekends' file. + weekend, err := weekEnd() + if err != nil { + return time.Time{}, time.Time{}, err + } + incr := int(weekend - begin.Weekday()) + if incr <= 0 { + incr += 7 // ensure that end is later than begin + } + end = time.Date(year, month, day+incr, 0, 0, 0, 0, time.UTC) + return begin, end, nil +} + +// rotate1 rotates the current counter file, returning its expiry, or the zero +// time if rotation failed. +func (f *file) rotate1() time.Time { + // Cleanup must be performed while unlocked, since invalidateCounters may + // involve calls to f.lookup. + var previous *mappedFile // read below while holding the f.mu. + defer func() { + // Counters must be invalidated whenever the mapped file changes. + if next := f.current.Load(); next != previous { + f.invalidateCounters() + // Ensure that the previous counter mapped file is closed. + if previous != nil { + previous.close() // safe to call multiple times + } + } + }() + + f.mu.Lock() + defer f.mu.Unlock() + + previous = f.current.Load() + + if f.err != nil { + return time.Time{} // already in failed state; nothing to do + } + + fail := func(err error) { + debugPrintf("rotate: %v", err) + f.err = err + f.current.Store(nil) + } + + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // TODO(rfindley): do we ever want to make ErrDisabled recoverable? + // Specifically, if f.err is ErrDisabled, should we check again during when + // rotating? + fail(ErrDisabled) + return time.Time{} + } + + if f.buildInfo == nil { + bi, ok := debug.ReadBuildInfo() + if !ok { + fail(errNoBuildInfo) + return time.Time{} + } + f.buildInfo = bi + } + + begin, end, err := counterSpan() + if err != nil { + fail(err) + return time.Time{} + } + if f.timeBegin.Equal(begin) && f.timeEnd.Equal(end) { + return f.timeEnd // nothing to do + } + f.timeBegin, f.timeEnd = begin, end + + goVers, progPath, progVers := telemetry.ProgramInfo(f.buildInfo) + meta := fmt.Sprintf("TimeBegin: %s\nTimeEnd: %s\nProgram: %s\nVersion: %s\nGoVersion: %s\nGOOS: %s\nGOARCH: %s\n\n", + f.timeBegin.Format(time.RFC3339), f.timeEnd.Format(time.RFC3339), + progPath, progVers, goVers, runtime.GOOS, runtime.GOARCH) + if len(meta) > maxMetaLen { // should be impossible for our use + fail(fmt.Errorf("metadata too long")) + return time.Time{} + } + + if progVers != "" { + progVers = "@" + progVers + } + baseName := fmt.Sprintf("%s%s-%s-%s-%s-%s.%s.count", + path.Base(progPath), + progVers, + goVers, + runtime.GOOS, + runtime.GOARCH, + f.timeBegin.Format(telemetry.DateOnly), + FileVersion, + ) + dir := telemetry.Default.LocalDir() + if err := os.MkdirAll(dir, 0777); err != nil { + fail(fmt.Errorf("making local dir: %v", err)) + return time.Time{} + } + name := filepath.Join(dir, baseName) + + m, err := openMapped(name, meta) + if err != nil { + // Mapping failed: + // If there used to be a mapped file, after cleanup + // incrementing counters will only change their internal state. + // (before cleanup the existing mapped file would be updated) + fail(fmt.Errorf("openMapped: %v", err)) + return time.Time{} + } + + debugPrintf("using %v", m.f.Name()) + f.current.Store(m) + return f.timeEnd +} + +func (f *file) newCounter(name string) *atomic.Uint64 { + v, cleanup := f.newCounter1(name) + cleanup() + return v +} + +func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { + f.mu.Lock() + defer f.mu.Unlock() + + current := f.current.Load() + if current == nil { + return nil, nop + } + debugPrintf("newCounter %s in %s\n", name, current.f.Name()) + if v, _, _, _ := current.lookup(name); v != nil { + return v, nop + } + v, newM, err := current.newCounter(name) + if err != nil { + debugPrintf("newCounter %s: %v\n", name, err) + return nil, nop + } + + cleanup = nop + if newM != nil { + f.current.Store(newM) + cleanup = func() { + f.invalidateCounters() + current.close() + } + } + return v, cleanup +} + +var ( + openOnce sync.Once + // rotating reports whether the call to Open had rotate = true. + // + // In golang/go#68497, we observed that file rotation can break runtime + // deadlock detection. To minimize the fix for 1.23, we are splitting the + // Open API into one version that rotates the counter file, and another that + // does not. The rotating variable guards against use of both APIs from the + // same process. + rotating bool +) + +// Open associates counting with the defaultFile. +// The returned function is for testing only, and should +// be called after all Inc()s are finished, but before +// any reports are generated. +// (Otherwise expired count files will not be deleted on Windows.) +func Open(rotate bool) func() { + if telemetry.DisabledOnPlatform { + return func() {} + } + close := func() {} + openOnce.Do(func() { + rotating = rotate + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. + return + } + debugPrintf("Open(%v)", rotate) + if rotate { + defaultFile.rotate() // calls rotate1 and schedules a rotation + } else { + defaultFile.rotate1() + } + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + if rotating != rotate { + panic("BUG: Open called with inconsistent values for 'rotate'") + } + return close +} + +const ( + FileVersion = "v1" + hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" + recordUnit = 32 + maxMetaLen = 512 + numHash = 512 // 2kB for hash table + maxNameLen = 4 * 1024 + limitOff = 0 + hashOff = 4 + pageSize = 16 * 1024 + minFileLen = 16 * 1024 +) + +// A mappedFile is a counter file mmapped into memory. +// +// The file layout for a mappedFile m is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, hdrLen: header, containing metadata; see [mappedHeader] +// hdrLen+limitOff, 4: uint32 allocation limit (byte offset of the end of counter records) +// hdrLen+hashOff, 4*numHash: hash table, stores uint32 heads of a linked list of records, keyed by name hash +// hdrLen+hashOff+4*numHash to limit: counter records: see record syntax below +// +// The record layout is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, 8: uint64 counter value +// 8, 12: uint32 name length +// 12, 16: uint32 offset of next record in linked list +// 16, name length: counter name +type mappedFile struct { + meta string + hdrLen uint32 + zero [4]byte + closeOnce sync.Once + f *os.File + mapping *mmap.Data +} + +// openMapped opens and memory maps a file. +// +// name is the path to the file. +// +// meta is the file metadata, which must match the metadata of the file on disk +// exactly. +// +// existing should be nil the first time this is called for a file, +// and when remapping, should be the previous mappedFile. +func openMapped(name, meta string) (_ *mappedFile, err error) { + hdr, err := mappedHeader(meta) + if err != nil { + return nil, err + } + + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + // Note: using local variable m here, not return value, + // so that return nil, err does not set m = nil and break the code in the defer. + m := &mappedFile{ + f: f, + meta: meta, + } + + defer func() { + if err != nil { + m.close() + } + }() + + info, err := f.Stat() + if err != nil { + return nil, err + } + + // Establish file header and initial data area if not already present. + if info.Size() < minFileLen { + if _, err := f.WriteAt(hdr, 0); err != nil { + return nil, err + } + // Write zeros at the end of the file to extend it to minFileLen. + if _, err := f.WriteAt(m.zero[:], int64(minFileLen-len(m.zero))); err != nil { + return nil, err + } + info, err = f.Stat() + if err != nil { + return nil, err + } + if info.Size() < minFileLen { + return nil, fmt.Errorf("counter: writing file did not extend it") + } + } + + // Map into memory. + mapping, err := memmap(f) + if err != nil { + return nil, err + } + m.mapping = mapping + if !bytes.HasPrefix(m.mapping.Data, hdr) { + // TODO(rfindley): we can and should do better here, reading the mapped + // header length and comparing headers exactly. + return nil, fmt.Errorf("counter: header mismatch") + } + m.hdrLen = uint32(len(hdr)) + + return m, nil +} + +func mappedHeader(meta string) ([]byte, error) { + if len(meta) > maxMetaLen { + return nil, fmt.Errorf("counter: metadata too large") + } + np := round(len(hdrPrefix), 4) + n := round(np+4+len(meta), 32) + hdr := make([]byte, n) + copy(hdr, hdrPrefix) + *(*uint32)(unsafe.Pointer(&hdr[np])) = uint32(n) + copy(hdr[np+4:], meta) + return hdr, nil +} + +func (m *mappedFile) place(limit uint32, name string) (start, end uint32) { + if limit == 0 { + // first record in file + limit = m.hdrLen + hashOff + 4*numHash + } + n := round(uint32(16+len(name)), recordUnit) + start = round(limit, recordUnit) // should already be rounded but just in case + // Note: Checking for crossing a page boundary would be + // start/pageSize != (start+n-1)/pageSize, + // but we are checking for reaching the page end, so no -1. + // The page end is reserved for use by extend. + // See the comment in m.extend. + if start/pageSize != (start+n)/pageSize { + // bump start to next page + start = round(limit, pageSize) + } + return start, start + n +} + +var memmap = mmap.Mmap +var munmap = mmap.Munmap + +func (m *mappedFile) close() { + m.closeOnce.Do(func() { + if m.mapping != nil { + munmap(m.mapping) + m.mapping = nil + } + if m.f != nil { + m.f.Close() // best effort + m.f = nil + } + }) +} + +// hash returns the hash code for name. +// The implementation is FNV-1a. +// This hash function is a fixed detail of the file format. +// It cannot be changed without also changing the file format version. +func hash(name string) uint32 { + const ( + offset32 = 2166136261 + prime32 = 16777619 + ) + h := uint32(offset32) + for i := 0; i < len(name); i++ { + c := name[i] + h = (h ^ uint32(c)) * prime32 + } + return (h ^ (h >> 16)) % numHash +} + +func (m *mappedFile) load32(off uint32) uint32 { + if int64(off) >= int64(len(m.mapping.Data)) { + return 0 + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).Load() +} + +func (m *mappedFile) cas32(off, old, new uint32) bool { + if int64(off) >= int64(len(m.mapping.Data)) { + panic("bad cas32") // return false would probably loop + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).CompareAndSwap(old, new) +} + +// entryAt reads a counter record at the given byte offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Uint64, ok bool) { + if off < m.hdrLen+hashOff || int64(off)+16 > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + nameLen := m.load32(off+8) & 0x00ffffff + if nameLen == 0 || int64(off)+16+int64(nameLen) > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + name = m.mapping.Data[off+16 : off+16+nameLen] + next = m.load32(off + 12) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return name, next, v, true +} + +// writeEntryAt writes a new counter record at the given offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +// +// writeEntryAt only returns false in the presence of some form of corruption: +// an offset outside the bounds of the record region in the mapped file. +func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, v *atomic.Uint64, ok bool) { + // TODO(rfindley): shouldn't this first condition be off < m.hdrLen+hashOff+4*numHash? + if off < m.hdrLen+hashOff || int64(off)+16+int64(len(name)) > int64(len(m.mapping.Data)) { + return nil, nil, false + } + copy(m.mapping.Data[off+16:], name) + atomic.StoreUint32((*uint32)(unsafe.Pointer(&m.mapping.Data[off+8])), uint32(len(name))|0xff000000) + next = (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off+12])) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return next, v, true +} + +// lookup searches the mapped file for a counter record with the given name, returning: +// - v: the mapped counter value +// - headOff: the offset of the head pointer (see [mappedFile]) +// - head: the value of the head pointer +// - ok: whether lookup succeeded +func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32, ok bool) { + h := hash(name) + headOff = m.hdrLen + hashOff + h*4 + head = m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return nil, 0, 0, false + } + if string(ename) == name { + return v, headOff, head, true + } + off = next + } + return nil, headOff, head, true +} + +// newCounter allocates and writes a new counter record with the given name. +// +// If name is already recorded in the file, newCounter returns the existing counter. +func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, err error) { + if len(name) > maxNameLen { + return nil, nil, fmt.Errorf("counter name too long") + } + orig := m + defer func() { + if m != orig { + if err != nil { + m.close() + } else { + m1 = m + } + } + }() + + v, headOff, head, ok := m.lookup(name) + for tries := 0; !ok; tries++ { + if tries >= 10 { + debugFatalf("corrupt: failed to remap after 10 tries") + return nil, nil, errCorrupt + } + // Lookup found an invalid pointer, + // perhaps because the file has grown larger than the mapping. + limit := m.load32(m.hdrLen + limitOff) + if limit, datalen := int64(limit), int64(len(m.mapping.Data)); limit <= datalen { + // Mapping doesn't need to grow, so lookup found actual corruption, + // in the form of an entry pointer that exceeds the recorded allocation + // limit. This should never happen, unless the actual file contents are + // corrupt. + debugFatalf("corrupt: limit %d is within mapping length %d", limit, datalen) + return nil, nil, errCorrupt + } + // That the recorded limit is greater than the mapped data indicates that + // an external process has extended the file. Re-map to pick up this extension. + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, nil, err + } + if limit, datalen := int64(limit), int64(len(newM.mapping.Data)); limit > datalen { + // We've re-mapped, yet limit still exceeds the data length. This + // indicates that the underlying file was somehow truncated, or the + // recorded limit is corrupt. + debugFatalf("corrupt: limit %d exceeds file size %d", limit, datalen) + return nil, nil, errCorrupt + } + // If m != orig, this is at least the second time around the loop + // trying to open the mapping. Close the previous attempt. + if m != orig { + m.close() + } + m = newM + v, headOff, head, ok = m.lookup(name) + } + if v != nil { + return v, nil, nil + } + + // Reserve space for new record. + // We are competing against other programs using the same file, + // so we use a compare-and-swap on the allocation limit in the header. + var start, end uint32 + for { + // Determine where record should end, and grow file if needed. + limit := m.load32(m.hdrLen + limitOff) + start, end = m.place(limit, name) + debugPrintf("place %s at %#x-%#x\n", name, start, end) + if int64(end) > int64(len(m.mapping.Data)) { + newM, err := m.extend(end) + if err != nil { + return nil, nil, err + } + if m != orig { + m.close() + } + m = newM + continue + } + + // Attempt to reserve that space for our record. + if m.cas32(m.hdrLen+limitOff, limit, end) { + break + } + } + + // Write record. + next, v, ok := m.writeEntryAt(start, name) + if !ok { + debugFatalf("corrupt: failed to write entry: %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) + return nil, nil, errCorrupt // more likely our math is wrong + } + + // Link record into hash chain, making sure not to introduce a duplicate. + // We know name does not appear in the chain starting at head. + for { + next.Store(head) + if m.cas32(headOff, head, start) { + return v, nil, nil + } + + // Check new elements in chain for duplicates. + old := head + head = m.load32(headOff) + for off := head; off != old; { + ename, enext, v, ok := m.entryAt(off) + if !ok { + return nil, nil, errCorrupt + } + if string(ename) == name { + next.Store(^uint32(0)) // mark ours as dead + return v, nil, nil + } + off = enext + } + } +} + +func (m *mappedFile) extend(end uint32) (*mappedFile, error) { + end = round(end, pageSize) + info, err := m.f.Stat() + if err != nil { + return nil, err + } + if info.Size() < int64(end) { + // Note: multiple processes could be calling extend at the same time, + // but this write only writes the last 4 bytes of the page. + // The last 4 bytes of the page are reserved for this purpose and hold no data. + // (In m.place, if a new record would extend to the very end of the page, + // it is placed in the next page instead.) + // So it is fine if multiple processes extend at the same time. + if _, err := m.f.WriteAt(m.zero[:], int64(end)-int64(len(m.zero))); err != nil { + return nil, err + } + } + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, err + } + if int64(len(newM.mapping.Data)) < int64(end) { + // File system or logic bug: new file is somehow not extended. + // See go.dev/issue/68311, where this appears to have been happening. + newM.close() + return nil, errCorrupt + } + return newM, err +} + +// round returns x rounded up to the next multiple of unit, +// which must be a power of two. +func round[T int | uint32](x T, unit T) T { + return (x + unit - 1) &^ (unit - 1) +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/counter/parse.go b/history-api/vendor/golang.org/x/telemetry/internal/counter/parse.go new file mode 100644 index 00000000..a42a3513 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/counter/parse.go @@ -0,0 +1,82 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "fmt" + "strings" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" +) + +type File struct { + Meta map[string]string + Count map[string]uint64 +} + +func Parse(filename string, data []byte) (*File, error) { + if !bytes.HasPrefix(data, []byte(hdrPrefix)) || len(data) < pageSize { + if len(data) < pageSize { + return nil, fmt.Errorf("%s: file too short (%d<%d)", filename, len(data), pageSize) + } + return nil, fmt.Errorf("%s: wrong hdr (not %q)", filename, hdrPrefix) + } + corrupt := func() (*File, error) { + // TODO(rfindley): return a useful error message. + return nil, fmt.Errorf("%s: corrupt counter file", filename) + } + + f := &File{ + Meta: make(map[string]string), + Count: make(map[string]uint64), + } + np := round(len(hdrPrefix), 4) + hdrLen := *(*uint32)(unsafe.Pointer(&data[np])) + if hdrLen > pageSize { + return corrupt() + } + meta := data[np+4 : hdrLen] + if i := bytes.IndexByte(meta, 0); i >= 0 { + meta = meta[:i] + } + m := &mappedFile{ + meta: string(meta), + hdrLen: hdrLen, + mapping: &mmap.Data{Data: data}, + } + + lines := strings.Split(m.meta, "\n") + for _, line := range lines { + if line == "" { + continue + } + k, v, ok := strings.Cut(line, ": ") + if !ok { + return corrupt() + } + f.Meta[k] = v + } + + for i := uint32(0); i < numHash; i++ { + headOff := hdrLen + hashOff + i*4 + head := m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return corrupt() + } + if _, ok := f.Count[string(ename)]; ok { + return corrupt() + } + ctrName := DecodeStack(string(ename)) + f.Count[ctrName] = v.Load() + off = next + } + } + return f, nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go b/history-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go new file mode 100644 index 00000000..3e7ffdeb --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go @@ -0,0 +1,212 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "fmt" + "runtime" + "strings" + "sync" +) + +// On the disk, and upstream, stack counters look like sets of +// regular counters with names that include newlines. + +// a StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter struct { + name string + depth int + file *file + + mu sync.Mutex + // as this is a detail of the implementation, it could be replaced + // by a more efficient mechanism + stacks []stack +} + +type stack struct { + pcs []uintptr + counter *Counter +} + +func NewStack(name string, depth int) *StackCounter { + return &StackCounter{name: name, depth: depth, file: &defaultFile} +} + +// Inc increments a stack counter. It computes the caller's stack and +// looks up the corresponding counter. It then increments that counter, +// creating it if necessary. +func (c *StackCounter) Inc() { + pcs := make([]uintptr, c.depth) + n := runtime.Callers(2, pcs) // caller of Inc + pcs = pcs[:n] + + c.mu.Lock() + defer c.mu.Unlock() + + // Existing counter? + var ctr *Counter + for _, s := range c.stacks { + if eq(s.pcs, pcs) { + if s.counter != nil { + ctr = s.counter + break + } + } + } + + if ctr == nil { + // Create new counter. + ctr = &Counter{ + name: EncodeStack(pcs, c.name), + file: c.file, + } + c.stacks = append(c.stacks, stack{pcs: pcs, counter: ctr}) + } + + ctr.Inc() +} + +// EncodeStack returns the name of the counter to +// use for the given stack of program counters. +// The name encodes the stack. +func EncodeStack(pcs []uintptr, prefix string) string { + var locs []string + lastImport := "" + frs := runtime.CallersFrames(pcs) + for { + fr, more := frs.Next() + // TODO(adonovan): this CutLast(".") operation isn't + // appropriate for generic function symbols. + path, fname := cutLastDot(fr.Function) + if path == lastImport { + path = `"` // (a ditto mark) + } else { + lastImport = path + } + var loc string + if fr.Func != nil { + // Use function-relative line numbering. + // f:+2 means two lines into function f. + // f:-1 should never happen, but be conservative. + // + // An inlined call is replaced by a NOP instruction + // with the correct pclntab information. + _, entryLine := fr.Func.FileLine(fr.Entry) + loc = fmt.Sprintf("%s.%s:%+d,+0x%x", path, fname, fr.Line-entryLine, fr.PC-fr.Entry) + } else { + // The function is non-Go code or is fully inlined: + // use absolute line number within enclosing file. + // + // For inlined calls, the PC and Entry values + // both refer to the enclosing combined function. + // For example, both these PCs are relative to "caller": + // + // callee:=1,+0x12 ('=' means inlined) + // caller:+2,+0x34 + loc = fmt.Sprintf("%s.%s:=%d,+0x%x", path, fname, fr.Line, fr.PC-fr.Entry) + } + locs = append(locs, loc) + if !more { + break + } + } + + name := prefix + "\n" + strings.Join(locs, "\n") + if len(name) > maxNameLen { + const bad = "\ntruncated\n" + name = name[:maxNameLen-len(bad)] + bad + } + return name +} + +// DecodeStack expands the (compressed) stack encoded in the counter name. +func DecodeStack(ename string) string { + if !strings.Contains(ename, "\n") { + return ename // not a stack counter + } + lines := strings.Split(ename, "\n") + var lastPath string // empty or ends with . + for i, line := range lines { + path, rest := cutLastDot(line) + if len(path) == 0 { + continue // unchanged + } + if len(path) == 1 && path[0] == '"' { + lines[i] = lastPath + rest + } else { + lastPath = path + "." + // line unchanged + } + } + return strings.Join(lines, "\n") // trailing \n? +} + +// input is . +// output is (import path, function name) +func cutLastDot(x string) (before, after string) { + i := strings.LastIndex(x, ".") + if i < 0 { + return "", x + } + return x[:i], x[i+1:] +} + +// Names reports all the counter names associated with a StackCounter. +func (c *StackCounter) Names() []string { + c.mu.Lock() + defer c.mu.Unlock() + names := make([]string, len(c.stacks)) + for i, s := range c.stacks { + names[i] = s.counter.Name() + } + return names +} + +// Counters returns the known Counters for a StackCounter. +// There may be more in the count file. +func (c *StackCounter) Counters() []*Counter { + c.mu.Lock() + defer c.mu.Unlock() + counters := make([]*Counter, len(c.stacks)) + for i, s := range c.stacks { + counters[i] = s.counter + } + return counters +} + +func eq(a, b []uintptr) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// ReadStack reads the given stack counter. +// This is the implementation of +// golang.org/x/telemetry/counter/countertest.ReadStackCounter. +func ReadStack(c *StackCounter) (map[string]uint64, error) { + ret := map[string]uint64{} + for _, ctr := range c.Counters() { + v, err := Read(ctr) + if err != nil { + return nil, err + } + ret[DecodeStack(ctr.Name())] = v + } + return ret, nil +} + +// IsStackCounter reports whether the counter name is for a stack counter. +func IsStackCounter(name string) bool { + return strings.Contains(name, "\n") +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go b/history-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go new file mode 100644 index 00000000..53966ad2 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go @@ -0,0 +1,336 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crashmonitor + +// This file defines a monitor that reports arbitrary Go runtime +// crashes to telemetry. + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "reflect" + "runtime/debug" + "strconv" + "strings" + + "golang.org/x/telemetry/internal/counter" +) + +// Parent sets up the parent side of the crashmonitor. It requires +// exclusive use of a writable pipe connected to the child process's stdin. +func Parent(pipe *os.File) { + writeSentinel(pipe) + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + debug.SetCrashOutput(pipe, debug.CrashOptions{}) // ignore error +} + +// Child runs the part of the crashmonitor that runs in the child process. +// It expects its stdin to be connected via a pipe to the parent which has +// run Parent. +func Child() { + // Wait for parent process's dying gasp. + // If the parent dies for any reason this read will return. + data, err := io.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("failed to read from input pipe: %v", err) + } + + // If the only line is the sentinel, it wasn't a crash. + if bytes.Count(data, []byte("\n")) < 2 { + childExitHook() + os.Exit(0) // parent exited without crash report + } + + log.Printf("parent reported crash:\n%s", data) + + // Parse the stack out of the crash report + // and record a telemetry count for it. + name, err := telemetryCounterName(data) + if err != nil { + // Keep count of how often this happens + // so that we can investigate if necessary. + incrementCounter("crash/malformed") + + // Something went wrong. + // Save the crash securely in the file system. + f, err := os.CreateTemp(os.TempDir(), "*.crash") + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(data); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + log.Printf("failed to report crash to telemetry: %v", err) + log.Fatalf("crash report saved at %s", f.Name()) + } + + incrementCounter(name) + + childExitHook() + log.Fatalf("telemetry crash recorded") +} + +// (stubbed by test) +var ( + incrementCounter = func(name string) { counter.New(name).Inc() } + childExitHook = func() {} +) + +// The sentinel function returns its address. The difference between +// this value as observed by calls in two different processes of the +// same executable tells us the relative offset of their text segments. +// +// It would be nice if SetCrashOutput took care of this as it's fiddly +// and likely to confuse every user at first. +func sentinel() uint64 { + return uint64(reflect.ValueOf(sentinel).Pointer()) +} + +func writeSentinel(out io.Writer) { + fmt.Fprintf(out, "sentinel %x\n", sentinel()) +} + +// telemetryCounterName parses a crash report produced by the Go +// runtime, extracts the stack of the first runnable goroutine, +// converts each line into telemetry form ("symbol:relative-line"), +// and returns this as the name of a counter. +func telemetryCounterName(crash []byte) (string, error) { + pcs, err := parseStackPCs(string(crash)) + if err != nil { + return "", err + } + + // Limit the number of frames we request. + pcs = pcs[:min(len(pcs), 16)] + + if len(pcs) == 0 { + // This can occur if all goroutines are idle, as when + // caught in a deadlock, or killed by an async signal + // while blocked. + // + // TODO(adonovan): consider how to report such + // situations. Reporting a goroutine in [sleep] or + // [select] state could be quite confusing without + // further information about the nature of the crash, + // as the problem is not local to the code location. + // + // For now, we keep count of this situation so that we + // can access whether it needs a more involved solution. + return "crash/no-running-goroutine", nil + } + + // This string appears at the start of all + // crashmonitor-generated counter names. + // + // It is tempting to expose this as a parameter of Start, but + // it is not without risk. What value should most programs + // provide? There's no point giving the name of the executable + // as this is already recorded by telemetry. What if the + // application runs in multiple modes? Then it might be useful + // to record the mode. The problem is that an application with + // multiple modes probably doesn't know its mode by line 1 of + // main.main: it might require flag or argument parsing, or + // even validation of an environment variable, and we really + // want to steer users aware from any logic before Start. The + // flags and arguments will be wrong in the child process, and + // every extra conditional branch creates a risk that the + // recursively executed child program will behave not like the + // monitor but like the application. If the child process + // exits before calling Start, then the parent application + // will not have a monitor, and its crash reports will be + // discarded (written in to a pipe that is never read). + // + // So for now, we use this constant string. + const prefix = "crash/crash" + return counter.EncodeStack(pcs, prefix), nil +} + +// parseStackPCs parses the parent process's program counters for the +// first running goroutine out of a GOTRACEBACK=system traceback, +// adjusting them so that they are valid for the child process's text +// segment. +// +// This function returns only program counter values, ensuring that +// there is no possibility of strings from the crash report (which may +// contain PII) leaking into the telemetry system. +func parseStackPCs(crash string) ([]uintptr, error) { + // getSymbol parses the symbol name out of a line of the form: + // SYMBOL(ARGS) + // + // Note: SYMBOL may contain parens "pkg.(*T).method". However, type + // parameters are always replaced with ..., so they cannot introduce + // more parens. e.g., "pkg.(*T[...]).method". + // + // ARGS can contain parens. We want the first paren that is not + // immediately preceded by a ".". + // + // TODO(prattmic): This is mildly complicated and is only used to find + // runtime.sigpanic, so perhaps simplify this by checking explicitly + // for sigpanic. + getSymbol := func(line string) (string, error) { + var prev rune + for i, c := range line { + if line[i] != '(' { + prev = c + continue + } + if prev == '.' { + prev = c + continue + } + return line[:i], nil + } + return "", fmt.Errorf("no symbol for stack frame: %s", line) + } + + // getPC parses the PC out of a line of the form: + // \tFILE:LINE +0xRELPC sp=... fp=... pc=... + getPC := func(line string) (uint64, error) { + _, pcstr, ok := strings.Cut(line, " pc=") // e.g. pc=0x%x + if !ok { + return 0, fmt.Errorf("no pc= for stack frame: %s", line) + } + return strconv.ParseUint(pcstr, 0, 64) // 0 => allow 0x prefix + } + + var ( + pcs []uintptr + parentSentinel uint64 + childSentinel = sentinel() + on = false // are we in the first running goroutine? + lines = strings.Split(crash, "\n") + symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. + currSymbol string + prevSymbol string // symbol of the most recent previous frame with a PC. + ) + for i := 0; i < len(lines); i++ { + line := lines[i] + + // Read sentinel value. + if parentSentinel == 0 && strings.HasPrefix(line, "sentinel ") { + _, err := fmt.Sscanf(line, "sentinel %x", &parentSentinel) + if err != nil { + return nil, fmt.Errorf("can't read sentinel line") + } + continue + } + + // Search for "goroutine GID [STATUS]" + if !on { + if strings.HasPrefix(line, "goroutine ") && + strings.Contains(line, " [running]:") { + on = true + + if parentSentinel == 0 { + return nil, fmt.Errorf("no sentinel value in crash report") + } + } + continue + } + + // A blank line marks end of a goroutine stack. + if line == "" { + break + } + + // Skip the final "created by SYMBOL in goroutine GID" part. + if strings.HasPrefix(line, "created by ") { + break + } + + // Expect a pair of lines: + // SYMBOL(ARGS) + // \tFILE:LINE +0xRELPC sp=0x%x fp=0x%x pc=0x%x + // Note: SYMBOL may contain parens "pkg.(*T).method" + // The RELPC is sometimes missing. + + if symLine { + var err error + currSymbol, err = getSymbol(line) + if err != nil { + return nil, fmt.Errorf("error extracting symbol: %v", err) + } + + symLine = false // Next line is FILE:LINE. + } else { + // Parse the PC, and correct for the parent and child's + // different mappings of the text section. + pc, err := getPC(line) + if err != nil { + // Inlined frame, perhaps; skip it. + + // Done with this frame. Next line is a new frame. + // + // Don't update prevSymbol; we only want to + // track frames with a PC. + currSymbol = "" + symLine = true + continue + } + + pc = pc - parentSentinel + childSentinel + + // If the previous frame was sigpanic, then this frame + // was a trap (e.g., SIGSEGV). + // + // Typically all middle frames are calls, and report + // the "return PC". That is, the instruction following + // the CALL where the callee will eventually return to. + // + // runtime.CallersFrames is aware of this property and + // will decrement each PC by 1 to "back up" to the + // location of the CALL, which is the actual line + // number the user expects. + // + // This does not work for traps, as a trap is not a + // call, so the reported PC is not the return PC, but + // the actual PC of the trap. + // + // runtime.Callers is aware of this and will + // intentionally increment trap PCs in order to correct + // for the decrement performed by + // runtime.CallersFrames. See runtime.tracebackPCs and + // runtume.(*unwinder).symPC. + // + // We must emulate the same behavior, otherwise we will + // report the location of the instruction immediately + // prior to the trap, which may be on a different line, + // or even a different inlined functions. + // + // TODO(prattmic): The runtime applies the same trap + // behavior for other "injected calls", see injectCall + // in runtime.(*unwinder).next. Do we want to handle + // those as well? I don't believe we'd ever see + // runtime.asyncPreempt or runtime.debugCallV2 in a + // typical crash. + if prevSymbol == "runtime.sigpanic" { + pc++ + } + + pcs = append(pcs, uintptr(pc)) + + // Done with this frame. Next line is a new frame. + prevSymbol = currSymbol + currSymbol = "" + symLine = true + } + } + return pcs, nil +} + +func min(x, y int) int { + if x < y { + return x + } else { + return y + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go new file mode 100644 index 00000000..2febe3ec --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package is a lightly modified version of the mmap code +// in github.com/google/codesearch/index. + +// The mmap package provides an abstraction for memory mapping files +// on different platforms. +package mmap + +import ( + "os" +) + +// The backing file is never closed, so Data +// remains valid for the lifetime of the process. +type Data struct { + // TODO(pjw): might be better to define versions of Data + // for the 3 specializations + f *os.File + Data []byte + // Some windows magic + Windows interface{} +} + +// Mmap maps the given file into memory. +// When remapping a file, pass the most recently returned Data. +func Mmap(f *os.File) (*Data, error) { + return mmapFile(f) +} + +// Munmap unmaps the given file from memory. +func Munmap(d *Data) error { + return munmapFile(d) +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go new file mode 100644 index 00000000..610ab1a1 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go @@ -0,0 +1,25 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || wasip1 || plan9 + +package mmap + +import ( + "io" + "os" +) + +// mmapFile on other systems doesn't mmap the file. It just reads everything. +func mmapFile(f *os.File) (*Data, error) { + b, err := io.ReadAll(f) + if err != nil { + return nil, err + } + return &Data{f, b, nil}, nil +} + +func munmapFile(_ *Data) error { + return nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go new file mode 100644 index 00000000..72ad91d5 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go @@ -0,0 +1,47 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix + +package mmap + +import ( + "fmt" + "io/fs" + "os" + "syscall" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + pagesize := int64(os.Getpagesize()) + if int64(int(size+(pagesize-1))) != size+(pagesize-1) { + return nil, fmt.Errorf("%s: too large for mmap", f.Name()) + } + n := int(size) + if n == 0 { + return &Data{f, nil, nil}, nil + } + mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size + data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} + } + return &Data{f, data[:n], nil}, nil +} + +func munmapFile(d *Data) error { + if len(d.Data) == 0 { + return nil + } + err := syscall.Munmap(d.Data) + if err != nil { + return &fs.PathError{Op: "munmap", Path: d.f.Name(), Err: err} + } + return nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go new file mode 100644 index 00000000..2e8dfbea --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go @@ -0,0 +1,52 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mmap + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + if size == 0 { + return &Data{f, nil, nil}, nil + } + // set the min and max sizes to zero to map the whole file, as described in + // https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object#file-mapping-size + h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, syscall.PAGE_READWRITE, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) + } + // the mapping extends from zero to the end of the file mapping + // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile + addr, err := windows.MapViewOfFile(h, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, 0) + if err != nil { + return nil, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) + } + // Note: previously, we called windows.VirtualQuery here to get the exact + // size of the memory mapped region, but VirtualQuery reported sizes smaller + // than the actual file size (hypothesis: VirtualQuery only reports pages in + // a certain state, and newly written pages may not be counted). + return &Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil +} + +func munmapFile(d *Data) error { + err := windows.UnmapViewOfFile(uintptr(unsafe.Pointer(&d.Data[0]))) + x, ok := d.Windows.(windows.Handle) + if ok { + windows.CloseHandle(x) + } + d.f.Close() + return err +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go new file mode 100644 index 00000000..71953018 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// TODO(rfindley): replace uses of DateOnly with time.DateOnly once we no +// longer support building gopls with go 1.19. +const DateOnly = "2006-01-02" diff --git a/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go new file mode 100644 index 00000000..0673be56 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go @@ -0,0 +1,163 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package telemetry manages the telemetry mode file. +package telemetry + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +// Default is the default directory containing Go telemetry configuration and +// data. +// +// If Default is uninitialized, Default.Mode will be "off". As a consequence, +// no data should be written to the directory, and so the path values of +// LocalDir, UploadDir, etc. must not matter. +// +// Default is a global for convenience and testing, but should not be mutated +// outside of tests. +// +// TODO(rfindley): it would be nice to completely eliminate this global state, +// or at least push it in the golang.org/x/telemetry package +var Default Dir + +// A Dir holds paths to telemetry data inside a directory. +type Dir struct { + dir, local, upload, debug, modefile string +} + +// NewDir creates a new Dir encapsulating paths in the given dir. +// +// NewDir does not create any new directories or files--it merely encapsulates +// the telemetry directory layout. +func NewDir(dir string) Dir { + return Dir{ + dir: dir, + local: filepath.Join(dir, "local"), + upload: filepath.Join(dir, "upload"), + debug: filepath.Join(dir, "debug"), + modefile: filepath.Join(dir, "mode"), + } +} + +func init() { + cfgDir, err := os.UserConfigDir() + if err != nil { + return + } + Default = NewDir(filepath.Join(cfgDir, "go", "telemetry")) +} + +func (d Dir) Dir() string { + return d.dir +} + +func (d Dir) LocalDir() string { + return d.local +} + +func (d Dir) UploadDir() string { + return d.upload +} + +func (d Dir) DebugDir() string { + return d.debug +} + +func (d Dir) ModeFile() string { + return d.modefile +} + +// SetMode updates the telemetry mode with the given mode. +// Acceptable values for mode are "on", "off", or "local". +// +// SetMode always writes the mode file, and explicitly records the date at +// which the modefile was updated. This means that calling SetMode with "on" +// effectively resets the timeout before the next telemetry report is uploaded. +func (d Dir) SetMode(mode string) error { + return d.SetModeAsOf(mode, time.Now()) +} + +// SetModeAsOf is like SetMode, but accepts an explicit time to use to +// back-date the mode state. This exists only for testing purposes. +func (d Dir) SetModeAsOf(mode string, asofTime time.Time) error { + mode = strings.TrimSpace(mode) + switch mode { + case "on", "off", "local": + default: + return fmt.Errorf("invalid telemetry mode: %q", mode) + } + if d.modefile == "" { + return fmt.Errorf("cannot determine telemetry mode file name") + } + // TODO(rfindley): why is this not 777, consistent with the use of 666 below? + if err := os.MkdirAll(filepath.Dir(d.modefile), 0755); err != nil { + return fmt.Errorf("cannot create a telemetry mode file: %w", err) + } + + asof := asofTime.UTC().Format(DateOnly) + // Defensively guarantee that we can parse the asof time. + if _, err := time.Parse(DateOnly, asof); err != nil { + return fmt.Errorf("internal error: invalid mode date %q: %v", asof, err) + } + + data := []byte(mode + " " + asof) + return os.WriteFile(d.modefile, data, 0666) +} + +// Mode returns the current telemetry mode, as well as the time that the mode +// was effective. +// +// If there is no effective time, the second result is the zero time. +// +// If Mode is "off", no data should be written to the telemetry directory, and +// the other paths values referenced by Dir should be considered undefined. +// This accounts for the case where initializing [Default] fails, and therefore +// local telemetry paths are unknown. +func (d Dir) Mode() (string, time.Time) { + if d.modefile == "" { + return "off", time.Time{} // it's likely LocalDir/UploadDir are empty too. Turn off telemetry. + } + data, err := os.ReadFile(d.modefile) + if err != nil { + return "local", time.Time{} // default + } + mode := string(data) + mode = strings.TrimSpace(mode) + + // Forward compatibility for https://go.dev/issue/63142#issuecomment-1734025130 + // + // If the modefile contains a date, return it. + if idx := strings.Index(mode, " "); idx >= 0 { + d, err := time.Parse(DateOnly, mode[idx+1:]) + if err != nil { + d = time.Time{} + } + return mode[:idx], d + } + + return mode, time.Time{} +} + +// DisabledOnPlatform indicates whether telemetry is disabled +// due to bugs in the current platform. +// +// TODO(rfindley): move to a more appropriate file. +const DisabledOnPlatform = false || + // The following platforms could potentially be supported in the future: + runtime.GOOS == "openbsd" || // #60614 + runtime.GOOS == "solaris" || // #60968 #60970 + runtime.GOOS == "android" || // #60967 + runtime.GOOS == "illumos" || // #65544 + // These platforms fundamentally can't be supported: + runtime.GOOS == "js" || // #60971 + runtime.GOOS == "wasip1" || // #60971 + runtime.GOOS == "plan9" || // https://github.com/golang/go/issues/57540#issuecomment-1470766639 + runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" // mips lacks cross-process 64-bit atomics diff --git a/history-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go new file mode 100644 index 00000000..5ff7d34f --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -0,0 +1,57 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "go/version" + "os" + "path/filepath" + "runtime/debug" + "strings" +) + +// IsToolchainProgram reports whether a program with the given path is a Go +// toolchain program. +func IsToolchainProgram(progPath string) bool { + return strings.HasPrefix(progPath, "cmd/") +} + +// ProgramInfo extracts the go version, program package path, and program +// version to use for counter files. +// +// For programs in the Go toolchain, the program version will be the same as +// the Go version, and will typically be of the form "go1.2.3", not a semantic +// version of the form "v1.2.3". Go versions may also include spaces and +// special characters. +func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { + goVers = info.GoVersion + if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") || !version.IsValid(goVers) { + goVers = "devel" + } + + progPath = info.Path + if progPath == "" { + progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + + // Main module version information is not populated for the cmd module, but + // we can re-use the Go version here. + if IsToolchainProgram(progPath) { + progVers = goVers + } else { + progVers = info.Main.Version + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). + progVers = "devel" + } + } + + return goVers, progPath, progVers +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go new file mode 100644 index 00000000..0fd61f8d --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig struct { + GOOS []string + GOARCH []string + GoVersion []string + SampleRate float64 + Programs []*ProgramConfig +} + +type ProgramConfig struct { + // the counter names may have to be + // repeated for each program. (e.g., if the counters are in a package + // that is used in more than one program.) + Name string + Versions []string // versions present in a counterconfig + Counters []CounterConfig `json:",omitempty"` + Stacks []CounterConfig `json:",omitempty"` +} + +type CounterConfig struct { + Name string // The "collapsed" counter: :{,,...} + Rate float64 // If X <= Rate, report this counter + Depth int `json:",omitempty"` // for stack counters +} + +// A Report is the weekly aggregate of counters. +type Report struct { + Week string // End day this report covers (YYYY-MM-DD) + LastWeek string // Week field from latest previous report uploaded + X float64 // A random probability used to determine which counters are uploaded + Programs []*ProgramReport + Config string // version of UploadConfig used +} + +type ProgramReport struct { + Program string // Package path of the program. + Version string // Program version. Go version if the program is part of the go distribution. Module version, otherwise. + GoVersion string // Go version used to build the program. + GOOS string + GOARCH string + Counters map[string]int64 + Stacks map[string]int64 +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt b/history-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt new file mode 100644 index 00000000..45601e65 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt @@ -0,0 +1,45 @@ +The upload process converts count files into reports, and +uploads reports. There will be only one report, named YYYY-MM-DD.json, +for a given day. + +First phase. Look at the localdir (os.UserConfigdir()/go/telemetry/local) +and find all .count and .json files. Find the count files that are no +longer active by looking at their metadata. + +Second phase. Group the inactive count files by their expiry date, and +for each date generate the local report and the upload report. (The upload +report only contains the counters in the upload configuration.) The upload +report is saved in the local directory with a name like YYYY-MM-DD.json, if +there is no file already existing with that name. +If the local report is different, it is saved in the local directory +with a name like local.YYYY-MM-DD.json. The new upload report is +added to the list of .json files from the first phase. At this point +the count files are no longer needed and can be deleted. + +Third phase. Look at the .json files in the list from the first phase. +If the name starts with local, skip it. If there is a file with the +identical name in the upload directory, remove the one in the local directory. +Otherwise try to upload the one in the local directory, +If the upload succeeds, move the file to the uploaded directory. + + +There are various error conditions. +1. Several processes could look at localdir and see work to do. +1A. They could see different sets of expired count files for some day. + This could happen if another process is removing count files. In this + case there is already a YYYY-MM-DD.json file either in localdir + or updatedir, so the process seeing fewer count files will not generate + a report. +1B. They could see the same count files, and no report in either directory. + They will both generate (in memory) reports and check to see if there + is a YYYY-MM-DD.json file in either directory. They could both then + write two files with the same name, but different X values, but + otherwise the same contents. The X values are very close to the front + of the file. Assuming reasonable file system semantics one version of + the file will be written. To minimize this, just before writing reports + the code checks again to see if they exist. +1C. Once there is an existing well-formed file YYYY-MM-DD.json in localdir + eventually the upload will succeed, and the file will be moved to updatedir. + It is possible that other processes will not see the file in updatedir and + upload it again and also move it to uploaddir. This is harmless as all + the uploaded files are identical. diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/date.go b/history-api/vendor/golang.org/x/telemetry/internal/upload/date.go new file mode 100644 index 00000000..d6d67a16 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/date.go @@ -0,0 +1,85 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "os" + "sync" + "time" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// time and date handling + +var distantPast = 21 * 24 * time.Hour + +// reports that are too old (21 days) are not uploaded +func (u *uploader) tooOld(date string, uploadStartTime time.Time) bool { + t, err := time.Parse(telemetry.DateOnly, date) + if err != nil { + u.logger.Printf("tooOld: %v", err) + return false + } + age := uploadStartTime.Sub(t) + return age > distantPast +} + +// counterDateSpan parses the counter file named fname and returns the (begin, +// end) span recorded in its metadata, or an error if this data could not be +// extracted. +func (u *uploader) counterDateSpan(fname string) (begin, end time.Time, _ error) { + parsed, err := u.parseCountFile(fname) + if err != nil { + return time.Time{}, time.Time{}, err + } + timeBegin, ok := parsed.Meta["TimeBegin"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeBegin") + } + begin, err = time.Parse(time.RFC3339, timeBegin) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeBegin: %v", err) + } + timeEnd, ok := parsed.Meta["TimeEnd"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeEnd") + } + end, err = time.Parse(time.RFC3339, timeEnd) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeEnd: %v", err) + } + return begin, end, nil +} + +// avoid parsing count files multiple times +type parsedCache struct { + mu sync.Mutex + m map[string]*counter.File +} + +func (u *uploader) parseCountFile(fname string) (*counter.File, error) { + u.cache.mu.Lock() + defer u.cache.mu.Unlock() + if u.cache.m == nil { + u.cache.m = make(map[string]*counter.File) + } + if f, ok := u.cache.m[fname]; ok { + return f, nil + } + buf, err := os.ReadFile(fname) + if err != nil { + return nil, fmt.Errorf("parse ReadFile: %v for %s", err, fname) + } + f, err := counter.Parse(fname, buf) + if err != nil { + + return nil, fmt.Errorf("parse Parse: %v for %s", err, fname) + } + u.cache.m[fname] = f + return f, nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go b/history-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go new file mode 100644 index 00000000..2b165be3 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go @@ -0,0 +1,102 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "os" + "path/filepath" + "strings" +) + +// files to handle +type work struct { + // absolute file names + countfiles []string // count files to process + readyfiles []string // old reports to upload + // relative names + uploaded map[string]bool // reports that have been uploaded +} + +// find all the files that look like counter files or reports +// that need to be uploaded. (There may be unexpected leftover files +// and uploading is supposed to be idempotent.) +func (u *uploader) findWork() work { + localdir, uploaddir := u.dir.LocalDir(), u.dir.UploadDir() + var ans work + fis, err := os.ReadDir(localdir) + if err != nil { + u.logger.Printf("Could not find work: failed to read local dir %s: %v", localdir, err) + return ans + } + + mode, asof := u.dir.Mode() + u.logger.Printf("Finding work: mode %s asof %s", mode, asof) + + // count files end in .v1.count + // reports end in .json. If they are not to be uploaded they + // start with local. + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".v1.count") { + fname := filepath.Join(localdir, fi.Name()) + _, expiry, err := u.counterDateSpan(fname) + switch { + case err != nil: + u.logger.Printf("Error reading expiry for count file %s: %v", fi.Name(), err) + case expiry.After(u.startTime): + u.logger.Printf("Skipping count file %s: still active", fi.Name()) + default: + u.logger.Printf("Collecting count file %s", fi.Name()) + ans.countfiles = append(ans.countfiles, fname) + } + } else if strings.HasPrefix(fi.Name(), "local.") { + // skip + } else if strings.HasSuffix(fi.Name(), ".json") && mode == "on" { + // Collect reports that are ready for upload. + reportDate := u.uploadReportDate(fi.Name()) + if !asof.IsZero() && !reportDate.IsZero() { + // If both the mode asof date and the report date are present, do the + // right thing... + // + // (see https://github.com/golang/go/issues/63142#issuecomment-1734025130) + if asof.Before(reportDate) { + // Note: since this report was created after telemetry was enabled, + // we can only assume that the process that created it checked that + // the counter data contained therein was all from after the asof + // date. + // + // TODO(rfindley): store the begin date in reports, so that we can + // verify this assumption. + u.logger.Printf("Uploadable: %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } else { + // ...otherwise fall back on the old behavior of uploading all + // unuploaded files. + // + // TODO(rfindley): invert this logic following more testing. We + // should only upload if we know both the asof date and the report + // date, and they are acceptable. + u.logger.Printf("Uploadable (missing date): %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } + } + + fis, err = os.ReadDir(uploaddir) + if err != nil { + os.MkdirAll(uploaddir, 0777) + return ans + } + // There should be only one of these per day; maybe sometime + // we'll want to clean the directory. + ans.uploaded = make(map[string]bool) + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".json") { + u.logger.Printf("Already uploaded: %s", fi.Name()) + ans.uploaded[fi.Name()] = true + } + } + return ans +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/reports.go b/history-api/vendor/golang.org/x/telemetry/internal/upload/reports.go new file mode 100644 index 00000000..34bb29d8 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/reports.go @@ -0,0 +1,344 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "crypto/rand" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/telemetry/internal/config" + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// reports generates reports from inactive count files +func (u *uploader) reports(todo *work) ([]string, error) { + if mode, _ := u.dir.Mode(); mode == "off" { + return nil, nil // no reports + } + thisInstant := u.startTime + today := thisInstant.Format(telemetry.DateOnly) + lastWeek := latestReport(todo.uploaded) + if lastWeek >= today { //should never happen + lastWeek = "" + } + u.logger.Printf("Last week: %s, today: %s", lastWeek, today) + countFiles := make(map[string][]string) // expiry date string->filenames + earliest := make(map[string]time.Time) // earliest begin time for any counter + for _, f := range todo.countfiles { + begin, end, err := u.counterDateSpan(f) + if err != nil { + // This shouldn't happen: we should have already skipped count files that + // don't contain valid start or end times. + u.logger.Printf("BUG: failed to parse expiry for collected count file: %v", err) + continue + } + + if end.Before(thisInstant) { + expiry := end.Format(dateFormat) + countFiles[expiry] = append(countFiles[expiry], f) + if earliest[expiry].IsZero() || earliest[expiry].After(begin) { + earliest[expiry] = begin + } + } + } + for expiry, files := range countFiles { + if notNeeded(expiry, *todo) { + u.logger.Printf("Files for %s not needed, deleting %v", expiry, files) + // The report already exists. + // There's another check in createReport. + u.deleteFiles(files) + continue + } + fname, err := u.createReport(earliest[expiry], expiry, files, lastWeek) + if err != nil { + u.logger.Printf("Failed to create report for %s: %v", expiry, err) + continue + } + if fname != "" { + u.logger.Printf("Ready to upload: %s", filepath.Base(fname)) + todo.readyfiles = append(todo.readyfiles, fname) + } + } + return todo.readyfiles, nil +} + +// latestReport returns the YYYY-MM-DD of the last report uploaded +// or the empty string if there are no reports. +func latestReport(uploaded map[string]bool) string { + var latest string + for name := range uploaded { + if strings.HasSuffix(name, ".json") { + if name > latest { + latest = name + } + } + } + if latest == "" { + return "" + } + // strip off the .json + return latest[:len(latest)-len(".json")] +} + +// notNeeded returns true if the report for date has already been created +func notNeeded(date string, todo work) bool { + if todo.uploaded != nil && todo.uploaded[date+".json"] { + return true + } + // maybe the report is already in todo.readyfiles + for _, f := range todo.readyfiles { + if strings.Contains(f, date) { + return true + } + } + return false +} + +func (u *uploader) deleteFiles(files []string) { + for _, f := range files { + if err := os.Remove(f); err != nil { + // this could be a race condition. + // conversely, on Windows, err may be nil and + // the file not deleted if anyone has it open. + u.logger.Printf("%v failed to remove %s", err, f) + } + } +} + +// createReport creates local and upload report files by +// combining all the count files for the expiryDate, and +// returns the upload report file's path. +// It may delete the count files once local and upload report +// files are successfully created. +func (u *uploader) createReport(start time.Time, expiryDate string, countFiles []string, lastWeek string) (string, error) { + uploadOK := true + mode, asof := u.dir.Mode() + if mode != "on" { + u.logger.Printf("No upload config or mode %q is not 'on'", mode) + uploadOK = false // no config, nothing to upload + } + if u.tooOld(expiryDate, u.startTime) { + u.logger.Printf("Expiry date %s is too old", expiryDate) + uploadOK = false + } + // If the mode is recorded with an asof date, don't upload if the report + // includes any data on or before the asof date. + if !asof.IsZero() && !asof.Before(start) { + u.logger.Printf("As-of date %s is not before start %s", asof, start) + uploadOK = false + } + // TODO(rfindley): check that all the x.Meta are consistent for GOOS, GOARCH, etc. + report := &telemetry.Report{ + Config: u.configVersion, + X: computeRandom(), // json encodes all the bits + Week: expiryDate, + LastWeek: lastWeek, + } + if report.X > u.config.SampleRate && u.config.SampleRate > 0 { + u.logger.Printf("X: %f > SampleRate:%f, not uploadable", report.X, u.config.SampleRate) + uploadOK = false + } + var succeeded bool + for _, f := range countFiles { + fok := false + x, err := u.parseCountFile(f) + if err != nil { + u.logger.Printf("Unparseable count file %s: %v", filepath.Base(f), err) + continue + } + prog := findProgReport(x.Meta, report) + for k, v := range x.Count { + if counter.IsStackCounter(k) { + // stack + prog.Stacks[k] += int64(v) + } else { + // counter + prog.Counters[k] += int64(v) + } + succeeded = true + fok = true + } + if !fok { + u.logger.Printf("no counters found in %s", f) + } + } + if !succeeded { + return "", fmt.Errorf("none of the %d count files for %s contained counters", len(countFiles), expiryDate) + } + // 1. generate the local report + localContents, err := json.MarshalIndent(report, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal report for %s: %v", expiryDate, err) + } + // check that the report can be read back + // TODO(pjw): remove for production? + var report2 telemetry.Report + if err := json.Unmarshal(localContents, &report2); err != nil { + return "", fmt.Errorf("failed to unmarshal local report for %s: %v", expiryDate, err) + } + + var uploadContents []byte + if uploadOK { + // 2. create the uploadable version + cfg := config.NewConfig(u.config) + upload := &telemetry.Report{ + Week: report.Week, + LastWeek: report.LastWeek, + X: report.X, + Config: report.Config, + } + for _, p := range report.Programs { + // does the uploadConfig want this program? + // if so, copy over the Stacks and Counters + // that the uploadConfig mentions. + if !cfg.HasGoVersion(p.GoVersion) || !cfg.HasProgram(p.Program) || !cfg.HasVersion(p.Program, p.Version) { + continue + } + x := &telemetry.ProgramReport{ + Program: p.Program, + Version: p.Version, + GOOS: p.GOOS, + GOARCH: p.GOARCH, + GoVersion: p.GoVersion, + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + upload.Programs = append(upload.Programs, x) + for k, v := range p.Counters { + if cfg.HasCounter(p.Program, k) && report.X <= cfg.Rate(p.Program, k) { + x.Counters[k] = v + } + } + // and the same for Stacks + // this can be made more efficient, when it matters + for k, v := range p.Stacks { + before, _, _ := strings.Cut(k, "\n") + if cfg.HasStack(p.Program, before) && report.X <= cfg.Rate(p.Program, before) { + x.Stacks[k] = v + } + } + } + + uploadContents, err = json.MarshalIndent(upload, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal upload report for %s: %v", expiryDate, err) + } + } + localFileName := filepath.Join(u.dir.LocalDir(), "local."+expiryDate+".json") + uploadFileName := filepath.Join(u.dir.LocalDir(), expiryDate+".json") + + /* Prepare to write files */ + // if either file exists, someone has been here ahead of us + // (there is still a race, but this check shortens the open window) + if _, err := os.Stat(localFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("local report %s already exists", localFileName) + } + if _, err := os.Stat(uploadFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("report %s already exists", uploadFileName) + } + // write the uploadable file + var errUpload, errLocal error + if uploadOK { + _, errUpload = exclusiveWrite(uploadFileName, uploadContents) + } + // write the local file + _, errLocal = exclusiveWrite(localFileName, localContents) + /* Wrote the files */ + + // even though these errors won't occur, what should happen + // if errUpload == nil and it is ok to upload, and errLocal != nil? + if errLocal != nil { + return "", fmt.Errorf("failed to write local file %s (%v)", localFileName, errLocal) + } + if errUpload != nil { + return "", fmt.Errorf("failed to write upload file %s (%v)", uploadFileName, errUpload) + } + u.logger.Printf("Created %s, deleting %d count files", filepath.Base(uploadFileName), len(countFiles)) + u.deleteFiles(countFiles) + if uploadOK { + return uploadFileName, nil + } + return "", nil +} + +// exclusiveWrite attempts to create filename exclusively, and if successful, +// writes content to the resulting file handle. +// +// It returns a boolean indicating whether the exclusive handle was acquired, +// and an error indicating whether the operation succeeded. +// If the file already exists, exclusiveWrite returns (false, nil). +func exclusiveWrite(filename string, content []byte) (_ bool, rerr error) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + if os.IsExist(err) { + return false, nil + } + return false, err + } + defer func() { + if err := f.Close(); err != nil && rerr == nil { + rerr = err + } + }() + if _, err := f.Write(content); err != nil { + return false, err + } + return true, nil +} + +// return an existing ProgremReport, or create anew +func findProgReport(meta map[string]string, report *telemetry.Report) *telemetry.ProgramReport { + for _, prog := range report.Programs { + if prog.Program == meta["Program"] && prog.Version == meta["Version"] && + prog.GoVersion == meta["GoVersion"] && prog.GOOS == meta["GOOS"] && + prog.GOARCH == meta["GOARCH"] { + return prog + } + } + prog := telemetry.ProgramReport{ + Program: meta["Program"], + Version: meta["Version"], + GoVersion: meta["GoVersion"], + GOOS: meta["GOOS"], + GOARCH: meta["GOARCH"], + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + report.Programs = append(report.Programs, &prog) + return &prog +} + +// computeRandom returns a cryptographic random float64 in the range [0, 1], +// with 52 bits of precision. +func computeRandom() float64 { + for { + b := make([]byte, 8) + _, err := rand.Read(b) + if err != nil { + panic(fmt.Sprintf("rand.Read failed: %v", err)) + } + // and turn it into a float64 + x := math.Float64frombits(binary.LittleEndian.Uint64(b)) + if math.IsNaN(x) || math.IsInf(x, 0) { + continue + } + x = math.Abs(x) + if x < 0x1p-1000 { // avoid underflow patterns + continue + } + frac, _ := math.Frexp(x) // 52 bits of randomness + return frac*2 - 1 + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/run.go b/history-api/vendor/golang.org/x/telemetry/internal/upload/run.go new file mode 100644 index 00000000..e9c8dc20 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/run.go @@ -0,0 +1,226 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "io" + "log" + "os" + "path" + "path/filepath" + "runtime/debug" + "strings" + "time" + + "golang.org/x/telemetry/internal/configstore" + "golang.org/x/telemetry/internal/telemetry" +) + +// RunConfig configures non-default behavior of a call to Run. +// +// All fields are optional, for testing or observability. +type RunConfig struct { + TelemetryDir string // if set, overrides the telemetry data directory + UploadURL string // if set, overrides the telemetry upload endpoint + LogWriter io.Writer // if set, used for detailed logging of the upload process + Env []string // if set, appended to the config download environment + StartTime time.Time // if set, overrides the upload start time +} + +// Run generates and uploads reports, as allowed by the mode file. +func Run(config RunConfig) error { + defer func() { + if err := recover(); err != nil { + log.Printf("upload recover: %v", err) + } + }() + uploader, err := newUploader(config) + if err != nil { + return err + } + defer uploader.Close() + return uploader.Run() +} + +// uploader encapsulates a single upload operation, carrying parameters and +// shared state. +type uploader struct { + // config is used to select counters to upload. + config *telemetry.UploadConfig // + configVersion string // version of the config + dir telemetry.Dir // the telemetry dir to process + + uploadServerURL string + startTime time.Time + + cache parsedCache + + logFile *os.File + logger *log.Logger +} + +// newUploader creates a new uploader to use for running the upload for the +// given config. +// +// Uploaders should only be used for one call to [uploader.Run]. +func newUploader(rcfg RunConfig) (*uploader, error) { + // Determine the upload directory. + var dir telemetry.Dir + if rcfg.TelemetryDir != "" { + dir = telemetry.NewDir(rcfg.TelemetryDir) + } else { + dir = telemetry.Default + } + + // Determine the upload URL. + uploadURL := rcfg.UploadURL + if uploadURL == "" { + uploadURL = "https://telemetry.go.dev/upload" + } + + // Determine the upload logger. + // + // This depends on the provided rcfg.LogWriter and the presence of + // dir.DebugDir, as follows: + // 1. If LogWriter is present, log to it. + // 2. If DebugDir is present, log to a file within it. + // 3. If both LogWriter and DebugDir are present, log to a multi writer. + // 4. If neither LogWriter nor DebugDir are present, log to a noop logger. + var logWriters []io.Writer + logFile, err := debugLogFile(dir.DebugDir()) + if err != nil { + logFile = nil + } + if logFile != nil { + logWriters = append(logWriters, logFile) + } + if rcfg.LogWriter != nil { + logWriters = append(logWriters, rcfg.LogWriter) + } + var logWriter io.Writer + switch len(logWriters) { + case 0: + logWriter = io.Discard + case 1: + logWriter = logWriters[0] + default: + logWriter = io.MultiWriter(logWriters...) + } + logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile) + + // Fetch the upload config, if it is not provided. + var ( + config *telemetry.UploadConfig + configVersion string + ) + + if mode, _ := dir.Mode(); mode == "on" { + // golang/go#68946: only download the upload config if it will be used. + // + // TODO(rfindley): This is a narrow change aimed at minimally fixing the + // associated bug. In the future, we should read the mode only once during + // the upload process. + config, configVersion, err = configstore.Download("latest", rcfg.Env) + if err != nil { + return nil, err + } + } else { + config = &telemetry.UploadConfig{} + configVersion = "v0.0.0-0" + } + + // Set the start time, if it is not provided. + startTime := time.Now().UTC() + if !rcfg.StartTime.IsZero() { + startTime = rcfg.StartTime + } + + return &uploader{ + config: config, + configVersion: configVersion, + dir: dir, + uploadServerURL: uploadURL, + startTime: startTime, + + logFile: logFile, + logger: logger, + }, nil +} + +// Close cleans up any resources associated with the uploader. +func (u *uploader) Close() error { + if u.logFile == nil { + return nil + } + return u.logFile.Close() +} + +// Run generates and uploads reports +func (u *uploader) Run() error { + if telemetry.DisabledOnPlatform { + return nil + } + todo := u.findWork() + ready, err := u.reports(&todo) + if err != nil { + u.logger.Printf("Error building reports: %v", err) + return fmt.Errorf("reports failed: %v", err) + } + u.logger.Printf("Uploading %d reports", len(ready)) + for _, f := range ready { + u.uploadReport(f) + } + return nil +} + +// debugLogFile arranges to write a log file in the given debug directory, if +// it exists. +func debugLogFile(debugDir string) (*os.File, error) { + fd, err := os.Stat(debugDir) + if os.IsNotExist(err) { + return nil, nil + } + if err != nil { + return nil, err + } + if !fd.IsDir() { + return nil, fmt.Errorf("debug path %q is not a directory", debugDir) + } + info, ok := debug.ReadBuildInfo() + if !ok { + return nil, fmt.Errorf("no build info") + } + year, month, day := time.Now().UTC().Date() + goVers := info.GoVersion + // E.g., goVers:"go1.22-20240109-RC01 cl/597041403 +dcbe772469 X:loopvar" + words := strings.Fields(goVers) + goVers = words[0] + progPkgPath := info.Path + if progPkgPath == "" { + progPkgPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + prog := path.Base(progPkgPath) + progVers := info.Main.Version + if progVers == "(devel)" { // avoid special characters in created file names + progVers = "devel" + } + logBase := strings.ReplaceAll( + fmt.Sprintf("%s-%s-%s-%4d%02d%02d-%d.log", prog, progVers, goVers, year, month, day, os.Getpid()), + " ", "") + fname := filepath.Join(debugDir, logBase) + if _, err := os.Stat(fname); err == nil { + // This process previously called upload.Run + return nil, nil + } + f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return nil, nil // this process previously called upload.Run + } + return nil, err + } + return f, nil +} diff --git a/history-api/vendor/golang.org/x/telemetry/internal/upload/upload.go b/history-api/vendor/golang.org/x/telemetry/internal/upload/upload.go new file mode 100644 index 00000000..419745f6 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/internal/upload/upload.go @@ -0,0 +1,117 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "bytes" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "golang.org/x/telemetry/internal/telemetry" +) + +var ( + dateRE = regexp.MustCompile(`(\d\d\d\d-\d\d-\d\d)[.]json$`) + dateFormat = telemetry.DateOnly + // TODO(rfindley): use dateFormat throughout. +) + +// uploadReportDate returns the date component of the upload file name, or "" if the +// date was unmatched. +func (u *uploader) uploadReportDate(fname string) time.Time { + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("malformed report name: missing date: %q", filepath.Base(fname)) + return time.Time{} + } + d, err := time.Parse(dateFormat, match[1]) + if err != nil { + u.logger.Printf("malformed report name: bad date: %q", filepath.Base(fname)) + return time.Time{} + } + return d +} + +func (u *uploader) uploadReport(fname string) { + thisInstant := u.startTime + // TODO(rfindley): use uploadReportDate here, once we've done a gopls release. + + // first make sure it is not in the future + today := thisInstant.Format(telemetry.DateOnly) + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("Report name %q missing date", filepath.Base(fname)) + } else if match[1] > today { + u.logger.Printf("Report date for %q is later than today (%s)", filepath.Base(fname), today) + return // report is in the future, which shouldn't happen + } + buf, err := os.ReadFile(fname) + if err != nil { + u.logger.Printf("%v reading %s", err, fname) + return + } + if u.uploadReportContents(fname, buf) { + // anything left to do? + } +} + +// try to upload the report, 'true' if successful +func (u *uploader) uploadReportContents(fname string, buf []byte) bool { + fdate := strings.TrimSuffix(filepath.Base(fname), ".json") + fdate = fdate[len(fdate)-len(telemetry.DateOnly):] + + newname := filepath.Join(u.dir.UploadDir(), fdate+".json") + + // Lock the upload, to prevent duplicate uploads. + { + lockname := newname + ".lock" + lockfile, err := os.OpenFile(lockname, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + u.logger.Printf("Failed to acquire lock %s: %v", lockname, err) + return false + } + _ = lockfile.Close() + defer os.Remove(lockname) + } + + if _, err := os.Stat(newname); err == nil { + // Another process uploaded but failed to clean up (or hasn't yet cleaned + // up). Ensure that cleanup occurs. + u.logger.Printf("After acquire: report already uploaded") + _ = os.Remove(fname) + return false + } + + endpoint := u.uploadServerURL + "/" + fdate + b := bytes.NewReader(buf) + resp, err := http.Post(endpoint, "application/json", b) + if err != nil { + u.logger.Printf("Error upload %s to %s: %v", filepath.Base(fname), endpoint, err) + return false + } + // hope for a 200, remove file on a 4xx, otherwise it will be retried by another process + if resp.StatusCode != 200 { + u.logger.Printf("Failed to upload %s to %s: %s", filepath.Base(fname), endpoint, resp.Status) + if resp.StatusCode >= 400 && resp.StatusCode < 500 { + err := os.Remove(fname) + if err == nil { + u.logger.Printf("Removed local/%s", filepath.Base(fname)) + } else { + u.logger.Printf("Error removing local/%s: %v", filepath.Base(fname), err) + } + } + return false + } + // Store a copy of the uploaded report in the uploaded directory. + if err := os.WriteFile(newname, buf, 0644); err == nil { + os.Remove(fname) // if it exists + } + u.logger.Printf("Uploaded %s to %q", fdate+".json", endpoint) + return true +} diff --git a/history-api/vendor/golang.org/x/telemetry/mode.go b/history-api/vendor/golang.org/x/telemetry/mode.go new file mode 100644 index 00000000..8cdcd134 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/mode.go @@ -0,0 +1,38 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Mode returns the current telemetry mode. +// +// The telemetry mode is a global value that controls both the local collection +// and uploading of telemetry data. Possible mode values are: +// - "on": both collection and uploading is enabled +// - "local": collection is enabled, but uploading is disabled +// - "off": both collection and uploading are disabled +// +// When mode is "on", or "local", telemetry data is written to the local file +// system and may be inspected with the [gotelemetry] command. +// +// If an error occurs while reading the telemetry mode from the file system, +// Mode returns the default value "local". +// +// [gotelemetry]: https://pkg.go.dev/golang.org/x/telemetry/cmd/gotelemetry +func Mode() string { + mode, _ := telemetry.Default.Mode() + return mode +} + +// SetMode sets the global telemetry mode to the given value. +// +// See the documentation of [Mode] for a description of the supported mode +// values. +// +// An error is returned if the provided mode value is invalid, or if an error +// occurs while persisting the mode value to the file system. +func SetMode(mode string) error { + return telemetry.Default.SetMode(mode) +} diff --git a/history-api/vendor/golang.org/x/telemetry/npm b/history-api/vendor/golang.org/x/telemetry/npm new file mode 100644 index 00000000..a5455cfb --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/npm @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npm \ + node:18.16.0-slim \ + $@ diff --git a/history-api/vendor/golang.org/x/telemetry/npx b/history-api/vendor/golang.org/x/telemetry/npx new file mode 100644 index 00000000..47bb38bb --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/npx @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npx \ + node:18.16.0-slim \ + $@ diff --git a/history-api/vendor/golang.org/x/telemetry/package-lock.json b/history-api/vendor/golang.org/x/telemetry/package-lock.json new file mode 100644 index 00000000..9c86033e --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/package-lock.json @@ -0,0 +1,4363 @@ +{ + "name": "workspace", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.1.1.tgz", + "integrity": "sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz", + "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.4.tgz", + "integrity": "sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@observablehq/plot": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.9.tgz", + "integrity": "sha512-vwV6bzQsGjv2XrPEpc3Voixcz2e5EVvCSzzcs/uW9KXO5ZM8GdMVXtNTaRwYXUOk98nbiYFCFwzMaIyRjrt9IA==", + "dependencies": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz", + "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "dependencies": { + "binary-search-bounds": "^2.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", + "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1", + "@csstools/media-query-list-parser": "^2.0.4", + "@csstools/selector-specificity": "^2.2.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.1.3", + "css-functions-list": "^3.1.0", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.27.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.12", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^12.0.0" + }, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/package.json b/history-api/vendor/golang.org/x/telemetry/package.json new file mode 100644 index 00000000..3680ce22 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/package.json @@ -0,0 +1,23 @@ +{ + "scripts": { + "eslint": "eslint . --fix", + "stylelint": "stylelint '**/*.css' --fix", + "prettier": "prettier --write **/*.{css,ts,md,yaml} !**/*.min.css", + "all": "run-s --continue-on-error eslint stylelint prettier" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + }, + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/start.go b/history-api/vendor/golang.org/x/telemetry/start.go new file mode 100644 index 00000000..9c0519a6 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/start.go @@ -0,0 +1,354 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "sync" + "time" + + "golang.org/x/sync/errgroup" + "golang.org/x/telemetry/counter" + "golang.org/x/telemetry/internal/crashmonitor" + "golang.org/x/telemetry/internal/telemetry" + "golang.org/x/telemetry/internal/upload" +) + +// Config controls the behavior of [Start]. +type Config struct { + // ReportCrashes, if set, will enable crash reporting. + // ReportCrashes uses the [debug.SetCrashOutput] mechanism, which is a + // process-wide resource. + // Do not make other calls to that function within your application. + // ReportCrashes is a non-functional unless the program is built with go1.23+. + ReportCrashes bool + + // Upload causes this program to periodically upload approved counters + // from the local telemetry database to telemetry.go.dev. + // + // This option has no effect unless the user has given consent + // to enable data collection, for example by running + // cmd/gotelemetry or affirming the gopls dialog. + // + // (This feature is expected to be used only by gopls. + // Longer term, the go command may become the sole program + // responsible for uploading.) + Upload bool + + // TelemetryDir, if set, will specify an alternate telemetry + // directory to write data to. If not set, it uses the default + // directory. + // This field is intended to be used for isolating testing environments. + TelemetryDir string + + // UploadStartTime, if set, overrides the time used as the upload start time, + // which is the time used by the upload logic to determine whether counter + // file data should be uploaded. Only counter files that have expired before + // the start time are considered for upload. + // + // This field can be used to simulate a future upload that collects recently + // modified counters. + UploadStartTime time.Time + + // UploadURL, if set, overrides the URL used to receive uploaded reports. If + // unset, this URL defaults to https://telemetry.go.dev/upload. + UploadURL string +} + +// Start initializes telemetry using the specified configuration. +// +// Start opens the local telemetry database so that counter increment +// operations are durably recorded in the local file system. +// +// If [Config.Upload] is set, and the user has opted in to telemetry +// uploading, this process may attempt to upload approved counters +// to telemetry.go.dev. +// +// If [Config.ReportCrashes] is set, any fatal crash will be +// recorded by incrementing a counter named for the stack of the +// first running goroutine in the traceback. +// +// If either of these flags is set, Start re-executes the current +// executable as a child process, in a special mode in which it +// acts as a telemetry sidecar for the parent process (the application). +// In that mode, the call to Start will never return, so Start must +// be called immediately within main, even before such things as +// inspecting the command line. The application should avoid expensive +// steps or external side effects in init functions, as they will +// be executed twice (parent and child). +// +// Start returns a StartResult, which may be awaited via [StartResult.Wait] to +// wait for all work done by Start to complete. +func Start(config Config) *StartResult { + switch v := os.Getenv(telemetryChildVar); v { + case "": + // The subprocess started by parent has GO_TELEMETRY_CHILD=1. + return parent(config) + case "1": + child(config) // child will exit the process when it's done. + case "2": + // Do nothing: this was executed directly or indirectly by a child. + default: + log.Fatalf("unexpected value for %q: %q", telemetryChildVar, v) + } + + return &StartResult{} +} + +// MaybeChild executes the telemetry child logic if the calling program is +// the telemetry child process, and does nothing otherwise. It is meant to be +// called as the first thing in a program that uses telemetry.Start but cannot +// call telemetry.Start immediately when it starts. +func MaybeChild(config Config) { + if v := os.Getenv(telemetryChildVar); v == "1" { + child(config) // child will exit the process when it's done. + } + // other values of the telemetryChildVar environment variable + // will be handled by telemetry.Start. +} + +// A StartResult is a handle to the result of a call to [Start]. Call +// [StartResult.Wait] to wait for the completion of all work done on behalf of +// Start. +type StartResult struct { + wg sync.WaitGroup +} + +// Wait waits for the completion of all work initiated by [Start]. +func (res *StartResult) Wait() { + if res == nil { + return + } + res.wg.Wait() +} + +var daemonize = func(cmd *exec.Cmd) {} + +// If telemetryChildVar is set to "1" in the environment, this is the telemetry +// child. +// +// If telemetryChildVar is set to "2", this is a child of the child, and no +// further forking should occur. +const telemetryChildVar = "GO_TELEMETRY_CHILD" + +// If telemetryUploadVar is set to "1" in the environment, the upload token has been +// acquired by the parent, and the child should attempt an upload. +const telemetryUploadVar = "GO_TELEMETRY_CHILD_UPLOAD" + +func parent(config Config) *StartResult { + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + result := new(StartResult) + + mode, _ := telemetry.Default.Mode() + if mode == "off" { + // Telemetry is turned off. Crash reporting doesn't work without telemetry + // at least set to "local". The upload process runs in both "on" and "local" modes. + // In local mode the upload process builds local reports but does not do the upload. + return result + } + + counter.Open() + + if _, err := os.Stat(telemetry.Default.LocalDir()); err != nil { + // There was a problem statting LocalDir, which is needed for both + // crash monitoring and counter uploading. Most likely, there was an + // error creating telemetry.LocalDir in the counter.Open call above. + // Don't start the child. + return result + } + + childShouldUpload := config.Upload && acquireUploadToken() + reportCrashes := config.ReportCrashes + + if reportCrashes || childShouldUpload { + startChild(reportCrashes, childShouldUpload, result) + } + + return result +} + +func startChild(reportCrashes, upload bool, result *StartResult) { + // This process is the application (parent). + // Fork+exec the telemetry child. + exe, err := os.Executable() + if err != nil { + // There was an error getting os.Executable. It's possible + // for this to happen on AIX if os.Args[0] is not an absolute + // path and we can't find os.Args[0] in PATH. + log.Printf("failed to start telemetry sidecar: os.Executable: %v", err) + return + } + cmd := exec.Command(exe, "** telemetry **") // this unused arg is just for ps(1) + daemonize(cmd) + cmd.Env = append(os.Environ(), telemetryChildVar+"=1") + if upload { + cmd.Env = append(cmd.Env, telemetryUploadVar+"=1") + } + cmd.Dir = telemetry.Default.LocalDir() + + // The child process must write to a log file, not + // the stderr file it inherited from the parent, as + // the child may outlive the parent but should not prolong + // the life of any pipes created (by the grandparent) + // to gather the output of the parent. + // + // By default, we discard the child process's stderr, + // but in line with the uploader, log to a file in debug + // only if that directory was created by the user. + fd, err := os.Stat(telemetry.Default.DebugDir()) + if err != nil { + if !os.IsNotExist(err) { + log.Printf("failed to stat debug directory: %v", err) + return + } + } else if fd.IsDir() { + // local/debug exists and is a directory. Set stderr to a log file path + // in local/debug. + childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log") + childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) + if err != nil { + log.Printf("opening sidecar log file for child: %v", err) + return + } + defer childLog.Close() + cmd.Stderr = childLog + } + + var crashOutputFile *os.File + if reportCrashes { + pipe, err := cmd.StdinPipe() + if err != nil { + log.Printf("StdinPipe: %v", err) + return + } + + crashOutputFile = pipe.(*os.File) // (this conversion is safe) + } + + if err := cmd.Start(); err != nil { + // The child couldn't be started. Log the failure. + log.Printf("can't start telemetry child process: %v", err) + return + } + if reportCrashes { + crashmonitor.Parent(crashOutputFile) + } + result.wg.Add(1) + go func() { + cmd.Wait() // Release resources if cmd happens not to outlive this process. + result.wg.Done() + }() +} + +func child(config Config) { + log.SetPrefix(fmt.Sprintf("telemetry-sidecar (pid %v): ", os.Getpid())) + + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + + // golang/go#67211: be sure to set telemetryChildVar before running the + // child, because the child itself invokes the go command to download the + // upload config. If the telemetryChildVar variable is still set to "1", + // that delegated go command may think that it is itself a telemetry + // child. + // + // On the other hand, if telemetryChildVar were simply unset, then the + // delegated go commands would fork themselves recursively. Short-circuit + // this recursion. + os.Setenv(telemetryChildVar, "2") + upload := os.Getenv(telemetryUploadVar) == "1" + + // The crashmonitor and/or upload process may themselves record counters. + counter.Open() + + // Start crashmonitoring and uploading depending on what's requested + // and wait for the longer running child to complete before exiting: + // if we collected a crash before the upload finished, wait for the + // upload to finish before exiting + var g errgroup.Group + + if config.ReportCrashes { + g.Go(func() error { + crashmonitor.Child() + return nil + }) + } + if upload { + g.Go(func() error { + uploaderChild(config.UploadStartTime, config.UploadURL) + return nil + }) + } + g.Wait() + + os.Exit(0) +} + +func uploaderChild(asof time.Time, uploadURL string) { + if err := upload.Run(upload.RunConfig{ + UploadURL: uploadURL, + LogWriter: os.Stderr, + StartTime: asof, + }); err != nil { + log.Printf("upload failed: %v", err) + } +} + +// acquireUploadToken acquires a token permitting the caller to upload. +// To limit the frequency of uploads, only one token is issue per +// machine per time period. +// The boolean indicates whether the token was acquired. +func acquireUploadToken() bool { + if telemetry.Default.LocalDir() == "" { + // The telemetry dir wasn't initialized properly, probably because + // os.UserConfigDir did not complete successfully. In that case + // there are no counters to upload, so we should just do nothing. + return false + } + tokenfile := filepath.Join(telemetry.Default.LocalDir(), "upload.token") + const period = 24 * time.Hour + + // A process acquires a token by successfully creating a + // well-known file. If the file already exists and has an + // mtime age less then than the period, the process does + // not acquire the token. If the file is older than the + // period, the process is allowed to remove the file and + // try to re-create it. + fi, err := os.Stat(tokenfile) + if err == nil { + if time.Since(fi.ModTime()) < period { + return false + } + // There's a possible race here where two processes check the + // token file and see that it's older than the period, then the + // first one removes it and creates another, and then a second one + // removes the newly created file and creates yet another + // file. Then both processes would act as though they had the token. + // This is very rare, but it's also okay because we're only grabbing + // the token to do rate limiting, not for correctness. + _ = os.Remove(tokenfile) + } else if !os.IsNotExist(err) { + log.Printf("error acquiring upload taken: statting token file: %v", err) + return false + } + + f, err := os.OpenFile(tokenfile, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return false + } + log.Printf("error acquiring upload token: creating token file: %v", err) + return false + } + _ = f.Close() + return true +} diff --git a/history-api/vendor/golang.org/x/telemetry/start_posix.go b/history-api/vendor/golang.org/x/telemetry/start_posix.go new file mode 100644 index 00000000..078b2353 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/start_posix.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package telemetry + +import ( + "os/exec" + "syscall" +) + +func init() { + daemonize = daemonizePosix +} + +func daemonizePosix(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/start_windows.go b/history-api/vendor/golang.org/x/telemetry/start_windows.go new file mode 100644 index 00000000..ceb2c029 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/start_windows.go @@ -0,0 +1,29 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package telemetry + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + daemonize = daemonizeWindows +} + +func daemonizeWindows(cmd *exec.Cmd) { + // Set DETACHED_PROCESS creation flag so that closing + // the console window the parent process was run in + // does not kill the child. + // See documentation of creation flags in the Microsoft documentation: + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.DETACHED_PROCESS, + } +} diff --git a/history-api/vendor/golang.org/x/telemetry/tsconfig.json b/history-api/vendor/golang.org/x/telemetry/tsconfig.json new file mode 100644 index 00000000..7833e310 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/tsconfig.json @@ -0,0 +1,26 @@ +{ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "node", + + "strict": true, + "allowUnusedLabels": false, + "allowUnreachableCode": false, + "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "checkJs": true, + + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, +} \ No newline at end of file diff --git a/history-api/vendor/golang.org/x/telemetry/types_alias.go b/history-api/vendor/golang.org/x/telemetry/types_alias.go new file mode 100644 index 00000000..83ba7e05 --- /dev/null +++ b/history-api/vendor/golang.org/x/telemetry/types_alias.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig = telemetry.UploadConfig + +type ProgramConfig = telemetry.ProgramConfig + +type CounterConfig = telemetry.CounterConfig + +// A Report is what's uploaded (or saved locally) +type Report = telemetry.Report + +type ProgramReport = telemetry.ProgramReport diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index 436b03cb..1aa7afb9 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -57,7 +57,7 @@ type asmArch struct { // include the first integer register and first floating-point register. Accessing // any of them counts as writing to result. retRegs []string - // writeResult is a list of instructions that will change result register implicity. + // writeResult is a list of instructions that will change result register implicitly. writeResult []string // calculated during initialization sizes types.Sizes diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go index 1413ee13..1914bb47 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go @@ -9,11 +9,11 @@ package assign import ( _ "embed" - "fmt" "go/ast" "go/token" "go/types" "reflect" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -48,31 +48,84 @@ func run(pass *analysis.Pass) (any, error) { // If LHS and RHS have different cardinality, they can't be the same. return } + + // Delete redundant LHS, RHS pairs, taking care + // to include intervening commas. + var ( + exprs []string // expressions appearing on both sides (x = x) + edits []analysis.TextEdit + runStartLHS, runStartRHS token.Pos // non-zero => within a run + ) for i, lhs := range stmt.Lhs { rhs := stmt.Rhs[i] - if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || - analysisutil.HasSideEffects(pass.TypesInfo, rhs) || - isMapIndex(pass.TypesInfo, lhs) { - continue // expressions may not be equal - } - if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { - continue // short-circuit the heavy-weight gofmt check + isSelfAssign := false + var le string + + if !analysisutil.HasSideEffects(pass.TypesInfo, lhs) && + !analysisutil.HasSideEffects(pass.TypesInfo, rhs) && + !isMapIndex(pass.TypesInfo, lhs) && + reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check + + le = analysisinternal.Format(pass.Fset, lhs) + re := analysisinternal.Format(pass.Fset, rhs) + if le == re { + isSelfAssign = true + } } - le := analysisinternal.Format(pass.Fset, lhs) - re := analysisinternal.Format(pass.Fset, rhs) - if le == re { - pass.Report(analysis.Diagnostic{ - Pos: stmt.Pos(), Message: fmt.Sprintf("self-assignment of %s to %s", re, le), - SuggestedFixes: []analysis.SuggestedFix{{ - Message: "Remove self-assignment", - TextEdits: []analysis.TextEdit{{ - Pos: stmt.Pos(), - End: stmt.End(), - }}}, - }, - }) + + if isSelfAssign { + exprs = append(exprs, le) + if !runStartLHS.IsValid() { + // Start of a new run of self-assignments. + if i > 0 { + runStartLHS = stmt.Lhs[i-1].End() + runStartRHS = stmt.Rhs[i-1].End() + } else { + runStartLHS = lhs.Pos() + runStartRHS = rhs.Pos() + } + } + } else if runStartLHS.IsValid() { + // End of a run of self-assignments. + endLHS, endRHS := stmt.Lhs[i-1].End(), stmt.Rhs[i-1].End() + if runStartLHS == stmt.Lhs[0].Pos() { + endLHS, endRHS = lhs.Pos(), rhs.Pos() + } + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: endLHS}, + analysis.TextEdit{Pos: runStartRHS, End: endRHS}, + ) + runStartLHS, runStartRHS = 0, 0 } } + + // If a run of self-assignments continues to the end of the statement, close it. + if runStartLHS.IsValid() { + last := len(stmt.Lhs) - 1 + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: stmt.Lhs[last].End()}, + analysis.TextEdit{Pos: runStartRHS, End: stmt.Rhs[last].End()}, + ) + } + + if len(exprs) == 0 { + return + } + + if len(exprs) == len(stmt.Lhs) { + // If every part of the statement is a self-assignment, + // remove the whole statement. + edits = []analysis.TextEdit{{Pos: stmt.Pos(), End: stmt.End()}} + } + + pass.Report(analysis.Diagnostic{ + Pos: stmt.Pos(), + Message: "self-assignment of " + strings.Join(exprs, ", "), + SuggestedFixes: []analysis.SuggestedFix{{ + Message: "Remove self-assignment", + TextEdits: edits, + }}, + }) }) return nil, nil diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 25c98a97..ed2284e6 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -153,7 +153,8 @@ func isLocalType(pass *analysis.Pass, typ types.Type) bool { return isLocalType(pass, x.Elem()) case interface{ Obj() *types.TypeName }: // *Named or *TypeParam (aliases were removed already) // names in package foo are local to foo_test too - return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") + return x.Obj().Pkg() != nil && + strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") } return false } diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go index ba94fd68..ff9c8b4f 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go @@ -28,9 +28,9 @@ var Analyzer = &analysis.Analyzer{ // Per-architecture checks for instructions. // Assume comments, leading and trailing spaces are removed. type arch struct { - isFPWrite func(string) bool - isFPRead func(string) bool - isBranch func(string) bool + isFPWrite func(string) bool + isFPRead func(string) bool + isUnconditionalBranch func(string) bool } var re = regexp.MustCompile @@ -48,8 +48,8 @@ var arches = map[string]arch{ "amd64": { isFPWrite: re(`,\s*BP$`).MatchString, // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely. isFPRead: re(`\bBP\b`).MatchString, - isBranch: func(s string) bool { - return hasAnyPrefix(s, "J", "RET") + isUnconditionalBranch: func(s string) bool { + return hasAnyPrefix(s, "JMP", "RET") }, }, "arm64": { @@ -70,49 +70,16 @@ var arches = map[string]arch{ return false }, isFPRead: re(`\bR29\b`).MatchString, - isBranch: func(s string) bool { + isUnconditionalBranch: func(s string) bool { // Get just the instruction if i := strings.IndexFunc(s, unicode.IsSpace); i > 0 { s = s[:i] } - return arm64Branch[s] + return s == "B" || s == "JMP" || s == "RET" }, }, } -// arm64 has many control flow instructions. -// ^(B|RET) isn't sufficient or correct (e.g. BIC, BFI aren't control flow.) -// It's easier to explicitly enumerate them in a map than to write a regex. -// Borrowed from Go tree, cmd/asm/internal/arch/arm64.go -var arm64Branch = map[string]bool{ - "B": true, - "BL": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CBZ": true, - "CBZW": true, - "CBNZ": true, - "CBNZW": true, - "JMP": true, - "TBNZ": true, - "TBZ": true, - "RET": true, -} - func run(pass *analysis.Pass) (any, error) { arch, ok := arches[build.Default.GOARCH] if !ok { @@ -164,7 +131,7 @@ func run(pass *analysis.Pass) (any, error) { active = false continue } - if arch.isFPRead(line) || arch.isBranch(line) { + if arch.isFPRead(line) || arch.isUnconditionalBranch(line) { active = false continue } diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go index 64df1b10..2580a0ac 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go @@ -88,7 +88,7 @@ func run(pass *analysis.Pass) (any, error) { // // TODO: consider allowing the "last" go/defer/Go statement to be followed by // N "trivial" statements, possibly under a recursive definition of "trivial" - // so that that checker could, for example, conclude that a go statement is + // so that checker could, for example, conclude that a go statement is // followed by an if statement made of only trivial statements and trivial expressions, // and hence the go statement could still be checked. forEachLastStmt(body.List, func(last ast.Stmt) { diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index a28ed365..159a95ae 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/internal/analysisinternal" + "golang.org/x/tools/internal/astutil" "golang.org/x/tools/internal/fmtstr" "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/versions" @@ -540,7 +541,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", name) + pass.ReportRangef(call.Args[firstArg], "%s call has arguments but no formatting directives", name) } return } @@ -552,7 +553,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C if err != nil { // All error messages are in predicate form ("call has a problem") // so that they may be affixed into a subject ("log.Printf "). - pass.ReportRangef(call.Args[idx], "%s %s", name, err) + pass.ReportRangef(formatArg, "%s %s", name, err) return } @@ -560,20 +561,21 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C maxArgIndex := firstArg - 1 anyIndex := false // Check formats against args. - for _, operation := range operations { - if operation.Prec.Index != -1 || - operation.Width.Index != -1 || - operation.Verb.Index != -1 { + for _, op := range operations { + if op.Prec.Index != -1 || + op.Width.Index != -1 || + op.Verb.Index != -1 { anyIndex = true } - if !okPrintfArg(pass, call, &maxArgIndex, firstArg, name, operation) { + rng := opRange(formatArg, op) + if !okPrintfArg(pass, call, rng, &maxArgIndex, firstArg, name, op) { // One error per format is enough. return } - if operation.Verb.Verb == 'w' { + if op.Verb.Verb == 'w' { switch kind { case KindNone, KindPrint, KindPrintf: - pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", name) + pass.ReportRangef(rng, "%s does not support error-wrapping directive %%w", name) return } } @@ -594,6 +596,18 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C } } +// opRange returns the source range for the specified printf operation, +// such as the position of the %v substring of "...%v...". +func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range { + if lit, ok := formatArg.(*ast.BasicLit); ok { + start, end, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End) + if err == nil { + return analysisinternal.Range(start, end) // position of "%v" + } + } + return formatArg // entire format string +} + // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask. type printfArgType int @@ -657,7 +671,7 @@ var printVerbs = []printVerb{ // okPrintfArg compares the operation to the arguments actually present, // reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index. // If the final argument is ellipsissed, there's little it can do for that. -func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { +func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { verb := operation.Verb.Verb var v printVerb found := false @@ -680,7 +694,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if !formatter { if !found { - pass.ReportRangef(call, "%s format %s has unknown verb %c", name, operation.Text, verb) + pass.ReportRangef(rng, "%s format %s has unknown verb %c", name, operation.Text, verb) return false } for _, flag := range operation.Flags { @@ -690,7 +704,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs continue } if !strings.ContainsRune(v.flags, rune(flag)) { - pass.ReportRangef(call, "%s format %s has unrecognized flag %c", name, operation.Text, flag) + pass.ReportRangef(rng, "%s format %s has unrecognized flag %c", name, operation.Text, flag) return false } } @@ -707,7 +721,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // If len(argIndexes)>0, we have something like %.*s and all // indexes in argIndexes must be an integer. for _, argIndex := range argIndexes { - if !argCanBeChecked(pass, call, argIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, argIndex, firstArg, operation, name) { return } arg := call.Args[argIndex] @@ -716,7 +730,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) + pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) return false } } @@ -738,12 +752,12 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // Now check verb's type. verbArgIndex := operation.Verb.ArgIndex - if !argCanBeChecked(pass, call, verbArgIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, verbArgIndex, firstArg, operation, name) { return false } arg := call.Args[verbArgIndex] if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' { - pass.ReportRangef(call, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) + pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) return false } if reason, ok := matchArgType(pass, v.typ, arg); !ok { @@ -755,12 +769,14 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) + pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) return false } - if v.typ&argString != 0 && v.verb != 'T' && !strings.Contains(operation.Flags, "#") { + // Detect recursive formatting via value's String/Error methods. + // The '#' flag suppresses the methods, except with %x, %X, and %q. + if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) { if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) + pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) return false } } @@ -844,7 +860,7 @@ func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { // argCanBeChecked reports whether the specified argument is statically present; // it may be beyond the list of arguments or in a terminal slice... argument, which // means we can't see it. -func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { +func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { if argIndex <= 0 { // Shouldn't happen, so catch it with prejudice. panic("negative argIndex") @@ -861,7 +877,7 @@ func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg // There are bad indexes in the format or there are fewer arguments than the format needs. // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". arg := argIndex - firstArg + 1 // People think of arguments as 1-indexed. - pass.ReportRangef(call, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) + pass.ReportRangef(rng, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) return false } diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index a23721cd..7dbff1e4 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/typesinternal" ) //go:embed doc.go @@ -60,12 +61,11 @@ func describe(typ, inType types.Type, inName string) string { } func typeName(t types.Type) string { - type hasTypeName interface{ Obj() *types.TypeName } // Alias, Named, TypeParam - switch t := t.(type) { - case *types.Basic: - return t.Name() - case hasTypeName: - return t.Obj().Name() + if basic, ok := t.(*types.Basic); ok { + return basic.Name() // may be (e.g.) "untyped int", which has no TypeName + } + if tname := typesinternal.TypeNameFor(t); tname != nil { + return tname.Name() } return "" } diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go index 13a99973..cc90f733 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go @@ -107,7 +107,7 @@ func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, s // Embedded struct. Nothing to do for now, but that // may change, depending on what happens with issue 7363. - // TODO(adonovan): investigate, now that that issue is fixed. + // TODO(adonovan): investigate, now that issue is fixed. if field.Anonymous() { return } diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 9f59006e..d4e9b025 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -447,18 +447,6 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { } } -type tokenRange struct { - p, e token.Pos -} - -func (r tokenRange) Pos() token.Pos { - return r.p -} - -func (r tokenRange) End() token.Pos { - return r.e -} - func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { // Want functions with 0 results and 1 parameter. if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || @@ -476,8 +464,9 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 { // Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters. // We have currently decided to also warn before compilation/package loading. This can help users in IDEs. - at := tokenRange{tparams.Opening, tparams.Closing} - pass.ReportRangef(at, "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix) + pass.ReportRangef(analysisinternal.Range(tparams.Opening, tparams.Closing), + "%s has type parameters: it will not be run by go test as a %sXXX function", + fn.Name.Name, prefix) } if !isTestSuffix(fn.Name.Name[len(prefix):]) { diff --git a/history-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/history-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index 932f1347..556ffed7 100644 --- a/history-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/history-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -26,6 +26,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/analysisinternal" ) //go:embed doc.go @@ -59,23 +60,62 @@ func init() { // The context.With{Cancel,Deadline,Timeout} entries are // effectively redundant wrt the lostcancel analyzer. funcs = stringSetFlag{ - "context.WithCancel": true, - "context.WithDeadline": true, - "context.WithTimeout": true, - "context.WithValue": true, - "errors.New": true, - "fmt.Errorf": true, - "fmt.Sprint": true, - "fmt.Sprintf": true, - "slices.Clip": true, - "slices.Compact": true, - "slices.CompactFunc": true, - "slices.Delete": true, - "slices.DeleteFunc": true, - "slices.Grow": true, - "slices.Insert": true, - "slices.Replace": true, - "sort.Reverse": true, + "context.WithCancel": true, + "context.WithDeadline": true, + "context.WithTimeout": true, + "context.WithValue": true, + "errors.New": true, + "fmt.Append": true, + "fmt.Appendf": true, + "fmt.Appendln": true, + "fmt.Errorf": true, + "fmt.Sprint": true, + "fmt.Sprintf": true, + "fmt.Sprintln": true, + "maps.All": true, + "maps.Clone": true, + "maps.Collect": true, + "maps.Equal": true, + "maps.EqualFunc": true, + "maps.Keys": true, + "maps.Values": true, + "slices.All": true, + "slices.AppendSeq": true, + "slices.Backward": true, + "slices.BinarySearch": true, + "slices.BinarySearchFunc": true, + "slices.Chunk": true, + "slices.Clip": true, + "slices.Clone": true, + "slices.Collect": true, + "slices.Compact": true, + "slices.CompactFunc": true, + "slices.Compare": true, + "slices.CompareFunc": true, + "slices.Concat": true, + "slices.Contains": true, + "slices.ContainsFunc": true, + "slices.Delete": true, + "slices.DeleteFunc": true, + "slices.Equal": true, + "slices.EqualFunc": true, + "slices.Grow": true, + "slices.Index": true, + "slices.IndexFunc": true, + "slices.Insert": true, + "slices.IsSorted": true, + "slices.IsSortedFunc": true, + "slices.Max": true, + "slices.MaxFunc": true, + "slices.Min": true, + "slices.MinFunc": true, + "slices.Repeat": true, + "slices.Replace": true, + "slices.Sorted": true, + "slices.SortedFunc": true, + "slices.SortedStableFunc": true, + "slices.Values": true, + "sort.Reverse": true, } Analyzer.Flags.Var(&funcs, "funcs", "comma-separated list of functions whose results must be used") @@ -114,14 +154,16 @@ func run(pass *analysis.Pass) (any, error) { // method (e.g. foo.String()) if types.Identical(sig, sigNoArgsStringResult) { if stringMethods[fn.Name()] { - pass.Reportf(call.Lparen, "result of (%s).%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of (%s).%s call not used", sig.Recv().Type(), fn.Name()) } } } else { // package-level function (e.g. fmt.Errorf) if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] { - pass.Reportf(call.Lparen, "result of %s.%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of %s.%s call not used", fn.Pkg().Path(), fn.Name()) } } diff --git a/history-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/history-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6e34df46..0fb4e7ee 100644 --- a/history-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/history-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -113,7 +113,7 @@ func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Nod // childrenOf elides the FuncType node beneath FuncDecl. // Add it back here for TypeParams, Params, Results, // all FieldLists). But we don't add it back for the "func" token - // even though it is is the tree at FuncDecl.Type.Func. + // even though it is the tree at FuncDecl.Type.Func. if decl, ok := node.(*ast.FuncDecl); ok { if fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv { path = append(path, decl.Type) @@ -207,6 +207,9 @@ func childrenOf(n ast.Node) []ast.Node { return false // no recursion }) + // TODO(adonovan): be more careful about missing (!Pos.Valid) + // tokens in trees produced from invalid input. + // Then add fake Nodes for bare tokens. switch n := n.(type) { case *ast.ArrayType: @@ -226,9 +229,12 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) + if n.Lbrace.IsValid() { + children = append(children, tok(n.Lbrace, len("{"))) + } + if n.Rbrace.IsValid() { + children = append(children, tok(n.Rbrace, len("}"))) + } case *ast.BranchStmt: children = append(children, @@ -304,9 +310,12 @@ func childrenOf(n ast.Node) []ast.Node { // TODO(adonovan): Field.{Doc,Comment,Tag}? case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), // or len("[") - tok(n.Closing, len(")"))) // or len("]") + if n.Opening.IsValid() { + children = append(children, tok(n.Opening, len("("))) + } + if n.Closing.IsValid() { + children = append(children, tok(n.Closing, len(")"))) + } case *ast.File: // TODO test: Doc diff --git a/history-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/history-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index 5c8dbbb7..4ad05493 100644 --- a/history-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/history-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -67,6 +67,10 @@ var abort = new(int) // singleton, to signal termination of Apply // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. +// +// This type is not to be confused with [inspector.Cursor] from +// package [golang.org/x/tools/go/ast/inspector], which provides +// stateless navigation of immutable syntax trees. type Cursor struct { parent ast.Node name string diff --git a/history-api/vendor/golang.org/x/tools/internal/astutil/edge/edge.go b/history-api/vendor/golang.org/x/tools/go/ast/edge/edge.go similarity index 100% rename from history-api/vendor/golang.org/x/tools/internal/astutil/edge/edge.go rename to history-api/vendor/golang.org/x/tools/go/ast/edge/edge.go diff --git a/history-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/history-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go new file mode 100644 index 00000000..31c8d2f2 --- /dev/null +++ b/history-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go @@ -0,0 +1,502 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package inspector + +import ( + "fmt" + "go/ast" + "go/token" + "iter" + "reflect" + + "golang.org/x/tools/go/ast/edge" +) + +// A Cursor represents an [ast.Node]. It is immutable. +// +// Two Cursors compare equal if they represent the same node. +// +// Call [Inspector.Root] to obtain a valid cursor for the virtual root +// node of the traversal. +// +// Use the following methods to navigate efficiently around the tree: +// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing]; +// - for children, use [Cursor.Child], [Cursor.Children], +// [Cursor.FirstChild], and [Cursor.LastChild]; +// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling]; +// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode], +// [Cursor.Inspect], and [Cursor.Preorder]. +// +// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for +// information about the edges in a tree: which field (and slice +// element) of the parent node holds the child. +type Cursor struct { + in *Inspector + index int32 // index of push node; -1 for virtual root node +} + +// Root returns a cursor for the virtual root node, +// whose children are the files provided to [New]. +// +// Its [Cursor.Node] and [Cursor.Stack] methods return nil. +func (in *Inspector) Root() Cursor { + return Cursor{in, -1} +} + +// At returns the cursor at the specified index in the traversal, +// which must have been obtained from [Cursor.Index] on a Cursor +// belonging to the same Inspector (see [Cursor.Inspector]). +func (in *Inspector) At(index int32) Cursor { + if index < 0 { + panic("negative index") + } + if int(index) >= len(in.events) { + panic("index out of range for this inspector") + } + if in.events[index].index < index { + panic("invalid index") // (a push, not a pop) + } + return Cursor{in, index} +} + +// Inspector returns the cursor's Inspector. +func (c Cursor) Inspector() *Inspector { return c.in } + +// Index returns the index of this cursor position within the package. +// +// Clients should not assume anything about the numeric Index value +// except that it increases monotonically throughout the traversal. +// It is provided for use with [At]. +// +// Index must not be called on the Root node. +func (c Cursor) Index() int32 { + if c.index < 0 { + panic("Index called on Root node") + } + return c.index +} + +// Node returns the node at the current cursor position, +// or nil for the cursor returned by [Inspector.Root]. +func (c Cursor) Node() ast.Node { + if c.index < 0 { + return nil + } + return c.in.events[c.index].node +} + +// String returns information about the cursor's node, if any. +func (c Cursor) String() string { + if c.in == nil { + return "(invalid)" + } + if c.index < 0 { + return "(root)" + } + return reflect.TypeOf(c.Node()).String() +} + +// indices return the [start, end) half-open interval of event indices. +func (c Cursor) indices() (int32, int32) { + if c.index < 0 { + return 0, int32(len(c.in.events)) // root: all events + } else { + return c.index, c.in.events[c.index].index + 1 // just one subtree + } +} + +// Preorder returns an iterator over the nodes of the subtree +// represented by c in depth-first order. Each node in the sequence is +// represented by a Cursor that allows access to the Node, but may +// also be used to start a new traversal, or to obtain the stack of +// nodes enclosing the cursor. +// +// The traversal sequence is determined by [ast.Inspect]. The types +// argument, if non-empty, enables type-based filtering of events. The +// function f if is called only for nodes whose type matches an +// element of the types slice. +// +// If you need control over descent into subtrees, +// or need both pre- and post-order notifications, use [Cursor.Inspect] +func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain types: skip. + i = pop + 1 + continue + } + } + i++ + } + } +} + +// Inspect visits the nodes of the subtree represented by c in +// depth-first order. It calls f(n) for each node n before it +// visits n's children. If f returns true, Inspect invokes f +// recursively for each of the non-nil children of the node. +// +// Each node is represented by a Cursor that allows access to the +// Node, but may also be used to start a new traversal, or to obtain +// the stack of nodes enclosing the cursor. +// +// The complete traversal sequence is determined by [ast.Inspect]. +// The types argument, if non-empty, enables type-based filtering of +// events. The function f if is called only for nodes whose type +// matches an element of the types slice. +func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { + mask := maskOf(types) + events := c.in.events + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { + // push + pop := ev.index + if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || + events[pop].typ&mask == 0 { + // The user opted not to descend, or the + // subtree does not contain types: + // skip past the pop. + i = pop + 1 + continue + } + } + i++ + } +} + +// Enclosing returns an iterator over the nodes enclosing the current +// current node, starting with the Cursor itself. +// +// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// The types argument, if non-empty, enables type-based filtering of +// events: the sequence includes only enclosing nodes whose type +// matches an element of the types slice. +func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { + if c.index < 0 { + panic("Cursor.Enclosing called on Root node") + } + + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + for i := c.index; i >= 0; i = events[i].parent { + if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + } + } +} + +// Parent returns the parent of the current node. +// +// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Parent() Cursor { + if c.index < 0 { + panic("Cursor.Parent called on Root node") + } + + return Cursor{c.in, c.in.events[c.index].parent} +} + +// ParentEdge returns the identity of the field in the parent node +// that holds this cursor's node, and if it is a list, the index within it. +// +// For example, f(x, y) is a CallExpr whose three children are Idents. +// f has edge kind [edge.CallExpr_Fun] and index -1. +// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. +// +// If called on a child of the Root node, it returns ([edge.Invalid], -1). +// +// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) ParentEdge() (edge.Kind, int) { + if c.index < 0 { + panic("Cursor.ParentEdge called on Root node") + } + events := c.in.events + pop := events[c.index].index + return unpackEdgeKindAndIndex(events[pop].parent) +} + +// ChildAt returns the cursor for the child of the +// current node identified by its edge and index. +// The index must be -1 if the edge.Kind is not a slice. +// The indicated child node must exist. +// +// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. +func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { + target := packEdgeKindAndIndex(k, idx) + + // Unfortunately there's no shortcut to looping. + events := c.in.events + i := c.index + 1 + for { + pop := events[i].index + if pop < i { + break + } + if events[pop].parent == target { + return Cursor{c.in, i} + } + i = pop + 1 + } + panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) +} + +// Child returns the cursor for n, which must be a direct child of c's Node. +// +// Child must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Child(n ast.Node) Cursor { + if c.index < 0 { + panic("Cursor.Child called on Root node") + } + + if false { + // reference implementation + for child := range c.Children() { + if child.Node() == n { + return child + } + } + + } else { + // optimized implementation + events := c.in.events + for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { + if events[i].node == n { + return Cursor{c.in, i} + } + } + } + panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) +} + +// NextSibling returns the cursor for the next sibling node in the same list +// (for example, of files, decls, specs, statements, fields, or expressions) as +// the current node. It returns (zero, false) if the node is the last node in +// the list, or is not part of a list. +// +// NextSibling must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) NextSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.NextSibling called on Root node") + } + + events := c.in.events + i := events[c.index].index + 1 // after corresponding pop + if i < int32(len(events)) { + if events[i].index > i { // push? + return Cursor{c.in, i}, true + } + } + return Cursor{}, false +} + +// PrevSibling returns the cursor for the previous sibling node in the +// same list (for example, of files, decls, specs, statements, fields, +// or expressions) as the current node. It returns zero if the node is +// the first node in the list, or is not part of a list. +// +// It must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) PrevSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.PrevSibling called on Root node") + } + + events := c.in.events + i := c.index - 1 + if i >= 0 { + if j := events[i].index; j < i { // pop? + return Cursor{c.in, j}, true + } + } + return Cursor{}, false +} + +// FirstChild returns the first direct child of the current node, +// or zero if it has no children. +func (c Cursor) FirstChild() (Cursor, bool) { + events := c.in.events + i := c.index + 1 // i=0 if c is root + if i < int32(len(events)) && events[i].index > i { // push? + return Cursor{c.in, i}, true + } + return Cursor{}, false +} + +// LastChild returns the last direct child of the current node, +// or zero if it has no children. +func (c Cursor) LastChild() (Cursor, bool) { + events := c.in.events + if c.index < 0 { // root? + if len(events) > 0 { + // return push of final event (a pop) + return Cursor{c.in, events[len(events)-1].index}, true + } + } else { + j := events[c.index].index - 1 // before corresponding pop + // Inv: j == c.index if c has no children + // or j is last child's pop. + if j > c.index { // c has children + return Cursor{c.in, events[j].index}, true + } + } + return Cursor{}, false +} + +// Children returns an iterator over the direct children of the +// current node, if any. +// +// When using Children, NextChild, and PrevChild, bear in mind that a +// Node's children may come from different fields, some of which may +// be lists of nodes without a distinguished intervening container +// such as [ast.BlockStmt]. +// +// For example, [ast.CaseClause] has a field List of expressions and a +// field Body of statements, so the children of a CaseClause are a mix +// of expressions and statements. Other nodes that have "uncontained" +// list fields include: +// +// - [ast.ValueSpec] (Names, Values) +// - [ast.CompositeLit] (Type, Elts) +// - [ast.IndexListExpr] (X, Indices) +// - [ast.CallExpr] (Fun, Args) +// - [ast.AssignStmt] (Lhs, Rhs) +// +// So, do not assume that the previous sibling of an ast.Stmt is also +// an ast.Stmt, or if it is, that they are executed sequentially, +// unless you have established that, say, its parent is a BlockStmt +// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. +// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, +// even though they are not executed in sequence. +func (c Cursor) Children() iter.Seq[Cursor] { + return func(yield func(Cursor) bool) { + c, ok := c.FirstChild() + for ok && yield(c) { + c, ok = c.NextSibling() + } + } +} + +// Contains reports whether c contains or is equal to c2. +// +// Both Cursors must belong to the same [Inspector]; +// neither may be its Root node. +func (c Cursor) Contains(c2 Cursor) bool { + if c.in != c2.in { + panic("different inspectors") + } + events := c.in.events + return c.index <= c2.index && events[c2.index].index <= events[c.index].index +} + +// FindNode returns the cursor for node n if it belongs to the subtree +// rooted at c. It returns zero if n is not found. +func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { + + // FindNode is equivalent to this code, + // but more convenient and 15-20% faster: + if false { + for candidate := range c.Preorder(n) { + if candidate.Node() == n { + return candidate, true + } + } + return Cursor{}, false + } + + // TODO(adonovan): opt: should we assume Node.Pos is accurate + // and combine type-based filtering with position filtering + // like FindByPos? + + mask := maskOf([]ast.Node{n}) + events := c.in.events + + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && ev.node == n { + return Cursor{c.in, i}, true + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain type of n: skip. + i = pop + } + } + } + return Cursor{}, false +} + +// FindByPos returns the cursor for the innermost node n in the tree +// rooted at c such that n.Pos() <= start && end <= n.End(). +// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) +// +// It returns zero if none is found. +// Precondition: start <= end. +// +// See also [astutil.PathEnclosingInterval], which +// tolerates adjoining whitespace. +func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { + if end < start { + panic("end < start") + } + events := c.in.events + + // This algorithm could be implemented using c.Inspect, + // but it is about 2.5x slower. + + best := int32(-1) // push index of latest (=innermost) node containing range + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + n := ev.node + var nodeEnd token.Pos + if file, ok := n.(*ast.File); ok { + nodeEnd = file.FileEnd + // Note: files may be out of Pos order. + if file.FileStart > start { + i = ev.index // disjoint, after; skip to next file + continue + } + } else { + nodeEnd = n.End() + if n.Pos() > start { + break // disjoint, after; stop + } + } + // Inv: node.{Pos,FileStart} <= start + if end <= nodeEnd { + // node fully contains target range + best = i + } else if nodeEnd < start { + i = ev.index // disjoint, before; skip forward + } + } + } + if best >= 0 { + return Cursor{c.in, best}, true + } + return Cursor{}, false +} diff --git a/history-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/history-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go index 674490a6..a703cdfc 100644 --- a/history-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go +++ b/history-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go @@ -13,10 +13,19 @@ // This representation is sometimes called a "balanced parenthesis tree." // // Experiments suggest the inspector's traversals are about 2.5x faster -// than ast.Inspect, but it may take around 5 traversals for this +// than [ast.Inspect], but it may take around 5 traversals for this // benefit to amortize the inspector's construction cost. // If efficiency is the primary concern, do not use Inspector for // one-off traversals. +// +// The [Cursor] type provides a more flexible API for efficient +// navigation of syntax trees in all four "cardinal directions". For +// example, traversals may be nested, so you can find each node of +// type A and then search within it for nodes of type B. Or you can +// traverse from a node to its immediate neighbors: its parent, its +// previous and next sibling, or its first and last child. We +// recommend using methods of Cursor in preference to Inspector where +// possible. package inspector // There are four orthogonal features in a traversal: @@ -37,9 +46,8 @@ package inspector import ( "go/ast" - _ "unsafe" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) // An Inspector provides methods for inspecting @@ -48,18 +56,12 @@ type Inspector struct { events []event } -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *Inspector) []event { return in.events } - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex func packEdgeKindAndIndex(ek edge.Kind, index int) int32 { return int32(uint32(index+1)<<7 | uint32(ek)) } // unpackEdgeKindAndIndex unpacks the edge kind and edge index (within // an []ast.Node slice) from the parent field of a pop event. -// -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) { // The "parent" field of a pop node holds the // edge Kind in the lower 7 bits and the index+1 @@ -83,15 +85,21 @@ type event struct { // TODO: Experiment with storing only the second word of event.node (unsafe.Pointer). // Type can be recovered from the sole bit in typ. +// [Tried this, wasn't faster. --adonovan] // Preorder visits all the nodes of the files supplied to New in // depth-first order. It calls f(n) for each node n before it visits // n's children. // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Preorder] method provides a richer alternative interface. +// Example: +// +// for c := range in.Root().Preorder(types) { ... } func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // Because it avoids postorder calls to f, and the pruning // check, Preorder is almost twice as fast as Nodes. The two @@ -131,10 +139,18 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // of the non-nil children of the node, followed by a call of // f(n, false). // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f if is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// ... +// return true +// } func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) { mask := maskOf(types) for i := int32(0); i < int32(len(in.events)); { @@ -168,6 +184,15 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proc // supplies each call to f an additional argument, the current // traversal stack. The stack's first element is the outermost node, // an *ast.File; its last is the innermost, n. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// stack := slices.Collect(c.Enclosing()) +// ... +// return true +// }) func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) { mask := maskOf(types) var stack []ast.Node @@ -233,7 +258,7 @@ type visitor struct { type item struct { index int32 // index of current node's push event parentIndex int32 // index of parent node's push event - typAccum uint64 // accumulated type bits of current node's descendents + typAccum uint64 // accumulated type bits of current node's descendants edgeKindAndIndex int32 // edge.Kind and index, bit packed } diff --git a/history-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/history-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index e936c67c..9852331a 100644 --- a/history-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/history-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - _ "unsafe" ) const ( @@ -217,7 +215,6 @@ func typeOf(n ast.Node) uint64 { return 0 } -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf func maskOf(nodes []ast.Node) uint64 { if len(nodes) == 0 { return math.MaxUint64 // match all node types diff --git a/history-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go b/history-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go index 5a42174a..5f1c93c8 100644 --- a/history-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go +++ b/history-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go @@ -13,7 +13,7 @@ import ( "fmt" "go/ast" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) { diff --git a/history-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go b/history-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go index 26225e7d..f66f4c73 100644 --- a/history-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go +++ b/history-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go @@ -658,7 +658,7 @@ func (b *builder) call(c ssa.CallInstruction) { } func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) { - // When f has no paremeters (including receiver), there is no type + // When f has no parameters (including receiver), there is no type // flow here. Also, f's body and parameters might be missing, such // as when vta is used within the golang.org/x/tools/go/analysis // framework (see github.com/golang/go/issues/50670). @@ -803,7 +803,7 @@ func (b *builder) nodeFromVal(val ssa.Value) node { return function{f: v} case *ssa.Parameter, *ssa.FreeVar, ssa.Instruction: // ssa.Param, ssa.FreeVar, and a specific set of "register" instructions, - // satisifying the ssa.Value interface, can serve as local variables. + // satisfying the ssa.Value interface, can serve as local variables. return local{val: v} default: panic(fmt.Errorf("unsupported value %v in node creation", val)) diff --git a/history-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go b/history-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go index bdd39397..adef1282 100644 --- a/history-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go +++ b/history-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go @@ -245,7 +245,7 @@ func (b *Builder) create(leaves []*leaf) node { } else if n == 1 { return leaves[0] } - // Note: we can do a more sophisicated algorithm by: + // Note: we can do a more sophisticated algorithm by: // - sorting the leaves ahead of time, // - taking the prefix and branching bit of the min and max key, // - binary searching for the branching bit, diff --git a/history-api/vendor/golang.org/x/tools/go/loader/doc.go b/history-api/vendor/golang.org/x/tools/go/loader/doc.go index e35b1fd7..769a1fcf 100644 --- a/history-api/vendor/golang.org/x/tools/go/loader/doc.go +++ b/history-api/vendor/golang.org/x/tools/go/loader/doc.go @@ -164,7 +164,7 @@ package loader // entry is created in this cache by startLoad the first time the // package is imported. The first goroutine to request an entry becomes // responsible for completing the task and broadcasting completion to -// subsequent requestors, which block until then. +// subsequent requesters, which block until then. // // Type checking occurs in (parallel) postorder: we cannot type-check a // set of files until we have loaded and type-checked all of their diff --git a/history-api/vendor/golang.org/x/tools/go/packages/doc.go b/history-api/vendor/golang.org/x/tools/go/packages/doc.go index f1931d10..366aab6b 100644 --- a/history-api/vendor/golang.org/x/tools/go/packages/doc.go +++ b/history-api/vendor/golang.org/x/tools/go/packages/doc.go @@ -76,6 +76,8 @@ uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. +See also [golang.org/x/tools/go/packages/internal/linecount] +for an example application. # The driver protocol diff --git a/history-api/vendor/golang.org/x/tools/go/packages/golist.go b/history-api/vendor/golang.org/x/tools/go/packages/golist.go index 96e43cd8..89f89dd2 100644 --- a/history-api/vendor/golang.org/x/tools/go/packages/golist.go +++ b/history-api/vendor/golang.org/x/tools/go/packages/golist.go @@ -224,13 +224,22 @@ extractQueries: return response.dr, nil } +// abs returns an absolute representation of path, based on cfg.Dir. +func (cfg *Config) abs(path string) (string, error) { + if filepath.IsAbs(path) { + return path, nil + } + // In case cfg.Dir is relative, pass it to filepath.Abs. + return filepath.Abs(filepath.Join(cfg.Dir, path)) +} + func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { for _, query := range queries { // TODO(matloob): Do only one query per directory. fdir := filepath.Dir(query) // Pass absolute path of directory to go list so that it knows to treat it as a directory, // not a package path. - pattern, err := filepath.Abs(fdir) + pattern, err := state.cfg.abs(fdir) if err != nil { return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err) } @@ -703,9 +712,8 @@ func (state *golistState) getGoVersion() (int, error) { // getPkgPath finds the package path of a directory if it's relative to a root // directory. func (state *golistState) getPkgPath(dir string) (string, bool, error) { - absDir, err := filepath.Abs(dir) - if err != nil { - return "", false, err + if !filepath.IsAbs(dir) { + panic("non-absolute dir passed to getPkgPath") } roots, err := state.determineRootDirs() if err != nil { @@ -715,7 +723,7 @@ func (state *golistState) getPkgPath(dir string) (string, bool, error) { for rdir, rpath := range roots { // Make sure that the directory is in the module, // to avoid creating a path relative to another module. - if !strings.HasPrefix(absDir, rdir) { + if !strings.HasPrefix(dir, rdir) { continue } // TODO(matloob): This doesn't properly handle symlinks. diff --git a/history-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/history-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go index d823c474..d9d5a45c 100644 --- a/history-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/history-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -55,7 +55,7 @@ func (state *golistState) determineRootDirsModules() (map[string]string, error) } if mod.Dir != "" && mod.Path != "" { // This is a valid module; add it to the map. - absDir, err := filepath.Abs(mod.Dir) + absDir, err := state.cfg.abs(mod.Dir) if err != nil { return nil, err } diff --git a/history-api/vendor/golang.org/x/tools/go/ssa/builder.go b/history-api/vendor/golang.org/x/tools/go/ssa/builder.go index 84ccbc09..a5ef8fb4 100644 --- a/history-api/vendor/golang.org/x/tools/go/ssa/builder.go +++ b/history-api/vendor/golang.org/x/tools/go/ssa/builder.go @@ -25,7 +25,7 @@ package ssa // populating fields such as Function.Body, .Params, and others. // // Building may create additional methods, including: -// - wrapper methods (e.g. for embeddding, or implicit &recv) +// - wrapper methods (e.g. for embedding, or implicit &recv) // - bound method closures (e.g. for use(recv.f)) // - thunks (e.g. for use(I.f) or use(T.f)) // - generic instances (e.g. to produce f[int] from f[any]). @@ -138,7 +138,7 @@ type builder struct { finished int // finished is the length of the prefix of fns containing built functions. // The task of building shared functions within the builder. - // Shared functions are ones the the builder may either create or lookup. + // Shared functions are ones the builder may either create or lookup. // These may be built by other builders in parallel. // The task is done when the builder has finished iterating, and it // waits for all shared functions to finish building. @@ -2920,6 +2920,9 @@ func (b *builder) buildParamsOnly(fn *Function) { for i, n := 0, params.Len(); i < n; i++ { fn.addParamVar(params.At(i)) } + + // clear out other function state (keep consistent with finishBody) + fn.subst = nil } // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. diff --git a/history-api/vendor/golang.org/x/tools/go/ssa/func.go b/history-api/vendor/golang.org/x/tools/go/ssa/func.go index 2d52309b..f48bd718 100644 --- a/history-api/vendor/golang.org/x/tools/go/ssa/func.go +++ b/history-api/vendor/golang.org/x/tools/go/ssa/func.go @@ -386,6 +386,8 @@ func (f *Function) finishBody() { f.results = nil // (used by lifting) f.deferstack = nil // (used by lifting) f.vars = nil // (used by lifting) + + // clear out other function state (keep consistent with buildParamsOnly) f.subst = nil numberRegisters(f) // uses f.namedRegisters diff --git a/history-api/vendor/golang.org/x/tools/go/ssa/sanity.go b/history-api/vendor/golang.org/x/tools/go/ssa/sanity.go index b11680a1..c47a137c 100644 --- a/history-api/vendor/golang.org/x/tools/go/ssa/sanity.go +++ b/history-api/vendor/golang.org/x/tools/go/ssa/sanity.go @@ -27,9 +27,10 @@ type sanity struct { } // sanityCheck performs integrity checking of the SSA representation -// of the function fn and returns true if it was valid. Diagnostics -// are written to reporter if non-nil, os.Stderr otherwise. Some -// diagnostics are only warnings and do not imply a negative result. +// of the function fn (which must have been "built") and returns true +// if it was valid. Diagnostics are written to reporter if non-nil, +// os.Stderr otherwise. Some diagnostics are only warnings and do not +// imply a negative result. // // Sanity-checking is intended to facilitate the debugging of code // transformation passes. diff --git a/history-api/vendor/golang.org/x/tools/go/ssa/subst.go b/history-api/vendor/golang.org/x/tools/go/ssa/subst.go index b4ea1685..362dce12 100644 --- a/history-api/vendor/golang.org/x/tools/go/ssa/subst.go +++ b/history-api/vendor/golang.org/x/tools/go/ssa/subst.go @@ -543,7 +543,7 @@ func (subst *subster) signature(t *types.Signature) types.Type { // We are choosing not to support tparams.Len() > 0 until a need has been observed in practice. // // There are some known usages for types.Types coming from types.{Eval,CheckExpr}. - // To support tparams.Len() > 0, we just need to do the following [psuedocode]: + // To support tparams.Len() > 0, we just need to do the following [pseudocode]: // targs := {subst.replacements[tparams[i]]]}; Instantiate(ctxt, t, targs, false) assert(tparams.Len() == 0, "Substituting types.Signatures with generic functions are currently unsupported.") diff --git a/history-api/vendor/golang.org/x/tools/go/ssa/util.go b/history-api/vendor/golang.org/x/tools/go/ssa/util.go index e53b31ff..932eb6cb 100644 --- a/history-api/vendor/golang.org/x/tools/go/ssa/util.go +++ b/history-api/vendor/golang.org/x/tools/go/ssa/util.go @@ -25,7 +25,7 @@ type unit struct{} //// Sanity checking utilities -// assert panics with the mesage msg if p is false. +// assert panics with the message msg if p is false. // Avoid combining with expensive string formatting. func assert(p bool, msg string) { if !p { diff --git a/history-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/history-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 16ed3c17..d3c2913b 100644 --- a/history-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/history-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -603,7 +603,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { type hasTypeParams interface { TypeParams() *types.TypeParamList } - // abstraction of *types.{Named,TypeParam} + // abstraction of *types.{Alias,Named,TypeParam} type hasObj interface { Obj() *types.TypeName } diff --git a/history-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/history-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index c4d10de3..e46aab02 100644 --- a/history-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/history-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -22,7 +22,6 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/cursor" "golang.org/x/tools/internal/typesinternal" ) @@ -526,7 +525,7 @@ func CanImport(from, to string) bool { func DeleteStmt(fset *token.FileSet, astFile *ast.File, stmt ast.Stmt, report func(string, ...any)) []analysis.TextEdit { // TODO: pass in the cursor to a ast.Stmt. callers should provide the Cursor insp := inspector.New([]*ast.File{astFile}) - root := cursor.Root(insp) + root := insp.Root() cstmt, ok := root.FindNode(stmt) if !ok { report("%s not found in file", stmt.Pos()) @@ -620,8 +619,8 @@ Outer: // otherwise remove the line edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()} if from.IsValid() || to.IsValid() { - // remove just the statment. - // we can't tell if there is a ; or whitespace right after the statment + // remove just the statement. + // we can't tell if there is a ; or whitespace right after the statement // ideally we'd like to remove the former and leave the latter // (if gofmt has run, there likely won't be a ;) // In type switches we know there's a semicolon somewhere after the statement, @@ -671,3 +670,14 @@ func IsStdPackage(path string) bool { } return !strings.Contains(path[:slash], ".") && path != "testdata" } + +// Range returns an [analysis.Range] for the specified start and end positions. +func Range(pos, end token.Pos) analysis.Range { + return tokenRange{pos, end} +} + +// tokenRange is an implementation of the [analysis.Range] interface. +type tokenRange struct{ StartPos, EndPos token.Pos } + +func (r tokenRange) Pos() token.Pos { return r.StartPos } +func (r tokenRange) End() token.Pos { return r.EndPos } diff --git a/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go b/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go deleted file mode 100644 index 78d874a8..00000000 --- a/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -// Package cursor augments [inspector.Inspector] with [Cursor] -// functionality allowing more flexibility and control during -// inspection. -// -// This package is a temporary private extension of inspector until -// proposal #70859 is accepted, and which point it will be moved into -// the inspector package, and [Root] will become a method of -// Inspector. -package cursor - -import ( - "fmt" - "go/ast" - "go/token" - "iter" - "reflect" - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// A Cursor represents an [ast.Node]. It is immutable. -// -// Two Cursors compare equal if they represent the same node. -// -// Call [Root] to obtain a valid cursor. -type Cursor struct { - in *inspector.Inspector - index int32 // index of push node; -1 for virtual root node -} - -// Root returns a cursor for the virtual root node, -// whose children are the files provided to [New]. -// -// Its [Cursor.Node] and [Cursor.Stack] methods return nil. -func Root(in *inspector.Inspector) Cursor { - return Cursor{in, -1} -} - -// At returns the cursor at the specified index in the traversal, -// which must have been obtained from [Cursor.Index] on a Cursor -// belonging to the same Inspector (see [Cursor.Inspector]). -func At(in *inspector.Inspector, index int32) Cursor { - if index < 0 { - panic("negative index") - } - events := events(in) - if int(index) >= len(events) { - panic("index out of range for this inspector") - } - if events[index].index < index { - panic("invalid index") // (a push, not a pop) - } - return Cursor{in, index} -} - -// Inspector returns the cursor's Inspector. -func (c Cursor) Inspector() *inspector.Inspector { return c.in } - -// Index returns the index of this cursor position within the package. -// -// Clients should not assume anything about the numeric Index value -// except that it increases monotonically throughout the traversal. -// It is provided for use with [At]. -// -// Index must not be called on the Root node. -func (c Cursor) Index() int32 { - if c.index < 0 { - panic("Index called on Root node") - } - return c.index -} - -// Node returns the node at the current cursor position, -// or nil for the cursor returned by [Inspector.Root]. -func (c Cursor) Node() ast.Node { - if c.index < 0 { - return nil - } - return c.events()[c.index].node -} - -// String returns information about the cursor's node, if any. -func (c Cursor) String() string { - if c.in == nil { - return "(invalid)" - } - if c.index < 0 { - return "(root)" - } - return reflect.TypeOf(c.Node()).String() -} - -// indices return the [start, end) half-open interval of event indices. -func (c Cursor) indices() (int32, int32) { - if c.index < 0 { - return 0, int32(len(c.events())) // root: all events - } else { - return c.index, c.events()[c.index].index + 1 // just one subtree - } -} - -// Preorder returns an iterator over the nodes of the subtree -// represented by c in depth-first order. Each node in the sequence is -// represented by a Cursor that allows access to the Node, but may -// also be used to start a new traversal, or to obtain the stack of -// nodes enclosing the cursor. -// -// The traversal sequence is determined by [ast.Inspect]. The types -// argument, if non-empty, enables type-based filtering of events. The -// function f if is called only for nodes whose type matches an -// element of the types slice. -// -// If you need control over descent into subtrees, -// or need both pre- and post-order notifications, use [Cursor.Inspect] -func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain types: skip. - i = pop + 1 - continue - } - } - i++ - } - } -} - -// Inspect visits the nodes of the subtree represented by c in -// depth-first order. It calls f(n) for each node n before it -// visits n's children. If f returns true, Inspect invokes f -// recursively for each of the non-nil children of the node. -// -// Each node is represented by a Cursor that allows access to the -// Node, but may also be used to start a new traversal, or to obtain -// the stack of nodes enclosing the cursor. -// -// The complete traversal sequence is determined by [ast.Inspect]. -// The types argument, if non-empty, enables type-based filtering of -// events. The function f if is called only for nodes whose type -// matches an element of the types slice. -func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { - mask := maskOf(types) - events := c.events() - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { - // push - pop := ev.index - if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || - events[pop].typ&mask == 0 { - // The user opted not to descend, or the - // subtree does not contain types: - // skip past the pop. - i = pop + 1 - continue - } - } - i++ - } -} - -// Enclosing returns an iterator over the nodes enclosing the current -// current node, starting with the Cursor itself. -// -// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// The types argument, if non-empty, enables type-based filtering of -// events: the sequence includes only enclosing nodes whose type -// matches an element of the types slice. -func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { - if c.index < 0 { - panic("Cursor.Enclosing called on Root node") - } - - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - for i := c.index; i >= 0; i = events[i].parent { - if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - } - } -} - -// Parent returns the parent of the current node. -// -// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Parent() Cursor { - if c.index < 0 { - panic("Cursor.Parent called on Root node") - } - - return Cursor{c.in, c.events()[c.index].parent} -} - -// ParentEdge returns the identity of the field in the parent node -// that holds this cursor's node, and if it is a list, the index within it. -// -// For example, f(x, y) is a CallExpr whose three children are Idents. -// f has edge kind [edge.CallExpr_Fun] and index -1. -// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. -// -// If called on a child of the Root node, it returns ([edge.Invalid], -1). -// -// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) ParentEdge() (edge.Kind, int) { - if c.index < 0 { - panic("Cursor.ParentEdge called on Root node") - } - events := c.events() - pop := events[c.index].index - return unpackEdgeKindAndIndex(events[pop].parent) -} - -// ChildAt returns the cursor for the child of the -// current node identified by its edge and index. -// The index must be -1 if the edge.Kind is not a slice. -// The indicated child node must exist. -// -// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. -func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { - target := packEdgeKindAndIndex(k, idx) - - // Unfortunately there's no shortcut to looping. - events := c.events() - i := c.index + 1 - for { - pop := events[i].index - if pop < i { - break - } - if events[pop].parent == target { - return Cursor{c.in, i} - } - i = pop + 1 - } - panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) -} - -// Child returns the cursor for n, which must be a direct child of c's Node. -// -// Child must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Child(n ast.Node) Cursor { - if c.index < 0 { - panic("Cursor.Child called on Root node") - } - - if false { - // reference implementation - for child := range c.Children() { - if child.Node() == n { - return child - } - } - - } else { - // optimized implementation - events := c.events() - for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { - if events[i].node == n { - return Cursor{c.in, i} - } - } - } - panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) -} - -// NextSibling returns the cursor for the next sibling node in the same list -// (for example, of files, decls, specs, statements, fields, or expressions) as -// the current node. It returns (zero, false) if the node is the last node in -// the list, or is not part of a list. -// -// NextSibling must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) NextSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.NextSibling called on Root node") - } - - events := c.events() - i := events[c.index].index + 1 // after corresponding pop - if i < int32(len(events)) { - if events[i].index > i { // push? - return Cursor{c.in, i}, true - } - } - return Cursor{}, false -} - -// PrevSibling returns the cursor for the previous sibling node in the -// same list (for example, of files, decls, specs, statements, fields, -// or expressions) as the current node. It returns zero if the node is -// the first node in the list, or is not part of a list. -// -// It must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) PrevSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.PrevSibling called on Root node") - } - - events := c.events() - i := c.index - 1 - if i >= 0 { - if j := events[i].index; j < i { // pop? - return Cursor{c.in, j}, true - } - } - return Cursor{}, false -} - -// FirstChild returns the first direct child of the current node, -// or zero if it has no children. -func (c Cursor) FirstChild() (Cursor, bool) { - events := c.events() - i := c.index + 1 // i=0 if c is root - if i < int32(len(events)) && events[i].index > i { // push? - return Cursor{c.in, i}, true - } - return Cursor{}, false -} - -// LastChild returns the last direct child of the current node, -// or zero if it has no children. -func (c Cursor) LastChild() (Cursor, bool) { - events := c.events() - if c.index < 0 { // root? - if len(events) > 0 { - // return push of final event (a pop) - return Cursor{c.in, events[len(events)-1].index}, true - } - } else { - j := events[c.index].index - 1 // before corresponding pop - // Inv: j == c.index if c has no children - // or j is last child's pop. - if j > c.index { // c has children - return Cursor{c.in, events[j].index}, true - } - } - return Cursor{}, false -} - -// Children returns an iterator over the direct children of the -// current node, if any. -// -// When using Children, NextChild, and PrevChild, bear in mind that a -// Node's children may come from different fields, some of which may -// be lists of nodes without a distinguished intervening container -// such as [ast.BlockStmt]. -// -// For example, [ast.CaseClause] has a field List of expressions and a -// field Body of statements, so the children of a CaseClause are a mix -// of expressions and statements. Other nodes that have "uncontained" -// list fields include: -// -// - [ast.ValueSpec] (Names, Values) -// - [ast.CompositeLit] (Type, Elts) -// - [ast.IndexListExpr] (X, Indices) -// - [ast.CallExpr] (Fun, Args) -// - [ast.AssignStmt] (Lhs, Rhs) -// -// So, do not assume that the previous sibling of an ast.Stmt is also -// an ast.Stmt, or if it is, that they are executed sequentially, -// unless you have established that, say, its parent is a BlockStmt -// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. -// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, -// even though they are not executed in sequence. -func (c Cursor) Children() iter.Seq[Cursor] { - return func(yield func(Cursor) bool) { - c, ok := c.FirstChild() - for ok && yield(c) { - c, ok = c.NextSibling() - } - } -} - -// Contains reports whether c contains or is equal to c2. -// -// Both Cursors must belong to the same [Inspector]; -// neither may be its Root node. -func (c Cursor) Contains(c2 Cursor) bool { - if c.in != c2.in { - panic("different inspectors") - } - events := c.events() - return c.index <= c2.index && events[c2.index].index <= events[c.index].index -} - -// FindNode returns the cursor for node n if it belongs to the subtree -// rooted at c. It returns zero if n is not found. -func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { - - // FindNode is equivalent to this code, - // but more convenient and 15-20% faster: - if false { - for candidate := range c.Preorder(n) { - if candidate.Node() == n { - return candidate, true - } - } - return Cursor{}, false - } - - // TODO(adonovan): opt: should we assume Node.Pos is accurate - // and combine type-based filtering with position filtering - // like FindByPos? - - mask := maskOf([]ast.Node{n}) - events := c.events() - - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && ev.node == n { - return Cursor{c.in, i}, true - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain type of n: skip. - i = pop - } - } - } - return Cursor{}, false -} - -// FindByPos returns the cursor for the innermost node n in the tree -// rooted at c such that n.Pos() <= start && end <= n.End(). -// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) -// -// It returns zero if none is found. -// Precondition: start <= end. -// -// See also [astutil.PathEnclosingInterval], which -// tolerates adjoining whitespace. -func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { - if end < start { - panic("end < start") - } - events := c.events() - - // This algorithm could be implemented using c.Inspect, - // but it is about 2.5x slower. - - best := int32(-1) // push index of latest (=innermost) node containing range - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - n := ev.node - var nodeEnd token.Pos - if file, ok := n.(*ast.File); ok { - nodeEnd = file.FileEnd - // Note: files may be out of Pos order. - if file.FileStart > start { - i = ev.index // disjoint, after; skip to next file - continue - } - } else { - nodeEnd = n.End() - if n.Pos() > start { - break // disjoint, after; stop - } - } - // Inv: node.{Pos,FileStart} <= start - if end <= nodeEnd { - // node fully contains target range - best = i - } else if nodeEnd < start { - i = ev.index // disjoint, before; skip forward - } - } - } - if best >= 0 { - return Cursor{c.in, best}, true - } - return Cursor{}, false -} diff --git a/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go b/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go deleted file mode 100644 index 0257d61d..00000000 --- a/history-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -package cursor - -import ( - "go/ast" - _ "unsafe" // for go:linkname - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// This file defines backdoor access to inspector. - -// Copied from inspector.event; must remain in sync. -// (Note that the linkname effects a type coercion too.) -type event struct { - node ast.Node - typ uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events - index int32 // index of corresponding push or pop event (relative to this event's index, +ve=push, -ve=pop) - parent int32 // index of parent's push node (push nodes only); or edge and index, bit packed (pop nodes only) -} - -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf -func maskOf(nodes []ast.Node) uint64 - -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *inspector.Inspector) []event - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex -func packEdgeKindAndIndex(edge.Kind, int) int32 - -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex -func unpackEdgeKindAndIndex(int32) (edge.Kind, int) - -func (c Cursor) events() []event { return events(c.in) } diff --git a/history-api/vendor/golang.org/x/tools/internal/astutil/util.go b/history-api/vendor/golang.org/x/tools/internal/astutil/util.go index 1862668a..f06dbda3 100644 --- a/history-api/vendor/golang.org/x/tools/internal/astutil/util.go +++ b/history-api/vendor/golang.org/x/tools/internal/astutil/util.go @@ -71,6 +71,8 @@ func PosInStringLiteral(lit *ast.BasicLit, offset int) (token.Pos, error) { // In practice, the second call is nearly always used only to pop the // stack, and it is surprisingly tricky to do this correctly; see // https://go.dev/issue/73319. +// +// TODO(adonovan): replace with [ast.PreorderStack] when go1.25 is assured. func PreorderStack(root ast.Node, stack []ast.Node, f func(n ast.Node, stack []ast.Node) bool) { before := len(stack) ast.Inspect(root, func(n ast.Node) bool { diff --git a/history-api/vendor/golang.org/x/tools/internal/imports/fix.go b/history-api/vendor/golang.org/x/tools/internal/imports/fix.go index 89b96381..50b6ca51 100644 --- a/history-api/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/history-api/vendor/golang.org/x/tools/internal/imports/fix.go @@ -27,12 +27,13 @@ import ( "unicode" "unicode/utf8" + "maps" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/stdlib" - "maps" ) // importToGroup is a list of functions which map from an import path to @@ -290,8 +291,8 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro return nil } -// if there is a trailing major version, remove it -func withoutVersion(nm string) string { +// WithoutVersion removes a trailing major version, if there is one. +func WithoutVersion(nm string) string { if v := path.Base(nm); len(v) > 0 && v[0] == 'v' { if _, err := strconv.Atoi(v[1:]); err == nil { // this is, for instance, called with rand/v2 and returns rand @@ -313,7 +314,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { } known := p.knownPackages[imp.ImportPath] if known != nil && known.Name != "" { - return withoutVersion(known.Name) + return WithoutVersion(known.Name) } return ImportPathToAssumedName(imp.ImportPath) } diff --git a/history-api/vendor/golang.org/x/tools/internal/imports/imports.go b/history-api/vendor/golang.org/x/tools/internal/imports/imports.go index 2215a128..b5f5218b 100644 --- a/history-api/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/history-api/vendor/golang.org/x/tools/internal/imports/imports.go @@ -93,7 +93,7 @@ func FixImports(ctx context.Context, filename string, src []byte, goroot string, // env is needed. func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) { // Don't use parse() -- we don't care about fragments or statement lists - // here, and we need to work with unparseable files. + // here, and we need to work with unparsable files. fileSet := token.NewFileSet() parserMode := parser.SkipObjectResolution if opt.Comments { diff --git a/history-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go b/history-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go index 05229f06..ca745d4a 100644 --- a/history-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go +++ b/history-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go @@ -15,6 +15,10 @@ import ( // This code is here rather than in the modindex package // to avoid import loops +// TODO(adonovan): this code is only used by a test in this package. +// Can we delete it? Or is there a plan to call NewIndexSource from +// cmd/goimports? + // implements Source using modindex, so only for module cache. // // this is perhaps over-engineered. A new Index is read at first use. @@ -22,8 +26,8 @@ import ( // is read if the index changed. It is not clear the Mutex is needed. type IndexSource struct { modcachedir string - mutex sync.Mutex - ix *modindex.Index + mu sync.Mutex + index *modindex.Index // (access via getIndex) expires time.Time } @@ -39,13 +43,14 @@ func (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths } func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) { - if err := s.maybeReadIndex(); err != nil { + index, err := s.getIndex() + if err != nil { return nil, err } var cs []modindex.Candidate for pkg, nms := range missing { for nm := range nms { - x := s.ix.Lookup(pkg, nm, false) + x := index.Lookup(pkg, nm, false) cs = append(cs, x...) } } @@ -74,30 +79,22 @@ func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, mi return ans, nil } -func (s *IndexSource) maybeReadIndex() error { - s.mutex.Lock() - defer s.mutex.Unlock() - - var readIndex bool - if time.Now().After(s.expires) { - ok, err := modindex.Update(s.modcachedir) - if err != nil { - return err - } - if ok { - readIndex = true - } - } +func (s *IndexSource) getIndex() (*modindex.Index, error) { + s.mu.Lock() + defer s.mu.Unlock() - if readIndex || s.ix == nil { - ix, err := modindex.ReadIndex(s.modcachedir) + // (s.index = nil => s.expires is zero, + // so the first condition is strictly redundant. + // But it makes the postcondition very clear.) + if s.index == nil || time.Now().After(s.expires) { + index, err := modindex.Update(s.modcachedir) if err != nil { - return err + return nil, err } - s.ix = ix - // for now refresh every 15 minutes - s.expires = time.Now().Add(time.Minute * 15) + s.index = index + s.expires = index.ValidAt.Add(15 * time.Minute) // (refresh period) } + // Inv: s.index != nil - return nil + return s.index, nil } diff --git a/history-api/vendor/golang.org/x/tools/internal/modindex/directories.go b/history-api/vendor/golang.org/x/tools/internal/modindex/directories.go index 1e1a02f2..9a963744 100644 --- a/history-api/vendor/golang.org/x/tools/internal/modindex/directories.go +++ b/history-api/vendor/golang.org/x/tools/internal/modindex/directories.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "regexp" - "slices" "strings" "sync" "time" @@ -20,50 +19,48 @@ import ( ) type directory struct { - path Relpath + path string // relative to GOMODCACHE importPath string version string // semantic version - syms []symbol } -// filterDirs groups the directories by import path, -// sorting the ones with the same import path by semantic version, -// most recent first. -func byImportPath(dirs []Relpath) (map[string][]*directory, error) { - ans := make(map[string][]*directory) // key is import path - for _, d := range dirs { - ip, sv, err := DirToImportPathVersion(d) +// bestDirByImportPath returns the best directory for each import +// path, where "best" means most recent semantic version. These import +// paths are inferred from the GOMODCACHE-relative dir names in dirs. +func bestDirByImportPath(dirs []string) (map[string]directory, error) { + dirsByPath := make(map[string]directory) + for _, dir := range dirs { + importPath, version, err := dirToImportPathVersion(dir) if err != nil { return nil, err } - ans[ip] = append(ans[ip], &directory{ - path: d, - importPath: ip, - version: sv, - }) - } - for k, v := range ans { - semanticSort(v) - ans[k] = v + new := directory{ + path: dir, + importPath: importPath, + version: version, + } + if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 { + dirsByPath[importPath] = new + } } - return ans, nil + return dirsByPath, nil } -// sort the directories by semantic version, latest first -func semanticSort(v []*directory) { - slices.SortFunc(v, func(l, r *directory) int { - if n := semver.Compare(l.version, r.version); n != 0 { - return -n // latest first - } - return strings.Compare(string(l.path), string(r.path)) - }) +// compareDirectory defines an ordering of path@version directories, +// by descending version, then by ascending path. +func compareDirectory(x, y directory) int { + if sign := -semver.Compare(x.version, y.version); sign != 0 { + return sign // latest first + } + return strings.Compare(string(x.path), string(y.path)) } // modCacheRegexp splits a relpathpath into module, module version, and package. var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`) -// DirToImportPathVersion computes import path and semantic version -func DirToImportPathVersion(dir Relpath) (string, string, error) { +// dirToImportPathVersion computes import path and semantic version +// from a GOMODCACHE-relative directory name. +func dirToImportPathVersion(dir string) (string, string, error) { m := modCacheRegexp.FindStringSubmatch(string(dir)) // m[1] is the module path // m[2] is the version major.minor.patch(-

 that contains the name
+// Package modindex contains code for building and searching an
+// [Index] of the Go module cache.
+package modindex
+
+// The directory containing the index, returned by
+// [IndexDir], contains a file index-name- that contains the name
 // of the current index. We believe writing that short file is atomic.
-// ReadIndex reads that file to get the file name of the index.
+// [Read] reads that file to get the file name of the index.
 // WriteIndex writes an index with a unique name and then
 // writes that name into a new version of index-name-.
 // ( stands for the CurrentVersion of the index format.)
-package modindex
 
 import (
+	"maps"
+	"os"
 	"path/filepath"
 	"slices"
 	"strings"
@@ -21,144 +25,95 @@ import (
 	"golang.org/x/mod/semver"
 )
 
-// Create always creates a new index for the go module cache that is in cachedir.
-func Create(cachedir string) error {
-	_, err := indexModCache(cachedir, true)
-	return err
-}
-
-// Update the index for the go module cache that is in cachedir,
-// If there is no existing index it will build one.
-// If there are changed directories since the last index, it will
-// write a new one and return true. Otherwise it returns false.
-func Update(cachedir string) (bool, error) {
-	return indexModCache(cachedir, false)
+// Update updates the index for the specified Go
+// module cache directory, creating it as needed.
+// On success it returns the current index.
+func Update(gomodcache string) (*Index, error) {
+	prev, err := Read(gomodcache)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return nil, err
+		}
+		prev = nil
+	}
+	return update(gomodcache, prev)
 }
 
-// indexModCache writes an index current as of when it is called.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and the updates to the cache. It returns true if it wrote an index,
-// false otherwise.
-func indexModCache(cachedir string, clear bool) (bool, error) {
-	cachedir, err := filepath.Abs(cachedir)
+// update builds, writes, and returns the current index.
+//
+// If old is nil, the new index is built from all of GOMODCACHE;
+// otherwise it is built from the old index plus cache updates
+// since the previous index's time.
+func update(gomodcache string, old *Index) (*Index, error) {
+	gomodcache, err := filepath.Abs(gomodcache)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	cd := Abspath(cachedir)
-	future := time.Now().Add(24 * time.Hour) // safely in the future
-	ok, err := modindexTimed(future, cd, clear)
+	new, changed, err := build(gomodcache, old)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	return ok, nil
-}
-
-// modindexTimed writes an index current as of onlyBefore.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and all the updates to the cache before onlyBefore.
-// It returns true if it wrote a new index, false if it wrote nothing.
-func modindexTimed(onlyBefore time.Time, cachedir Abspath, clear bool) (bool, error) {
-	var curIndex *Index
-	if !clear {
-		var err error
-		curIndex, err = ReadIndex(string(cachedir))
-		if clear && err != nil {
-			return false, err
+	if old == nil || changed {
+		if err := write(gomodcache, new); err != nil {
+			return nil, err
 		}
-		// TODO(pjw): check that most of those directories still exist
-	}
-	cfg := &work{
-		onlyBefore: onlyBefore,
-		oldIndex:   curIndex,
-		cacheDir:   cachedir,
-	}
-	if curIndex != nil {
-		cfg.onlyAfter = curIndex.Changed
-	}
-	if err := cfg.buildIndex(); err != nil {
-		return false, err
 	}
-	if len(cfg.newIndex.Entries) == 0 && curIndex != nil {
-		// no changes from existing curIndex, don't write a new index
-		return false, nil
-	}
-	if err := cfg.writeIndex(); err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-type work struct {
-	onlyBefore time.Time // do not use directories later than this
-	onlyAfter  time.Time // only interested in directories after this
-	// directories from before onlyAfter come from oldIndex
-	oldIndex *Index
-	newIndex *Index
-	cacheDir Abspath
+	return new, nil
 }
 
-func (w *work) buildIndex() error {
-	// The effective date of the new index should be at least
-	// slightly earlier than when the directories are scanned
-	// so set it now.
-	w.newIndex = &Index{Changed: time.Now(), Cachedir: w.cacheDir}
-	dirs := findDirs(string(w.cacheDir), w.onlyAfter, w.onlyBefore)
-	if len(dirs) == 0 {
-		return nil
+// build returns a new index for the specified Go module cache (an
+// absolute path).
+//
+// If an old index is provided, only directories more recent than it
+// that it are scanned; older directories are provided by the old
+// Index.
+//
+// The boolean result indicates whether new entries were found.
+func build(gomodcache string, old *Index) (*Index, bool, error) {
+	// Set the time window.
+	var start time.Time // = dawn of time
+	if old != nil {
+		start = old.ValidAt
 	}
-	newdirs, err := byImportPath(dirs)
+	now := time.Now()
+	end := now.Add(24 * time.Hour) // safely in the future
+
+	// Enumerate GOMODCACHE package directories.
+	// Choose the best (latest) package for each import path.
+	pkgDirs := findDirs(gomodcache, start, end)
+	dirByPath, err := bestDirByImportPath(pkgDirs)
 	if err != nil {
-		return err
+		return nil, false, err
 	}
-	// for each import path it might occur only in newdirs,
-	// only in w.oldIndex, or in both.
-	// If it occurs in both, use the semantically later one
-	if w.oldIndex != nil {
-		for _, e := range w.oldIndex.Entries {
-			found, ok := newdirs[e.ImportPath]
-			if !ok {
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				continue // use this one, there is no new one
-			}
-			if semver.Compare(found[0].version, e.Version) > 0 {
-				// use the new one
-			} else {
-				// use the old one, forget the new one
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				delete(newdirs, e.ImportPath)
+
+	// For each import path it might occur only in
+	// dirByPath, only in old, or in both.
+	// If both, use the semantically later one.
+	var entries []Entry
+	if old != nil {
+		for _, entry := range old.Entries {
+			dir, ok := dirByPath[entry.ImportPath]
+			if !ok || semver.Compare(dir.version, entry.Version) <= 0 {
+				// New dir is missing or not more recent; use old entry.
+				entries = append(entries, entry)
+				delete(dirByPath, entry.ImportPath)
 			}
 		}
 	}
-	// get symbol information for all the new diredtories
-	getSymbols(w.cacheDir, newdirs)
-	// assemble the new index entries
-	for k, v := range newdirs {
-		d := v[0]
-		pkg, names := processSyms(d.syms)
-		if pkg == "" {
-			continue // PJW: does this ever happen?
-		}
-		entry := Entry{
-			PkgName:    pkg,
-			Dir:        d.path,
-			ImportPath: k,
-			Version:    d.version,
-			Names:      names,
-		}
-		w.newIndex.Entries = append(w.newIndex.Entries, entry)
-	}
-	// sort the entries in the new index
-	slices.SortFunc(w.newIndex.Entries, func(l, r Entry) int {
-		if n := strings.Compare(l.PkgName, r.PkgName); n != 0 {
+
+	// Extract symbol information for all the new directories.
+	newEntries := extractSymbols(gomodcache, maps.Values(dirByPath))
+	entries = append(entries, newEntries...)
+	slices.SortFunc(entries, func(x, y Entry) int {
+		if n := strings.Compare(x.PkgName, y.PkgName); n != 0 {
 			return n
 		}
-		return strings.Compare(l.ImportPath, r.ImportPath)
+		return strings.Compare(x.ImportPath, y.ImportPath)
 	})
-	return nil
-}
 
-func (w *work) writeIndex() error {
-	return writeIndex(w.cacheDir, w.newIndex)
+	return &Index{
+		GOMODCACHE: gomodcache,
+		ValidAt:    now, // time before the directories were scanned
+		Entries:    entries,
+	}, len(newEntries) > 0, nil
 }
diff --git a/history-api/vendor/golang.org/x/tools/internal/modindex/symbols.go b/history-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
index b918529d..fe24db9b 100644
--- a/history-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
+++ b/history-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -10,11 +10,13 @@ import (
 	"go/parser"
 	"go/token"
 	"go/types"
+	"iter"
 	"os"
 	"path/filepath"
 	"runtime"
 	"slices"
 	"strings"
+	"sync"
 
 	"golang.org/x/sync/errgroup"
 )
@@ -30,45 +32,69 @@ import (
 type symbol struct {
 	pkg  string // name of the symbols's package
 	name string // declared name
-	kind string // T, C, V, or F, follwed by D if deprecated
+	kind string // T, C, V, or F, followed by D if deprecated
 	sig  string // signature information, for F
 }
 
-// find the symbols for the best directories
-func getSymbols(cd Abspath, dirs map[string][]*directory) {
+// extractSymbols returns a (new, unordered) array of Entries, one for
+// each provided package directory, describing its exported symbols.
+func extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {
+	var (
+		mu      sync.Mutex
+		entries []Entry
+	)
+
 	var g errgroup.Group
 	g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
-	for _, vv := range dirs {
-		// throttling some day?
-		d := vv[0]
+	for dir := range dirs {
 		g.Go(func() error {
-			thedir := filepath.Join(string(cd), string(d.path))
+			thedir := filepath.Join(cwd, string(dir.path))
 			mode := parser.SkipObjectResolution | parser.ParseComments
 
-			fi, err := os.ReadDir(thedir)
+			// Parse all Go files in dir and extract symbols.
+			dirents, err := os.ReadDir(thedir)
 			if err != nil {
 				return nil // log this someday?
 			}
-			for _, fx := range fi {
-				if !strings.HasSuffix(fx.Name(), ".go") || strings.HasSuffix(fx.Name(), "_test.go") {
+			var syms []symbol
+			for _, dirent := range dirents {
+				if !strings.HasSuffix(dirent.Name(), ".go") ||
+					strings.HasSuffix(dirent.Name(), "_test.go") {
 					continue
 				}
-				fname := filepath.Join(thedir, fx.Name())
+				fname := filepath.Join(thedir, dirent.Name())
 				tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
 				if err != nil {
 					continue // ignore errors, someday log them?
 				}
-				d.syms = append(d.syms, getFileExports(tr)...)
+				syms = append(syms, getFileExports(tr)...)
+			}
+
+			// Create an entry for the package.
+			pkg, names := processSyms(syms)
+			if pkg != "" {
+				mu.Lock()
+				defer mu.Unlock()
+				entries = append(entries, Entry{
+					PkgName:    pkg,
+					Dir:        dir.path,
+					ImportPath: dir.importPath,
+					Version:    dir.version,
+					Names:      names,
+				})
 			}
+
 			return nil
 		})
 	}
-	g.Wait()
+	g.Wait() // ignore error
+
+	return entries
 }
 
 func getFileExports(f *ast.File) []symbol {
 	pkg := f.Name.Name
-	if pkg == "main" {
+	if pkg == "main" || pkg == "" {
 		return nil
 	}
 	var ans []symbol
@@ -110,7 +136,7 @@ func getFileExports(f *ast.File) []symbol {
 				// The only place a $ can occur seems to be in a struct tag, which
 				// can be an arbitrary string literal, and ExprString does not presently
 				// print struct tags. So for this to happen the type of a formal parameter
-				// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
+				// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
 				// would have to show the struct tag. Even testing for this case seems
 				// a waste of effort, but let's remember the possibility
 				if strings.Contains(tp, "$") {
@@ -202,17 +228,18 @@ func processSyms(syms []symbol) (string, []string) {
 	pkg := syms[0].pkg
 	var names []string
 	for _, s := range syms {
+		if s.pkg != pkg {
+			// Symbols came from two files in same dir
+			// with different package declarations.
+			continue
+		}
 		var nx string
-		if s.pkg == pkg {
-			if s.sig != "" {
-				nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
-			} else {
-				nx = fmt.Sprintf("%s %s", s.name, s.kind)
-			}
-			names = append(names, nx)
+		if s.sig != "" {
+			nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
 		} else {
-			continue // PJW: do we want to keep track of these?
+			nx = fmt.Sprintf("%s %s", s.name, s.kind)
 		}
+		names = append(names, nx)
 	}
 	return pkg, names
 }
diff --git a/history-api/vendor/golang.org/x/tools/internal/modindex/types.go b/history-api/vendor/golang.org/x/tools/internal/modindex/types.go
deleted file mode 100644
index ece44886..00000000
--- a/history-api/vendor/golang.org/x/tools/internal/modindex/types.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modindex
-
-import (
-	"strings"
-)
-
-// some special types to avoid confusions
-
-// distinguish various types of directory names. It's easy to get confused.
-type Abspath string // absolute paths
-type Relpath string // paths with GOMODCACHE prefix removed
-
-func toRelpath(cachedir Abspath, s string) Relpath {
-	if strings.HasPrefix(s, string(cachedir)) {
-		if s == string(cachedir) {
-			return Relpath("")
-		}
-		return Relpath(s[len(cachedir)+1:])
-	}
-	return Relpath(s)
-}
diff --git a/history-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/history-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 73eefa2a..929b470b 100644
--- a/history-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/history-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -5,6 +5,8 @@
 // Package packagesinternal exposes internal-only fields from go/packages.
 package packagesinternal
 
+import "fmt"
+
 var GetDepsErrors = func(p any) []*PackageError { return nil }
 
 type PackageError struct {
@@ -13,5 +15,9 @@ type PackageError struct {
 	Err         string   // the error itself
 }
 
+func (err PackageError) String() string {
+	return fmt.Sprintf("%s: %s (import stack: %s)", err.Pos, err.Err, err.ImportStack)
+}
+
 var TypecheckCgo int
 var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
diff --git a/history-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go b/history-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
index 649c82b6..3db2a135 100644
--- a/history-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
+++ b/history-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
@@ -65,14 +65,16 @@ func ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {
 	if info.Types == nil {
 		panic("ClassifyCall: info.Types is nil")
 	}
-	if info.Types[call.Fun].IsType() {
+	tv := info.Types[call.Fun]
+	if tv.IsType() {
 		return CallConversion
 	}
+	if tv.IsBuiltin() {
+		return CallBuiltin
+	}
 	obj := info.Uses[UsedIdent(info, call.Fun)]
 	// Classify the call by the type of the object, if any.
 	switch obj := obj.(type) {
-	case *types.Builtin:
-		return CallBuiltin
 	case *types.Func:
 		if interfaceMethod(obj) {
 			return CallInterface
diff --git a/history-api/vendor/golang.org/x/tools/internal/typesinternal/types.go b/history-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
index cc244689..a5cd7e8d 100644
--- a/history-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/history-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -69,6 +69,34 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 	}
 }
 
+// TypeNameFor returns the type name symbol for the specified type, if
+// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a
+// [*types.Basic] representing a type.
+//
+// For all other types, and for Basic types representing a builtin,
+// constant, or nil, it returns nil. Be careful not to convert the
+// resulting nil pointer to a [types.Object]!
+//
+// If t is the type of a constant, it may be an "untyped" type, which
+// has no TypeName. To access the name of such types (e.g. "untyped
+// int"), use [types.Basic.Name].
+func TypeNameFor(t types.Type) *types.TypeName {
+	switch t := t.(type) {
+	case *types.Alias:
+		return t.Obj()
+	case *types.Named:
+		return t.Obj()
+	case *types.TypeParam:
+		return t.Obj()
+	case *types.Basic:
+		// See issues #71886 and #66890 for some history.
+		if tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {
+			return tname
+		}
+	}
+	return nil
+}
+
 // A NamedOrAlias is a [types.Type] that is named (as
 // defined by the spec) and capable of bearing type parameters: it
 // abstracts aliases ([types.Alias]) and defined types
@@ -77,7 +105,7 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 // Every type declared by an explicit "type" declaration is a
 // NamedOrAlias. (Built-in type symbols may additionally
 // have type [types.Basic], which is not a NamedOrAlias,
-// though the spec regards them as "named".)
+// though the spec regards them as "named"; see [TypeNameFor].)
 //
 // NamedOrAlias cannot expose the Origin method, because
 // [types.Alias.Origin] and [types.Named.Origin] have different
@@ -85,32 +113,15 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 type NamedOrAlias interface {
 	types.Type
 	Obj() *types.TypeName
-	// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
-}
-
-// TypeParams is a light shim around t.TypeParams().
-// (go/types.Alias).TypeParams requires >= 1.23.
-func TypeParams(t NamedOrAlias) *types.TypeParamList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeParams(t)
-	case *types.Named:
-		return t.TypeParams()
-	}
-	return nil
+	TypeArgs() *types.TypeList
+	TypeParams() *types.TypeParamList
+	SetTypeParams(tparams []*types.TypeParam)
 }
 
-// TypeArgs is a light shim around t.TypeArgs().
-// (go/types.Alias).TypeArgs requires >= 1.23.
-func TypeArgs(t NamedOrAlias) *types.TypeList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeArgs(t)
-	case *types.Named:
-		return t.TypeArgs()
-	}
-	return nil
-}
+var (
+	_ NamedOrAlias = (*types.Alias)(nil)
+	_ NamedOrAlias = (*types.Named)(nil)
+)
 
 // Origin returns the generic type of the Named or Alias type t if it
 // is instantiated, otherwise it returns t.
diff --git a/history-api/vendor/golang.org/x/vuln/LICENSE b/history-api/vendor/golang.org/x/vuln/LICENSE
index 6a66aea5..2a7cf70d 100644
--- a/history-api/vendor/golang.org/x/vuln/LICENSE
+++ b/history-api/vendor/golang.org/x/vuln/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
+Copyright 2009 The Go Authors.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
-   * Neither the name of Google Inc. nor the names of its
+   * Neither the name of Google LLC nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.
 
diff --git a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
index b7b16d9f..8de6904a 100644
--- a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
+++ b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
@@ -9,10 +9,10 @@ only those that could affect the application.
 
 By default, govulncheck makes requests to the Go vulnerability database at
 https://vuln.go.dev. Requests to the vulnerability database contain only module
-paths, not code or other properties of your program. See
-https://vuln.go.dev/privacy.html for more. Use the -db flag to specify a
-different database, which must implement the specification at
-https://go.dev/security/vuln/database.
+paths with vulnerabilities already known to the database, not code or other
+properties of your program. See https://vuln.go.dev/privacy.html for more.
+Use the -db flag to specify a different database, which must implement the
+specification at https://go.dev/security/vuln/database.
 
 Govulncheck looks for vulnerabilities in Go programs using a specific build
 configuration. For analyzing source code, that configuration is the Go version
@@ -20,8 +20,6 @@ specified by the “go” command found on the PATH. For binaries, the build
 configuration is the one used to build the binary. Note that different build
 configurations may have different known vulnerabilities.
 
-Govulncheck must be built with Go version 1.18 or later.
-
 # Usage
 
 To analyze source code, run govulncheck from the module directory, using the
@@ -41,44 +39,45 @@ To control which files are processed, use the -tags flag to provide a
 comma-separated list of build tags, and the -test flag to indicate that test
 files should be included.
 
-To run govulncheck on a compiled binary, pass it the path to the binary file
-with the -mode=binary flag:
-
-	$ govulncheck -mode=binary $HOME/go/bin/my-go-program
+To include more detailed stack traces, pass '-show traces', this will cause it to
+print the full call stack for each entry.
 
-Govulncheck uses the binary's symbol information to find mentions of vulnerable
-functions. Its output omits call stacks, which require source code analysis.
+To include progress messages and more details on findings, pass '-show verbose'.
 
-Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
-and exits unsuccessfully if there are. It also exits successfully if -json flag
-is provided, regardless of the number of detected vulnerabilities.
+To run govulncheck on a compiled binary, pass it the path to the binary file
+with the '-mode binary' flag:
 
-# Flags
+	$ govulncheck -mode binary $HOME/go/bin/my-go-program
 
-A few flags control govulncheck's behavior.
+Govulncheck uses the binary's symbol information to find mentions of vulnerable
+functions. These functions can belong to binary's transitive dependencies and
+also the main module of the binary. The latter functions are checked for only
+when the precise version of the binary module is known. Govulncheck output on
+binaries omits call stacks, which require source code analysis.
 
-The -C flag causes govulncheck to change its working directory to the provided
-directory before running. Any patterns or files named on the command line are
-interpreted after changing directories.
+Govulncheck also supports '-mode extract' on a Go binary for extraction of minimal
+information needed to analyze the binary. This will produce a blob, typically much
+smaller than the binary, that can also be passed to govulncheck as an argument with
+'-mode binary'. The users should not rely on the contents or representation of the blob.
 
-The -db flag causes govulncheck to read from the specified database, which must
-implement the specification at https://go.dev/security/vuln/database. By
-default, govulncheck fetches vulnerability data from https://vuln.go.dev.
+# Integrations
 
-The -json flag causes govulncheck to print its output as a JSON object
-corresponding to the type [golang.org/x/vuln/internal/govulncheck.Result]. The
-exit code of govulncheck is 0 when this flag is provided.
+Govulncheck supports streaming JSON. For more details, please see [golang.org/x/vuln/internal/govulncheck].
 
-The -mode flag causes govulncheck to run source or binary analysis. By default,
-govulnchecks runs source analysis.
+Govulncheck also supports Static Analysis Results Interchange Format (SARIF) output
+format, following the specification at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+For more details, please see [golang.org/x/vuln/internal/sarif].
 
-The -tags flag accepts a comma-separated list of build tags to control which
-files should be included in loaded packages for source analysis.
+Govulncheck supports the Vulnerability EXchange (VEX) output format, following
+the specification at https://github.com/openvex/spec.
+For more details, please see [golang.org/x/vuln/internal/openvex].
 
-The -test flag causes govulncheck to include test files in the source analysis.
+# Exit codes
 
-The -v flag causes govulncheck to output more information when run on source.
-It has no effect when run on a binary.
+Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
+and exits unsuccessfully if there are. It also exits successfully if the
+'format -json' ('-json'), '-format sarif', or '-format openvex' is provided,
+regardless of the number of detected vulnerabilities.
 
 # Limitations
 
@@ -88,22 +87,20 @@ Govulncheck has these limitations:
     which may result in false positives or inaccurate call stacks in some cases.
   - Calls to functions made using package reflect are not visible to static
     analysis. Vulnerable code reachable only through those calls will not be
-    reported.
+    reported in source scan mode. Similarly, use of the unsafe package may
+    result in false negatives.
   - Because Go binaries do not contain detailed call information, govulncheck
     cannot show the call graphs for detected vulnerabilities. It may also
     report false positives for code that is in the binary but unreachable.
-  - There is no support for silencing vulnerability findings.
-  - Govulncheck only reads binaries compiled with Go 1.18 and later.
-  - Govulncheck only reports vulnerabilities that apply to the current Go
-    version. For example, a standard library vulnerability that only applies for
-    Go 1.18 will not be reported if the current Go version is 1.19. See
-    https://go.dev/issue/54841 for updates to this limitation.
+  - There is no support for silencing vulnerability findings. See https://go.dev/issue/61211 for
+    updates.
+  - Govulncheck reports only standard library vulnerabilities for binaries
+    built with Go versions prior to Go 1.18.
   - For binaries where the symbol information cannot be extracted, govulncheck
     reports vulnerabilities for all modules on which the binary depends.
 
 # Feedback
 
-Govulncheck is an experimental tool under active development. To share
-feedback, see https://go.dev/security/vuln#feedback.
+To share feedback, see https://go.dev/security/vuln#feedback.
 */
 package main
diff --git a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
new file mode 100644
index 00000000..288c10c2
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
@@ -0,0 +1,12 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.23
+
+//go:debug gotypesalias=1
+
+package main
+
+// Materialize aliases whenever the go toolchain version is after 1.23 (#69772).
+// Remove this file after go.mod >= 1.23 (which implies gotypesalias=1).
diff --git a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
index f6ca253f..73e3370a 100644
--- a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
+++ b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
@@ -9,10 +9,13 @@ import (
 	"fmt"
 	"os"
 
+	"golang.org/x/telemetry"
 	"golang.org/x/vuln/scan"
 )
 
 func main() {
+	telemetry.Start(telemetry.Config{ReportCrashes: true})
+
 	ctx := context.Background()
 
 	cmd := scan.Command(ctx, os.Args[1:]...)
diff --git a/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
new file mode 100644
index 00000000..826d6caf
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
@@ -0,0 +1,128 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"testing"
+)
+
+// copyTestCase copies the test case at dir into a
+// temporary directory. The created files have 0644
+// permission and directories 0755. It does not create
+// symlinks.
+func copyTestCase(dir string, t *testing.T) string {
+	newDir, err := filepath.Abs(t.TempDir())
+	if err != nil {
+		t.Fatalf("failed to copy test case %s: cannot create root %v", dir, err)
+	}
+
+	if err := copyDir(dir, newDir); err != nil {
+		t.Fatalf("failed to copy test case %s: copy failure %v", dir, err)
+	}
+	return newDir
+}
+
+func copyDir(srcDir, destDir string) error {
+	entries, err := os.ReadDir(srcDir)
+	if err != nil {
+		return err
+	}
+	for _, entry := range entries {
+		src := filepath.Join(srcDir, entry.Name())
+		dest := filepath.Join(destDir, entry.Name())
+
+		fileInfo, err := os.Stat(src)
+		if err != nil {
+			return err
+		}
+
+		switch fileInfo.Mode() & os.ModeType {
+		case os.ModeDir:
+			if err := os.MkdirAll(dest, 0755); err != nil {
+				return err
+			}
+			if err := copyDir(src, dest); err != nil {
+				return err
+			}
+		default:
+			if err := copyFile(src, dest); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func copyFile(src, dest string) error {
+	b, err := os.ReadFile(src)
+	if err != nil {
+		return err
+	}
+	return os.WriteFile(dest, b, 0644)
+}
+
+type config struct {
+	// SkipGOOS is a list of GOOS to skip
+	SkipGOOS []string `json:"skipGOOS,omitempty"`
+	// Copy the folder to isolate it
+	Copy bool `json:"copy,omitempty"`
+	// SkipBuild the test case
+	SkipBuild bool `json:"skipBuild,omitempty"`
+	// Strip indicates if binaries should be stripped
+	Strip bool `json:"strip,omitempty"`
+	// EnableSBOM indicates if sbom should be
+	// printed in JSON.
+	EnableSBOM bool `json:"sbom,omitempty"`
+
+	Fixups []fixup `json:"fixups,omitempty"`
+}
+
+func (c *config) skip() bool {
+	for _, sg := range c.SkipGOOS {
+		if runtime.GOOS == sg {
+			return true
+		}
+	}
+	return false
+}
+
+type fixup struct {
+	Pattern     string `json:"pattern,omitempty"`
+	Replace     string `json:"replace,omitempty"`
+	compiled    *regexp.Regexp
+	replaceFunc func(b []byte) []byte
+}
+
+func (f *fixup) init() {
+	f.compiled = regexp.MustCompile(f.Pattern)
+}
+
+func (f *fixup) apply(data []byte) []byte {
+	if f.replaceFunc != nil {
+		return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
+	}
+	return f.compiled.ReplaceAll(data, []byte(f.Replace))
+}
+
+// loadConfig loads and initializes the config from path.
+func loadConfig(path string) (*config, error) {
+	b, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	var cfg config
+	if err := json.Unmarshal(b, &cfg); err != nil {
+		return nil, err
+	}
+	for i := range cfg.Fixups {
+		cfg.Fixups[i].init()
+	}
+	return &cfg, nil
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/README.md
similarity index 100%
rename from history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md
rename to history-api/vendor/golang.org/x/vuln/internal/buildinfo/README.md
diff --git a/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
new file mode 100644
index 00000000..49869ce3
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
@@ -0,0 +1,257 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// This file adds to buildinfo the functionality for extracting the PCLN table.
+
+import (
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// ErrNoSymbols represents non-existence of symbol
+// table in binaries supported by buildinfo.
+var ErrNoSymbols = errors.New("no symbol section")
+
+// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
+func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil || sym == nil {
+		if errors.Is(err, elf.ErrNoSymbols) {
+			return 0, 0, nil, ErrNoSymbols
+		}
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	prog := x.progContaining(sym.Value)
+	if prog == nil {
+		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
+}
+
+func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		syms, err := x.f.Symbols()
+		if err != nil {
+			x.symbolsErr = err
+			return
+		}
+		x.symbols = make(map[string]*elf.Symbol, len(syms))
+		for _, s := range syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *elfExe) progContaining(addr uint64) *elf.Prog {
+	for _, p := range x.f.Progs {
+		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
+			return p
+		}
+	}
+	return nil
+}
+
+const go12magic = 0xfffffffb
+const go116magic = 0xfffffffa
+
+// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
+func (x *elfExe) PCLNTab() ([]byte, uint64) {
+	var offset uint64
+	text := x.f.Section(".text")
+	if text != nil {
+		offset = text.Offset
+	}
+	pclntab := x.f.Section(".gopclntab")
+	if pclntab == nil {
+		// Addition: this code is added to support some form of stripping.
+		pclntab = x.f.Section(".data.rel.ro.gopclntab")
+		if pclntab == nil {
+			pclntab = x.f.Section(".data.rel.ro")
+			if pclntab == nil {
+				return nil, 0
+			}
+			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
+			// its own section header. We can search for for the start by looking for the four
+			// byte magic and the go magic.
+			b, err := pclntab.Data()
+			if err != nil {
+				return nil, 0
+			}
+			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
+			// actually correct. During testing it worked, but that may be because I got lucky
+			// with the binary I was using, and we need to do four byte jumps to exhaustively
+			// search the section?
+			for i := 0; i < len(b); i += 16 {
+				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
+					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
+					(b[i+7] == 4 || b[i+7] == 8) {
+					// Also check for the go magic
+					leMagic := binary.LittleEndian.Uint32(b[i:])
+					beMagic := binary.BigEndian.Uint32(b[i:])
+					switch {
+					case leMagic == go12magic:
+						fallthrough
+					case beMagic == go12magic:
+						fallthrough
+					case leMagic == go116magic:
+						fallthrough
+					case beMagic == go116magic:
+						return b[i:], offset
+					}
+				}
+			}
+		}
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, offset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
+func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	sect := x.f.Sections[sym.SectionNumber-1]
+	// In PE, the symbol's value is the offset from the section start.
+	return uint64(sym.Value), 0, sect.ReaderAt, nil
+}
+
+func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
+		if len(x.f.Symbols) == 0 {
+			x.symbolsErr = ErrNoSymbols
+			return
+		}
+		for _, s := range x.f.Symbols {
+			x.symbols[s.Name] = s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
+// Assumes that the underlying symbol table exists, otherwise
+// it might panic.
+func (x *peExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	for _, section := range x.f.Sections {
+		if section.Name == ".text" {
+			textOffset = uint64(section.Offset)
+			break
+		}
+	}
+
+	var start, end int64
+	var section int
+	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
+		start = int64(s.Value)
+		section = int(s.SectionNumber - 1)
+	}
+	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
+		end = int64(s.Value)
+	}
+	if start == 0 || end == 0 {
+		return nil, 0
+	}
+	offset := int64(x.f.Sections[section].Offset) + start
+	size := end - start
+
+	pclntab := make([]byte, size)
+	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
+		return nil, 0
+	}
+	return pclntab, textOffset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
+func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	seg := x.segmentContaining(sym.Value)
+	if seg == nil {
+		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, seg.Addr, seg.ReaderAt, nil
+}
+
+func (x *machoExe) lookupSymbol(name string) (*macho.Symbol, error) {
+	const mustExistSymbol = "runtime.main"
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
+		for _, s := range x.f.Symtab.Syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+		// In the presence of stripping, the symbol table for darwin
+		// binaries will not be empty, but the program symbols will
+		// be missing.
+		if _, ok := x.symbols[mustExistSymbol]; !ok {
+			x.symbolsErr = ErrNoSymbols
+		}
+	})
+
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
+			return seg
+		}
+	}
+	return nil
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
+func (x *machoExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	text := x.f.Section("__text")
+	if text != nil {
+		textOffset = uint64(text.Offset)
+	}
+	pclntab := x.f.Section("__gopclntab")
+	if pclntab == nil {
+		return nil, 0
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, textOffset
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
new file mode 100644
index 00000000..ddbdea08
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
@@ -0,0 +1,160 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Code in this package is dervied from src/cmd/go/internal/version/version.go
+// and cmd/go/internal/version/exe.go.
+
+import (
+	"debug/buildinfo"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"runtime/debug"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/gosym"
+	"golang.org/x/vuln/internal/goversion"
+)
+
+func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
+	packagesModules := make([]*packages.Module, len(debugModules))
+	for i, mod := range debugModules {
+		packagesModules[i] = &packages.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+		if mod.Replace != nil {
+			packagesModules[i].Replace = &packages.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+	}
+	return packagesModules
+}
+
+type Symbol struct {
+	Pkg  string `json:"pkg,omitempty"`
+	Name string `json:"name,omitempty"`
+}
+
+// ExtractPackagesAndSymbols extracts symbols, packages, modules from
+// Go binary file as well as bin's metadata.
+//
+// If the symbol table is not available, such as in the case of stripped
+// binaries, returns module and binary info but without the symbol info.
+func ExtractPackagesAndSymbols(file string) ([]*packages.Module, []Symbol, *debug.BuildInfo, error) {
+	bin, err := os.Open(file)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+	defer bin.Close()
+
+	bi, err := buildinfo.Read(bin)
+	if err != nil {
+		// It could be that bin is an ancient Go binary.
+		v, err := goversion.ReadExe(file)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		bi := &debug.BuildInfo{
+			GoVersion: v.Release,
+			Main:      debug.Module{Path: v.ModuleInfo},
+		}
+		// We cannot analyze symbol tables of ancient binaries.
+		return nil, nil, bi, nil
+	}
+
+	funcSymName := gosym.FuncSymName(bi.GoVersion)
+	if funcSymName == "" {
+		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
+	}
+
+	x, err := openExe(bin)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	value, base, r, err := x.SymbolInfo(funcSymName)
+	if err != nil {
+		if errors.Is(err, ErrNoSymbols) {
+			// bin is stripped, so return just module info and metadata.
+			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+		}
+		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
+	}
+
+	pclntab, textOffset := x.PCLNTab()
+	if pclntab == nil {
+		// If we have build information, but not PCLN table, fall
+		// back to much higher granularity vulnerability checking.
+		return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+	}
+	lineTab := gosym.NewLineTable(pclntab, textOffset)
+	if lineTab == nil {
+		return nil, nil, nil, errors.New("invalid line table")
+	}
+	tab, err := gosym.NewTable(nil, lineTab)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	pkgSyms := make(map[Symbol]bool)
+	for _, f := range tab.Funcs {
+		if f.Func == nil {
+			continue
+		}
+		pkgName, symName, err := parseName(f.Func.Sym)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		pkgSyms[Symbol{pkgName, symName}] = true
+
+		// Collect symbols that were inlined in f.
+		it, err := lineTab.InlineTree(&f, value, base, r)
+		if err != nil {
+			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
+		}
+		for _, ic := range it {
+			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
+			if err != nil {
+				return nil, nil, nil, err
+			}
+			pkgSyms[Symbol{pkgName, symName}] = true
+		}
+	}
+
+	var syms []Symbol
+	for ps := range pkgSyms {
+		syms = append(syms, ps)
+	}
+
+	return debugModulesToPackagesModules(bi.Deps), syms, bi, nil
+}
+
+func parseName(s *gosym.Sym) (pkg, sym string, err error) {
+	symName := s.BaseName()
+	if r := s.ReceiverName(); r != "" {
+		if strings.HasPrefix(r, "(*") {
+			r = strings.Trim(r, "(*)")
+		}
+		symName = fmt.Sprintf("%s.%s", r, symName)
+	}
+
+	pkgName := s.PackageName()
+	if pkgName != "" {
+		pkgName, err = url.PathUnescape(pkgName)
+		if err != nil {
+			return "", "", err
+		}
+	}
+	return pkgName, symName, nil
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
new file mode 100644
index 00000000..f29dffa2
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
@@ -0,0 +1,221 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"fmt"
+	"sync"
+
+	// "internal/xcoff"
+	"io"
+)
+
+// Addition: modification of rawBuildInfo in the original file.
+// openExe returns reader r as an exe.
+func openExe(r io.ReaderAt) (exe, error) {
+	data := make([]byte, 16)
+	if _, err := r.ReadAt(data, 0); err != nil {
+		return nil, err
+	}
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &elfExe{f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &peExe{r: r, f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &machoExe{f: e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type exe interface {
+	// ReadData reads and returns up to size byte starting at virtual address addr.
+	ReadData(addr, size uint64) ([]byte, error)
+
+	// DataStart returns the virtual address of the segment or section that
+	// should contain build information. This is either a specially named section
+	// or the first writable non-zero data segment.
+	DataStart() uint64
+
+	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
+
+	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
+}
+
+// elfExe is the ELF implementation of the exe interface.
+type elfExe struct {
+	f *elf.File
+
+	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once              // Addition: for computing symbols
+	symbolsErr  error                  // Addition: error for computing symbols
+}
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *elfExe) DataStart() uint64 {
+	for _, s := range x.f.Sections {
+		if s.Name == ".go.buildinfo" {
+			return s.Addr
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
+			return p.Vaddr
+		}
+	}
+	return 0
+}
+
+// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
+type peExe struct {
+	r io.ReaderAt
+	f *pe.File
+
+	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once             // Addition: for computing symbols
+	symbolsErr  error                 // Addition: error for computing symbols
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
+			n := uint64(sect.VirtualAddress+sect.Size) - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *peExe) DataStart() uint64 {
+	// Assume data is first writable section.
+	const (
+		IMAGE_SCN_CNT_CODE               = 0x00000020
+		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
+		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
+		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
+		IMAGE_SCN_MEM_READ               = 0x40000000
+		IMAGE_SCN_MEM_WRITE              = 0x80000000
+		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
+		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
+		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
+	)
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 &&
+			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
+			return uint64(sect.VirtualAddress) + x.imageBase()
+		}
+	}
+	return 0
+}
+
+// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
+type machoExe struct {
+	f *macho.File
+
+	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once                // Addition: for computing symbols
+	symbolsErr  error                    // Addition: error for computing symbols
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			n := seg.Addr + seg.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *machoExe) DataStart() uint64 {
+	// Look for section named "__go_buildinfo".
+	for _, sec := range x.f.Sections {
+		if sec.Name == "__go_buildinfo" {
+			return sec.Addr
+		}
+	}
+	// Try the first non-empty writable segment.
+	const RW = 3
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
+			return seg.Addr
+		}
+	}
+	return 0
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/client/index.go b/history-api/vendor/golang.org/x/vuln/internal/client/index.go
index 5f2d0c00..435980c4 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/client/index.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/client/index.go
@@ -96,7 +96,7 @@ func (i *index) add(entry *osv.Entry) {
 		module.Vulns = append(module.Vulns, moduleVuln{
 			ID:       entry.ID,
 			Modified: entry.Modified,
-			Fixed:    isem.LatestFixedVersion(affected.Ranges),
+			Fixed:    isem.NonSupersededFix(affected.Ranges),
 		})
 	}
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/client/source.go b/history-api/vendor/golang.org/x/vuln/internal/client/source.go
index 3e47b09f..2e848c32 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/client/source.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/client/source.go
@@ -45,8 +45,9 @@ type httpSource struct {
 func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err error) {
 	derrors.Wrap(&err, "get(%s)", endpoint)
 
+	method := http.MethodGet
 	reqURL := fmt.Sprintf("%s/%s", hs.url, endpoint+".json.gz")
-	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
+	req, err := http.NewRequestWithContext(ctx, method, reqURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -56,7 +57,7 @@ func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err e
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
+		return nil, fmt.Errorf("HTTP %s %s returned unexpected status: %s", method, reqURL, resp.Status)
 	}
 
 	// Uncompress the result.
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md b/history-api/vendor/golang.org/x/vuln/internal/gosym/README.md
similarity index 100%
rename from history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md
rename to history-api/vendor/golang.org/x/vuln/internal/gosym/README.md
diff --git a/history-api/vendor/golang.org/x/vuln/internal/gosym/additions.go b/history-api/vendor/golang.org/x/vuln/internal/gosym/additions.go
new file mode 100644
index 00000000..022cf92e
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/gosym/additions.go
@@ -0,0 +1,184 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gosym
+
+import (
+	"encoding/binary"
+	"io"
+	"strings"
+
+	sv "golang.org/x/mod/semver"
+	"golang.org/x/vuln/internal/semver"
+)
+
+const (
+	funcSymNameGo119Lower string = "go.func.*"
+	funcSymNameGo120      string = "go:func.*"
+)
+
+// FuncSymName returns symbol name for Go functions used in binaries
+// based on Go version. Supported Go versions are 1.18 and greater.
+// If the go version is unreadable it assumes that it is a newer version
+// and returns the symbol name for go version 1.20 or greater.
+func FuncSymName(goVersion string) string {
+	// Support devel goX.Y...
+	v := strings.TrimPrefix(goVersion, "devel ")
+	v = semver.GoTagToSemver(v)
+	mm := sv.MajorMinor(v)
+	if sv.Compare(mm, "v1.20") >= 0 || mm == "" {
+		return funcSymNameGo120
+	} else if sv.Compare(mm, "v1.18") >= 0 {
+		return funcSymNameGo119Lower
+	}
+	return ""
+}
+
+// Additions to the original package from cmd/internal/objabi/funcdata.go
+const (
+	pcdata_InlTreeIndex = 2
+	funcdata_InlTree    = 3
+)
+
+// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
+// goFuncValue is the value of the gosym.FuncSymName symbol.
+// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
+// progReader is a ReaderAt positioned at the start of that region.
+func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
+	if f.inlineTreeCount == 0 {
+		return nil, nil
+	}
+	if f.inlineTreeOffset == ^uint32(0) {
+		return nil, nil
+	}
+	var offset int64
+	if t.version >= ver118 {
+		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
+	} else {
+		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
+	}
+
+	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
+	ics := make([]InlinedCall, 0, f.inlineTreeCount)
+	for i := 0; i < f.inlineTreeCount; i++ {
+		if t.version >= ver120 {
+			var ric rawInlinedCall120
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.NameOff)),
+				ParentPC: ric.ParentPC,
+			})
+		} else {
+			var ric rawInlinedCall112
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.Func_)),
+				ParentPC: ric.ParentPC,
+			})
+		}
+	}
+	return ics, nil
+}
+
+// InlinedCall describes a call to an inlined function.
+type InlinedCall struct {
+	FuncID   uint8  // type of the called function
+	Name     string // name of called function
+	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall112 struct {
+	Parent   int16 // index of parent in the inltree, or < 0
+	FuncID   uint8 // type of the called function
+	_        byte
+	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
+	Line     int32 // line number of the call site
+	Func_    int32 // offset into pclntab for name of called function
+	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.20. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall120 struct {
+	FuncID    uint8 // type of the called function
+	_         [3]byte
+	NameOff   int32 // offset into pclntab for name of called function
+	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
+	StartLine int32 // line number of start of function (func keyword/TEXT directive)
+}
+
+func (f funcData) npcdata() uint32 { return f.field(7) }
+func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
+	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
+}
+
+func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.nfuncdata(numFuncFields) {
+		return ^uint32(0)
+	}
+	var off uint32
+	if f.t.version >= ver118 {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4 + // skip pcdata
+			uint32(i)*4 // index of i'th FUNCDATA
+	} else {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4
+		off += uint32(i) * f.t.ptrsize
+	}
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+func (f funcData) fieldOffset(n uint32) uint32 {
+	// In Go 1.18, the first field of _func changed
+	// from a uintptr entry PC to a uint32 entry offset.
+	sz0 := f.t.ptrsize
+	if f.t.version >= ver118 {
+		sz0 = 4
+	}
+	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
+}
+
+func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.npcdata() {
+		return ^uint32(0)
+	}
+	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
+		uint32(i)*4 // index of i'th PCDATA
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+// maxInlineTreeIndexValue returns the maximum value of the inline tree index
+// pc-value table in info. This is the only way to determine how many
+// IndexedCalls are in an inline tree, since the data of the tree itself is not
+// delimited in any way.
+func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
+	if info.npcdata() <= pcdata_InlTreeIndex {
+		return -1
+	}
+	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
+	p := t.pctab[off:]
+	val := int32(-1)
+	max := int32(-1)
+	var pc uint64
+	for t.step(&p, &pc, &val, pc == 0) {
+		if val > max {
+			max = val
+		}
+	}
+	return int(max)
+}
+
+type inlTree struct {
+	inlineTreeOffset uint32 // offset from go.func.* symbol
+	inlineTreeCount  int    // number of entries in inline tree
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go b/history-api/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
similarity index 100%
rename from history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go
rename to history-api/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go b/history-api/vendor/golang.org/x/vuln/internal/gosym/symtab.go
similarity index 100%
rename from history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go
rename to history-api/vendor/golang.org/x/vuln/internal/gosym/symtab.go
diff --git a/history-api/vendor/golang.org/x/vuln/internal/goversion/asm.go b/history-api/vendor/golang.org/x/vuln/internal/goversion/asm.go
new file mode 100644
index 00000000..1c165e60
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/goversion/asm.go
@@ -0,0 +1,349 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"encoding/binary"
+	"fmt"
+	"os"
+)
+
+type matcher [][]uint32
+
+const (
+	pWild    uint32 = 0xff00
+	pAddr    uint32 = 0x10000
+	pEnd     uint32 = 0x20000
+	pRelAddr uint32 = 0x30000
+
+	opMaybe = 1 + iota
+	opMust
+	opDone
+	opAnchor = 0x100
+	opSub8   = 0x200
+	opFlags  = opAnchor | opSub8
+)
+
+var amd64Matcher = matcher{
+	{opMaybe | opAnchor,
+		// __rt0_amd64_darwin:
+		//	JMP __rt0_amd64
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	lea ADDR(%rip), %rax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24, 0x48,
+		0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	mov $ADDR, %eax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24,
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// __rt0_amd64:
+		//	mov (%rsp), %rdi
+		//	lea 8(%rsp), %rsi
+		//	jmp runtime.rt0_g0
+		0x48, 0x8b, 0x3c, 0x24,
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	lea __libc_csu_fini(%rip), %r8
+		//	lea __libc_csu_init(%rip), %rcx
+		//	lea ADDR(%rip), %rdi # main
+		//	callq *xxx(%rip)
+		0x4c, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x3d, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0x15,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	push %rsp (1)
+		//	mov $__libc_csu_fini, %r8 (7)
+		//	mov $__libc_csu_init, %rcx (7)
+		//	mov $ADDR, %rdi # main (7)
+		//	callq *xxx(%rip)
+		0x54,
+		0x49, 0xc7, 0xc0, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc1, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc7, pAddr | pWild, pWild, pWild, pWild,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	lea ADDR(%rip), %rax # rt0_go
+		//	jmpq *%rax
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	mov $ADDR, %eax
+		//	jmpq *%rax
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	JMP runtime.rt0_go(SB)
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMust | opAnchor,
+		// rt0_go:
+		//	mov %rdi, %rax
+		//	mov %rsi, %rbx
+		//	sub %0x27, %rsp
+		//	and $0xfffffffffffffff0,%rsp
+		//	mov %rax,0x10(%rsp)
+		//	mov %rbx,0x18(%rsp)
+		0x48, 0x89, 0xf8,
+		0x48, 0x89, 0xf3,
+		0x48, 0x83, 0xec, 0x27,
+		0x48, 0x83, 0xe4, 0xf0,
+		0x48, 0x89, 0x44, 0x24, 0x10,
+		0x48, 0x89, 0x5c, 0x24, 0x18,
+	},
+	{opMust,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		//	lea other(%rip), %rdi
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0x8d, 0x05,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.hashinit
+		//	callq runtime.schedinit (ADDR)
+		//	pushq $main.main
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x68,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rax
+		//	test %rax, %rax
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc0,
+		0x75, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rbx
+		//	cmp $0x0, %rbx
+		//	jne 
+		//	lea "unknown"(%rip), %rbx
+		//	mov %rbx, ADDR(%rip)
+		//	movq $7, (ADDR+8)(%rip)
+		0x48, 0x8b, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x83, 0xfb, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	lea "unknown"(%rip), %rax
+		//	mov %rax, ADDR(%rip)
+		//	lea ADDR(%rip), %rax
+		//	movq $7, 8(%rax)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		//	test %eax, %eax
+		//	jne 
+		//	lea "unknown"(RIP), %rax
+		//	mov %rax, ADDR(%rip)
+		0x48, 0x85, 0xc0, 0x75, pWild, 0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild, 0x48, 0x89, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rcx
+		//	test %rcx, %rcx
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc9,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+}
+
+var DebugMatch bool
+
+func (m matcher) match(f exe, addr uint64) (uint64, bool) {
+	data, err := f.ReadData(addr, 512)
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
+	}
+	if err != nil {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "match: %v\n", err)
+		}
+		return 0, false
+	}
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
+	}
+Matchers:
+	for pc, p := range m {
+		op := p[0]
+		p = p[1:]
+	Search:
+		for i := 0; i <= len(data)-len(p); i++ {
+			a := -1
+			e := -1
+			if i > 0 && op&opAnchor != 0 {
+				break
+			}
+			for j := 0; j < len(p); j++ {
+				b := byte(p[j])
+				m := byte(p[j] >> 8)
+				if data[i+j]&^m != b {
+					continue Search
+				}
+				if p[j]&pAddr != 0 {
+					a = j
+				}
+				if p[j]&pEnd != 0 {
+					e = j + 1
+				}
+			}
+			// matched
+			if DebugMatch {
+				fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
+			}
+			if a != -1 {
+				val := uint64(int32(binary.LittleEndian.Uint32(data[i+a:])))
+				if e == -1 {
+					addr = val
+				} else {
+					addr += uint64(i+e) + val
+				}
+				if op&opSub8 != 0 {
+					addr -= 8
+				}
+			}
+			if op&^opFlags == opDone {
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "done %x\n", addr)
+				}
+				return addr, true
+			}
+			if a != -1 {
+				// changed addr, so reload
+				data, err = f.ReadData(addr, 512)
+				if err != nil {
+					return 0, false
+				}
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
+				}
+			}
+			continue Matchers
+		}
+		// not matched
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
+		}
+		if op&^opFlags == opMust {
+			return 0, false
+		}
+	}
+	// ran off end of matcher
+	return 0, false
+}
+
+func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
+	entry := f.Entry()
+	if entry == 0 {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "missing entry!\n")
+		}
+		return
+	}
+	addr, ok := amd64Matcher.match(f, entry)
+	if !ok {
+		return
+	}
+	v, err := readBuildVersion(f, addr, 16)
+	if err != nil {
+		return
+	}
+	return true, v
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/goversion/exe.go b/history-api/vendor/golang.org/x/vuln/internal/goversion/exe.go
new file mode 100644
index 00000000..d833bfe6
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/goversion/exe.go
@@ -0,0 +1,324 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+type sym struct {
+	Name string
+	Addr uint64
+	Size uint64
+}
+
+type exe interface {
+	AddrSize() int // bytes
+	ReadData(addr, size uint64) ([]byte, error)
+	Symbols() ([]sym, error)
+	SectionNames() []string
+	Close() error
+	ByteOrder() binary.ByteOrder
+	Entry() uint64
+	TextRange() (uint64, uint64)
+	RODataRange() (uint64, uint64)
+}
+
+func openExe(file string) (exe, error) {
+	f, err := os.Open(file)
+	if err != nil {
+		return nil, err
+	}
+	data := make([]byte, 16)
+	if _, err := io.ReadFull(f, data); err != nil {
+		return nil, err
+	}
+	f.Seek(0, 0)
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &elfExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &peExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &machoExe{f, e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type elfExe struct {
+	os *os.File
+	f  *elf.File
+}
+
+func (x *elfExe) AddrSize() int { return 0 }
+
+func (x *elfExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *elfExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *elfExe) Entry() uint64 { return x.f.Entry }
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		// The following line was commented from the original code.
+		//fmt.Printf("%#x %#x %#x\n", addr, prog.Vaddr, prog.Vaddr+prog.Filesz)
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *elfExe) Symbols() ([]sym, error) {
+	syms, err := x.f.Symbols()
+	if err != nil {
+		return nil, err
+	}
+	var out []sym
+	for _, s := range syms {
+		out = append(out, sym{s.Name, s.Value, s.Size})
+	}
+	return out, nil
+}
+
+func (x *elfExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *elfExe) TextRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *elfExe) RODataRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == elf.PF_R {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == (elf.PF_R|elf.PF_X) {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+type peExe struct {
+	os *os.File
+	f  *pe.File
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) AddrSize() int {
+	if x.f.Machine == pe.IMAGE_FILE_MACHINE_AMD64 {
+		return 8
+	}
+	return 4
+}
+
+func (x *peExe) ByteOrder() binary.ByteOrder { return binary.LittleEndian }
+
+func (x *peExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *peExe) Entry() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase + oh.AddressOfEntryPoint)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase + uint64(oh.AddressOfEntryPoint)
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	data := make([]byte, size)
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr+size-1 <= uint64(sect.VirtualAddress+sect.Size-1) {
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *peExe) Symbols() ([]sym, error) {
+	base := x.imageBase()
+	var out []sym
+	for _, s := range x.f.Symbols {
+		if s.SectionNumber <= 0 || int(s.SectionNumber) > len(x.f.Sections) {
+			continue
+		}
+		sect := x.f.Sections[s.SectionNumber-1]
+		out = append(out, sym{s.Name, uint64(s.Value) + base + uint64(sect.VirtualAddress), 0})
+	}
+	return out, nil
+}
+
+func (x *peExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *peExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty section.
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 {
+			return uint64(sect.VirtualAddress) + x.imageBase(), uint64(sect.VirtualAddress+sect.Size) + x.imageBase()
+		}
+	}
+	return 0, 0
+}
+
+func (x *peExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
+
+type machoExe struct {
+	os *os.File
+	f  *macho.File
+}
+
+func (x *machoExe) AddrSize() int {
+	if x.f.Cpu&0x01000000 != 0 {
+		return 8
+	}
+	return 4
+}
+
+func (x *machoExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *machoExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *machoExe) Entry() uint64 {
+	for _, load := range x.f.Loads {
+		b, ok := load.(macho.LoadBytes)
+		if !ok {
+			continue
+		}
+		// TODO: Other thread states.
+		bo := x.f.ByteOrder
+		const x86_THREAD_STATE64 = 4
+		cmd, siz := macho.LoadCmd(bo.Uint32(b[0:4])), bo.Uint32(b[4:8])
+		if cmd == macho.LoadCmdUnixThread && siz == 184 && bo.Uint32(b[8:12]) == x86_THREAD_STATE64 {
+			return bo.Uint64(b[144:])
+		}
+	}
+	return 0
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	data := make([]byte, size)
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr+size-1 <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *machoExe) Symbols() ([]sym, error) {
+	var out []sym
+	for _, s := range x.f.Symtab.Syms {
+		out = append(out, sym{s.Name, s.Value, 0})
+	}
+	return out, nil
+}
+
+func (x *machoExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *machoExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty segment.
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Name != "__PAGEZERO" && seg.Addr != 0 && seg.Filesz != 0 {
+			return seg.Addr, seg.Addr + seg.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *machoExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/goversion/read.go b/history-api/vendor/golang.org/x/vuln/internal/goversion/read.go
new file mode 100644
index 00000000..f298ef07
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/goversion/read.go
@@ -0,0 +1,246 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package goversion reports the Go version used to build program executables.
+//
+// This is a copy of rsc.io/goversion/version. We renamed the package to goversion
+// to differentiate between version package in standard library that we also use.
+package goversion
+
+import (
+	"bytes"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// Version is the information reported by ReadExe.
+type Version struct {
+	Release        string // Go version (runtime.Version in the program)
+	ModuleInfo     string // program's module information
+	BoringCrypto   bool   // program uses BoringCrypto
+	StandardCrypto bool   // program uses standard crypto (replaced by BoringCrypto)
+	FIPSOnly       bool   // program imports "crypto/tls/fipsonly"
+}
+
+// ReadExe reports information about the Go version used to build
+// the program executable named by file.
+func ReadExe(file string) (Version, error) {
+	var v Version
+	f, err := openExe(file)
+	if err != nil {
+		return v, err
+	}
+	defer f.Close()
+	isGo := false
+	for _, name := range f.SectionNames() {
+		if name == ".note.go.buildid" {
+			isGo = true
+		}
+	}
+	syms, symsErr := f.Symbols()
+	isGccgo := false
+	for _, sym := range syms {
+		name := sym.Name
+		if name == "runtime.main" || name == "main.main" {
+			isGo = true
+		}
+		if strings.HasPrefix(name, "runtime.") && strings.HasSuffix(name, "$descriptor") {
+			isGccgo = true
+		}
+		if name == "runtime.buildVersion" {
+			isGo = true
+			release, err := readBuildVersion(f, sym.Addr, sym.Size)
+			if err != nil {
+				return v, err
+			}
+			v.Release = release
+		}
+		// Note: Using strings.HasPrefix because Go 1.17+ adds ".abi0" to many of these symbols.
+		if strings.Contains(name, "_Cfunc__goboringcrypto_") || strings.HasPrefix(name, "crypto/internal/boring/sig.BoringCrypto") {
+			v.BoringCrypto = true
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.FIPSOnly") {
+			v.FIPSOnly = true
+		}
+		for _, re := range standardCryptoNames {
+			if re.MatchString(name) {
+				v.StandardCrypto = true
+			}
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.StandardCrypto") {
+			v.StandardCrypto = true
+		}
+	}
+
+	if DebugMatch {
+		v.Release = ""
+	}
+	if err := findModuleInfo(&v, f); err != nil {
+		return v, err
+	}
+	if v.Release == "" {
+		g, release := readBuildVersionX86Asm(f)
+		if g {
+			isGo = true
+			v.Release = release
+			if err := findCryptoSigs(&v, f); err != nil {
+				return v, err
+			}
+		}
+	}
+	if isGccgo && v.Release == "" {
+		isGo = true
+		v.Release = "gccgo (version unknown)"
+	}
+	if !isGo && symsErr != nil {
+		return v, symsErr
+	}
+
+	if !isGo {
+		return v, errors.New("not a Go executable")
+	}
+	if v.Release == "" {
+		v.Release = "unknown Go version"
+	}
+	return v, nil
+}
+
+var re = regexp.MustCompile
+
+var standardCryptoNames = []*regexp.Regexp{
+	re(`^crypto/sha1\.\(\*digest\)`),
+	re(`^crypto/sha256\.\(\*digest\)`),
+	re(`^crypto/rand\.\(\*devReader\)`),
+	re(`^crypto/rsa\.encrypt(\.abi.)?$`),
+	re(`^crypto/rsa\.decrypt(\.abi.)?$`),
+}
+
+func readBuildVersion(f exe, addr, size uint64) (string, error) {
+	if size == 0 {
+		size = uint64(f.AddrSize() * 2)
+	}
+	if size != 8 && size != 16 {
+		return "", fmt.Errorf("invalid size for runtime.buildVersion")
+	}
+	data, err := f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion: %v", err)
+	}
+
+	if size == 8 {
+		addr = uint64(f.ByteOrder().Uint32(data))
+		size = uint64(f.ByteOrder().Uint32(data[4:]))
+	} else {
+		addr = f.ByteOrder().Uint64(data)
+		size = f.ByteOrder().Uint64(data[8:])
+	}
+	if size > 1000 {
+		return "", fmt.Errorf("implausible string size %d for runtime.buildVersion", size)
+	}
+
+	data, err = f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion string data: %v", err)
+	}
+	return string(data), nil
+}
+
+// Code signatures that indicate BoringCrypto or crypto/internal/fipsonly.
+// These are not byte literals in order to avoid the actual
+// byte signatures appearing in the goversion binary,
+// because on some systems you can't tell rodata from text.
+var (
+	sigBoringCrypto, _   = hex.DecodeString("EB1DF448F44BF4B332F52813A3B450D441CC2485F001454E92101B1D2F1950C3")
+	sigStandardCrypto, _ = hex.DecodeString("EB1DF448F44BF4BAEE4DFA9851CA56A91145E83E99C59CF911CB8E80DAF12FC3")
+	sigFIPSOnly, _       = hex.DecodeString("EB1DF448F44BF4363CB9CE9D68047D31F28D325D5CA5873F5D80CAF6D6151BC3")
+)
+
+func findCryptoSigs(v *Version, f exe) error {
+	const maxSigLen = 1 << 10
+	start, end := f.TextRange()
+	for addr := start; addr < end; {
+		size := uint64(1 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveSig(data, sigBoringCrypto) {
+			v.BoringCrypto = true
+		}
+		if haveSig(data, sigFIPSOnly) {
+			v.FIPSOnly = true
+		}
+		if haveSig(data, sigStandardCrypto) {
+			v.StandardCrypto = true
+		}
+		if addr+size < end {
+			size -= maxSigLen
+		}
+		addr += size
+	}
+	return nil
+}
+
+func haveSig(data, sig []byte) bool {
+	const align = 16
+	for {
+		i := bytes.Index(data, sig)
+		if i < 0 {
+			return false
+		}
+		if i&(align-1) == 0 {
+			return true
+		}
+		// Found unaligned match; unexpected but
+		// skip to next aligned boundary and keep searching.
+		data = data[(i+align-1)&^(align-1):]
+	}
+}
+
+func findModuleInfo(v *Version, f exe) error {
+	const maxModInfo = 128 << 10
+	start, end := f.RODataRange()
+	for addr := start; addr < end; {
+		size := uint64(4 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveModuleInfo(data, v) {
+			return nil
+		}
+		if addr+size < end {
+			size -= maxModInfo
+		}
+		addr += size
+	}
+	return nil
+}
+
+var (
+	infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+	infoEnd, _   = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func haveModuleInfo(data []byte, v *Version) bool {
+	i := bytes.Index(data, infoStart)
+	if i < 0 {
+		return false
+	}
+	j := bytes.Index(data[i:], infoEnd)
+	if j < 0 {
+		return false
+	}
+	v.ModuleInfo = string(data[i+len(infoStart) : i+j])
+	return true
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
new file mode 100644
index 00000000..377a3787
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
@@ -0,0 +1,241 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package govulncheck contains the JSON output structs for govulncheck.
+//
+// govulncheck supports streaming JSON by emitting a series of Message
+// objects as it analyzes user code and discovers vulnerabilities.
+// Streaming JSON is useful for displaying progress in real-time for
+// large projects where govulncheck execution might take some time.
+//
+// govulncheck JSON emits configuration used to perform the analysis,
+// a user-friendly message about what is being analyzed, and the
+// vulnerability findings. Findings for the same vulnerability can
+// can be emitted several times. For instance, govulncheck JSON will
+// emit a finding when it sees that a vulnerable module is required
+// before proceeding to check if the vulnerability is imported or called.
+// Please see documentation on Message and related types for precise
+// details on the stream encoding.
+//
+// There are no guarantees on the order of messages. The pattern of emitted
+// messages can change in the future. Clients can follow code in handler.go
+// for consuming the streaming JSON programmatically.
+package govulncheck
+
+import (
+	"time"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+const (
+	// ProtocolVersion is the current protocol version this file implements
+	ProtocolVersion = "v1.0.0"
+)
+
+// Message is an entry in the output stream. It will always have exactly one
+// field filled in.
+type Message struct {
+	Config   *Config   `json:"config,omitempty"`
+	Progress *Progress `json:"progress,omitempty"`
+	SBOM     *SBOM     `json:"SBOM,omitempty"`
+	// OSV is emitted for every vulnerability in the current database
+	// that applies to user modules regardless of their version. If a
+	// module is being used at a vulnerable version, the corresponding
+	// OSV will be referenced in Findings depending on the type of usage
+	// and the desired scan level.
+	OSV     *osv.Entry `json:"osv,omitempty"`
+	Finding *Finding   `json:"finding,omitempty"`
+}
+
+// Config must occur as the first message of a stream and informs the client
+// about the information used to generate the findings.
+// The only required field is the protocol version.
+type Config struct {
+	// ProtocolVersion specifies the version of the JSON protocol.
+	ProtocolVersion string `json:"protocol_version"`
+
+	// ScannerName is the name of the tool, for example, govulncheck.
+	//
+	// We expect this JSON format to be used by other tools that wrap
+	// govulncheck, which will have a different name.
+	ScannerName string `json:"scanner_name,omitempty"`
+
+	// ScannerVersion is the version of the tool.
+	ScannerVersion string `json:"scanner_version,omitempty"`
+
+	// DB is the database used by the tool, for example,
+	// vuln.go.dev.
+	DB string `json:"db,omitempty"`
+
+	// LastModified is the last modified time of the data source.
+	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
+
+	// GoVersion is the version of Go used for analyzing standard library
+	// vulnerabilities.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// ScanLevel instructs govulncheck to analyze at a specific level of detail.
+	// Valid values include module, package and symbol.
+	ScanLevel ScanLevel `json:"scan_level,omitempty"`
+
+	// ScanMode instructs govulncheck how to interpret the input and
+	// what to do with it. Valid values are source, binary, query,
+	// and extract.
+	ScanMode ScanMode `json:"scan_mode,omitempty"`
+}
+
+// SBOM contains minimal information about the artifacts govulncheck is scanning.
+type SBOM struct {
+	// The go version used by govulncheck when scanning, which also defines
+	// the version of the standard library used for detecting vulns.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// The set of modules included in the scan.
+	Modules []*Module `json:"modules,omitempty"`
+
+	// The roots of the scan, as package paths.
+	// For binaries, this will be the main package.
+	// For source code, this will be the packages matching the provided package patterns.
+	Roots []string `json:"roots,omitempty"`
+}
+
+type Module struct {
+	// The full module path.
+	Path string `json:"path,omitempty"`
+
+	// The version of the module.
+	Version string `json:"version,omitempty"`
+}
+
+// Progress messages are informational only, intended to allow users to monitor
+// the progress of a long running scan.
+// A stream must remain fully valid and able to be interpreted with all progress
+// messages removed.
+type Progress struct {
+	// A time stamp for the message.
+	Timestamp *time.Time `json:"time,omitempty"`
+
+	// Message is the progress message.
+	Message string `json:"message,omitempty"`
+}
+
+// Finding contains information on a discovered vulnerability. Each vulnerability
+// will likely have multiple findings in JSON mode. This is because govulncheck
+// emits findings as it does work, and therefore could emit one module level,
+// one package level, and potentially multiple symbol level findings depending
+// on scan level.
+// Multiple symbol level findings can be emitted when multiple symbols of the
+// same vuln are called or govulncheck decides to show multiple traces for the
+// same symbol.
+type Finding struct {
+	// OSV is the id of the detected vulnerability.
+	OSV string `json:"osv,omitempty"`
+
+	// FixedVersion is the module version where the vulnerability was
+	// fixed. This is empty if a fix is not available.
+	//
+	// If there are multiple fixed versions in the OSV report, this will
+	// be the fixed version in the latest range event for the OSV report.
+	//
+	// For example, if the range events are
+	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
+	// will be empty.
+	//
+	// For the stdlib, we will show the fixed version closest to the
+	// Go version that is used. For example, if a fix is available in 1.17.5 and
+	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
+	// fixed version.
+	FixedVersion string `json:"fixed_version,omitempty"`
+
+	// Trace contains an entry for each frame in the trace.
+	//
+	// Frames are sorted starting from the imported vulnerable symbol
+	// until the entry point. The first frame in Frames should match
+	// Symbol.
+	//
+	// In binary mode, trace will contain a single-frame with no position
+	// information.
+	//
+	// For module level source findings, the trace will contain a single-frame
+	// with no symbol, position, or package information. For package level source
+	// findings, the trace will contain a single-frame with no symbol or position
+	// information.
+	Trace []*Frame `json:"trace,omitempty"`
+}
+
+// Frame represents an entry in a finding trace.
+type Frame struct {
+	// Module is the module path of the module containing this symbol.
+	//
+	// Importable packages in the standard library will have the path "stdlib".
+	Module string `json:"module"`
+
+	// Version is the module version from the build graph.
+	Version string `json:"version,omitempty"`
+
+	// Package is the import path.
+	Package string `json:"package,omitempty"`
+
+	// Function is the function name.
+	Function string `json:"function,omitempty"`
+
+	// Receiver is the receiver type if the called symbol is a method.
+	//
+	// The client can create the final symbol name by
+	// prepending Receiver to FuncName.
+	Receiver string `json:"receiver,omitempty"`
+
+	// Position describes an arbitrary source position
+	// including the file, line, and column location.
+	// A Position is valid if the line number is > 0.
+	//
+	// The filenames are relative to the directory of
+	// the enclosing module and always use "/" for
+	// portability.
+	Position *Position `json:"position,omitempty"`
+}
+
+// Position represents arbitrary source position.
+type Position struct {
+	Filename string `json:"filename,omitempty"` // filename, if any
+	Offset   int    `json:"offset"`             // byte offset, starting at 0
+	Line     int    `json:"line"`               // line number, starting at 1
+	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
+}
+
+// ScanLevel represents the detail level at which a scan occurred.
+// This can be necessary to correctly interpret the findings, for instance if
+// a scan is at symbol level and a finding does not have a symbol it means the
+// vulnerability was imported but not called. If the scan however was at
+// "package" level, that determination cannot be made.
+type ScanLevel string
+
+const (
+	ScanLevelModule  = "module"
+	ScanLevelPackage = "package"
+	ScanLevelSymbol  = "symbol"
+)
+
+// WantSymbols can be used to check whether the scan level is one that is able
+// to generate symbol-level findings.
+func (l ScanLevel) WantSymbols() bool { return l == ScanLevelSymbol }
+
+// WantPackages can be used to check whether the scan level is one that is able
+// to generate package-level findings.
+func (l ScanLevel) WantPackages() bool { return l == ScanLevelPackage || l == ScanLevelSymbol }
+
+// ScanMode represents the mode in which a scan occurred. This can
+// be necessary to correctly to interpret findings. For instance,
+// a binary can be checked for vulnerabilities or the user just wants
+// to extract minimal data necessary for the vulnerability check.
+type ScanMode string
+
+const (
+	ScanModeSource  = "source"
+	ScanModeBinary  = "binary"
+	ScanModeConvert = "convert"
+	ScanModeQuery   = "query"
+	ScanModeExtract = "extract" // currently, only binary extraction is supported
+)
diff --git a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
index 5676ea94..5ce7d532 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
@@ -17,6 +17,9 @@ type Handler interface {
 	// Config communicates introductory message to the user.
 	Config(config *Config) error
 
+	// SBOM shows information about what govulncheck is scanning.
+	SBOM(sbom *SBOM) error
+
 	// Progress is called to display a progress message.
 	Progress(progress *Progress) error
 
@@ -45,6 +48,9 @@ func HandleJSON(from io.Reader, to Handler) error {
 		if msg.Progress != nil {
 			err = to.Progress(msg.Progress)
 		}
+		if msg.SBOM != nil {
+			err = to.SBOM(msg.SBOM)
+		}
 		if msg.OSV != nil {
 			err = to.OSV(msg.OSV)
 		}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go
deleted file mode 100644
index d1ea78af..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package govulncheck
-
-import (
-	"encoding/json"
-
-	"io"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-type jsonHandler struct {
-	enc *json.Encoder
-}
-
-// NewJSONHandler returns a handler that writes govulncheck output as json.
-func NewJSONHandler(w io.Writer) Handler {
-	enc := json.NewEncoder(w)
-	enc.SetIndent("", "  ")
-	return &jsonHandler{enc: enc}
-}
-
-// Config writes config block in JSON to the underlying writer.
-func (h *jsonHandler) Config(config *Config) error {
-	return h.enc.Encode(Message{Config: config})
-}
-
-// Progress writes a progress message in JSON to the underlying writer.
-func (h *jsonHandler) Progress(progress *Progress) error {
-	return h.enc.Encode(Message{Progress: progress})
-}
-
-// OSV writes an osv entry in JSON to the underlying writer.
-func (h *jsonHandler) OSV(entry *osv.Entry) error {
-	return h.enc.Encode(Message{OSV: entry})
-}
-
-// Finding writes a finding in JSON to the underlying writer.
-func (h *jsonHandler) Finding(finding *Finding) error {
-	return h.enc.Encode(Message{Finding: finding})
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
new file mode 100644
index 00000000..b1586e09
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
@@ -0,0 +1,49 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package govulncheck
+
+import (
+	"encoding/json"
+
+	"io"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+type jsonHandler struct {
+	enc *json.Encoder
+}
+
+// NewJSONHandler returns a handler that writes govulncheck output as json.
+func NewJSONHandler(w io.Writer) Handler {
+	enc := json.NewEncoder(w)
+	enc.SetIndent("", "  ")
+	return &jsonHandler{enc: enc}
+}
+
+// Config writes config block in JSON to the underlying writer.
+func (h *jsonHandler) Config(config *Config) error {
+	return h.enc.Encode(Message{Config: config})
+}
+
+// Progress writes a progress message in JSON to the underlying writer.
+func (h *jsonHandler) Progress(progress *Progress) error {
+	return h.enc.Encode(Message{Progress: progress})
+}
+
+// SBOM writes the SBOM block in JSON to the underlying writer.
+func (h *jsonHandler) SBOM(sbom *SBOM) error {
+	return h.enc.Encode(Message{SBOM: sbom})
+}
+
+// OSV writes an osv entry in JSON to the underlying writer.
+func (h *jsonHandler) OSV(entry *osv.Entry) error {
+	return h.enc.Encode(Message{OSV: entry})
+}
+
+// Finding writes a finding in JSON to the underlying writer.
+func (h *jsonHandler) Finding(finding *Finding) error {
+	return h.enc.Encode(Message{Finding: finding})
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go b/history-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go
deleted file mode 100644
index 3c1f2bdd..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package result contains the JSON output structs for govulncheck.
-package govulncheck
-
-import (
-	"time"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-const (
-	// ProtocolVersion is the current protocol version this file implements
-	ProtocolVersion = "v0.1.0"
-)
-
-// Message is an entry in the output stream. It will always have exactly one
-// field filled in.
-type Message struct {
-	Config   *Config    `json:"config,omitempty"`
-	Progress *Progress  `json:"progress,omitempty"`
-	OSV      *osv.Entry `json:"osv,omitempty"`
-	Finding  *Finding   `json:"finding,omitempty"`
-}
-
-type Config struct {
-	// ProtocolVersion specifies the version of the JSON protocol.
-	ProtocolVersion string `json:"protocol_version,omitempty"`
-
-	// ScannerName is the name of the tool, for example, govulncheck.
-	//
-	// We expect this JSON format to be used by other tools that wrap
-	// govulncheck, which will have a different name.
-	ScannerName string `json:"scanner_name,omitempty"`
-
-	// ScannerVersion is the version of the tool.
-	ScannerVersion string `json:"scanner_version,omitempty"`
-
-	// DB is the database used by the tool, for example,
-	// vuln.go.dev.
-	DB string `json:"db,omitempty"`
-
-	// LastModified is the last modified time of the data source.
-	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
-
-	// GoVersion is the version of Go used for analyzing standard library
-	// vulnerabilities.
-	GoVersion string `json:"go_version,omitempty"`
-
-	// ScanLevel instructs vulncheck to analyze at a specific level of detail.
-	// Valid values include module, package and symbol.
-	ScanLevel ScanLevel `json:"scan_level,omitempty"`
-}
-
-type Progress struct {
-	// A time stamp for the message.
-	Timestamp *time.Time `json:"time,omitempty"`
-
-	// Message is the progress message.
-	Message string `json:"message,omitempty"`
-}
-
-// Vuln represents a single OSV entry.
-type Finding struct {
-	// OSV is the id of the detected vulnerability.
-	OSV string `json:"osv,omitempty"`
-
-	// FixedVersion is the module version where the vulnerability was
-	// fixed. This is empty if a fix is not available.
-	//
-	// If there are multiple fixed versions in the OSV report, this will
-	// be the fixed version in the latest range event for the OSV report.
-	//
-	// For example, if the range events are
-	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
-	// will be empty.
-	//
-	// For the stdlib, we will show the fixed version closest to the
-	// Go version that is used. For example, if a fix is available in 1.17.5 and
-	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
-	// fixed version.
-	FixedVersion string `json:"fixed_version,omitempty"`
-
-	// Trace contains an entry for each frame in the trace.
-	//
-	// Frames are sorted starting from the imported vulnerable symbol
-	// until the entry point. The first frame in Frames should match
-	// Symbol.
-	//
-	// In binary mode, trace will contain a single-frame with no position
-	// information.
-	//
-	// When a package is imported but no vulnerable symbol is called, the trace
-	// will contain a single-frame with no symbol or position information.
-	Trace []*Frame `json:"trace,omitempty"`
-}
-
-// Frame represents an entry in a finding trace.
-type Frame struct {
-	// Module is the module path of the module containing this symbol.
-	//
-	// Importable packages in the standard library will have the path "stdlib".
-	Module string `json:"module"`
-
-	// Version is the module version from the build graph.
-	Version string `json:"version,omitempty"`
-
-	// Package is the import path.
-	Package string `json:"package,omitempty"`
-
-	// Function is the function name.
-	Function string `json:"function,omitempty"`
-
-	// Receiver is the receiver type if the called symbol is a method.
-	//
-	// The client can create the final symbol name by
-	// prepending Receiver to FuncName.
-	Receiver string `json:"receiver,omitempty"`
-
-	// Position describes an arbitrary source position
-	// including the file, line, and column location.
-	// A Position is valid if the line number is > 0.
-	Position *Position `json:"position,omitempty"`
-}
-
-// Position is a copy of token.Position used to marshal/unmarshal
-// JSON correctly.
-type Position struct {
-	Filename string `json:"filename,omitempty"` // filename, if any
-	Offset   int    `json:"offset"`             // offset, starting at 0
-	Line     int    `json:"line"`               // line number, starting at 1
-	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
-}
-
-type ScanLevel string
-
-const (
-	scanLevelModule  = "module"
-	scanLevelPackage = "package"
-	scanLevelSymbol  = "symbol"
-)
-
-func (l ScanLevel) WantSymbols() bool { return l == scanLevelSymbol }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/internal.go b/history-api/vendor/golang.org/x/vuln/internal/internal.go
index 64c5e8d5..8e6b7f5c 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/internal.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/internal.go
@@ -24,5 +24,9 @@ const (
 
 	// UnknownModulePath is a special module path for when we cannot work out
 	// the module for a package.
-	UnknownModulePath = "unknown"
+	UnknownModulePath = "unknown-module"
+
+	// UnknownPackagePath is a special package path for when we cannot work out
+	// the packagUnknownModulePath = "unknown"
+	UnknownPackagePath = "unknown-package"
 )
diff --git a/history-api/vendor/golang.org/x/vuln/internal/openvex/handler.go b/history-api/vendor/golang.org/x/vuln/internal/openvex/handler.go
new file mode 100644
index 00000000..a2d32829
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/openvex/handler.go
@@ -0,0 +1,261 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"io"
+	"slices"
+	"time"
+
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+)
+
+type findingLevel int
+
+const (
+	invalid findingLevel = iota
+	required
+	imported
+	called
+)
+
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	sbom *govulncheck.SBOM
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(cfg *govulncheck.Config) error {
+	h.cfg = cfg
+	return nil
+}
+
+func (h *handler) Progress(progress *govulncheck.Progress) error {
+	return nil
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	h.sbom = s
+	return nil
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// foundAtLevel returns the level at which a specific finding is present in the
+// scanned product.
+func foundAtLevel(f *govulncheck.Finding) findingLevel {
+	frame := f.Trace[0]
+	if frame.Function != "" {
+		return called
+	}
+	if frame.Package != "" {
+		return imported
+	}
+	return required
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is at the same level of precision.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print the vex json to w.
+// This is needed as vex is not streamed.
+func (h *handler) Flush() error {
+	doc := toVex(h)
+	out, err := json.MarshalIndent(doc, "", "  ")
+	if err != nil {
+		return err
+	}
+	_, err = h.w.Write(out)
+	return err
+}
+
+func toVex(h *handler) Document {
+	doc := Document{
+		Context:    ContextURI,
+		Author:     DefaultAuthor,
+		Timestamp:  time.Now().UTC(),
+		Version:    1,
+		Tooling:    Tooling,
+		Statements: statements(h),
+	}
+
+	id := hashVex(doc)
+	doc.ID = "govulncheck/vex:" + id
+	return doc
+}
+
+// Given a slice of findings, returns those findings as a set of subcomponents
+// that are unique per the vulnerable artifact's PURL.
+func subcomponentSet(findings []*govulncheck.Finding) []Component {
+	var scs []Component
+	seen := make(map[string]bool)
+	for _, f := range findings {
+		purl := purlFromFinding(f)
+		if !seen[purl] {
+			scs = append(scs, Component{
+				ID: purlFromFinding(f),
+			})
+			seen[purl] = true
+		}
+	}
+	return scs
+}
+
+// statements combines all OSVs found by govulncheck and generates the list of
+// vex statements with the proper affected level and justification to match the
+// openVex specification.
+func statements(h *handler) []Statement {
+	var scanLevel findingLevel
+	switch h.cfg.ScanLevel {
+	case govulncheck.ScanLevelModule:
+		scanLevel = required
+	case govulncheck.ScanLevelPackage:
+		scanLevel = imported
+	case govulncheck.ScanLevelSymbol:
+		scanLevel = called
+	}
+
+	var statements []Statement
+	for id, osv := range h.osvs {
+		// if there are no findings emitted for a given OSV that means that
+		// the vulnerable module is not required at a vulnerable version.
+		if len(h.findings[id]) == 0 {
+			continue
+		}
+		description := osv.Summary
+		if description == "" {
+			description = osv.Details
+		}
+
+		s := Statement{
+			Vulnerability: Vulnerability{
+				ID:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", id),
+				Name:        id,
+				Description: description,
+				Aliases:     osv.Aliases,
+			},
+			Products: []Product{
+				{
+					Component:     Component{ID: DefaultPID},
+					Subcomponents: subcomponentSet(h.findings[id]),
+				},
+			},
+		}
+
+		// Findings are guaranteed to be at the same level, so we can just check the first element
+		fLevel := foundAtLevel(h.findings[id][0])
+		if fLevel >= scanLevel {
+			s.Status = StatusAffected
+		} else {
+			s.Status = StatusNotAffected
+			s.ImpactStatement = Impact
+			s.Justification = JustificationNotPresent
+			// We only reach this case if running in symbol mode
+			if fLevel == imported {
+				s.Justification = JustificationNotExecuted
+			}
+		}
+		statements = append(statements, s)
+	}
+
+	slices.SortFunc(statements, func(a, b Statement) int {
+		if a.Vulnerability.ID > b.Vulnerability.ID {
+			return 1
+		}
+		if a.Vulnerability.ID < b.Vulnerability.ID {
+			return -1
+		}
+		// this should never happen in practice, since statements are being
+		// populated from a map with the vulnerability IDs as keys
+		return 0
+	})
+	return statements
+}
+
+func hashVex(doc Document) string {
+	// json.Marshal should never error here (because of the structure of Document).
+	// If an error does occur, it won't be a jsonerror, but instead a panic
+	d := Document{
+		Context:    doc.Context,
+		ID:         doc.ID,
+		Author:     doc.Author,
+		Version:    doc.Version,
+		Tooling:    doc.Tooling,
+		Statements: doc.Statements,
+	}
+	out, err := json.Marshal(d)
+	if err != nil {
+		panic(err)
+	}
+	return fmt.Sprintf("%x", sha256.Sum256(out))
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/openvex/purl.go b/history-api/vendor/golang.org/x/vuln/internal/openvex/purl.go
new file mode 100644
index 00000000..fc1cea9c
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/openvex/purl.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"net/url"
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// The PURL is printed as: pkg:golang/MODULE_PATH@VERSION
+// Conceptually there is no namespace and the name is entirely defined by
+// the module path. See https://github.com/package-url/purl-spec/issues/63
+// for further disucssion.
+
+const suffix = "pkg:golang/"
+
+type purl struct {
+	name    string
+	version string
+}
+
+func (p *purl) String() string {
+	var b strings.Builder
+	b.WriteString(suffix)
+	b.WriteString(url.PathEscape(p.name))
+	if p.version != "" {
+		b.WriteString("@")
+		b.WriteString(p.version)
+	}
+	return b.String()
+}
+
+// purlFromFinding takes a govulncheck finding and generates a purl to the
+// vulnerable dependency.
+func purlFromFinding(f *govulncheck.Finding) string {
+	purl := purl{
+		name:    f.Trace[0].Module,
+		version: f.Trace[0].Version,
+	}
+
+	return purl.String()
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/openvex/vex.go b/history-api/vendor/golang.org/x/vuln/internal/openvex/vex.go
new file mode 100644
index 00000000..18779f70
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/openvex/vex.go
@@ -0,0 +1,113 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vex defines the Vulnerability EXchange Format (VEX) types
+// supported by govulncheck.
+//
+// These types match the OpenVEX standard. See https://github.com/openvex for
+// more information on VEX and OpenVEX.
+//
+// This is intended to be the minimimal amount of information required to output
+// a complete VEX document according to the specification.
+package openvex
+
+import "time"
+
+const (
+	ContextURI = "https://openvex.dev/ns/v0.2.0"
+	Tooling    = "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Impact     = "Govulncheck determined that the vulnerable code isn't called"
+
+	DefaultAuthor = "Unknown Author"
+	DefaultPID    = "Unknown Product"
+
+	// The following are defined by the VEX standard.
+	StatusAffected    = "affected"
+	StatusNotAffected = "not_affected"
+
+	// The following are defined by the VEX standard.
+	JustificationNotExecuted = "vulnerable_code_not_in_execute_path"
+	JustificationNotPresent  = "vulnerable_code_not_present"
+)
+
+// Document is the top-level struct for a VEX document.
+type Document struct {
+	// Context is an IRI pointing to the version of openVEX being used by the doc
+	// For govulncheck, it will always be https://openvex.dev/ns/v0.2.0
+	Context string `json:"@context,omitempty"`
+
+	// ID is the identifying string for the VEX document.
+	// govulncheck/vex-[content-based-hash]
+	ID string `json:"@id,omitempty"`
+
+	// Author is the identifier for the author of the VEX statement.
+	// Govulncheck will leave this field default (Unknown author) to be filled in by the user.
+	Author string `json:"author,omitempty"`
+
+	// Timestamp defines the time at which the document was issued.
+	Timestamp time.Time `json:"timestamp,omitempty"`
+
+	// Version is the document version. For govulncheck's output, this will always be 1.
+	Version int `json:"version,omitempty"`
+
+	// Tooling expresses how the VEX document and contained VEX statements were
+	// generated. In this case, it will always be:
+	// "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Tooling string `json:"tooling,omitempty"`
+
+	// Statements are all statements for a given govulncheck output.
+	// Each OSV emitted by govulncheck will have a corresponding statement.
+	Statements []Statement `json:"statements,omitempty"`
+}
+
+// Statement conveys a single status for a single vulnerability for one or more products.
+type Statement struct {
+	// Vulnerability is the vuln being referenced by the statement.
+	Vulnerability Vulnerability `json:"vulnerability,omitempty"`
+
+	// Products are the products associated with the given vulnerability in the statement.
+	Products []Product `json:"products,omitempty"`
+
+	// The status of the vulnerability. Will be either not_affected or affected for govulncheck.
+	Status string `json:"status,omitempty"`
+
+	// If the status is not_affected, this must be filled. The official VEX justification that
+	// best matches govulncheck's vuln filtering is "vulnerable_code_not_in_execute_path"
+	Justification string `json:"justification,omitempty"`
+
+	// If the status is not_affected, this must be filled. For govulncheck, this will always be:
+	// "Govulncheck determined that the vulnerable code isn't called"
+	ImpactStatement string `json:"impact_statement,omitempty"`
+}
+
+// Vulnerability captures a vulnerability and its identifiers/aliases.
+type Vulnerability struct {
+	// ID is a URI that in govulncheck's case points to the govulndb link for the vulnerability.
+	// I.E. https://pkg.go.dev/vuln/GO-2024-2497
+	ID string `json:"@id,omitempty"`
+
+	// Name is the main identifier for the vulnerability (GO-YYYY-XXXX)
+	Name string `json:"name,omitempty"`
+
+	// Description is a short text description of the vulnerability.
+	// It will be populated from the 'summary' field of the vuln's OSV if it exists,
+	// and the 'description' field of the osv if a summary isn't present.
+	Description string `json:"description,omitempty"`
+
+	// Aliases a list of identifiers that other systems are using to track the vulnerability.
+	// I.E. GHSA or CVE ids.
+	Aliases []string `json:"aliases,omitempty"`
+}
+
+// Product identifies the products associated with the given vuln.
+type Product struct {
+	// The main product ID will remian default for now.
+	Component
+	// The subcomponent ID will be a PURL to the vulnerable dependency.
+	Subcomponents []Component `json:"subcomponents,omitempty"`
+}
+
+type Component struct {
+	ID string `json:"@id,omitempty"`
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/osv/osv.go b/history-api/vendor/golang.org/x/vuln/internal/osv/osv.go
index 3fa3a086..0bb44b27 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/osv/osv.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/osv/osv.go
@@ -97,7 +97,7 @@ type Range struct {
 	Events []RangeEvent `json:"events"`
 }
 
-// Reference type is a reference (link) type.
+// ReferenceType is a reference (link) type.
 type ReferenceType string
 
 const (
@@ -235,4 +235,6 @@ type DatabaseSpecific struct {
 	// The URL of the Go advisory for this vulnerability, of the form
 	// "https://pkg.go.dev/GO-YYYY-XXXX".
 	URL string `json:"url,omitempty"`
+	// The review status of this report (UNREVIEWED or REVIEWED).
+	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/osv/review_status.go b/history-api/vendor/golang.org/x/vuln/internal/osv/review_status.go
new file mode 100644
index 00000000..7185e184
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/osv/review_status.go
@@ -0,0 +1,67 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package osv
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type ReviewStatus int
+
+const (
+	ReviewStatusUnknown ReviewStatus = iota
+	ReviewStatusUnreviewed
+	ReviewStatusReviewed
+)
+
+var statusStrs = []string{
+	ReviewStatusUnknown:    "",
+	ReviewStatusUnreviewed: "UNREVIEWED",
+	ReviewStatusReviewed:   "REVIEWED",
+}
+
+func (r ReviewStatus) String() string {
+	if !r.IsValid() {
+		return fmt.Sprintf("INVALID(%d)", r)
+	}
+	return statusStrs[r]
+}
+
+func ReviewStatusValues() []string {
+	return statusStrs[1:]
+}
+
+func (r ReviewStatus) IsValid() bool {
+	return int(r) >= 0 && int(r) < len(statusStrs)
+}
+
+func ToReviewStatus(s string) (ReviewStatus, bool) {
+	for stat, str := range statusStrs {
+		if s == str {
+			return ReviewStatus(stat), true
+		}
+	}
+	return 0, false
+}
+
+func (r ReviewStatus) MarshalJSON() ([]byte, error) {
+	if !r.IsValid() {
+		return nil, fmt.Errorf("MarshalJSON: unrecognized review status: %d", r)
+	}
+	return json.Marshal(r.String())
+}
+
+func (r *ReviewStatus) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if rs, ok := ToReviewStatus(s); ok {
+		*r = rs
+		return nil
+	}
+	return fmt.Errorf("UnmarshalJSON: unrecognized review status: %s", s)
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/sarif/handler.go b/history-api/vendor/golang.org/x/vuln/internal/sarif/handler.go
new file mode 100644
index 00000000..d9e585b7
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/sarif/handler.go
@@ -0,0 +1,409 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"path/filepath"
+	"sort"
+
+	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
+)
+
+// handler for sarif output.
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(c *govulncheck.Config) error {
+	h.cfg = c
+	return nil
+}
+
+func (h *handler) Progress(p *govulncheck.Progress) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is equal to an existing one and
+			// because of the invariant on h.findings, it is
+			// also equal to all existing ones.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print out to w the sarif json output.
+// This is needed as sarif is not streamed.
+func (h *handler) Flush() error {
+	sLog := toSarif(h)
+	s, err := json.MarshalIndent(sLog, "", "  ")
+	if err != nil {
+		return err
+	}
+	h.w.Write(s)
+	return nil
+}
+
+func toSarif(h *handler) Log {
+	cfg := h.cfg
+	r := Run{
+		Tool: Tool{
+			Driver: Driver{
+				Name:           cfg.ScannerName,
+				Version:        cfg.ScannerVersion,
+				InformationURI: "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
+				Properties:     *cfg,
+				Rules:          rules(h),
+			},
+		},
+		Results: results(h),
+	}
+
+	return Log{
+		Version: "2.1.0",
+		Schema:  "https://json.schemastore.org/sarif-2.1.0.json",
+		Runs:    []Run{r},
+	}
+}
+
+func rules(h *handler) []Rule {
+	rs := make([]Rule, 0, len(h.findings)) // must not be nil
+	for id := range h.findings {
+		osv := h.osvs[id]
+		// s is either summary if it exists, or details
+		// otherwise. Govulncheck text does the same.
+		s := osv.Summary
+		if s == "" {
+			s = osv.Details
+		}
+		rs = append(rs, Rule{
+			ID:               osv.ID,
+			ShortDescription: Description{Text: fmt.Sprintf("[%s] %s", osv.ID, s)},
+			FullDescription:  Description{Text: s},
+			HelpURI:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", osv.ID),
+			Help:             Description{Text: osv.Details},
+			Properties:       RuleTags{Tags: tags(osv)},
+		})
+	}
+	sort.SliceStable(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
+	return rs
+}
+
+// tags returns an slice of zero or
+// more aliases of o.
+func tags(o *osv.Entry) []string {
+	if len(o.Aliases) > 0 {
+		return o.Aliases
+	}
+	return []string{} // must not be nil
+}
+
+func results(h *handler) []Result {
+	results := make([]Result, 0, len(h.findings)) // must not be nil
+	for osv, fs := range h.findings {
+		var locs []Location
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			// Attach result to the go.mod file for source analysis.
+			// But there is no such place for binaries.
+			locs = []Location{{PhysicalLocation: PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       "go.mod",
+					URIBaseID: SrcRootID,
+				},
+				Region: Region{StartLine: 1}, // for now, point to the first line
+			},
+				Message: Description{Text: fmt.Sprintf("Findings for vulnerability %s", osv)}, // not having a message here results in an invalid sarif
+			}}
+		}
+
+		res := Result{
+			RuleID:    osv,
+			Level:     level(fs[0], h.cfg),
+			Message:   Description{Text: resultMessage(fs, h.cfg)},
+			Stacks:    stacks(h, fs),
+			CodeFlows: codeFlows(h, fs),
+			Locations: locs,
+		}
+		results = append(results, res)
+	}
+	sort.SliceStable(results, func(i, j int) bool { return results[i].RuleID < results[j].RuleID }) // for deterministic output
+	return results
+}
+
+func resultMessage(findings []*govulncheck.Finding, cfg *govulncheck.Config) string {
+	// We can infer the findings' level by just looking at the
+	// top trace frame of any finding.
+	frame := findings[0].Trace[0]
+	uniqueElems := make(map[string]bool)
+	if frame.Function == "" && frame.Package == "" { // module level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Module] = true
+		}
+	} else { // symbol and package level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Package] = true
+		}
+	}
+	var elems []string
+	for e := range uniqueElems {
+		elems = append(elems, e)
+	}
+	sort.Strings(elems)
+
+	l := len(elems)
+	elemList := list(elems)
+	main, addition := "", ""
+	const runCallAnalysis = "Run the call-level analysis to understand whether your code actually calls the vulnerabilities."
+	switch {
+	case frame.Function != "":
+		main = fmt.Sprintf("calls vulnerable functions in %d package%s (%s).", l, choose("", "s", l == 1), elemList)
+	case frame.Package != "":
+		main = fmt.Sprintf("imports %d vulnerable package%s (%s)", l, choose("", "s", l == 1), elemList)
+		addition = choose(", but doesn’t appear to call any of the vulnerable symbols.", ". "+runCallAnalysis, cfg.ScanLevel.WantSymbols())
+	default:
+		main = fmt.Sprintf("depends on %d vulnerable module%s (%s)", l, choose("", "s", l == 1), elemList)
+		informational := ", but doesn't appear to " + choose("call", "import", cfg.ScanLevel.WantSymbols()) + " any of the vulnerable symbols."
+		addition = choose(informational, ". "+runCallAnalysis, cfg.ScanLevel.WantPackages())
+	}
+
+	return fmt.Sprintf("Your code %s%s", main, addition)
+}
+
+const (
+	errorLevel         = "error"
+	warningLevel       = "warning"
+	informationalLevel = "note"
+)
+
+func level(f *govulncheck.Finding, cfg *govulncheck.Config) string {
+	fr := f.Trace[0]
+	switch {
+	case cfg.ScanLevel.WantSymbols():
+		if fr.Function != "" {
+			return errorLevel
+		}
+		if fr.Package != "" {
+			return warningLevel
+		}
+		return informationalLevel
+	case cfg.ScanLevel.WantPackages():
+		if fr.Package != "" {
+			return errorLevel
+		}
+		return warningLevel
+	default:
+		return errorLevel
+	}
+}
+
+func stacks(h *handler, fs []*govulncheck.Finding) []Stack {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	var stacks []Stack
+	for _, f := range fs {
+		stacks = append(stacks, stack(h, f))
+	}
+	// Sort stacks for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(stacks, func(i, j int) bool { return stacks[i].Message.Text < stacks[j].Message.Text })
+	return stacks
+}
+
+// stack transforms call stack in f to a sarif stack.
+func stack(h *handler, f *govulncheck.Finding) Stack {
+	trace := f.Trace
+	top := trace[len(trace)-1] // belongs to top level module
+
+	frames := make([]Frame, 0, len(trace)) // must not be nil
+	for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+		frame := trace[i]
+		pos := govulncheck.Position{Line: 1, Column: 1}
+		if frame.Position != nil {
+			pos = *frame.Position
+		}
+
+		sf := Frame{
+			Module:   frame.Module + "@" + frame.Version,
+			Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+		}
+		file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			sf.Location.PhysicalLocation = PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       file,
+					URIBaseID: base,
+				},
+				Region: Region{
+					StartLine:   pos.Line,
+					StartColumn: pos.Column,
+				},
+			}
+		}
+		frames = append(frames, sf)
+	}
+
+	return Stack{
+		Frames:  frames,
+		Message: Description{Text: fmt.Sprintf("A call stack for vulnerable function %s", symbol(trace[0]))},
+	}
+}
+
+func codeFlows(h *handler, fs []*govulncheck.Finding) []CodeFlow {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	// group call stacks per symbol. There should
+	// be one call stack currently per symbol, but
+	// this might change in the future.
+	m := make(map[govulncheck.Frame][]*govulncheck.Finding)
+	for _, f := range fs {
+		// fr.Position is currently the position
+		// of the definition of the vuln symbol
+		fr := *f.Trace[0]
+		m[fr] = append(m[fr], f)
+	}
+
+	var codeFlows []CodeFlow
+	for fr, fs := range m {
+		tfs := threadFlows(h, fs)
+		codeFlows = append(codeFlows, CodeFlow{
+			ThreadFlows: tfs,
+			// TODO: should we instead show the message from govulncheck text output?
+			Message: Description{Text: fmt.Sprintf("A summarized code flow for vulnerable function %s", symbol(&fr))},
+		})
+	}
+	// Sort flows for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(codeFlows, func(i, j int) bool { return codeFlows[i].Message.Text < codeFlows[j].Message.Text })
+	return codeFlows
+}
+
+func threadFlows(h *handler, fs []*govulncheck.Finding) []ThreadFlow {
+	tfs := make([]ThreadFlow, 0, len(fs)) // must not be nil
+	for _, f := range fs {
+		trace := traces.Compact(f)
+		top := trace[len(trace)-1] // belongs to top level module
+
+		var tf []ThreadFlowLocation
+		for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+			// TODO: should we, similar to govulncheck text output, only
+			// mention three elements of the compact trace?
+			frame := trace[i]
+			pos := govulncheck.Position{Line: 1, Column: 1}
+			if frame.Position != nil {
+				pos = *frame.Position
+			}
+
+			tfl := ThreadFlowLocation{
+				Module:   frame.Module + "@" + frame.Version,
+				Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+			}
+			file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+			if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+				tfl.Location.PhysicalLocation = PhysicalLocation{
+					ArtifactLocation: ArtifactLocation{
+						URI:       file,
+						URIBaseID: base,
+					},
+					Region: Region{
+						StartLine:   pos.Line,
+						StartColumn: pos.Column,
+					},
+				}
+			}
+			tf = append(tf, tfl)
+		}
+		tfs = append(tfs, ThreadFlow{Locations: tf})
+	}
+	return tfs
+}
+
+func fileURIInfo(filename, top, module, version string) (string, string) {
+	if top == module {
+		return filename, SrcRootID
+	}
+	if module == internal.GoStdModulePath {
+		return filename, GoRootID
+	}
+	return filepath.ToSlash(filepath.Join(module+"@"+version, filename)), GoModCacheID
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go b/history-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go
new file mode 100644
index 00000000..934ade8b
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go
@@ -0,0 +1,213 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sarif defines Static Analysis Results Interchange Format
+// (SARIF) types supported by govulncheck.
+//
+// The implementation covers the subset of the specification available
+// at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+//
+// The sarif encoding models govulncheck findings as Results. Each
+// Result encodes findings for a unique OSV entry at the most precise
+// detected level only. CodeFlows summarize call stacks, similar to govulncheck
+// textual output, while Stacks contain call stack information verbatim.
+//
+// The result Levels are defined by the govulncheck.ScanLevel and the most
+// precise level at which the finding was detected. Result error is produced
+// when the finding level matches the user desired level of scan precision;
+// all other finding levels are then classified as progressively weaker.
+// For instance, if the user specified symbol scan level and govulncheck
+// detected a use of a vulnerable symbol, then the Result will have error
+// Level. If the symbol was not used but its package was imported, then the
+// Result Level is warning, and so on.
+//
+// Each Result is attached to the first line of the go.mod file. Other
+// ArtifactLocations are paths relative to their enclosing modules.
+// Similar to JSON output format, this makes govulncheck sarif locations
+// portable.
+//
+// The relative paths in PhysicalLocations also come with a URIBaseID offset.
+// Paths for the source module analyzed, the Go standard library, and third-party
+// dependencies are relative to %SRCROOT%, %GOROOT%, and %GOMODCACHE% offsets,
+// resp. We note that the URIBaseID offsets are not explicitly defined in
+// the sarif output. It is the clients responsibility to set them to resolve
+// paths at their local machines.
+//
+// All paths use "/" delimiter for portability.
+//
+// Properties field of a Tool.Driver is a govulncheck.Config used for the
+// invocation of govulncheck producing the Results. Properties field of
+// a Rule contains information on CVE and GHSA aliases for the corresponding
+// rule OSV. Clients can use this information to, say, suppress and filter
+// vulnerabilities.
+//
+// Please see the definition of types below for more information.
+package sarif
+
+import "golang.org/x/vuln/internal/govulncheck"
+
+// Log is the top-level SARIF object encoded in UTF-8.
+type Log struct {
+	// Version should always be "2.1.0"
+	Version string `json:"version,omitempty"`
+
+	// Schema should always be "https://json.schemastore.org/sarif-2.1.0.json"
+	Schema string `json:"$schema,omitempty"`
+
+	// Runs describes executions of static analysis tools. For govulncheck,
+	// there will be only one run object.
+	Runs []Run `json:"runs,omitempty"`
+}
+
+// Run summarizes results of a single invocation of a static analysis tool,
+// in this case govulncheck.
+type Run struct {
+	Tool Tool `json:"tool,omitempty"`
+	// Results contain govulncheck findings. There should be exactly one
+	// Result per a detected use of an OSV.
+	Results []Result `json:"results"`
+}
+
+// Tool captures information about govulncheck analysis that was run.
+type Tool struct {
+	Driver Driver `json:"driver,omitempty"`
+}
+
+// Driver provides details about the govulncheck binary being executed.
+type Driver struct {
+	// Name is "govulncheck"
+	Name string `json:"name,omitempty"`
+	// Version is the govulncheck version
+	Version string `json:"semanticVersion,omitempty"`
+	// InformationURI points to the description of govulncheck tool
+	InformationURI string `json:"informationUri,omitempty"`
+	// Properties are govulncheck run metadata, such as vuln db, Go version, etc.
+	Properties govulncheck.Config `json:"properties,omitempty"`
+
+	Rules []Rule `json:"rules"`
+}
+
+// Rule corresponds to the static analysis rule/analyzer that
+// produces findings. For govulncheck, rules are OSVs.
+type Rule struct {
+	// ID is OSV.ID
+	ID               string      `json:"id,omitempty"`
+	ShortDescription Description `json:"shortDescription,omitempty"`
+	FullDescription  Description `json:"fullDescription,omitempty"`
+	Help             Description `json:"help,omitempty"`
+	HelpURI          string      `json:"helpUri,omitempty"`
+	// Properties contain OSV.Aliases (CVEs and GHSAs) as tags.
+	// Consumers of govulncheck SARIF can use these tags to filter
+	// results.
+	Properties RuleTags `json:"properties,omitempty"`
+}
+
+// RuleTags defines properties.tags.
+type RuleTags struct {
+	Tags []string `json:"tags"`
+}
+
+// Description is a text in its raw or markdown form.
+type Description struct {
+	Text     string `json:"text,omitempty"`
+	Markdown string `json:"markdown,omitempty"`
+}
+
+// Result is a set of govulncheck findings for an OSV. For call stack
+// mode, it will contain call stacks for the OSV. There is exactly
+// one Result per detected OSV. Only findings at the most precise
+// detected level appear in the Result. For instance, if there are
+// symbol findings for an OSV, those findings will be in the Result,
+// but not the package and module level findings for the same OSV.
+type Result struct {
+	// RuleID is the Rule.ID/OSV producing the finding.
+	RuleID string `json:"ruleId,omitempty"`
+	// Level is one of "error", "warning", and "note".
+	Level string `json:"level,omitempty"`
+	// Message explains the overall findings.
+	Message Description `json:"message,omitempty"`
+	// Locations to which the findings are associated. Always
+	// a single location pointing to the first line of the go.mod
+	// file. The path to the file is "go.mod".
+	Locations []Location `json:"locations,omitempty"`
+	// CodeFlows summarize call stacks produced by govulncheck.
+	CodeFlows []CodeFlow `json:"codeFlows,omitempty"`
+	// Stacks encode call stacks produced by govulncheck.
+	Stacks []Stack `json:"stacks,omitempty"`
+}
+
+// CodeFlow summarizes a detected offending flow of information in terms of
+// code locations. More precisely, it can contain several related information
+// flows, keeping them together. In govulncheck, those can be all call stacks
+// for, say, a particular symbol or package.
+type CodeFlow struct {
+	// ThreadFlows is effectively a set of related information flows.
+	ThreadFlows []ThreadFlow `json:"threadFlows"`
+	Message     Description  `json:"message,omitempty"`
+}
+
+// ThreadFlow encodes an information flow as a sequence of locations.
+// For govulncheck, it can encode a call stack.
+type ThreadFlow struct {
+	Locations []ThreadFlowLocation `json:"locations,omitempty"`
+}
+
+type ThreadFlowLocation struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module string `json:"module,omitempty"`
+	// Location also contains a Message field.
+	Location Location `json:"location,omitempty"`
+}
+
+// Stack is a sequence of frames and can encode a govulncheck call stack.
+type Stack struct {
+	Message Description `json:"message,omitempty"`
+	Frames  []Frame     `json:"frames"`
+}
+
+// Frame is effectively a module location. It can also contain thread and
+// parameter info, but those are not needed for govulncheck.
+type Frame struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module   string   `json:"module,omitempty"`
+	Location Location `json:"location,omitempty"`
+}
+
+// Location is currently a physical location annotated with a message.
+type Location struct {
+	PhysicalLocation PhysicalLocation `json:"physicalLocation,omitempty"`
+	Message          Description      `json:"message,omitempty"`
+}
+
+type PhysicalLocation struct {
+	ArtifactLocation ArtifactLocation `json:"artifactLocation,omitempty"`
+	Region           Region           `json:"region,omitempty"`
+}
+
+const (
+	SrcRootID    = "%SRCROOT%"
+	GoRootID     = "%GOROOT%"
+	GoModCacheID = "%GOMODCACHE%"
+)
+
+// ArtifactLocation is a path to an offending file.
+type ArtifactLocation struct {
+	// URI is a path relative to URIBaseID.
+	URI string `json:"uri,omitempty"`
+	// URIBaseID is offset for URI, one of %SRCROOT%, %GOROOT%,
+	// and %GOMODCACHE%.
+	URIBaseID string `json:"uriBaseId,omitempty"`
+}
+
+// Region is a target region within a file.
+type Region struct {
+	StartLine   int `json:"startLine,omitempty"`
+	StartColumn int `json:"startColumn,omitempty"`
+	EndLine     int `json:"endLine,omitempty"`
+	EndColumn   int `json:"endColumn,omitempty"`
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/sarif/utils.go b/history-api/vendor/golang.org/x/vuln/internal/sarif/utils.go
new file mode 100644
index 00000000..045cac76
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/sarif/utils.go
@@ -0,0 +1,46 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+func choose(s1, s2 string, cond bool) string {
+	if cond {
+		return s1
+	}
+	return s2
+}
+
+func list(elems []string) string {
+	l := len(elems)
+	if l == 0 {
+		return ""
+	}
+	if l == 1 {
+		return elems[0]
+	}
+
+	cList := strings.Join(elems[:l-1], ", ")
+	return cList + choose("", ",", l == 2) + " and " + elems[l-1]
+}
+
+// symbol is simplified adaptation of internal/scan/symbol.
+func symbol(fr *govulncheck.Frame) string {
+	if fr.Function == "" {
+		return ""
+	}
+	sym := strings.Split(fr.Function, "$")[0]
+	if fr.Receiver != "" {
+		sym = fr.Receiver + "." + sym
+	}
+	if fr.Package != "" {
+		sym = fr.Package + "." + sym
+	}
+	return sym
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/binary.go b/history-api/vendor/golang.org/x/vuln/internal/scan/binary.go
index 76b17f75..5cc8f6ba 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/binary.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/binary.go
@@ -2,93 +2,109 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package scan
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
+	"errors"
 	"os"
-	"strings"
-	"unicode"
+	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
-// runBinary detects presence of vulnerable symbols in an executable.
-func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) error {
-	var exe *os.File
-	exe, err := os.Open(cfg.patterns[0])
+// runBinary detects presence of vulnerable symbols in an executable or its minimal blob representation.
+func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
 	if err != nil {
 		return err
 	}
-	defer exe.Close()
 
 	p := &govulncheck.Progress{Message: binaryProgressMessage}
 	if err := handler.Progress(p); err != nil {
 		return err
 	}
-	vr, err := binary(ctx, exe, &cfg.Config, client)
-	if err != nil {
-		return fmt.Errorf("govulncheck: %v", err)
-	}
-	callstacks := binaryCallstacks(vr)
-	return emitResult(handler, vr, callstacks)
+	return vulncheck.Binary(ctx, handler, bin, &cfg.Config, client)
 }
 
-func binaryCallstacks(vr *vulncheck.Result) map[*vulncheck.Vuln]vulncheck.CallStack {
-	callstacks := map[*vulncheck.Vuln]vulncheck.CallStack{}
-	for _, vv := range uniqueVulns(vr.Vulns) {
-		f := &vulncheck.FuncNode{Package: vv.ImportSink, Name: vv.Symbol}
-		parts := strings.Split(vv.Symbol, ".")
-		if len(parts) != 1 {
-			f.RecvType = parts[0]
-			f.Name = parts[1]
+func createBin(path string) (*vulncheck.Bin, error) {
+	// First check if the path points to a Go binary. Otherwise, blob
+	// parsing might json decode a Go binary which takes time.
+	//
+	// TODO(#64716): use fingerprinting to make this precise, clean, and fast.
+	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(path)
+	if err == nil {
+		var main *packages.Module
+		if bi.Main.Path != "" {
+			main = &packages.Module{
+				Path:    bi.Main.Path,
+				Version: bi.Main.Version,
+			}
 		}
-		callstacks[vv] = vulncheck.CallStack{vulncheck.StackEntry{Function: f}}
+
+		return &vulncheck.Bin{
+			Path:       bi.Path,
+			Main:       main,
+			Modules:    mods,
+			PkgSymbols: packageSymbols,
+			GoVersion:  bi.GoVersion,
+			GOOS:       findSetting("GOOS", bi),
+			GOARCH:     findSetting("GOARCH", bi),
+		}, nil
+	}
+
+	// Otherwise, see if the path points to a valid blob.
+	bin := parseBlob(path)
+	if bin != nil {
+		return bin, nil
 	}
-	return callstacks
+
+	return nil, errors.New("unrecognized binary format")
 }
 
-// uniqueVulns does for binary mode what uniqueCallStack does for source mode.
-// It tries not to report redundant symbols. Since there are no call stacks in
-// binary mode, the following approximate approach is used. Do not report unexported
-// symbols for a  triple if there are some exported symbols.
-// Otherwise, report all unexported symbols to avoid not reporting anything.
-func uniqueVulns(vulns []*vulncheck.Vuln) []*vulncheck.Vuln {
-	type key struct {
-		id  string
-		pkg string
-		mod string
+// parseBlob extracts vulncheck.Bin from a valid blob at path.
+// If it cannot recognize a valid blob, returns nil.
+func parseBlob(path string) *vulncheck.Bin {
+	from, err := os.Open(path)
+	if err != nil {
+		return nil
 	}
-	hasExported := make(map[key]bool)
-	for _, v := range vulns {
-		if isExported(v.Symbol) {
-			k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-			hasExported[k] = true
-		}
+	defer from.Close()
+
+	dec := json.NewDecoder(from)
+
+	var h header
+	if err := dec.Decode(&h); err != nil {
+		return nil // no header
+	} else if h.Name != extractModeID || h.Version != extractModeVersion {
+		return nil // invalid header
 	}
 
-	var uniques []*vulncheck.Vuln
-	for _, v := range vulns {
-		k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-		if isExported(v.Symbol) || !hasExported[k] {
-			uniques = append(uniques, v)
-		}
+	var b vulncheck.Bin
+	if err := dec.Decode(&b); err != nil {
+		return nil // no body
+	}
+	if dec.More() {
+		return nil // we want just header and body, nothing else
 	}
-	return uniques
+	return &b
 }
 
-// isExported checks if the symbol is exported. Assumes that the
-// symbol is of the form "identifier" or "identifier1.identifier2".
-func isExported(symbol string) bool {
-	parts := strings.Split(symbol, ".")
-	if len(parts) == 1 {
-		return unicode.IsUpper(rune(symbol[0]))
+// findSetting returns value of setting from bi if present.
+// Otherwise, returns "".
+func findSetting(setting string, bi *debug.BuildInfo) string {
+	for _, s := range bi.Settings {
+		if s.Key == setting {
+			return s.Value
+		}
 	}
-	return unicode.IsUpper(rune(parts[1][0]))
+	return ""
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go b/history-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go
deleted file mode 100644
index d4345f3b..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package scan
-
-import (
-	"context"
-	"io"
-
-	"golang.org/x/vuln/internal/client"
-	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *vulncheck.Result, err error) {
-	return vulncheck.Binary(ctx, exe, cfg, client)
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go b/history-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
deleted file mode 100644
index 0f66a02c..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package scan
-
-import (
-	"context"
-	"errors"
-	"io"
-
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *vulncheck.Config) (_ *vulncheck.Result, err error) {
-	return nil, errors.New("compile with Go 1.18 or higher to analyze binary files")
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/errors.go b/history-api/vendor/golang.org/x/vuln/internal/scan/errors.go
index 920edd4c..c28e3c5a 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/errors.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/errors.go
@@ -22,7 +22,7 @@ var (
 	// errUsage indicates that there was a usage error on the command line.
 	//
 	// In this case, we assume that the user does not know how to run
-	// govulncheck, and print the usage message with exit status 2.
+	// govulncheck and exit with status 2.
 	errUsage = &exitCodeError{message: "invalid usage", code: 2}
 
 	// errGoVersionMismatch is used to indicate that there is a mismatch between
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/extract.go b/history-api/vendor/golang.org/x/vuln/internal/scan/extract.go
new file mode 100644
index 00000000..58a3f673
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/extract.go
@@ -0,0 +1,60 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scan
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"sort"
+
+	"golang.org/x/vuln/internal/derrors"
+	"golang.org/x/vuln/internal/vulncheck"
+)
+
+const (
+	// extractModeID is the unique name of the extract mode protocol
+	extractModeID      = "govulncheck-extract"
+	extractModeVersion = "0.1.0"
+)
+
+// header information for the blob output.
+type header struct {
+	Name    string `json:"name"`
+	Version string `json:"version"`
+}
+
+// runExtract dumps the extracted abstraction of binary at cfg.patterns to out.
+// It prints out exactly two blob messages, one with the header and one with
+// the vulncheck.Bin as the body.
+func runExtract(cfg *config, out io.Writer) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
+	if err != nil {
+		return err
+	}
+	sortBin(bin) // sort for easier testing and validation
+	header := header{
+		Name:    extractModeID,
+		Version: extractModeVersion,
+	}
+
+	enc := json.NewEncoder(out)
+
+	if err := enc.Encode(header); err != nil {
+		return fmt.Errorf("marshaling blob header: %v", err)
+	}
+	if err := enc.Encode(bin); err != nil {
+		return fmt.Errorf("marshaling blob body: %v", err)
+	}
+	return nil
+}
+
+func sortBin(bin *vulncheck.Bin) {
+	sort.SliceStable(bin.PkgSymbols, func(i, j int) bool {
+		return bin.PkgSymbols[i].Pkg+"."+bin.PkgSymbols[i].Name < bin.PkgSymbols[j].Pkg+"."+bin.PkgSymbols[j].Name
+	})
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/flags.go b/history-api/vendor/golang.org/x/vuln/internal/scan/flags.go
index 1e581102..5512540f 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/flags.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/flags.go
@@ -19,37 +19,37 @@ import (
 type config struct {
 	govulncheck.Config
 	patterns []string
-	mode     string
 	db       string
-	json     bool
 	dir      string
-	tags     []string
+	tags     buildutil.TagsFlag
 	test     bool
-	show     []string
+	show     ShowFlag
+	format   FormatFlag
 	env      []string
 }
 
-const (
-	modeBinary  = "binary"
-	modeSource  = "source"
-	modeConvert = "convert" // only intended for use by gopls
-	modeQuery   = "query"   // only intended for use by gopls
-)
-
 func parseFlags(cfg *config, stderr io.Writer, args []string) error {
-	var tagsFlag buildutil.TagsFlag
-	var showFlag showFlag
+	var version bool
+	var json bool
+	var scanFlag ScanFlag
+	var modeFlag ModeFlag
 	flags := flag.NewFlagSet("", flag.ContinueOnError)
 	flags.SetOutput(stderr)
-	flags.BoolVar(&cfg.json, "json", false, "output JSON")
-	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode)")
+	flags.BoolVar(&json, "json", false, "output JSON (Go compatible legacy flag, see format flag)")
+	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode, default false)")
 	flags.StringVar(&cfg.dir, "C", "", "change to `dir` before running govulncheck")
 	flags.StringVar(&cfg.db, "db", "https://vuln.go.dev", "vulnerability database `url`")
-	flags.StringVar(&cfg.mode, "mode", modeSource, "supports source or binary")
-	flags.Var(&tagsFlag, "tags", "comma-separated `list` of build tags")
-	flags.Var(&showFlag, "show", "enable display of additional information specified by `list`")
-	scanLevel := flags.String("scan-level", "symbol", "set the scanning level desired, one of module, package or symbol")
-	flags.Usage = func() {
+	flags.Var(&modeFlag, "mode", "supports 'source', 'binary', and 'extract' (default 'source')")
+	flags.Var(&cfg.tags, "tags", "comma-separated `list` of build tags")
+	flags.Var(&cfg.show, "show", "enable display of additional information specified by the comma separated `list`\nThe supported values are 'traces','color', 'version', and 'verbose'")
+	flags.Var(&cfg.format, "format", "specify format output\nThe supported values are 'text', 'json', 'sarif', and 'openvex' (default 'text')")
+	flags.BoolVar(&version, "version", false, "print the version information")
+	flags.Var(&scanFlag, "scan", "set the scanning level desired, one of 'module', 'package', or 'symbol' (default 'symbol')")
+
+	// We don't want to print the whole usage message on each flags
+	// error, so we set to a no-op and do the printing ourselves.
+	flags.Usage = func() {}
+	usage := func() {
 		fmt.Fprint(flags.Output(), `Govulncheck reports known vulnerabilities in dependencies.
 
 Usage:
@@ -61,44 +61,60 @@ Usage:
 		flags.PrintDefaults()
 		fmt.Fprintf(flags.Output(), "\n%s\n", detailsMessage)
 	}
+
 	if err := flags.Parse(args); err != nil {
 		if err == flag.ErrHelp {
+			usage() // print usage only on help
 			return errHelp
 		}
-		return err
+		return errUsage
 	}
 	cfg.patterns = flags.Args()
-	if cfg.mode != modeConvert && len(cfg.patterns) == 0 {
-		flags.Usage()
-		return errUsage
+	if version {
+		cfg.show = append(cfg.show, "version")
 	}
-	cfg.tags = tagsFlag
-	cfg.show = showFlag
-	cfg.ScanLevel = govulncheck.ScanLevel(*scanLevel)
-	if err := validateConfig(cfg); err != nil {
+	cfg.ScanLevel = govulncheck.ScanLevel(scanFlag)
+	cfg.ScanMode = govulncheck.ScanMode(modeFlag)
+	if err := validateConfig(cfg, json); err != nil {
 		fmt.Fprintln(flags.Output(), err)
 		return errUsage
 	}
 	return nil
 }
 
-var supportedModes = map[string]bool{
-	modeSource:  true,
-	modeBinary:  true,
-	modeConvert: true,
-	modeQuery:   true,
-}
+func validateConfig(cfg *config, json bool) error {
+	// take care of default values
+	if cfg.ScanMode == "" {
+		cfg.ScanMode = govulncheck.ScanModeSource
+	}
+	if cfg.ScanLevel == "" {
+		cfg.ScanLevel = govulncheck.ScanLevelSymbol
+	}
+	if json {
+		if cfg.format != formatUnset {
+			return fmt.Errorf("the -json flag cannot be used with -format flag")
+		}
+		cfg.format = formatJSON
+	} else {
+		if cfg.format == formatUnset {
+			cfg.format = formatText
+		}
+	}
 
-func validateConfig(cfg *config) error {
-	if _, ok := supportedModes[cfg.mode]; !ok {
-		return fmt.Errorf("%q is not a valid mode", cfg.mode)
+	// show flag is only supported with text output
+	if cfg.format != formatText && len(cfg.show) > 0 {
+		return fmt.Errorf("the -show flag is not supported for %s output", cfg.format)
 	}
-	switch cfg.mode {
-	case modeSource:
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		if len(cfg.patterns) == 1 && isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is a file.\n\n%v", cfg.patterns[0], errNoBinaryFlag)
 		}
-	case modeBinary:
+		if cfg.ScanLevel == govulncheck.ScanLevelModule && len(cfg.patterns) != 0 {
+			return fmt.Errorf("patterns are not accepted for module only scanning")
+		}
+	case govulncheck.ScanModeBinary:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in binary mode")
 		}
@@ -111,7 +127,23 @@ func validateConfig(cfg *config) error {
 		if !isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is not a file", cfg.patterns[0])
 		}
-	case modeConvert:
+	case govulncheck.ScanModeExtract:
+		if cfg.test {
+			return fmt.Errorf("the -test flag is not supported in extract mode")
+		}
+		if len(cfg.tags) > 0 {
+			return fmt.Errorf("the -tags flag is not supported in extract mode")
+		}
+		if len(cfg.patterns) != 1 {
+			return fmt.Errorf("only 1 binary can be extracted at a time")
+		}
+		if cfg.format == formatJSON {
+			return fmt.Errorf("the json format must be off in extract mode")
+		}
+		if !isFile(cfg.patterns[0]) {
+			return fmt.Errorf("%q is not a file (source extraction is not supported)", cfg.patterns[0])
+		}
+	case govulncheck.ScanModeConvert:
 		if len(cfg.patterns) != 0 {
 			return fmt.Errorf("patterns are not accepted in convert mode")
 		}
@@ -124,15 +156,15 @@ func validateConfig(cfg *config) error {
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in convert mode")
 		}
-	case modeQuery:
+	case govulncheck.ScanModeQuery:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in query mode")
 		}
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in query mode")
 		}
-		if !cfg.json {
-			return fmt.Errorf("the -json flag must be set in query mode")
+		if cfg.format != formatJSON {
+			return fmt.Errorf("the json format must be set in query mode")
 		}
 		for _, pattern := range cfg.patterns {
 			// Parse the input here so that we can catch errors before
@@ -142,9 +174,6 @@ func validateConfig(cfg *config) error {
 			}
 		}
 	}
-	if cfg.json && len(cfg.show) > 0 {
-		return fmt.Errorf("the -show flag is not supported for JSON output")
-	}
 	return nil
 }
 
@@ -156,26 +185,119 @@ func isFile(path string) bool {
 	return !s.IsDir()
 }
 
-// fileExists checks if file path exists. Returns true
-// if the file exists or it cannot prove that it does
-// not exist. Otherwise, returns false.
-func fileExists(path string) bool {
-	if _, err := os.Stat(path); err == nil {
-		return true
-	} else if errors.Is(err, os.ErrNotExist) {
-		return false
+var errFlagParse = errors.New("see -help for details")
+
+// ShowFlag is used for parsing and validation of
+// govulncheck -show flag.
+type ShowFlag []string
+
+var supportedShows = map[string]bool{
+	"traces":  true,
+	"color":   true,
+	"verbose": true,
+	"version": true,
+}
+
+func (v *ShowFlag) Set(s string) error {
+	if s == "" {
+		return nil
+	}
+	for _, show := range strings.Split(s, ",") {
+		sh := strings.TrimSpace(show)
+		if _, ok := supportedShows[sh]; !ok {
+			return errFlagParse
+		}
+		*v = append(*v, sh)
 	}
-	// Conservatively return true if os.Stat fails
-	// for some other reason.
-	return true
+	return nil
 }
 
-type showFlag []string
+func (v *ShowFlag) Get() interface{} { return *v }
+func (v *ShowFlag) String() string   { return "" }
+
+// Update the text handler h with values of the flag.
+func (v ShowFlag) Update(h *TextHandler) {
+	for _, show := range v {
+		switch show {
+		case "traces":
+			h.showTraces = true
+		case "color":
+			h.showColor = true
+		case "version":
+			h.showVersion = true
+		case "verbose":
+			h.showVerbose = true
+		}
+	}
+}
 
-func (v *showFlag) Set(s string) error {
-	*v = append(*v, strings.Split(s, ",")...)
+// FormatFlag is used for parsing and validation of
+// govulncheck -format flag.
+type FormatFlag string
+
+const (
+	formatUnset   = ""
+	formatJSON    = "json"
+	formatText    = "text"
+	formatSarif   = "sarif"
+	formatOpenVEX = "openvex"
+)
+
+var supportedFormats = map[string]bool{
+	formatJSON:    true,
+	formatText:    true,
+	formatSarif:   true,
+	formatOpenVEX: true,
+}
+
+func (f *FormatFlag) Get() interface{} { return *f }
+func (f *FormatFlag) Set(s string) error {
+	if _, ok := supportedFormats[s]; !ok {
+		return errFlagParse
+	}
+	*f = FormatFlag(s)
 	return nil
 }
+func (f *FormatFlag) String() string { return "" }
 
-func (f *showFlag) Get() interface{} { return *f }
-func (f *showFlag) String() string   { return "" }
+// ModeFlag is used for parsing and validation of
+// govulncheck -mode flag.
+type ModeFlag string
+
+var supportedModes = map[string]bool{
+	govulncheck.ScanModeSource:  true,
+	govulncheck.ScanModeBinary:  true,
+	govulncheck.ScanModeConvert: true,
+	govulncheck.ScanModeQuery:   true,
+	govulncheck.ScanModeExtract: true,
+}
+
+func (f *ModeFlag) Get() interface{} { return *f }
+func (f *ModeFlag) Set(s string) error {
+	if _, ok := supportedModes[s]; !ok {
+		return errFlagParse
+	}
+	*f = ModeFlag(s)
+	return nil
+}
+func (f *ModeFlag) String() string { return "" }
+
+// ScanFlag is used for parsing and validation of
+// govulncheck -scan flag.
+type ScanFlag string
+
+var supportedLevels = map[string]bool{
+	govulncheck.ScanLevelModule:  true,
+	govulncheck.ScanLevelPackage: true,
+	govulncheck.ScanLevelSymbol:  true,
+}
+
+func (f *ScanFlag) Get() interface{} { return *f }
+func (f *ScanFlag) Set(s string) error {
+	if _, ok := supportedLevels[s]; !ok {
+		return errFlagParse
+	}
+	*f = ScanFlag(s)
+	return nil
+}
+func (f *ScanFlag) String() string { return "" }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/run.go b/history-api/vendor/golang.org/x/vuln/internal/scan/run.go
index fe452cfa..f29b9d31 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/run.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/run.go
@@ -15,8 +15,11 @@ import (
 	"strings"
 	"time"
 
+	"golang.org/x/telemetry/counter"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/openvex"
+	"golang.org/x/vuln/internal/sarif"
 )
 
 // RunGovulncheck performs main govulncheck functionality and exits the
@@ -27,9 +30,6 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 	if err := parseFlags(cfg, stderr, args); err != nil {
 		return err
 	}
-	if cfg.mode == modeConvert {
-		return convertJSONToText(r, stdout)
-	}
 
 	client, err := client.NewClient(cfg.db, nil)
 	if err != nil {
@@ -38,42 +38,48 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 
 	prepareConfig(ctx, cfg, client)
 	var handler govulncheck.Handler
-	switch {
-	case cfg.json:
+	switch cfg.format {
+	case formatJSON:
 		handler = govulncheck.NewJSONHandler(stdout)
+	case formatSarif:
+		handler = sarif.NewHandler(stdout)
+	case formatOpenVEX:
+		handler = openvex.NewHandler(stdout)
 	default:
 		th := NewTextHandler(stdout)
-		th.Show(cfg.show)
+		cfg.show.Update(th)
 		handler = th
 	}
 
-	// Write the introductory message to the user.
 	if err := handler.Config(&cfg.Config); err != nil {
 		return err
 	}
 
-	switch cfg.mode {
-	case modeSource:
+	incTelemetryFlagCounters(cfg)
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		dir := filepath.FromSlash(cfg.dir)
 		err = runSource(ctx, handler, cfg, client, dir)
-	case modeBinary:
+	case govulncheck.ScanModeBinary:
 		err = runBinary(ctx, handler, cfg, client)
-	case modeQuery:
+	case govulncheck.ScanModeExtract:
+		return runExtract(cfg, stdout)
+	case govulncheck.ScanModeQuery:
 		err = runQuery(ctx, handler, cfg, client)
+	case govulncheck.ScanModeConvert:
+		err = govulncheck.HandleJSON(r, handler)
 	}
 	if err != nil {
 		return err
 	}
-	if err := Flush(handler); err != nil {
-		return err
-	}
-	return nil
+	return Flush(handler)
 }
 
 func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 	cfg.ProtocolVersion = govulncheck.ProtocolVersion
 	cfg.DB = cfg.db
-	if cfg.mode == modeSource && cfg.GoVersion == "" {
+	if cfg.ScanMode == govulncheck.ScanModeSource && cfg.GoVersion == "" {
 		const goverPrefix = "GOVERSION="
 		for _, env := range cfg.env {
 			if val := strings.TrimPrefix(env, goverPrefix); val != env {
@@ -82,7 +88,7 @@ func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 		}
 		if cfg.GoVersion == "" {
 			if out, err := exec.Command("go", "env", "GOVERSION").Output(); err == nil {
-				cfg.GoVersion = string(out)
+				cfg.GoVersion = strings.TrimSpace(string(out))
 			}
 		}
 	}
@@ -133,13 +139,22 @@ func scannerVersion(cfg *config, bi *debug.BuildInfo) {
 	cfg.ScannerVersion = buf.String()
 }
 
-// convertJSONToText converts r, which is expected to be the JSON output of govulncheck,
-// into the text output, and writes the output to w.
-func convertJSONToText(r io.Reader, w io.Writer) error {
-	h := NewTextHandler(w)
-	if err := govulncheck.HandleJSON(r, h); err != nil {
-		return err
+func incTelemetryFlagCounters(cfg *config) {
+	counter.Inc(fmt.Sprintf("govulncheck/mode:%s", cfg.ScanMode))
+	counter.Inc(fmt.Sprintf("govulncheck/scan:%s", cfg.ScanLevel))
+	counter.Inc(fmt.Sprintf("govulncheck/format:%s", cfg.format))
+
+	if len(cfg.show) == 0 {
+		counter.Inc("govulncheck/show:none")
+	}
+	for _, s := range cfg.show {
+		counter.Inc(fmt.Sprintf("govulncheck/show:%s", s))
+	}
+}
+
+func Flush(h govulncheck.Handler) error {
+	if th, ok := h.(interface{ Flush() error }); ok {
+		return th.Flush()
 	}
-	Flush(h)
 	return nil
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/source.go b/history-api/vendor/golang.org/x/vuln/internal/scan/source.go
index cfdc1227..e9232112 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/source.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/source.go
@@ -7,13 +7,11 @@ package scan
 import (
 	"context"
 	"fmt"
-	"path/filepath"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
@@ -22,189 +20,30 @@ import (
 // Vulnerabilities can be called (affecting the package, because a vulnerable
 // symbol is actually exercised) or just imported by the package
 // (likely having a non-affecting outcome).
-func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) error {
-	var pkgs []*packages.Package
+func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	if cfg.ScanLevel.WantPackages() && len(cfg.patterns) == 0 {
+		return nil // don't throw an error here
+	}
+	if !gomodExists(dir) {
+		return errNoGoMod
+	}
 	graph := vulncheck.NewPackageGraph(cfg.GoVersion)
 	pkgConfig := &packages.Config{
 		Dir:   dir,
 		Tests: cfg.test,
 		Env:   cfg.env,
 	}
-	pkgs, err := graph.LoadPackages(pkgConfig, cfg.tags, cfg.patterns)
-	if err != nil {
-		// Try to provide a meaningful and actionable error message.
-		if !fileExists(filepath.Join(dir, "go.mod")) {
-			return fmt.Errorf("govulncheck: %v", errNoGoMod)
-		}
+	if err := graph.LoadPackagesAndMods(pkgConfig, cfg.tags, cfg.patterns, cfg.ScanLevel == govulncheck.ScanLevelSymbol); err != nil {
 		if isGoVersionMismatchError(err) {
-			return fmt.Errorf("govulncheck: %v\n\n%v", errGoVersionMismatch, err)
-		}
-		return fmt.Errorf("govulncheck: loading packages: %w", err)
-	}
-	if err := handler.Progress(sourceProgressMessage(pkgs)); err != nil {
-		return err
-	}
-	vr, err := vulncheck.Source(ctx, pkgs, &cfg.Config, client, graph)
-	if err != nil {
-		return err
-	}
-	callStacks := vulncheck.CallStacks(vr)
-	return emitResult(handler, vr, callStacks)
-}
-
-func emitResult(handler govulncheck.Handler, vr *vulncheck.Result, callstacks map[*vulncheck.Vuln]vulncheck.CallStack) error {
-	osvs := map[string]*osv.Entry{}
-	// first deal with all the affected vulnerabilities
-	emitted := map[string]bool{}
-	seen := map[string]bool{}
-	for _, vv := range vr.Vulns {
-		osvs[vv.OSV.ID] = vv.OSV
-		fixed := fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected)
-		stack := callstacks[vv]
-		if stack == nil {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixed,
-			Trace:        tracefromEntries(stack),
-		})
-	}
-	for _, vv := range vr.Vulns {
-		if emitted[vv.OSV.ID] {
-			continue
+			return fmt.Errorf("%v\n\n%v", errGoVersionMismatch, err)
 		}
-		stacks := callstacks[vv]
-		if len(stacks) != 0 {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected),
-			Trace:        []*govulncheck.Frame{frameFromPackage(vv.ImportSink)},
-		})
-	}
-	return nil
-}
-
-func emitFinding(handler govulncheck.Handler, osvs map[string]*osv.Entry, seen map[string]bool, finding *govulncheck.Finding) error {
-	if !seen[finding.OSV] {
-		seen[finding.OSV] = true
-		if err := handler.OSV(osvs[finding.OSV]); err != nil {
-			return err
-		}
-	}
-	return handler.Finding(finding)
-}
-
-// tracefromEntries creates a sequence of
-// frames from vcs. Position of a Frame is the
-// call position of the corresponding stack entry.
-func tracefromEntries(vcs vulncheck.CallStack) []*govulncheck.Frame {
-	var frames []*govulncheck.Frame
-	for i := len(vcs) - 1; i >= 0; i-- {
-		e := vcs[i]
-		fr := frameFromPackage(e.Function.Package)
-		fr.Function = e.Function.Name
-		fr.Receiver = e.Function.Receiver()
-		if e.Call == nil || e.Call.Pos == nil {
-			fr.Position = nil
-		} else {
-			fr.Position = &govulncheck.Position{
-				Filename: e.Call.Pos.Filename,
-				Offset:   e.Call.Pos.Offset,
-				Line:     e.Call.Pos.Line,
-				Column:   e.Call.Pos.Column,
-			}
-		}
-		frames = append(frames, fr)
+		return fmt.Errorf("loading packages: %w", err)
 	}
-	return frames
-}
 
-func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
-	fr := &govulncheck.Frame{}
-	if pkg != nil {
-		fr.Module = pkg.Module.Path
-		fr.Version = pkg.Module.Version
-		fr.Package = pkg.PkgPath
-	}
-	if pkg.Module.Replace != nil {
-		fr.Module = pkg.Module.Replace.Path
-		fr.Version = pkg.Module.Replace.Version
+	if cfg.ScanLevel.WantPackages() && len(graph.TopPkgs()) == 0 {
+		return nil // early exit
 	}
-	return fr
-}
-
-// sourceProgressMessage returns a string of the form
-//
-//	"Scanning your code and P packages across M dependent modules for known vulnerabilities..."
-//
-// P is the number of strictly dependent packages of
-// topPkgs and Y is the number of their modules.
-func sourceProgressMessage(topPkgs []*packages.Package) *govulncheck.Progress {
-	pkgs, mods := depPkgsAndMods(topPkgs)
-
-	pkgsPhrase := fmt.Sprintf("%d package", pkgs)
-	if pkgs != 1 {
-		pkgsPhrase += "s"
-	}
-
-	modsPhrase := fmt.Sprintf("%d dependent module", mods)
-	if mods != 1 {
-		modsPhrase += "s"
-	}
-
-	msg := fmt.Sprintf("Scanning your code and %s across %s for known vulnerabilities...", pkgsPhrase, modsPhrase)
-	return &govulncheck.Progress{Message: msg}
-}
-
-// depPkgsAndMods returns the number of packages that
-// topPkgs depend on and the number of their modules.
-func depPkgsAndMods(topPkgs []*packages.Package) (int, int) {
-	tops := make(map[string]bool)
-	depPkgs := make(map[string]bool)
-	depMods := make(map[string]bool)
-
-	for _, t := range topPkgs {
-		tops[t.PkgPath] = true
-	}
-
-	var visit func(*packages.Package, bool)
-	visit = func(p *packages.Package, top bool) {
-		path := p.PkgPath
-		if depPkgs[path] {
-			return
-		}
-		if tops[path] && !top {
-			// A top package that is a dependency
-			// will not be in depPkgs, so we skip
-			// reiterating on it here.
-			return
-		}
-
-		// We don't count a top-level package as
-		// a dependency even when they are used
-		// as a dependent package.
-		if !tops[path] {
-			depPkgs[path] = true
-			if p.Module != nil &&
-				p.Module.Path != internal.GoStdModulePath && // no module for stdlib
-				p.Module.Path != internal.UnknownModulePath { // no module for unknown
-				depMods[p.Module.Path] = true
-			}
-		}
-
-		for _, d := range p.Imports {
-			visit(d, false)
-		}
-	}
-
-	for _, t := range topPkgs {
-		visit(t, true)
-	}
-
-	return len(depPkgs), len(depMods)
+	return vulncheck.Source(ctx, handler, &cfg.Config, client, graph)
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/template.go b/history-api/vendor/golang.org/x/vuln/internal/scan/template.go
index 953fbaeb..5c1a4a75 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/template.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/template.go
@@ -14,9 +14,9 @@ import (
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
 )
 
 type findingSummary struct {
@@ -26,9 +26,11 @@ type findingSummary struct {
 }
 
 type summaryCounters struct {
-	VulnerabilitiesCalled int
-	ModulesCalled         int
-	StdlibCalled          bool
+	VulnerabilitiesCalled   int
+	ModulesCalled           int
+	VulnerabilitiesImported int
+	VulnerabilitiesRequired int
+	StdlibCalled            bool
 }
 
 func fixupFindings(osvs []*osv.Entry, findings []*findingSummary) {
@@ -74,27 +76,22 @@ func groupBy(findings []*findingSummary, compare func(left, right *findingSummar
 	return result
 }
 
-func counters(findings []*findingSummary) summaryCounters {
-	vulns := map[string]struct{}{}
-	modules := map[string]struct{}{}
+func isRequired(findings []*findingSummary) bool {
 	for _, f := range findings {
-		if f.Trace[0].Function == "" {
-			continue
+		if f.Trace[0].Module != "" {
+			return true
 		}
-		id := f.OSV.ID
-		vulns[id] = struct{}{}
-		mod := f.Trace[0].Module
-		modules[mod] = struct{}{}
-	}
-	result := summaryCounters{
-		VulnerabilitiesCalled: len(vulns),
-		ModulesCalled:         len(modules),
 	}
-	if _, found := modules[internal.GoStdModulePath]; found {
-		result.StdlibCalled = true
-		result.ModulesCalled--
+	return false
+}
+
+func isImported(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if f.Trace[0].Package != "" {
+			return true
+		}
 	}
-	return result
+	return false
 }
 
 func isCalled(findings []*findingSummary) bool {
@@ -105,6 +102,7 @@ func isCalled(findings []*findingSummary) bool {
 	}
 	return false
 }
+
 func getOSV(osvs []*osv.Entry, id string) *osv.Entry {
 	for _, entry := range osvs {
 		if entry.ID == id {
@@ -184,7 +182,13 @@ func posToString(p *govulncheck.Position) string {
 
 func symbol(frame *govulncheck.Frame, short bool) string {
 	buf := &strings.Builder{}
-	addSymbolName(buf, frame, short)
+	addSymbol(buf, frame, short)
+	return buf.String()
+}
+
+func symbolName(frame *govulncheck.Frame) string {
+	buf := &strings.Builder{}
+	addSymbolName(buf, frame)
 	return buf.String()
 }
 
@@ -196,44 +200,36 @@ func symbol(frame *govulncheck.Frame, short bool) string {
 // If the vulnerable symbol is in the users code, it will show the entry point
 // and the vulnerable symbol.
 func compactTrace(finding *govulncheck.Finding) string {
-	if len(finding.Trace) < 1 {
+	compact := traces.Compact(finding)
+	if len(compact) == 0 {
 		return ""
 	}
-	iTop := len(finding.Trace) - 1
-	topModule := finding.Trace[iTop].Module
-	// search for the exit point of the top module
-	for i, frame := range finding.Trace {
-		if frame.Module == topModule {
-			iTop = i
-			break
-		}
-	}
-
-	if iTop == 0 {
-		// all in one module, reset to the end
-		iTop = len(finding.Trace) - 1
-	}
 
+	l := len(compact)
+	iTop := l - 1
 	buf := &strings.Builder{}
-	topPos := posToString(finding.Trace[iTop].Position)
+	topPos := posToString(compact[iTop].Position)
 	if topPos != "" {
 		buf.WriteString(topPos)
 		buf.WriteString(": ")
 	}
 
-	if iTop > 0 {
-		addSymbolName(buf, finding.Trace[iTop], true)
+	if l > 1 {
+		// print the root of the compact trace
+		addSymbol(buf, compact[iTop], true)
 		buf.WriteString(" calls ")
 	}
-	if iTop > 1 {
-		addSymbolName(buf, finding.Trace[iTop-1], true)
+	if l > 2 {
+		// print next element of the trace, if any
+		addSymbol(buf, compact[iTop-1], true)
 		buf.WriteString(", which")
-		if iTop > 2 {
+		if l > 3 {
+			// don't print the third element, just acknowledge it
 			buf.WriteString(" eventually")
 		}
 		buf.WriteString(" calls ")
 	}
-	addSymbolName(buf, finding.Trace[0], true)
+	addSymbol(buf, compact[0], true) // print the vulnerable symbol
 	return buf.String()
 }
 
@@ -265,7 +261,7 @@ func importPathToAssumedName(importPath string) string {
 	return base
 }
 
-func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
+func addSymbol(w io.Writer, frame *govulncheck.Frame, short bool) {
 	if frame.Function == "" {
 		return
 	}
@@ -277,6 +273,10 @@ func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
 		io.WriteString(w, pkg)
 		io.WriteString(w, ".")
 	}
+	addSymbolName(w, frame)
+}
+
+func addSymbolName(w io.Writer, frame *govulncheck.Frame) {
 	if frame.Receiver != "" {
 		if frame.Receiver[0] == '*' {
 			io.WriteString(w, frame.Receiver[1:])
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/text.go b/history-api/vendor/golang.org/x/vuln/internal/scan/text.go
index 845054b9..ab49bdd1 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/text.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/text.go
@@ -7,19 +7,19 @@ package scan
 import (
 	"fmt"
 	"io"
+	"sort"
 	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/vulncheck"
 )
 
 type style int
 
 const (
 	defaultStyle = style(iota)
-	goStyle
-	scannerStyle
 	osvCalledStyle
 	osvImportedStyle
 	detailsStyle
@@ -34,81 +34,143 @@ func NewTextHandler(w io.Writer) *TextHandler {
 }
 
 type TextHandler struct {
-	w        io.Writer
-	osvs     []*osv.Entry
-	findings []*findingSummary
+	w         io.Writer
+	sbom      *govulncheck.SBOM
+	osvs      []*osv.Entry
+	findings  []*findingSummary
+	scanLevel govulncheck.ScanLevel
+	scanMode  govulncheck.ScanMode
 
 	err error
 
-	showColor  bool
-	showTraces bool
+	showColor   bool
+	showTraces  bool
+	showVersion bool
+	showVerbose bool
 }
 
 const (
 	detailsMessage = `For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.`
 
 	binaryProgressMessage = `Scanning your binary for known vulnerabilities...`
-)
 
-func (h *TextHandler) Show(show []string) {
-	for _, show := range show {
-		switch show {
-		case "traces":
-			h.showTraces = true
-		case "color":
-			h.showColor = true
-		}
-	}
-}
+	noVulnsMessage = `No vulnerabilities found.`
 
-func Flush(h govulncheck.Handler) error {
-	if th, ok := h.(interface{ Flush() error }); ok {
-		return th.Flush()
-	}
-	return nil
-}
+	noOtherVulnsMessage = `No other vulnerabilities found.`
+
+	verboseMessage = `'-show verbose' for more details`
+
+	symbolMessage = `'-scan symbol' for more fine grained vulnerability detection`
+)
 
 func (h *TextHandler) Flush() error {
+	if h.showVerbose {
+		h.printSBOM()
+	}
 	if len(h.findings) == 0 {
-		return nil
+		h.print(noVulnsMessage + "\n")
+	} else {
+		fixupFindings(h.osvs, h.findings)
+		counters := h.allVulns(h.findings)
+		h.summary(counters)
 	}
-	fixupFindings(h.osvs, h.findings)
-	h.byVulnerability(h.findings)
-	h.summary(h.findings)
 	if h.err != nil {
 		return h.err
 	}
-	if isCalled(h.findings) {
+	// We found vulnerabilities when the findings' level matches the scan level.
+	if (isCalled(h.findings) && h.scanLevel == govulncheck.ScanLevelSymbol) ||
+		(isImported(h.findings) && h.scanLevel == govulncheck.ScanLevelPackage) ||
+		(isRequired(h.findings) && h.scanLevel == govulncheck.ScanLevelModule) {
 		return errVulnerabilitiesFound
 	}
+
 	return nil
 }
 
-// Config writes text output formatted according to govulncheck-intro.tmpl.
+// Config writes version information only if --version was set.
 func (h *TextHandler) Config(config *govulncheck.Config) error {
-	h.print("govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.\n\nUsing ")
+	h.scanLevel = config.ScanLevel
+	h.scanMode = config.ScanMode
+
+	if !h.showVersion {
+		return nil
+	}
 	if config.GoVersion != "" {
-		h.style(goStyle, config.GoVersion)
-		h.print(` and `)
+		h.style(keyStyle, "Go: ")
+		h.print(config.GoVersion, "\n")
 	}
 	if config.ScannerName != "" {
-		h.style(scannerStyle, config.ScannerName)
+		h.style(keyStyle, "Scanner: ")
+		h.print(config.ScannerName)
 		if config.ScannerVersion != "" {
 			h.print(`@`, config.ScannerVersion)
 		}
-		h.print(` with `)
+		h.print("\n")
 	}
-	h.print(`vulnerability data from `, config.DB)
-	if config.DBLastModified != nil {
-		h.print(` (last modified `, *config.DBLastModified, `)`)
+	if config.DB != "" {
+		h.style(keyStyle, "DB: ")
+		h.print(config.DB, "\n")
+		if config.DBLastModified != nil {
+			h.style(keyStyle, "DB updated: ")
+			h.print(*config.DBLastModified, "\n")
+		}
 	}
-	h.print(".\n\n")
+	h.print("\n")
 	return h.err
 }
 
-// Progress writes progress updates during govulncheck execution..
+func (h *TextHandler) SBOM(sbom *govulncheck.SBOM) error {
+	h.sbom = sbom
+	return nil
+}
+
+func (h *TextHandler) printSBOM() error {
+	if h.sbom == nil {
+		h.print("No packages matched the provided pattern.\n")
+		return nil
+	}
+
+	printed := false
+
+	for i, root := range h.sbom.Roots {
+		if i == 0 {
+			if len(h.sbom.Roots) > 1 {
+				h.print("The package pattern matched the following ", len(h.sbom.Roots), " root packages:\n")
+			} else {
+				h.print("The package pattern matched the following root package:\n")
+			}
+		}
+
+		h.print("  ", root, "\n")
+		printed = true
+	}
+	for i, mod := range h.sbom.Modules {
+		if i == 0 && mod.Path != "stdlib" {
+			h.print("Govulncheck scanned the following ", len(h.sbom.Modules)-1, " modules and the ", h.sbom.GoVersion, " standard library:\n")
+		}
+
+		if mod.Path == "stdlib" {
+			continue
+		}
+
+		h.print("  ", mod.Path)
+		if mod.Version != "" {
+			h.print("@", mod.Version)
+		}
+		h.print("\n")
+		printed = true
+	}
+	if printed {
+		h.print("\n")
+	}
+	return nil
+}
+
+// Progress writes progress updates during govulncheck execution.
 func (h *TextHandler) Progress(progress *govulncheck.Progress) error {
-	h.print(progress.Message, "\n\n")
+	if h.showVerbose {
+		h.print(progress.Message, "\n\n")
+	}
 	return h.err
 }
 
@@ -127,39 +189,64 @@ func (h *TextHandler) Finding(finding *govulncheck.Finding) error {
 	return nil
 }
 
-func (h *TextHandler) byVulnerability(findings []*findingSummary) {
+func (h *TextHandler) allVulns(findings []*findingSummary) summaryCounters {
 	byVuln := groupByVuln(findings)
-	called := 0
+	var called, imported, required [][]*findingSummary
+	mods := map[string]struct{}{}
+	stdlibCalled := false
 	for _, findings := range byVuln {
-		if isCalled(findings) {
-			if called > 0 {
-				h.print("\n")
+		switch {
+		case isCalled(findings):
+			called = append(called, findings)
+			if isStdFindings(findings) {
+				stdlibCalled = true
+			} else {
+				mods[findings[0].Trace[0].Module] = struct{}{}
 			}
-			h.vulnerability(called, findings)
-			called++
+		case isImported(findings):
+			imported = append(imported, findings)
+		default:
+			required = append(required, findings)
 		}
 	}
-	unCalled := len(byVuln) - called
-	if unCalled == 0 {
-		return
+
+	if h.scanLevel.WantSymbols() {
+		h.style(sectionStyle, "=== Symbol Results ===\n\n")
+		if len(called) == 0 {
+			h.print(noVulnsMessage, "\n\n")
+		}
+		for index, findings := range called {
+			h.vulnerability(index, findings)
+		}
 	}
-	h.print("\n")
-	h.style(sectionStyle, "=== Informational ===\n")
-	h.print("\nFound ", unCalled)
-	h.print(choose(unCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(" in packages that you import, but there are no call\nstacks leading to the use of ")
-	h.print(choose(unCalled == 1, `this vulnerability`, `these vulnerabilities`))
-	h.print(". You may not need to\ntake any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck\nfor details.\n\n")
-	index := 0
-	for _, findings := range byVuln {
-		if !isCalled(findings) {
-			if index > 0 {
-				h.print("\n")
-			}
+
+	if h.scanLevel == govulncheck.ScanLevelPackage || (h.scanLevel.WantPackages() && h.showVerbose) {
+		h.style(sectionStyle, "=== Package Results ===\n\n")
+		if len(imported) == 0 {
+			h.print(choose(!h.scanLevel.WantSymbols(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range imported {
 			h.vulnerability(index, findings)
-			index++
 		}
 	}
+
+	if h.showVerbose || h.scanLevel == govulncheck.ScanLevelModule {
+		h.style(sectionStyle, "=== Module Results ===\n\n")
+		if len(required) == 0 {
+			h.print(choose(!h.scanLevel.WantPackages(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range required {
+			h.vulnerability(index, findings)
+		}
+	}
+
+	return summaryCounters{
+		VulnerabilitiesCalled:   len(called),
+		VulnerabilitiesImported: len(imported),
+		VulnerabilitiesRequired: len(required),
+		ModulesCalled:           len(mods),
+		StdlibCalled:            stdlibCalled,
+	}
 }
 
 func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
@@ -185,13 +272,20 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 	byModule := groupByModule(findings)
 	first := true
 	for _, module := range byModule {
-		//TODO: this assumes all traces on a module are found and fixed at the same versions
+		// Note: there can be several findingSummaries for the same vulnerability
+		// emitted during streaming for different scan levels.
+
+		// The module is same for all finding summaries.
 		lastFrame := module[0].Trace[0]
 		mod := lastFrame.Module
+		// For stdlib, try to show package path as module name where
+		// the scan level allows it.
+		// TODO: should this be done in byModule as well?
 		path := lastFrame.Module
-		if path == internal.GoStdModulePath {
-			path = lastFrame.Package
+		if stdPkg := h.pkg(module); path == internal.GoStdModulePath && stdPkg != "" {
+			path = stdPkg
 		}
+		// All findings on a module are found and fixed at the same version
 		foundVersion := moduleVersionString(lastFrame.Module, lastFrame.Version)
 		fixedVersion := moduleVersionString(lastFrame.Module, module[0].FixedVersion)
 		if !first {
@@ -228,59 +322,180 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 		}
 		h.traces(module)
 	}
+	h.print("\n")
+}
+
+// pkg gives the package information for findings summaries
+// if one exists. This is only used to print package path
+// instead of a module for stdlib vulnerabilities at symbol
+// and package scan level.
+func (h *TextHandler) pkg(summaries []*findingSummary) string {
+	for _, f := range summaries {
+		if pkg := f.Trace[0].Package; pkg != "" {
+			return pkg
+		}
+	}
+	return ""
 }
 
+// traces prints out the most precise trace information
+// found in the given summaries.
 func (h *TextHandler) traces(traces []*findingSummary) {
-	first := true
-	for i, entry := range traces {
-		if entry.Compact == "" {
-			continue
+	// Sort the traces by the vulnerable symbol. This
+	// guarantees determinism since we are currently
+	// showing only one trace per symbol.
+	sort.SliceStable(traces, func(i, j int) bool {
+		return symbol(traces[i].Trace[0], true) < symbol(traces[j].Trace[0], true)
+	})
+
+	// compacts are finding summaries with compact traces
+	// suitable for non-verbose textual output. Currently,
+	// only traces produced by symbol analysis.
+	var compacts []*findingSummary
+	for _, t := range traces {
+		if t.Compact != "" {
+			compacts = append(compacts, t)
 		}
-		if first {
-			h.style(keyStyle, "    Example traces found:\n")
+	}
+
+	// binLimit is a limit on the number of binary traces
+	// to show. Traces for binaries are less interesting
+	// as users cannot act on them and they can hence
+	// spam users.
+	const binLimit = 5
+	binary := h.scanMode == govulncheck.ScanModeBinary
+	for i, entry := range compacts {
+		if i == 0 {
+			if binary {
+				h.style(keyStyle, "    Vulnerable symbols found:\n")
+			} else {
+				h.style(keyStyle, "    Example traces found:\n")
+			}
+		}
+
+		// skip showing all symbols in binary mode unless '-show traces' is on.
+		if binary && (i+1) > binLimit && !h.showTraces {
+			h.print("      Use '-show traces' to see the other ", len(compacts)-binLimit, " found symbols\n")
+			break
 		}
-		first = false
 
 		h.print("      #", i+1, ": ")
-		if !h.showTraces {
+
+		if !h.showTraces { // show summarized traces
 			h.print(entry.Compact, "\n")
+			continue
+		}
+
+		if binary {
+			// There are no call stacks in binary mode
+			// so just show the full symbol name.
+			h.print(symbol(entry.Trace[0], false), "\n")
 		} else {
 			h.print("for function ", symbol(entry.Trace[0], false), "\n")
 			for i := len(entry.Trace) - 1; i >= 0; i-- {
 				t := entry.Trace[i]
 				h.print("        ")
+				h.print(symbolName(t))
 				if t.Position != nil {
-					h.print(posToString(t.Position), ": ")
+					h.print(" @ ", symbolPath(t))
 				}
-				h.print(symbol(t, false), "\n")
+				h.print("\n")
 			}
 		}
 	}
 }
 
-func (h *TextHandler) summary(findings []*findingSummary) {
-	counters := counters(findings)
-	h.print("\n")
-	if counters.VulnerabilitiesCalled == 0 {
-		h.print("No vulnerabilities found.\n")
-		return
-	}
-	h.print(`Your code is affected by `)
-	h.style(valueStyle, counters.VulnerabilitiesCalled)
-	h.print(choose(counters.VulnerabilitiesCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(` from`)
-	if counters.ModulesCalled > 0 {
-		h.print(` `)
-		h.style(valueStyle, counters.ModulesCalled)
-		h.print(choose(counters.ModulesCalled == 1, ` module`, ` modules`))
+// symbolPath returns a user-friendly path to a symbol.
+func symbolPath(t *govulncheck.Frame) string {
+	// Add module path prefix to symbol paths to be more
+	// explicit to which module the symbols belong to.
+	return t.Module + "/" + posToString(t.Position)
+}
+
+func (h *TextHandler) summary(c summaryCounters) {
+	// print short summary of findings identified at the desired level of scan precision
+	var vulnCount int
+	h.print("Your code ", choose(h.scanLevel.WantSymbols(), "is", "may be"), " affected by ")
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		vulnCount = c.VulnerabilitiesCalled
+	case govulncheck.ScanLevelPackage:
+		vulnCount = c.VulnerabilitiesImported
+	case govulncheck.ScanLevelModule:
+		vulnCount = c.VulnerabilitiesRequired
 	}
-	if counters.StdlibCalled {
-		if counters.ModulesCalled != 0 {
-			h.print(` and`)
+	h.style(valueStyle, vulnCount)
+	h.print(choose(vulnCount == 1, ` vulnerability`, ` vulnerabilities`))
+	if h.scanLevel.WantSymbols() {
+		h.print(choose(c.ModulesCalled > 0 || c.StdlibCalled, ` from `, ``))
+		if c.ModulesCalled > 0 {
+			h.style(valueStyle, c.ModulesCalled)
+			h.print(choose(c.ModulesCalled == 1, ` module`, ` modules`))
+		}
+		if c.StdlibCalled {
+			if c.ModulesCalled != 0 {
+				h.print(` and `)
+			}
+			h.print(`the Go standard library`)
 		}
-		h.print(` the Go standard library`)
 	}
 	h.print(".\n")
+
+	// print summary for vulnerabilities found at other levels of scan precision
+	if other := h.summaryOtherVulns(c); other != "" {
+		h.wrap("", other, 80)
+		h.print("\n")
+	}
+
+	// print suggested flags for more/better info depending on scan level and if in verbose mode
+	if sugg := h.summarySuggestion(); sugg != "" {
+		h.wrap("", sugg, 80)
+		h.print("\n")
+	}
+}
+
+func (h *TextHandler) summaryOtherVulns(c summaryCounters) string {
+	var summary strings.Builder
+	if c.VulnerabilitiesRequired+c.VulnerabilitiesImported == 0 {
+		summary.WriteString("This scan found no other vulnerabilities in ")
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString("packages you import or ")
+		}
+		summary.WriteString("modules you require.")
+	} else {
+		summary.WriteString(choose(h.scanLevel.WantPackages(), "This scan also found ", ""))
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesImported))
+			summary.WriteString(choose(c.VulnerabilitiesImported == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in packages you import and ")
+		}
+		if h.scanLevel.WantPackages() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesRequired))
+			summary.WriteString(choose(c.VulnerabilitiesRequired == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in modules you require")
+			summary.WriteString(choose(h.scanLevel.WantSymbols(), ", but your code doesn't appear to call these vulnerabilities.", "."))
+		}
+	}
+	return summary.String()
+}
+
+func (h *TextHandler) summarySuggestion() string {
+	var sugg strings.Builder
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		if !h.showVerbose {
+			sugg.WriteString("Use " + verboseMessage + ".")
+		}
+	case govulncheck.ScanLevelPackage:
+		sugg.WriteString("Use " + symbolMessage)
+		if !h.showVerbose {
+			sugg.WriteString(" and " + verboseMessage)
+		}
+		sugg.WriteString(".")
+	case govulncheck.ScanLevelModule:
+		sugg.WriteString("Use " + symbolMessage + ".")
+	}
+	return sugg.String()
 }
 
 func (h *TextHandler) style(style style, values ...any) {
@@ -288,10 +503,6 @@ func (h *TextHandler) style(style style, values ...any) {
 		switch style {
 		default:
 			h.print(colorReset)
-		case goStyle:
-			h.print(colorBold)
-		case scannerStyle:
-			h.print(colorBold)
 		case osvCalledStyle:
 			h.print(colorBold, fgRed)
 		case osvImportedStyle:
@@ -347,9 +558,18 @@ func (h *TextHandler) wrap(indent string, s string, maxWidth int) {
 	}
 }
 
-func choose(b bool, yes, no any) any {
+func choose[t any](b bool, yes, no t) t {
 	if b {
 		return yes
 	}
 	return no
 }
+
+func isStdFindings(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if vulncheck.IsStdPackage(f.Trace[0].Package) || f.Trace[0].Module == internal.GoStdModulePath {
+			return true
+		}
+	}
+	return false
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/scan/util.go b/history-api/vendor/golang.org/x/vuln/internal/scan/util.go
index ce5500bb..0d82ca82 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/scan/util.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/scan/util.go
@@ -6,11 +6,12 @@ package scan
 
 import (
 	"fmt"
+	"os"
+	"os/exec"
+	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	isem "golang.org/x/vuln/internal/semver"
 )
 
 // validateFindings checks that the supplied findings all obey the protocol
@@ -25,48 +26,19 @@ func validateFindings(findings ...*govulncheck.Finding) error {
 		}
 		for _, frame := range f.Trace {
 			if frame.Version != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Version is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Version (%s) is set, Frame.Module must also be", frame.Version)
 			}
 			if frame.Package != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Package is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Package (%s) is set, Frame.Module must also be", frame.Package)
 			}
 			if frame.Function != "" && frame.Package == "" {
-				return fmt.Errorf("invalid finding: if Frame.Function is set, Frame.Package must also be")
+				return fmt.Errorf("invalid finding: if Frame.Function (%s) is set, Frame.Package must also be", frame.Function)
 			}
 		}
 	}
 	return nil
 }
 
-// latestFixed returns the latest fixed version in the list of affected ranges,
-// or the empty string if there are no fixed versions.
-func latestFixed(modulePath string, as []osv.Affected) string {
-	v := ""
-	for _, a := range as {
-		if modulePath != a.Module.Path {
-			continue
-		}
-		fixed := isem.LatestFixedVersion(a.Ranges)
-		// Special case: if there is any affected block for this module
-		// with no fix, the module is considered unfixed.
-		if fixed == "" {
-			return ""
-		}
-		if isem.Less(v, fixed) {
-			v = fixed
-		}
-	}
-	return v
-}
-
-func fixedVersion(modulePath string, affected []osv.Affected) string {
-	fixed := latestFixed(modulePath, affected)
-	if fixed != "" {
-		fixed = "v" + fixed
-	}
-	return fixed
-}
-
 func moduleVersionString(modulePath, version string) string {
 	if version == "" {
 		return ""
@@ -76,3 +48,13 @@ func moduleVersionString(modulePath, version string) string {
 	}
 	return version
 }
+
+func gomodExists(dir string) bool {
+	cmd := exec.Command("go", "env", "GOMOD")
+	cmd.Dir = dir
+	out, err := cmd.Output()
+	output := strings.TrimSpace(string(out))
+	// If module-aware mode is enabled, but there is no go.mod, GOMOD will be os.DevNull
+	// If module-aware mode is disabled, GOMOD will be the empty string.
+	return err == nil && !(output == os.DevNull || output == "")
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/semver/affects.go b/history-api/vendor/golang.org/x/vuln/internal/semver/affects.go
index 603d8277..03ea6fd7 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/semver/affects.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/semver/affects.go
@@ -21,7 +21,7 @@ func Affects(a []osv.Range, v string) bool {
 			continue
 		}
 		semverRangePresent = true
-		if containsSemver(r, v) {
+		if ContainsSemver(r, v) {
 			return true
 		}
 	}
@@ -32,9 +32,10 @@ func Affects(a []osv.Range, v string) bool {
 	return !semverRangePresent
 }
 
-// containsSemver checks if semver version v is in the
+// ContainsSemver checks if semver version v is in the
 // range encoded by ar. If ar is not a semver range,
-// returns false.
+// returns false. A range is interpreted as a left-closed
+// and right-open interval.
 //
 // Assumes that
 //   - exactly one of Introduced or Fixed fields is set
@@ -42,7 +43,7 @@ func Affects(a []osv.Range, v string) bool {
 //   - beginning of time is encoded with .Introduced="0"
 //   - no-fix is not an event, as opposed to being an
 //     event where Introduced="" and Fixed=""
-func containsSemver(ar osv.Range, v string) bool {
+func ContainsSemver(ar osv.Range, v string) bool {
 	if ar.Type != osv.RangeTypeSemver {
 		return false
 	}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/semver/fixed.go b/history-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
index 152fc1de..bd29c407 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
@@ -6,7 +6,11 @@ package semver
 
 import "golang.org/x/vuln/internal/osv"
 
-func LatestFixedVersion(ranges []osv.Range) string {
+// NonSupersededFix returns a fixed version from ranges
+// that is not superseded by any other fix or any other
+// introduction of a vulnerability. Returns "" in case
+// there is no such fixed version.
+func NonSupersededFix(ranges []osv.Range) string {
 	var latestFixed string
 	for _, r := range ranges {
 		if r.Type == "SEMVER" {
@@ -16,6 +20,7 @@ func LatestFixedVersion(ranges []osv.Range) string {
 					latestFixed = fixed
 				}
 			}
+
 			// If the vulnerability was re-introduced after the latest fix
 			// we found, there is no latest fix for this range.
 			for _, e := range r.Events {
diff --git a/history-api/vendor/golang.org/x/vuln/internal/semver/semver.go b/history-api/vendor/golang.org/x/vuln/internal/semver/semver.go
index fe0f701b..efe1e006 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/semver/semver.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/semver/semver.go
@@ -7,6 +7,7 @@
 package semver
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -93,3 +94,47 @@ func GoTagToSemver(tag string) string {
 	}
 	return version
 }
+
+// This is a modified copy of pkgsite/internal/stlib:TagForVersion
+func SemverToGoTag(v string) string {
+	// Special case: v1.0.0 => go1.
+	if v == "v1.0.0" {
+		return "go1"
+	}
+
+	goVersion := semver.Canonical(v)
+	prerelease := semver.Prerelease(goVersion)
+	versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)
+	patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".")
+	if patch == "0" && (semver.Compare(v, "v1.21.0") < 0 || prerelease != "") {
+		// Starting with go1.21.0, the first patch version includes .0.
+		// Prereleases do not include .0 (we don't do prereleases for other patch releases).
+		versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0")
+	}
+	goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v"))
+	if prerelease != "" {
+		i := finalDigitsIndex(prerelease)
+		if i >= 1 {
+			// Remove the dot.
+			prerelease = prerelease[:i-1] + prerelease[i:]
+		}
+		goVersion += prerelease
+	}
+	return goVersion
+}
+
+// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.
+// If s doesn't end in digits, it returns -1.
+func finalDigitsIndex(s string) int {
+	// Assume ASCII (since the semver package does anyway).
+	var i int
+	for i = len(s) - 1; i >= 0; i-- {
+		if s[i] < '0' || s[i] > '9' {
+			break
+		}
+	}
+	if i == len(s)-1 {
+		return -1
+	}
+	return i + 1
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/traces/traces.go b/history-api/vendor/golang.org/x/vuln/internal/traces/traces.go
new file mode 100644
index 00000000..e413ae7d
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/traces/traces.go
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package traces
+
+import (
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// Compact returns a summarization of finding.Trace. The first
+// returned element is the vulnerable symbol and the last element
+// is the exit point of the user module. There can also be two
+// elements in between, if applicable, which are the two elements
+// preceding the user module exit point.
+func Compact(finding *govulncheck.Finding) []*govulncheck.Frame {
+	if len(finding.Trace) < 1 {
+		return nil
+	}
+	iTop := len(finding.Trace) - 1
+	topModule := finding.Trace[iTop].Module
+	// search for the exit point of the top module
+	for i, frame := range finding.Trace {
+		if frame.Module == topModule {
+			iTop = i
+			break
+		}
+	}
+
+	if iTop == 0 {
+		// all in one module, reset to the end
+		iTop = len(finding.Trace) - 1
+	}
+
+	compact := []*govulncheck.Frame{finding.Trace[0]}
+	if iTop > 1 {
+		if iTop > 2 {
+			compact = append(compact, finding.Trace[iTop-2])
+		}
+		compact = append(compact, finding.Trace[iTop-1])
+	}
+	if iTop > 0 {
+		compact = append(compact, finding.Trace[iTop])
+	}
+	return compact
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
index a35a3a0a..d78af3ff 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
@@ -2,120 +2,184 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package vulncheck
 
 import (
 	"context"
 	"fmt"
-	"io"
-	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	"golang.org/x/vuln/internal/vulncheck/internal/buildinfo"
+	"golang.org/x/vuln/internal/semver"
 )
 
-// Binary detects presence of vulnerable symbols in exe.
-// The Calls, Imports, and Requires fields on Result will be empty.
-func Binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *Result, err error) {
-	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(exe)
+// Bin is an abstraction of Go binary containing
+// minimal information needed by govulncheck.
+type Bin struct {
+	// Path of the main package.
+	Path string `json:"path,omitempty"`
+	// Main module. When present, it never has empty information.
+	Main       *packages.Module   `json:"main,omitempty"`
+	Modules    []*packages.Module `json:"modules,omitempty"`
+	PkgSymbols []buildinfo.Symbol `json:"pkgSymbols,omitempty"`
+	GoVersion  string             `json:"goVersion,omitempty"`
+	GOOS       string             `json:"goos,omitempty"`
+	GOARCH     string             `json:"goarch,omitempty"`
+}
+
+// Binary detects presence of vulnerable symbols in bin and
+// emits findings to handler.
+func Binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) error {
+	vr, err := binary(ctx, handler, bin, cfg, client)
 	if err != nil {
-		return nil, fmt.Errorf("could not parse provided binary: %v", err)
+		return err
+	}
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, binaryCallstacks(vr))
+	}
+	return nil
+}
+
+// binary detects presence of vulnerable symbols in bin.
+// It does not compute call graphs so the corresponding
+// info in Result will be empty.
+func binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) (*Result, error) {
+	graph := NewPackageGraph(bin.GoVersion)
+	mods := append(bin.Modules, graph.GetModule(internal.GoStdModulePath))
+
+	if bin.Main != nil {
+		mods = append(mods, bin.Main)
 	}
 
-	graph := NewPackageGraph(bi.GoVersion)
 	graph.AddModules(mods...)
-	mods = append(mods, graph.GetModule(internal.GoStdModulePath))
+
+	if err := handler.SBOM(bin.SBOM()); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
+	}
 
 	mv, err := FetchVulnerabilities(ctx, client, mods)
 	if err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
 
-	goos := findSetting("GOOS", bi)
-	goarch := findSetting("GOARCH", bi)
-	if goos == "" || goarch == "" {
-		fmt.Printf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", goos, goarch)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingBinVulnsMessage}); err != nil {
+		return nil, err
+	}
+
+	// Emit warning message for ancient Go binaries, defined as binaries
+	// built with Go version without support for debug.BuildInfo (< go1.18).
+	if semver.Valid(bin.GoVersion) && semver.Less(bin.GoVersion, "go1.18") {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: binary built with Go version %s, only standard library vulnerabilities will be checked", bin.GoVersion)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+
+	if bin.GOOS == "" || bin.GOARCH == "" {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", bin.GOOS, bin.GOARCH)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+	affVulns := affectingVulnerabilities(mv, bin.GOOS, bin.GOARCH)
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
 
-	modVulns = modVulns.filter(goos, goarch)
-	result := &Result{}
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
+	}
 
-	if packageSymbols == nil {
+	// Group symbols per package to avoid querying affVulns all over again.
+	var pkgSymbols map[string][]string
+	if len(bin.PkgSymbols) == 0 {
 		// The binary exe is stripped. We currently cannot detect inlined
 		// symbols for stripped binaries (see #57764), so we report
 		// vulnerabilities at the go.mod-level precision.
-		addRequiresOnlyVulns(result, graph, modVulns)
+		pkgSymbols = allKnownVulnerableSymbols(affVulns)
 	} else {
-		for pkg, symbols := range packageSymbols {
-			if !cfg.ScanLevel.WantSymbols() {
-				addImportsOnlyVulns(result, graph, pkg, symbols, modVulns)
-			} else {
-				addSymbolVulns(result, graph, pkg, symbols, modVulns)
-			}
-		}
+		pkgSymbols = packagesAndSymbols(bin)
 	}
-	return result, nil
-}
 
-// addImportsOnlyVulns adds Vuln entries to result in imports only mode, i.e., for each vulnerable symbol
-// of pkg.
-func addImportsOnlyVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, osv := range modVulns.vulnsForPackage(pkg) {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg {
-					continue
-				}
-				syms := p.Symbols
-				if len(syms) == 0 {
-					// If every symbol of pkg is vulnerable, we would ideally
-					// compute every symbol mentioned in the pkg and then add
-					// Vuln entry for it, just as we do in Source. However,
-					// we don't have code of pkg here so we have to do best
-					// we can, which is the symbols of pkg actually appearing
-					// in the binary.
-					syms = symbols
-				}
+	impVulns := binImportedVulnPackages(graph, pkgSymbols, affVulns)
+	// Emit information on imported vulnerable packages now to
+	// mimic behavior of source.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
+	}
 
-				for _, symbol := range syms {
-					addVuln(result, graph, osv, symbol, pkg)
-				}
-			}
+	// Return result immediately if not in symbol mode to mimic the
+	// behavior of source.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
+
+	symVulns := binVulnSymbols(graph, pkgSymbols, affVulns)
+	return &Result{Vulns: symVulns}, nil
+}
+
+func packagesAndSymbols(bin *Bin) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, sym := range bin.PkgSymbols {
+		// If the name of the package is main, we need to expand
+		// it to its full path as that is what vuln db uses.
+		if sym.Pkg == "main" && bin.Path != "" {
+			pkgSymbols[bin.Path] = append(pkgSymbols[bin.Path], sym.Name)
+		} else {
+			pkgSymbols[sym.Pkg] = append(pkgSymbols[sym.Pkg], sym.Name)
 		}
 	}
+	return pkgSymbols
 }
 
-// addSymbolVulns adds Vuln entries to result for every symbol of pkg in the binary that is vulnerable.
-func addSymbolVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, symbol := range symbols {
-		for _, osv := range modVulns.vulnsForSymbol(pkg, symbol) {
-			addVuln(result, graph, osv, symbol, pkg)
+func binImportedVulnPackages(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg := range pkgSymbols {
+		for _, osv := range affVulns.ForPackage(internal.UnknownModulePath, pkg) {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg),
+			}
+			vulns = append(vulns, vuln)
 		}
 	}
+	return vulns
 }
 
-// findSetting returns value of setting from bi if present.
-// Otherwise, returns "".
-func findSetting(setting string, bi *debug.BuildInfo) string {
-	for _, s := range bi.Settings {
-		if s.Key == setting {
-			return s.Value
+func binVulnSymbols(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg, symbols := range pkgSymbols {
+		for _, symbol := range symbols {
+			for _, osv := range affVulns.ForSymbol(internal.UnknownModulePath, pkg, symbol) {
+				vuln := &Vuln{
+					OSV:     osv,
+					Symbol:  symbol,
+					Package: graph.GetPackage(pkg),
+				}
+				vulns = append(vulns, vuln)
+			}
 		}
 	}
-	return ""
+	return vulns
 }
 
-// addRequiresOnlyVulns adds to result all vulnerabilities in modVulns.
-// Used when the binary under analysis is stripped.
-func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVulnerabilities) {
-	for _, mv := range modVulns {
+// allKnownVulnerableSymbols returns all known vulnerable symbols for packages in graph.
+// If all symbols of a package are vulnerable, that is modeled as a wild car symbol "/*".
+func allKnownVulnerableSymbols(affVulns affectingVulns) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, mv := range affVulns {
 		for _, osv := range mv.Vulns {
 			for _, affected := range osv.Affected {
 				for _, p := range affected.EcosystemSpecific.Packages {
@@ -134,19 +198,40 @@ func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVu
 						syms = []string{fmt.Sprintf("%s/*", p.Path)}
 					}
 
-					for _, symbol := range syms {
-						addVuln(result, graph, osv, symbol, p.Path)
-					}
+					pkgSymbols[p.Path] = append(pkgSymbols[p.Path], syms...)
 				}
 			}
 		}
 	}
+	return pkgSymbols
 }
 
-func addVuln(result *Result, graph *PackageGraph, osv *osv.Entry, symbol string, pkgPath string) {
-	result.Vulns = append(result.Vulns, &Vuln{
-		OSV:        osv,
-		Symbol:     symbol,
-		ImportSink: graph.GetPackage(pkgPath),
+func (bin *Bin) SBOM() (sbom *govulncheck.SBOM) {
+	sbom = &govulncheck.SBOM{}
+	if bin.Main != nil {
+		sbom.Roots = []string{bin.Main.Path}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    bin.Main.Path,
+			Version: bin.Main.Version,
+		})
+	}
+
+	sbom.GoVersion = bin.GoVersion
+	for _, mod := range bin.Modules {
+		if mod.Replace != nil {
+			mod = mod.Replace
+		}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		})
+	}
+
+	// add stdlib to mirror source mode output
+	sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+		Path:    internal.GoStdModulePath,
+		Version: bin.GoVersion,
 	})
+
+	return sbom
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
index 3f19e299..e56cdfbc 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
@@ -24,8 +24,7 @@ detection in Go source code and binaries, respectively.
 
 [Source] accepts a list of [Package] objects, which
 are a trimmed version of [golang.org/x/tools/go/packages.Package] objects to
-reduce memory consumption. [Binary] accepts a path to a Go binary file that
-must have been compiled with Go 1.18 or greater.
+reduce memory consumption. [Binary] accepts a path to a Go binary file.
 
 Both [Source] and [Binary] require information about known
 vulnerabilities in the form of a vulnerability database,
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
new file mode 100644
index 00000000..fc9b2d7a
--- /dev/null
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
@@ -0,0 +1,198 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vulncheck
+
+import (
+	"go/token"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// emitOSVs emits all OSV vuln entries in modVulns to handler.
+func emitOSVs(handler govulncheck.Handler, modVulns []*ModVulns) error {
+	for _, mv := range modVulns {
+		for _, v := range mv.Vulns {
+			if err := handler.OSV(v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitModuleFindings emits module-level findings for vulnerabilities in modVulns.
+func emitModuleFindings(handler govulncheck.Handler, affVulns affectingVulns) error {
+	for _, vuln := range affVulns {
+		for _, osv := range vuln.Vulns {
+			if err := handler.Finding(&govulncheck.Finding{
+				OSV:          osv.ID,
+				FixedVersion: FixedVersion(modPath(vuln.Module), modVersion(vuln.Module), osv.Affected),
+				Trace:        []*govulncheck.Frame{frameFromModule(vuln.Module)},
+			}); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitPackageFinding emits package-level findings fod vulnerabilities in vulns.
+func emitPackageFindings(handler govulncheck.Handler, vulns []*Vuln) error {
+	for _, v := range vulns {
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          v.OSV.ID,
+			FixedVersion: FixedVersion(modPath(v.Package.Module), modVersion(v.Package.Module), v.OSV.Affected),
+			Trace:        []*govulncheck.Frame{frameFromPackage(v.Package)},
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// emitCallFindings emits call-level findings for vulnerabilities
+// that have a call stack in callstacks.
+func emitCallFindings(handler govulncheck.Handler, callstacks map[*Vuln]CallStack) error {
+	var vulns []*Vuln
+	for v := range callstacks {
+		vulns = append(vulns, v)
+	}
+
+	for _, vuln := range vulns {
+		stack := callstacks[vuln]
+		if stack == nil {
+			continue
+		}
+		fixed := FixedVersion(modPath(vuln.Package.Module), modVersion(vuln.Package.Module), vuln.OSV.Affected)
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          vuln.OSV.ID,
+			FixedVersion: fixed,
+			Trace:        traceFromEntries(stack),
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// traceFromEntries creates a sequence of
+// frames from vcs. Position of a Frame is the
+// call position of the corresponding stack entry.
+func traceFromEntries(vcs CallStack) []*govulncheck.Frame {
+	var frames []*govulncheck.Frame
+	for i := len(vcs) - 1; i >= 0; i-- {
+		e := vcs[i]
+		fr := frameFromPackage(e.Function.Package)
+		fr.Function = e.Function.Name
+		fr.Receiver = e.Function.Receiver()
+		isSink := i == (len(vcs) - 1)
+		fr.Position = posFromStackEntry(e, isSink)
+		frames = append(frames, fr)
+	}
+	return frames
+}
+
+func posFromStackEntry(e StackEntry, sink bool) *govulncheck.Position {
+	var p *token.Position
+	var f *FuncNode
+	if sink && e.Function != nil && e.Function.Pos != nil {
+		// For sinks, i.e., vulns we take the position
+		// of the symbol.
+		p = e.Function.Pos
+		f = e.Function
+	} else if e.Call != nil && e.Call.Pos != nil {
+		// Otherwise, we take the position of
+		// the call statement.
+		p = e.Call.Pos
+		f = e.Call.Parent
+	}
+
+	if p == nil {
+		return nil
+	}
+	return &govulncheck.Position{
+		Filename: pathRelativeToMod(p.Filename, f),
+		Offset:   p.Offset,
+		Line:     p.Line,
+		Column:   p.Column,
+	}
+}
+
+// pathRelativeToMod computes a version of path
+// relative to the module of f. If it does not
+// have all the necessary information, returns
+// an empty string.
+//
+// The returned paths always use slash as separator
+// so they can work across different platforms.
+func pathRelativeToMod(path string, f *FuncNode) string {
+	if path == "" || f == nil || f.Package == nil { // sanity
+		return ""
+	}
+
+	mod := f.Package.Module
+	if mod.Replace != nil {
+		mod = mod.Replace // for replace directive
+	}
+
+	modDir := modDirWithVendor(mod.Dir, path, mod.Path)
+	p, err := filepath.Rel(modDir, path)
+	if err != nil {
+		return ""
+	}
+	// make sure paths are portable.
+	return filepath.ToSlash(p)
+}
+
+// modDirWithVendor returns modDir if modDir is not empty.
+// Otherwise, the module might be located in the vendor
+// directory. This function attempts to reconstruct the
+// vendored module directory from path and module. It
+// returns an empty string if reconstruction fails.
+func modDirWithVendor(modDir, path, module string) string {
+	if modDir != "" {
+		return modDir
+	}
+
+	sep := string(os.PathSeparator)
+	vendor := sep + "vendor" + sep
+	vendorIndex := strings.Index(path, vendor)
+	if vendorIndex == -1 {
+		return ""
+	}
+	return filepath.Join(path[:vendorIndex], "vendor", filepath.FromSlash(module))
+}
+
+func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
+	fr := &govulncheck.Frame{}
+	if pkg != nil {
+		fr.Module = pkg.Module.Path
+		fr.Version = pkg.Module.Version
+		fr.Package = pkg.PkgPath
+	}
+	if pkg.Module.Replace != nil {
+		fr.Module = pkg.Module.Replace.Path
+		fr.Version = pkg.Module.Replace.Version
+	}
+	return fr
+}
+
+func frameFromModule(mod *packages.Module) *govulncheck.Frame {
+	fr := &govulncheck.Frame{
+		Module:  mod.Path,
+		Version: mod.Version,
+	}
+
+	if mod.Replace != nil {
+		fr.Module = mod.Replace.Path
+		fr.Version = mod.Replace.Version
+	}
+
+	return fr
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
index 834d5901..3d46f6ca 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
@@ -10,6 +10,12 @@ import (
 	"golang.org/x/tools/go/ssa"
 )
 
+// entryPoints returns functions of topPackages considered entry
+// points of govulncheck analysis: main, inits, and exported methods
+// and functions.
+//
+// TODO(https://go.dev/issue/57221): currently, entry functions
+// that are generics are not considered an entry point.
 func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
 	var entries []*ssa.Function
 	for _, pkg := range topPackages {
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
index ef0c7ca9..700a7f99 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
@@ -6,6 +6,7 @@ package vulncheck
 
 import (
 	"context"
+	"fmt"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal/client"
@@ -25,7 +26,7 @@ func FetchVulnerabilities(ctx context.Context, c *client.Client, modules []*pack
 	}
 	resps, err := c.ByModules(ctx, mreqs)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("fetching vulnerabilities: %v", err)
 	}
 	var mv []*ModVulns
 	for i, resp := range resps {
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
deleted file mode 100644
index 1bdd38c7..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// This file adds to buildinfo the functionality for extracting the PCLN table.
-
-import (
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-)
-
-// ErrNoSymbols represents non-existence of symbol
-// table in binaries supported by buildinfo.
-var ErrNoSymbols = errors.New("no symbol section")
-
-// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
-func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		if errors.Is(err, elf.ErrNoSymbols) {
-			return 0, 0, nil, ErrNoSymbols
-		}
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	prog := x.progContaining(sym.Value)
-	if prog == nil {
-		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
-}
-
-func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		syms, err := x.f.Symbols()
-		if err != nil {
-			x.symbolsErr = err
-			return
-		}
-		x.symbols = make(map[string]*elf.Symbol, len(syms))
-		for _, s := range syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-func (x *elfExe) progContaining(addr uint64) *elf.Prog {
-	for _, p := range x.f.Progs {
-		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
-			return p
-		}
-	}
-	return nil
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
-	var offset uint64
-	text := x.f.Section(".text")
-	if text != nil {
-		offset = text.Offset
-	}
-	pclntab := x.f.Section(".gopclntab")
-	if pclntab == nil {
-		// Addition: this code is added to support some form of stripping.
-		pclntab = x.f.Section(".data.rel.ro.gopclntab")
-		if pclntab == nil {
-			pclntab = x.f.Section(".data.rel.ro")
-			if pclntab == nil {
-				return nil, 0
-			}
-			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
-			// its own section header. We can search for for the start by looking for the four
-			// byte magic and the go magic.
-			b, err := pclntab.Data()
-			if err != nil {
-				return nil, 0
-			}
-			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
-			// actually correct. During testing it worked, but that may be because I got lucky
-			// with the binary I was using, and we need to do four byte jumps to exhaustively
-			// search the section?
-			for i := 0; i < len(b); i += 16 {
-				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
-					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
-					(b[i+7] == 4 || b[i+7] == 8) {
-					// Also check for the go magic
-					leMagic := binary.LittleEndian.Uint32(b[i:])
-					beMagic := binary.BigEndian.Uint32(b[i:])
-					switch {
-					case leMagic == go12magic:
-						fallthrough
-					case beMagic == go12magic:
-						fallthrough
-					case leMagic == go116magic:
-						fallthrough
-					case beMagic == go116magic:
-						return b[i:], offset
-					}
-				}
-			}
-		}
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, offset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
-func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		return 0, 0, nil, err
-	}
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	sect := x.f.Sections[sym.SectionNumber-1]
-	// In PE, the symbol's value is the offset from the section start.
-	return uint64(sym.Value), 0, sect.ReaderAt, nil
-}
-
-func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
-		if len(x.f.Symbols) == 0 {
-			x.symbolsErr = ErrNoSymbols
-			return
-		}
-		for _, s := range x.f.Symbols {
-			x.symbols[s.Name] = s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
-// Assumes that the underlying symbol table exists, otherwise
-// it might panic.
-func (x *peExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	for _, section := range x.f.Sections {
-		if section.Name == ".text" {
-			textOffset = uint64(section.Offset)
-			break
-		}
-	}
-
-	var start, end int64
-	var section int
-	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
-		start = int64(s.Value)
-		section = int(s.SectionNumber - 1)
-	}
-	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
-		end = int64(s.Value)
-	}
-	if start == 0 || end == 0 {
-		return nil, 0
-	}
-	offset := int64(x.f.Sections[section].Offset) + start
-	size := end - start
-
-	pclntab := make([]byte, size)
-	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
-		return nil, 0
-	}
-	return pclntab, textOffset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
-func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym := x.lookupSymbol(name)
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	seg := x.segmentContaining(sym.Value)
-	if seg == nil {
-		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, seg.Addr, seg.ReaderAt, nil
-}
-
-func (x *machoExe) lookupSymbol(name string) *macho.Symbol {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
-		for _, s := range x.f.Symtab.Syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	return x.symbols[name]
-}
-
-func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
-			return seg
-		}
-	}
-	return nil
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	text := x.f.Section("__text")
-	if text != nil {
-		textOffset = uint64(text.Offset)
-	}
-	pclntab := x.f.Section("__gopclntab")
-	if pclntab == nil {
-		return nil, 0
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, textOffset
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
deleted file mode 100644
index 9790cfa9..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
-	"debug/buildinfo"
-	"errors"
-	"fmt"
-	"io"
-	"net/url"
-	"runtime/debug"
-	"sort"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal/vulncheck/internal/gosym"
-)
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
-	packagesModules := make([]*packages.Module, len(debugModules))
-	for i, mod := range debugModules {
-		packagesModules[i] = &packages.Module{
-			Path:    mod.Path,
-			Version: mod.Version,
-		}
-		if mod.Replace != nil {
-			packagesModules[i].Replace = &packages.Module{
-				Path:    mod.Replace.Path,
-				Version: mod.Replace.Version,
-			}
-		}
-	}
-	return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts symbols, packages, modules from
-// bin as well as bin's metadata.
-//
-// If the symbol table is not available, such as in the case of stripped
-// binaries, returns module and binary info but without the symbol info.
-func ExtractPackagesAndSymbols(bin io.ReaderAt) ([]*packages.Module, map[string][]string, *debug.BuildInfo, error) {
-	bi, err := buildinfo.Read(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	funcSymName := gosym.FuncSymName(bi.GoVersion)
-	if funcSymName == "" {
-		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
-	}
-
-	x, err := openExe(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	value, base, r, err := x.SymbolInfo(funcSymName)
-	if err != nil {
-		if errors.Is(err, ErrNoSymbols) {
-			// bin is stripped, so return just module info and metadata.
-			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
-		}
-		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
-	}
-
-	pclntab, textOffset := x.PCLNTab()
-	if pclntab == nil {
-		// TODO(https://go.dev/issue/59731): if we have build information, but
-		// not PCLN table, we should be able to fall back to much higher
-		// granularity vulnerability checking.
-		return nil, nil, nil, errors.New("unable to load the PCLN table")
-	}
-	lineTab := gosym.NewLineTable(pclntab, textOffset)
-	if lineTab == nil {
-		return nil, nil, nil, errors.New("invalid line table")
-	}
-	tab, err := gosym.NewTable(nil, lineTab)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	type pkgSymbol struct {
-		pkg string
-		sym string
-	}
-	pkgSyms := make(map[pkgSymbol]bool)
-	for _, f := range tab.Funcs {
-		if f.Func == nil {
-			continue
-		}
-		pkgName, symName, err := parseName(f.Func.Sym)
-		if err != nil {
-			return nil, nil, nil, err
-		}
-		pkgSyms[pkgSymbol{pkgName, symName}] = true
-
-		// Collect symbols that were inlined in f.
-		it, err := lineTab.InlineTree(&f, value, base, r)
-		if err != nil {
-			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
-		}
-		for _, ic := range it {
-			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
-			if err != nil {
-				return nil, nil, nil, err
-			}
-			pkgSyms[pkgSymbol{pkgName, symName}] = true
-		}
-	}
-
-	packageSymbols := make(map[string][]string)
-	for p := range pkgSyms {
-		packageSymbols[p.pkg] = append(packageSymbols[p.pkg], p.sym)
-	}
-	// Sort symbols per pkg for deterministic results.
-	for _, syms := range packageSymbols {
-		sort.Strings(syms)
-	}
-
-	return debugModulesToPackagesModules(bi.Deps), packageSymbols, bi, nil
-}
-
-func parseName(s *gosym.Sym) (pkg, sym string, err error) {
-	symName := s.BaseName()
-	if r := s.ReceiverName(); r != "" {
-		if strings.HasPrefix(r, "(*") {
-			r = strings.Trim(r, "(*)")
-		}
-		symName = fmt.Sprintf("%s.%s", r, symName)
-	}
-
-	pkgName := s.PackageName()
-	if pkgName != "" {
-		pkgName, err = url.PathUnescape(pkgName)
-		if err != nil {
-			return "", "", err
-		}
-	}
-	return pkgName, symName, nil
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
deleted file mode 100644
index 1be795ee..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
-
-import (
-	"bytes"
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"fmt"
-	"sync"
-
-	// "internal/xcoff"
-	"io"
-)
-
-// Addition: modification of rawBuildInfo in the original file.
-// openExe returns reader r as an exe.
-func openExe(r io.ReaderAt) (exe, error) {
-	data := make([]byte, 16)
-	if _, err := r.ReadAt(data, 0); err != nil {
-		return nil, err
-	}
-	if bytes.HasPrefix(data, []byte("\x7FELF")) {
-		e, err := elf.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &elfExe{f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("MZ")) {
-		e, err := pe.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &peExe{r: r, f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
-		e, err := macho.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &machoExe{f: e}, nil
-	}
-	return nil, fmt.Errorf("unrecognized executable format")
-}
-
-type exe interface {
-	// ReadData reads and returns up to size byte starting at virtual address addr.
-	ReadData(addr, size uint64) ([]byte, error)
-
-	// DataStart returns the virtual address of the segment or section that
-	// should contain build information. This is either a specially named section
-	// or the first writable non-zero data segment.
-	DataStart() uint64
-
-	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
-
-	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
-	f *elf.File
-
-	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once              // Addition: for computing symbols
-	symbolsErr  error                  // Addition: error for computing symbols
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, prog := range x.f.Progs {
-		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
-			n := prog.Vaddr + prog.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *elfExe) DataStart() uint64 {
-	for _, s := range x.f.Sections {
-		if s.Name == ".go.buildinfo" {
-			return s.Addr
-		}
-	}
-	for _, p := range x.f.Progs {
-		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
-			return p.Vaddr
-		}
-	}
-	return 0
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
-	r io.ReaderAt
-	f *pe.File
-
-	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once             // Addition: for computing symbols
-	symbolsErr  error                 // Addition: error for computing symbols
-}
-
-func (x *peExe) imageBase() uint64 {
-	switch oh := x.f.OptionalHeader.(type) {
-	case *pe.OptionalHeader32:
-		return uint64(oh.ImageBase)
-	case *pe.OptionalHeader64:
-		return oh.ImageBase
-	}
-	return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
-	addr -= x.imageBase()
-	for _, sect := range x.f.Sections {
-		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-			n := uint64(sect.VirtualAddress+sect.Size) - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *peExe) DataStart() uint64 {
-	// Assume data is first writable section.
-	const (
-		IMAGE_SCN_CNT_CODE               = 0x00000020
-		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-		IMAGE_SCN_MEM_READ               = 0x40000000
-		IMAGE_SCN_MEM_WRITE              = 0x80000000
-		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-	)
-	for _, sect := range x.f.Sections {
-		if sect.VirtualAddress != 0 && sect.Size != 0 &&
-			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
-			return uint64(sect.VirtualAddress) + x.imageBase()
-		}
-	}
-	return 0
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
-	f *macho.File
-
-	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once                // Addition: for computing symbols
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if !ok {
-			continue
-		}
-		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
-			if seg.Name == "__PAGEZERO" {
-				continue
-			}
-			n := seg.Addr + seg.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *machoExe) DataStart() uint64 {
-	// Look for section named "__go_buildinfo".
-	for _, sec := range x.f.Sections {
-		if sec.Name == "__go_buildinfo" {
-			return sec.Addr
-		}
-	}
-	// Try the first non-empty writable segment.
-	const RW = 3
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
-			return seg.Addr
-		}
-	}
-	return 0
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
deleted file mode 100644
index f608c151..00000000
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gosym
-
-import (
-	"encoding/binary"
-	"io"
-	"strings"
-
-	sv "golang.org/x/mod/semver"
-	"golang.org/x/vuln/internal/semver"
-)
-
-const (
-	funcSymNameGo119Lower string = "go.func.*"
-	funcSymNameGo120      string = "go:func.*"
-)
-
-// FuncSymName returns symbol name for Go functions
-// used in binaries based on Go version. Supported
-// Go versions are 1.18, 1.19, and 1.20. Otherwise,
-// returns an empty string.
-func FuncSymName(goVersion string) string {
-	// Support devel goX.Y...
-	v := strings.TrimPrefix(goVersion, "devel ")
-	v = semver.GoTagToSemver(v)
-	mm := sv.MajorMinor(v)
-	if mm == "v1.18" || mm == "v1.19" {
-		return funcSymNameGo119Lower
-	} else if mm == "v1.20" {
-		return funcSymNameGo120
-	} else if v == "" && strings.HasPrefix(goVersion, "devel") {
-		// We currently don't have a direct way of mapping
-		// Go versions of the form devel  to semver,
-		// so we map it to the most recent supported major
-		// Go version, which is currently go1.20.
-		return funcSymNameGo120
-	}
-	return ""
-}
-
-// Additions to the original package from cmd/internal/objabi/funcdata.go
-const (
-	pcdata_InlTreeIndex = 2
-	funcdata_InlTree    = 3
-)
-
-// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
-// goFuncValue is the value of the gosym.FuncSymName symbol.
-// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
-// progReader is a ReaderAt positioned at the start of that region.
-func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
-	if f.inlineTreeCount == 0 {
-		return nil, nil
-	}
-	if f.inlineTreeOffset == ^uint32(0) {
-		return nil, nil
-	}
-	var offset int64
-	if t.version >= ver118 {
-		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
-	} else {
-		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
-	}
-
-	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
-	var ics []InlinedCall
-	for i := 0; i < f.inlineTreeCount; i++ {
-		if t.version >= ver120 {
-			var ric rawInlinedCall120
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.NameOff)),
-				ParentPC: ric.ParentPC,
-			})
-		} else {
-			var ric rawInlinedCall112
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.Func_)),
-				ParentPC: ric.ParentPC,
-			})
-		}
-	}
-	return ics, nil
-}
-
-// InlinedCall describes a call to an inlined function.
-type InlinedCall struct {
-	FuncID   uint8  // type of the called function
-	Name     string // name of called function
-	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall112 struct {
-	Parent   int16 // index of parent in the inltree, or < 0
-	FuncID   uint8 // type of the called function
-	_        byte
-	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
-	Line     int32 // line number of the call site
-	Func_    int32 // offset into pclntab for name of called function
-	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.20. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall120 struct {
-	FuncID    uint8 // type of the called function
-	_         [3]byte
-	NameOff   int32 // offset into pclntab for name of called function
-	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
-	StartLine int32 // line number of start of function (func keyword/TEXT directive)
-}
-
-func (f funcData) npcdata() uint32 { return f.field(7) }
-func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
-	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
-}
-
-func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.nfuncdata(numFuncFields) {
-		return ^uint32(0)
-	}
-	var off uint32
-	if f.t.version >= ver118 {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4 + // skip pcdata
-			uint32(i)*4 // index of i'th FUNCDATA
-	} else {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4
-		off += uint32(i) * f.t.ptrsize
-	}
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-func (f funcData) fieldOffset(n uint32) uint32 {
-	// In Go 1.18, the first field of _func changed
-	// from a uintptr entry PC to a uint32 entry offset.
-	sz0 := f.t.ptrsize
-	if f.t.version >= ver118 {
-		sz0 = 4
-	}
-	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
-}
-
-func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.npcdata() {
-		return ^uint32(0)
-	}
-	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
-		uint32(i)*4 // index of i'th PCDATA
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-// maxInlineTreeIndexValue returns the maximum value of the inline tree index
-// pc-value table in info. This is the only way to determine how many
-// IndexedCalls are in an inline tree, since the data of the tree itself is not
-// delimited in any way.
-func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
-	if info.npcdata() <= pcdata_InlTreeIndex {
-		return -1
-	}
-	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
-	p := t.pctab[off:]
-	val := int32(-1)
-	max := int32(-1)
-	var pc uint64
-	for t.step(&p, &pc, &val, pc == 0) {
-		if val > max {
-			max = val
-		}
-	}
-	return int(max)
-}
-
-type inlTree struct {
-	inlineTreeOffset uint32 // offset from go.func.* symbol
-	inlineTreeCount  int    // number of entries in inline tree
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
index 124a9a50..484e5494 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
@@ -6,18 +6,25 @@ package vulncheck
 
 import (
 	"fmt"
+	"os/exec"
+	"slices"
 	"strings"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/semver"
 )
 
 // PackageGraph holds a complete module and package graph.
-// Its primary purpose is to allow fast access to the nodes by path.
+// Its primary purpose is to allow fast access to the nodes
+// by path and make sure all(stdlib)  packages have a module.
 type PackageGraph struct {
-	modules  map[string]*packages.Module
-	packages map[string]*packages.Package
+	// topPkgs are top-level packages specified by the user.
+	// Empty in binary mode.
+	topPkgs  []*packages.Package
+	modules  map[string]*packages.Module  // all modules (even replacing ones)
+	packages map[string]*packages.Package // all packages (even dependencies)
 }
 
 func NewPackageGraph(goVersion string) *PackageGraph {
@@ -25,15 +32,83 @@ func NewPackageGraph(goVersion string) *PackageGraph {
 		modules:  map[string]*packages.Module{},
 		packages: map[string]*packages.Package{},
 	}
-	graph.AddModules(&packages.Module{
+
+	goRoot := ""
+	if out, err := exec.Command("go", "env", "GOROOT").Output(); err == nil {
+		goRoot = strings.TrimSpace(string(out))
+	}
+	stdlibModule := &packages.Module{
 		Path:    internal.GoStdModulePath,
 		Version: semver.GoTagToSemver(goVersion),
-	})
+		Dir:     goRoot,
+	}
+	graph.AddModules(stdlibModule)
 	return graph
 }
 
+func (g *PackageGraph) TopPkgs() []*packages.Package {
+	return g.topPkgs
+}
+
+// DepPkgs returns the number of packages that graph.TopPkgs()
+// strictly depend on. This does not include topPkgs even if
+// they are dependency of each other.
+func (g *PackageGraph) DepPkgs() []*packages.Package {
+	topPkgs := g.TopPkgs()
+	tops := make(map[string]bool)
+	depPkgs := make(map[string]*packages.Package)
+
+	for _, t := range topPkgs {
+		tops[t.PkgPath] = true
+	}
+
+	var visit func(*packages.Package, bool)
+	visit = func(p *packages.Package, top bool) {
+		path := p.PkgPath
+		if _, ok := depPkgs[path]; ok {
+			return
+		}
+		if tops[path] && !top {
+			// A top package that is a dependency
+			// will not be in depPkgs, so we skip
+			// reiterating on it here.
+			return
+		}
+
+		// We don't count a top-level package as
+		// a dependency even when they are used
+		// as a dependent package.
+		if !tops[path] {
+			depPkgs[path] = p
+		}
+
+		for _, d := range p.Imports {
+			visit(d, false)
+		}
+	}
+
+	for _, t := range topPkgs {
+		visit(t, true)
+	}
+
+	var deps []*packages.Package
+	for _, d := range depPkgs {
+		deps = append(deps, g.GetPackage(d.PkgPath))
+	}
+	return deps
+}
+
+func (g *PackageGraph) Modules() []*packages.Module {
+	var mods []*packages.Module
+	for _, m := range g.modules {
+		mods = append(mods, m)
+	}
+	return mods
+}
+
 // AddModules adds the modules and any replace modules provided.
-// It will ignore modules that have duplicate paths to ones the graph already holds.
+// It will ignore modules that have duplicate paths to ones the
+// graph already holds.
 func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	for _, mod := range mods {
 		if _, found := g.modules[mod.Path]; found {
@@ -47,7 +122,8 @@ func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	}
 }
 
-// .
+// GetModule gets module at path if one exists. Otherwise,
+// it creates a module and returns it.
 func (g *PackageGraph) GetModule(path string) *packages.Module {
 	if mod, ok := g.modules[path]; ok {
 		return mod
@@ -60,8 +136,9 @@ func (g *PackageGraph) GetModule(path string) *packages.Module {
 	return mod
 }
 
-// AddPackages adds the packages and the full graph of imported packages.
-// It will ignore packages that have duplicate paths to ones the graph already holds.
+// AddPackages adds the packages and their full graph of imported packages.
+// It also adds the modules of the added packages. It will ignore packages
+// that have duplicate paths to ones the graph already holds.
 func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	for _, pkg := range pkgs {
 		if _, found := g.packages[pkg.PkgPath]; found {
@@ -76,6 +153,9 @@ func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	}
 }
 
+// fixupPackage adds the module of pkg, if any, to the set
+// of all modules in g. If packages is not assigned a module
+// (likely stdlib package), a module set for pkg.
 func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 	if pkg.Module != nil {
 		g.AddModules(pkg.Module)
@@ -89,7 +169,7 @@ func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 // not find anything, it returns the "unknown" module.
 func (g *PackageGraph) findModule(pkgPath string) *packages.Module {
 	//TODO: better stdlib test
-	if !strings.Contains(pkgPath, ".") {
+	if IsStdPackage(pkgPath) {
 		return g.GetModule(internal.GoStdModulePath)
 	}
 	for _, m := range g.modules {
@@ -116,22 +196,16 @@ func (g *PackageGraph) GetPackage(path string) *packages.Package {
 
 // LoadPackages loads the packages specified by the patterns into the graph.
 // See golang.org/x/tools/go/packages.Load for details of how it works.
-func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, patterns []string) ([]*packages.Package, error) {
+func (g *PackageGraph) LoadPackagesAndMods(cfg *packages.Config, tags []string, patterns []string, wantSymbols bool) error {
 	if len(tags) > 0 {
 		cfg.BuildFlags = []string{fmt.Sprintf("-tags=%s", strings.Join(tags, ","))}
 	}
-	cfg.Mode |=
-		packages.NeedDeps |
-			packages.NeedImports |
-			packages.NeedModule |
-			packages.NeedSyntax |
-			packages.NeedTypes |
-			packages.NeedTypesInfo |
-			packages.NeedName
+
+	addLoadMode(cfg, wantSymbols)
 
 	pkgs, err := packages.Load(cfg, patterns...)
 	if err != nil {
-		return nil, err
+		return err
 	}
 	var perrs []packages.Error
 	packages.Visit(pkgs, nil, func(p *packages.Package) {
@@ -140,8 +214,27 @@ func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, pattern
 	if len(perrs) > 0 {
 		err = &packageError{perrs}
 	}
+
+	// Add all packages, top-level ones and their imports.
+	// This will also add their respective modules.
 	g.AddPackages(pkgs...)
-	return pkgs, err
+
+	// save top-level packages
+	for _, p := range pkgs {
+		g.topPkgs = append(g.topPkgs, g.GetPackage(p.PkgPath))
+	}
+	return err
+}
+
+func addLoadMode(cfg *packages.Config, wantSymbols bool) {
+	cfg.Mode |=
+		packages.NeedModule |
+			packages.NeedName |
+			packages.NeedDeps |
+			packages.NeedImports
+	if wantSymbols {
+		cfg.Mode |= packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo
+	}
 }
 
 // packageError contains errors from loading a set of packages.
@@ -159,3 +252,67 @@ func (e *packageError) Error() string {
 	fmt.Fprintln(&b, "\nFor details on package patterns, see https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.")
 	return b.String()
 }
+
+func (g *PackageGraph) SBOM() *govulncheck.SBOM {
+	getMod := func(mod *packages.Module) *govulncheck.Module {
+		if mod.Replace != nil {
+			return &govulncheck.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+
+		return &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+	}
+
+	var roots []string
+	rootMods := make(map[string]*govulncheck.Module)
+	for _, pkg := range g.TopPkgs() {
+		roots = append(roots, pkg.PkgPath)
+		mod := getMod(pkg.Module)
+		rootMods[mod.Path] = mod
+	}
+
+	// Govulncheck attempts to put the modules that correspond to the matched package patterns (i.e. the root modules)
+	// at the beginning of the SBOM.Modules message.
+	// Note: This does not guarantee that the first element is the root module.
+	var topMods, depMods []*govulncheck.Module
+	var goVersion string
+	for _, mod := range g.Modules() {
+		mod := getMod(mod)
+
+		if mod.Path == internal.GoStdModulePath {
+			goVersion = semver.SemverToGoTag(mod.Version)
+		}
+
+		// if the mod is not associated with a root package, add it to depMods
+		if rootMods[mod.Path] == nil {
+			depMods = append(depMods, mod)
+		}
+	}
+
+	for _, mod := range rootMods {
+		topMods = append(topMods, mod)
+	}
+	// Sort for deterministic output
+	sortMods(topMods)
+	sortMods(depMods)
+
+	mods := append(topMods, depMods...)
+
+	return &govulncheck.SBOM{
+		GoVersion: goVersion,
+		Modules:   mods,
+		Roots:     roots,
+	}
+}
+
+// Sorts modules alphabetically by path.
+func sortMods(mods []*govulncheck.Module) {
+	slices.SortFunc(mods, func(a, b *govulncheck.Module) int {
+		return strings.Compare(a.Path, b.Path)
+	})
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
index 71fffc41..0bfa1603 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
@@ -44,12 +44,3 @@ func forwardSlice(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.
 	}
 	return seen
 }
-
-// pruneSet removes functions in `set` that are in `toPrune`.
-func pruneSet(set, toPrune map[*ssa.Function]bool) {
-	for f := range set {
-		if !toPrune[f] {
-			delete(set, f)
-		}
-	}
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
index 2119c70d..348c3b96 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
@@ -6,8 +6,6 @@ package vulncheck
 
 import (
 	"context"
-	"fmt"
-	"go/token"
 	"sync"
 
 	"golang.org/x/tools/go/callgraph"
@@ -18,32 +16,24 @@ import (
 	"golang.org/x/vuln/internal/osv"
 )
 
-// Source detects vulnerabilities in packages. The result will contain:
-//
-// 1) An ImportGraph related to an import of a package with some known
-// vulnerabilities.
-//
-// 2) A RequireGraph related to a require of a module with a package that has
-// some known vulnerabilities.
-//
-// 3) A CallGraph leading to the use of a known vulnerable function or method.
-func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (_ *Result, err error) {
-	// buildSSA builds a whole program that assumes all packages use the same FileSet.
-	// Check all packages in pkgs are using the same FileSet.
-	// TODO(https://go.dev/issue/59729): take FileSet out of Package and
-	// let Source take a single FileSet. That will make the enforcement
-	// clearer from the API level.
-	var fset *token.FileSet
-	for _, p := range pkgs {
-		if fset == nil {
-			fset = p.Fset
-		} else {
-			if fset != p.Fset {
-				return nil, fmt.Errorf("[]*Package must have created with the same FileSet")
-			}
-		}
+// Source detects vulnerabilities in pkgs and emits the findings to handler.
+func Source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) error {
+	vr, err := source(ctx, handler, cfg, client, graph)
+	if err != nil {
+		return err
+	}
+
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, sourceCallstacks(vr))
 	}
+	return nil
+}
 
+// source detects vulnerabilities in packages. It emits findings to handler
+// and produces a Result that contains info on detected vulnerabilities.
+//
+// Assumes that pkgs are non-empty and belong to the same program.
+func source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (*Result, error) {
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
@@ -57,118 +47,109 @@ func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Conf
 		buildErr error
 	)
 	if cfg.ScanLevel.WantSymbols() {
+		fset := graph.TopPkgs()[0].Fset
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			prog, ssaPkgs := buildSSA(pkgs, fset)
+			prog, ssaPkgs := buildSSA(graph.TopPkgs(), fset)
 			entries = entryPoints(ssaPkgs)
 			cg, buildErr = callGraph(ctx, prog, entries)
 		}()
 	}
 
-	mods := extractModules(pkgs)
-	mv, err := FetchVulnerabilities(ctx, client, mods)
-	if err != nil {
+	if err := handler.SBOM(graph.SBOM()); err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
-	modVulns = modVulns.filter("", "")
-	result := &Result{}
 
-	vulnPkgModSlice(pkgs, modVulns, result)
-	// Return result immediately if not in symbol mode or
-	// if there are no vulnerable packages.
-	if !cfg.ScanLevel.WantSymbols() || len(result.EntryPackages) == 0 {
-		return result, nil
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
 	}
 
-	wg.Wait() // wait for build to finish
-	if buildErr != nil {
+	mv, err := FetchVulnerabilities(ctx, client, graph.Modules())
+	if err != nil {
 		return nil, err
 	}
 
-	vulnCallGraphSlice(entries, modVulns, cg, result, graph)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
 
-	return result, nil
-}
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingSrcVulnsMessage}); err != nil {
+		return nil, err
+	}
 
-// vulnPkgModSlice computes the slice of pkgs imports and requires graph
-// leading to imports/requires of vulnerable packages/modules in modVulns
-// and stores the computed slices to result.
-func vulnPkgModSlice(pkgs []*packages.Package, modVulns moduleVulnerabilities, result *Result) {
-	// analyzedPkgs contains information on packages analyzed thus far.
-	// If a package is mapped to false, this means it has been visited
-	// but it does not lead to a vulnerable imports. Otherwise, a
-	// visited package is mapped to true.
-	analyzedPkgs := make(map[*packages.Package]bool)
-	for _, pkg := range pkgs {
-		// Top level packages that lead to vulnerable imports are
-		// stored as result.EntryPackages graph entry points.
-		if vulnerable := vulnImportSlice(pkg, modVulns, result, analyzedPkgs); vulnerable {
-			result.EntryPackages = append(result.EntryPackages, pkg)
-		}
+	affVulns := affectingVulnerabilities(mv, "", "")
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
-}
 
-// vulnImportSlice checks if pkg has some vulnerabilities or transitively imports
-// a package with known vulnerabilities. If that is the case, populates result.Imports
-// graph with this reachability information and returns the result.Imports package
-// node for pkg. Otherwise, returns nil.
-func vulnImportSlice(pkg *packages.Package, modVulns moduleVulnerabilities, result *Result, analyzed map[*packages.Package]bool) bool {
-	if vulnerable, ok := analyzed[pkg]; ok {
-		return vulnerable
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
 	}
-	analyzed[pkg] = false
-	// Recursively compute which direct dependencies lead to an import of
-	// a vulnerable package and remember the nodes of such dependencies.
-	transitiveVulnerable := false
-	for _, imp := range pkg.Imports {
-		if impVulnerable := vulnImportSlice(imp, modVulns, result, analyzed); impVulnerable {
-			transitiveVulnerable = true
-		}
+
+	impVulns := importedVulnPackages(affVulns, graph)
+	// Emit information on imported vulnerable packages now as
+	// call graph computation might take a while.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
 	}
 
-	// Check if pkg has known vulnerabilities.
-	vulns := modVulns.vulnsForPackage(pkg.PkgPath)
+	// Return result immediately if not in symbol mode or
+	// if there are no vulnerabilities imported.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
 
-	// If pkg is not vulnerable nor it transitively leads
-	// to vulnerabilities, jump out.
-	if !transitiveVulnerable && len(vulns) == 0 {
-		return false
+	wg.Wait() // wait for build to finish
+	if buildErr != nil {
+		return nil, err
 	}
 
-	// Create Vuln entry for each symbol of known OSV entries for pkg.
-	for _, osv := range vulns {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg.PkgPath {
-					continue
-				}
-
-				symbols := p.Symbols
-				if len(symbols) == 0 {
-					symbols = allSymbols(pkg.Types)
-				}
-
-				for _, symbol := range symbols {
-					vuln := &Vuln{
-						OSV:        osv,
-						Symbol:     symbol,
-						ImportSink: pkg,
-					}
-					result.Vulns = append(result.Vulns, vuln)
-				}
+	entryFuncs, callVulns := calledVulnSymbols(entries, affVulns, cg, graph)
+	return &Result{EntryFunctions: entryFuncs, Vulns: callVulns}, nil
+}
+
+// importedVulnPackages detects imported vulnerable packages.
+func importedVulnPackages(affVulns affectingVulns, graph *PackageGraph) []*Vuln {
+	var vulns []*Vuln
+	analyzed := make(map[*packages.Package]bool) // skip analyzing the same package multiple times
+	var vulnImports func(pkg *packages.Package)
+	vulnImports = func(pkg *packages.Package) {
+		if analyzed[pkg] {
+			return
+		}
+
+		osvs := affVulns.ForPackage(pkgModPath(pkg), pkg.PkgPath)
+		// Create Vuln entry for each OSV entry for pkg.
+		for _, osv := range osvs {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg.PkgPath),
 			}
+			vulns = append(vulns, vuln)
+		}
+
+		analyzed[pkg] = true
+		for _, imp := range pkg.Imports {
+			vulnImports(imp)
 		}
 	}
-	analyzed[pkg] = true
-	return true
+
+	for _, pkg := range graph.TopPkgs() {
+		vulnImports(pkg)
+	}
+	return vulns
 }
 
-// vulnCallGraphSlice checks if known vulnerabilities are transitively reachable from sources
-// via call graph cg. If so, populates result.Calls graph with this reachability information.
-func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result, graph *PackageGraph) {
-	sinksWithVulns := vulnFuncs(cg, modVulns)
+// calledVulnSymbols detects vuln symbols transitively reachable from sources
+// via call graph cg.
+//
+// A slice of call graph is computed related to the reachable vulnerabilities. Each
+// reachable Vuln has attached FuncNode that can be upward traversed to the entry points.
+// Entry points that reach the vulnerable symbols are also returned.
+func calledVulnSymbols(sources []*ssa.Function, affVulns affectingVulns, cg *callgraph.Graph, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	sinksWithVulns := vulnFuncs(cg, affVulns, graph)
 
 	// Compute call graph backwards reachable
 	// from vulnerable functions and methods.
@@ -197,8 +178,8 @@ func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities,
 	}
 
 	// Transform the resulting call graph slice into
-	// vulncheck representation and store it to result.
-	vulnCallGraph(filteredSources, filteredSinks, result, graph)
+	// vulncheck representation.
+	return vulnCallGraph(filteredSources, filteredSinks, graph)
 }
 
 // callGraphSlice computes a slice of callgraph beginning at starts
@@ -240,25 +221,25 @@ func callGraphSlice(starts []*callgraph.Node, forward bool) *callgraph.Graph {
 	return g
 }
 
-// vulnCallGraph creates vulnerability call graph from sources -> sinks reachability info.
-func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, result *Result, graph *PackageGraph) {
+// vulnCallGraph creates vulnerability call graph in terms of sources and sinks.
+func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	var entries []*FuncNode
+	var vulns []*Vuln
 	nodes := make(map[*ssa.Function]*FuncNode)
 
 	// First create entries and sinks and store relevant information.
 	for _, s := range sources {
 		fn := createNode(nodes, s.Func, graph)
-		result.EntryFunctions = append(result.EntryFunctions, fn)
+		entries = append(entries, fn)
 	}
 
-	for s, vulns := range sinks {
+	for s, osvs := range sinks {
 		f := s.Func
 		funNode := createNode(nodes, s.Func, graph)
 
 		// Populate CallSink field for each detected vuln symbol.
-		for _, osv := range vulns {
-			if vulnMatchesPackage(osv, funNode.Package.PkgPath) {
-				addCallSinkForVuln(funNode, osv, dbFuncName(f), funNode.Package.PkgPath, result)
-			}
+		for _, osv := range osvs {
+			vulns = append(vulns, calledVuln(funNode, osv, dbFuncName(f), funNode.Package))
 		}
 	}
 
@@ -291,13 +272,15 @@ func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.E
 	for s := range sinks {
 		visit(s)
 	}
+	return entries, vulns
 }
 
 // vulnFuncs returns vulnerability information for vulnerable functions in cg.
-func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgraph.Node][]*osv.Entry {
+func vulnFuncs(cg *callgraph.Graph, affVulns affectingVulns, graph *PackageGraph) map[*callgraph.Node][]*osv.Entry {
 	m := make(map[*callgraph.Node][]*osv.Entry)
 	for f, n := range cg.Nodes {
-		vulns := modVulns.vulnsForSymbol(pkgPath(f), dbFuncName(f))
+		p := pkgPath(f)
+		vulns := affVulns.ForSymbol(pkgModPath(graph.GetPackage(p)), p, dbFuncName(f))
 		if len(vulns) > 0 {
 			m[n] = vulns
 		}
@@ -305,15 +288,6 @@ func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgra
 	return m
 }
 
-// pkgPath returns the path of the f's enclosing package, if any.
-// Otherwise, returns "".
-func pkgPath(f *ssa.Function) string {
-	if f.Package() != nil && f.Package().Pkg != nil {
-		return f.Package().Pkg.Path()
-	}
-	return ""
-}
-
 func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *PackageGraph) *FuncNode {
 	if fn, ok := nodes[f]; ok {
 		return fn
@@ -328,46 +302,11 @@ func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *Packa
 	return fn
 }
 
-// addCallSinkForVuln adds callID as call sink to vuln of result.Vulns
-// identified with .
-func addCallSinkForVuln(call *FuncNode, osv *osv.Entry, symbol, pkg string, result *Result) {
-	for _, vuln := range result.Vulns {
-		if vuln.OSV == osv && vuln.Symbol == symbol && vuln.ImportSink.PkgPath == pkg {
-			vuln.CallSink = call
-			return
-		}
-	}
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*packages.Package) []*packages.Module {
-	modMap := map[string]*packages.Module{}
-	seen := map[*packages.Package]bool{}
-	var extract func(*packages.Package, map[string]*packages.Module)
-	extract = func(pkg *packages.Package, modMap map[string]*packages.Module) {
-		if pkg == nil || seen[pkg] {
-			return
-		}
-		if pkg.Module != nil {
-			if pkg.Module.Replace != nil {
-				modMap[pkg.Module.Replace.Path] = pkg.Module
-			} else {
-				modMap[pkg.Module.Path] = pkg.Module
-			}
-		}
-		seen[pkg] = true
-		for _, imp := range pkg.Imports {
-			extract(imp, modMap)
-		}
-	}
-	for _, pkg := range pkgs {
-		extract(pkg, modMap)
-	}
-
-	modules := []*packages.Module{}
-	for _, mod := range modMap {
-		modules = append(modules, mod)
+func calledVuln(call *FuncNode, osv *osv.Entry, symbol string, pkg *packages.Package) *Vuln {
+	return &Vuln{
+		Symbol:   symbol,
+		Package:  pkg,
+		OSV:      osv,
+		CallSink: call,
 	}
-	return modules
 }
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
index 4fa9c69a..e752f4a0 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
@@ -9,15 +9,17 @@ import (
 	"context"
 	"go/token"
 	"go/types"
+	"sort"
 	"strings"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/callgraph/cha"
 	"golang.org/x/tools/go/callgraph/vta"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa/ssautil"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/semver"
 
 	"golang.org/x/tools/go/ssa"
 )
@@ -26,7 +28,6 @@ import (
 // the ssa program encapsulating the packages and top level
 // ssa packages corresponding to pkgs.
 func buildSSA(pkgs []*packages.Package, fset *token.FileSet) (*ssa.Program, []*ssa.Package) {
-	// TODO(https://go.dev/issue/57221): what about entry functions that are generics?
 	prog := ssa.NewProgram(fset, ssa.InstantiateGenerics)
 
 	imports := make(map[*packages.Package]*ssa.Package)
@@ -69,12 +70,8 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 		return nil, err
 	}
 	initial := cha.CallGraph(prog)
-	allFuncs := ssautil.AllFunctions(prog)
 
 	fslice := forwardSlice(entrySlice, initial)
-	// Keep only actually linked functions.
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -83,8 +80,6 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 	// Repeat the process once more, this time using
 	// the produced VTA call graph as the base graph.
 	fslice = forwardSlice(entrySlice, vtaCg)
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -110,15 +105,17 @@ func dbTypeFormat(t types.Type) string {
 
 // dbFuncName computes a function name consistent with the namings used in vulnerability
 // databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
+// If a receiver is a pointer, this information is not encoded in the resulting name. If
+// a function has type argument/parameter, this information is omitted. The name of
+// anonymous functions is simply "". The function names are unique subject to the enclosing
+// package, but not globally.
 //
 // Examples:
 //
 //	func (a A) foo (...) {...}  -> A.foo
 //	func foo(...) {...}         -> foo
 //	func (b *B) bar (...) {...} -> B.bar
+//	func (c C[T]) do(...) {...} -> C.do
 func dbFuncName(f *ssa.Function) string {
 	selectBound := func(f *ssa.Function) types.Type {
 		// If f is a "bound" function introduced by ssa for a given type, return the type.
@@ -151,18 +148,17 @@ func dbFuncName(f *ssa.Function) string {
 	}
 
 	if qprefix == "" {
-		return f.Name()
+		return funcName(f)
 	}
-	return qprefix + "." + f.Name()
+	return qprefix + "." + funcName(f)
 }
 
-// dbTypesFuncName is dbFuncName defined over *types.Func.
-func dbTypesFuncName(f *types.Func) string {
-	sig := f.Type().(*types.Signature)
-	if sig.Recv() == nil {
-		return f.Name()
-	}
-	return dbTypeFormat(sig.Recv().Type()) + "." + f.Name()
+// funcName returns the name of the ssa function f.
+// It is f.Name() without additional type argument
+// information in case of generics.
+func funcName(f *ssa.Function) string {
+	n, _, _ := strings.Cut(f.Name(), "[")
+	return n
 }
 
 // memberFuncs returns functions associated with the `member`:
@@ -227,35 +223,124 @@ func funcRecvType(f *ssa.Function) string {
 	return buf.String()
 }
 
-// allSymbols returns all top-level functions and methods defined in pkg.
-func allSymbols(pkg *types.Package) []string {
-	var names []string
-	scope := pkg.Scope()
-	for _, name := range scope.Names() {
-		o := scope.Lookup(name)
-		switch o := o.(type) {
-		case *types.Func:
-			names = append(names, dbTypesFuncName(o))
-		case *types.TypeName:
-			ms := types.NewMethodSet(types.NewPointer(o.Type()))
-			for i := 0; i < ms.Len(); i++ {
-				if f, ok := ms.At(i).Obj().(*types.Func); ok {
-					names = append(names, dbTypesFuncName(f))
+func FixedVersion(modulePath, version string, affected []osv.Affected) string {
+	fixed := earliestValidFix(modulePath, version, affected)
+	// Add "v" prefix if one does not exist. moduleVersionString
+	// will later on replace it with "go" if needed.
+	if fixed != "" && !strings.HasPrefix(fixed, "v") {
+		fixed = "v" + fixed
+	}
+	return fixed
+}
+
+// earliestValidFix returns the earliest fix for version of modulePath that
+// itself is not vulnerable in affected.
+//
+// Suppose we have a version "v1.0.0" and we use {...} to denote different
+// affected regions. Assume for simplicity that all affected apply to the
+// same input modulePath.
+//
+//	{[v0.1.0, v0.1.9), [v1.0.0, v2.0.0)} -> v2.0.0
+//	{[v1.0.0, v1.5.0), [v2.0.0, v2.1.0}, {[v1.4.0, v1.6.0)} -> v2.1.0
+func earliestValidFix(modulePath, version string, affected []osv.Affected) string {
+	var moduleAffected []osv.Affected
+	for _, a := range affected {
+		if a.Module.Path == modulePath {
+			moduleAffected = append(moduleAffected, a)
+		}
+	}
+
+	vFixes := validFixes(version, moduleAffected)
+	for _, fix := range vFixes {
+		if !fixNegated(fix, moduleAffected) {
+			return fix
+		}
+	}
+	return ""
+
+}
+
+// validFixes computes all fixes for version in affected and
+// returns them sorted increasingly. Assumes that all affected
+// apply to the same module.
+func validFixes(version string, affected []osv.Affected) []string {
+	var fixes []string
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if r.Type != osv.RangeTypeSemver {
+				continue
+			}
+			for _, e := range r.Events {
+				fix := e.Fixed
+				if fix != "" && semver.Less(version, fix) {
+					fixes = append(fixes, fix)
 				}
 			}
 		}
 	}
-	return names
+	sort.SliceStable(fixes, func(i, j int) bool { return semver.Less(fixes[i], fixes[j]) })
+	return fixes
 }
 
-// vulnMatchesPackage reports whether an entry applies to pkg (an import path).
-func vulnMatchesPackage(v *osv.Entry, pkg string) bool {
-	for _, a := range v.Affected {
-		for _, p := range a.EcosystemSpecific.Packages {
-			if p.Path == pkg {
+// fixNegated checks if fix is negated to by a re-introduction
+// of a vulnerability in affected. Assumes that all affected apply
+// to the same module.
+func fixNegated(fix string, affected []osv.Affected) bool {
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if semver.ContainsSemver(r, fix) {
 				return true
 			}
 		}
 	}
 	return false
 }
+
+func modPath(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Path
+	}
+	return mod.Path
+}
+
+func modVersion(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Version
+	}
+	return mod.Version
+}
+
+// pkgPath returns the path of the f's enclosing package, if any.
+// Otherwise, returns internal.UnknownPackagePath.
+func pkgPath(f *ssa.Function) string {
+	g := f
+	if f.Origin() != nil {
+		// Instantiations of generics do not have
+		// an associated package. We hence look up
+		// the original function for the package.
+		g = f.Origin()
+	}
+	if g.Package() != nil && g.Package().Pkg != nil {
+		return g.Package().Pkg.Path()
+	}
+	return internal.UnknownPackagePath
+}
+
+func pkgModPath(pkg *packages.Package) string {
+	if pkg != nil && pkg.Module != nil {
+		return pkg.Module.Path
+	}
+	return internal.UnknownModulePath
+}
+
+func IsStdPackage(pkg string) bool {
+	if pkg == "" || pkg == internal.UnknownPackagePath {
+		return false
+	}
+	// std packages do not have a "." in their path. For instance, see
+	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
+	if i := strings.IndexByte(pkg, '/'); i != -1 {
+		pkg = pkg[:i]
+	}
+	return !strings.Contains(pkg, ".")
+}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
index 7786695c..198fffe0 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
@@ -16,31 +16,31 @@ import (
 	"golang.org/x/vuln/internal/semver"
 )
 
-// Result contains information on how known vulnerabilities are reachable
-// in the call graph, package imports graph, and module requires graph of
-// the user code.
+const (
+	fetchingVulnsMessage    = "Fetching vulnerabilities from the database..."
+	checkingSrcVulnsMessage = "Checking the code against the vulnerabilities..."
+	checkingBinVulnsMessage = "Checking the binary against the vulnerabilities..."
+)
+
+// Result contains information on detected vulnerabilities.
+// For call graph analysis, it provides information on reachability
+// of vulnerable symbols through entry points of the program.
 type Result struct {
 	// EntryFunctions are a subset of Functions representing vulncheck entry points.
 	EntryFunctions []*FuncNode
 
-	// EntryPackages are a subset of Packages representing packages of vulncheck entry points.
-	EntryPackages []*packages.Package
-
-	// Vulns contains information on detected vulnerabilities and their place in
-	// the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
-	// or whose packages are imported in Imports, or whose modules are required in
-	// Requires, have an entry in Vulns.
+	// Vulns contains information on detected vulnerabilities.
 	Vulns []*Vuln
 }
 
-// Vuln provides information on how a vulnerability is affecting user code by
-// connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities
-// detected in Go binaries do not appear in the Result graphs.
+// Vuln provides information on a detected vulnerability. For call
+// graph mode, Vuln will also contain the information on how the
+// vulnerability is reachable in the user call graph.
 type Vuln struct {
 	// OSV contains information on the detected vulnerability in the shared
 	// vulnerability format.
 	//
-	// OSV, Symbol, PkgPath, and ModPath identify a vulnerability.
+	// OSV, Symbol, and Package identify a vulnerability.
 	//
 	// Note that *osv.Entry may describe multiple symbols from multiple
 	// packages.
@@ -49,17 +49,17 @@ type Vuln struct {
 	// Symbol is the name of the detected vulnerable function or method.
 	Symbol string
 
-	// CallSink is the FuncNode in Result.Calls corresponding to Symbol.
+	// CallSink is the FuncNode corresponding to Symbol.
 	//
 	// When analyzing binaries, Symbol is not reachable, or cfg.ScanLevel
-	// is symbol, CallSink will be unavailable and set to 0.
+	// is symbol, CallSink will be unavailable and set to nil.
 	CallSink *FuncNode
 
-	// ImportSink is the PkgNode in Result.Imports corresponding to PkgPath.
+	// Package of Symbol.
 	//
-	// When analyzing binaries or PkgPath is not imported, ImportSink will be
-	// unavailable and set to 0.
-	ImportSink *packages.Package
+	// When the package of symbol is not imported, Package will be
+	// unavailable and set to nil.
+	Package *packages.Package
 }
 
 // A FuncNode describes a function in the call graph.
@@ -111,10 +111,10 @@ type CallSite struct {
 	Resolved bool
 }
 
-// moduleVulnerabilities is an internal structure for
-// holding and querying vulnerabilities provided by a
-// vulnerability database client.
-type moduleVulnerabilities []*ModVulns
+// affectingVulns is an internal structure for querying
+// vulnerabilities that apply to the current program
+// and platform under consideration.
+type affectingVulns []*ModVulns
 
 // ModVulns groups vulnerabilities per module.
 type ModVulns struct {
@@ -122,10 +122,10 @@ type ModVulns struct {
 	Vulns  []*osv.Entry
 }
 
-func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
+func affectingVulnerabilities(vulns []*ModVulns, os, arch string) affectingVulns {
 	now := time.Now()
-	var filteredMod moduleVulnerabilities
-	for _, mod := range mv {
+	var filtered affectingVulns
+	for _, mod := range vulns {
 		module := mod.Module
 		modVersion := module.Version
 		if module.Replace != nil {
@@ -150,24 +150,20 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 				if a.Module.Path != module.Path {
 					continue
 				}
-
-				// A module version is affected if
-				//  - it is included in one of the affected version ranges
-				//  - and module version is not ""
-				if modVersion == "" {
-					// Module version of "" means the module version is not available,
-					// and so we don't want to spam users with potential false alarms.
-					continue
-				}
-				if !semver.Affects(a.Ranges, modVersion) {
+				if !affected(modVersion, a) {
 					continue
 				}
+
 				var filteredImports []osv.Package
 				for _, p := range a.EcosystemSpecific.Packages {
 					if matchesPlatform(os, arch, p) {
 						filteredImports = append(filteredImports, p)
 					}
 				}
+				// If we pruned all existing Packages, then the affected is
+				// empty and we can filter it out. Note that Packages can
+				// be empty for vulnerabilities that have no package or
+				// symbol information available.
 				if len(a.EcosystemSpecific.Packages) != 0 && len(filteredImports) == 0 {
 					continue
 				}
@@ -183,12 +179,28 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 			newV.Affected = filteredAffected
 			filteredVulns = append(filteredVulns, &newV)
 		}
-		filteredMod = append(filteredMod, &ModVulns{
+
+		filtered = append(filtered, &ModVulns{
 			Module: module,
 			Vulns:  filteredVulns,
 		})
 	}
-	return filteredMod
+	return filtered
+}
+
+// affected checks if modVersion is affected by a:
+//   - it is included in one of the affected version ranges
+//   - and module version is not "" and "(devel)"
+func affected(modVersion string, a osv.Affected) bool {
+	const devel = "(devel)"
+	if modVersion == "" || modVersion == devel {
+		// Module version of "" means the module version is not available
+		// and devel means it is in development stage. Either way, we don't
+		// know the exact version so we don't want to spam users with
+		// potential false alarms.
+		return false
+	}
+	return semver.Affects(a.Ranges, modVersion)
 }
 
 func matchesPlatform(os, arch string, e osv.Package) bool {
@@ -211,37 +223,66 @@ func matchesPlatformComponent(s string, ps []string) bool {
 	return false
 }
 
-// vulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv moduleVulnerabilities) vulnsForPackage(importPath string) []*osv.Entry {
-	isStd := isStdPackage(importPath)
-	var mostSpecificMod *ModVulns
-	for _, mod := range mv {
+// moduleVulns return vulnerabilities for module. If module is unknown,
+// it figures the module from package importPath. It returns the module
+// whose path is the longest prefix of importPath.
+func (aff affectingVulns) moduleVulns(module, importPath string) *ModVulns {
+	moduleKnown := module != "" && module != internal.UnknownModulePath
+
+	isStd := IsStdPackage(importPath)
+	var mostSpecificMod *ModVulns // for the case where !moduleKnown
+	for _, mod := range aff {
 		md := mod
 		if isStd && mod.Module.Path == internal.GoStdModulePath {
-			// standard library packages do not have an associated module,
+			// Standard library packages do not have an associated module,
 			// so we relate them to the artificial stdlib module.
-			mostSpecificMod = md
+			return md
+		}
+
+		if moduleKnown {
+			if mod.Module.Path == module {
+				// If we know exactly which module we need,
+				// return its vulnerabilities.
+				return md
+			}
 		} else if strings.HasPrefix(importPath, md.Module.Path) {
+			// If module is unknown, we try to figure it out from importPath.
+			// We take the module whose path has the longest match to importPath.
+			// TODO: do matching based on path components.
 			if mostSpecificMod == nil || len(mostSpecificMod.Module.Path) < len(md.Module.Path) {
 				mostSpecificMod = md
 			}
 		}
 	}
-	if mostSpecificMod == nil {
+	return mostSpecificMod
+}
+
+// ForPackage returns the vulnerabilities for the importPath belonging to
+// module.
+//
+// If module is unknown, ForPackage will resolve it as the most specific
+// prefix of importPath.
+func (aff affectingVulns) ForPackage(module, importPath string) []*osv.Entry {
+	mod := aff.moduleVulns(module, importPath)
+	if mod == nil {
 		return nil
 	}
 
-	if mostSpecificMod.Module.Replace != nil {
+	if mod.Module.Replace != nil {
 		// standard libraries do not have a module nor replace module
-		importPath = fmt.Sprintf("%s%s", mostSpecificMod.Module.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.Module.Path))
+		importPath = fmt.Sprintf("%s%s", mod.Module.Replace.Path, strings.TrimPrefix(importPath, mod.Module.Path))
 	}
-	vulns := mostSpecificMod.Vulns
+	vulns := mod.Vulns
 	packageVulns := []*osv.Entry{}
 Vuln:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all packages are vulnerable
+				packageVulns = append(packageVulns, v)
+				continue Vuln
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path == importPath {
 					packageVulns = append(packageVulns, v)
@@ -253,9 +294,9 @@ Vuln:
 	return packageVulns
 }
 
-// vulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv.Entry {
-	vulns := mv.vulnsForPackage(importPath)
+// ForSymbol returns vulnerabilities for symbol in aff.ForPackage(module, importPath).
+func (aff affectingVulns) ForSymbol(module, importPath, symbol string) []*osv.Entry {
+	vulns := aff.ForPackage(module, importPath)
 	if vulns == nil {
 		return nil
 	}
@@ -264,6 +305,12 @@ func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv
 vulnLoop:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all symbols of all packages are vulnerable
+				symbolVulns = append(symbolVulns, v)
+				continue vulnLoop
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path != importPath {
 					continue
@@ -287,15 +334,3 @@ func contains(symbols []string, target string) bool {
 	}
 	return false
 }
-
-func isStdPackage(pkg string) bool {
-	if pkg == "" {
-		return false
-	}
-	// std packages do not have a "." in their path. For instance, see
-	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
-	if i := strings.IndexByte(pkg, '/'); i != -1 {
-		pkg = pkg[:i]
-	}
-	return !strings.Contains(pkg, ".")
-}
diff --git a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
index 7de37587..7bc18581 100644
--- a/history-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
+++ b/history-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
@@ -13,6 +13,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"unicode"
 
 	"golang.org/x/tools/go/packages"
 )
@@ -32,18 +33,18 @@ type StackEntry struct {
 	Call *CallSite
 }
 
-// CallStacks returns representative call stacks for each
+// sourceCallstacks returns representative call stacks for each
 // vulnerability in res. The returned call stacks are heuristically
 // ordered by how seemingly easy is to understand them: shorter
 // call stacks with less dynamic call sites appear earlier in the
 // returned slices.
 //
-// CallStacks performs a breadth-first search of res.CallGraph starting
-// at the vulnerable symbol and going up until reaching an entry
+// sourceCallstacks performs a breadth-first search of res.CallGraph
+// starting at the vulnerable symbol and going up until reaching an entry
 // function or method in res.CallGraph.Entries. During this search,
 // each function is visited at most once to avoid potential
 // exponential explosion. Hence, not all call stacks are analyzed.
-func CallStacks(res *Result) map[*Vuln]CallStack {
+func sourceCallstacks(res *Result) map[*Vuln]CallStack {
 	var (
 		wg sync.WaitGroup
 		mu sync.Mutex
@@ -53,7 +54,7 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 		vuln := vuln
 		wg.Add(1)
 		go func() {
-			cs := callStack(vuln, res)
+			cs := sourceCallstack(vuln, res)
 			mu.Lock()
 			stackPerVuln[vuln] = cs
 			mu.Unlock()
@@ -66,10 +67,10 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 	return stackPerVuln
 }
 
-// callStack finds a representative call stack for vuln.
+// sourceCallstack finds a representative call stack for vuln.
 // This is a shortest unique call stack with the least
 // number of dynamic call sites.
-func callStack(vuln *Vuln, res *Result) CallStack {
+func sourceCallstack(vuln *Vuln, res *Result) CallStack {
 	vulnSink := vuln.CallSink
 	if vulnSink == nil {
 		return nil
@@ -100,7 +101,7 @@ func callStack(vuln *Vuln, res *Result) CallStack {
 	skipSymbols := make(map[*FuncNode]bool)
 	for _, v := range res.Vulns {
 		if v.CallSink != nil && v != vuln &&
-			v.OSV == vuln.OSV && v.ImportSink == vuln.ImportSink {
+			v.OSV == vuln.OSV && v.Package == vuln.Package {
 			skipSymbols[v.CallSink] = true
 		}
 	}
@@ -390,3 +391,59 @@ func isInit(f *FuncNode) bool {
 	// positive integer. Implicit inits are named simply "init".
 	return f.Name == "init" || strings.HasPrefix(f.Name, "init#")
 }
+
+// binaryCallstacks computes representative call stacks for binary results.
+func binaryCallstacks(vr *Result) map[*Vuln]CallStack {
+	callstacks := map[*Vuln]CallStack{}
+	for _, vv := range uniqueVulns(vr.Vulns) {
+		f := &FuncNode{Package: vv.Package, Name: vv.Symbol}
+		parts := strings.Split(vv.Symbol, ".")
+		if len(parts) != 1 {
+			f.RecvType = parts[0]
+			f.Name = parts[1]
+		}
+		callstacks[vv] = CallStack{StackEntry{Function: f}}
+	}
+	return callstacks
+}
+
+// uniqueVulns does for binary mode what sourceCallstacks does for source mode.
+// It tries not to report redundant symbols. Since there are no call stacks in
+// binary mode, the following approximate approach is used. Do not report unexported
+// symbols for a  triple if there are some exported symbols.
+// Otherwise, report all unexported symbols to avoid not reporting anything.
+func uniqueVulns(vulns []*Vuln) []*Vuln {
+	type key struct {
+		id  string
+		pkg string
+		mod string
+	}
+	hasExported := make(map[key]bool)
+	for _, v := range vulns {
+		if isExported(v.Symbol) {
+			k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+			hasExported[k] = true
+		}
+	}
+
+	var uniques []*Vuln
+	for _, v := range vulns {
+		k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+		if isExported(v.Symbol) || !hasExported[k] {
+			uniques = append(uniques, v)
+		}
+	}
+	return uniques
+}
+
+// isExported checks if the symbol is exported. Assumes that the
+// symbol is of the form "identifier", "identifier1.identifier2",
+// or "identifier.".
+func isExported(symbol string) bool {
+	parts := strings.Split(symbol, ".")
+	last := parts[len(parts)-1]
+	if last == "" { // case for "identifier."
+		return false
+	}
+	return unicode.IsUpper(rune(last[0]))
+}
diff --git a/history-api/vendor/golang.org/x/vuln/scan/scan.go b/history-api/vendor/golang.org/x/vuln/scan/scan.go
index 83ed75a9..0aa9975e 100644
--- a/history-api/vendor/golang.org/x/vuln/scan/scan.go
+++ b/history-api/vendor/golang.org/x/vuln/scan/scan.go
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+/*
+Package scan provides functionality for running govulncheck.
+
+See [cmd/govulncheck/main.go] as a usage example.
+
+[cmd/govulncheck/main.go]: https://go.googlesource.com/vuln/+/master/cmd/govulncheck/main.go
+*/
 package scan
 
 import (
diff --git a/history-api/vendor/google.golang.org/grpc/MAINTAINERS.md b/history-api/vendor/google.golang.org/grpc/MAINTAINERS.md
index 5d4096d4..df35bb9a 100644
--- a/history-api/vendor/google.golang.org/grpc/MAINTAINERS.md
+++ b/history-api/vendor/google.golang.org/grpc/MAINTAINERS.md
@@ -9,21 +9,19 @@ for general contribution guidelines.
 
 ## Maintainers (in alphabetical order)
 
-- [aranjans](https://github.com/aranjans), Google LLC
 - [arjan-bal](https://github.com/arjan-bal), Google LLC
 - [arvindbr8](https://github.com/arvindbr8), Google LLC
 - [atollena](https://github.com/atollena), Datadog, Inc.
 - [dfawley](https://github.com/dfawley), Google LLC
 - [easwars](https://github.com/easwars), Google LLC
-- [erm-g](https://github.com/erm-g), Google LLC
 - [gtcooke94](https://github.com/gtcooke94), Google LLC
-- [purnesh42h](https://github.com/purnesh42h), Google LLC
-- [zasweq](https://github.com/zasweq), Google LLC
 
 ## Emeritus Maintainers (in alphabetical order)
 - [adelez](https://github.com/adelez)
+- [aranjans](https://github.com/aranjans)
 - [canguler](https://github.com/canguler)
 - [cesarghali](https://github.com/cesarghali)
+- [erm-g](https://github.com/erm-g)
 - [iamqizhao](https://github.com/iamqizhao)
 - [jeanbza](https://github.com/jeanbza)
 - [jtattermusch](https://github.com/jtattermusch)
@@ -32,5 +30,7 @@ for general contribution guidelines.
 - [matt-kwong](https://github.com/matt-kwong)
 - [menghanl](https://github.com/menghanl)
 - [nicolasnoble](https://github.com/nicolasnoble)
+- [purnesh42h](https://github.com/purnesh42h)
 - [srini100](https://github.com/srini100)
 - [yongni](https://github.com/yongni)
+- [zasweq](https://github.com/zasweq)
diff --git a/history-api/vendor/google.golang.org/grpc/balancer/balancer.go b/history-api/vendor/google.golang.org/grpc/balancer/balancer.go
index c9b343c7..b1264017 100644
--- a/history-api/vendor/google.golang.org/grpc/balancer/balancer.go
+++ b/history-api/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -360,6 +360,10 @@ type Balancer interface {
 	// call SubConn.Shutdown for its existing SubConns; however, this will be
 	// required in a future release, so it is recommended.
 	Close()
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // ExitIdler is an optional interface for balancers to implement.  If
@@ -367,8 +371,8 @@ type Balancer interface {
 // the ClientConn is idle.  If unimplemented, ClientConn.Connect will cause
 // all SubConns to connect.
 //
-// Notice: it will be required for all balancers to implement this in a future
-// release.
+// Deprecated: All balancers must implement this interface. This interface will
+// be removed in a future release.
 type ExitIdler interface {
 	// ExitIdle instructs the LB policy to reconnect to backends / exit the
 	// IDLE state, if appropriate and possible.  Note that SubConns that enter
diff --git a/history-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/history-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
index cc606f4d..360db08e 100644
--- a/history-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
+++ b/history-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
@@ -37,6 +37,8 @@ import (
 	"google.golang.org/grpc/resolver"
 )
 
+var randIntN = rand.IntN
+
 // ChildState is the balancer state of a child along with the endpoint which
 // identifies the child balancer.
 type ChildState struct {
@@ -45,7 +47,15 @@ type ChildState struct {
 
 	// Balancer exposes only the ExitIdler interface of the child LB policy.
 	// Other methods of the child policy are called only by endpointsharding.
-	Balancer balancer.ExitIdler
+	Balancer ExitIdler
+}
+
+// ExitIdler provides access to only the ExitIdle method of the child balancer.
+type ExitIdler interface {
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // Options are the options to configure the behaviour of the
@@ -104,6 +114,21 @@ type endpointSharding struct {
 	mu sync.Mutex
 }
 
+// rotateEndpoints returns a slice of all the input endpoints rotated a random
+// amount.
+func rotateEndpoints(es []resolver.Endpoint) []resolver.Endpoint {
+	les := len(es)
+	if les == 0 {
+		return es
+	}
+	r := randIntN(les)
+	// Make a copy to avoid mutating data beyond the end of es.
+	ret := make([]resolver.Endpoint, les)
+	copy(ret, es[r:])
+	copy(ret[les-r:], es[:r])
+	return ret
+}
+
 // UpdateClientConnState creates a child for new endpoints and deletes children
 // for endpoints that are no longer present. It also updates all the children,
 // and sends a single synchronous update of the childrens' aggregated state at
@@ -125,7 +150,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
 	newChildren := resolver.NewEndpointMap[*balancerWrapper]()
 
 	// Update/Create new children.
-	for _, endpoint := range state.ResolverState.Endpoints {
+	for _, endpoint := range rotateEndpoints(state.ResolverState.Endpoints) {
 		if _, ok := newChildren.Get(endpoint); ok {
 			// Endpoint child was already created, continue to avoid duplicate
 			// update.
@@ -205,6 +230,16 @@ func (es *endpointSharding) Close() {
 	}
 }
 
+func (es *endpointSharding) ExitIdle() {
+	es.childMu.Lock()
+	defer es.childMu.Unlock()
+	for _, bw := range es.children.Load().Values() {
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+	}
+}
+
 // updateState updates this component's state. It sends the aggregated state,
 // and a picker with round robin behavior with all the child states present if
 // needed.
@@ -261,7 +296,7 @@ func (es *endpointSharding) updateState() {
 	p := &pickerWithChildStates{
 		pickers:     pickers,
 		childStates: childStates,
-		next:        uint32(rand.IntN(len(pickers))),
+		next:        uint32(randIntN(len(pickers))),
 	}
 	es.cc.UpdateState(balancer.State{
 		ConnectivityState: aggState,
@@ -326,15 +361,13 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) {
 // ExitIdle pings an IDLE child balancer to exit idle in a new goroutine to
 // avoid deadlocks due to synchronous balancer state updates.
 func (bw *balancerWrapper) ExitIdle() {
-	if ei, ok := bw.child.(balancer.ExitIdler); ok {
-		go func() {
-			bw.es.childMu.Lock()
-			if !bw.isClosed {
-				ei.ExitIdle()
-			}
-			bw.es.childMu.Unlock()
-		}()
-	}
+	go func() {
+		bw.es.childMu.Lock()
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+		bw.es.childMu.Unlock()
+	}()
 }
 
 // updateClientConnStateLocked delivers the ClientConnState to the child
diff --git a/history-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/history-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
index 494314f2..67f315a0 100644
--- a/history-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
+++ b/history-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
@@ -54,18 +54,9 @@ func init() {
 	balancer.Register(pickfirstBuilder{})
 }
 
-type (
-	// enableHealthListenerKeyType is a unique key type used in resolver
-	// attributes to indicate whether the health listener usage is enabled.
-	enableHealthListenerKeyType struct{}
-	// managedByPickfirstKeyType is an attribute key type to inform Outlier
-	// Detection that the generic health listener is being used.
-	// TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when
-	// implementing the dualstack design. This is a hack. Once Dualstack is
-	// completed, outlier detection will stop sending ejection updates through
-	// the connectivity listener.
-	managedByPickfirstKeyType struct{}
-)
+// enableHealthListenerKeyType is a unique key type used in resolver
+// attributes to indicate whether the health listener usage is enabled.
+type enableHealthListenerKeyType struct{}
 
 var (
 	logger = grpclog.Component("pick-first-leaf-lb")
@@ -76,21 +67,21 @@ var (
 	disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.disconnections",
 		Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
-		Unit:        "disconnection",
+		Unit:        "{disconnection}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_succeeded",
 		Description: "EXPERIMENTAL. Number of successful connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_failed",
 		Description: "EXPERIMENTAL. Number of failed connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
@@ -149,17 +140,6 @@ func EnableHealthListener(state resolver.State) resolver.State {
 	return state
 }
 
-// IsManagedByPickfirst returns whether an address belongs to a SubConn
-// managed by the pickfirst LB policy.
-// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable
-// outlier_detection via the with connectivity listener when using pick_first.
-// Once Dualstack changes are complete, all SubConns will be created by
-// pick_first and outlier detection will only use the health listener for
-// ejection. This hack can then be removed.
-func IsManagedByPickfirst(addr resolver.Address) bool {
-	return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil
-}
-
 type pfConfig struct {
 	serviceconfig.LoadBalancingConfig `json:"-"`
 
@@ -186,7 +166,6 @@ type scData struct {
 }
 
 func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) {
-	addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true)
 	sd := &scData{
 		rawConnectivityState: connectivity.Idle,
 		effectiveState:       connectivity.Idle,
diff --git a/history-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/history-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
index 35da5d1e..22045bf3 100644
--- a/history-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
+++ b/history-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -70,10 +70,3 @@ func (b *rrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
 		ResolverState: pickfirstleaf.EnableHealthListener(ccs.ResolverState),
 	})
 }
-
-func (b *rrBalancer) ExitIdle() {
-	// Should always be ok, as child is endpoint sharding.
-	if ei, ok := b.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-	}
-}
diff --git a/history-api/vendor/google.golang.org/grpc/clientconn.go b/history-api/vendor/google.golang.org/grpc/clientconn.go
index cd3eaf8d..3f762285 100644
--- a/history-api/vendor/google.golang.org/grpc/clientconn.go
+++ b/history-api/vendor/google.golang.org/grpc/clientconn.go
@@ -208,7 +208,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error)
 	channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority)
 
 	cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz)
-	cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers)
+	cc.pickerWrapper = newPickerWrapper()
 
 	cc.metricsRecorderList = stats.NewMetricsRecorderList(cc.dopts.copts.StatsHandlers)
 
@@ -1076,13 +1076,6 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
 	return cc.sc.healthCheckConfig
 }
 
-func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
-	return cc.pickerWrapper.pick(ctx, failfast, balancer.PickInfo{
-		Ctx:            ctx,
-		FullMethodName: method,
-	})
-}
-
 func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSelector iresolver.ConfigSelector) {
 	if sc == nil {
 		// should never reach here.
@@ -1831,7 +1824,7 @@ func (cc *ClientConn) initAuthority() error {
 	} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
 		cc.authority = auth.OverrideAuthority(cc.parsedTarget)
 	} else if strings.HasPrefix(endpoint, ":") {
-		cc.authority = "localhost" + endpoint
+		cc.authority = "localhost" + encodeAuthority(endpoint)
 	} else {
 		cc.authority = encodeAuthority(endpoint)
 	}
diff --git a/history-api/vendor/google.golang.org/grpc/credentials/credentials.go b/history-api/vendor/google.golang.org/grpc/credentials/credentials.go
index a63ab606..c8e337cd 100644
--- a/history-api/vendor/google.golang.org/grpc/credentials/credentials.go
+++ b/history-api/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -96,10 +96,11 @@ func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
 	return c
 }
 
-// ProtocolInfo provides information regarding the gRPC wire protocol version,
-// security protocol, security protocol version in use, server name, etc.
+// ProtocolInfo provides static information regarding transport credentials.
 type ProtocolInfo struct {
 	// ProtocolVersion is the gRPC wire protocol version.
+	//
+	// Deprecated: this is unused by gRPC.
 	ProtocolVersion string
 	// SecurityProtocol is the security protocol in use.
 	SecurityProtocol string
@@ -109,7 +110,16 @@ type ProtocolInfo struct {
 	//
 	// Deprecated: please use Peer.AuthInfo.
 	SecurityVersion string
-	// ServerName is the user-configured server name.
+	// ServerName is the user-configured server name.  If set, this overrides
+	// the default :authority header used for all RPCs on the channel using the
+	// containing credentials, unless grpc.WithAuthority is set on the channel,
+	// in which case that setting will take precedence.
+	//
+	// This must be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: Users should use grpc.WithAuthority to override the authority
+	// on a channel instead of configuring the credentials.
 	ServerName string
 }
 
@@ -173,12 +183,17 @@ type TransportCredentials interface {
 	// Clone makes a copy of this TransportCredentials.
 	Clone() TransportCredentials
 	// OverrideServerName specifies the value used for the following:
+	//
 	// - verifying the hostname on the returned certificates
 	// - as SNI in the client's handshake to support virtual hosting
 	// - as the value for `:authority` header at stream creation time
 	//
-	// Deprecated: use grpc.WithAuthority instead. Will be supported
-	// throughout 1.x.
+	// The provided string should be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: this method is unused by gRPC.  Users should use
+	// grpc.WithAuthority to override the authority on a channel instead of
+	// configuring the credentials.
 	OverrideServerName(string) error
 }
 
diff --git a/history-api/vendor/google.golang.org/grpc/credentials/tls.go b/history-api/vendor/google.golang.org/grpc/credentials/tls.go
index 20f65f7b..8277be7d 100644
--- a/history-api/vendor/google.golang.org/grpc/credentials/tls.go
+++ b/history-api/vendor/google.golang.org/grpc/credentials/tls.go
@@ -110,14 +110,14 @@ func (c tlsCreds) Info() ProtocolInfo {
 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
 	// use local cfg to avoid clobbering ServerName if using multiple endpoints
 	cfg := credinternal.CloneTLSConfig(c.config)
-	if cfg.ServerName == "" {
-		serverName, _, err := net.SplitHostPort(authority)
-		if err != nil {
-			// If the authority had no host port or if the authority cannot be parsed, use it as-is.
-			serverName = authority
-		}
-		cfg.ServerName = serverName
+
+	serverName, _, err := net.SplitHostPort(authority)
+	if err != nil {
+		// If the authority had no host port or if the authority cannot be parsed, use it as-is.
+		serverName = authority
 	}
+	cfg.ServerName = serverName
+
 	conn := tls.Client(rawConn, cfg)
 	errChannel := make(chan error, 1)
 	go func() {
@@ -259,9 +259,11 @@ func applyDefaults(c *tls.Config) *tls.Config {
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
 }
@@ -271,9 +273,11 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
 	b, err := os.ReadFile(certFile)
 	if err != nil {
diff --git a/history-api/vendor/google.golang.org/grpc/dialoptions.go b/history-api/vendor/google.golang.org/grpc/dialoptions.go
index 050ba0f1..7a5ac2e7 100644
--- a/history-api/vendor/google.golang.org/grpc/dialoptions.go
+++ b/history-api/vendor/google.golang.org/grpc/dialoptions.go
@@ -213,6 +213,7 @@ func WithReadBufferSize(s int) DialOption {
 func WithInitialWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -222,6 +223,26 @@ func WithInitialWindowSize(s int32) DialOption {
 func WithInitialConnWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticStreamWindowSize returns a DialOption which sets the initial
+// stream window size to the value provided and disables dynamic flow control.
+func WithStaticStreamWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticConnWindowSize returns a DialOption which sets the initial
+// connection window size to the value provided and disables dynamic flow
+// control.
+func WithStaticConnWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -587,6 +608,8 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
 
 // WithAuthority returns a DialOption that specifies the value to be used as the
 // :authority pseudo-header and as the server name in authentication handshake.
+// This overrides all other ways of setting authority on the channel, but can be
+// overridden per-call by using grpc.CallAuthority.
 func WithAuthority(a string) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.authority = a
diff --git a/history-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go b/history-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
index 93136610..f2c01f29 100644
--- a/history-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
+++ b/history-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
@@ -188,13 +188,13 @@ type HealthServer interface {
 type UnimplementedHealthServer struct{}
 
 func (UnimplementedHealthServer) Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
+	return nil, status.Error(codes.Unimplemented, "method Check not implemented")
 }
 func (UnimplementedHealthServer) List(context.Context, *HealthListRequest) (*HealthListResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+	return nil, status.Error(codes.Unimplemented, "method List not implemented")
 }
 func (UnimplementedHealthServer) Watch(*HealthCheckRequest, grpc.ServerStreamingServer[HealthCheckResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method Watch not implemented")
+	return status.Error(codes.Unimplemented, "method Watch not implemented")
 }
 func (UnimplementedHealthServer) testEmbeddedByValue() {}
 
diff --git a/history-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/history-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
index fbc1ca35..ba25b898 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
@@ -223,15 +223,7 @@ func (gsb *Balancer) ExitIdle() {
 	// There is no need to protect this read with a mutex, as the write to the
 	// Balancer field happens in SwitchTo, which completes before this can be
 	// called.
-	if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-		return
-	}
-	gsb.mu.Lock()
-	defer gsb.mu.Unlock()
-	for sc := range balToUpdate.subconns {
-		sc.Connect()
-	}
+	balToUpdate.ExitIdle()
 }
 
 // updateSubConnState forwards the update to the appropriate child.
diff --git a/history-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/history-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
index f5f2bdeb..7e060f5e 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -26,30 +26,32 @@ import (
 )
 
 var (
-	// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
+	// EnableTXTServiceConfig is set if the DNS resolver should perform TXT
+	// lookups for service config ("GRPC_ENABLE_TXT_SERVICE_CONFIG" is not
+	// "false").
+	EnableTXTServiceConfig = boolFromEnv("GRPC_ENABLE_TXT_SERVICE_CONFIG", true)
+
+	// TXTErrIgnore is set if TXT errors should be ignored
+	// ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
 	TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
+
 	// RingHashCap indicates the maximum ring size which defaults to 4096
 	// entries but may be overridden by setting the environment variable
 	// "GRPC_RING_HASH_CAP".  This does not override the default bounds
 	// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
 	RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
-	// LeastRequestLB is set if we should support the least_request_experimental
-	// LB policy, which can be enabled by setting the environment variable
-	// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
-	LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", true)
+
 	// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
 	// handshakes that can be performed.
 	ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
+
 	// EnforceALPNEnabled is set if TLS connections to servers with ALPN disabled
 	// should be rejected. The HTTP/2 protocol requires ALPN to be enabled, this
 	// option is present for backward compatibility. This option may be overridden
 	// by setting the environment variable "GRPC_ENFORCE_ALPN_ENABLED" to "true"
 	// or "false".
 	EnforceALPNEnabled = boolFromEnv("GRPC_ENFORCE_ALPN_ENABLED", true)
-	// XDSFallbackSupport is the env variable that controls whether support for
-	// xDS fallback is turned on. If this is unset or is false, only the first
-	// xDS server in the list of server configs will be used.
-	XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true)
+
 	// NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used
 	// instead of the exiting pickfirst implementation. This can be disabled by
 	// setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST"
diff --git a/history-api/vendor/google.golang.org/grpc/internal/internal.go b/history-api/vendor/google.golang.org/grpc/internal/internal.go
index 3ac798e8..2699223a 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/internal.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/internal.go
@@ -182,35 +182,6 @@ var (
 	// other features, including the CSDS service.
 	NewXDSResolverWithClientForTesting any // func(xdsclient.XDSClient) (resolver.Builder, error)
 
-	// RegisterRLSClusterSpecifierPluginForTesting registers the RLS Cluster
-	// Specifier Plugin for testing purposes, regardless of the XDSRLS environment
-	// variable.
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	RegisterRLSClusterSpecifierPluginForTesting func()
-
-	// UnregisterRLSClusterSpecifierPluginForTesting unregisters the RLS Cluster
-	// Specifier Plugin for testing purposes. This is needed because there is no way
-	// to unregister the RLS Cluster Specifier Plugin after registering it solely
-	// for testing purposes using RegisterRLSClusterSpecifierPluginForTesting().
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	UnregisterRLSClusterSpecifierPluginForTesting func()
-
-	// RegisterRBACHTTPFilterForTesting registers the RBAC HTTP Filter for testing
-	// purposes, regardless of the RBAC environment variable.
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	RegisterRBACHTTPFilterForTesting func()
-
-	// UnregisterRBACHTTPFilterForTesting unregisters the RBAC HTTP Filter for
-	// testing purposes. This is needed because there is no way to unregister the
-	// HTTP Filter after registering it solely for testing purposes using
-	// RegisterRBACHTTPFilterForTesting().
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	UnregisterRBACHTTPFilterForTesting func()
-
 	// ORCAAllowAnyMinReportingInterval is for examples/orca use ONLY.
 	ORCAAllowAnyMinReportingInterval any // func(so *orca.ServiceOptions)
 
diff --git a/history-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/history-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
index ba5c5a95..ada5251c 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
@@ -132,13 +132,13 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
 	// DNS address (non-IP).
 	ctx, cancel := context.WithCancel(context.Background())
 	d := &dnsResolver{
-		host:                 host,
-		port:                 port,
-		ctx:                  ctx,
-		cancel:               cancel,
-		cc:                   cc,
-		rn:                   make(chan struct{}, 1),
-		disableServiceConfig: opts.DisableServiceConfig,
+		host:                host,
+		port:                port,
+		ctx:                 ctx,
+		cancel:              cancel,
+		cc:                  cc,
+		rn:                  make(chan struct{}, 1),
+		enableServiceConfig: envconfig.EnableTXTServiceConfig && !opts.DisableServiceConfig,
 	}
 
 	d.resolver, err = internal.NewNetResolver(target.URL.Host)
@@ -181,8 +181,8 @@ type dnsResolver struct {
 	// finishes, race detector sometimes will warn lookup (READ the lookup
 	// function pointers) inside watcher() goroutine has data race with
 	// replaceNetFunc (WRITE the lookup function pointers).
-	wg                   sync.WaitGroup
-	disableServiceConfig bool
+	wg                  sync.WaitGroup
+	enableServiceConfig bool
 }
 
 // ResolveNow invoke an immediate resolution of the target that this
@@ -346,7 +346,7 @@ func (d *dnsResolver) lookup() (*resolver.State, error) {
 	if len(srv) > 0 {
 		state = grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: srv})
 	}
-	if !d.disableServiceConfig {
+	if d.enableServiceConfig {
 		state.ServiceConfig = d.lookupTXT(ctx)
 	}
 	return &state, nil
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/history-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
index ef72fbb3..a2831e5d 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -40,6 +40,13 @@ var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
 	e.SetMaxDynamicTableSizeLimit(v)
 }
 
+// itemNodePool is used to reduce heap allocations.
+var itemNodePool = sync.Pool{
+	New: func() any {
+		return &itemNode{}
+	},
+}
+
 type itemNode struct {
 	it   any
 	next *itemNode
@@ -51,7 +58,9 @@ type itemList struct {
 }
 
 func (il *itemList) enqueue(i any) {
-	n := &itemNode{it: i}
+	n := itemNodePool.Get().(*itemNode)
+	n.next = nil
+	n.it = i
 	if il.tail == nil {
 		il.head, il.tail = n, n
 		return
@@ -71,7 +80,9 @@ func (il *itemList) dequeue() any {
 		return nil
 	}
 	i := il.head.it
+	temp := il.head
 	il.head = il.head.next
+	itemNodePool.Put(temp)
 	if il.head == nil {
 		il.tail = nil
 	}
@@ -146,10 +157,11 @@ type earlyAbortStream struct {
 func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
 
 type dataFrame struct {
-	streamID  uint32
-	endStream bool
-	h         []byte
-	reader    mem.Reader
+	streamID   uint32
+	endStream  bool
+	h          []byte
+	data       mem.BufferSlice
+	processing bool
 	// onEachWrite is called every time
 	// a part of data is written out.
 	onEachWrite func()
@@ -234,6 +246,7 @@ type outStream struct {
 	itl              *itemList
 	bytesOutStanding int
 	wq               *writeQuota
+	reader           mem.Reader
 
 	next *outStream
 	prev *outStream
@@ -461,7 +474,9 @@ func (c *controlBuffer) finish() {
 				v.onOrphaned(ErrConnClosing)
 			}
 		case *dataFrame:
-			_ = v.reader.Close()
+			if !v.processing {
+				v.data.Free()
+			}
 		}
 	}
 
@@ -650,10 +665,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
 
 func (l *loopyWriter) registerStreamHandler(h *registerStream) {
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	l.estdStreams[h.streamID] = str
 }
@@ -685,10 +701,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
 	}
 	// Case 2: Client wants to originate stream.
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	return l.originateStream(str, h)
 }
@@ -790,10 +807,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
 		// a RST_STREAM before stream initialization thus the stream might
 		// not be established yet.
 		delete(l.estdStreams, c.streamID)
+		str.reader.Close()
 		str.deleteSelf()
 		for head := str.itl.dequeueAll(); head != nil; head = head.next {
 			if df, ok := head.it.(*dataFrame); ok {
-				_ = df.reader.Close()
+				if !df.processing {
+					df.data.Free()
+				}
 			}
 		}
 	}
@@ -928,7 +948,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	if str == nil {
 		return true, nil
 	}
+	reader := str.reader
 	dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
+	if !dataItem.processing {
+		dataItem.processing = true
+		str.reader.Reset(dataItem.data)
+		dataItem.data.Free()
+	}
 	// A data item is represented by a dataFrame, since it later translates into
 	// multiple HTTP2 data frames.
 	// Every dataFrame has two buffers; h that keeps grpc-message header and data
@@ -936,13 +962,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	// from data is copied to h to make as big as the maximum possible HTTP2 frame
 	// size.
 
-	if len(dataItem.h) == 0 && dataItem.reader.Remaining() == 0 { // Empty data frame
+	if len(dataItem.h) == 0 && reader.Remaining() == 0 { // Empty data frame
 		// Client sends out empty data frame with endStream = true
 		if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
 			return false, err
 		}
 		str.itl.dequeue() // remove the empty data item from stream
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		if str.itl.isEmpty() {
 			str.state = empty
 		} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
@@ -971,8 +997,8 @@ func (l *loopyWriter) processData() (bool, error) {
 	}
 	// Compute how much of the header and data we can send within quota and max frame length
 	hSize := min(maxSize, len(dataItem.h))
-	dSize := min(maxSize-hSize, dataItem.reader.Remaining())
-	remainingBytes := len(dataItem.h) + dataItem.reader.Remaining() - hSize - dSize
+	dSize := min(maxSize-hSize, reader.Remaining())
+	remainingBytes := len(dataItem.h) + reader.Remaining() - hSize - dSize
 	size := hSize + dSize
 
 	var buf *[]byte
@@ -993,7 +1019,7 @@ func (l *loopyWriter) processData() (bool, error) {
 		defer pool.Put(buf)
 
 		copy((*buf)[:hSize], dataItem.h)
-		_, _ = dataItem.reader.Read((*buf)[hSize:])
+		_, _ = reader.Read((*buf)[hSize:])
 	}
 
 	// Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1014,7 +1040,7 @@ func (l *loopyWriter) processData() (bool, error) {
 	dataItem.h = dataItem.h[hSize:]
 
 	if remainingBytes == 0 { // All the data from that message was written out.
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		str.itl.dequeue()
 	}
 	if str.itl.isEmpty() {
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/history-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 3dea2357..d954a64c 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -277,11 +277,13 @@ func (ht *serverHandlerTransport) writeStatus(s *ServerStream, st *status.Status
 	if err == nil { // transport has not been closed
 		// Note: The trailer fields are compressed with hpack after this call returns.
 		// No WireLength field is set here.
+		s.hdrMu.Lock()
 		for _, sh := range ht.stats {
 			sh.HandleRPC(s.Context(), &stats.OutTrailer{
 				Trailer: s.trailer.Copy(),
 			})
 		}
+		s.hdrMu.Unlock()
 	}
 	ht.Close(errors.New("finished writing status"))
 	return err
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/history-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index ef56592b..5467fe97 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -309,11 +309,9 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 			scheme = "https"
 		}
 	}
-	dynamicWindow := true
 	icwz := int32(initialWindowSize)
 	if opts.InitialConnWindowSize >= defaultWindowSize {
 		icwz = opts.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	writeBufSize := opts.WriteBufferSize
 	readBufSize := opts.ReadBufferSize
@@ -381,9 +379,8 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 	t.controlBuf = newControlBuffer(t.ctxDone)
 	if opts.InitialWindowSize >= defaultWindowSize {
 		t.initialWindowSize = opts.InitialWindowSize
-		dynamicWindow = false
 	}
-	if dynamicWindow {
+	if !opts.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -1091,32 +1088,29 @@ func (t *http2Client) GracefulClose() {
 // Write formats the data into HTTP2 data frame(s) and sends it out. The caller
 // should proceed only if Write returns nil.
 func (t *http2Client) write(s *ClientStream, hdr []byte, data mem.BufferSlice, opts *WriteOptions) error {
-	reader := data.Reader()
-
 	if opts.Last {
 		// If it's the last message, update stream state.
 		if !s.compareAndSwapState(streamActive, streamWriteDone) {
-			_ = reader.Close()
 			return errStreamDone
 		}
 	} else if s.getState() != streamActive {
-		_ = reader.Close()
 		return errStreamDone
 	}
 	df := &dataFrame{
 		streamID:  s.id,
 		endStream: opts.Last,
 		h:         hdr,
-		reader:    reader,
+		data:      data,
 	}
-	if hdr != nil || df.reader.Remaining() != 0 { // If it's not an empty data frame, check quota.
-		if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-			_ = reader.Close()
+	dataLen := data.Len()
+	if hdr != nil || dataLen != 0 { // If it's not an empty data frame, check quota.
+		if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 			return err
 		}
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/history-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index e4c3731b..83cee314 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -132,6 +132,10 @@ type http2Server struct {
 	maxStreamID uint32 // max stream ID ever seen
 
 	logger *grpclog.PrefixLogger
+	// setResetPingStrikes is stored as a closure instead of making this a
+	// method on http2Server to avoid a heap allocation when converting a method
+	// to a closure for passing to frames objects.
+	setResetPingStrikes func()
 }
 
 // NewServerTransport creates a http2 transport with conn and configuration
@@ -176,16 +180,13 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 			Val: config.MaxStreams,
 		})
 	}
-	dynamicWindow := true
 	iwz := int32(initialWindowSize)
 	if config.InitialWindowSize >= defaultWindowSize {
 		iwz = config.InitialWindowSize
-		dynamicWindow = false
 	}
 	icwz := int32(initialWindowSize)
 	if config.InitialConnWindowSize >= defaultWindowSize {
 		icwz = config.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	if iwz != defaultWindowSize {
 		isettings = append(isettings, http2.Setting{
@@ -266,6 +267,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		initialWindowSize: iwz,
 		bufferPool:        config.BufferPool,
 	}
+	t.setResetPingStrikes = func() {
+		atomic.StoreUint32(&t.resetPingStrikes, 1)
+	}
 	var czSecurity credentials.ChannelzSecurityValue
 	if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok {
 		czSecurity = au.GetSecurityValue()
@@ -285,7 +289,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 	t.logger = prefixLoggerForServerTransport(t)
 
 	t.controlBuf = newControlBuffer(t.done)
-	if dynamicWindow {
+	if !config.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -596,10 +600,25 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
 			return nil
 		}
 	}
+
+	if s.ctx.Err() != nil {
+		t.mu.Unlock()
+		// Early abort in case the timeout was zero or so low it already fired.
+		t.controlBuf.put(&earlyAbortStream{
+			httpStatus:     http.StatusOK,
+			streamID:       s.id,
+			contentSubtype: s.contentSubtype,
+			status:         status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()),
+			rst:            !frame.StreamEnded(),
+		})
+		return nil
+	}
+
 	t.activeStreams[streamID] = s
 	if len(t.activeStreams) == 1 {
 		t.idle = time.Time{}
 	}
+
 	// Start a timer to close the stream on reaching the deadline.
 	if timeoutSet {
 		// We need to wait for s.cancel to be updated before calling
@@ -1016,10 +1035,6 @@ func (t *http2Server) writeHeader(s *ServerStream, md metadata.MD) error {
 	return nil
 }
 
-func (t *http2Server) setResetPingStrikes() {
-	atomic.StoreUint32(&t.resetPingStrikes, 1)
-}
-
 func (t *http2Server) writeHeaderLocked(s *ServerStream) error {
 	// TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
 	// first and create a slice of that exact size.
@@ -1132,17 +1147,13 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error {
 // Write converts the data into HTTP2 data frame and sends it out. Non-nil error
 // is returns if it fails (e.g., framing error, transport error).
 func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _ *WriteOptions) error {
-	reader := data.Reader()
-
 	if !s.isHeaderSent() { // Headers haven't been written yet.
 		if err := t.writeHeader(s, nil); err != nil {
-			_ = reader.Close()
 			return err
 		}
 	} else {
 		// Writing headers checks for this condition.
 		if s.getState() == streamDone {
-			_ = reader.Close()
 			return t.streamContextErr(s)
 		}
 	}
@@ -1150,15 +1161,16 @@ func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _
 	df := &dataFrame{
 		streamID:    s.id,
 		h:           hdr,
-		reader:      reader,
+		data:        data,
 		onEachWrite: t.setResetPingStrikes,
 	}
-	if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-		_ = reader.Close()
+	dataLen := data.Len()
+	if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 		return t.streamContextErr(s)
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
@@ -1341,10 +1353,10 @@ func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCo
 	// called to interrupt the potential blocking on other goroutines.
 	s.cancel()
 
-	oldState := s.swapState(streamDone)
-	if oldState == streamDone {
-		return
-	}
+	// We can't return early even if the stream's state is "done" as the state
+	// might have been set by the `finishStream` method. Deleting the stream via
+	// `finishStream` can get blocked on flow control.
+	s.swapState(streamDone)
 	t.deleteStream(s, eosReceived)
 
 	t.controlBuf.put(&cleanupStream{
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/http_util.go b/history-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 607d2c4c..e3663f87 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -200,9 +200,6 @@ func decodeTimeout(s string) (time.Duration, error) {
 	if err != nil {
 		return 0, err
 	}
-	if t == 0 {
-		return 0, fmt.Errorf("transport: timeout must be positive: %q", s)
-	}
 	const maxHours = math.MaxInt64 / uint64(time.Hour)
 	if d == time.Hour && t > maxHours {
 		// This timeout would overflow math.MaxInt64; clamp it.
diff --git a/history-api/vendor/google.golang.org/grpc/internal/transport/transport.go b/history-api/vendor/google.golang.org/grpc/internal/transport/transport.go
index 1730a639..7dd53e80 100644
--- a/history-api/vendor/google.golang.org/grpc/internal/transport/transport.go
+++ b/history-api/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -466,6 +466,7 @@ type ServerConfig struct {
 	MaxHeaderListSize     *uint32
 	HeaderTableSize       *uint32
 	BufferPool            mem.BufferPool
+	StaticWindowSize      bool
 }
 
 // ConnectOptions covers all relevant options for communicating with the server.
@@ -504,6 +505,8 @@ type ConnectOptions struct {
 	MaxHeaderListSize *uint32
 	// The mem.BufferPool to use when reading/writing to the wire.
 	BufferPool mem.BufferPool
+	// StaticWindowSize controls whether dynamic window sizing is enabled.
+	StaticWindowSize bool
 }
 
 // WriteOptions provides additional hints and information for message
diff --git a/history-api/vendor/google.golang.org/grpc/mem/buffer_slice.go b/history-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
index 65002e2c..af510d20 100644
--- a/history-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
+++ b/history-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
@@ -137,6 +137,9 @@ type Reader interface {
 	Close() error
 	// Remaining returns the number of unread bytes remaining in the slice.
 	Remaining() int
+	// Reset frees the currently held buffer slice and starts reading from the
+	// provided slice. This allows reusing the reader object.
+	Reset(s BufferSlice)
 }
 
 type sliceReader struct {
@@ -150,6 +153,14 @@ func (r *sliceReader) Remaining() int {
 	return r.len
 }
 
+func (r *sliceReader) Reset(s BufferSlice) {
+	r.data.Free()
+	s.Ref()
+	r.data = s
+	r.len = s.Len()
+	r.bufferIdx = 0
+}
+
 func (r *sliceReader) Close() error {
 	r.data.Free()
 	r.data = nil
diff --git a/history-api/vendor/google.golang.org/grpc/picker_wrapper.go b/history-api/vendor/google.golang.org/grpc/picker_wrapper.go
index a2d2a798..aa52bfe9 100644
--- a/history-api/vendor/google.golang.org/grpc/picker_wrapper.go
+++ b/history-api/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -29,7 +29,6 @@ import (
 	"google.golang.org/grpc/internal/channelz"
 	istatus "google.golang.org/grpc/internal/status"
 	"google.golang.org/grpc/internal/transport"
-	"google.golang.org/grpc/stats"
 	"google.golang.org/grpc/status"
 )
 
@@ -48,14 +47,11 @@ type pickerGeneration struct {
 // actions and unblock when there's a picker update.
 type pickerWrapper struct {
 	// If pickerGen holds a nil pointer, the pickerWrapper is closed.
-	pickerGen     atomic.Pointer[pickerGeneration]
-	statsHandlers []stats.Handler // to record blocking picker calls
+	pickerGen atomic.Pointer[pickerGeneration]
 }
 
-func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
-	pw := &pickerWrapper{
-		statsHandlers: statsHandlers,
-	}
+func newPickerWrapper() *pickerWrapper {
+	pw := &pickerWrapper{}
 	pw.pickerGen.Store(&pickerGeneration{
 		blockingCh: make(chan struct{}),
 	})
@@ -93,6 +89,12 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 	}
 }
 
+type pick struct {
+	transport transport.ClientTransport // the selected transport
+	result    balancer.PickResult       // the contents of the pick from the LB policy
+	blocked   bool                      // set if a picker call queued for a new picker
+}
+
 // pick returns the transport that will be used for the RPC.
 // It may block in the following cases:
 // - there's no picker
@@ -100,15 +102,16 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 // - the current picker returns other errors and failfast is false.
 // - the subConn returned by the current picker is not READY
 // When one of these situations happens, pick blocks until the picker gets updated.
-func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
+func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (pick, error) {
 	var ch chan struct{}
 
 	var lastPickErr error
+	pickBlocked := false
 
 	for {
 		pg := pw.pickerGen.Load()
 		if pg == nil {
-			return nil, balancer.PickResult{}, ErrClientConnClosing
+			return pick{}, ErrClientConnClosing
 		}
 		if pg.picker == nil {
 			ch = pg.blockingCh
@@ -127,9 +130,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				}
 				switch ctx.Err() {
 				case context.DeadlineExceeded:
-					return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
+					return pick{}, status.Error(codes.DeadlineExceeded, errStr)
 				case context.Canceled:
-					return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
+					return pick{}, status.Error(codes.Canceled, errStr)
 				}
 			case <-ch:
 			}
@@ -145,9 +148,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		// In the second case, the only way it will get to this conditional is
 		// if there is a new picker.
 		if ch != nil {
-			for _, sh := range pw.statsHandlers {
-				sh.HandleRPC(ctx, &stats.PickerUpdated{})
-			}
+			pickBlocked = true
 		}
 
 		ch = pg.blockingCh
@@ -164,7 +165,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				if istatus.IsRestrictedControlPlaneCode(st) {
 					err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
 				}
-				return nil, balancer.PickResult{}, dropError{error: err}
+				return pick{}, dropError{error: err}
 			}
 			// For all other errors, wait for ready RPCs should block and other
 			// RPCs should fail with unavailable.
@@ -172,7 +173,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				lastPickErr = err
 				continue
 			}
-			return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
+			return pick{}, status.Error(codes.Unavailable, err.Error())
 		}
 
 		acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
@@ -183,9 +184,8 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		if t := acbw.ac.getReadyTransport(); t != nil {
 			if channelz.IsOn() {
 				doneChannelzWrapper(acbw, &pickResult)
-				return t, pickResult, nil
 			}
-			return t, pickResult, nil
+			return pick{transport: t, result: pickResult, blocked: pickBlocked}, nil
 		}
 		if pickResult.Done != nil {
 			// Calling done with nil error, no bytes sent and no bytes received.
diff --git a/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
index 03108280..f4a361c6 100644
--- a/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
+++ b/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
@@ -90,7 +90,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
index 80755d74..0a43b521 100644
--- a/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
+++ b/history-api/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
@@ -87,7 +87,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/history-api/vendor/google.golang.org/grpc/resolver/resolver.go b/history-api/vendor/google.golang.org/grpc/resolver/resolver.go
index b84ef26d..8e6af951 100644
--- a/history-api/vendor/google.golang.org/grpc/resolver/resolver.go
+++ b/history-api/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -332,6 +332,11 @@ type AuthorityOverrider interface {
 	// OverrideAuthority returns the authority to use for a ClientConn with the
 	// given target. The implementation must generate it without blocking,
 	// typically in line, and must keep it unchanged.
+	//
+	// The returned string must be a valid ":authority" header value, i.e. be
+	// encoded according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
+	// necessary.
 	OverrideAuthority(Target) string
 }
 
diff --git a/history-api/vendor/google.golang.org/grpc/server.go b/history-api/vendor/google.golang.org/grpc/server.go
index 976e70ae..1da2a542 100644
--- a/history-api/vendor/google.golang.org/grpc/server.go
+++ b/history-api/vendor/google.golang.org/grpc/server.go
@@ -179,6 +179,7 @@ type serverOptions struct {
 	numServerWorkers      uint32
 	bufferPool            mem.BufferPool
 	waitForHandlers       bool
+	staticWindowSize      bool
 }
 
 var defaultServerOptions = serverOptions{
@@ -279,6 +280,7 @@ func ReadBufferSize(s int) ServerOption {
 func InitialWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -287,6 +289,29 @@ func InitialWindowSize(s int32) ServerOption {
 func InitialConnWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialConnWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticStreamWindowSize returns a ServerOption to set the initial stream
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticStreamWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticConnWindowSize returns a ServerOption to set the initial connection
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticConnWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialConnWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -986,6 +1011,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
 		MaxHeaderListSize:     s.opts.maxHeaderListSize,
 		HeaderTableSize:       s.opts.headerTableSize,
 		BufferPool:            s.opts.bufferPool,
+		StaticWindowSize:      s.opts.staticWindowSize,
 	}
 	st, err := transport.NewServerTransport(c, config)
 	if err != nil {
@@ -1572,6 +1598,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv
 		s:                     stream,
 		p:                     &parser{r: stream, bufferPool: s.opts.bufferPool},
 		codec:                 s.getCodec(stream.ContentSubtype()),
+		desc:                  sd,
 		maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
 		maxSendMessageSize:    s.opts.maxSendMessageSize,
 		trInfo:                trInfo,
diff --git a/history-api/vendor/google.golang.org/grpc/stats/stats.go b/history-api/vendor/google.golang.org/grpc/stats/stats.go
index baf7740e..10bf998a 100644
--- a/history-api/vendor/google.golang.org/grpc/stats/stats.go
+++ b/history-api/vendor/google.golang.org/grpc/stats/stats.go
@@ -64,15 +64,21 @@ func (s *Begin) IsClient() bool { return s.Client }
 
 func (s *Begin) isRPCStats() {}
 
-// PickerUpdated indicates that the LB policy provided a new picker while the
-// RPC was waiting for one.
-type PickerUpdated struct{}
+// DelayedPickComplete indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+type DelayedPickComplete struct{}
 
-// IsClient indicates if the stats information is from client side. Only Client
-// Side interfaces with a Picker, thus always returns true.
-func (*PickerUpdated) IsClient() bool { return true }
+// IsClient indicates DelayedPickComplete is available on the client.
+func (*DelayedPickComplete) IsClient() bool { return true }
 
-func (*PickerUpdated) isRPCStats() {}
+func (*DelayedPickComplete) isRPCStats() {}
+
+// PickerUpdated indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+//
+// Deprecated: will be removed in a future release; use DelayedPickComplete
+// instead.
+type PickerUpdated = DelayedPickComplete
 
 // InPayload contains stats about an incoming payload.
 type InPayload struct {
diff --git a/history-api/vendor/google.golang.org/grpc/stream.go b/history-api/vendor/google.golang.org/grpc/stream.go
index d58bb647..d9bbd4c5 100644
--- a/history-api/vendor/google.golang.org/grpc/stream.go
+++ b/history-api/vendor/google.golang.org/grpc/stream.go
@@ -469,8 +469,9 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error)
 func (a *csAttempt) getTransport() error {
 	cs := a.cs
 
-	var err error
-	a.transport, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method)
+	pickInfo := balancer.PickInfo{Ctx: a.ctx, FullMethodName: cs.callHdr.Method}
+	pick, err := cs.cc.pickerWrapper.pick(a.ctx, cs.callInfo.failFast, pickInfo)
+	a.transport, a.pickResult = pick.transport, pick.result
 	if err != nil {
 		if de, ok := err.(dropError); ok {
 			err = de.error
@@ -481,6 +482,11 @@ func (a *csAttempt) getTransport() error {
 	if a.trInfo != nil {
 		a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr())
 	}
+	if pick.blocked {
+		for _, sh := range a.statsHandlers {
+			sh.HandleRPC(a.ctx, &stats.DelayedPickComplete{})
+		}
+	}
 	return nil
 }
 
@@ -1171,7 +1177,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (a *csAttempt) finish(err error) {
@@ -1495,7 +1501,7 @@ func (as *addrConnStream) RecvMsg(m any) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (as *addrConnStream) finish(err error) {
@@ -1580,6 +1586,7 @@ type serverStream struct {
 	s     *transport.ServerStream
 	p     *parser
 	codec baseCodec
+	desc  *StreamDesc
 
 	compressorV0   Compressor
 	compressorV1   encoding.Compressor
@@ -1588,6 +1595,8 @@ type serverStream struct {
 
 	sendCompressorName string
 
+	recvFirstMsg bool // set after the first message is received
+
 	maxReceiveMessageSize int
 	maxSendMessageSize    int
 	trInfo                *traceInfo
@@ -1774,6 +1783,10 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 					binlog.Log(ss.ctx, chc)
 				}
 			}
+			// Received no request msg for non-client streaming rpcs.
+			if !ss.desc.ClientStreams && !ss.recvFirstMsg {
+				return status.Error(codes.Internal, "cardinality violation: received no request message from non-client-streaming RPC")
+			}
 			return err
 		}
 		if err == io.ErrUnexpectedEOF {
@@ -1781,6 +1794,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 		}
 		return toRPCErr(err)
 	}
+	ss.recvFirstMsg = true
 	if len(ss.statsHandler) != 0 {
 		for _, sh := range ss.statsHandler {
 			sh.HandleRPC(ss.s.Context(), &stats.InPayload{
@@ -1800,7 +1814,19 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 			binlog.Log(ss.ctx, cm)
 		}
 	}
-	return nil
+
+	if ss.desc.ClientStreams {
+		// Subsequent messages should be received by subsequent RecvMsg calls.
+		return nil
+	}
+	// Special handling for non-client-stream rpcs.
+	// This recv expects EOF or errors, so we don't collect inPayload.
+	if err := recv(ss.p, ss.codec, ss.s, ss.decompressorV0, m, ss.maxReceiveMessageSize, nil, ss.decompressorV1, true); err == io.EOF {
+		return nil
+	} else if err != nil {
+		return err
+	}
+	return status.Error(codes.Internal, "cardinality violation: received multiple request messages for non-client-streaming RPC")
 }
 
 // MethodFromServerStream returns the method string for the input stream.
diff --git a/history-api/vendor/google.golang.org/grpc/version.go b/history-api/vendor/google.golang.org/grpc/version.go
index bd82673d..468f1106 100644
--- a/history-api/vendor/google.golang.org/grpc/version.go
+++ b/history-api/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.73.0"
+const Version = "1.75.1"
diff --git a/history-api/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go b/history-api/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
index 999a2515..45749edd 100644
--- a/history-api/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
+++ b/history-api/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
@@ -11,6 +11,7 @@ import (
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/reflect/protoreflect"
 
@@ -279,8 +280,7 @@ func isLazy(field *protogen.Field) bool {
 	}
 
 	// Was the field marked as [lazy = true] in the .proto file?
-	fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
-	return fopts.GetLazy()
+	return field.Desc.(interface{ IsLazy() bool }).IsLazy()
 }
 
 // opaqueGenGet generates a Get method for a field.
@@ -573,16 +573,8 @@ func usePresence(message *messageInfo, field *protogen.Field) bool {
 	if !message.isOpaque() {
 		return false
 	}
-	return opaqueFieldNeedsPresenceArray(message, field)
-}
-
-func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
-	// Non optional fields need presence if truly lazy field, i.e. are message fields.
-	if isLazy(field) {
-		return true
-	}
-	isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
-	return field.Desc.HasPresence() && field.Message == nil && isNotOneof
+	usePresence, _ := filedesc.UsePresenceForField(field.Desc)
+	return usePresence
 }
 
 // opaqueGenHas generates a Has method for a field.
@@ -832,7 +824,7 @@ func opaqueNeedsPresenceArray(message *messageInfo) bool {
 		return false
 	}
 	for _, field := range message.Fields {
-		if opaqueFieldNeedsPresenceArray(message, field) {
+		if usePresence, _ := filedesc.UsePresenceForField(field.Desc); usePresence {
 			return true
 		}
 	}
diff --git a/history-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/history-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
index e942bc98..743bfb81 100644
--- a/history-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
+++ b/history-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
@@ -371,7 +371,31 @@ func ConsumeVarint(b []byte) (v uint64, n int) {
 func SizeVarint(v uint64) int {
 	// This computes 1 + (bits.Len64(v)-1)/7.
 	// 9/64 is a good enough approximation of 1/7
-	return int(9*uint32(bits.Len64(v))+64) / 64
+	//
+	// The Go compiler can translate the bits.LeadingZeros64 call into the LZCNT
+	// instruction, which is very fast on CPUs from the last few years. The
+	// specific way of expressing the calculation matches C++ Protobuf, see
+	// https://godbolt.org/z/4P3h53oM4 for the C++ code and how gcc/clang
+	// optimize that function for GOAMD64=v1 and GOAMD64=v3 (-march=haswell).
+
+	// By OR'ing v with 1, we guarantee that v is never 0, without changing the
+	// result of SizeVarint. LZCNT is not defined for 0, meaning the compiler
+	// needs to add extra instructions to handle that case.
+	//
+	// The Go compiler currently (go1.24.4) does not make use of this knowledge.
+	// This opportunity (removing the XOR instruction, which handles the 0 case)
+	// results in a small (1%) performance win across CPU architectures.
+	//
+	// Independently of avoiding the 0 case, we need the v |= 1 line because
+	// it allows the Go compiler to eliminate an extra XCHGL barrier.
+	v |= 1
+
+	// It would be clearer to write log2value := 63 - uint32(...), but
+	// writing uint32(...) ^ 63 is much more efficient (-14% ARM, -20% Intel).
+	// Proof of identity for our value range [0..63]:
+	// https://go.dev/play/p/Pdn9hEWYakX
+	log2value := uint32(bits.LeadingZeros64(v)) ^ 63
+	return int((log2value*9 + (64 + 9)) / 64)
 }
 
 // AppendFixed32 appends v to b as a little-endian uint32.
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/history-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb
index 323829da..04696351 100644
Binary files a/history-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb and b/history-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb differ
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/history-api/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
index bf1aba0e..7b9f01af 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
@@ -9,7 +9,7 @@ import "google.golang.org/protobuf/types/descriptorpb"
 
 const (
 	Minimum = descriptorpb.Edition_EDITION_PROTO2
-	Maximum = descriptorpb.Edition_EDITION_2023
+	Maximum = descriptorpb.Edition_EDITION_2024
 
 	// MaximumKnown is the maximum edition that is known to Go Protobuf, but not
 	// declared as supported. In other words: end users cannot use it, but
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 688aabe4..dbcf90b8 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -72,9 +72,10 @@ type (
 		EditionFeatures EditionFeatures
 	}
 	FileL2 struct {
-		Options   func() protoreflect.ProtoMessage
-		Imports   FileImports
-		Locations SourceLocations
+		Options       func() protoreflect.ProtoMessage
+		Imports       FileImports
+		OptionImports func() protoreflect.FileImports
+		Locations     SourceLocations
 	}
 
 	// EditionFeatures is a frequently-instantiated struct, so please take care
@@ -126,12 +127,9 @@ func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
 func (fd *File) Parent() protoreflect.Descriptor         { return nil }
 func (fd *File) Index() int                              { return 0 }
 func (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }
-
-// Not exported and just used to reconstruct the original FileDescriptor proto
-func (fd *File) Edition() int32                  { return int32(fd.L1.Edition) }
-func (fd *File) Name() protoreflect.Name         { return fd.L1.Package.Name() }
-func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
-func (fd *File) IsPlaceholder() bool             { return false }
+func (fd *File) Name() protoreflect.Name                 { return fd.L1.Package.Name() }
+func (fd *File) FullName() protoreflect.FullName         { return fd.L1.Package }
+func (fd *File) IsPlaceholder() bool                     { return false }
 func (fd *File) Options() protoreflect.ProtoMessage {
 	if f := fd.lazyInit().Options; f != nil {
 		return f()
@@ -150,6 +148,16 @@ func (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatD
 func (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
 func (fd *File) ProtoInternal(pragma.DoNotImplement)           {}
 
+// The next two are not part of the FileDescriptor interface. They are just used to reconstruct
+// the original FileDescriptor proto.
+func (fd *File) Edition() int32 { return int32(fd.L1.Edition) }
+func (fd *File) OptionImports() protoreflect.FileImports {
+	if f := fd.lazyInit().OptionImports; f != nil {
+		return f()
+	}
+	return emptyFiles
+}
+
 func (fd *File) lazyInit() *FileL2 {
 	if atomic.LoadUint32(&fd.once) == 0 {
 		fd.lazyInitOnce()
@@ -182,9 +190,9 @@ type (
 		L2 *EnumL2 // protected by fileDesc.once
 	}
 	EnumL1 struct {
-		eagerValues bool // controls whether EnumL2.Values is already populated
-
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		eagerValues     bool // controls whether EnumL2.Values is already populated
 	}
 	EnumL2 struct {
 		Options        func() protoreflect.ProtoMessage
@@ -219,6 +227,11 @@ func (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit()
 func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
 func (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
 func (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
+
+// This is not part of the EnumDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (ed *Enum) Visibility() int32 { return ed.L1.Visibility }
+
 func (ed *Enum) lazyInit() *EnumL2 {
 	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return ed.L2
@@ -244,13 +257,13 @@ type (
 		L2 *MessageL2 // protected by fileDesc.once
 	}
 	MessageL1 struct {
-		Enums        Enums
-		Messages     Messages
-		Extensions   Extensions
-		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
-		IsMessageSet bool // promoted from google.protobuf.MessageOptions
-
+		Enums           Enums
+		Messages        Messages
+		Extensions      Extensions
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		IsMapEntry      bool // promoted from google.protobuf.MessageOptions
+		IsMessageSet    bool // promoted from google.protobuf.MessageOptions
 	}
 	MessageL2 struct {
 		Options               func() protoreflect.ProtoMessage
@@ -319,6 +332,11 @@ func (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L
 func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
 func (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
 func (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
+
+// This is not part of the MessageDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (md *Message) Visibility() int32 { return md.L1.Visibility }
+
 func (md *Message) lazyInit() *MessageL2 {
 	md.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return md.L2
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
index d2f54949..e91860f5 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
@@ -284,6 +284,13 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protorefl
 			case genid.EnumDescriptorProto_Value_field_number:
 				numValues++
 			}
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.EnumDescriptorProto_Visibility_field_number:
+				ed.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
@@ -365,6 +372,13 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
 				md.unmarshalSeedOptions(v)
 			}
 			prevField = num
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.DescriptorProto_Visibility_field_number:
+				md.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index d4c94458..dd31faae 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -134,6 +134,7 @@ func (fd *File) unmarshalFull(b []byte) {
 
 	var enumIdx, messageIdx, extensionIdx, serviceIdx int
 	var rawOptions []byte
+	var optionImports []string
 	fd.L2 = new(FileL2)
 	for len(b) > 0 {
 		num, typ, n := protowire.ConsumeTag(b)
@@ -157,6 +158,8 @@ func (fd *File) unmarshalFull(b []byte) {
 					imp = PlaceholderFile(path)
 				}
 				fd.L2.Imports = append(fd.L2.Imports, protoreflect.FileImport{FileDescriptor: imp})
+			case genid.FileDescriptorProto_OptionDependency_field_number:
+				optionImports = append(optionImports, sb.MakeString(v))
 			case genid.FileDescriptorProto_EnumType_field_number:
 				fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
 				enumIdx++
@@ -178,6 +181,23 @@ func (fd *File) unmarshalFull(b []byte) {
 		}
 	}
 	fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
+	if len(optionImports) > 0 {
+		var imps FileImports
+		var once sync.Once
+		fd.L2.OptionImports = func() protoreflect.FileImports {
+			once.Do(func() {
+				imps = make(FileImports, len(optionImports))
+				for i, path := range optionImports {
+					imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
+					if imp == nil {
+						imp = PlaceholderFile(path)
+					}
+					imps[i] = protoreflect.FileImport{FileDescriptor: imp}
+				}
+			})
+			return &imps
+		}
+	}
 }
 
 func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
index b08b7183..66ba9068 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
@@ -13,8 +13,10 @@ import (
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
-var defaultsCache = make(map[Edition]EditionFeatures)
-var defaultsKeys = []Edition{}
+var (
+	defaultsCache = make(map[Edition]EditionFeatures)
+	defaultsKeys  = []Edition{}
+)
 
 func init() {
 	unmarshalEditionDefaults(editiondefaults.Defaults)
@@ -41,7 +43,7 @@ func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
 			b = b[m:]
 			parent.StripEnumPrefix = int(v)
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling GoFeatures", num))
 		}
 	}
 	return parent
@@ -72,8 +74,11 @@ func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
 			case genid.FeatureSet_EnforceNamingStyle_field_number:
 				// EnforceNamingStyle is enforced in protoc, languages other than C++
 				// are not supposed to do anything with this feature.
+			case genid.FeatureSet_DefaultSymbolVisibility_field_number:
+				// DefaultSymbolVisibility is enforced in protoc, runtimes should not
+				// inspect this value.
 			default:
-				panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
+				panic(fmt.Sprintf("unknown field number %d while unmarshalling FeatureSet", num))
 			}
 		case protowire.BytesType:
 			v, m := protowire.ConsumeBytes(b)
@@ -147,7 +152,7 @@ func unmarshalEditionDefaults(b []byte) {
 			_, m := protowire.ConsumeVarint(b)
 			b = b[m:]
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling EditionDefault", num))
 		}
 	}
 }
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
new file mode 100644
index 00000000..a12ec979
--- /dev/null
+++ b/history-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
@@ -0,0 +1,33 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package filedesc
+
+import "google.golang.org/protobuf/reflect/protoreflect"
+
+// UsePresenceForField reports whether the presence bitmap should be used for
+// the specified field.
+func UsePresenceForField(fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
+	switch {
+	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
+		// Oneof fields never use the presence bitmap.
+		//
+		// Synthetic oneofs are an exception: Those are used to implement proto3
+		// optional fields and hence should follow non-oneof field semantics.
+		return false, false
+
+	case fd.IsMap():
+		// Map-typed fields never use the presence bitmap.
+		return false, false
+
+	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
+		// Lazy fields always use the presence bitmap (only messages can be lazy).
+		isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
+		return isLazy, isLazy
+
+	default:
+		// If the field has presence, use the presence bitmap.
+		return fd.HasPresence(), false
+	}
+}
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go b/history-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
index df8f9185..3ceb6fa7 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
@@ -27,6 +27,7 @@ const (
 	Api_SourceContext_field_name protoreflect.Name = "source_context"
 	Api_Mixins_field_name        protoreflect.Name = "mixins"
 	Api_Syntax_field_name        protoreflect.Name = "syntax"
+	Api_Edition_field_name       protoreflect.Name = "edition"
 
 	Api_Name_field_fullname          protoreflect.FullName = "google.protobuf.Api.name"
 	Api_Methods_field_fullname       protoreflect.FullName = "google.protobuf.Api.methods"
@@ -35,6 +36,7 @@ const (
 	Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context"
 	Api_Mixins_field_fullname        protoreflect.FullName = "google.protobuf.Api.mixins"
 	Api_Syntax_field_fullname        protoreflect.FullName = "google.protobuf.Api.syntax"
+	Api_Edition_field_fullname       protoreflect.FullName = "google.protobuf.Api.edition"
 )
 
 // Field numbers for google.protobuf.Api.
@@ -46,6 +48,7 @@ const (
 	Api_SourceContext_field_number protoreflect.FieldNumber = 5
 	Api_Mixins_field_number        protoreflect.FieldNumber = 6
 	Api_Syntax_field_number        protoreflect.FieldNumber = 7
+	Api_Edition_field_number       protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Method.
@@ -63,6 +66,7 @@ const (
 	Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming"
 	Method_Options_field_name           protoreflect.Name = "options"
 	Method_Syntax_field_name            protoreflect.Name = "syntax"
+	Method_Edition_field_name           protoreflect.Name = "edition"
 
 	Method_Name_field_fullname              protoreflect.FullName = "google.protobuf.Method.name"
 	Method_RequestTypeUrl_field_fullname    protoreflect.FullName = "google.protobuf.Method.request_type_url"
@@ -71,6 +75,7 @@ const (
 	Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming"
 	Method_Options_field_fullname           protoreflect.FullName = "google.protobuf.Method.options"
 	Method_Syntax_field_fullname            protoreflect.FullName = "google.protobuf.Method.syntax"
+	Method_Edition_field_fullname           protoreflect.FullName = "google.protobuf.Method.edition"
 )
 
 // Field numbers for google.protobuf.Method.
@@ -82,6 +87,7 @@ const (
 	Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5
 	Method_Options_field_number           protoreflect.FieldNumber = 6
 	Method_Syntax_field_number            protoreflect.FieldNumber = 7
+	Method_Edition_field_number           protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Mixin.
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/history-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
index 39524782..950a6a32 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
@@ -34,6 +34,19 @@ const (
 	Edition_EDITION_MAX_enum_value             = 2147483647
 )
 
+// Full and short names for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_enum_fullname = "google.protobuf.SymbolVisibility"
+	SymbolVisibility_enum_name     = "SymbolVisibility"
+)
+
+// Enum values for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_VISIBILITY_UNSET_enum_value  = 0
+	SymbolVisibility_VISIBILITY_LOCAL_enum_value  = 1
+	SymbolVisibility_VISIBILITY_EXPORT_enum_value = 2
+)
+
 // Names for google.protobuf.FileDescriptorSet.
 const (
 	FileDescriptorSet_message_name     protoreflect.Name     = "FileDescriptorSet"
@@ -65,6 +78,7 @@ const (
 	FileDescriptorProto_Dependency_field_name       protoreflect.Name = "dependency"
 	FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency"
 	FileDescriptorProto_WeakDependency_field_name   protoreflect.Name = "weak_dependency"
+	FileDescriptorProto_OptionDependency_field_name protoreflect.Name = "option_dependency"
 	FileDescriptorProto_MessageType_field_name      protoreflect.Name = "message_type"
 	FileDescriptorProto_EnumType_field_name         protoreflect.Name = "enum_type"
 	FileDescriptorProto_Service_field_name          protoreflect.Name = "service"
@@ -79,6 +93,7 @@ const (
 	FileDescriptorProto_Dependency_field_fullname       protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency"
 	FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency"
 	FileDescriptorProto_WeakDependency_field_fullname   protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency"
+	FileDescriptorProto_OptionDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.option_dependency"
 	FileDescriptorProto_MessageType_field_fullname      protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type"
 	FileDescriptorProto_EnumType_field_fullname         protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type"
 	FileDescriptorProto_Service_field_fullname          protoreflect.FullName = "google.protobuf.FileDescriptorProto.service"
@@ -96,6 +111,7 @@ const (
 	FileDescriptorProto_Dependency_field_number       protoreflect.FieldNumber = 3
 	FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10
 	FileDescriptorProto_WeakDependency_field_number   protoreflect.FieldNumber = 11
+	FileDescriptorProto_OptionDependency_field_number protoreflect.FieldNumber = 15
 	FileDescriptorProto_MessageType_field_number      protoreflect.FieldNumber = 4
 	FileDescriptorProto_EnumType_field_number         protoreflect.FieldNumber = 5
 	FileDescriptorProto_Service_field_number          protoreflect.FieldNumber = 6
@@ -124,6 +140,7 @@ const (
 	DescriptorProto_Options_field_name        protoreflect.Name = "options"
 	DescriptorProto_ReservedRange_field_name  protoreflect.Name = "reserved_range"
 	DescriptorProto_ReservedName_field_name   protoreflect.Name = "reserved_name"
+	DescriptorProto_Visibility_field_name     protoreflect.Name = "visibility"
 
 	DescriptorProto_Name_field_fullname           protoreflect.FullName = "google.protobuf.DescriptorProto.name"
 	DescriptorProto_Field_field_fullname          protoreflect.FullName = "google.protobuf.DescriptorProto.field"
@@ -135,6 +152,7 @@ const (
 	DescriptorProto_Options_field_fullname        protoreflect.FullName = "google.protobuf.DescriptorProto.options"
 	DescriptorProto_ReservedRange_field_fullname  protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range"
 	DescriptorProto_ReservedName_field_fullname   protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name"
+	DescriptorProto_Visibility_field_fullname     protoreflect.FullName = "google.protobuf.DescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.DescriptorProto.
@@ -149,6 +167,7 @@ const (
 	DescriptorProto_Options_field_number        protoreflect.FieldNumber = 7
 	DescriptorProto_ReservedRange_field_number  protoreflect.FieldNumber = 9
 	DescriptorProto_ReservedName_field_number   protoreflect.FieldNumber = 10
+	DescriptorProto_Visibility_field_number     protoreflect.FieldNumber = 11
 )
 
 // Names for google.protobuf.DescriptorProto.ExtensionRange.
@@ -388,12 +407,14 @@ const (
 	EnumDescriptorProto_Options_field_name       protoreflect.Name = "options"
 	EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
 	EnumDescriptorProto_ReservedName_field_name  protoreflect.Name = "reserved_name"
+	EnumDescriptorProto_Visibility_field_name    protoreflect.Name = "visibility"
 
 	EnumDescriptorProto_Name_field_fullname          protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name"
 	EnumDescriptorProto_Value_field_fullname         protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value"
 	EnumDescriptorProto_Options_field_fullname       protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options"
 	EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range"
 	EnumDescriptorProto_ReservedName_field_fullname  protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name"
+	EnumDescriptorProto_Visibility_field_fullname    protoreflect.FullName = "google.protobuf.EnumDescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.EnumDescriptorProto.
@@ -403,6 +424,7 @@ const (
 	EnumDescriptorProto_Options_field_number       protoreflect.FieldNumber = 3
 	EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4
 	EnumDescriptorProto_ReservedName_field_number  protoreflect.FieldNumber = 5
+	EnumDescriptorProto_Visibility_field_number    protoreflect.FieldNumber = 6
 )
 
 // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
@@ -1008,32 +1030,35 @@ const (
 
 // Field names for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_name         protoreflect.Name = "field_presence"
-	FeatureSet_EnumType_field_name              protoreflect.Name = "enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_name        protoreflect.Name = "utf8_validation"
-	FeatureSet_MessageEncoding_field_name       protoreflect.Name = "message_encoding"
-	FeatureSet_JsonFormat_field_name            protoreflect.Name = "json_format"
-	FeatureSet_EnforceNamingStyle_field_name    protoreflect.Name = "enforce_naming_style"
-
-	FeatureSet_FieldPresence_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
-	FeatureSet_EnumType_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_fullname        protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
-	FeatureSet_MessageEncoding_field_fullname       protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
-	FeatureSet_JsonFormat_field_fullname            protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
-	FeatureSet_EnforceNamingStyle_field_fullname    protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_FieldPresence_field_name           protoreflect.Name = "field_presence"
+	FeatureSet_EnumType_field_name                protoreflect.Name = "enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_name   protoreflect.Name = "repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_name          protoreflect.Name = "utf8_validation"
+	FeatureSet_MessageEncoding_field_name         protoreflect.Name = "message_encoding"
+	FeatureSet_JsonFormat_field_name              protoreflect.Name = "json_format"
+	FeatureSet_EnforceNamingStyle_field_name      protoreflect.Name = "enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_name protoreflect.Name = "default_symbol_visibility"
+
+	FeatureSet_FieldPresence_field_fullname           protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
+	FeatureSet_EnumType_field_fullname                protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_fullname   protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_fullname          protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
+	FeatureSet_MessageEncoding_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
+	FeatureSet_JsonFormat_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
+	FeatureSet_EnforceNamingStyle_field_fullname      protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.default_symbol_visibility"
 )
 
 // Field numbers for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_number         protoreflect.FieldNumber = 1
-	FeatureSet_EnumType_field_number              protoreflect.FieldNumber = 2
-	FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
-	FeatureSet_Utf8Validation_field_number        protoreflect.FieldNumber = 4
-	FeatureSet_MessageEncoding_field_number       protoreflect.FieldNumber = 5
-	FeatureSet_JsonFormat_field_number            protoreflect.FieldNumber = 6
-	FeatureSet_EnforceNamingStyle_field_number    protoreflect.FieldNumber = 7
+	FeatureSet_FieldPresence_field_number           protoreflect.FieldNumber = 1
+	FeatureSet_EnumType_field_number                protoreflect.FieldNumber = 2
+	FeatureSet_RepeatedFieldEncoding_field_number   protoreflect.FieldNumber = 3
+	FeatureSet_Utf8Validation_field_number          protoreflect.FieldNumber = 4
+	FeatureSet_MessageEncoding_field_number         protoreflect.FieldNumber = 5
+	FeatureSet_JsonFormat_field_number              protoreflect.FieldNumber = 6
+	FeatureSet_EnforceNamingStyle_field_number      protoreflect.FieldNumber = 7
+	FeatureSet_DefaultSymbolVisibility_field_number protoreflect.FieldNumber = 8
 )
 
 // Full and short names for google.protobuf.FeatureSet.FieldPresence.
@@ -1128,6 +1153,27 @@ const (
 	FeatureSet_STYLE_LEGACY_enum_value                 = 2
 )
 
+// Names for google.protobuf.FeatureSet.VisibilityFeature.
+const (
+	FeatureSet_VisibilityFeature_message_name     protoreflect.Name     = "VisibilityFeature"
+	FeatureSet_VisibilityFeature_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet.VisibilityFeature"
+)
+
+// Full and short names for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_fullname = "google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility"
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_name     = "DefaultSymbolVisibility"
+)
+
+// Enum values for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN_enum_value = 0
+	FeatureSet_VisibilityFeature_EXPORT_ALL_enum_value                        = 1
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL_enum_value                  = 2
+	FeatureSet_VisibilityFeature_LOCAL_ALL_enum_value                         = 3
+	FeatureSet_VisibilityFeature_STRICT_enum_value                            = 4
+)
+
 // Names for google.protobuf.FeatureSetDefaults.
 const (
 	FeatureSetDefaults_message_name     protoreflect.Name     = "FeatureSetDefaults"
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/history-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
index 41c1f74e..bdad12a9 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
@@ -11,6 +11,7 @@ import (
 
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/encoding/messageset"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/order"
 	"google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -80,7 +81,7 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
 		// permit us to skip over definitely-unset fields at marshal time.
 
 		var hasPresence bool
-		hasPresence, cf.isLazy = usePresenceForField(si, fd)
+		hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
 
 		if hasPresence {
 			cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/history-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
index dd55e8e0..5a439daa 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"sync/atomic"
 
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
@@ -53,7 +54,7 @@ func opaqueInitHook(mi *MessageInfo) bool {
 		fd := fds.Get(i)
 		fs := si.fieldsByNumber[fd.Number()]
 		var fi fieldInfo
-		usePresence, _ := usePresenceForField(si, fd)
+		usePresence, _ := filedesc.UsePresenceForField(fd)
 
 		switch {
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
@@ -343,17 +344,15 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return false
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return false
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			return rv.Elem().Len() > 0
 		},
 		clear: func(p pointer) {
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if !sp.IsNil() {
-				rv := sp.AsValueOf(fs.Type.Elem())
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if !rv.IsNil() {
 				rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
 			}
 		},
@@ -361,11 +360,10 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return conv.Zero()
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return conv.Zero()
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			if rv.Elem().Len() == 0 {
 				return conv.Zero()
 			}
@@ -598,30 +596,3 @@ func (mi *MessageInfo) clearPresent(p pointer, index uint32) {
 func (mi *MessageInfo) present(p pointer, index uint32) bool {
 	return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
 }
-
-// usePresenceForField implements the somewhat intricate logic of when
-// the presence bitmap is used for a field.  The main logic is that a
-// field that is optional or that can be lazy will use the presence
-// bit, but for proto2, also maps have a presence bit. It also records
-// if the field can ever be lazy, which is true if we have a
-// lazyOffset and the field is a message or a slice of messages. A
-// field that is lazy will always need a presence bit.  Oneofs are not
-// lazy and do not use presence, unless they are a synthetic oneof,
-// which is a proto3 optional field. For proto3 optionals, we use the
-// presence and they can also be lazy when applicable (a message).
-func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
-	hasLazyField := fd.(interface{ IsLazy() bool }).IsLazy()
-
-	// Non-oneof scalar fields with explicit field presence use the presence array.
-	usesPresenceArray := fd.HasPresence() && fd.Message() == nil && (fd.ContainingOneof() == nil || fd.ContainingOneof().IsSynthetic())
-	switch {
-	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
-		return false, false
-	case fd.IsMap():
-		return false, false
-	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
-		return hasLazyField, hasLazyField
-	default:
-		return usesPresenceArray || (hasLazyField && fd.HasPresence()), false
-	}
-}
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/impl/presence.go b/history-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
index 914cb1de..443afe81 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
@@ -32,9 +32,6 @@ func (p presence) toElem(num uint32) (ret *uint32) {
 
 // Present checks for the presence of a specific field number in a presence set.
 func (p presence) Present(num uint32) bool {
-	if p.P == nil {
-		return false
-	}
 	return Export{}.Present(p.toElem(num), num)
 }
 
diff --git a/history-api/vendor/google.golang.org/protobuf/internal/version/version.go b/history-api/vendor/google.golang.org/protobuf/internal/version/version.go
index aac1cb18..77de0f23 100644
--- a/history-api/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/history-api/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -52,7 +52,7 @@ import (
 const (
 	Major      = 1
 	Minor      = 36
-	Patch      = 6
+	Patch      = 10
 	PreRelease = ""
 )
 
diff --git a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
index 823dbf3b..9196288e 100644
--- a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
+++ b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
@@ -152,6 +152,28 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
 		imp := &f.L2.Imports[i]
 		imps.importPublic(imp.Imports())
 	}
+	if len(fd.GetOptionDependency()) > 0 {
+		optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency()))
+		for i, path := range fd.GetOptionDependency() {
+			imp := &optionImports[i]
+			f, err := r.FindFileByPath(path)
+			if err == protoregistry.NotFound {
+				// We always allow option imports to be unresolvable.
+				f = filedesc.PlaceholderFile(path)
+			} else if err != nil {
+				return nil, errors.New("could not resolve import %q: %v", path, err)
+			}
+			imp.FileDescriptor = f
+
+			if imps[imp.Path()] {
+				return nil, errors.New("already imported %q", path)
+			}
+			imps[imp.Path()] = true
+		}
+		f.L2.OptionImports = func() protoreflect.FileImports {
+			return &optionImports
+		}
+	}
 
 	// Handle source locations.
 	f.L2.Locations.File = f
diff --git a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
index 9da34998..c826ad04 100644
--- a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
+++ b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
@@ -29,6 +29,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
 			e.L2.Options = func() protoreflect.ProtoMessage { return opts }
 		}
 		e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
+		e.L1.Visibility = int32(ed.GetVisibility())
 		for _, s := range ed.GetReservedName() {
 			e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
 		}
@@ -70,6 +71,7 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
 			return nil, err
 		}
 		m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
+		m.L1.Visibility = int32(md.GetVisibility())
 		if opts := md.GetOptions(); opts != nil {
 			opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
 			m.L2.Options = func() protoreflect.ProtoMessage { return opts }
diff --git a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
index 9b880aa8..6f91074e 100644
--- a/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
+++ b/history-api/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
@@ -70,16 +70,27 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
 	if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
 		p.Syntax = proto.String(file.Syntax().String())
 	}
+	desc := file
+	if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
+		desc = fileImportDesc.FileDescriptor
+	}
 	if file.Syntax() == protoreflect.Editions {
-		desc := file
-		if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
-			desc = fileImportDesc.FileDescriptor
-		}
-
 		if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok {
 			p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum()
 		}
 	}
+	type hasOptionImports interface {
+		OptionImports() protoreflect.FileImports
+	}
+	if opts, ok := desc.(hasOptionImports); ok {
+		if optionImports := opts.OptionImports(); optionImports.Len() > 0 {
+			optionDeps := make([]string, optionImports.Len())
+			for i := range optionImports.Len() {
+				optionDeps[i] = optionImports.Get(i).Path()
+			}
+			p.OptionDependency = optionDeps
+		}
+	}
 	return p
 }
 
@@ -123,6 +134,14 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
 	for i, names := 0, message.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := message.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
@@ -216,6 +235,14 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
 	for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := enum.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
diff --git a/history-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/history-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
index a4a0a297..730331e6 100644
--- a/history-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
+++ b/history-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
@@ -21,6 +21,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "public_dependency", nil)
 	case 11:
 		b = p.appendRepeatedField(b, "weak_dependency", nil)
+	case 15:
+		b = p.appendRepeatedField(b, "option_dependency", nil)
 	case 4:
 		b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto)
 	case 5:
@@ -66,6 +68,8 @@ func (p *SourcePath) appendDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange)
 	case 10:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 11:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -85,6 +89,8 @@ func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange)
 	case 5:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 6:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -400,6 +406,8 @@ func (p *SourcePath) appendFeatureSet(b []byte) []byte {
 		b = p.appendSingularField(b, "json_format", nil)
 	case 7:
 		b = p.appendSingularField(b, "enforce_naming_style", nil)
+	case 8:
+		b = p.appendSingularField(b, "default_symbol_visibility", nil)
 	}
 	return b
 }
diff --git a/history-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/history-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
index 7fe280f1..4eacb523 100644
--- a/history-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
+++ b/history-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
@@ -151,6 +151,70 @@ func (Edition) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0}
 }
 
+// Describes the 'visibility' of a symbol with respect to the proto import
+// system. Symbols can only be imported when the visibility rules do not prevent
+// it (ex: local symbols cannot be imported).  Visibility modifiers can only set
+// on `message` and `enum` as they are the only types available to be referenced
+// from other files.
+type SymbolVisibility int32
+
+const (
+	SymbolVisibility_VISIBILITY_UNSET  SymbolVisibility = 0
+	SymbolVisibility_VISIBILITY_LOCAL  SymbolVisibility = 1
+	SymbolVisibility_VISIBILITY_EXPORT SymbolVisibility = 2
+)
+
+// Enum value maps for SymbolVisibility.
+var (
+	SymbolVisibility_name = map[int32]string{
+		0: "VISIBILITY_UNSET",
+		1: "VISIBILITY_LOCAL",
+		2: "VISIBILITY_EXPORT",
+	}
+	SymbolVisibility_value = map[string]int32{
+		"VISIBILITY_UNSET":  0,
+		"VISIBILITY_LOCAL":  1,
+		"VISIBILITY_EXPORT": 2,
+	}
+)
+
+func (x SymbolVisibility) Enum() *SymbolVisibility {
+	p := new(SymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x SymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+}
+
+func (SymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+}
+
+func (x SymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *SymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = SymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use SymbolVisibility.Descriptor instead.
+func (SymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1}
+}
+
 // The verification state of the extension range.
 type ExtensionRangeOptions_VerificationState int32
 
@@ -183,11 +247,11 @@ func (x ExtensionRangeOptions_VerificationState) String() string {
 }
 
 func (ExtensionRangeOptions_VerificationState) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
 }
 
 func (ExtensionRangeOptions_VerificationState) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+	return &file_google_protobuf_descriptor_proto_enumTypes[2]
 }
 
 func (x ExtensionRangeOptions_VerificationState) Number() protoreflect.EnumNumber {
@@ -299,11 +363,11 @@ func (x FieldDescriptorProto_Type) String() string {
 }
 
 func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
 }
 
 func (FieldDescriptorProto_Type) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[2]
+	return &file_google_protobuf_descriptor_proto_enumTypes[3]
 }
 
 func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber {
@@ -362,11 +426,11 @@ func (x FieldDescriptorProto_Label) String() string {
 }
 
 func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
 }
 
 func (FieldDescriptorProto_Label) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[3]
+	return &file_google_protobuf_descriptor_proto_enumTypes[4]
 }
 
 func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber {
@@ -423,11 +487,11 @@ func (x FileOptions_OptimizeMode) String() string {
 }
 
 func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
 }
 
 func (FileOptions_OptimizeMode) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[4]
+	return &file_google_protobuf_descriptor_proto_enumTypes[5]
 }
 
 func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber {
@@ -489,11 +553,11 @@ func (x FieldOptions_CType) String() string {
 }
 
 func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
 }
 
 func (FieldOptions_CType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[5]
+	return &file_google_protobuf_descriptor_proto_enumTypes[6]
 }
 
 func (x FieldOptions_CType) Number() protoreflect.EnumNumber {
@@ -551,11 +615,11 @@ func (x FieldOptions_JSType) String() string {
 }
 
 func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
 }
 
 func (FieldOptions_JSType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[6]
+	return &file_google_protobuf_descriptor_proto_enumTypes[7]
 }
 
 func (x FieldOptions_JSType) Number() protoreflect.EnumNumber {
@@ -611,11 +675,11 @@ func (x FieldOptions_OptionRetention) String() string {
 }
 
 func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
 }
 
 func (FieldOptions_OptionRetention) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[7]
+	return &file_google_protobuf_descriptor_proto_enumTypes[8]
 }
 
 func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber {
@@ -694,11 +758,11 @@ func (x FieldOptions_OptionTargetType) String() string {
 }
 
 func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
 }
 
 func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[8]
+	return &file_google_protobuf_descriptor_proto_enumTypes[9]
 }
 
 func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber {
@@ -756,11 +820,11 @@ func (x MethodOptions_IdempotencyLevel) String() string {
 }
 
 func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
 }
 
 func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[9]
+	return &file_google_protobuf_descriptor_proto_enumTypes[10]
 }
 
 func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber {
@@ -818,11 +882,11 @@ func (x FeatureSet_FieldPresence) String() string {
 }
 
 func (FeatureSet_FieldPresence) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
 }
 
 func (FeatureSet_FieldPresence) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[10]
+	return &file_google_protobuf_descriptor_proto_enumTypes[11]
 }
 
 func (x FeatureSet_FieldPresence) Number() protoreflect.EnumNumber {
@@ -877,11 +941,11 @@ func (x FeatureSet_EnumType) String() string {
 }
 
 func (FeatureSet_EnumType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
 }
 
 func (FeatureSet_EnumType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[11]
+	return &file_google_protobuf_descriptor_proto_enumTypes[12]
 }
 
 func (x FeatureSet_EnumType) Number() protoreflect.EnumNumber {
@@ -936,11 +1000,11 @@ func (x FeatureSet_RepeatedFieldEncoding) String() string {
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[12]
+	return &file_google_protobuf_descriptor_proto_enumTypes[13]
 }
 
 func (x FeatureSet_RepeatedFieldEncoding) Number() protoreflect.EnumNumber {
@@ -995,11 +1059,11 @@ func (x FeatureSet_Utf8Validation) String() string {
 }
 
 func (FeatureSet_Utf8Validation) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
 }
 
 func (FeatureSet_Utf8Validation) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[13]
+	return &file_google_protobuf_descriptor_proto_enumTypes[14]
 }
 
 func (x FeatureSet_Utf8Validation) Number() protoreflect.EnumNumber {
@@ -1054,11 +1118,11 @@ func (x FeatureSet_MessageEncoding) String() string {
 }
 
 func (FeatureSet_MessageEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
 }
 
 func (FeatureSet_MessageEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[14]
+	return &file_google_protobuf_descriptor_proto_enumTypes[15]
 }
 
 func (x FeatureSet_MessageEncoding) Number() protoreflect.EnumNumber {
@@ -1113,11 +1177,11 @@ func (x FeatureSet_JsonFormat) String() string {
 }
 
 func (FeatureSet_JsonFormat) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
 }
 
 func (FeatureSet_JsonFormat) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[15]
+	return &file_google_protobuf_descriptor_proto_enumTypes[16]
 }
 
 func (x FeatureSet_JsonFormat) Number() protoreflect.EnumNumber {
@@ -1172,11 +1236,11 @@ func (x FeatureSet_EnforceNamingStyle) String() string {
 }
 
 func (FeatureSet_EnforceNamingStyle) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
 }
 
 func (FeatureSet_EnforceNamingStyle) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[16]
+	return &file_google_protobuf_descriptor_proto_enumTypes[17]
 }
 
 func (x FeatureSet_EnforceNamingStyle) Number() protoreflect.EnumNumber {
@@ -1198,6 +1262,77 @@ func (FeatureSet_EnforceNamingStyle) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 6}
 }
 
+type FeatureSet_VisibilityFeature_DefaultSymbolVisibility int32
+
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 0
+	// Default pre-EDITION_2024, all UNSET visibility are export.
+	FeatureSet_VisibilityFeature_EXPORT_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 1
+	// All top-level symbols default to export, nested default to local.
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 2
+	// All symbols default to local.
+	FeatureSet_VisibilityFeature_LOCAL_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 3
+	// All symbols local by default. Nested types cannot be exported.
+	// With special case caveat for message { enum {} reserved 1 to max; }
+	// This is the recommended setting for new protos.
+	FeatureSet_VisibilityFeature_STRICT FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 4
+)
+
+// Enum value maps for FeatureSet_VisibilityFeature_DefaultSymbolVisibility.
+var (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_name = map[int32]string{
+		0: "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN",
+		1: "EXPORT_ALL",
+		2: "EXPORT_TOP_LEVEL",
+		3: "LOCAL_ALL",
+		4: "STRICT",
+	}
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_value = map[string]int32{
+		"DEFAULT_SYMBOL_VISIBILITY_UNKNOWN": 0,
+		"EXPORT_ALL":                        1,
+		"EXPORT_TOP_LEVEL":                  2,
+		"LOCAL_ALL":                         3,
+		"STRICT":                            4,
+	}
+)
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Enum() *FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	p := new(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[18].Descriptor()
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[18]
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_VisibilityFeature_DefaultSymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = FeatureSet_VisibilityFeature_DefaultSymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature_DefaultSymbolVisibility.Descriptor instead.
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0, 0}
+}
+
 // Represents the identified object's effect on the element in the original
 // .proto file.
 type GeneratedCodeInfo_Annotation_Semantic int32
@@ -1236,11 +1371,11 @@ func (x GeneratedCodeInfo_Annotation_Semantic) String() string {
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[19].Descriptor()
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[17]
+	return &file_google_protobuf_descriptor_proto_enumTypes[19]
 }
 
 func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber {
@@ -1321,6 +1456,9 @@ type FileDescriptorProto struct {
 	// Indexes of the weak imported files in the dependency list.
 	// For Google-internal migration only. Do not use.
 	WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+	// Names of files imported by this file purely for the purpose of providing
+	// option extensions. These are excluded from the dependency list above.
+	OptionDependency []string `protobuf:"bytes,15,rep,name=option_dependency,json=optionDependency" json:"option_dependency,omitempty"`
 	// All top-level definitions in this file.
 	MessageType []*DescriptorProto        `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
 	EnumType    []*EnumDescriptorProto    `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
@@ -1414,6 +1552,13 @@ func (x *FileDescriptorProto) GetWeakDependency() []int32 {
 	return nil
 }
 
+func (x *FileDescriptorProto) GetOptionDependency() []string {
+	if x != nil {
+		return x.OptionDependency
+	}
+	return nil
+}
+
 func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto {
 	if x != nil {
 		return x.MessageType
@@ -1484,7 +1629,9 @@ type DescriptorProto struct {
 	ReservedRange  []*DescriptorProto_ReservedRange  `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved field names, which may not be used by fields in the same message.
 	// A given name may only be reserved once.
-	ReservedName  []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,11,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1589,6 +1736,13 @@ func (x *DescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *DescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 type ExtensionRangeOptions struct {
 	state protoimpl.MessageState `protogen:"open.v1"`
 	// The parser stores options it doesn't recognize here. See above.
@@ -1901,7 +2055,9 @@ type EnumDescriptorProto struct {
 	ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved enum value names, which may not be reused. A given name may only
 	// be reserved once.
-	ReservedName  []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,6,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1971,6 +2127,13 @@ func (x *EnumDescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *EnumDescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 // Describes a value within an enum.
 type EnumValueDescriptorProto struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
@@ -2710,7 +2873,10 @@ type FieldOptions struct {
 	// for accessors, or it will be completely ignored; in the very least, this
 	// is a formalization for deprecating fields.
 	Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+	// DEPRECATED. DO NOT USE!
 	// For Google-internal migration only. Do not use.
+	//
+	// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 	Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
 	// Indicate that the field value should not be printed out when using debug
 	// formats, e.g. when the field contains sensitive credentials.
@@ -2814,6 +2980,7 @@ func (x *FieldOptions) GetDeprecated() bool {
 	return Default_FieldOptions_Deprecated
 }
 
+// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 func (x *FieldOptions) GetWeak() bool {
 	if x != nil && x.Weak != nil {
 		return *x.Weak
@@ -3392,17 +3559,18 @@ func (x *UninterpretedOption) GetAggregateValue() string {
 // be designed and implemented to handle this, hopefully before we ever hit a
 // conflict here.
 type FeatureSet struct {
-	state                 protoimpl.MessageState            `protogen:"open.v1"`
-	FieldPresence         *FeatureSet_FieldPresence         `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
-	EnumType              *FeatureSet_EnumType              `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
-	RepeatedFieldEncoding *FeatureSet_RepeatedFieldEncoding `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
-	Utf8Validation        *FeatureSet_Utf8Validation        `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
-	MessageEncoding       *FeatureSet_MessageEncoding       `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
-	JsonFormat            *FeatureSet_JsonFormat            `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
-	EnforceNamingStyle    *FeatureSet_EnforceNamingStyle    `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
-	extensionFields       protoimpl.ExtensionFields
-	unknownFields         protoimpl.UnknownFields
-	sizeCache             protoimpl.SizeCache
+	state                   protoimpl.MessageState                                `protogen:"open.v1"`
+	FieldPresence           *FeatureSet_FieldPresence                             `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
+	EnumType                *FeatureSet_EnumType                                  `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
+	RepeatedFieldEncoding   *FeatureSet_RepeatedFieldEncoding                     `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
+	Utf8Validation          *FeatureSet_Utf8Validation                            `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
+	MessageEncoding         *FeatureSet_MessageEncoding                           `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
+	JsonFormat              *FeatureSet_JsonFormat                                `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
+	EnforceNamingStyle      *FeatureSet_EnforceNamingStyle                        `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
+	DefaultSymbolVisibility *FeatureSet_VisibilityFeature_DefaultSymbolVisibility `protobuf:"varint,8,opt,name=default_symbol_visibility,json=defaultSymbolVisibility,enum=google.protobuf.FeatureSet_VisibilityFeature_DefaultSymbolVisibility" json:"default_symbol_visibility,omitempty"`
+	extensionFields         protoimpl.ExtensionFields
+	unknownFields           protoimpl.UnknownFields
+	sizeCache               protoimpl.SizeCache
 }
 
 func (x *FeatureSet) Reset() {
@@ -3484,6 +3652,13 @@ func (x *FeatureSet) GetEnforceNamingStyle() FeatureSet_EnforceNamingStyle {
 	return FeatureSet_ENFORCE_NAMING_STYLE_UNKNOWN
 }
 
+func (x *FeatureSet) GetDefaultSymbolVisibility() FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	if x != nil && x.DefaultSymbolVisibility != nil {
+		return *x.DefaultSymbolVisibility
+	}
+	return FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN
+}
+
 // A compiled specification for the defaults of a set of features.  These
 // messages are generated from FeatureSet extensions and can be used to seed
 // feature resolution. The resolution with this object becomes a simple search
@@ -4144,6 +4319,42 @@ func (x *UninterpretedOption_NamePart) GetIsExtension() bool {
 	return false
 }
 
+type FeatureSet_VisibilityFeature struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *FeatureSet_VisibilityFeature) Reset() {
+	*x = FeatureSet_VisibilityFeature{}
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *FeatureSet_VisibilityFeature) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSet_VisibilityFeature) ProtoMessage() {}
+
+func (x *FeatureSet_VisibilityFeature) ProtoReflect() protoreflect.Message {
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature.ProtoReflect.Descriptor instead.
+func (*FeatureSet_VisibilityFeature) Descriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+}
+
 // A map from every known edition with a unique set of defaults to its
 // defaults. Not all editions may be contained here.  For a given edition,
 // the defaults at the closest matching edition ordered at or before it should
@@ -4161,7 +4372,7 @@ type FeatureSetDefaults_FeatureSetEditionDefault struct {
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() {
 	*x = FeatureSetDefaults_FeatureSetEditionDefault{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4173,7 +4384,7 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string {
 func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {}
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4309,7 +4520,7 @@ type SourceCodeInfo_Location struct {
 
 func (x *SourceCodeInfo_Location) Reset() {
 	*x = SourceCodeInfo_Location{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4321,7 +4532,7 @@ func (x *SourceCodeInfo_Location) String() string {
 func (*SourceCodeInfo_Location) ProtoMessage() {}
 
 func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4393,7 +4604,7 @@ type GeneratedCodeInfo_Annotation struct {
 
 func (x *GeneratedCodeInfo_Annotation) Reset() {
 	*x = GeneratedCodeInfo_Annotation{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4405,7 +4616,7 @@ func (x *GeneratedCodeInfo_Annotation) String() string {
 func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
 
 func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4462,7 +4673,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\n" +
 	" google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"[\n" +
 	"\x11FileDescriptorSet\x128\n" +
-	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\x98\x05\n" +
+	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\xc5\x05\n" +
 	"\x13FileDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
 	"\apackage\x18\x02 \x01(\tR\apackage\x12\x1e\n" +
@@ -4471,7 +4682,8 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"dependency\x12+\n" +
 	"\x11public_dependency\x18\n" +
 	" \x03(\x05R\x10publicDependency\x12'\n" +
-	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12C\n" +
+	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12+\n" +
+	"\x11option_dependency\x18\x0f \x03(\tR\x10optionDependency\x12C\n" +
 	"\fmessage_type\x18\x04 \x03(\v2 .google.protobuf.DescriptorProtoR\vmessageType\x12A\n" +
 	"\tenum_type\x18\x05 \x03(\v2$.google.protobuf.EnumDescriptorProtoR\benumType\x12A\n" +
 	"\aservice\x18\x06 \x03(\v2'.google.protobuf.ServiceDescriptorProtoR\aservice\x12C\n" +
@@ -4479,7 +4691,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\b \x01(\v2\x1c.google.protobuf.FileOptionsR\aoptions\x12I\n" +
 	"\x10source_code_info\x18\t \x01(\v2\x1f.google.protobuf.SourceCodeInfoR\x0esourceCodeInfo\x12\x16\n" +
 	"\x06syntax\x18\f \x01(\tR\x06syntax\x122\n" +
-	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xb9\x06\n" +
+	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xfc\x06\n" +
 	"\x0fDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12;\n" +
 	"\x05field\x18\x02 \x03(\v2%.google.protobuf.FieldDescriptorProtoR\x05field\x12C\n" +
@@ -4493,7 +4705,10 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\a \x01(\v2\x1f.google.protobuf.MessageOptionsR\aoptions\x12U\n" +
 	"\x0ereserved_range\x18\t \x03(\v2..google.protobuf.DescriptorProto.ReservedRangeR\rreservedRange\x12#\n" +
 	"\rreserved_name\x18\n" +
-	" \x03(\tR\freservedName\x1az\n" +
+	" \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\v \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1az\n" +
 	"\x0eExtensionRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\x12@\n" +
@@ -4562,13 +4777,16 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0eLABEL_REQUIRED\x10\x02\"c\n" +
 	"\x14OneofDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x127\n" +
-	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xe3\x02\n" +
+	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xa6\x03\n" +
 	"\x13EnumDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12?\n" +
 	"\x05value\x18\x02 \x03(\v2).google.protobuf.EnumValueDescriptorProtoR\x05value\x126\n" +
 	"\aoptions\x18\x03 \x01(\v2\x1c.google.protobuf.EnumOptionsR\aoptions\x12]\n" +
 	"\x0ereserved_range\x18\x04 \x03(\v26.google.protobuf.EnumDescriptorProto.EnumReservedRangeR\rreservedRange\x12#\n" +
-	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x1a;\n" +
+	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\x06 \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1a;\n" +
 	"\x11EnumReservedRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\"\x83\x01\n" +
@@ -4629,7 +4847,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"&deprecated_legacy_json_field_conflicts\x18\v \x01(\bB\x02\x18\x01R\"deprecatedLegacyJsonFieldConflicts\x127\n" +
 	"\bfeatures\x18\f \x01(\v2\x1b.google.protobuf.FeatureSetR\bfeatures\x12X\n" +
 	"\x14uninterpreted_option\x18\xe7\a \x03(\v2$.google.protobuf.UninterpretedOptionR\x13uninterpretedOption*\t\b\xe8\a\x10\x80\x80\x80\x80\x02J\x04\b\x04\x10\x05J\x04\b\x05\x10\x06J\x04\b\x06\x10\aJ\x04\b\b\x10\tJ\x04\b\t\x10\n" +
-	"\"\x9d\r\n" +
+	"\"\xa1\r\n" +
 	"\fFieldOptions\x12A\n" +
 	"\x05ctype\x18\x01 \x01(\x0e2#.google.protobuf.FieldOptions.CType:\x06STRINGR\x05ctype\x12\x16\n" +
 	"\x06packed\x18\x02 \x01(\bR\x06packed\x12G\n" +
@@ -4638,9 +4856,9 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0funverified_lazy\x18\x0f \x01(\b:\x05falseR\x0eunverifiedLazy\x12%\n" +
 	"\n" +
 	"deprecated\x18\x03 \x01(\b:\x05falseR\n" +
-	"deprecated\x12\x19\n" +
+	"deprecated\x12\x1d\n" +
 	"\x04weak\x18\n" +
-	" \x01(\b:\x05falseR\x04weak\x12(\n" +
+	" \x01(\b:\x05falseB\x02\x18\x01R\x04weak\x12(\n" +
 	"\fdebug_redact\x18\x10 \x01(\b:\x05falseR\vdebugRedact\x12K\n" +
 	"\tretention\x18\x11 \x01(\x0e2-.google.protobuf.FieldOptions.OptionRetentionR\tretention\x12H\n" +
 	"\atargets\x18\x13 \x03(\x0e2..google.protobuf.FieldOptions.OptionTargetTypeR\atargets\x12W\n" +
@@ -4728,7 +4946,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0faggregate_value\x18\b \x01(\tR\x0eaggregateValue\x1aJ\n" +
 	"\bNamePart\x12\x1b\n" +
 	"\tname_part\x18\x01 \x02(\tR\bnamePart\x12!\n" +
-	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\xae\f\n" +
+	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\x8e\x0f\n" +
 	"\n" +
 	"FeatureSet\x12\x91\x01\n" +
 	"\x0efield_presence\x18\x01 \x01(\x0e2).google.protobuf.FeatureSet.FieldPresenceB?\x88\x01\x01\x98\x01\x04\x98\x01\x01\xa2\x01\r\x12\bEXPLICIT\x18\x84\a\xa2\x01\r\x12\bIMPLICIT\x18\xe7\a\xa2\x01\r\x12\bEXPLICIT\x18\xe8\a\xb2\x01\x03\b\xe8\aR\rfieldPresence\x12l\n" +
@@ -4739,7 +4957,18 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\vjson_format\x18\x06 \x01(\x0e2&.google.protobuf.FeatureSet.JsonFormatB9\x88\x01\x01\x98\x01\x03\x98\x01\x06\x98\x01\x01\xa2\x01\x17\x12\x12LEGACY_BEST_EFFORT\x18\x84\a\xa2\x01\n" +
 	"\x12\x05ALLOW\x18\xe7\a\xb2\x01\x03\b\xe8\aR\n" +
 	"jsonFormat\x12\xab\x01\n" +
-	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\"\\\n" +
+	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\x12\xb9\x01\n" +
+	"\x19default_symbol_visibility\x18\b \x01(\x0e2E.google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibilityB6\x88\x01\x02\x98\x01\x01\xa2\x01\x0f\x12\n" +
+	"EXPORT_ALL\x18\x84\a\xa2\x01\x15\x12\x10EXPORT_TOP_LEVEL\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x17defaultSymbolVisibility\x1a\xa1\x01\n" +
+	"\x11VisibilityFeature\"\x81\x01\n" +
+	"\x17DefaultSymbolVisibility\x12%\n" +
+	"!DEFAULT_SYMBOL_VISIBILITY_UNKNOWN\x10\x00\x12\x0e\n" +
+	"\n" +
+	"EXPORT_ALL\x10\x01\x12\x14\n" +
+	"\x10EXPORT_TOP_LEVEL\x10\x02\x12\r\n" +
+	"\tLOCAL_ALL\x10\x03\x12\n" +
+	"\n" +
+	"\x06STRICT\x10\x04J\b\b\x01\x10\x80\x80\x80\x80\x02\"\\\n" +
 	"\rFieldPresence\x12\x1a\n" +
 	"\x16FIELD_PRESENCE_UNKNOWN\x10\x00\x12\f\n" +
 	"\bEXPLICIT\x10\x01\x12\f\n" +
@@ -4817,7 +5046,11 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99998_TEST_ONLY\x10\x9e\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99999_TEST_ONLY\x10\x9f\x8d\x06\x12\x13\n" +
-	"\vEDITION_MAX\x10\xff\xff\xff\xff\aB~\n" +
+	"\vEDITION_MAX\x10\xff\xff\xff\xff\a*U\n" +
+	"\x10SymbolVisibility\x12\x14\n" +
+	"\x10VISIBILITY_UNSET\x10\x00\x12\x14\n" +
+	"\x10VISIBILITY_LOCAL\x10\x01\x12\x15\n" +
+	"\x11VISIBILITY_EXPORT\x10\x02B~\n" +
 	"\x13com.google.protobufB\x10DescriptorProtosH\x01Z-google.golang.org/protobuf/types/descriptorpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection"
 
 var (
@@ -4832,145 +5065,151 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte {
 	return file_google_protobuf_descriptor_proto_rawDescData
 }
 
-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 18)
-var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 20)
+var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
 var file_google_protobuf_descriptor_proto_goTypes = []any{
-	(Edition)(0), // 0: google.protobuf.Edition
-	(ExtensionRangeOptions_VerificationState)(0),        // 1: google.protobuf.ExtensionRangeOptions.VerificationState
-	(FieldDescriptorProto_Type)(0),                      // 2: google.protobuf.FieldDescriptorProto.Type
-	(FieldDescriptorProto_Label)(0),                     // 3: google.protobuf.FieldDescriptorProto.Label
-	(FileOptions_OptimizeMode)(0),                       // 4: google.protobuf.FileOptions.OptimizeMode
-	(FieldOptions_CType)(0),                             // 5: google.protobuf.FieldOptions.CType
-	(FieldOptions_JSType)(0),                            // 6: google.protobuf.FieldOptions.JSType
-	(FieldOptions_OptionRetention)(0),                   // 7: google.protobuf.FieldOptions.OptionRetention
-	(FieldOptions_OptionTargetType)(0),                  // 8: google.protobuf.FieldOptions.OptionTargetType
-	(MethodOptions_IdempotencyLevel)(0),                 // 9: google.protobuf.MethodOptions.IdempotencyLevel
-	(FeatureSet_FieldPresence)(0),                       // 10: google.protobuf.FeatureSet.FieldPresence
-	(FeatureSet_EnumType)(0),                            // 11: google.protobuf.FeatureSet.EnumType
-	(FeatureSet_RepeatedFieldEncoding)(0),               // 12: google.protobuf.FeatureSet.RepeatedFieldEncoding
-	(FeatureSet_Utf8Validation)(0),                      // 13: google.protobuf.FeatureSet.Utf8Validation
-	(FeatureSet_MessageEncoding)(0),                     // 14: google.protobuf.FeatureSet.MessageEncoding
-	(FeatureSet_JsonFormat)(0),                          // 15: google.protobuf.FeatureSet.JsonFormat
-	(FeatureSet_EnforceNamingStyle)(0),                  // 16: google.protobuf.FeatureSet.EnforceNamingStyle
-	(GeneratedCodeInfo_Annotation_Semantic)(0),          // 17: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	(*FileDescriptorSet)(nil),                           // 18: google.protobuf.FileDescriptorSet
-	(*FileDescriptorProto)(nil),                         // 19: google.protobuf.FileDescriptorProto
-	(*DescriptorProto)(nil),                             // 20: google.protobuf.DescriptorProto
-	(*ExtensionRangeOptions)(nil),                       // 21: google.protobuf.ExtensionRangeOptions
-	(*FieldDescriptorProto)(nil),                        // 22: google.protobuf.FieldDescriptorProto
-	(*OneofDescriptorProto)(nil),                        // 23: google.protobuf.OneofDescriptorProto
-	(*EnumDescriptorProto)(nil),                         // 24: google.protobuf.EnumDescriptorProto
-	(*EnumValueDescriptorProto)(nil),                    // 25: google.protobuf.EnumValueDescriptorProto
-	(*ServiceDescriptorProto)(nil),                      // 26: google.protobuf.ServiceDescriptorProto
-	(*MethodDescriptorProto)(nil),                       // 27: google.protobuf.MethodDescriptorProto
-	(*FileOptions)(nil),                                 // 28: google.protobuf.FileOptions
-	(*MessageOptions)(nil),                              // 29: google.protobuf.MessageOptions
-	(*FieldOptions)(nil),                                // 30: google.protobuf.FieldOptions
-	(*OneofOptions)(nil),                                // 31: google.protobuf.OneofOptions
-	(*EnumOptions)(nil),                                 // 32: google.protobuf.EnumOptions
-	(*EnumValueOptions)(nil),                            // 33: google.protobuf.EnumValueOptions
-	(*ServiceOptions)(nil),                              // 34: google.protobuf.ServiceOptions
-	(*MethodOptions)(nil),                               // 35: google.protobuf.MethodOptions
-	(*UninterpretedOption)(nil),                         // 36: google.protobuf.UninterpretedOption
-	(*FeatureSet)(nil),                                  // 37: google.protobuf.FeatureSet
-	(*FeatureSetDefaults)(nil),                          // 38: google.protobuf.FeatureSetDefaults
-	(*SourceCodeInfo)(nil),                              // 39: google.protobuf.SourceCodeInfo
-	(*GeneratedCodeInfo)(nil),                           // 40: google.protobuf.GeneratedCodeInfo
-	(*DescriptorProto_ExtensionRange)(nil),              // 41: google.protobuf.DescriptorProto.ExtensionRange
-	(*DescriptorProto_ReservedRange)(nil),               // 42: google.protobuf.DescriptorProto.ReservedRange
-	(*ExtensionRangeOptions_Declaration)(nil),           // 43: google.protobuf.ExtensionRangeOptions.Declaration
-	(*EnumDescriptorProto_EnumReservedRange)(nil),       // 44: google.protobuf.EnumDescriptorProto.EnumReservedRange
-	(*FieldOptions_EditionDefault)(nil),                 // 45: google.protobuf.FieldOptions.EditionDefault
-	(*FieldOptions_FeatureSupport)(nil),                 // 46: google.protobuf.FieldOptions.FeatureSupport
-	(*UninterpretedOption_NamePart)(nil),                // 47: google.protobuf.UninterpretedOption.NamePart
-	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 48: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	(*SourceCodeInfo_Location)(nil),                     // 49: google.protobuf.SourceCodeInfo.Location
-	(*GeneratedCodeInfo_Annotation)(nil),                // 50: google.protobuf.GeneratedCodeInfo.Annotation
+	(Edition)(0),          // 0: google.protobuf.Edition
+	(SymbolVisibility)(0), // 1: google.protobuf.SymbolVisibility
+	(ExtensionRangeOptions_VerificationState)(0),              // 2: google.protobuf.ExtensionRangeOptions.VerificationState
+	(FieldDescriptorProto_Type)(0),                            // 3: google.protobuf.FieldDescriptorProto.Type
+	(FieldDescriptorProto_Label)(0),                           // 4: google.protobuf.FieldDescriptorProto.Label
+	(FileOptions_OptimizeMode)(0),                             // 5: google.protobuf.FileOptions.OptimizeMode
+	(FieldOptions_CType)(0),                                   // 6: google.protobuf.FieldOptions.CType
+	(FieldOptions_JSType)(0),                                  // 7: google.protobuf.FieldOptions.JSType
+	(FieldOptions_OptionRetention)(0),                         // 8: google.protobuf.FieldOptions.OptionRetention
+	(FieldOptions_OptionTargetType)(0),                        // 9: google.protobuf.FieldOptions.OptionTargetType
+	(MethodOptions_IdempotencyLevel)(0),                       // 10: google.protobuf.MethodOptions.IdempotencyLevel
+	(FeatureSet_FieldPresence)(0),                             // 11: google.protobuf.FeatureSet.FieldPresence
+	(FeatureSet_EnumType)(0),                                  // 12: google.protobuf.FeatureSet.EnumType
+	(FeatureSet_RepeatedFieldEncoding)(0),                     // 13: google.protobuf.FeatureSet.RepeatedFieldEncoding
+	(FeatureSet_Utf8Validation)(0),                            // 14: google.protobuf.FeatureSet.Utf8Validation
+	(FeatureSet_MessageEncoding)(0),                           // 15: google.protobuf.FeatureSet.MessageEncoding
+	(FeatureSet_JsonFormat)(0),                                // 16: google.protobuf.FeatureSet.JsonFormat
+	(FeatureSet_EnforceNamingStyle)(0),                        // 17: google.protobuf.FeatureSet.EnforceNamingStyle
+	(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)(0), // 18: google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	(GeneratedCodeInfo_Annotation_Semantic)(0),                // 19: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	(*FileDescriptorSet)(nil),                                 // 20: google.protobuf.FileDescriptorSet
+	(*FileDescriptorProto)(nil),                               // 21: google.protobuf.FileDescriptorProto
+	(*DescriptorProto)(nil),                                   // 22: google.protobuf.DescriptorProto
+	(*ExtensionRangeOptions)(nil),                             // 23: google.protobuf.ExtensionRangeOptions
+	(*FieldDescriptorProto)(nil),                              // 24: google.protobuf.FieldDescriptorProto
+	(*OneofDescriptorProto)(nil),                              // 25: google.protobuf.OneofDescriptorProto
+	(*EnumDescriptorProto)(nil),                               // 26: google.protobuf.EnumDescriptorProto
+	(*EnumValueDescriptorProto)(nil),                          // 27: google.protobuf.EnumValueDescriptorProto
+	(*ServiceDescriptorProto)(nil),                            // 28: google.protobuf.ServiceDescriptorProto
+	(*MethodDescriptorProto)(nil),                             // 29: google.protobuf.MethodDescriptorProto
+	(*FileOptions)(nil),                                       // 30: google.protobuf.FileOptions
+	(*MessageOptions)(nil),                                    // 31: google.protobuf.MessageOptions
+	(*FieldOptions)(nil),                                      // 32: google.protobuf.FieldOptions
+	(*OneofOptions)(nil),                                      // 33: google.protobuf.OneofOptions
+	(*EnumOptions)(nil),                                       // 34: google.protobuf.EnumOptions
+	(*EnumValueOptions)(nil),                                  // 35: google.protobuf.EnumValueOptions
+	(*ServiceOptions)(nil),                                    // 36: google.protobuf.ServiceOptions
+	(*MethodOptions)(nil),                                     // 37: google.protobuf.MethodOptions
+	(*UninterpretedOption)(nil),                               // 38: google.protobuf.UninterpretedOption
+	(*FeatureSet)(nil),                                        // 39: google.protobuf.FeatureSet
+	(*FeatureSetDefaults)(nil),                                // 40: google.protobuf.FeatureSetDefaults
+	(*SourceCodeInfo)(nil),                                    // 41: google.protobuf.SourceCodeInfo
+	(*GeneratedCodeInfo)(nil),                                 // 42: google.protobuf.GeneratedCodeInfo
+	(*DescriptorProto_ExtensionRange)(nil),                    // 43: google.protobuf.DescriptorProto.ExtensionRange
+	(*DescriptorProto_ReservedRange)(nil),                     // 44: google.protobuf.DescriptorProto.ReservedRange
+	(*ExtensionRangeOptions_Declaration)(nil),                 // 45: google.protobuf.ExtensionRangeOptions.Declaration
+	(*EnumDescriptorProto_EnumReservedRange)(nil),             // 46: google.protobuf.EnumDescriptorProto.EnumReservedRange
+	(*FieldOptions_EditionDefault)(nil),                       // 47: google.protobuf.FieldOptions.EditionDefault
+	(*FieldOptions_FeatureSupport)(nil),                       // 48: google.protobuf.FieldOptions.FeatureSupport
+	(*UninterpretedOption_NamePart)(nil),                      // 49: google.protobuf.UninterpretedOption.NamePart
+	(*FeatureSet_VisibilityFeature)(nil),                      // 50: google.protobuf.FeatureSet.VisibilityFeature
+	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil),       // 51: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	(*SourceCodeInfo_Location)(nil),                           // 52: google.protobuf.SourceCodeInfo.Location
+	(*GeneratedCodeInfo_Annotation)(nil),                      // 53: google.protobuf.GeneratedCodeInfo.Annotation
 }
 var file_google_protobuf_descriptor_proto_depIdxs = []int32{
-	19, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
-	20, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
-	24, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	26, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
-	22, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	28, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
-	39, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
+	21, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
+	22, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
+	26, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	28, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
+	24, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	30, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
+	41, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
 	0,  // 7: google.protobuf.FileDescriptorProto.edition:type_name -> google.protobuf.Edition
-	22, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
-	22, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	20, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
-	24, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	41, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
-	23, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
-	29, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
-	42, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
-	36, // 16: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	43, // 17: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
-	37, // 18: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
-	1,  // 19: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
-	3,  // 20: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
-	2,  // 21: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
-	30, // 22: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
-	31, // 23: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
-	25, // 24: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
-	32, // 25: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
-	44, // 26: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
-	33, // 27: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
-	27, // 28: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
-	34, // 29: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
-	35, // 30: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
-	4,  // 31: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
-	37, // 32: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 33: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 34: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 35: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	5,  // 36: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
-	6,  // 37: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
-	7,  // 38: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
-	8,  // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
-	45, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
-	37, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	9,  // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
-	37, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	47, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
-	10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
-	11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
-	12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
-	13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
-	14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
-	15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
-	16, // 63: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
-	48, // 64: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	0,  // 65: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
-	0,  // 66: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
-	49, // 67: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
-	50, // 68: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
-	21, // 69: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
-	0,  // 70: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
-	0,  // 71: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
-	0,  // 72: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
-	0,  // 73: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
-	0,  // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
-	37, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
-	37, // 76: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
-	17, // 77: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	78, // [78:78] is the sub-list for method output_type
-	78, // [78:78] is the sub-list for method input_type
-	78, // [78:78] is the sub-list for extension type_name
-	78, // [78:78] is the sub-list for extension extendee
-	0,  // [0:78] is the sub-list for field type_name
+	24, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
+	24, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	22, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
+	26, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	43, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
+	25, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
+	31, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
+	44, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
+	1,  // 16: google.protobuf.DescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	38, // 17: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	45, // 18: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
+	39, // 19: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
+	2,  // 20: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
+	4,  // 21: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
+	3,  // 22: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
+	32, // 23: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
+	33, // 24: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
+	27, // 25: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
+	34, // 26: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
+	46, // 27: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
+	1,  // 28: google.protobuf.EnumDescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	35, // 29: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
+	29, // 30: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
+	36, // 31: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
+	37, // 32: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
+	5,  // 33: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
+	39, // 34: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 35: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 36: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 37: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	6,  // 38: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
+	7,  // 39: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
+	8,  // 40: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
+	9,  // 41: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
+	47, // 42: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
+	39, // 43: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 44: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 45: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 46: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 47: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 48: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 49: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 50: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 51: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 52: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 53: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 54: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	10, // 55: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
+	39, // 56: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 57: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	49, // 58: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
+	11, // 59: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
+	12, // 60: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
+	13, // 61: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
+	14, // 62: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
+	15, // 63: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
+	16, // 64: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
+	17, // 65: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
+	18, // 66: google.protobuf.FeatureSet.default_symbol_visibility:type_name -> google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	51, // 67: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	0,  // 68: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
+	0,  // 69: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
+	52, // 70: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
+	53, // 71: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
+	23, // 72: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
+	0,  // 73: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
+	0,  // 74: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
+	0,  // 75: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
+	0,  // 76: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
+	0,  // 77: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
+	39, // 78: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
+	39, // 79: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
+	19, // 80: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	81, // [81:81] is the sub-list for method output_type
+	81, // [81:81] is the sub-list for method input_type
+	81, // [81:81] is the sub-list for extension type_name
+	81, // [81:81] is the sub-list for extension extendee
+	0,  // [0:81] is the sub-list for field type_name
 }
 
 func init() { file_google_protobuf_descriptor_proto_init() }
@@ -4983,8 +5222,8 @@ func file_google_protobuf_descriptor_proto_init() {
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_protobuf_descriptor_proto_rawDesc), len(file_google_protobuf_descriptor_proto_rawDesc)),
-			NumEnums:      18,
-			NumMessages:   33,
+			NumEnums:      20,
+			NumMessages:   34,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/history-api/vendor/gopkg.in/ini.v1/.editorconfig b/history-api/vendor/gopkg.in/ini.v1/.editorconfig
deleted file mode 100644
index 4a2d9180..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# http://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*_test.go]
-trim_trailing_whitespace = false
diff --git a/history-api/vendor/gopkg.in/ini.v1/.gitignore b/history-api/vendor/gopkg.in/ini.v1/.gitignore
deleted file mode 100644
index 588388bd..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-testdata/conf_out.ini
-ini.sublime-project
-ini.sublime-workspace
-testdata/conf_reflect.ini
-.idea
-/.vscode
-.DS_Store
diff --git a/history-api/vendor/gopkg.in/ini.v1/.golangci.yml b/history-api/vendor/gopkg.in/ini.v1/.golangci.yml
deleted file mode 100644
index 631e3692..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/.golangci.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-linters-settings:
-  staticcheck:
-    checks: [
-      "all",
-      "-SA1019" # There are valid use cases of strings.Title
-    ]
-  nakedret:
-    max-func-lines: 0 # Disallow any unnamed return statement
-
-linters:
-  enable:
-    - deadcode
-    - errcheck
-    - gosimple
-    - govet
-    - ineffassign
-    - staticcheck
-    - structcheck
-    - typecheck
-    - unused
-    - varcheck
-    - nakedret
-    - gofmt
-    - rowserrcheck
-    - unconvert
-    - goimports
-    - unparam
diff --git a/history-api/vendor/gopkg.in/ini.v1/LICENSE b/history-api/vendor/gopkg.in/ini.v1/LICENSE
deleted file mode 100644
index d361bbcd..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the Work and such
-Derivative Works in Source or Object form.
-
-3. Grant of Patent License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable (except as stated in this section) patent license to make, have
-made, use, offer to sell, sell, import, and otherwise transfer the Work, where
-such license applies only to those patent claims licensable by such Contributor
-that are necessarily infringed by their Contribution(s) alone or by combination
-of their Contribution(s) with the Work to which such Contribution(s) was
-submitted. If You institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work or a
-Contribution incorporated within the Work constitutes direct or contributory
-patent infringement, then any patent licenses granted to You under this License
-for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.
-
-You may reproduce and distribute copies of the Work or Derivative Works thereof
-in any medium, with or without modifications, and in Source or Object form,
-provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of
-this License; and
-You must cause any modified files to carry prominent notices stating that You
-changed the files; and
-You must retain, in the Source form of any Derivative Works that You distribute,
-all copyright, patent, trademark, and attribution notices from the Source form
-of the Work, excluding those notices that do not pertain to any part of the
-Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any
-Derivative Works that You distribute must include a readable copy of the
-attribution notices contained within such NOTICE file, excluding those notices
-that do not pertain to any part of the Derivative Works, in at least one of the
-following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions.
-
-Unless You explicitly state otherwise, any Contribution intentionally submitted
-for inclusion in the Work by You to the Licensor shall be under the terms and
-conditions of this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify the terms of
-any separate license agreement you may have executed with Licensor regarding
-such Contributions.
-
-6. Trademarks.
-
-This License does not grant permission to use the trade names, trademarks,
-service marks, or product names of the Licensor, except as required for
-reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty.
-
-Unless required by applicable law or agreed to in writing, Licensor provides the
-Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
-including, without limitation, any warranties or conditions of TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
-solely responsible for determining the appropriateness of using or
-redistributing the Work and assume any risks associated with Your exercise of
-permissions under this License.
-
-8. Limitation of Liability.
-
-In no event and under no legal theory, whether in tort (including negligence),
-contract, or otherwise, unless required by applicable law (such as deliberate
-and grossly negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special, incidental,
-or consequential damages of any character arising as a result of this License or
-out of the use or inability to use the Work (including but not limited to
-damages for loss of goodwill, work stoppage, computer failure or malfunction, or
-any and all other commercial damages or losses), even if such Contributor has
-been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability.
-
-While redistributing the Work or Derivative Works thereof, You may choose to
-offer, and charge a fee for, acceptance of support, warranty, indemnity, or
-other liability obligations and/or rights consistent with this License. However,
-in accepting such obligations, You may act only on Your own behalf and on Your
-sole responsibility, not on behalf of any other Contributor, and only if You
-agree to indemnify, defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason of your
-accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work
-
-To apply the Apache License to your work, attach the following boilerplate
-notice, with the fields enclosed by brackets "[]" replaced with your own
-identifying information. (Don't include the brackets!) The text should be
-enclosed in the appropriate comment syntax for the file format. We also
-recommend that a file or class name and description of purpose be included on
-the same "printed page" as the copyright notice for easier identification within
-third-party archives.
-
-   Copyright 2014 Unknwon
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/history-api/vendor/gopkg.in/ini.v1/Makefile b/history-api/vendor/gopkg.in/ini.v1/Makefile
deleted file mode 100644
index f3b0dae2..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-.PHONY: build test bench vet coverage
-
-build: vet bench
-
-test:
-	go test -v -cover -race
-
-bench:
-	go test -v -cover -test.bench=. -test.benchmem
-
-vet:
-	go vet
-
-coverage:
-	go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
diff --git a/history-api/vendor/gopkg.in/ini.v1/README.md b/history-api/vendor/gopkg.in/ini.v1/README.md
deleted file mode 100644
index 30606d97..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# INI
-
-[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain)
-[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini)
-[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc)
-[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini)
-
-![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
-
-Package ini provides INI file read and write functionality in Go.
-
-## Features
-
-- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites.
-- Read with recursion values.
-- Read with parent-child sections.
-- Read with auto-increment key names.
-- Read with multiple-line values.
-- Read with tons of helper methods.
-- Read and convert values to Go types.
-- Read and **WRITE** comments of sections and keys.
-- Manipulate sections, keys and comments with ease.
-- Keep sections and keys in order as you parse and save.
-
-## Installation
-
-The minimum requirement of Go is **1.13**.
-
-```sh
-$ go get gopkg.in/ini.v1
-```
-
-Please add `-u` flag to update in the future.
-
-## Getting Help
-
-- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started)
-- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
-- 中国大陆镜像:https://ini.unknwon.cn
-
-## License
-
-This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
diff --git a/history-api/vendor/gopkg.in/ini.v1/codecov.yml b/history-api/vendor/gopkg.in/ini.v1/codecov.yml
deleted file mode 100644
index e02ec84b..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/codecov.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-coverage:
-  range: "60...95"
-  status:
-    project:
-      default:
-        threshold: 1%
-        informational: true
-    patch:
-      defualt:
-        only_pulls: true
-        informational: true
-
-comment:
-  layout: 'diff'
-
-github_checks: false
diff --git a/history-api/vendor/gopkg.in/ini.v1/data_source.go b/history-api/vendor/gopkg.in/ini.v1/data_source.go
deleted file mode 100644
index c3a541f1..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/data_source.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-)
-
-var (
-	_ dataSource = (*sourceFile)(nil)
-	_ dataSource = (*sourceData)(nil)
-	_ dataSource = (*sourceReadCloser)(nil)
-)
-
-// dataSource is an interface that returns object which can be read and closed.
-type dataSource interface {
-	ReadCloser() (io.ReadCloser, error)
-}
-
-// sourceFile represents an object that contains content on the local file system.
-type sourceFile struct {
-	name string
-}
-
-func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
-	return os.Open(s.name)
-}
-
-// sourceData represents an object that contains content in memory.
-type sourceData struct {
-	data []byte
-}
-
-func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewReader(s.data)), nil
-}
-
-// sourceReadCloser represents an input stream with Close method.
-type sourceReadCloser struct {
-	reader io.ReadCloser
-}
-
-func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
-	return s.reader, nil
-}
-
-func parseDataSource(source interface{}) (dataSource, error) {
-	switch s := source.(type) {
-	case string:
-		return sourceFile{s}, nil
-	case []byte:
-		return &sourceData{s}, nil
-	case io.ReadCloser:
-		return &sourceReadCloser{s}, nil
-	case io.Reader:
-		return &sourceReadCloser{ioutil.NopCloser(s)}, nil
-	default:
-		return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
-	}
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/deprecated.go b/history-api/vendor/gopkg.in/ini.v1/deprecated.go
deleted file mode 100644
index 48b8e66d..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/deprecated.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-var (
-	// Deprecated: Use "DefaultSection" instead.
-	DEFAULT_SECTION = DefaultSection
-	// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
-	AllCapsUnderscore = SnackCase
-)
diff --git a/history-api/vendor/gopkg.in/ini.v1/error.go b/history-api/vendor/gopkg.in/ini.v1/error.go
deleted file mode 100644
index f66bc94b..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/error.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"fmt"
-)
-
-// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
-type ErrDelimiterNotFound struct {
-	Line string
-}
-
-// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
-func IsErrDelimiterNotFound(err error) bool {
-	_, ok := err.(ErrDelimiterNotFound)
-	return ok
-}
-
-func (err ErrDelimiterNotFound) Error() string {
-	return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
-}
-
-// ErrEmptyKeyName indicates the error type of no key name is found which there should be one.
-type ErrEmptyKeyName struct {
-	Line string
-}
-
-// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName.
-func IsErrEmptyKeyName(err error) bool {
-	_, ok := err.(ErrEmptyKeyName)
-	return ok
-}
-
-func (err ErrEmptyKeyName) Error() string {
-	return fmt.Sprintf("empty key name: %s", err.Line)
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/file.go b/history-api/vendor/gopkg.in/ini.v1/file.go
deleted file mode 100644
index f8b22408..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/file.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2017 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"sync"
-)
-
-// File represents a combination of one or more INI files in memory.
-type File struct {
-	options     LoadOptions
-	dataSources []dataSource
-
-	// Should make things safe, but sometimes doesn't matter.
-	BlockMode bool
-	lock      sync.RWMutex
-
-	// To keep data in order.
-	sectionList []string
-	// To keep track of the index of a section with same name.
-	// This meta list is only used with non-unique section names are allowed.
-	sectionIndexes []int
-
-	// Actual data is stored here.
-	sections map[string][]*Section
-
-	NameMapper
-	ValueMapper
-}
-
-// newFile initializes File object with given data sources.
-func newFile(dataSources []dataSource, opts LoadOptions) *File {
-	if len(opts.KeyValueDelimiters) == 0 {
-		opts.KeyValueDelimiters = "=:"
-	}
-	if len(opts.KeyValueDelimiterOnWrite) == 0 {
-		opts.KeyValueDelimiterOnWrite = "="
-	}
-	if len(opts.ChildSectionDelimiter) == 0 {
-		opts.ChildSectionDelimiter = "."
-	}
-
-	return &File{
-		BlockMode:   true,
-		dataSources: dataSources,
-		sections:    make(map[string][]*Section),
-		options:     opts,
-	}
-}
-
-// Empty returns an empty file object.
-func Empty(opts ...LoadOptions) *File {
-	var opt LoadOptions
-	if len(opts) > 0 {
-		opt = opts[0]
-	}
-
-	// Ignore error here, we are sure our data is good.
-	f, _ := LoadSources(opt, []byte(""))
-	return f
-}
-
-// NewSection creates a new section.
-func (f *File) NewSection(name string) (*Section, error) {
-	if len(name) == 0 {
-		return nil, errors.New("empty section name")
-	}
-
-	if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) {
-		return f.sections[name][0], nil
-	}
-
-	f.sectionList = append(f.sectionList, name)
-
-	// NOTE: Append to indexes must happen before appending to sections,
-	// otherwise index will have off-by-one problem.
-	f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name]))
-
-	sec := newSection(f, name)
-	f.sections[name] = append(f.sections[name], sec)
-
-	return sec, nil
-}
-
-// NewRawSection creates a new section with an unparseable body.
-func (f *File) NewRawSection(name, body string) (*Section, error) {
-	section, err := f.NewSection(name)
-	if err != nil {
-		return nil, err
-	}
-
-	section.isRawSection = true
-	section.rawBody = body
-	return section, nil
-}
-
-// NewSections creates a list of sections.
-func (f *File) NewSections(names ...string) (err error) {
-	for _, name := range names {
-		if _, err = f.NewSection(name); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// GetSection returns section by given name.
-func (f *File) GetSection(name string) (*Section, error) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return nil, err
-	}
-
-	return secs[0], err
-}
-
-// HasSection returns true if the file contains a section with given name.
-func (f *File) HasSection(name string) bool {
-	section, _ := f.GetSection(name)
-	return section != nil
-}
-
-// SectionsByName returns all sections with given name.
-func (f *File) SectionsByName(name string) ([]*Section, error) {
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	secs := f.sections[name]
-	if len(secs) == 0 {
-		return nil, fmt.Errorf("section %q does not exist", name)
-	}
-
-	return secs, nil
-}
-
-// Section assumes named section exists and returns a zero-value when not.
-func (f *File) Section(name string) *Section {
-	sec, err := f.GetSection(name)
-	if err != nil {
-		if name == "" {
-			name = DefaultSection
-		}
-		sec, _ = f.NewSection(name)
-		return sec
-	}
-	return sec
-}
-
-// SectionWithIndex assumes named section exists and returns a new section when not.
-func (f *File) SectionWithIndex(name string, index int) *Section {
-	secs, err := f.SectionsByName(name)
-	if err != nil || len(secs) <= index {
-		// NOTE: It's OK here because the only possible error is empty section name,
-		// but if it's empty, this piece of code won't be executed.
-		newSec, _ := f.NewSection(name)
-		return newSec
-	}
-
-	return secs[index]
-}
-
-// Sections returns a list of Section stored in the current instance.
-func (f *File) Sections() []*Section {
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	sections := make([]*Section, len(f.sectionList))
-	for i, name := range f.sectionList {
-		sections[i] = f.sections[name][f.sectionIndexes[i]]
-	}
-	return sections
-}
-
-// ChildSections returns a list of child sections of given section name.
-func (f *File) ChildSections(name string) []*Section {
-	return f.Section(name).ChildSections()
-}
-
-// SectionStrings returns list of section names.
-func (f *File) SectionStrings() []string {
-	list := make([]string, len(f.sectionList))
-	copy(list, f.sectionList)
-	return list
-}
-
-// DeleteSection deletes a section or all sections with given name.
-func (f *File) DeleteSection(name string) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(secs); i++ {
-		// For non-unique sections, it is always needed to remove the first one so
-		// in the next iteration, the subsequent section continue having index 0.
-		// Ignoring the error as index 0 never returns an error.
-		_ = f.DeleteSectionWithIndex(name, 0)
-	}
-}
-
-// DeleteSectionWithIndex deletes a section with given name and index.
-func (f *File) DeleteSectionWithIndex(name string, index int) error {
-	if !f.options.AllowNonUniqueSections && index != 0 {
-		return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled")
-	}
-
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	// Count occurrences of the sections
-	occurrences := 0
-
-	sectionListCopy := make([]string, len(f.sectionList))
-	copy(sectionListCopy, f.sectionList)
-
-	for i, s := range sectionListCopy {
-		if s != name {
-			continue
-		}
-
-		if occurrences == index {
-			if len(f.sections[name]) <= 1 {
-				delete(f.sections, name) // The last one in the map
-			} else {
-				f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...)
-			}
-
-			// Fix section lists
-			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
-			f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...)
-
-		} else if occurrences > index {
-			// Fix the indices of all following sections with this name.
-			f.sectionIndexes[i-1]--
-		}
-
-		occurrences++
-	}
-
-	return nil
-}
-
-func (f *File) reload(s dataSource) error {
-	r, err := s.ReadCloser()
-	if err != nil {
-		return err
-	}
-	defer r.Close()
-
-	return f.parse(r)
-}
-
-// Reload reloads and parses all data sources.
-func (f *File) Reload() (err error) {
-	for _, s := range f.dataSources {
-		if err = f.reload(s); err != nil {
-			// In loose mode, we create an empty default section for nonexistent files.
-			if os.IsNotExist(err) && f.options.Loose {
-				_ = f.parse(bytes.NewBuffer(nil))
-				continue
-			}
-			return err
-		}
-		if f.options.ShortCircuit {
-			return nil
-		}
-	}
-	return nil
-}
-
-// Append appends one or more data sources and reloads automatically.
-func (f *File) Append(source interface{}, others ...interface{}) error {
-	ds, err := parseDataSource(source)
-	if err != nil {
-		return err
-	}
-	f.dataSources = append(f.dataSources, ds)
-	for _, s := range others {
-		ds, err = parseDataSource(s)
-		if err != nil {
-			return err
-		}
-		f.dataSources = append(f.dataSources, ds)
-	}
-	return f.Reload()
-}
-
-func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
-	equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight
-
-	if PrettyFormat || PrettyEqual {
-		equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite)
-	}
-
-	// Use buffer to make sure target is safe until finish encoding.
-	buf := bytes.NewBuffer(nil)
-	lastSectionIdx := len(f.sectionList) - 1
-	for i, sname := range f.sectionList {
-		sec := f.SectionWithIndex(sname, f.sectionIndexes[i])
-		if len(sec.Comment) > 0 {
-			// Support multiline comments
-			lines := strings.Split(sec.Comment, LineBreak)
-			for i := range lines {
-				if lines[i][0] != '#' && lines[i][0] != ';' {
-					lines[i] = "; " + lines[i]
-				} else {
-					lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-				}
-
-				if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) {
-			if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
-				return nil, err
-			}
-		} else {
-			// Write nothing if default section is empty
-			if len(sec.keyList) == 0 {
-				continue
-			}
-		}
-
-		isLastSection := i == lastSectionIdx
-		if sec.isRawSection {
-			if _, err := buf.WriteString(sec.rawBody); err != nil {
-				return nil, err
-			}
-
-			if PrettySection && !isLastSection {
-				// Put a line between sections
-				if _, err := buf.WriteString(LineBreak); err != nil {
-					return nil, err
-				}
-			}
-			continue
-		}
-
-		// Count and generate alignment length and buffer spaces using the
-		// longest key. Keys may be modified if they contain certain characters so
-		// we need to take that into account in our calculation.
-		alignLength := 0
-		if PrettyFormat {
-			for _, kname := range sec.keyList {
-				keyLength := len(kname)
-				// First case will surround key by ` and second by """
-				if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) {
-					keyLength += 2
-				} else if strings.Contains(kname, "`") {
-					keyLength += 6
-				}
-
-				if keyLength > alignLength {
-					alignLength = keyLength
-				}
-			}
-		}
-		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
-
-	KeyList:
-		for _, kname := range sec.keyList {
-			key := sec.Key(kname)
-			if len(key.Comment) > 0 {
-				if len(indent) > 0 && sname != DefaultSection {
-					buf.WriteString(indent)
-				}
-
-				// Support multiline comments
-				lines := strings.Split(key.Comment, LineBreak)
-				for i := range lines {
-					if lines[i][0] != '#' && lines[i][0] != ';' {
-						lines[i] = "; " + strings.TrimSpace(lines[i])
-					} else {
-						lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-					}
-
-					if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-						return nil, err
-					}
-				}
-			}
-
-			if len(indent) > 0 && sname != DefaultSection {
-				buf.WriteString(indent)
-			}
-
-			switch {
-			case key.isAutoIncrement:
-				kname = "-"
-			case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters):
-				kname = "`" + kname + "`"
-			case strings.Contains(kname, "`"):
-				kname = `"""` + kname + `"""`
-			}
-
-			writeKeyValue := func(val string) (bool, error) {
-				if _, err := buf.WriteString(kname); err != nil {
-					return false, err
-				}
-
-				if key.isBooleanType {
-					buf.WriteString(LineBreak)
-					return true, nil
-				}
-
-				// Write out alignment spaces before "=" sign
-				if PrettyFormat {
-					buf.Write(alignSpaces[:alignLength-len(kname)])
-				}
-
-				// In case key value contains "\n", "`", "\"", "#" or ";"
-				if strings.ContainsAny(val, "\n`") {
-					val = `"""` + val + `"""`
-				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
-					val = "`" + val + "`"
-				} else if len(strings.TrimSpace(val)) != len(val) {
-					val = `"` + val + `"`
-				}
-				if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
-					return false, err
-				}
-				return false, nil
-			}
-
-			shadows := key.ValueWithShadows()
-			if len(shadows) == 0 {
-				if _, err := writeKeyValue(""); err != nil {
-					return nil, err
-				}
-			}
-
-			for _, val := range shadows {
-				exitLoop, err := writeKeyValue(val)
-				if err != nil {
-					return nil, err
-				} else if exitLoop {
-					continue KeyList
-				}
-			}
-
-			for _, val := range key.nestedValues {
-				if _, err := buf.WriteString(indent + "  " + val + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if PrettySection && !isLastSection {
-			// Put a line between sections
-			if _, err := buf.WriteString(LineBreak); err != nil {
-				return nil, err
-			}
-		}
-	}
-
-	return buf, nil
-}
-
-// WriteToIndent writes content into io.Writer with given indention.
-// If PrettyFormat has been set to be true,
-// it will align "=" sign with spaces under each section.
-func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return 0, err
-	}
-	return buf.WriteTo(w)
-}
-
-// WriteTo writes file content into io.Writer.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
-	return f.WriteToIndent(w, "")
-}
-
-// SaveToIndent writes content to file system with given value indention.
-func (f *File) SaveToIndent(filename, indent string) error {
-	// Note: Because we are truncating with os.Create,
-	// 	so it's safer to save to a temporary file location and rename after done.
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return err
-	}
-
-	return ioutil.WriteFile(filename, buf.Bytes(), 0666)
-}
-
-// SaveTo writes content to file system.
-func (f *File) SaveTo(filename string) error {
-	return f.SaveToIndent(filename, "")
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/helper.go b/history-api/vendor/gopkg.in/ini.v1/helper.go
deleted file mode 100644
index f9d80a68..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/helper.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-func inSlice(str string, s []string) bool {
-	for _, v := range s {
-		if str == v {
-			return true
-		}
-	}
-	return false
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/ini.go b/history-api/vendor/gopkg.in/ini.v1/ini.go
deleted file mode 100644
index 99e7f865..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/ini.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-// Package ini provides INI file read and write functionality in Go.
-package ini
-
-import (
-	"os"
-	"regexp"
-	"runtime"
-	"strings"
-)
-
-const (
-	// Maximum allowed depth when recursively substituing variable names.
-	depthValues = 99
-)
-
-var (
-	// DefaultSection is the name of default section. You can use this var or the string literal.
-	// In most of cases, an empty string is all you need to access the section.
-	DefaultSection = "DEFAULT"
-
-	// LineBreak is the delimiter to determine or compose a new line.
-	// This variable will be changed to "\r\n" automatically on Windows at package init time.
-	LineBreak = "\n"
-
-	// Variable regexp pattern: %(variable)s
-	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)
-
-	// DefaultHeader explicitly writes default section header.
-	DefaultHeader = false
-
-	// PrettySection indicates whether to put a line between sections.
-	PrettySection = true
-	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
-	// or reduce all possible spaces for compact format.
-	PrettyFormat = true
-	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
-	PrettyEqual = false
-	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatLeft = ""
-	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatRight = ""
-)
-
-var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
-
-func init() {
-	if runtime.GOOS == "windows" && !inTest {
-		LineBreak = "\r\n"
-	}
-}
-
-// LoadOptions contains all customized options used for load data source(s).
-type LoadOptions struct {
-	// Loose indicates whether the parser should ignore nonexistent files or return error.
-	Loose bool
-	// Insensitive indicates whether the parser forces all section and key names to lowercase.
-	Insensitive bool
-	// InsensitiveSections indicates whether the parser forces all section to lowercase.
-	InsensitiveSections bool
-	// InsensitiveKeys indicates whether the parser forces all key names to lowercase.
-	InsensitiveKeys bool
-	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
-	IgnoreContinuation bool
-	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
-	IgnoreInlineComment bool
-	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs.
-	SkipUnrecognizableLines bool
-	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source.
-	ShortCircuit bool
-	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
-	// This type of keys are mostly used in my.cnf.
-	AllowBooleanKeys bool
-	// AllowShadows indicates whether to keep track of keys with same name under same section.
-	AllowShadows bool
-	// AllowNestedValues indicates whether to allow AWS-like nested values.
-	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
-	AllowNestedValues bool
-	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values.
-	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
-	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper
-	// than the first line of the value.
-	AllowPythonMultilineValues bool
-	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
-	// Docs: https://docs.python.org/2/library/configparser.html
-	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
-	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
-	SpaceBeforeInlineComment bool
-	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
-	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
-	UnescapeValueDoubleQuotes bool
-	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
-	// when value is NOT surrounded by any quotes.
-	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
-	UnescapeValueCommentSymbols bool
-	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
-	// conform to key/value pairs. Specify the names of those blocks here.
-	UnparseableSections []string
-	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
-	KeyValueDelimiters string
-	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=".
-	KeyValueDelimiterOnWrite string
-	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
-	ChildSectionDelimiter string
-	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
-	PreserveSurroundedQuote bool
-	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
-	DebugFunc DebugFunc
-	// ReaderBufferSize is the buffer size of the reader in bytes.
-	ReaderBufferSize int
-	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
-	AllowNonUniqueSections bool
-	// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated.
-	AllowDuplicateShadowValues bool
-}
-
-// DebugFunc is the type of function called to log parse events.
-type DebugFunc func(message string)
-
-// LoadSources allows caller to apply customized options for loading from data source(s).
-func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
-	sources := make([]dataSource, len(others)+1)
-	sources[0], err = parseDataSource(source)
-	if err != nil {
-		return nil, err
-	}
-	for i := range others {
-		sources[i+1], err = parseDataSource(others[i])
-		if err != nil {
-			return nil, err
-		}
-	}
-	f := newFile(sources, opts)
-	if err = f.Reload(); err != nil {
-		return nil, err
-	}
-	return f, nil
-}
-
-// Load loads and parses from INI data sources.
-// Arguments can be mixed of file name with string type, or raw data in []byte.
-// It will return error if list contains nonexistent files.
-func Load(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{}, source, others...)
-}
-
-// LooseLoad has exactly same functionality as Load function
-// except it ignores nonexistent files instead of returning error.
-func LooseLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Loose: true}, source, others...)
-}
-
-// InsensitiveLoad has exactly same functionality as Load function
-// except it forces all section and key names to be lowercased.
-func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
-}
-
-// ShadowLoad has exactly same functionality as Load function
-// except it allows have shadow keys.
-func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/key.go b/history-api/vendor/gopkg.in/ini.v1/key.go
deleted file mode 100644
index a19d9f38..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/key.go
+++ /dev/null
@@ -1,837 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Key represents a key under a section.
-type Key struct {
-	s               *Section
-	Comment         string
-	name            string
-	value           string
-	isAutoIncrement bool
-	isBooleanType   bool
-
-	isShadow bool
-	shadows  []*Key
-
-	nestedValues []string
-}
-
-// newKey simply return a key object with given values.
-func newKey(s *Section, name, val string) *Key {
-	return &Key{
-		s:     s,
-		name:  name,
-		value: val,
-	}
-}
-
-func (k *Key) addShadow(val string) error {
-	if k.isShadow {
-		return errors.New("cannot add shadow to another shadow key")
-	} else if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add shadow to auto-increment or boolean key")
-	}
-
-	if !k.s.f.options.AllowDuplicateShadowValues {
-		// Deduplicate shadows based on their values.
-		if k.value == val {
-			return nil
-		}
-		for i := range k.shadows {
-			if k.shadows[i].value == val {
-				return nil
-			}
-		}
-	}
-
-	shadow := newKey(k.s, k.name, val)
-	shadow.isShadow = true
-	k.shadows = append(k.shadows, shadow)
-	return nil
-}
-
-// AddShadow adds a new shadow key to itself.
-func (k *Key) AddShadow(val string) error {
-	if !k.s.f.options.AllowShadows {
-		return errors.New("shadow key is not allowed")
-	}
-	return k.addShadow(val)
-}
-
-func (k *Key) addNestedValue(val string) error {
-	if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add nested value to auto-increment or boolean key")
-	}
-
-	k.nestedValues = append(k.nestedValues, val)
-	return nil
-}
-
-// AddNestedValue adds a nested value to the key.
-func (k *Key) AddNestedValue(val string) error {
-	if !k.s.f.options.AllowNestedValues {
-		return errors.New("nested value is not allowed")
-	}
-	return k.addNestedValue(val)
-}
-
-// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
-type ValueMapper func(string) string
-
-// Name returns name of key.
-func (k *Key) Name() string {
-	return k.name
-}
-
-// Value returns raw value of key for performance purpose.
-func (k *Key) Value() string {
-	return k.value
-}
-
-// ValueWithShadows returns raw values of key and its shadows if any. Shadow
-// keys with empty values are ignored from the returned list.
-func (k *Key) ValueWithShadows() []string {
-	if len(k.shadows) == 0 {
-		if k.value == "" {
-			return []string{}
-		}
-		return []string{k.value}
-	}
-
-	vals := make([]string, 0, len(k.shadows)+1)
-	if k.value != "" {
-		vals = append(vals, k.value)
-	}
-	for _, s := range k.shadows {
-		if s.value != "" {
-			vals = append(vals, s.value)
-		}
-	}
-	return vals
-}
-
-// NestedValues returns nested values stored in the key.
-// It is possible returned value is nil if no nested values stored in the key.
-func (k *Key) NestedValues() []string {
-	return k.nestedValues
-}
-
-// transformValue takes a raw value and transforms to its final string.
-func (k *Key) transformValue(val string) string {
-	if k.s.f.ValueMapper != nil {
-		val = k.s.f.ValueMapper(val)
-	}
-
-	// Fail-fast if no indicate char found for recursive value
-	if !strings.Contains(val, "%") {
-		return val
-	}
-	for i := 0; i < depthValues; i++ {
-		vr := varPattern.FindString(val)
-		if len(vr) == 0 {
-			break
-		}
-
-		// Take off leading '%(' and trailing ')s'.
-		noption := vr[2 : len(vr)-2]
-
-		// Search in the same section.
-		// If not found or found the key itself, then search again in default section.
-		nk, err := k.s.GetKey(noption)
-		if err != nil || k == nk {
-			nk, _ = k.s.f.Section("").GetKey(noption)
-			if nk == nil {
-				// Stop when no results found in the default section,
-				// and returns the value as-is.
-				break
-			}
-		}
-
-		// Substitute by new value and take off leading '%(' and trailing ')s'.
-		val = strings.Replace(val, vr, nk.value, -1)
-	}
-	return val
-}
-
-// String returns string representation of value.
-func (k *Key) String() string {
-	return k.transformValue(k.value)
-}
-
-// Validate accepts a validate function which can
-// return modifed result as key value.
-func (k *Key) Validate(fn func(string) string) string {
-	return fn(k.String())
-}
-
-// parseBool returns the boolean value represented by the string.
-//
-// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
-// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
-// Any other value returns an error.
-func parseBool(str string) (value bool, err error) {
-	switch str {
-	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
-		return true, nil
-	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
-		return false, nil
-	}
-	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
-}
-
-// Bool returns bool type value.
-func (k *Key) Bool() (bool, error) {
-	return parseBool(k.String())
-}
-
-// Float64 returns float64 type value.
-func (k *Key) Float64() (float64, error) {
-	return strconv.ParseFloat(k.String(), 64)
-}
-
-// Int returns int type value.
-func (k *Key) Int() (int, error) {
-	v, err := strconv.ParseInt(k.String(), 0, 64)
-	return int(v), err
-}
-
-// Int64 returns int64 type value.
-func (k *Key) Int64() (int64, error) {
-	return strconv.ParseInt(k.String(), 0, 64)
-}
-
-// Uint returns uint type valued.
-func (k *Key) Uint() (uint, error) {
-	u, e := strconv.ParseUint(k.String(), 0, 64)
-	return uint(u), e
-}
-
-// Uint64 returns uint64 type value.
-func (k *Key) Uint64() (uint64, error) {
-	return strconv.ParseUint(k.String(), 0, 64)
-}
-
-// Duration returns time.Duration type value.
-func (k *Key) Duration() (time.Duration, error) {
-	return time.ParseDuration(k.String())
-}
-
-// TimeFormat parses with given format and returns time.Time type value.
-func (k *Key) TimeFormat(format string) (time.Time, error) {
-	return time.Parse(format, k.String())
-}
-
-// Time parses with RFC3339 format and returns time.Time type value.
-func (k *Key) Time() (time.Time, error) {
-	return k.TimeFormat(time.RFC3339)
-}
-
-// MustString returns default value if key value is empty.
-func (k *Key) MustString(defaultVal string) string {
-	val := k.String()
-	if len(val) == 0 {
-		k.value = defaultVal
-		return defaultVal
-	}
-	return val
-}
-
-// MustBool always returns value without error,
-// it returns false if error occurs.
-func (k *Key) MustBool(defaultVal ...bool) bool {
-	val, err := k.Bool()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatBool(defaultVal[0])
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustFloat64 always returns value without error,
-// it returns 0.0 if error occurs.
-func (k *Key) MustFloat64(defaultVal ...float64) float64 {
-	val, err := k.Float64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt(defaultVal ...int) int {
-	val, err := k.Int()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt64(defaultVal ...int64) int64 {
-	val, err := k.Int64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint(defaultVal ...uint) uint {
-	val, err := k.Uint()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
-	val, err := k.Uint64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustDuration always returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
-	val, err := k.Duration()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].String()
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTimeFormat always parses with given format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
-	val, err := k.TimeFormat(format)
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].Format(format)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTime always parses with RFC3339 format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
-	return k.MustTimeFormat(time.RFC3339, defaultVal...)
-}
-
-// In always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) In(defaultVal string, candidates []string) string {
-	val := k.String()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InFloat64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
-	val := k.MustFloat64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt(defaultVal int, candidates []int) int {
-	val := k.MustInt()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
-	val := k.MustInt64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
-	val := k.MustUint()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
-	val := k.MustUint64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTimeFormat always parses with given format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTime always parses with RFC3339 format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
-	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
-}
-
-// RangeFloat64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
-	val := k.MustFloat64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt(defaultVal, min, max int) int {
-	val := k.MustInt()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
-	val := k.MustInt64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTimeFormat checks if value with given format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTime checks if value with RFC3339 format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
-	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
-}
-
-// Strings returns list of string divided by given delimiter.
-func (k *Key) Strings(delim string) []string {
-	str := k.String()
-	if len(str) == 0 {
-		return []string{}
-	}
-
-	runes := []rune(str)
-	vals := make([]string, 0, 2)
-	var buf bytes.Buffer
-	escape := false
-	idx := 0
-	for {
-		if escape {
-			escape = false
-			if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
-				buf.WriteRune('\\')
-			}
-			buf.WriteRune(runes[idx])
-		} else {
-			if runes[idx] == '\\' {
-				escape = true
-			} else if strings.HasPrefix(string(runes[idx:]), delim) {
-				idx += len(delim) - 1
-				vals = append(vals, strings.TrimSpace(buf.String()))
-				buf.Reset()
-			} else {
-				buf.WriteRune(runes[idx])
-			}
-		}
-		idx++
-		if idx == len(runes) {
-			break
-		}
-	}
-
-	if buf.Len() > 0 {
-		vals = append(vals, strings.TrimSpace(buf.String()))
-	}
-
-	return vals
-}
-
-// StringsWithShadows returns list of string divided by given delimiter.
-// Shadows will also be appended if any.
-func (k *Key) StringsWithShadows(delim string) []string {
-	vals := k.ValueWithShadows()
-	results := make([]string, 0, len(vals)*2)
-	for i := range vals {
-		if len(vals) == 0 {
-			continue
-		}
-
-		results = append(results, strings.Split(vals[i], delim)...)
-	}
-
-	for i := range results {
-		results[i] = k.transformValue(strings.TrimSpace(results[i]))
-	}
-	return results
-}
-
-// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Float64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Ints(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), true, false)
-	return vals
-}
-
-// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Int64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Bools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), true, false)
-	return vals
-}
-
-// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) TimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
-	return vals
-}
-
-// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) Times(delim string) []time.Time {
-	return k.TimesFormat(time.RFC3339, delim)
-}
-
-// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
-// it will not be included to result list.
-func (k *Key) ValidFloat64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
-// not be included to result list.
-func (k *Key) ValidInts(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
-// then it will not be included to result list.
-func (k *Key) ValidInt64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
-// then it will not be included to result list.
-func (k *Key) ValidUints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidUint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidBools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimes(delim string) []time.Time {
-	return k.ValidTimesFormat(time.RFC3339, delim)
-}
-
-// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
-	return k.parseFloat64s(k.Strings(delim), false, true)
-}
-
-// StrictInts returns list of int divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInts(delim string) ([]int, error) {
-	return k.parseInts(k.Strings(delim), false, true)
-}
-
-// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInt64s(delim string) ([]int64, error) {
-	return k.parseInt64s(k.Strings(delim), false, true)
-}
-
-// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUints(delim string) ([]uint, error) {
-	return k.parseUints(k.Strings(delim), false, true)
-}
-
-// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
-	return k.parseUint64s(k.Strings(delim), false, true)
-}
-
-// StrictBools returns list of bool divided by given delimiter or error on first invalid input.
-func (k *Key) StrictBools(delim string) ([]bool, error) {
-	return k.parseBools(k.Strings(delim), false, true)
-}
-
-// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
-	return k.parseTimesFormat(format, k.Strings(delim), false, true)
-}
-
-// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
-	return k.StrictTimesFormat(time.RFC3339, delim)
-}
-
-// parseBools transforms strings to bools.
-func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) {
-	vals := make([]bool, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := parseBool(str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(bool))
-		}
-	}
-	return vals, err
-}
-
-// parseFloat64s transforms strings to float64s.
-func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
-	vals := make([]float64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseFloat(str, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(float64))
-		}
-	}
-	return vals, err
-}
-
-// parseInts transforms strings to ints.
-func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
-	vals := make([]int, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, int(val.(int64)))
-		}
-	}
-	return vals, err
-}
-
-// parseInt64s transforms strings to int64s.
-func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
-	vals := make([]int64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(int64))
-		}
-	}
-	return vals, err
-}
-
-// parseUints transforms strings to uints.
-func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
-	vals := make([]uint, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, uint(val.(uint64)))
-		}
-	}
-	return vals, err
-}
-
-// parseUint64s transforms strings to uint64s.
-func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
-	vals := make([]uint64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(uint64))
-		}
-	}
-	return vals, err
-}
-
-type Parser func(str string) (interface{}, error)
-
-// parseTimesFormat transforms strings to times in given format.
-func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
-	vals := make([]time.Time, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := time.Parse(format, str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(time.Time))
-		}
-	}
-	return vals, err
-}
-
-// doParse transforms strings to different types
-func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) {
-	vals := make([]interface{}, 0, len(strs))
-	for _, str := range strs {
-		val, err := parser(str)
-		if err != nil && returnOnInvalid {
-			return nil, err
-		}
-		if err == nil || addInvalid {
-			vals = append(vals, val)
-		}
-	}
-	return vals, nil
-}
-
-// SetValue changes key value.
-func (k *Key) SetValue(v string) {
-	if k.s.f.BlockMode {
-		k.s.f.lock.Lock()
-		defer k.s.f.lock.Unlock()
-	}
-
-	k.value = v
-	k.s.keysHash[k.name] = v
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/parser.go b/history-api/vendor/gopkg.in/ini.v1/parser.go
deleted file mode 100644
index 44fc526c..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/parser.go
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2015 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"regexp"
-	"strconv"
-	"strings"
-	"unicode"
-)
-
-const minReaderBufferSize = 4096
-
-var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`)
-
-type parserOptions struct {
-	IgnoreContinuation          bool
-	IgnoreInlineComment         bool
-	AllowPythonMultilineValues  bool
-	SpaceBeforeInlineComment    bool
-	UnescapeValueDoubleQuotes   bool
-	UnescapeValueCommentSymbols bool
-	PreserveSurroundedQuote     bool
-	DebugFunc                   DebugFunc
-	ReaderBufferSize            int
-}
-
-type parser struct {
-	buf     *bufio.Reader
-	options parserOptions
-
-	isEOF   bool
-	count   int
-	comment *bytes.Buffer
-}
-
-func (p *parser) debug(format string, args ...interface{}) {
-	if p.options.DebugFunc != nil {
-		p.options.DebugFunc(fmt.Sprintf(format, args...))
-	}
-}
-
-func newParser(r io.Reader, opts parserOptions) *parser {
-	size := opts.ReaderBufferSize
-	if size < minReaderBufferSize {
-		size = minReaderBufferSize
-	}
-
-	return &parser{
-		buf:     bufio.NewReaderSize(r, size),
-		options: opts,
-		count:   1,
-		comment: &bytes.Buffer{},
-	}
-}
-
-// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
-// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
-func (p *parser) BOM() error {
-	mask, err := p.buf.Peek(2)
-	if err != nil && err != io.EOF {
-		return err
-	} else if len(mask) < 2 {
-		return nil
-	}
-
-	switch {
-	case mask[0] == 254 && mask[1] == 255:
-		fallthrough
-	case mask[0] == 255 && mask[1] == 254:
-		_, err = p.buf.Read(mask)
-		if err != nil {
-			return err
-		}
-	case mask[0] == 239 && mask[1] == 187:
-		mask, err := p.buf.Peek(3)
-		if err != nil && err != io.EOF {
-			return err
-		} else if len(mask) < 3 {
-			return nil
-		}
-		if mask[2] == 191 {
-			_, err = p.buf.Read(mask)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func (p *parser) readUntil(delim byte) ([]byte, error) {
-	data, err := p.buf.ReadBytes(delim)
-	if err != nil {
-		if err == io.EOF {
-			p.isEOF = true
-		} else {
-			return nil, err
-		}
-	}
-	return data, nil
-}
-
-func cleanComment(in []byte) ([]byte, bool) {
-	i := bytes.IndexAny(in, "#;")
-	if i == -1 {
-		return nil, false
-	}
-	return in[i:], true
-}
-
-func readKeyName(delimiters string, in []byte) (string, int, error) {
-	line := string(in)
-
-	// Check if key name surrounded by quotes.
-	var keyQuote string
-	if line[0] == '"' {
-		if len(line) > 6 && line[0:3] == `"""` {
-			keyQuote = `"""`
-		} else {
-			keyQuote = `"`
-		}
-	} else if line[0] == '`' {
-		keyQuote = "`"
-	}
-
-	// Get out key name
-	var endIdx int
-	if len(keyQuote) > 0 {
-		startIdx := len(keyQuote)
-		// FIXME: fail case -> """"""name"""=value
-		pos := strings.Index(line[startIdx:], keyQuote)
-		if pos == -1 {
-			return "", -1, fmt.Errorf("missing closing key quote: %s", line)
-		}
-		pos += startIdx
-
-		// Find key-value delimiter
-		i := strings.IndexAny(line[pos+startIdx:], delimiters)
-		if i < 0 {
-			return "", -1, ErrDelimiterNotFound{line}
-		}
-		endIdx = pos + i
-		return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
-	}
-
-	endIdx = strings.IndexAny(line, delimiters)
-	if endIdx < 0 {
-		return "", -1, ErrDelimiterNotFound{line}
-	}
-	if endIdx == 0 {
-		return "", -1, ErrEmptyKeyName{line}
-	}
-
-	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
-}
-
-func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := string(data)
-
-		pos := strings.LastIndex(next, valQuote)
-		if pos > -1 {
-			val += next[:pos]
-
-			comment, has := cleanComment([]byte(next[pos:]))
-			if has {
-				p.comment.Write(bytes.TrimSpace(comment))
-			}
-			break
-		}
-		val += next
-		if p.isEOF {
-			return "", fmt.Errorf("missing closing key quote from %q to %q", line, next)
-		}
-	}
-	return val, nil
-}
-
-func (p *parser) readContinuationLines(val string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := strings.TrimSpace(string(data))
-
-		if len(next) == 0 {
-			break
-		}
-		val += next
-		if val[len(val)-1] != '\\' {
-			break
-		}
-		val = val[:len(val)-1]
-	}
-	return val, nil
-}
-
-// hasSurroundedQuote check if and only if the first and last characters
-// are quotes \" or \'.
-// It returns false if any other parts also contain same kind of quotes.
-func hasSurroundedQuote(in string, quote byte) bool {
-	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
-		strings.IndexByte(in[1:], quote) == len(in)-2
-}
-
-func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
-
-	line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
-	if len(line) == 0 {
-		if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
-			return p.readPythonMultilines(line, bufferSize)
-		}
-		return "", nil
-	}
-
-	var valQuote string
-	if len(line) > 3 && line[0:3] == `"""` {
-		valQuote = `"""`
-	} else if line[0] == '`' {
-		valQuote = "`"
-	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
-		valQuote = `"`
-	}
-
-	if len(valQuote) > 0 {
-		startIdx := len(valQuote)
-		pos := strings.LastIndex(line[startIdx:], valQuote)
-		// Check for multi-line value
-		if pos == -1 {
-			return p.readMultilines(line, line[startIdx:], valQuote)
-		}
-
-		if p.options.UnescapeValueDoubleQuotes && valQuote == `"` {
-			return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
-		}
-		return line[startIdx : pos+startIdx], nil
-	}
-
-	lastChar := line[len(line)-1]
-	// Won't be able to reach here if value only contains whitespace
-	line = strings.TrimSpace(line)
-	trimmedLastChar := line[len(line)-1]
-
-	// Check continuation lines when desired
-	if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
-		return p.readContinuationLines(line[:len(line)-1])
-	}
-
-	// Check if ignore inline comment
-	if !p.options.IgnoreInlineComment {
-		var i int
-		if p.options.SpaceBeforeInlineComment {
-			i = strings.Index(line, " #")
-			if i == -1 {
-				i = strings.Index(line, " ;")
-			}
-
-		} else {
-			i = strings.IndexAny(line, "#;")
-		}
-
-		if i > -1 {
-			p.comment.WriteString(line[i:])
-			line = strings.TrimSpace(line[:i])
-		}
-
-	}
-
-	// Trim single and double quotes
-	if (hasSurroundedQuote(line, '\'') ||
-		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
-		line = line[1 : len(line)-1]
-	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
-		line = strings.ReplaceAll(line, `\;`, ";")
-		line = strings.ReplaceAll(line, `\#`, "#")
-	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
-		return p.readPythonMultilines(line, bufferSize)
-	}
-
-	return line, nil
-}
-
-func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
-	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
-	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
-
-	for {
-		peekData, peekErr := peekBuffer.ReadBytes('\n')
-		if peekErr != nil && peekErr != io.EOF {
-			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
-			return "", peekErr
-		}
-
-		p.debug("readPythonMultilines: parsing %q", string(peekData))
-
-		peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
-		p.debug("readPythonMultilines: matched %d parts", len(peekMatches))
-		for n, v := range peekMatches {
-			p.debug("   %d: %q", n, v)
-		}
-
-		// Return if not a Python multiline value.
-		if len(peekMatches) != 3 {
-			p.debug("readPythonMultilines: end of value, got: %q", line)
-			return line, nil
-		}
-
-		// Advance the parser reader (buffer) in-sync with the peek buffer.
-		_, err := p.buf.Discard(len(peekData))
-		if err != nil {
-			p.debug("readPythonMultilines: failed to skip to the end, returning error")
-			return "", err
-		}
-
-		line += "\n" + peekMatches[0]
-	}
-}
-
-// parse parses data through an io.Reader.
-func (f *File) parse(reader io.Reader) (err error) {
-	p := newParser(reader, parserOptions{
-		IgnoreContinuation:          f.options.IgnoreContinuation,
-		IgnoreInlineComment:         f.options.IgnoreInlineComment,
-		AllowPythonMultilineValues:  f.options.AllowPythonMultilineValues,
-		SpaceBeforeInlineComment:    f.options.SpaceBeforeInlineComment,
-		UnescapeValueDoubleQuotes:   f.options.UnescapeValueDoubleQuotes,
-		UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols,
-		PreserveSurroundedQuote:     f.options.PreserveSurroundedQuote,
-		DebugFunc:                   f.options.DebugFunc,
-		ReaderBufferSize:            f.options.ReaderBufferSize,
-	})
-	if err = p.BOM(); err != nil {
-		return fmt.Errorf("BOM: %v", err)
-	}
-
-	// Ignore error because default section name is never empty string.
-	name := DefaultSection
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(DefaultSection)
-	}
-	section, _ := f.NewSection(name)
-
-	// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
-	var isLastValueEmpty bool
-	var lastRegularKey *Key
-
-	var line []byte
-	var inUnparseableSection bool
-
-	// NOTE: Iterate and increase `currentPeekSize` until
-	// the size of the parser buffer is found.
-	// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`.
-	parserBufferSize := 0
-	// NOTE: Peek 4kb at a time.
-	currentPeekSize := minReaderBufferSize
-
-	if f.options.AllowPythonMultilineValues {
-		for {
-			peekBytes, _ := p.buf.Peek(currentPeekSize)
-			peekBytesLength := len(peekBytes)
-
-			if parserBufferSize >= peekBytesLength {
-				break
-			}
-
-			currentPeekSize *= 2
-			parserBufferSize = peekBytesLength
-		}
-	}
-
-	for !p.isEOF {
-		line, err = p.readUntil('\n')
-		if err != nil {
-			return err
-		}
-
-		if f.options.AllowNestedValues &&
-			isLastValueEmpty && len(line) > 0 {
-			if line[0] == ' ' || line[0] == '\t' {
-				err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
-				if err != nil {
-					return err
-				}
-				continue
-			}
-		}
-
-		line = bytes.TrimLeftFunc(line, unicode.IsSpace)
-		if len(line) == 0 {
-			continue
-		}
-
-		// Comments
-		if line[0] == '#' || line[0] == ';' {
-			// Note: we do not care ending line break,
-			// it is needed for adding second line,
-			// so just clean it once at the end when set to value.
-			p.comment.Write(line)
-			continue
-		}
-
-		// Section
-		if line[0] == '[' {
-			// Read to the next ']' (TODO: support quoted strings)
-			closeIdx := bytes.LastIndexByte(line, ']')
-			if closeIdx == -1 {
-				return fmt.Errorf("unclosed section: %s", line)
-			}
-
-			name := string(line[1:closeIdx])
-			section, err = f.NewSection(name)
-			if err != nil {
-				return err
-			}
-
-			comment, has := cleanComment(line[closeIdx+1:])
-			if has {
-				p.comment.Write(comment)
-			}
-
-			section.Comment = strings.TrimSpace(p.comment.String())
-
-			// Reset auto-counter and comments
-			p.comment.Reset()
-			p.count = 1
-			// Nested values can't span sections
-			isLastValueEmpty = false
-
-			inUnparseableSection = false
-			for i := range f.options.UnparseableSections {
-				if f.options.UnparseableSections[i] == name ||
-					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
-					inUnparseableSection = true
-					continue
-				}
-			}
-			continue
-		}
-
-		if inUnparseableSection {
-			section.isRawSection = true
-			section.rawBody += string(line)
-			continue
-		}
-
-		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
-		if err != nil {
-			switch {
-			// Treat as boolean key when desired, and whole line is key name.
-			case IsErrDelimiterNotFound(err):
-				switch {
-				case f.options.AllowBooleanKeys:
-					kname, err := p.readValue(line, parserBufferSize)
-					if err != nil {
-						return err
-					}
-					key, err := section.NewBooleanKey(kname)
-					if err != nil {
-						return err
-					}
-					key.Comment = strings.TrimSpace(p.comment.String())
-					p.comment.Reset()
-					continue
-
-				case f.options.SkipUnrecognizableLines:
-					continue
-				}
-			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines:
-				continue
-			}
-			return err
-		}
-
-		// Auto increment.
-		isAutoIncr := false
-		if kname == "-" {
-			isAutoIncr = true
-			kname = "#" + strconv.Itoa(p.count)
-			p.count++
-		}
-
-		value, err := p.readValue(line[offset:], parserBufferSize)
-		if err != nil {
-			return err
-		}
-		isLastValueEmpty = len(value) == 0
-
-		key, err := section.NewKey(kname, value)
-		if err != nil {
-			return err
-		}
-		key.isAutoIncrement = isAutoIncr
-		key.Comment = strings.TrimSpace(p.comment.String())
-		p.comment.Reset()
-		lastRegularKey = key
-	}
-	return nil
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/section.go b/history-api/vendor/gopkg.in/ini.v1/section.go
deleted file mode 100644
index a3615d82..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/section.go
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"errors"
-	"fmt"
-	"strings"
-)
-
-// Section represents a config section.
-type Section struct {
-	f        *File
-	Comment  string
-	name     string
-	keys     map[string]*Key
-	keyList  []string
-	keysHash map[string]string
-
-	isRawSection bool
-	rawBody      string
-}
-
-func newSection(f *File, name string) *Section {
-	return &Section{
-		f:        f,
-		name:     name,
-		keys:     make(map[string]*Key),
-		keyList:  make([]string, 0, 10),
-		keysHash: make(map[string]string),
-	}
-}
-
-// Name returns name of Section.
-func (s *Section) Name() string {
-	return s.name
-}
-
-// Body returns rawBody of Section if the section was marked as unparseable.
-// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
-func (s *Section) Body() string {
-	return strings.TrimSpace(s.rawBody)
-}
-
-// SetBody updates body content only if section is raw.
-func (s *Section) SetBody(body string) {
-	if !s.isRawSection {
-		return
-	}
-	s.rawBody = body
-}
-
-// NewKey creates a new key to given section.
-func (s *Section) NewKey(name, val string) (*Key, error) {
-	if len(name) == 0 {
-		return nil, errors.New("error creating new key: empty key name")
-	} else if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	if inSlice(name, s.keyList) {
-		if s.f.options.AllowShadows {
-			if err := s.keys[name].addShadow(val); err != nil {
-				return nil, err
-			}
-		} else {
-			s.keys[name].value = val
-			s.keysHash[name] = val
-		}
-		return s.keys[name], nil
-	}
-
-	s.keyList = append(s.keyList, name)
-	s.keys[name] = newKey(s, name, val)
-	s.keysHash[name] = val
-	return s.keys[name], nil
-}
-
-// NewBooleanKey creates a new boolean type key to given section.
-func (s *Section) NewBooleanKey(name string) (*Key, error) {
-	key, err := s.NewKey(name, "true")
-	if err != nil {
-		return nil, err
-	}
-
-	key.isBooleanType = true
-	return key, nil
-}
-
-// GetKey returns key in section by given name.
-func (s *Section) GetKey(name string) (*Key, error) {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-	}
-	if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-	key := s.keys[name]
-	if s.f.BlockMode {
-		s.f.lock.RUnlock()
-	}
-
-	if key == nil {
-		// Check if it is a child-section.
-		sname := s.name
-		for {
-			if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-				sname = sname[:i]
-				sec, err := s.f.GetSection(sname)
-				if err != nil {
-					continue
-				}
-				return sec.GetKey(name)
-			}
-			break
-		}
-		return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name)
-	}
-	return key, nil
-}
-
-// HasKey returns true if section contains a key with given name.
-func (s *Section) HasKey(name string) bool {
-	key, _ := s.GetKey(name)
-	return key != nil
-}
-
-// Deprecated: Use "HasKey" instead.
-func (s *Section) Haskey(name string) bool {
-	return s.HasKey(name)
-}
-
-// HasValue returns true if section contains given raw value.
-func (s *Section) HasValue(value string) bool {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	for _, k := range s.keys {
-		if value == k.value {
-			return true
-		}
-	}
-	return false
-}
-
-// Key assumes named Key exists in section and returns a zero-value when not.
-func (s *Section) Key(name string) *Key {
-	key, err := s.GetKey(name)
-	if err != nil {
-		// It's OK here because the only possible error is empty key name,
-		// but if it's empty, this piece of code won't be executed.
-		key, _ = s.NewKey(name, "")
-		return key
-	}
-	return key
-}
-
-// Keys returns list of keys of section.
-func (s *Section) Keys() []*Key {
-	keys := make([]*Key, len(s.keyList))
-	for i := range s.keyList {
-		keys[i] = s.Key(s.keyList[i])
-	}
-	return keys
-}
-
-// ParentKeys returns list of keys of parent section.
-func (s *Section) ParentKeys() []*Key {
-	var parentKeys []*Key
-	sname := s.name
-	for {
-		if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-			sname = sname[:i]
-			sec, err := s.f.GetSection(sname)
-			if err != nil {
-				continue
-			}
-			parentKeys = append(parentKeys, sec.Keys()...)
-		} else {
-			break
-		}
-
-	}
-	return parentKeys
-}
-
-// KeyStrings returns list of key names of section.
-func (s *Section) KeyStrings() []string {
-	list := make([]string, len(s.keyList))
-	copy(list, s.keyList)
-	return list
-}
-
-// KeysHash returns keys hash consisting of names and values.
-func (s *Section) KeysHash() map[string]string {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	hash := make(map[string]string, len(s.keysHash))
-	for key, value := range s.keysHash {
-		hash[key] = value
-	}
-	return hash
-}
-
-// DeleteKey deletes a key from section.
-func (s *Section) DeleteKey(name string) {
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	for i, k := range s.keyList {
-		if k == name {
-			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
-			delete(s.keys, name)
-			delete(s.keysHash, name)
-			return
-		}
-	}
-}
-
-// ChildSections returns a list of child sections of current section.
-// For example, "[parent.child1]" and "[parent.child12]" are child sections
-// of section "[parent]".
-func (s *Section) ChildSections() []*Section {
-	prefix := s.name + s.f.options.ChildSectionDelimiter
-	children := make([]*Section, 0, 3)
-	for _, name := range s.f.sectionList {
-		if strings.HasPrefix(name, prefix) {
-			children = append(children, s.f.sections[name]...)
-		}
-	}
-	return children
-}
diff --git a/history-api/vendor/gopkg.in/ini.v1/struct.go b/history-api/vendor/gopkg.in/ini.v1/struct.go
deleted file mode 100644
index a486b2fe..00000000
--- a/history-api/vendor/gopkg.in/ini.v1/struct.go
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"reflect"
-	"strings"
-	"time"
-	"unicode"
-)
-
-// NameMapper represents a ini tag name mapper.
-type NameMapper func(string) string
-
-// Built-in name getters.
-var (
-	// SnackCase converts to format SNACK_CASE.
-	SnackCase NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-			}
-			newstr = append(newstr, unicode.ToUpper(chr))
-		}
-		return string(newstr)
-	}
-	// TitleUnderscore converts to format title_underscore.
-	TitleUnderscore NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-				chr -= 'A' - 'a'
-			}
-			newstr = append(newstr, chr)
-		}
-		return string(newstr)
-	}
-)
-
-func (s *Section) parseFieldName(raw, actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	if s.f.NameMapper != nil {
-		return s.f.NameMapper(raw)
-	}
-	return raw
-}
-
-func parseDelim(actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	return ","
-}
-
-var reflectTime = reflect.TypeOf(time.Now()).Kind()
-
-// setSliceWithProperType sets proper values to slice based on its type.
-func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	var strs []string
-	if allowShadow {
-		strs = key.StringsWithShadows(delim)
-	} else {
-		strs = key.Strings(delim)
-	}
-
-	numVals := len(strs)
-	if numVals == 0 {
-		return nil
-	}
-
-	var vals interface{}
-	var err error
-
-	sliceOf := field.Type().Elem().Kind()
-	switch sliceOf {
-	case reflect.String:
-		vals = strs
-	case reflect.Int:
-		vals, err = key.parseInts(strs, true, false)
-	case reflect.Int64:
-		vals, err = key.parseInt64s(strs, true, false)
-	case reflect.Uint:
-		vals, err = key.parseUints(strs, true, false)
-	case reflect.Uint64:
-		vals, err = key.parseUint64s(strs, true, false)
-	case reflect.Float64:
-		vals, err = key.parseFloat64s(strs, true, false)
-	case reflect.Bool:
-		vals, err = key.parseBools(strs, true, false)
-	case reflectTime:
-		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
-	default:
-		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-	}
-	if err != nil && isStrict {
-		return err
-	}
-
-	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
-	for i := 0; i < numVals; i++ {
-		switch sliceOf {
-		case reflect.String:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
-		case reflect.Int:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
-		case reflect.Int64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
-		case reflect.Uint:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
-		case reflect.Uint64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
-		case reflect.Float64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
-		case reflect.Bool:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i]))
-		case reflectTime:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
-		}
-	}
-	field.Set(slice)
-	return nil
-}
-
-func wrapStrictError(err error, isStrict bool) error {
-	if isStrict {
-		return err
-	}
-	return nil
-}
-
-// setWithProperType sets proper value to field based on its type,
-// but it does not return error for failing parsing,
-// because we want to use default value that is already assigned to struct.
-func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	vt := t
-	isPtr := t.Kind() == reflect.Ptr
-	if isPtr {
-		vt = t.Elem()
-	}
-	switch vt.Kind() {
-	case reflect.String:
-		stringVal := key.String()
-		if isPtr {
-			field.Set(reflect.ValueOf(&stringVal))
-		} else if len(stringVal) > 0 {
-			field.SetString(key.String())
-		}
-	case reflect.Bool:
-		boolVal, err := key.Bool()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&boolVal))
-		} else {
-			field.SetBool(boolVal)
-		}
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		// ParseDuration will not return err for `0`, so check the type name
-		if vt.Name() == "Duration" {
-			durationVal, err := key.Duration()
-			if err != nil {
-				if intVal, err := key.Int64(); err == nil {
-					field.SetInt(intVal)
-					return nil
-				}
-				return wrapStrictError(err, isStrict)
-			}
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else if int64(durationVal) > 0 {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		intVal, err := key.Int64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetInt(intVal)
-			field.Set(pv)
-		} else {
-			field.SetInt(intVal)
-		}
-	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
-	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		durationVal, err := key.Duration()
-		// Skip zero value
-		if err == nil && uint64(durationVal) > 0 {
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		uintVal, err := key.Uint64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetUint(uintVal)
-			field.Set(pv)
-		} else {
-			field.SetUint(uintVal)
-		}
-
-	case reflect.Float32, reflect.Float64:
-		floatVal, err := key.Float64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetFloat(floatVal)
-			field.Set(pv)
-		} else {
-			field.SetFloat(floatVal)
-		}
-	case reflectTime:
-		timeVal, err := key.Time()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&timeVal))
-		} else {
-			field.Set(reflect.ValueOf(timeVal))
-		}
-	case reflect.Slice:
-		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) {
-	opts := strings.SplitN(tag, ",", 5)
-	rawName = opts[0]
-	for _, opt := range opts[1:] {
-		omitEmpty = omitEmpty || (opt == "omitempty")
-		allowShadow = allowShadow || (opt == "allowshadow")
-		allowNonUnique = allowNonUnique || (opt == "nonunique")
-		extends = extends || (opt == "extends")
-	}
-	return rawName, omitEmpty, allowShadow, allowNonUnique, extends
-}
-
-// mapToField maps the given value to the matching field of the given section.
-// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
-func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		isStruct := tpField.Type.Kind() == reflect.Struct
-		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
-		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
-		if isAnonymousPtr {
-			field.Set(reflect.New(tpField.Type.Elem()))
-		}
-
-		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) {
-			if isStructPtr && field.IsNil() {
-				field.Set(reflect.New(tpField.Type.Elem()))
-			}
-			fieldSection := s
-			if rawName != "" {
-				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName
-				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) {
-					fieldSection = secs[sectionIndex]
-				}
-			}
-			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil {
-				return fmt.Errorf("map to field %q: %v", fieldName, err)
-			}
-		} else if isAnonymousPtr || isStruct || isStructPtr {
-			if secs, err := s.f.SectionsByName(fieldName); err == nil {
-				if len(secs) <= sectionIndex {
-					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
-				}
-				// Only set the field to non-nil struct value if we have a section for it.
-				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
-				if isStructPtr && field.IsNil() {
-					field.Set(reflect.New(tpField.Type.Elem()))
-				}
-				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil {
-					return fmt.Errorf("map to field %q: %v", fieldName, err)
-				}
-				continue
-			}
-		}
-
-		// Map non-unique sections
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			newField, err := s.mapToSlice(fieldName, field, isStrict)
-			if err != nil {
-				return fmt.Errorf("map to slice %q: %v", fieldName, err)
-			}
-
-			field.Set(newField)
-			continue
-		}
-
-		if key, err := s.GetKey(fieldName); err == nil {
-			delim := parseDelim(tpField.Tag.Get("delim"))
-			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
-				return fmt.Errorf("set field %q: %v", fieldName, err)
-			}
-		}
-	}
-	return nil
-}
-
-// mapToSlice maps all sections with the same name and returns the new value.
-// The type of the Value must be a slice.
-func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
-	secs, err := s.f.SectionsByName(secName)
-	if err != nil {
-		return reflect.Value{}, err
-	}
-
-	typ := val.Type().Elem()
-	for i, sec := range secs {
-		elem := reflect.New(typ)
-		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
-			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
-		}
-
-		val = reflect.Append(val, elem.Elem())
-	}
-	return val, nil
-}
-
-// mapTo maps a section to object v.
-func (s *Section) mapTo(v interface{}, isStrict bool) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-	if typ.Kind() == reflect.Ptr {
-		typ = typ.Elem()
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	if typ.Kind() == reflect.Slice {
-		newField, err := s.mapToSlice(s.name, val, isStrict)
-		if err != nil {
-			return err
-		}
-
-		val.Set(newField)
-		return nil
-	}
-
-	return s.mapToField(val, isStrict, 0, s.name)
-}
-
-// MapTo maps section to given struct.
-func (s *Section) MapTo(v interface{}) error {
-	return s.mapTo(v, false)
-}
-
-// StrictMapTo maps section to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (s *Section) StrictMapTo(v interface{}) error {
-	return s.mapTo(v, true)
-}
-
-// MapTo maps file to given struct.
-func (f *File) MapTo(v interface{}) error {
-	return f.Section("").MapTo(v)
-}
-
-// StrictMapTo maps file to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (f *File) StrictMapTo(v interface{}) error {
-	return f.Section("").StrictMapTo(v)
-}
-
-// MapToWithMapper maps data sources to given struct with name mapper.
-func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.MapTo(v)
-}
-
-// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.StrictMapTo(v)
-}
-
-// MapTo maps data sources to given struct.
-func MapTo(v, source interface{}, others ...interface{}) error {
-	return MapToWithMapper(v, nil, source, others...)
-}
-
-// StrictMapTo maps data sources to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapTo(v, source interface{}, others ...interface{}) error {
-	return StrictMapToWithMapper(v, nil, source, others...)
-}
-
-// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
-func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	slice := field.Slice(0, field.Len())
-	if field.Len() == 0 {
-		return nil
-	}
-	sliceOf := field.Type().Elem().Kind()
-
-	if allowShadow {
-		var keyWithShadows *Key
-		for i := 0; i < field.Len(); i++ {
-			var val string
-			switch sliceOf {
-			case reflect.String:
-				val = slice.Index(i).String()
-			case reflect.Int, reflect.Int64:
-				val = fmt.Sprint(slice.Index(i).Int())
-			case reflect.Uint, reflect.Uint64:
-				val = fmt.Sprint(slice.Index(i).Uint())
-			case reflect.Float64:
-				val = fmt.Sprint(slice.Index(i).Float())
-			case reflect.Bool:
-				val = fmt.Sprint(slice.Index(i).Bool())
-			case reflectTime:
-				val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
-			default:
-				return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-			}
-
-			if i == 0 {
-				keyWithShadows = newKey(key.s, key.name, val)
-			} else {
-				_ = keyWithShadows.AddShadow(val)
-			}
-		}
-		*key = *keyWithShadows
-		return nil
-	}
-
-	var buf bytes.Buffer
-	for i := 0; i < field.Len(); i++ {
-		switch sliceOf {
-		case reflect.String:
-			buf.WriteString(slice.Index(i).String())
-		case reflect.Int, reflect.Int64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
-		case reflect.Uint, reflect.Uint64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
-		case reflect.Float64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
-		case reflect.Bool:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
-		case reflectTime:
-			buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
-		default:
-			return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-		}
-		buf.WriteString(delim)
-	}
-	key.SetValue(buf.String()[:buf.Len()-len(delim)])
-	return nil
-}
-
-// reflectWithProperType does the opposite thing as setWithProperType.
-func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	switch t.Kind() {
-	case reflect.String:
-		key.SetValue(field.String())
-	case reflect.Bool:
-		key.SetValue(fmt.Sprint(field.Bool()))
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		key.SetValue(fmt.Sprint(field.Int()))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		key.SetValue(fmt.Sprint(field.Uint()))
-	case reflect.Float32, reflect.Float64:
-		key.SetValue(fmt.Sprint(field.Float()))
-	case reflectTime:
-		key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
-	case reflect.Slice:
-		return reflectSliceWithProperType(key, field, delim, allowShadow)
-	case reflect.Ptr:
-		if !field.IsNil() {
-			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
-		}
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-// CR: copied from encoding/json/encode.go with modifications of time.Time support.
-// TODO: add more test coverage.
-func isEmptyValue(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	case reflectTime:
-		t, ok := v.Interface().(time.Time)
-		return ok && t.IsZero()
-	}
-	return false
-}
-
-// StructReflector is the interface implemented by struct types that can extract themselves into INI objects.
-type StructReflector interface {
-	ReflectINIStruct(*File) error
-}
-
-func (s *Section) reflectFrom(val reflect.Value) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		if !val.Field(i).CanInterface() {
-			continue
-		}
-
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		if omitEmpty && isEmptyValue(field) {
-			continue
-		}
-
-		if r, ok := field.Interface().(StructReflector); ok {
-			return r.ReflectINIStruct(s.f)
-		}
-
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
-			if err := s.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
-			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
-			// Note: The only error here is section doesn't exist.
-			sec, err := s.f.GetSection(fieldName)
-			if err != nil {
-				// Note: fieldName can never be empty here, ignore error.
-				sec, _ = s.f.NewSection(fieldName)
-			}
-
-			// Add comment from comment tag
-			if len(sec.Comment) == 0 {
-				sec.Comment = tpField.Tag.Get("comment")
-			}
-
-			if err = sec.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			slice := field.Slice(0, field.Len())
-			if field.Len() == 0 {
-				return nil
-			}
-			sliceOf := field.Type().Elem().Kind()
-
-			for i := 0; i < field.Len(); i++ {
-				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
-					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
-				}
-
-				sec, err := s.f.NewSection(fieldName)
-				if err != nil {
-					return err
-				}
-
-				// Add comment from comment tag
-				if len(sec.Comment) == 0 {
-					sec.Comment = tpField.Tag.Get("comment")
-				}
-
-				if err := sec.reflectFrom(slice.Index(i)); err != nil {
-					return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-				}
-			}
-			continue
-		}
-
-		// Note: Same reason as section.
-		key, err := s.GetKey(fieldName)
-		if err != nil {
-			key, _ = s.NewKey(fieldName, "")
-		}
-
-		// Add comment from comment tag
-		if len(key.Comment) == 0 {
-			key.Comment = tpField.Tag.Get("comment")
-		}
-
-		delim := parseDelim(tpField.Tag.Get("delim"))
-		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
-			return fmt.Errorf("reflect field %q: %v", fieldName, err)
-		}
-
-	}
-	return nil
-}
-
-// ReflectFrom reflects section from given struct. It overwrites existing ones.
-func (s *Section) ReflectFrom(v interface{}) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-
-	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
-		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
-		// Clear sections to make sure none exists before adding the new ones
-		s.f.DeleteSection(s.name)
-
-		if typ.Kind() == reflect.Ptr {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-			return sec.reflectFrom(val.Elem())
-		}
-
-		slice := val.Slice(0, val.Len())
-		sliceOf := val.Type().Elem().Kind()
-		if sliceOf != reflect.Ptr {
-			return fmt.Errorf("not a slice of pointers")
-		}
-
-		for i := 0; i < slice.Len(); i++ {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-
-			err = sec.reflectFrom(slice.Index(i))
-			if err != nil {
-				return fmt.Errorf("reflect from %dth field: %v", i, err)
-			}
-		}
-
-		return nil
-	}
-
-	if typ.Kind() == reflect.Ptr {
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	return s.reflectFrom(val)
-}
-
-// ReflectFrom reflects file from given struct.
-func (f *File) ReflectFrom(v interface{}) error {
-	return f.Section("").ReflectFrom(v)
-}
-
-// ReflectFromWithMapper reflects data sources from given struct with name mapper.
-func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
-	cfg.NameMapper = mapper
-	return cfg.ReflectFrom(v)
-}
-
-// ReflectFrom reflects data sources from given struct.
-func ReflectFrom(cfg *File, v interface{}) error {
-	return ReflectFromWithMapper(cfg, v, nil)
-}
diff --git a/history-api/vendor/gorm.io/gorm/association.go b/history-api/vendor/gorm.io/gorm/association.go
index e3f51d17..f210ca0a 100644
--- a/history-api/vendor/gorm.io/gorm/association.go
+++ b/history-api/vendor/gorm.io/gorm/association.go
@@ -19,10 +19,10 @@ type Association struct {
 }
 
 func (db *DB) Association(column string) *Association {
-	association := &Association{DB: db}
+	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
 	table := db.Statement.Table
 
-	if err := db.Statement.Parse(db.Statement.Model); err == nil {
+	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
 		db.Statement.Table = table
 		association.Relationship = db.Statement.Schema.Relationships.Relations[column]
 
@@ -34,8 +34,6 @@ func (db *DB) Association(column string) *Association {
 		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
 			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
 		}
-	} else {
-		association.Error = err
 	}
 
 	return association
@@ -58,6 +56,8 @@ func (association *Association) Find(out interface{}, conds ...interface{}) erro
 }
 
 func (association *Association) Append(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		switch association.Relationship.Type {
 		case schema.HasOne, schema.BelongsTo:
@@ -73,6 +73,8 @@ func (association *Association) Append(values ...interface{}) error {
 }
 
 func (association *Association) Replace(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		reflectValue := association.DB.Statement.ReflectValue
 		rel := association.Relationship
@@ -195,6 +197,8 @@ func (association *Association) Replace(values ...interface{}) error {
 }
 
 func (association *Association) Delete(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		var (
 			reflectValue  = association.DB.Statement.ReflectValue
@@ -431,10 +435,49 @@ func (association *Association) saveAssociation(clear bool, values ...interface{
 				}
 			}
 
+			processMap := func(mapv reflect.Value) {
+				child := reflect.New(association.Relationship.FieldSchema.ModelType)
+
+				switch association.Relationship.Type {
+				case schema.HasMany:
+					for _, ref := range association.Relationship.References {
+						key := reflect.ValueOf(ref.ForeignKey.DBName)
+						if ref.OwnPrimaryKey {
+							v := ref.PrimaryKey.ReflectValueOf(association.DB.Statement.Context, source)
+							mapv.SetMapIndex(key, v)
+						} else if ref.PrimaryValue != "" {
+							mapv.SetMapIndex(key, reflect.ValueOf(ref.PrimaryValue))
+						}
+					}
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+				case schema.Many2Many:
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+
+					for _, key := range mapv.MapKeys() {
+						k := strings.ToLower(key.String())
+						if f, ok := association.Relationship.FieldSchema.FieldsByDBName[k]; ok {
+							_ = f.Set(association.DB.Statement.Context, child, mapv.MapIndex(key).Interface())
+						}
+					}
+					appendToFieldValues(child)
+				}
+			}
+
 			switch rv.Kind() {
+			case reflect.Map:
+				processMap(rv)
 			case reflect.Slice, reflect.Array:
 				for i := 0; i < rv.Len(); i++ {
-					appendToFieldValues(reflect.Indirect(rv.Index(i)).Addr())
+					elem := reflect.Indirect(rv.Index(i))
+					if elem.Kind() == reflect.Map {
+						processMap(elem)
+						continue
+					}
+					appendToFieldValues(elem.Addr())
 				}
 			case reflect.Struct:
 				if !rv.CanAddr() {
@@ -591,3 +634,32 @@ func (association *Association) buildCondition() *DB {
 
 	return tx
 }
+
+func expandValues(values ...any) (results []any) {
+	appendToResult := func(rv reflect.Value) {
+		// unwrap interface
+		if rv.IsValid() && rv.Kind() == reflect.Interface {
+			rv = rv.Elem()
+		}
+		if rv.IsValid() && rv.Kind() == reflect.Struct {
+			p := reflect.New(rv.Type())
+			p.Elem().Set(rv)
+			results = append(results, p.Interface())
+		} else if rv.IsValid() {
+			results = append(results, rv.Interface())
+		}
+	}
+
+	// Process each argument; if an argument is a slice/array, expand its elements
+	for _, value := range values {
+		rv := reflect.ValueOf(value)
+		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
+			for i := 0; i < rv.Len(); i++ {
+				appendToResult(rv.Index(i))
+			}
+		} else {
+			appendToResult(rv)
+		}
+	}
+	return
+}
diff --git a/history-api/vendor/gorm.io/gorm/callbacks.go b/history-api/vendor/gorm.io/gorm/callbacks.go
index 50b5b0e9..bd97f040 100644
--- a/history-api/vendor/gorm.io/gorm/callbacks.go
+++ b/history-api/vendor/gorm.io/gorm/callbacks.go
@@ -89,10 +89,16 @@ func (p *processor) Execute(db *DB) *DB {
 		resetBuildClauses = true
 	}
 
-	if optimizer, ok := db.Statement.Dest.(StatementModifier); ok {
+	if optimizer, ok := stmt.Dest.(StatementModifier); ok {
 		optimizer.ModifyStatement(stmt)
 	}
 
+	if db.DefaultContextTimeout > 0 {
+		if _, ok := stmt.Context.Deadline(); !ok {
+			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
+		}
+	}
+
 	// assign model values
 	if stmt.Model == nil {
 		stmt.Model = stmt.Dest
diff --git a/history-api/vendor/gorm.io/gorm/callbacks/create.go b/history-api/vendor/gorm.io/gorm/callbacks/create.go
index d8701f51..e5929adb 100644
--- a/history-api/vendor/gorm.io/gorm/callbacks/create.go
+++ b/history-api/vendor/gorm.io/gorm/callbacks/create.go
@@ -53,9 +53,13 @@ func Create(config *Config) func(db *gorm.DB) {
 				if _, ok := db.Statement.Clauses["RETURNING"]; !ok {
 					fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue))
 					for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue {
-						fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						if field.Readable {
+							fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						}
+					}
+					if len(fromColumns) > 0 {
+						db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 					}
-					db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 				}
 			}
 		}
@@ -76,8 +80,11 @@ func Create(config *Config) func(db *gorm.DB) {
 		ok, mode := hasReturning(db, supportReturning)
 		if ok {
 			if c, ok := db.Statement.Clauses["ON CONFLICT"]; ok {
-				if onConflict, _ := c.Expression.(clause.OnConflict); onConflict.DoNothing {
+				onConflict, _ := c.Expression.(clause.OnConflict)
+				if onConflict.DoNothing {
 					mode |= gorm.ScanOnConflictDoNothing
+				} else if len(onConflict.DoUpdates) > 0 || onConflict.UpdateAll {
+					mode |= gorm.ScanUpdate
 				}
 			}
 
@@ -122,6 +129,16 @@ func Create(config *Config) func(db *gorm.DB) {
 			pkFieldName = "@id"
 		)
 
+		if db.Statement.Schema != nil {
+			if db.Statement.Schema.PrioritizedPrimaryField == nil ||
+				!db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue ||
+				!db.Statement.Schema.PrioritizedPrimaryField.Readable {
+				return
+			}
+			pkField = db.Statement.Schema.PrioritizedPrimaryField
+			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
+		}
+
 		insertID, err := result.LastInsertId()
 		insertOk := err == nil && insertID > 0
 
@@ -132,14 +149,6 @@ func Create(config *Config) func(db *gorm.DB) {
 			return
 		}
 
-		if db.Statement.Schema != nil {
-			if db.Statement.Schema.PrioritizedPrimaryField == nil || !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue {
-				return
-			}
-			pkField = db.Statement.Schema.PrioritizedPrimaryField
-			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
-		}
-
 		// append @id column with value for auto-increment primary key
 		// the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1
 		switch values := db.Statement.Dest.(type) {
diff --git a/history-api/vendor/gorm.io/gorm/clause/association.go b/history-api/vendor/gorm.io/gorm/clause/association.go
new file mode 100644
index 00000000..a9bf7eb0
--- /dev/null
+++ b/history-api/vendor/gorm.io/gorm/clause/association.go
@@ -0,0 +1,35 @@
+package clause
+
+// AssociationOpType represents association operation types
+type AssociationOpType int
+
+const (
+	OpUnlink AssociationOpType = iota // Unlink association
+	OpDelete                          // Delete association records
+	OpUpdate                          // Update association records
+	OpCreate                          // Create association records with assignments
+)
+
+// Association represents an association operation
+type Association struct {
+	Association string            // Association name
+	Type        AssociationOpType // Operation type
+	Conditions  []Expression      // Filter conditions
+	Set         []Assignment      // Assignment operations (for Update and Create)
+	Values      []interface{}     // Values for Create operation
+}
+
+// AssociationAssigner is an interface for association operation providers
+type AssociationAssigner interface {
+	AssociationAssignments() []Association
+}
+
+// Assignments implements the Assigner interface so that AssociationOperation can be used as a Set method parameter
+func (ao Association) Assignments() []Assignment {
+	return []Assignment{}
+}
+
+// AssociationAssignments implements the AssociationAssigner interface
+func (ao Association) AssociationAssignments() []Association {
+	return []Association{ao}
+}
diff --git a/history-api/vendor/gorm.io/gorm/clause/set.go b/history-api/vendor/gorm.io/gorm/clause/set.go
index 75eb6bdd..cb5f36a0 100644
--- a/history-api/vendor/gorm.io/gorm/clause/set.go
+++ b/history-api/vendor/gorm.io/gorm/clause/set.go
@@ -9,6 +9,11 @@ type Assignment struct {
 	Value  interface{}
 }
 
+// Assigner assignments provider interface
+type Assigner interface {
+	Assignments() []Assignment
+}
+
 func (set Set) Name() string {
 	return "SET"
 }
@@ -37,6 +42,9 @@ func (set Set) MergeClause(clause *Clause) {
 	clause.Expression = Set(copiedAssignments)
 }
 
+// Assignments implements Assigner for Set.
+func (set Set) Assignments() []Assignment { return []Assignment(set) }
+
 func Assignments(values map[string]interface{}) Set {
 	keys := make([]string, 0, len(values))
 	for key := range values {
@@ -58,3 +66,6 @@ func AssignmentColumns(values []string) Set {
 	}
 	return assignments
 }
+
+// Assignments implements Assigner for a single Assignment.
+func (a Assignment) Assignments() []Assignment { return []Assignment{a} }
diff --git a/history-api/vendor/gorm.io/gorm/finisher_api.go b/history-api/vendor/gorm.io/gorm/finisher_api.go
index 57809d17..e601fe66 100644
--- a/history-api/vendor/gorm.io/gorm/finisher_api.go
+++ b/history-api/vendor/gorm.io/gorm/finisher_api.go
@@ -675,9 +675,9 @@ func (db *DB) Begin(opts ...*sql.TxOptions) *DB {
 	}
 
 	ctx := tx.Statement.Context
-	if _, ok := ctx.Deadline(); !ok {
-		if db.Config.DefaultTransactionTimeout > 0 {
-			ctx, _ = context.WithTimeout(ctx, db.Config.DefaultTransactionTimeout)
+	if db.DefaultTransactionTimeout > 0 {
+		if _, ok := ctx.Deadline(); !ok {
+			ctx, _ = context.WithTimeout(ctx, db.DefaultTransactionTimeout)
 		}
 	}
 
diff --git a/history-api/vendor/gorm.io/gorm/generics.go b/history-api/vendor/gorm.io/gorm/generics.go
index ad2d063f..79238d5f 100644
--- a/history-api/vendor/gorm.io/gorm/generics.go
+++ b/history-api/vendor/gorm.io/gorm/generics.go
@@ -3,12 +3,15 @@ package gorm
 import (
 	"context"
 	"database/sql"
+	"errors"
 	"fmt"
+	"reflect"
 	"sort"
 	"strings"
 
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/logger"
+	"gorm.io/gorm/schema"
 )
 
 type result struct {
@@ -35,10 +38,34 @@ type Interface[T any] interface {
 }
 
 type CreateInterface[T any] interface {
-	ChainInterface[T]
+	ExecInterface[T]
+	// chain methods available at start; return ChainInterface
+	Scopes(scopes ...func(db *Statement)) ChainInterface[T]
+	Where(query interface{}, args ...interface{}) ChainInterface[T]
+	Not(query interface{}, args ...interface{}) ChainInterface[T]
+	Or(query interface{}, args ...interface{}) ChainInterface[T]
+	Limit(offset int) ChainInterface[T]
+	Offset(offset int) ChainInterface[T]
+	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[T]
+	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[T]
+	Select(query string, args ...interface{}) ChainInterface[T]
+	Omit(columns ...string) ChainInterface[T]
+	MapColumns(m map[string]string) ChainInterface[T]
+	Distinct(args ...interface{}) ChainInterface[T]
+	Group(name string) ChainInterface[T]
+	Having(query interface{}, args ...interface{}) ChainInterface[T]
+	Order(value interface{}) ChainInterface[T]
+	Build(builder clause.Builder)
+
+	Delete(ctx context.Context) (rowsAffected int, err error)
+	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
+	Updates(ctx context.Context, t T) (rowsAffected int, err error)
+	Count(ctx context.Context, column string) (result int64, err error)
+
 	Table(name string, args ...interface{}) CreateInterface[T]
 	Create(ctx context.Context, r *T) error
 	CreateInBatches(ctx context.Context, r *[]T, batchSize int) error
+	Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T]
 }
 
 type ChainInterface[T any] interface {
@@ -58,15 +85,28 @@ type ChainInterface[T any] interface {
 	Group(name string) ChainInterface[T]
 	Having(query interface{}, args ...interface{}) ChainInterface[T]
 	Order(value interface{}) ChainInterface[T]
+	Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T]
 
 	Build(builder clause.Builder)
 
+	Table(name string, args ...interface{}) ChainInterface[T]
 	Delete(ctx context.Context) (rowsAffected int, err error)
 	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
 	Updates(ctx context.Context, t T) (rowsAffected int, err error)
 	Count(ctx context.Context, column string) (result int64, err error)
 }
 
+// SetUpdateOnlyInterface is returned by Set after chaining; only Update is allowed
+type SetUpdateOnlyInterface[T any] interface {
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
+// SetCreateOrUpdateInterface is returned by Set at start; Create or Update are allowed
+type SetCreateOrUpdateInterface[T any] interface {
+	Create(ctx context.Context) error
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
 type ExecInterface[T any] interface {
 	Scan(ctx context.Context, r interface{}) error
 	First(context.Context) (T, error)
@@ -142,13 +182,15 @@ func (c *g[T]) Raw(sql string, values ...interface{}) ExecInterface[T] {
 	return execG[T]{g: &g[T]{
 		db: c.db,
 		ops: append(c.ops, func(db *DB) *DB {
-			return db.Raw(sql, values...)
+			var r T
+			return db.Model(r).Raw(sql, values...)
 		}),
 	}}
 }
 
 func (c *g[T]) Exec(ctx context.Context, sql string, values ...interface{}) error {
-	return c.apply(ctx).Exec(sql, values...).Error
+	var r T
+	return c.apply(ctx).Model(r).Exec(sql, values...).Error
 }
 
 type createG[T any] struct {
@@ -161,6 +203,10 @@ func (c createG[T]) Table(name string, args ...interface{}) CreateInterface[T] {
 	})}
 }
 
+func (c createG[T]) Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c createG[T]) Create(ctx context.Context, r *T) error {
 	return c.g.apply(ctx).Create(r).Error
 }
@@ -187,6 +233,12 @@ func (c chainG[T]) with(v op) chainG[T] {
 	}
 }
 
+func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
+	return c.with(func(db *DB) *DB {
+		return db.Table(name, args...)
+	})
+}
+
 func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		for _, fc := range scopes {
@@ -196,12 +248,6 @@ func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	})
 }
 
-func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
-	return c.with(func(db *DB) *DB {
-		return db.Table(name, args...)
-	})
-}
-
 func (c chainG[T]) Where(query interface{}, args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Where(query, args...)
@@ -388,6 +434,10 @@ func (c chainG[T]) MapColumns(m map[string]string) ChainInterface[T] {
 	})
 }
 
+func (c chainG[T]) Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c chainG[T]) Distinct(args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Distinct(args...)
@@ -425,12 +475,12 @@ func (c chainG[T]) Preload(association string, query func(db PreloadBuilder) err
 			relation, ok := db.Statement.Schema.Relationships.Relations[association]
 			if !ok {
 				if preloadFields := strings.Split(association, "."); len(preloadFields) > 1 {
-					relationships := db.Statement.Schema.Relationships
+					relationships := &db.Statement.Schema.Relationships
 					for _, field := range preloadFields {
 						var ok bool
 						relation, ok = relationships.Relations[field]
 						if ok {
-							relationships = relation.FieldSchema.Relationships
+							relationships = &relation.FieldSchema.Relationships
 						} else {
 							db.AddError(fmt.Errorf("relation %s not found", association))
 							return nil
@@ -567,7 +617,7 @@ func (g execG[T]) First(ctx context.Context) (T, error) {
 
 func (g execG[T]) Scan(ctx context.Context, result interface{}) error {
 	var r T
-	err := g.g.apply(ctx).Model(r).Find(&result).Error
+	err := g.g.apply(ctx).Model(r).Find(result).Error
 	return err
 }
 
@@ -603,3 +653,242 @@ func (g execG[T]) Row(ctx context.Context) *sql.Row {
 func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) {
 	return g.g.apply(ctx).Rows()
 }
+
+func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdateG[T] {
+	var (
+		assigns  []clause.Assignment
+		assocOps []clause.Association
+	)
+
+	for _, item := range items {
+		// Check if it's an AssociationAssigner
+		if assocAssigner, ok := item.(clause.AssociationAssigner); ok {
+			assocOps = append(assocOps, assocAssigner.AssociationAssignments()...)
+		} else {
+			assigns = append(assigns, item.Assignments()...)
+		}
+	}
+
+	return setCreateOrUpdateG[T]{
+		c:        c,
+		assigns:  assigns,
+		assocOps: assocOps,
+	}
+}
+
+// setCreateOrUpdateG[T] is a struct that holds operations to be executed in a batch.
+// It supports regular assignments and association operations.
+type setCreateOrUpdateG[T any] struct {
+	c        chainG[T]
+	assigns  []clause.Assignment
+	assocOps []clause.Association
+}
+
+func (s setCreateOrUpdateG[T]) Update(ctx context.Context) (rowsAffected int, err error) {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return 0, err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		var r T
+		res := s.c.g.apply(ctx).Model(r).Clauses(clause.Set(s.assigns)).Updates(map[string]interface{}{})
+		return int(res.RowsAffected), res.Error
+	}
+
+	return 0, nil
+}
+
+func (s setCreateOrUpdateG[T]) Create(ctx context.Context) error {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		data := make(map[string]interface{}, len(s.assigns))
+		for _, a := range s.assigns {
+			data[a.Column.Name] = a.Value
+		}
+		var r T
+		return s.c.g.apply(ctx).Model(r).Create(data).Error
+	}
+
+	return nil
+}
+
+// executeAssociationOperation executes an association operation
+func (s setCreateOrUpdateG[T]) executeAssociationOperation(ctx context.Context, op clause.Association) error {
+	var r T
+	base := s.c.g.apply(ctx).Model(r)
+
+	switch op.Type {
+	case clause.OpCreate:
+		return s.handleAssociationCreate(ctx, base, op)
+	case clause.OpUnlink, clause.OpDelete, clause.OpUpdate:
+		return s.handleAssociation(ctx, base, op)
+	default:
+		return fmt.Errorf("unknown association operation type: %v", op.Type)
+	}
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociationCreate(ctx context.Context, base *DB, op clause.Association) error {
+	if len(op.Set) > 0 {
+		return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+			data := make(map[string]interface{}, len(op.Set))
+			for _, a := range op.Set {
+				data[a.Column.Name] = a.Value
+			}
+			return assoc.Append(data)
+		}, op.Association)
+	}
+
+	return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+		return assoc.Append(op.Values...)
+	}, op.Association)
+}
+
+// handleAssociationForOwners is a helper function that handles associations for all owners
+func (s setCreateOrUpdateG[T]) handleAssociationForOwners(base *DB, ctx context.Context, handler func(owner T, association *Association) error, associationName string) error {
+	var owners []T
+	if err := base.Find(&owners).Error; err != nil {
+		return err
+	}
+
+	for _, owner := range owners {
+		assoc := base.Session(&Session{NewDB: true, Context: ctx}).Model(&owner).Association(associationName)
+		if assoc.Error != nil {
+			return assoc.Error
+		}
+
+		if err := handler(owner, assoc); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, base *DB, op clause.Association) error {
+	assoc := base.Association(op.Association)
+	if assoc.Error != nil {
+		return assoc.Error
+	}
+
+	var (
+		rel            = assoc.Relationship
+		assocModel     = reflect.New(rel.FieldSchema.ModelType).Interface()
+		fkNil          = map[string]any{}
+		setMap         = make(map[string]any, len(op.Set))
+		ownerPKNames   []string
+		ownerFKNames   []string
+		primaryColumns []any
+		foreignColumns []any
+	)
+
+	for _, a := range op.Set {
+		setMap[a.Column.Name] = a.Value
+	}
+
+	for _, ref := range rel.References {
+		fkNil[ref.ForeignKey.DBName] = nil
+
+		if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerPKNames = append(ownerPKNames, ref.PrimaryKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+			foreignColumns = append(foreignColumns, clause.Column{Name: ref.ForeignKey.DBName})
+		} else if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerFKNames = append(ownerFKNames, ref.ForeignKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+		}
+	}
+
+	assocDB := s.c.g.db.Session(&Session{NewDB: true, Context: ctx}).Model(assocModel).Where(op.Conditions)
+
+	switch rel.Type {
+	case schema.HasOne, schema.HasMany:
+		assocDB = assocDB.Where("? IN (?)", foreignColumns, base.Select(ownerPKNames))
+		switch op.Type {
+		case clause.OpUnlink:
+			return assocDB.Updates(fkNil).Error
+		case clause.OpDelete:
+			return assocDB.Delete(assocModel).Error
+		case clause.OpUpdate:
+			return assocDB.Updates(setMap).Error
+		}
+	case schema.BelongsTo:
+		switch op.Type {
+		case clause.OpDelete:
+			return base.Transaction(func(tx *DB) error {
+				assocDB.Statement.ConnPool = tx.Statement.ConnPool
+				base.Statement.ConnPool = tx.Statement.ConnPool
+
+				if err := assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Delete(assocModel).Error; err != nil {
+					return err
+				}
+				return base.Updates(fkNil).Error
+			})
+		case clause.OpUnlink:
+			return base.Updates(fkNil).Error
+		case clause.OpUpdate:
+			return assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Updates(setMap).Error
+		}
+	case schema.Many2Many:
+		joinModel := reflect.New(rel.JoinTable.ModelType).Interface()
+		joinDB := base.Session(&Session{NewDB: true, Context: ctx}).Model(joinModel)
+
+		// EXISTS owners: owners.pk = join.owner_fk for all owner refs
+		ownersExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.Schema.Table).Select("1")
+		for _, ref := range rel.References {
+			if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				ownersExists = ownersExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.Schema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+
+		// EXISTS related: related.pk = join.rel_fk for all related refs, plus optional conditions
+		relatedExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Select("1")
+		for _, ref := range rel.References {
+			if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				relatedExists = relatedExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+		relatedExists = relatedExists.Where(op.Conditions)
+
+		switch op.Type {
+		case clause.OpUnlink, clause.OpDelete:
+			joinDB = joinDB.Where("EXISTS (?)", ownersExists)
+			if len(op.Conditions) > 0 {
+				joinDB = joinDB.Where("EXISTS (?)", relatedExists)
+			}
+			return joinDB.Delete(nil).Error
+		case clause.OpUpdate:
+			// Update related table rows that have join rows matching owners
+			relatedDB := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Where(op.Conditions)
+
+			// correlated join subquery: join.rel_fk = related.pk AND EXISTS owners
+			joinSub := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.JoinTable.Table).Select("1")
+			for _, ref := range rel.References {
+				if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+					joinSub = joinSub.Where(clause.Eq{
+						Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+						Value:  clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					})
+				}
+			}
+			joinSub = joinSub.Where("EXISTS (?)", ownersExists)
+			return relatedDB.Where("EXISTS (?)", joinSub).Updates(setMap).Error
+		}
+	}
+	return errors.New("unsupported relationship")
+}
diff --git a/history-api/vendor/gorm.io/gorm/gorm.go b/history-api/vendor/gorm.io/gorm/gorm.go
index 67889262..a209bb09 100644
--- a/history-api/vendor/gorm.io/gorm/gorm.go
+++ b/history-api/vendor/gorm.io/gorm/gorm.go
@@ -23,6 +23,7 @@ type Config struct {
 	// You can disable it by setting `SkipDefaultTransaction` to true
 	SkipDefaultTransaction    bool
 	DefaultTransactionTimeout time.Duration
+	DefaultContextTimeout     time.Duration
 
 	// NamingStrategy tables, columns naming strategy
 	NamingStrategy schema.Namer
@@ -137,6 +138,14 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
 		return isConfig && !isConfig2
 	})
 
+	if len(opts) > 0 {
+		if c, ok := opts[0].(*Config); ok {
+			config = c
+		} else {
+			opts = append([]Option{config}, opts...)
+		}
+	}
+
 	var skipAfterInitialize bool
 	for _, opt := range opts {
 		if opt != nil {
diff --git a/history-api/vendor/gorm.io/gorm/logger/slog.go b/history-api/vendor/gorm.io/gorm/logger/slog.go
new file mode 100644
index 00000000..613234ca
--- /dev/null
+++ b/history-api/vendor/gorm.io/gorm/logger/slog.go
@@ -0,0 +1,100 @@
+//go:build go1.21
+
+package logger
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"log/slog"
+	"time"
+)
+
+type slogLogger struct {
+	Logger                    *slog.Logger
+	LogLevel                  LogLevel
+	SlowThreshold             time.Duration
+	Parameterized             bool
+	Colorful                  bool // Ignored in slog
+	IgnoreRecordNotFoundError bool
+}
+
+func NewSlogLogger(logger *slog.Logger, config Config) Interface {
+	return &slogLogger{
+		Logger:                    logger,
+		LogLevel:                  config.LogLevel,
+		SlowThreshold:             config.SlowThreshold,
+		Parameterized:             config.ParameterizedQueries,
+		IgnoreRecordNotFoundError: config.IgnoreRecordNotFoundError,
+	}
+}
+
+func (l *slogLogger) LogMode(level LogLevel) Interface {
+	newLogger := *l
+	newLogger.LogLevel = level
+	return &newLogger
+}
+
+func (l *slogLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Info {
+		l.Logger.InfoContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Warn {
+		l.Logger.WarnContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Error {
+		l.Logger.ErrorContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	if l.LogLevel <= Silent {
+		return
+	}
+
+	elapsed := time.Since(begin)
+	sql, rows := fc()
+	fields := []slog.Attr{
+		slog.String("duration", fmt.Sprintf("%.3fms", float64(elapsed.Nanoseconds())/1e6)),
+		slog.String("sql", sql),
+	}
+
+	if rows != -1 {
+		fields = append(fields, slog.Int64("rows", rows))
+	}
+
+	switch {
+	case err != nil && (!l.IgnoreRecordNotFoundError || !errors.Is(err, ErrRecordNotFound)):
+		fields = append(fields, slog.String("error", err.Error()))
+		l.Logger.ErrorContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.SlowThreshold != 0 && elapsed > l.SlowThreshold:
+		l.Logger.WarnContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.LogLevel >= Info:
+		l.Logger.InfoContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+	}
+}
+
+// ParamsFilter filter params
+func (l *slogLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) {
+	if l.Parameterized {
+		return sql, nil
+	}
+	return sql, params
+}
diff --git a/history-api/vendor/gorm.io/gorm/migrator/migrator.go b/history-api/vendor/gorm.io/gorm/migrator/migrator.go
index cec4e30f..50a36d10 100644
--- a/history-api/vendor/gorm.io/gorm/migrator/migrator.go
+++ b/history-api/vendor/gorm.io/gorm/migrator/migrator.go
@@ -474,7 +474,6 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 	// found, smart migrate
 	fullDataType := strings.TrimSpace(strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL))
 	realDataType := strings.ToLower(columnType.DatabaseTypeName())
-
 	var (
 		alterColumn bool
 		isSameType  = fullDataType == realDataType
@@ -513,8 +512,19 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 				}
 			}
 		}
+	}
 
-		// check precision
+	// check precision
+	if realDataType == "decimal" || realDataType == "numeric" &&
+		regexp.MustCompile(realDataType+`\(.*\)`).FindString(fullDataType) != "" { // if realDataType has no precision,ignore
+		precision, scale, ok := columnType.DecimalSize()
+		if ok {
+			if !strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d,%d)", realDataType, precision, scale)) &&
+				!strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d)", realDataType, precision)) {
+				alterColumn = true
+			}
+		}
+	} else {
 		if precision, _, ok := columnType.DecimalSize(); ok && int64(field.Precision) != precision {
 			if regexp.MustCompile(fmt.Sprintf("[^0-9]%d[^0-9]", field.Precision)).MatchString(m.DataTypeOf(field)) {
 				alterColumn = true
diff --git a/history-api/vendor/gorm.io/gorm/schema/field.go b/history-api/vendor/gorm.io/gorm/schema/field.go
index a6ff1a72..de797402 100644
--- a/history-api/vendor/gorm.io/gorm/schema/field.go
+++ b/history-api/vendor/gorm.io/gorm/schema/field.go
@@ -448,16 +448,17 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 }
 
 // create valuer, setter when parse struct
-func (field *Field) setupValuerAndSetter() {
+func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
 	// Setup NewValuePool
 	field.setupNewValuePool()
 
 	// ValueOf returns field's value and if it is zero
 	fieldIndex := field.StructField.Index[0]
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
-			fieldValue := reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
+			v = reflect.Indirect(v)
+			fieldValue := v.Field(fieldIndex)
 			return fieldValue.Interface(), fieldValue.IsZero()
 		}
 	default:
@@ -504,9 +505,10 @@ func (field *Field) setupValuerAndSetter() {
 
 	// ReflectValueOf returns field's reflect value
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
-			return reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
+			v = reflect.Indirect(v)
+			return v.Field(fieldIndex)
 		}
 	default:
 		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
diff --git a/history-api/vendor/gorm.io/gorm/schema/relationship.go b/history-api/vendor/gorm.io/gorm/schema/relationship.go
index f1ace924..0535bba4 100644
--- a/history-api/vendor/gorm.io/gorm/schema/relationship.go
+++ b/history-api/vendor/gorm.io/gorm/schema/relationship.go
@@ -75,9 +75,7 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
 		}
 	)
 
-	cacheStore := schema.cacheStore
-
-	if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
+	if relation.FieldSchema, err = getOrParse(fieldValue, schema.cacheStore, schema.namer); err != nil {
 		schema.err = fmt.Errorf("failed to parse field: %s, error: %w", field.Name, err)
 		return nil
 	}
@@ -147,6 +145,9 @@ func hasPolymorphicRelation(tagSettings map[string]string) bool {
 }
 
 func (schema *Schema) setRelation(relation *Relationship) {
+	schema.Relationships.Mux.Lock()
+	defer schema.Relationships.Mux.Unlock()
+
 	// set non-embedded relation
 	if rel := schema.Relationships.Relations[relation.Name]; rel != nil {
 		if len(rel.Field.BindNames) > 1 {
@@ -590,6 +591,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 	// build references
 	for idx, foreignField := range foreignFields {
 		// use same data type for foreign keys
+		schema.Relationships.Mux.Lock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Lock()
+		}
 		if copyableDataType(primaryFields[idx].DataType) {
 			foreignField.DataType = primaryFields[idx].DataType
 		}
@@ -597,6 +602,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 		if foreignField.Size == 0 {
 			foreignField.Size = primaryFields[idx].Size
 		}
+		schema.Relationships.Mux.Unlock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Unlock()
+		}
 
 		relation.References = append(relation.References, &Reference{
 			PrimaryKey:    primaryFields[idx],
diff --git a/history-api/vendor/gorm.io/gorm/schema/schema.go b/history-api/vendor/gorm.io/gorm/schema/schema.go
index db236797..9419846b 100644
--- a/history-api/vendor/gorm.io/gorm/schema/schema.go
+++ b/history-api/vendor/gorm.io/gorm/schema/schema.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"go/ast"
+	"path"
 	"reflect"
 	"strings"
 	"sync"
@@ -59,14 +60,14 @@ type Schema struct {
 	cacheStore                *sync.Map
 }
 
-func (schema Schema) String() string {
+func (schema *Schema) String() string {
 	if schema.ModelType.Name() == "" {
 		return fmt.Sprintf("%s(%s)", schema.Name, schema.Table)
 	}
 	return fmt.Sprintf("%s.%s", schema.ModelType.PkgPath(), schema.ModelType.Name())
 }
 
-func (schema Schema) MakeSlice() reflect.Value {
+func (schema *Schema) MakeSlice() reflect.Value {
 	slice := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(schema.ModelType)), 0, 20)
 	results := reflect.New(slice.Type())
 	results.Elem().Set(slice)
@@ -74,7 +75,7 @@ func (schema Schema) MakeSlice() reflect.Value {
 	return results
 }
 
-func (schema Schema) LookUpField(name string) *Field {
+func (schema *Schema) LookUpField(name string) *Field {
 	if field, ok := schema.FieldsByDBName[name]; ok {
 		return field
 	}
@@ -92,10 +93,7 @@ func (schema Schema) LookUpField(name string) *Field {
 //		}
 //		ID string // is selected by LookUpFieldByBindName([]string{"ID"}, "ID")
 //	}
-func (schema Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
-	if len(bindNames) == 0 {
-		return nil
-	}
+func (schema *Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
 	for i := len(bindNames) - 1; i >= 0; i-- {
 		find := strings.Join(bindNames[:i], ".") + "." + name
 		if field, ok := schema.FieldsByBindName[find]; ok {
@@ -113,6 +111,14 @@ type TablerWithNamer interface {
 	TableName(Namer) string
 }
 
+var callbackTypes = []callbackType{
+	callbackTypeBeforeCreate, callbackTypeAfterCreate,
+	callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
+	callbackTypeBeforeSave, callbackTypeAfterSave,
+	callbackTypeBeforeDelete, callbackTypeAfterDelete,
+	callbackTypeAfterFind,
+}
+
 // Parse get data type from dialector
 func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	return ParseWithSpecialTableName(dest, cacheStore, namer, "")
@@ -124,34 +130,33 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
 	}
 
-	value := reflect.ValueOf(dest)
-	if value.Kind() == reflect.Ptr && value.IsNil() {
-		value = reflect.New(value.Type().Elem())
-	}
-	modelType := reflect.Indirect(value).Type()
-
-	if modelType.Kind() == reflect.Interface {
-		modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
-	}
-
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+	modelType := reflect.ValueOf(dest).Type()
+	if modelType.Kind() == reflect.Ptr {
 		modelType = modelType.Elem()
 	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		if modelType.Kind() == reflect.Interface {
+			modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
+		}
+
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	// Cache the Schema for performance,
 	// Use the modelType or modelType + schemaTable (if it present) as cache key.
-	var schemaCacheKey interface{}
+	var schemaCacheKey interface{} = modelType
 	if specialTableName != "" {
 		schemaCacheKey = fmt.Sprintf("%p-%s", modelType, specialTableName)
-	} else {
-		schemaCacheKey = modelType
 	}
 
 	// Load exist schema cache, return if exists
@@ -162,28 +167,29 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return s, s.err
 	}
 
+	var tableName string
 	modelValue := reflect.New(modelType)
-	tableName := namer.TableName(modelType.Name())
-	if tabler, ok := modelValue.Interface().(Tabler); ok {
+	if specialTableName != "" {
+		tableName = specialTableName
+	} else if en, ok := namer.(embeddedNamer); ok {
+		tableName = en.Table
+	} else if tabler, ok := modelValue.Interface().(Tabler); ok {
 		tableName = tabler.TableName()
-	}
-	if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
+	} else if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
 		tableName = tabler.TableName(namer)
-	}
-	if en, ok := namer.(embeddedNamer); ok {
-		tableName = en.Table
-	}
-	if specialTableName != "" && specialTableName != tableName {
-		tableName = specialTableName
+	} else {
+		tableName = namer.TableName(modelType.Name())
 	}
 
 	schema := &Schema{
 		Name:             modelType.Name(),
 		ModelType:        modelType,
 		Table:            tableName,
-		FieldsByName:     map[string]*Field{},
-		FieldsByBindName: map[string]*Field{},
-		FieldsByDBName:   map[string]*Field{},
+		DBNames:          make([]string, 0, 10),
+		Fields:           make([]*Field, 0, 10),
+		FieldsByName:     make(map[string]*Field, 10),
+		FieldsByBindName: make(map[string]*Field, 10),
+		FieldsByDBName:   make(map[string]*Field, 10),
 		Relationships:    Relationships{Relations: map[string]*Relationship{}},
 		cacheStore:       cacheStore,
 		namer:            namer,
@@ -227,8 +233,9 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 				schema.FieldsByBindName[bindName] = field
 
 				if v != nil && v.PrimaryKey {
+					// remove the existing primary key field
 					for idx, f := range schema.PrimaryFields {
-						if f == v {
+						if f.DBName == v.DBName {
 							schema.PrimaryFields = append(schema.PrimaryFields[0:idx], schema.PrimaryFields[idx+1:]...)
 						}
 					}
@@ -247,7 +254,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 			schema.FieldsByBindName[bindName] = field
 		}
 
-		field.setupValuerAndSetter()
+		field.setupValuerAndSetter(modelType)
 	}
 
 	prioritizedPrimaryField := schema.LookUpField("id")
@@ -283,10 +290,37 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		schema.PrimaryFieldDBNames = append(schema.PrimaryFieldDBNames, field.DBName)
 	}
 
+	_, embedded := schema.cacheStore.Load(embeddedCacheKey)
+	relationshipFields := []*Field{}
 	for _, field := range schema.Fields {
 		if field.DataType != "" && field.HasDefaultValue && field.DefaultValueInterface == nil {
 			schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field)
 		}
+
+		if !embedded {
+			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
+				relationshipFields = append(relationshipFields, field)
+				schema.FieldsByName[field.Name] = field
+				schema.FieldsByBindName[field.BindName()] = field
+			}
+
+			fieldValue := reflect.New(field.IndirectFieldType).Interface()
+			if fc, ok := fieldValue.(CreateClausesInterface); ok {
+				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(QueryClausesInterface); ok {
+				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(UpdateClausesInterface); ok {
+				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(DeleteClausesInterface); ok {
+				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
+			}
+		}
 	}
 
 	if field := schema.PrioritizedPrimaryField; field != nil {
@@ -303,24 +337,6 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}
 
-	callbackTypes := []callbackType{
-		callbackTypeBeforeCreate, callbackTypeAfterCreate,
-		callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
-		callbackTypeBeforeSave, callbackTypeAfterSave,
-		callbackTypeBeforeDelete, callbackTypeAfterDelete,
-		callbackTypeAfterFind,
-	}
-	for _, cbName := range callbackTypes {
-		if methodValue := callBackToMethodValue(modelValue, cbName); methodValue.IsValid() {
-			switch methodValue.Type().String() {
-			case "func(*gorm.DB) error": // TODO hack
-				reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
-			default:
-				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
-			}
-		}
-	}
-
 	// Cache the schema
 	if v, loaded := cacheStore.LoadOrStore(schemaCacheKey, schema); loaded {
 		s := v.(*Schema)
@@ -336,84 +352,47 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}()
 
-	if _, embedded := schema.cacheStore.Load(embeddedCacheKey); !embedded {
-		for _, field := range schema.Fields {
-			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
-				if schema.parseRelation(field); schema.err != nil {
-					return schema, schema.err
+	for _, cbName := range callbackTypes {
+		if methodValue := modelValue.MethodByName(string(cbName)); methodValue.IsValid() {
+			switch methodValue.Type().String() {
+			case "func(*gorm.DB) error":
+				expectedPkgPath := path.Dir(reflect.TypeOf(schema).Elem().PkgPath())
+				if inVarPkg := methodValue.Type().In(0).Elem().PkgPath(); inVarPkg == expectedPkgPath {
+					reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
 				} else {
-					schema.FieldsByName[field.Name] = field
-					schema.FieldsByBindName[field.BindName()] = field
+					logger.Default.Warn(context.Background(), "In model %v, the hook function `%v(*gorm.DB) error` has an incorrect parameter type. The expected parameter type is `%v`, but the provided type is `%v`.", schema, cbName, expectedPkgPath, inVarPkg)
+					// PASS
 				}
+			default:
+				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
 			}
+		}
+	}
 
-			fieldValue := reflect.New(field.IndirectFieldType)
-			fieldInterface := fieldValue.Interface()
-			if fc, ok := fieldInterface.(CreateClausesInterface); ok {
-				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(QueryClausesInterface); ok {
-				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(UpdateClausesInterface); ok {
-				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(DeleteClausesInterface); ok {
-				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
-			}
+	// parse relationships
+	for _, field := range relationshipFields {
+		if schema.parseRelation(field); schema.err != nil {
+			return schema, schema.err
 		}
 	}
 
 	return schema, schema.err
 }
 
-// This unrolling is needed to show to the compiler the exact set of methods
-// that can be used on the modelType.
-// Prior to go1.22 any use of MethodByName would cause the linker to
-// abandon dead code elimination for the entire binary.
-// As of go1.22 the compiler supports one special case of a string constant
-// being passed to MethodByName. For enterprise customers or those building
-// large binaries, this gives a significant reduction in binary size.
-// https://github.com/golang/go/issues/62257
-func callBackToMethodValue(modelType reflect.Value, cbType callbackType) reflect.Value {
-	switch cbType {
-	case callbackTypeBeforeCreate:
-		return modelType.MethodByName(string(callbackTypeBeforeCreate))
-	case callbackTypeAfterCreate:
-		return modelType.MethodByName(string(callbackTypeAfterCreate))
-	case callbackTypeBeforeUpdate:
-		return modelType.MethodByName(string(callbackTypeBeforeUpdate))
-	case callbackTypeAfterUpdate:
-		return modelType.MethodByName(string(callbackTypeAfterUpdate))
-	case callbackTypeBeforeSave:
-		return modelType.MethodByName(string(callbackTypeBeforeSave))
-	case callbackTypeAfterSave:
-		return modelType.MethodByName(string(callbackTypeAfterSave))
-	case callbackTypeBeforeDelete:
-		return modelType.MethodByName(string(callbackTypeBeforeDelete))
-	case callbackTypeAfterDelete:
-		return modelType.MethodByName(string(callbackTypeAfterDelete))
-	case callbackTypeAfterFind:
-		return modelType.MethodByName(string(callbackTypeAfterFind))
-	default:
-		return reflect.ValueOf(nil)
-	}
-}
-
 func getOrParse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	modelType := reflect.ValueOf(dest).Type()
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
-		modelType = modelType.Elem()
-	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	if v, ok := cacheStore.Load(modelType); ok {
diff --git a/history-api/vendor/gorm.io/gorm/schema/utils.go b/history-api/vendor/gorm.io/gorm/schema/utils.go
index fa1c65d4..d4fe252e 100644
--- a/history-api/vendor/gorm.io/gorm/schema/utils.go
+++ b/history-api/vendor/gorm.io/gorm/schema/utils.go
@@ -121,6 +121,17 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
 	}
 
 	switch reflectValue.Kind() {
+	case reflect.Map:
+		results = [][]interface{}{make([]interface{}, len(fields))}
+		for idx, field := range fields {
+			mapValue := reflectValue.MapIndex(reflect.ValueOf(field.DBName))
+			if mapValue.IsZero() {
+				mapValue = reflectValue.MapIndex(reflect.ValueOf(field.Name))
+			}
+			results[0][idx] = mapValue.Interface()
+		}
+
+		dataResults[utils.ToStringKey(results[0]...)] = []reflect.Value{reflectValue}
 	case reflect.Struct:
 		results = [][]interface{}{make([]interface{}, len(fields))}
 
diff --git a/history-api/vendor/gorm.io/gorm/statement.go b/history-api/vendor/gorm.io/gorm/statement.go
index c6183724..736087d7 100644
--- a/history-api/vendor/gorm.io/gorm/statement.go
+++ b/history-api/vendor/gorm.io/gorm/statement.go
@@ -96,7 +96,9 @@ func (stmt *Statement) QuoteTo(writer clause.Writer, field interface{}) {
 		if v.Name == clause.CurrentTable {
 			if stmt.TableExpr != nil {
 				stmt.TableExpr.Build(stmt)
-			} else {
+			} else if stmt.Table != "" {
+				write(v.Raw, stmt.Table)
+			} else if stmt.AddError(stmt.Parse(stmt.Model)) == nil {
 				write(v.Raw, stmt.Table)
 			}
 		} else {
@@ -334,6 +336,8 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 		switch v := arg.(type) {
 		case clause.Expression:
 			conds = append(conds, v)
+		case []clause.Expression:
+			conds = append(conds, v...)
 		case *DB:
 			v.executeScopes()
 
@@ -341,7 +345,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 				if where, ok := cs.Expression.(clause.Where); ok {
 					if len(where.Exprs) == 1 {
 						if orConds, ok := where.Exprs[0].(clause.OrConditions); ok {
-							where.Exprs[0] = clause.AndConditions(orConds)
+							if len(orConds.Exprs) == 1 {
+								where.Exprs[0] = clause.AndConditions(orConds)
+							}
 						}
 					}
 					conds = append(conds, clause.And(where.Exprs...))
@@ -362,6 +368,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 
 			for _, key := range keys {
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				conds = append(conds, clause.Eq{Column: column, Value: v[key]})
 			}
 		case map[string]interface{}:
@@ -374,6 +383,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 			for _, key := range keys {
 				reflectValue := reflect.Indirect(reflect.ValueOf(v[key]))
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				switch reflectValue.Kind() {
 				case reflect.Slice, reflect.Array:
 					if _, ok := v[key].(driver.Valuer); ok {
@@ -650,12 +662,15 @@ func (stmt *Statement) Changed(fields ...string) bool {
 				for destValue.Kind() == reflect.Ptr {
 					destValue = destValue.Elem()
 				}
-
-				changedValue, zero := field.ValueOf(stmt.Context, destValue)
-				if v {
-					return !utils.AssertEqual(changedValue, fieldValue)
+				if descSchema, err := schema.Parse(stmt.Dest, stmt.DB.cacheStore, stmt.DB.NamingStrategy); err == nil {
+					if destField := descSchema.LookUpField(field.DBName); destField != nil {
+						changedValue, zero := destField.ValueOf(stmt.Context, destValue)
+						if v {
+							return !utils.AssertEqual(changedValue, fieldValue)
+						}
+						return !zero && !utils.AssertEqual(changedValue, fieldValue)
+					}
 				}
-				return !zero && !utils.AssertEqual(changedValue, fieldValue)
 			}
 		}
 		return false
diff --git a/history-api/vendor/modules.txt b/history-api/vendor/modules.txt
index cfa1cc16..367043d6 100644
--- a/history-api/vendor/modules.txt
+++ b/history-api/vendor/modules.txt
@@ -180,9 +180,10 @@ github.com/felixge/httpsnoop
 # github.com/firefart/nonamedreturns v1.0.5
 ## explicit; go 1.18
 github.com/firefart/nonamedreturns/analyzer
-# github.com/fsnotify/fsnotify v1.6.0
-## explicit; go 1.16
+# github.com/fsnotify/fsnotify v1.8.0
+## explicit; go 1.17
 github.com/fsnotify/fsnotify
+github.com/fsnotify/fsnotify/internal
 # github.com/fzipp/gocyclo v0.6.0
 ## explicit; go 1.18
 github.com/fzipp/gocyclo
@@ -227,7 +228,7 @@ github.com/go-toolsmith/strparse
 # github.com/go-toolsmith/typep v1.1.0
 ## explicit; go 1.16
 github.com/go-toolsmith/typep
-# github.com/go-viper/mapstructure/v2 v2.2.1
+# github.com/go-viper/mapstructure/v2 v2.4.0
 ## explicit; go 1.18
 github.com/go-viper/mapstructure/v2
 github.com/go-viper/mapstructure/v2/internal/errors
@@ -462,8 +463,8 @@ github.com/gostaticanalysis/forcetypeassert
 # github.com/gostaticanalysis/nilerr v0.1.1
 ## explicit; go 1.15
 github.com/gostaticanalysis/nilerr
-# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
-## explicit; go 1.23.0
+# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
+## explicit; go 1.24.0
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/casing
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor
@@ -488,18 +489,6 @@ github.com/hashicorp/go-version
 ## explicit; go 1.18
 github.com/hashicorp/golang-lru/v2/internal
 github.com/hashicorp/golang-lru/v2/simplelru
-# github.com/hashicorp/hcl v1.0.0
-## explicit
-github.com/hashicorp/hcl
-github.com/hashicorp/hcl/hcl/ast
-github.com/hashicorp/hcl/hcl/parser
-github.com/hashicorp/hcl/hcl/printer
-github.com/hashicorp/hcl/hcl/scanner
-github.com/hashicorp/hcl/hcl/strconv
-github.com/hashicorp/hcl/hcl/token
-github.com/hashicorp/hcl/json/parser
-github.com/hashicorp/hcl/json/scanner
-github.com/hashicorp/hcl/json/token
 # github.com/hexops/gotextdiff v1.0.3
 ## explicit; go 1.16
 github.com/hexops/gotextdiff
@@ -514,8 +503,8 @@ github.com/jackc/pgpassfile
 # github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
 ## explicit; go 1.14
 github.com/jackc/pgservicefile
-# github.com/jackc/pgx/v5 v5.7.1
-## explicit; go 1.21
+# github.com/jackc/pgx/v5 v5.7.6
+## explicit; go 1.23.0
 github.com/jackc/pgx/v5
 github.com/jackc/pgx/v5/internal/iobufpool
 github.com/jackc/pgx/v5/internal/pgio
@@ -611,9 +600,6 @@ github.com/lufia/plan9stats
 # github.com/macabu/inamedparam v0.1.3
 ## explicit; go 1.20
 github.com/macabu/inamedparam
-# github.com/magiconair/properties v1.8.7
-## explicit; go 1.19
-github.com/magiconair/properties
 # github.com/maratori/testableexamples v1.0.0
 ## explicit; go 1.19
 github.com/maratori/testableexamples/pkg/testableexamples
@@ -644,9 +630,6 @@ github.com/mgechev/revive/rule
 # github.com/mitchellh/go-homedir v1.1.0
 ## explicit
 github.com/mitchellh/go-homedir
-# github.com/mitchellh/mapstructure v1.5.0
-## explicit; go 1.14
-github.com/mitchellh/mapstructure
 # github.com/moricho/tparallel v0.3.2
 ## explicit; go 1.20
 github.com/moricho/tparallel
@@ -729,8 +712,8 @@ github.com/prometheus/client_model/go
 ## explicit; go 1.21
 github.com/prometheus/common/expfmt
 github.com/prometheus/common/model
-# github.com/prometheus/procfs v0.15.1
-## explicit; go 1.20
+# github.com/prometheus/procfs v0.17.0
+## explicit; go 1.23.0
 github.com/prometheus/procfs
 github.com/prometheus/procfs/internal/fs
 github.com/prometheus/procfs/internal/util
@@ -782,21 +765,21 @@ github.com/rogpeppe/go-internal/internal/syscall/windows
 github.com/rogpeppe/go-internal/internal/syscall/windows/sysdll
 github.com/rogpeppe/go-internal/lockedfile
 github.com/rogpeppe/go-internal/lockedfile/internal/filelock
-# github.com/rs/cors v1.11.0
+# github.com/rs/cors v1.11.1
 ## explicit; go 1.13
 github.com/rs/cors
 github.com/rs/cors/internal
-# github.com/rs/zerolog v1.33.0
+# github.com/rs/zerolog v1.34.0
 ## explicit; go 1.15
 github.com/rs/zerolog
 github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/event-processor v0.0.0-00010101000000-000000000000 => ../event-processor
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/event-processor/api
 # github.com/runtime-radar/runtime-radar/lib v0.0.24 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/errcommon
 github.com/runtime-radar/runtime-radar/lib/logger
@@ -808,7 +791,7 @@ github.com/runtime-radar/runtime-radar/lib/server/healthcheck
 github.com/runtime-radar/runtime-radar/lib/server/interceptor
 github.com/runtime-radar/runtime-radar/lib/server/middleware
 # github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8 => ../policy-enforcer
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/policy-enforcer/api
 github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model
 # github.com/ryancurrah/gomodguard v1.3.5
@@ -817,12 +800,9 @@ github.com/ryancurrah/gomodguard
 # github.com/ryanrolds/sqlclosecheck v0.5.1
 ## explicit; go 1.20
 github.com/ryanrolds/sqlclosecheck/pkg/analyzer
-# github.com/sagikazarmark/locafero v0.3.0
-## explicit; go 1.20
+# github.com/sagikazarmark/locafero v0.7.0
+## explicit; go 1.21
 github.com/sagikazarmark/locafero
-# github.com/sagikazarmark/slog-shim v0.1.0
-## explicit; go 1.20
-github.com/sagikazarmark/slog-shim
 # github.com/sanposhiho/wastedassign/v2 v2.1.0
 ## explicit; go 1.18
 github.com/sanposhiho/wastedassign/v2
@@ -894,26 +874,23 @@ github.com/sourcegraph/go-diff/diff
 github.com/spf13/afero
 github.com/spf13/afero/internal/common
 github.com/spf13/afero/mem
-# github.com/spf13/cast v1.5.1
-## explicit; go 1.18
+# github.com/spf13/cast v1.7.1
+## explicit; go 1.19
 github.com/spf13/cast
 # github.com/spf13/cobra v1.9.1
 ## explicit; go 1.15
 github.com/spf13/cobra
-# github.com/spf13/pflag v1.0.6
+# github.com/spf13/pflag v1.0.7
 ## explicit; go 1.12
 github.com/spf13/pflag
-# github.com/spf13/viper v1.17.0
-## explicit; go 1.18
+# github.com/spf13/viper v1.20.1
+## explicit; go 1.21.0
 github.com/spf13/viper
-github.com/spf13/viper/internal/encoding
 github.com/spf13/viper/internal/encoding/dotenv
-github.com/spf13/viper/internal/encoding/hcl
-github.com/spf13/viper/internal/encoding/ini
-github.com/spf13/viper/internal/encoding/javaproperties
 github.com/spf13/viper/internal/encoding/json
 github.com/spf13/viper/internal/encoding/toml
 github.com/spf13/viper/internal/encoding/yaml
+github.com/spf13/viper/internal/features
 # github.com/ssgreg/nlreturn/v2 v2.2.1
 ## explicit; go 1.13
 github.com/ssgreg/nlreturn/v2/pkg/nlreturn
@@ -1006,15 +983,14 @@ go-simpler.org/musttag
 # go-simpler.org/sloglint v0.9.0
 ## explicit; go 1.22.0
 go-simpler.org/sloglint
-# go.opentelemetry.io/otel v1.35.0
-## explicit; go 1.22.0
+# go.opentelemetry.io/otel v1.37.0
+## explicit; go 1.23.0
 go.opentelemetry.io/otel/attribute
+go.opentelemetry.io/otel/attribute/internal
 go.opentelemetry.io/otel/codes
-go.opentelemetry.io/otel/internal
-go.opentelemetry.io/otel/internal/attribute
-go.opentelemetry.io/otel/semconv/v1.26.0
-# go.opentelemetry.io/otel/trace v1.35.0
-## explicit; go 1.22.0
+go.opentelemetry.io/otel/semconv/v1.34.0
+# go.opentelemetry.io/otel/trace v1.37.0
+## explicit; go 1.23.0
 go.opentelemetry.io/otel/trace
 go.opentelemetry.io/otel/trace/embedded
 go.opentelemetry.io/otel/trace/internal/telemetry
@@ -1037,26 +1013,22 @@ go.uber.org/zap/internal/exit
 go.uber.org/zap/internal/pool
 go.uber.org/zap/internal/stacktrace
 go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.38.0
+# go.yaml.in/yaml/v3 v3.0.4
+## explicit; go 1.16
+go.yaml.in/yaml/v3
+# golang.org/x/crypto v0.41.0
 ## explicit; go 1.23.0
 golang.org/x/crypto/pbkdf2
-# golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
-## explicit; go 1.22.0
-golang.org/x/exp/constraints
-golang.org/x/exp/slices
-golang.org/x/exp/slog
-golang.org/x/exp/slog/internal
-golang.org/x/exp/slog/internal/buffer
 # golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac
 ## explicit; go 1.18
 golang.org/x/exp/typeparams
-# golang.org/x/mod v0.25.0
+# golang.org/x/mod v0.27.0
 ## explicit; go 1.23.0
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.40.0
+# golang.org/x/net v0.43.0
 ## explicit; go 1.23.0
 golang.org/x/net/http/httpguts
 golang.org/x/net/http2
@@ -1065,17 +1037,28 @@ golang.org/x/net/idna
 golang.org/x/net/internal/httpcommon
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
-# golang.org/x/sync v0.15.0
-## explicit; go 1.23.0
+# golang.org/x/sync v0.17.0
+## explicit; go 1.24.0
 golang.org/x/sync/errgroup
 golang.org/x/sync/semaphore
-# golang.org/x/sys v0.33.0
+# golang.org/x/sys v0.35.0
 ## explicit; go 1.23.0
 golang.org/x/sys/cpu
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/text v0.26.0
+# golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
 ## explicit; go 1.23.0
+golang.org/x/telemetry
+golang.org/x/telemetry/counter
+golang.org/x/telemetry/internal/config
+golang.org/x/telemetry/internal/configstore
+golang.org/x/telemetry/internal/counter
+golang.org/x/telemetry/internal/crashmonitor
+golang.org/x/telemetry/internal/mmap
+golang.org/x/telemetry/internal/telemetry
+golang.org/x/telemetry/internal/upload
+# golang.org/x/text v0.29.0
+## explicit; go 1.24.0
 golang.org/x/text/cases
 golang.org/x/text/encoding
 golang.org/x/text/encoding/internal
@@ -1101,7 +1084,7 @@ golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
-# golang.org/x/tools v0.33.0
+# golang.org/x/tools v0.36.0
 ## explicit; go 1.23.0
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/passes/appends
@@ -1153,6 +1136,7 @@ golang.org/x/tools/go/analysis/passes/unusedresult
 golang.org/x/tools/go/analysis/passes/unusedwrite
 golang.org/x/tools/go/analysis/passes/waitgroup
 golang.org/x/tools/go/ast/astutil
+golang.org/x/tools/go/ast/edge
 golang.org/x/tools/go/ast/inspector
 golang.org/x/tools/go/buildutil
 golang.org/x/tools/go/callgraph
@@ -1173,8 +1157,6 @@ golang.org/x/tools/imports
 golang.org/x/tools/internal/aliases
 golang.org/x/tools/internal/analysisinternal
 golang.org/x/tools/internal/astutil
-golang.org/x/tools/internal/astutil/cursor
-golang.org/x/tools/internal/astutil/edge
 golang.org/x/tools/internal/event
 golang.org/x/tools/internal/event/core
 golang.org/x/tools/internal/event/keys
@@ -1191,32 +1173,36 @@ golang.org/x/tools/internal/stdlib
 golang.org/x/tools/internal/typeparams
 golang.org/x/tools/internal/typesinternal
 golang.org/x/tools/internal/versions
-# golang.org/x/vuln v0.2.0
-## explicit; go 1.18
+# golang.org/x/vuln v1.1.4
+## explicit; go 1.22.0
 golang.org/x/vuln/cmd/govulncheck
 golang.org/x/vuln/internal
+golang.org/x/vuln/internal/buildinfo
 golang.org/x/vuln/internal/client
 golang.org/x/vuln/internal/derrors
+golang.org/x/vuln/internal/gosym
+golang.org/x/vuln/internal/goversion
 golang.org/x/vuln/internal/govulncheck
+golang.org/x/vuln/internal/openvex
 golang.org/x/vuln/internal/osv
+golang.org/x/vuln/internal/sarif
 golang.org/x/vuln/internal/scan
 golang.org/x/vuln/internal/semver
+golang.org/x/vuln/internal/traces
 golang.org/x/vuln/internal/vulncheck
-golang.org/x/vuln/internal/vulncheck/internal/buildinfo
-golang.org/x/vuln/internal/vulncheck/internal/gosym
 golang.org/x/vuln/internal/web
 golang.org/x/vuln/scan
-# google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/api
 google.golang.org/genproto/googleapis/api/annotations
 google.golang.org/genproto/googleapis/api/httpbody
 google.golang.org/genproto/googleapis/api/visibility
-# google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/rpc/errdetails
 google.golang.org/genproto/googleapis/rpc/status
-# google.golang.org/grpc v1.73.0
+# google.golang.org/grpc v1.75.1
 ## explicit; go 1.23.0
 google.golang.org/grpc
 google.golang.org/grpc/attributes
@@ -1286,8 +1272,8 @@ google.golang.org/grpc/tap
 # google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
 ## explicit; go 1.21
 google.golang.org/grpc/cmd/protoc-gen-go-grpc
-# google.golang.org/protobuf v1.36.6
-## explicit; go 1.22
+# google.golang.org/protobuf v1.36.10
+## explicit; go 1.23
 google.golang.org/protobuf/cmd/protoc-gen-go
 google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo
 google.golang.org/protobuf/compiler/protogen
@@ -1338,9 +1324,6 @@ google.golang.org/protobuf/types/known/structpb
 google.golang.org/protobuf/types/known/timestamppb
 google.golang.org/protobuf/types/known/wrapperspb
 google.golang.org/protobuf/types/pluginpb
-# gopkg.in/ini.v1 v1.67.0
-## explicit
-gopkg.in/ini.v1
 # gopkg.in/yaml.v2 v2.4.0
 ## explicit; go 1.15
 gopkg.in/yaml.v2
@@ -1353,7 +1336,7 @@ gorm.io/driver/clickhouse
 # gorm.io/driver/postgres v1.6.0
 ## explicit; go 1.20
 gorm.io/driver/postgres
-# gorm.io/gorm v1.30.0
+# gorm.io/gorm v1.31.0
 ## explicit; go 1.18
 gorm.io/gorm
 gorm.io/gorm/callbacks
diff --git a/kubeconfig.yaml b/kubeconfig.yaml
new file mode 100644
index 00000000..361fd832
--- /dev/null
+++ b/kubeconfig.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJQU51ZHhxUmhWR0V3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBMU1UWXdNek0wTURaYUZ3MHpOVEExTVRRd016TTVNRFphTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURJMGFQaDhsQ2pUcXl0ejY1TWFiZTR2WUk2ZXNEcWllU0R2LzVoM0I0SkRUem95ck9acXpycUpJZmcKTWxqOWRJbjdqTkNrZ2REVlFOQ01iQ3pZck82di81MHZUYldKVGNjR1lRNDF5RzNwWkZ5OEFGRHhpeFoxNm1KNwpMSjhqeUUwcnU0MTY4QVErbmltaGRRSXFOTTR6OXVEazhJbFQwem8vRmI2OUpPUkdLazk2ZlNTQ3Z2STBoV2J6CmVlbW1SRStqUHQxS0N4bmhydGpuUW9jR2RBanl6NDBSVlNIL2VQOUFUKzIzWmNycEhPWHVTdENQTzNQbnpFVnoKMVVSVVRkTnZCRGFUYWlSSWlTaXJyL1pQRlJDQ0xCeldHbnZoS0tIM1MvTktYQ21GMForZ2FVMnZTWWpYTysrQgpTaHE1Y1FTUmpOaXZMNnB4cXdCMTJqazVNdUZKQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUWkZtcklBOStjaWJXbHlEbHEvRXQ3YUJmWWt6QVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQUFwNlU5dWNvdApVTzlFdm5CcVRUNkJLTjVsbVZmb2pBNCtVWTdabkFzaHhvRGMxUFBtWTBiM0REeU5ZbTZPSjF0NWxPWXFZRHloCjdqNCtubGh0UzJGejc2RnBEZU5mL1hrWG1lMm9sbDc4QkEyYmNyTjVPOTNNanFKYk5xOGhXM1ZobHd5YmNwTzQKT0h2WnVuaXArZC9VZXFNTW9YV2EzR1V2bzRtVHdRNElyUVQ1cTBGMVFHWUdwVnp6M2hhbk8yY0JJL1NkQnV6UgpQMUtuemYzQXplUGlsU1JUbzhlOFhDVDRQcU96OWQ0ekFxNE1WWUhYai9Hdys4K0QwWnd0Q2syQTlZb1EzZXpYCnlBZHNQV0Y2SENFaDVmeG1ySjFlenY2NktJT1JZTzM2RTVRWHU5OXB3SGR4eE8zSmlKTnZDdm96dHhQYVJZOGEKSkxuaklWbU1KWjY3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+    server: https://10.50.73.250:6443
+  name: os-izy-k8s
+contexts:
+- context:
+    cluster: os-izy-k8s
+    user: os-izy-k8s-admin
+  name: os-izy-k8s
+current-context: os-izy-k8s
+kind: Config
+preferences: {}
+users:
+- name: os-izy-k8s-admin
+  user:
+    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJQUtZdUZWb0FWN1F3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBMU1UWXdNek0wTURaYUZ3MHlOakExTVRZd016TTVNRGhhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDd3Q1MlcKbTFvRUh2YmdSOTBuY1VSeENLRVV0NEZRVjJkZ1Zlc2IwZW8zTmFhVkVrM243MHJJRjUwNk85N1lmRmhSckNwZQpRUFMvajdEeU05c0hxTVkrcVRPWFZyYU92d2ZWdEptbEpvQnp6S3k0OE4xZ1NON245VWJJQkM0MnNRZ3B2cUZpCnl4U0lwUjlHM0dHdHNsamxhZEExNVgveUYwYldmYXdZRzFMSzBoUE9EVlFCNm9wVmJNWHZCRkpKUmZ3cm54SGIKRDVZWkNPN3ZSSllpRGZSZlFJWWRTdnFiUUNQS2Frb29LQnkrUXIxbWJnVWdOcnFlV3hHdSt5eFdtRmtZeXBHKwpsQVlOdDkzWEVxMDJtSG4zZDcwdlF1NjM5NVFCV1RNVkhJNWhqTVNPK085Qld4ZE40UkhJaWlKMUR6ZFhueDZTCitCc1pDaTlvNVVIa0Q2aDdBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRk5rV2FzZ0QzNXlKdGFYSQpPV3I4UzN0b0Y5aVRNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFxZFNza2JBYVBGNWhiTW9odlE1S3dpc2JhCldZQjNhL1RoYkdHN1NVTTJzR2Rwd1NZQ2pqSFZ0RDYzM2MxVEswallqSnVENk1tdUoyU2FsSzFMWHh2aldSSHkKRFdrUTltV3h5NmdXV1JPdTdTQ2hCR2VIVjlGWDFwb3BvbG9kbU90bkZuZUQ0cEl4dlNpLzI1SUhJbFZ5NkxyQgpibDFyclRrQlh4cG9nR1Vqa0F0OEMvdGJXblJ6L2ptT000aEZXRW1kTTNvVFJ6MFZFMkM5MjY1cFRyaWxmdUNrClNPQlo0WkcvcHdOc3VleFp2b2dsejh6S0ZxdU11MzUxcDYzWVpOc2NKQXhCVlVYdnJLMUhwMFlPME1WWVR3Um8KdGpYaWhTcUErSXNlaVJKdVNVL1hBSGMwRkc4SkRCMURiMDhRTzFwYUUxTlp3QVQ0S3E4UlRNRHdkazVqCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBc0xlZGxwdGFCQjcyNEVmZEozRkVjUWloRkxlQlVGZG5ZRlhyRzlIcU56V21sUkpOCjUrOUt5QmVkT2p2ZTJIeFlVYXdxWGtEMHY0K3c4alBiQjZqR1Bxa3psMWEyanI4SDFiU1pwU2FBYzh5c3VQRGQKWUVqZTUvVkd5QVF1TnJFSUtiNmhZc3NVaUtVZlJ0eGhyYkpZNVduUU5lVi84aGRHMW4yc0dCdFN5dElUemcxVQpBZXFLVld6Rjd3UlNTVVg4SzU4UjJ3K1dHUWp1NzBTV0lnMzBYMENHSFVyNm0wQWp5bXBLS0NnY3ZrSzlabTRGCklEYTZubHNScnZzc1ZwaFpHTXFSdnBRR0RiZmQxeEt0TnBoNTkzZTlMMEx1dC9lVUFWa3pGUnlPWVl6RWp2anYKUVZzWFRlRVJ5SW9pZFE4M1Y1OGVrdmdiR1FvdmFPVkI1QStvZXdJREFRQUJBb0lCQUh1eHVxTzl6KzlNZ1QrUgo3ZEg2N1k0MUhSTTBNMWE2SjBqK090ZzVRYmt0VzVIQ3d6ZFNmc1M2Q3JyRlI0RyszODhqTkhEUEJNSEZZWFRYCktUd2VQYzJFZi9FeHFBMFkxL0lWUE9xbG5Zbnd2UUdpejBIakgrdTYrclZzZjdDV2tBRXdSeVN3dzRtMkVzTjEKNVFWQTdncCsyMWV1Y2JWUjU2cWhRc0dJOXBXeDlsUjdWcXpJS1JPQmVWZFpCbzVyZFFEaWovZ1pOWTdycTBRaApBRkQvcWdQMi92ZjJGNFMvdVdoVVhicTJUbEZ0RDV3UGl1VVBuTlU3Z3Z3TVRURHNIWG5WZEJDTmhUQnlQTGVLClZxbzF2aUd6WHhrZ3RqTXFOQ1FGRE5XYk9hTkdLMkFscW84ajRxeVA0bWlVbCtaUHBPdUdtNVlhOHptY1pRNEwKOVVKMkZNRUNnWUVBM2Y3cG1SWjdhSjFjb0ZkS21jbGRXNDdtQ2lKRHc4cFRyaVNUMWFOVURtMm02cVFDQlloagorajVaejlCRTJQd1dURVFqTitKRENzRnJKQk9kMEhXRTR4Q21aSnVKajBJREdiNWd3YXR3aE0xOEVsVzhrcHFVCnkxQjYyL1FqKy96ZlNIWGpHZ1VVaHZJMDMxZ1grNjQwaldUdSs3MjJXWERvTjJyMWF4a3ZqZUVDZ1lFQXk4azAKSVhmekY0cXpZQm5YWFpKeEh4eWs3MlhXMVlFaUhtN1gwRmFpazZNZW9LRm95c2RzNDZ2OG55aURmV1dNdzJpTwpsdjYxblVDazhoY3hDclV3TXZWa0RCRHBaK2EyeGl4M2d4ck4vd0FLdUMzVkdGUGZjcVJab05uTG5Pdk8yUUlQCk5HNUsxQnE0NHpWaGJIVDlLdVlIT2djWUxHTi9xMVdDQ2Qwd2Fkc0NnWUJIN3ZYYXVVSTczK0hId3dGVlc3NTQKa0pGUjcxQnQvUDJvakFtclRFVk1kNU9DcktwTENLcjh4MzlxcTEzandhdW9BdHcybTRhRjBhN1ovZEZCWHhNMApVSXphUk53S0k2WEZqYjdrZ3B6dkszWnNxb04wTGNyUkpyN296dTlxRThKMlJGeldiWmI5TXphV3VJRHMrTUhtCm56SWhPSlFCMzJnZnJQVGhRMFA1Z1FLQmdFWVlDTlJTTzgwbktoZXVDOFBsc1A4d2pSTERCcWdkYUt6ckYxUlQKMkV2TDJhY0tuYzdSMVlSaURkeDR4UEdHMG1vTU5xOTlJTjdiODJCSjFkYUhCL01mTUxCdHlMcXlRci9iWDZnNgp1Z3d4NlgzOFZjV3VZN2M5REk4bEdzSDQ0Z2NHakZCT2QzS0pWbnJnUzRoUW5SdjZUeFlJaHFvTjkwWHBmWGNECkc3bnRBb0dCQUo5dmtsVkhIbjJTYXFVUURTaDZMWjQ2bkZhNHlZL04vbG1ka2JIV0h6WFNabHJvYUxUQnh1aDAKT1ZFZnk2UHFoSTAyT0NoZmZrMWl6R3NWdms3WXRqSElNcDNsaXdpYnAvcm05YjRnOHYycWJISW52TG5yOFF2bwpNTGVoV1BTS2VxQWh2L2tCVUVXai9IdklMWnVEWG90TGxuWU9XWEZnMjZBeEJJL3lXV1ZKCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
diff --git a/lib/go.mod b/lib/go.mod
index 47e6df93..79282ab7 100644
--- a/lib/go.mod
+++ b/lib/go.mod
@@ -1,6 +1,6 @@
 module github.com/runtime-radar/runtime-radar/lib
 
-go 1.23
+go 1.25
 
 require (
 	github.com/distribution/reference v0.6.0
diff --git a/notifier/Dockerfile b/notifier/Dockerfile
index 313a07ce..d2e7ed3a 100644
--- a/notifier/Dockerfile
+++ b/notifier/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 ARG BUILD_RELEASE
 ARG BUILD_BRANCH
diff --git a/notifier/docker-compose.test.yml b/notifier/docker-compose.test.yml
index 87cba884..3c5ef076 100644
--- a/notifier/docker-compose.test.yml
+++ b/notifier/docker-compose.test.yml
@@ -17,7 +17,7 @@ services:
       - POSTGRES_DB=cs_test
 
   test:
-    image: golang:1.24
+    image: golang:1.25
     working_dir: /go/src/repo
     volumes:
       - .:/go/src/repo
diff --git a/notifier/go.mod b/notifier/go.mod
index de725c32..86e7e062 100644
--- a/notifier/go.mod
+++ b/notifier/go.mod
@@ -1,32 +1,32 @@
 module github.com/runtime-radar/runtime-radar/notifier
 
-go 1.23.0
+go 1.25
 
 require (
 	github.com/golangci/golangci-lint v1.64.8
 	github.com/google/gops v0.3.28
 	github.com/google/uuid v1.6.0
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
 	github.com/hashicorp/go-syslog v1.0.0
-	github.com/jackc/pgx/v5 v5.7.1
+	github.com/jackc/pgx/v5 v5.7.6
 	github.com/justinas/alice v1.2.0
 	github.com/lib/pq v1.10.9
-	github.com/rs/cors v1.11.0
-	github.com/rs/zerolog v1.33.0
+	github.com/rs/cors v1.11.1
+	github.com/rs/zerolog v1.34.0
 	github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000
 	github.com/runtime-radar/runtime-radar/lib v0.0.24
 	github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8
 	github.com/tidwall/gjson v1.18.0
 	github.com/wneessen/go-mail v0.4.0
 	go.uber.org/automaxprocs v1.6.0
-	golang.org/x/text v0.26.0
-	golang.org/x/vuln v0.2.0
-	google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-	google.golang.org/grpc v1.73.0
+	golang.org/x/text v0.29.0
+	golang.org/x/vuln v1.1.4
+	google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+	google.golang.org/grpc v1.75.1
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
-	google.golang.org/protobuf v1.36.6
+	google.golang.org/protobuf v1.36.10
 	gorm.io/driver/postgres v1.6.0
-	gorm.io/gorm v1.30.0
+	gorm.io/gorm v1.31.0
 )
 
 require (
@@ -74,7 +74,7 @@ require (
 	github.com/fatih/structtag v1.2.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/firefart/nonamedreturns v1.0.5 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/fsnotify/fsnotify v1.8.0 // indirect
 	github.com/fzipp/gocyclo v0.6.0 // indirect
 	github.com/ghostiam/protogetter v0.3.9 // indirect
 	github.com/go-critic/go-critic v0.12.0 // indirect
@@ -86,7 +86,7 @@ require (
 	github.com/go-toolsmith/astp v1.1.0 // indirect
 	github.com/go-toolsmith/strparse v1.1.0 // indirect
 	github.com/go-toolsmith/typep v1.1.0 // indirect
-	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
+	github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
 	github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
 	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
@@ -107,7 +107,6 @@ require (
 	github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
 	github.com/hashicorp/go-version v1.7.0 // indirect
 	github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
-	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/hexops/gotextdiff v1.0.3 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
@@ -133,7 +132,6 @@ require (
 	github.com/leonklingele/grouper v1.1.2 // indirect
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/macabu/inamedparam v0.1.3 // indirect
-	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/maratori/testableexamples v1.0.0 // indirect
 	github.com/maratori/testpackage v1.1.1 // indirect
 	github.com/matoous/godox v1.1.0 // indirect
@@ -142,7 +140,6 @@ require (
 	github.com/mattn/go-runewidth v0.0.16 // indirect
 	github.com/mgechev/revive v1.7.0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
-	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/moricho/tparallel v0.3.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/nakabonne/nestif v0.3.1 // indirect
@@ -157,7 +154,7 @@ require (
 	github.com/prometheus/client_golang v1.22.0 // indirect
 	github.com/prometheus/client_model v0.6.2 // indirect
 	github.com/prometheus/common v0.62.0 // indirect
-	github.com/prometheus/procfs v0.15.1 // indirect
+	github.com/prometheus/procfs v0.17.0 // indirect
 	github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
 	github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
 	github.com/quasilyte/gogrep v0.5.0 // indirect
@@ -169,8 +166,7 @@ require (
 	github.com/runtime-radar/runtime-radar/event-processor v0.0.0-00010101000000-000000000000 // indirect
 	github.com/ryancurrah/gomodguard v1.3.5 // indirect
 	github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
-	github.com/sagikazarmark/locafero v0.3.0 // indirect
-	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+	github.com/sagikazarmark/locafero v0.7.0 // indirect
 	github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
 	github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
 	github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
@@ -185,10 +181,10 @@ require (
 	github.com/sourcegraph/conc v0.3.0 // indirect
 	github.com/sourcegraph/go-diff v0.7.0 // indirect
 	github.com/spf13/afero v1.12.0 // indirect
-	github.com/spf13/cast v1.5.1 // indirect
+	github.com/spf13/cast v1.7.1 // indirect
 	github.com/spf13/cobra v1.9.1 // indirect
-	github.com/spf13/pflag v1.0.6 // indirect
-	github.com/spf13/viper v1.17.0 // indirect
+	github.com/spf13/pflag v1.0.7 // indirect
+	github.com/spf13/viper v1.20.1 // indirect
 	github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
 	github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
@@ -219,16 +215,16 @@ require (
 	go-simpler.org/sloglint v0.9.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.38.0 // indirect
-	golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
+	go.yaml.in/yaml/v3 v3.0.4 // indirect
+	golang.org/x/crypto v0.41.0 // indirect
 	golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
-	golang.org/x/mod v0.25.0 // indirect
-	golang.org/x/net v0.40.0 // indirect
-	golang.org/x/sync v0.15.0 // indirect
-	golang.org/x/sys v0.33.0 // indirect
-	golang.org/x/tools v0.33.0 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
-	gopkg.in/ini.v1 v1.67.0 // indirect
+	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/net v0.43.0 // indirect
+	golang.org/x/sync v0.17.0 // indirect
+	golang.org/x/sys v0.35.0 // indirect
+	golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 // indirect
+	golang.org/x/tools v0.36.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	honnef.co/go/tools v0.6.1 // indirect
diff --git a/notifier/go.sum b/notifier/go.sum
index ca6a0adb..ecf43287 100644
--- a/notifier/go.sum
+++ b/notifier/go.sum
@@ -96,18 +96,18 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
 github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
 github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
 github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ=
 github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA=
 github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w=
 github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@@ -135,8 +135,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi
 github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ=
 github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
 github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
-github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
-github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY=
 github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
@@ -198,8 +198,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW
 github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
 github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8=
 github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
 github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
@@ -211,8 +211,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe
 github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -221,8 +219,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
-github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
-github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
+github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
+github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
 github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
 github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
@@ -273,8 +271,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
 github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
 github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE=
 github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04=
@@ -297,8 +293,6 @@ github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY=
 github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
 github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
@@ -342,8 +336,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
 github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
 github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
 github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
@@ -361,20 +355,18 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
 github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
-github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
-github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
-github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
+github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
+github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU=
 github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE=
 github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
 github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
-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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
+github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
 github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
 github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
 github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
@@ -407,15 +399,16 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp
 github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
 github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
 github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
-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/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
 github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
-github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
+github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
 github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0=
 github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
 github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4=
@@ -502,16 +495,16 @@ go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE=
 go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
-go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
-go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
-go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
-go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
-go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
-go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
-go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
-go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
-go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
+go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
+go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
 go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -520,14 +513,16 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
 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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
-golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
+golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
+golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
@@ -545,8 +540,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
-golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
 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=
@@ -562,8 +557,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
-golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
 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-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -573,8 +568,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -593,7 +588,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -602,8 +596,10 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -622,8 +618,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
-golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
 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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
@@ -642,29 +638,33 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
-golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
-golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
-golang.org/x/vuln v0.2.0 h1:Dlz47lW0pvPHU7tnb10S8vbMn9GnV2B6eyT7Tem5XBI=
-golang.org/x/vuln v0.2.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
+golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
+golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
+golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
 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/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
-google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
-google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f h1:OiFuztEyBivVKDvguQJYWq1yDcfAHIID/FVrPR4oiI0=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f/go.mod h1:kprOiu9Tr0JYyD6DORrc4Hfyk3RFXqkQ3ctHEum3ZbM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
+google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
+google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
-google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
-google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-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.2/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=
@@ -673,8 +673,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
 gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
-gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
-gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
+gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
+gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
 honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
 honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
 mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/notifier/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
new file mode 100644
index 00000000..f4e7dbf3
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
@@ -0,0 +1,14 @@
+freebsd_task:
+  name: 'FreeBSD'
+  freebsd_instance:
+    image_family: freebsd-14-1
+  install_script:
+    - pkg update -f
+    - pkg install -y go
+  test_script:
+      # run tests as user "cirrus" instead of root
+    - pw useradd cirrus -m
+    - chown -R cirrus:cirrus .
+    - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    -                      sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    - FSNOTIFY_DEBUG=1     sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/.editorconfig b/notifier/vendor/github.com/fsnotify/fsnotify/.editorconfig
deleted file mode 100644
index fad89585..00000000
--- a/notifier/vendor/github.com/fsnotify/fsnotify/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-root = true
-
-[*.go]
-indent_style = tab
-indent_size = 4
-insert_final_newline = true
-
-[*.{yml,yaml}]
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/.gitattributes b/notifier/vendor/github.com/fsnotify/fsnotify/.gitattributes
deleted file mode 100644
index 32f1001b..00000000
--- a/notifier/vendor/github.com/fsnotify/fsnotify/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-go.sum linguist-generated
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/.gitignore b/notifier/vendor/github.com/fsnotify/fsnotify/.gitignore
index 1d89d85c..daea9dd6 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/.gitignore
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/.gitignore
@@ -4,3 +4,7 @@
 
 # Output of go build ./cmd/fsnotify
 /fsnotify
+/fsnotify.exe
+
+/test/kqueue
+/test/a.out
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/notifier/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
index 77f9593b..fa854785 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
@@ -1,16 +1,115 @@
 # Changelog
 
-All notable changes to this project will be documented in this file.
+1.8.0 2023-10-31
+----------------
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+### Additions
+
+- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
+
+### Changes and fixes
+
+- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610])
+
+- kqueue: ignore events with Ident=0 ([#590])
+
+- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617])
+
+- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625])
+
+- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620])
+
+- inotify: fix panic when calling Remove() in a goroutine ([#650])
+
+- fen: allow watching subdirectories of watched directories ([#621])
+
+[#590]: https://github.com/fsnotify/fsnotify/pull/590
+[#610]: https://github.com/fsnotify/fsnotify/pull/610
+[#617]: https://github.com/fsnotify/fsnotify/pull/617
+[#619]: https://github.com/fsnotify/fsnotify/pull/619
+[#620]: https://github.com/fsnotify/fsnotify/pull/620
+[#621]: https://github.com/fsnotify/fsnotify/pull/621
+[#625]: https://github.com/fsnotify/fsnotify/pull/625
+[#650]: https://github.com/fsnotify/fsnotify/pull/650
+
+1.7.0 - 2023-10-22
+------------------
+This version of fsnotify needs Go 1.17.
+
+### Additions
+
+- illumos: add FEN backend to support illumos and Solaris. ([#371])
+
+- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful
+  in cases where you can't control the kernel buffer and receive a large number
+  of events in bursts. ([#550], [#572])
+
+- all: add `AddWith()`, which is identical to `Add()` but allows passing
+  options. ([#521])
+
+- windows: allow setting the ReadDirectoryChangesW() buffer size with
+  `fsnotify.WithBufferSize()`; the default of 64K is the highest value that
+  works on all platforms and is enough for most purposes, but in some cases a
+  highest buffer is needed. ([#521])
+
+### Changes and fixes
+
+- inotify: remove watcher if a watched path is renamed ([#518])
+
+  After a rename the reported name wasn't updated, or even an empty string.
+  Inotify doesn't provide any good facilities to update it, so just remove the
+  watcher. This is already how it worked on kqueue and FEN.
+
+  On Windows this does work, and remains working.
+
+- windows: don't listen for file attribute changes ([#520])
+
+  File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API,
+  with no way to see if they're a file write or attribute change, so would show
+  up as a fsnotify.Write event. This is never useful, and could result in many
+  spurious Write events.
+
+- windows: return `ErrEventOverflow` if the buffer is full ([#525])
+
+  Before it would merely return "short read", making it hard to detect this
+  error.
+
+- kqueue: make sure events for all files are delivered properly when removing a
+  watched directory ([#526])
+
+  Previously they would get sent with `""` (empty string) or `"."` as the path
+  name.
+
+- kqueue: don't emit spurious Create events for symbolic links ([#524])
+
+  The link would get resolved but kqueue would "forget" it already saw the link
+  itself, resulting on a Create for every Write event for the directory.
+
+- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516])
 
-## [Unreleased]
+- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in
+  `backend_other.go`, making it easier to use on unsupported platforms such as
+  WASM, AIX, etc. ([#528])
 
-Nothing yet.
+- other: use the `backend_other.go` no-op if the `appengine` build tag is set;
+  Google AppEngine forbids usage of the unsafe package so the inotify backend
+  won't compile there.
 
-## [1.6.0] - 2022-10-13
+[#371]: https://github.com/fsnotify/fsnotify/pull/371
+[#516]: https://github.com/fsnotify/fsnotify/pull/516
+[#518]: https://github.com/fsnotify/fsnotify/pull/518
+[#520]: https://github.com/fsnotify/fsnotify/pull/520
+[#521]: https://github.com/fsnotify/fsnotify/pull/521
+[#524]: https://github.com/fsnotify/fsnotify/pull/524
+[#525]: https://github.com/fsnotify/fsnotify/pull/525
+[#526]: https://github.com/fsnotify/fsnotify/pull/526
+[#528]: https://github.com/fsnotify/fsnotify/pull/528
+[#537]: https://github.com/fsnotify/fsnotify/pull/537
+[#550]: https://github.com/fsnotify/fsnotify/pull/550
+[#572]: https://github.com/fsnotify/fsnotify/pull/572
 
+1.6.0 - 2022-10-13
+------------------
 This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1,
 but not documented). It also increases the minimum Linux version to 2.6.32.
 
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/notifier/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
index ea379759..e4ac2a2f 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
@@ -1,7 +1,7 @@
 Thank you for your interest in contributing to fsnotify! We try to review and
 merge PRs in a reasonable timeframe, but please be aware that:
 
-- To avoid "wasted" work, please discus changes on the issue tracker first. You
+- To avoid "wasted" work, please discuss changes on the issue tracker first. You
   can just send PRs, but they may end up being rejected for one reason or the
   other.
 
@@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like
 
 Use the `-short` flag to make the "stress test" run faster.
 
+Writing new tests
+-----------------
+Scripts in the testdata directory allow creating test cases in a "shell-like"
+syntax. The basic format is:
+
+    script
+
+    Output:
+    desired output
+
+For example:
+
+    # Create a new empty file with some data.
+    watch /
+    echo data >/file
+
+    Output:
+        create  /file
+        write   /file
+
+Just create a new file to add a new test; select which tests to run with
+`-run TestScript/[path]`.
+
+script
+------
+The script is a "shell-like" script:
+
+    cmd arg arg
+
+Comments are supported with `#`:
+
+    # Comment
+    cmd arg arg  # Comment
+
+All operations are done in a temp directory; a path like "/foo" is rewritten to
+"/tmp/TestFoo/foo".
+
+Arguments can be quoted with `"` or `'`; there are no escapes and they're
+functionally identical right now, but this may change in the future, so best to
+assume shell-like rules.
+
+    touch "/file with spaces"
+
+End-of-line escapes with `\` are not supported.
+
+### Supported commands
+
+    watch path [ops]    # Watch the path, reporting events for it. Nothing is
+                        # watched by default. Optionally a list of ops can be
+                        # given, as with AddWith(path, WithOps(...)).
+    unwatch path        # Stop watching the path.
+    watchlist n         # Assert watchlist length.
+
+    stop                # Stop running the script; for debugging.
+    debug [yes/no]      # Enable/disable FSNOTIFY_DEBUG (tests are run in
+                          parallel by default, so -parallel=1 is probably a good
+                          idea).
+
+    touch path
+    mkdir [-p] dir
+    ln -s target link   # Only ln -s supported.
+    mkfifo path
+    mknod dev path
+    mv src dst
+    rm [-r] path
+    chmod mode path     # Octal only
+    sleep time-in-ms
+
+    cat path            # Read path (does nothing with the data; just reads it).
+    echo str >>path     # Append "str" to "path".
+    echo str >path      # Truncate "path" and write "str".
+
+    require reason      # Skip the test if "reason" is true; "skip" and
+    skip reason         # "require" behave identical; it supports both for
+                        # readability. Possible reasons are:
+                        #
+                        #   always    Always skip this test.
+                        #   symlink   Symlinks are supported (requires admin
+                        #             permissions on Windows).
+                        #   mkfifo    Platform doesn't support FIFO named sockets.
+                        #   mknod     Platform doesn't support device nodes.
+
+
+output
+------
+After `Output:` the desired output is given; this is indented by convention, but
+that's not required.
+
+The format of that is:
+
+    # Comment
+    event  path  # Comment
+
+    system:
+        event  path
+    system2:
+        event  path
+
+Every event is one line, and any whitespace between the event and path are
+ignored. The path can optionally be surrounded in ". Anything after a "#" is
+ignored.
+
+Platform-specific tests can be added after GOOS; for example:
+
+    watch /
+    touch /file
+
+    Output:
+        # Tested if nothing else matches
+        create    /file
+
+        # Windows-specific test.
+        windows:
+            write  /file
+
+You can specify multiple platforms with a comma (e.g. "windows, linux:").
+"kqueue" is a shortcut for all kqueue systems (BSD, macOS).
+
 
 [goon]: https://github.com/arp242/goon
 [Vagrant]: https://www.vagrantup.com/
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/README.md b/notifier/vendor/github.com/fsnotify/fsnotify/README.md
index d4e6080f..e480733d 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/README.md
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/README.md
@@ -1,29 +1,31 @@
 fsnotify is a Go library to provide cross-platform filesystem notifications on
-Windows, Linux, macOS, and BSD systems.
+Windows, Linux, macOS, BSD, and illumos.
 
-Go 1.16 or newer is required; the full documentation is at
+Go 1.17 or newer is required; the full documentation is at
 https://pkg.go.dev/github.com/fsnotify/fsnotify
 
-**It's best to read the documentation at pkg.go.dev, as it's pinned to the last
-released version, whereas this README is for the last development version which
-may include additions/changes.**
-
 ---
 
 Platform support:
 
-| Adapter               | OS             | Status                                                       |
-| --------------------- | ---------------| -------------------------------------------------------------|
-| inotify               | Linux 2.6.32+  | Supported                                                    |
-| kqueue                | BSD, macOS     | Supported                                                    |
-| ReadDirectoryChangesW | Windows        | Supported                                                    |
-| FSEvents              | macOS          | [Planned](https://github.com/fsnotify/fsnotify/issues/11)    |
-| FEN                   | Solaris 11     | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) |
-| fanotify              | Linux 5.9+     | [Maybe](https://github.com/fsnotify/fsnotify/issues/114)     |
-| USN Journals          | Windows        | [Maybe](https://github.com/fsnotify/fsnotify/issues/53)      |
-| Polling               | *All*          | [Maybe](https://github.com/fsnotify/fsnotify/issues/9)       |
-
-Linux and macOS should include Android and iOS, but these are currently untested.
+| Backend               | OS         | Status                                                                    |
+| :-------------------- | :--------- | :------------------------------------------------------------------------ |
+| inotify               | Linux      | Supported                                                                 |
+| kqueue                | BSD, macOS | Supported                                                                 |
+| ReadDirectoryChangesW | Windows    | Supported                                                                 |
+| FEN                   | illumos    | Supported                                                                 |
+| fanotify              | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114)                |
+| AHAFS                 | AIX        | [aix branch]; experimental due to lack of maintainer and test environment |
+| FSEvents              | macOS      | [Needs support in x/sys/unix][fsevents]                                   |
+| USN Journals          | Windows    | [Needs support in x/sys/windows][usn]                                     |
+| Polling               | *All*      | [Not yet](https://github.com/fsnotify/fsnotify/issues/9)                  |
+
+Linux and illumos should include Android and Solaris, but these are currently
+untested.
+
+[fsevents]:   https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
+[usn]:        https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
+[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
 
 Usage
 -----
@@ -83,20 +85,23 @@ run with:
 
     % go run ./cmd/fsnotify
 
+Further detailed documentation can be found in godoc:
+https://pkg.go.dev/github.com/fsnotify/fsnotify
+
 FAQ
 ---
 ### Will a file still be watched when it's moved to another directory?
 No, not unless you are watching the location it was moved to.
 
-### Are subdirectories watched too?
+### Are subdirectories watched?
 No, you must add watches for any directory you want to watch (a recursive
 watcher is on the roadmap: [#18]).
 
 [#18]: https://github.com/fsnotify/fsnotify/issues/18
 
 ### Do I have to watch the Error and Event channels in a goroutine?
-As of now, yes (you can read both channels in the same goroutine using `select`,
-you don't need a separate goroutine for both channels; see the example).
+Yes. You can read both channels in the same goroutine using `select` (you don't
+need a separate goroutine for both channels; see the example).
 
 ### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys?
 fsnotify requires support from underlying OS to work. The current NFS and SMB
@@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented.
 
 [#9]: https://github.com/fsnotify/fsnotify/issues/9
 
+### Why do I get many Chmod events?
+Some programs may generate a lot of attribute changes; for example Spotlight on
+macOS, anti-virus programs, backup applications, and some others are known to do
+this. As a rule, it's typically best to ignore Chmod events. They're often not
+useful, and tend to cause problems.
+
+Spotlight indexing on macOS can result in multiple events (see [#15]). A
+temporary workaround is to add your folder(s) to the *Spotlight Privacy
+settings* until we have a native FSEvents implementation (see [#11]).
+
+[#11]: https://github.com/fsnotify/fsnotify/issues/11
+[#15]: https://github.com/fsnotify/fsnotify/issues/15
+
+### Watching a file doesn't work well
+Watching individual files (rather than directories) is generally not recommended
+as many programs (especially editors) update files atomically: it will write to
+a temporary file which is then moved to to destination, overwriting the original
+(or some variant thereof). The watcher on the original file is now lost, as that
+no longer exists.
+
+The upshot of this is that a power failure or crash won't leave a half-written
+file.
+
+Watch the parent directory and use `Event.Name` to filter out files you're not
+interested in. There is an example of this in `cmd/fsnotify/file.go`.
+
 Platform-specific notes
 -----------------------
 ### Linux
@@ -151,11 +182,3 @@ these platforms.
 
 The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to
 control the maximum number of open files.
-
-### macOS
-Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary
-workaround is to add your folder(s) to the *Spotlight Privacy settings* until we
-have a native FSEvents implementation (see [#11]).
-
-[#11]: https://github.com/fsnotify/fsnotify/issues/11
-[#15]: https://github.com/fsnotify/fsnotify/issues/15
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/notifier/vendor/github.com/fsnotify/fsnotify/backend_fen.go
index 1a95ad8e..c349c326 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/backend_fen.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/backend_fen.go
@@ -1,162 +1,484 @@
 //go:build solaris
-// +build solaris
+
+// FEN backend for illumos (supported) and Solaris (untested, but should work).
+//
+// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create
 
 package fsnotify
 
 import (
 	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"sync"
+	"time"
+
+	"github.com/fsnotify/fsnotify/internal"
+	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type fen struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
+
+	mu      sync.Mutex
+	port    *unix.EventPort
+	done    chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	dirs    map[string]Op // Explicitly watched directories
+	watches map[string]Op // Explicitly watched non-directories
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, errors.New("FEN based watcher not yet supported for fsnotify\n")
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	w := &fen{
+		Events:  ev,
+		Errors:  errs,
+		dirs:    make(map[string]Op),
+		watches: make(map[string]Op),
+		done:    make(chan struct{}),
+	}
+
+	var err error
+	w.port, err = unix.NewEventPort()
+	if err != nil {
+		return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err)
+	}
+
+	go w.readEvents()
+	return w, nil
+}
+
+// sendEvent attempts to send an event to the user, returning true if the event
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendEvent(name string, op Op) (sent bool) {
+	select {
+	case <-w.done:
+		return false
+	case w.Events <- Event{Name: name, Op: op}:
+		return true
+	}
+}
+
+// sendError attempts to send an error to the user, returning true if the error
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendError(err error) (sent bool) {
+	if err == nil {
+		return true
+	}
+	select {
+	case <-w.done:
+		return false
+	case w.Errors <- err:
+		return true
+	}
+}
+
+func (w *fen) isClosed() bool {
+	select {
+	case <-w.done:
+		return true
+	default:
+		return false
+	}
+}
+
+func (w *fen) Close() error {
+	// Take the lock used by associateFile to prevent lingering events from
+	// being processed after the close
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if w.isClosed() {
+		return nil
+	}
+	close(w.done)
+	return w.port.Close()
+}
+
+func (w *fen) Add(name string) error { return w.AddWith(name) }
+
+func (w *fen) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
+	// Currently we resolve symlinks that were explicitly requested to be
+	// watched. Otherwise we would use LStat here.
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Associate all files in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, true, w.associateFile)
+		if err != nil {
+			return err
+		}
+
+		w.mu.Lock()
+		w.dirs[name] = with.op
+		w.mu.Unlock()
+		return nil
+	}
+
+	err = w.associateFile(name, stat, true)
+	if err != nil {
+		return err
+	}
+
+	w.mu.Lock()
+	w.watches[name] = with.op
+	w.mu.Unlock()
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
+func (w *fen) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if !w.port.PathIsWatched(name) {
+		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	// The user has expressed an intent. Immediately remove this name from
+	// whichever watch list it might be in. If it's not in there the delete
+	// doesn't cause harm.
+	w.mu.Lock()
+	delete(w.watches, name)
+	delete(w.dirs, name)
+	w.mu.Unlock()
+
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Remove associations for every file in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, false, w.dissociateFile)
+		if err != nil {
+			return err
+		}
+		return nil
+	}
+
+	err = w.port.DissociatePath(name)
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+// readEvents contains the main loop that runs in a goroutine watching for events.
+func (w *fen) readEvents() {
+	// If this function returns, the watcher has been closed and we can close
+	// these channels
+	defer func() {
+		close(w.Errors)
+		close(w.Events)
+	}()
+
+	pevents := make([]unix.PortEvent, 8)
+	for {
+		count, err := w.port.Get(pevents, 1, nil)
+		if err != nil && err != unix.ETIME {
+			// Interrupted system call (count should be 0) ignore and continue
+			if errors.Is(err, unix.EINTR) && count == 0 {
+				continue
+			}
+			// Get failed because we called w.Close()
+			if errors.Is(err, unix.EBADF) && w.isClosed() {
+				return
+			}
+			// There was an error not caused by calling w.Close()
+			if !w.sendError(err) {
+				return
+			}
+		}
+
+		p := pevents[:count]
+		for _, pevent := range p {
+			if pevent.Source != unix.PORT_SOURCE_FILE {
+				// Event from unexpected source received; should never happen.
+				if !w.sendError(errors.New("Event from unexpected source received")) {
+					return
+				}
+				continue
+			}
+
+			if debug {
+				internal.Debug(pevent.Path, pevent.Events)
+			}
+
+			err = w.handleEvent(&pevent)
+			if !w.sendError(err) {
+				return
+			}
+		}
+	}
+}
+
+func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	// Handle all children of the directory.
+	for _, entry := range files {
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = handler(filepath.Join(path, finfo.Name()), finfo, false)
+		if err != nil {
+			return err
+		}
+	}
+
+	// And finally handle the directory itself.
+	return handler(path, stat, follow)
+}
+
+// handleEvent might need to emit more than one fsnotify event if the events
+// bitmap matches more than one event type (e.g. the file was both modified and
+// had the attributes changed between when the association was created and the
+// when event was returned)
+func (w *fen) handleEvent(event *unix.PortEvent) error {
+	var (
+		events     = event.Events
+		path       = event.Path
+		fmode      = event.Cookie.(os.FileMode)
+		reRegister = true
+	)
+
+	w.mu.Lock()
+	_, watchedDir := w.dirs[path]
+	_, watchedPath := w.watches[path]
+	w.mu.Unlock()
+	isWatched := watchedDir || watchedPath
+
+	if events&unix.FILE_DELETE != 0 {
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_FROM != 0 {
+		if !w.sendEvent(path, Rename) {
+			return nil
+		}
+		// Don't keep watching the new file name
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_TO != 0 {
+		// We don't report a Rename event for this case, because Rename events
+		// are interpreted as referring to the _old_ name of the file, and in
+		// this case the event would refer to the new name of the file. This
+		// type of rename event is not supported by fsnotify.
+
+		// inotify reports a Remove event in this case, so we simulate this
+		// here.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Don't keep watching the file that was removed
+		reRegister = false
+	}
+
+	// The file is gone, nothing left to do.
+	if !reRegister {
+		if watchedDir {
+			w.mu.Lock()
+			delete(w.dirs, path)
+			w.mu.Unlock()
+		}
+		if watchedPath {
+			w.mu.Lock()
+			delete(w.watches, path)
+			w.mu.Unlock()
+		}
+		return nil
+	}
+
+	// If we didn't get a deletion the file still exists and we're going to have
+	// to watch it again. Let's Stat it now so that we can compare permissions
+	// and have what we need to continue watching the file
+
+	stat, err := os.Lstat(path)
+	if err != nil {
+		// This is unexpected, but we should still emit an event. This happens
+		// most often on "rm -r" of a subdirectory inside a watched directory We
+		// get a modify event of something happening inside, but by the time we
+		// get here, the sudirectory is already gone. Clearly we were watching
+		// this path but now it is gone. Let's tell the user that it was
+		// removed.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Suppress extra write events on removed directories; they are not
+		// informative and can be confusing.
+		return nil
+	}
+
+	// resolve symlinks that were explicitly watched as we would have at Add()
+	// time. this helps suppress spurious Chmod events on watched symlinks
+	if isWatched {
+		stat, err = os.Stat(path)
+		if err != nil {
+			// The symlink still exists, but the target is gone. Report the
+			// Remove similar to above.
+			if !w.sendEvent(path, Remove) {
+				return nil
+			}
+			// Don't return the error
+		}
+	}
+
+	if events&unix.FILE_MODIFIED != 0 {
+		if fmode.IsDir() && watchedDir {
+			if err := w.updateDirectory(path); err != nil {
+				return err
+			}
+		} else {
+			if !w.sendEvent(path, Write) {
+				return nil
+			}
+		}
+	}
+	if events&unix.FILE_ATTRIB != 0 && stat != nil {
+		// Only send Chmod if perms changed
+		if stat.Mode().Perm() != fmode.Perm() {
+			if !w.sendEvent(path, Chmod) {
+				return nil
+			}
+		}
+	}
+
+	if stat != nil {
+		// If we get here, it means we've hit an event above that requires us to
+		// continue watching the file or directory
+		return w.associateFile(path, stat, isWatched)
+	}
+	return nil
+}
+
+func (w *fen) updateDirectory(path string) error {
+	// The directory was modified, so we must find unwatched entities and watch
+	// them. If something was removed from the directory, nothing will happen,
+	// as everything else should still be watched.
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	for _, entry := range files {
+		path := filepath.Join(path, entry.Name())
+		if w.port.PathIsWatched(path) {
+			continue
+		}
+
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = w.associateFile(path, finfo, false)
+		if !w.sendError(err) {
+			return nil
+		}
+		if !w.sendEvent(path, Create) {
+			return nil
+		}
+	}
 	return nil
 }
+
+func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	// This is primarily protecting the call to AssociatePath but it is
+	// important and intentional that the call to PathIsWatched is also
+	// protected by this mutex. Without this mutex, AssociatePath has been seen
+	// to error out that the path is already associated.
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.port.PathIsWatched(path) {
+		// Remove the old association in favor of this one If we get ENOENT,
+		// then while the x/sys/unix wrapper still thought that this path was
+		// associated, the underlying event port did not. This call will have
+		// cleared up that discrepancy. The most likely cause is that the event
+		// has fired but we haven't processed it yet.
+		err := w.port.DissociatePath(path)
+		if err != nil && !errors.Is(err, unix.ENOENT) {
+			return err
+		}
+	}
+
+	var events int
+	if !follow {
+		// Watch symlinks themselves rather than their targets unless this entry
+		// is explicitly watched.
+		events |= unix.FILE_NOFOLLOW
+	}
+	if true { // TODO: implement withOps()
+		events |= unix.FILE_MODIFIED
+	}
+	if true {
+		events |= unix.FILE_ATTRIB
+	}
+	return w.port.AssociatePath(path, stat, events, stat.Mode())
+}
+
+func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
+	if !w.port.PathIsWatched(path) {
+		return nil
+	}
+	return w.port.DissociatePath(path)
+}
+
+func (w *fen) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	entries := make([]string, 0, len(w.watches)+len(w.dirs))
+	for pathname := range w.dirs {
+		entries = append(entries, pathname)
+	}
+	for pathname := range w.watches {
+		entries = append(entries, pathname)
+	}
+
+	return entries
+}
+
+func (w *fen) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/notifier/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
index 54c77fbb..36c31169 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
@@ -1,5 +1,4 @@
-//go:build linux
-// +build linux
+//go:build linux && !appengine
 
 package fsnotify
 
@@ -7,142 +6,188 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/fs"
 	"os"
 	"path/filepath"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type inotify struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	// Store fd here as os.File.Read() will no longer return on close after
 	// calling Fd(). See: https://github.com/golang/go/issues/26439
 	fd          int
-	mu          sync.Mutex // Map access
 	inotifyFile *os.File
-	watches     map[string]*watch // Map of inotify watches (key: path)
-	paths       map[int]string    // Map of watched paths (key: watch descriptor)
-	done        chan struct{}     // Channel for sending a "quit message" to the reader goroutine
-	doneResp    chan struct{}     // Channel to respond to Close
+	watches     *watches
+	done        chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	doneMu      sync.Mutex
+	doneResp    chan struct{} // Channel to respond to Close
+
+	// Store rename cookies in an array, with the index wrapping to 0. Almost
+	// all of the time what we get is a MOVED_FROM to set the cookie and the
+	// next event inotify sends will be MOVED_TO to read it. However, this is
+	// not guaranteed – as described in inotify(7) – and we may get other events
+	// between the two MOVED_* events (including other MOVED_* ones).
+	//
+	// A second issue is that moving a file outside the watched directory will
+	// trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to
+	// read and delete it. So just storing it in a map would slowly leak memory.
+	//
+	// Doing it like this gives us a simple fast LRU-cache that won't allocate.
+	// Ten items should be more than enough for our purpose, and a loop over
+	// such a short array is faster than a map access anyway (not that it hugely
+	// matters since we're talking about hundreds of ns at the most, but still).
+	cookies     [10]koekje
+	cookieIndex uint8
+	cookiesMu   sync.Mutex
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	// Create inotify fd
-	// Need to set the FD to nonblocking mode in order for SetDeadline methods to work
-	// Otherwise, blocking i/o operations won't terminate on close
+type (
+	watches struct {
+		mu   sync.RWMutex
+		wd   map[uint32]*watch // wd → watch
+		path map[string]uint32 // pathname → wd
+	}
+	watch struct {
+		wd      uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+		flags   uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+		path    string // Watch path.
+		recurse bool   // Recursion with ./...?
+	}
+	koekje struct {
+		cookie uint32
+		path   string
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:   make(map[uint32]*watch),
+		path: make(map[string]uint32),
+	}
+}
+
+func (w *watches) len() int {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return len(w.wd)
+}
+
+func (w *watches) add(ww *watch) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.wd[ww.wd] = ww
+	w.path[ww.path] = ww.wd
+}
+
+func (w *watches) remove(wd uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	watch := w.wd[wd] // Could have had Remove() called. See #616.
+	if watch == nil {
+		return
+	}
+	delete(w.path, watch.path)
+	delete(w.wd, wd)
+}
+
+func (w *watches) removePath(path string) ([]uint32, error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	path, recurse := recursivePath(path)
+	wd, ok := w.path[path]
+	if !ok {
+		return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path)
+	}
+
+	watch := w.wd[wd]
+	if recurse && !watch.recurse {
+		return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path)
+	}
+
+	delete(w.path, path)
+	delete(w.wd, wd)
+	if !watch.recurse {
+		return []uint32{wd}, nil
+	}
+
+	wds := make([]uint32, 0, 8)
+	wds = append(wds, wd)
+	for p, rwd := range w.path {
+		if filepath.HasPrefix(p, path) {
+			delete(w.path, p)
+			delete(w.wd, rwd)
+			wds = append(wds, rwd)
+		}
+	}
+	return wds, nil
+}
+
+func (w *watches) byPath(path string) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[w.path[path]]
+}
+
+func (w *watches) byWd(wd uint32) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[wd]
+}
+
+func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	var existing *watch
+	wd, ok := w.path[path]
+	if ok {
+		existing = w.wd[wd]
+	}
+
+	upd, err := f(existing)
+	if err != nil {
+		return err
+	}
+	if upd != nil {
+		w.wd[upd.wd] = upd
+		w.path[upd.path] = upd.wd
+
+		if upd.wd != wd {
+			delete(w.wd, wd)
+		}
+	}
+
+	return nil
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
+	// I/O operations won't terminate on close.
 	fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
 	if fd == -1 {
 		return nil, errno
 	}
 
-	w := &Watcher{
+	w := &inotify{
+		Events:      ev,
+		Errors:      errs,
 		fd:          fd,
 		inotifyFile: os.NewFile(uintptr(fd), ""),
-		watches:     make(map[string]*watch),
-		paths:       make(map[int]string),
-		Events:      make(chan Event),
-		Errors:      make(chan error),
+		watches:     newWatches(),
 		done:        make(chan struct{}),
 		doneResp:    make(chan struct{}),
 	}
@@ -152,26 +197,29 @@ func NewWatcher() (*Watcher, error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *inotify) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
-	select {
-	case w.Errors <- err:
+func (w *inotify) sendError(err error) bool {
+	if err == nil {
 		return true
+	}
+	select {
 	case <-w.done:
 		return false
+	case w.Errors <- err:
+		return true
 	}
 }
 
-func (w *Watcher) isClosed() bool {
+func (w *inotify) isClosed() bool {
 	select {
 	case <-w.done:
 		return true
@@ -180,17 +228,14 @@ func (w *Watcher) isClosed() bool {
 	}
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
+func (w *inotify) Close() error {
+	w.doneMu.Lock()
 	if w.isClosed() {
-		w.mu.Unlock()
+		w.doneMu.Unlock()
 		return nil
 	}
-
-	// Send 'close' signal to goroutine, and set the Watcher to closed.
 	close(w.done)
-	w.mu.Unlock()
+	w.doneMu.Unlock()
 
 	// Causes any blocking reads to return with an error, provided the file
 	// still supports deadline operations.
@@ -205,138 +250,168 @@ func (w *Watcher) Close() error {
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) Add(name string) error { return w.AddWith(name) }
+
+func (w *inotify) AddWith(path string, opts ...addOpt) error {
 	if w.isClosed() {
-		return errors.New("inotify instance already closed")
+		return ErrClosed
 	}
-
-	var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
-		unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
-		unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
-
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watchEntry := w.watches[name]
-	if watchEntry != nil {
-		flags |= watchEntry.flags | unix.IN_MASK_ADD
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), path)
 	}
-	wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
-	if wd == -1 {
-		return errno
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
 	}
 
-	if watchEntry == nil {
-		w.watches[name] = &watch{wd: uint32(wd), flags: flags}
-		w.paths[wd] = name
-	} else {
-		watchEntry.wd = uint32(wd)
-		watchEntry.flags = flags
+	path, recurse := recursivePath(path)
+	if recurse {
+		return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
+			if err != nil {
+				return err
+			}
+			if !d.IsDir() {
+				if root == path {
+					return fmt.Errorf("fsnotify: not a directory: %q", path)
+				}
+				return nil
+			}
+
+			// Send a Create event when adding new directory from a recursive
+			// watch; this is for "mkdir -p one/two/three". Usually all those
+			// directories will be created before we can set up watchers on the
+			// subdirectories, so only "one" would be sent as a Create event and
+			// not "one/two" and "one/two/three" (inotifywait -r has the same
+			// problem).
+			if with.sendCreate && root != path {
+				w.sendEvent(Event{Name: root, Op: Create})
+			}
+
+			return w.add(root, with, true)
+		})
 	}
 
-	return nil
+	return w.add(path, with, false)
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) add(path string, with withOpts, recurse bool) error {
+	var flags uint32
+	if with.noFollow {
+		flags |= unix.IN_DONT_FOLLOW
+	}
+	if with.op.Has(Create) {
+		flags |= unix.IN_CREATE
+	}
+	if with.op.Has(Write) {
+		flags |= unix.IN_MODIFY
+	}
+	if with.op.Has(Remove) {
+		flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
+	}
+	if with.op.Has(Rename) {
+		flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
+	}
+	if with.op.Has(Chmod) {
+		flags |= unix.IN_ATTRIB
+	}
+	if with.op.Has(xUnportableOpen) {
+		flags |= unix.IN_OPEN
+	}
+	if with.op.Has(xUnportableRead) {
+		flags |= unix.IN_ACCESS
+	}
+	if with.op.Has(xUnportableCloseWrite) {
+		flags |= unix.IN_CLOSE_WRITE
+	}
+	if with.op.Has(xUnportableCloseRead) {
+		flags |= unix.IN_CLOSE_NOWRITE
+	}
+	return w.register(path, flags, recurse)
+}
 
-	// Fetch the watch.
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watch, ok := w.watches[name]
+func (w *inotify) register(path string, flags uint32, recurse bool) error {
+	return w.watches.updatePath(path, func(existing *watch) (*watch, error) {
+		if existing != nil {
+			flags |= existing.flags | unix.IN_MASK_ADD
+		}
 
-	// Remove it from inotify.
-	if !ok {
-		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
-	}
-
-	// We successfully removed the watch if InotifyRmWatch doesn't return an
-	// error, we need to clean up our internal state to ensure it matches
-	// inotify's kernel state.
-	delete(w.paths, int(watch.wd))
-	delete(w.watches, name)
-
-	// inotify_rm_watch will return EINVAL if the file has been deleted;
-	// the inotify will already have been removed.
-	// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
-	// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
-	// so that EINVAL means that the wd is being rm_watch()ed or its file removed
-	// by another thread and we have not received IN_IGNORE event.
-	success, errno := unix.InotifyRmWatch(w.fd, watch.wd)
-	if success == -1 {
-		// TODO: Perhaps it's not helpful to return an error here in every case;
-		//       The only two possible errors are:
-		//
-		//       - EBADF, which happens when w.fd is not a valid file descriptor
-		//         of any kind.
-		//       - EINVAL, which is when fd is not an inotify descriptor or wd
-		//         is not a valid watch descriptor. Watch descriptors are
-		//         invalidated when they are removed explicitly or implicitly;
-		//         explicitly by inotify_rm_watch, implicitly when the file they
-		//         are watching is deleted.
-		return errno
+		wd, err := unix.InotifyAddWatch(w.fd, path, flags)
+		if wd == -1 {
+			return nil, err
+		}
+
+		if existing == nil {
+			return &watch{
+				wd:      uint32(wd),
+				path:    path,
+				flags:   flags,
+				recurse: recurse,
+			}, nil
+		}
+
+		existing.wd = uint32(wd)
+		existing.flags = flags
+		return existing, nil
+	})
+}
+
+func (w *inotify) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(filepath.Clean(name))
+}
+
+func (w *inotify) remove(name string) error {
+	wds, err := w.watches.removePath(name)
+	if err != nil {
+		return err
 	}
 
+	for _, wd := range wds {
+		_, err := unix.InotifyRmWatch(w.fd, wd)
+		if err != nil {
+			// TODO: Perhaps it's not helpful to return an error here in every
+			// case; the only two possible errors are:
+			//
+			// EBADF, which happens when w.fd is not a valid file descriptor of
+			// any kind.
+			//
+			// EINVAL, which is when fd is not an inotify descriptor or wd is
+			// not a valid watch descriptor. Watch descriptors are invalidated
+			// when they are removed explicitly or implicitly; explicitly by
+			// inotify_rm_watch, implicitly when the file they are watching is
+			// deleted.
+			return err
+		}
+	}
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
+func (w *inotify) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
 
-	entries := make([]string, 0, len(w.watches))
-	for pathname := range w.watches {
+	entries := make([]string, 0, w.watches.len())
+	w.watches.mu.RLock()
+	for pathname := range w.watches.path {
 		entries = append(entries, pathname)
 	}
+	w.watches.mu.RUnlock()
 
 	return entries
 }
 
-type watch struct {
-	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
-	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
-}
-
 // readEvents reads from the inotify file descriptor, converts the
 // received events into Event objects and sends them via the Events channel
-func (w *Watcher) readEvents() {
+func (w *inotify) readEvents() {
 	defer func() {
 		close(w.doneResp)
 		close(w.Errors)
@@ -367,14 +442,11 @@ func (w *Watcher) readEvents() {
 		if n < unix.SizeofInotifyEvent {
 			var err error
 			if n == 0 {
-				// If EOF is received. This should really never happen.
-				err = io.EOF
+				err = io.EOF // If EOF is received. This should really never happen.
 			} else if n < 0 {
-				// If an error occurred while reading.
-				err = errno
+				err = errno // If an error occurred while reading.
 			} else {
-				// Read was too short.
-				err = errors.New("notify: short read in readEvents()")
+				err = errors.New("notify: short read in readEvents()") // Read was too short.
 			}
 			if !w.sendError(err) {
 				return
@@ -382,15 +454,17 @@ func (w *Watcher) readEvents() {
 			continue
 		}
 
-		var offset uint32
 		// We don't know how many events we just read into the buffer
 		// While the offset points to at least one whole event...
+		var offset uint32
 		for offset <= uint32(n-unix.SizeofInotifyEvent) {
 			var (
 				// Point "raw" to the event in the buffer
 				raw     = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
 				mask    = uint32(raw.Mask)
 				nameLen = uint32(raw.Len)
+				// Move to the next event in the buffer
+				next = func() { offset += unix.SizeofInotifyEvent + nameLen }
 			)
 
 			if mask&unix.IN_Q_OVERFLOW != 0 {
@@ -399,46 +473,124 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			// If the event happened to the watched directory or the watched file, the kernel
-			// doesn't append the filename to the event, but we would like to always fill the
-			// the "Name" field with a valid filename. We retrieve the path of the watch from
-			// the "paths" map.
-			w.mu.Lock()
-			name, ok := w.paths[int(raw.Wd)]
-			// IN_DELETE_SELF occurs when the file/directory being watched is removed.
-			// This is a sign to clean up the maps, otherwise we are no longer in sync
-			// with the inotify kernel state which has already deleted the watch
-			// automatically.
-			if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
-				delete(w.paths, int(raw.Wd))
-				delete(w.watches, name)
+			/// If the event happened to the watched directory or the watched
+			/// file, the kernel doesn't append the filename to the event, but
+			/// we would like to always fill the the "Name" field with a valid
+			/// filename. We retrieve the path of the watch from the "paths"
+			/// map.
+			watch := w.watches.byWd(uint32(raw.Wd))
+			/// Can be nil if Remove() was called in another goroutine for this
+			/// path inbetween reading the events from the kernel and reading
+			/// the internal state. Not much we can do about it, so just skip.
+			/// See #616.
+			if watch == nil {
+				next()
+				continue
 			}
-			w.mu.Unlock()
 
+			name := watch.path
 			if nameLen > 0 {
-				// Point "bytes" at the first byte of the filename
+				/// Point "bytes" at the first byte of the filename
 				bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
-				// The filename is padded with NULL bytes. TrimRight() gets rid of those.
+				/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
 				name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
 			}
 
-			event := w.newEvent(name, mask)
+			if debug {
+				internal.Debug(name, raw.Mask, raw.Cookie)
+			}
 
-			// Send the events that are not ignored on the events channel
-			if mask&unix.IN_IGNORED == 0 {
-				if !w.sendEvent(event) {
-					return
+			if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
+				next()
+				continue
+			}
+
+			// inotify will automatically remove the watch on deletes; just need
+			// to clean our state here.
+			if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
+				w.watches.remove(watch.wd)
+			}
+
+			// We can't really update the state when a watched path is moved;
+			// only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
+			// the watch.
+			if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
+				if watch.recurse {
+					next() // Do nothing
+					continue
+				}
+
+				err := w.remove(watch.path)
+				if err != nil && !errors.Is(err, ErrNonExistentWatch) {
+					if !w.sendError(err) {
+						return
+					}
+				}
+			}
+
+			/// Skip if we're watching both this path and the parent; the parent
+			/// will already send a delete so no need to do it twice.
+			if mask&unix.IN_DELETE_SELF != 0 {
+				if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok {
+					next()
+					continue
+				}
+			}
+
+			ev := w.newEvent(name, mask, raw.Cookie)
+			// Need to update watch path for recurse.
+			if watch.recurse {
+				isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR
+				/// New directory created: set up watch on it.
+				if isDir && ev.Has(Create) {
+					err := w.register(ev.Name, watch.flags, true)
+					if !w.sendError(err) {
+						return
+					}
+
+					// This was a directory rename, so we need to update all
+					// the children.
+					//
+					// TODO: this is of course pretty slow; we should use a
+					// better data structure for storing all of this, e.g. store
+					// children in the watch. I have some code for this in my
+					// kqueue refactor we can use in the future. For now I'm
+					// okay with this as it's not publicly available.
+					// Correctness first, performance second.
+					if ev.renamedFrom != "" {
+						w.watches.mu.Lock()
+						for k, ww := range w.watches.wd {
+							if k == watch.wd || ww.path == ev.Name {
+								continue
+							}
+							if strings.HasPrefix(ww.path, ev.renamedFrom) {
+								ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
+								w.watches.wd[k] = ww
+							}
+						}
+						w.watches.mu.Unlock()
+					}
 				}
 			}
 
-			// Move to the next event in the buffer
-			offset += unix.SizeofInotifyEvent + nameLen
+			/// Send the events that are not ignored on the events channel
+			if !w.sendEvent(ev) {
+				return
+			}
+			next()
 		}
 	}
 }
 
-// newEvent returns an platform-independent Event based on an inotify mask.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *inotify) isRecursive(path string) bool {
+	ww := w.watches.byPath(path)
+	if ww == nil { // path could be a file, so also check the Dir.
+		ww = w.watches.byPath(filepath.Dir(path))
+	}
+	return ww != nil && ww.recurse
+}
+
+func (w *inotify) newEvent(name string, mask, cookie uint32) Event {
 	e := Event{Name: name}
 	if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
 		e.Op |= Create
@@ -449,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.IN_MODIFY == unix.IN_MODIFY {
 		e.Op |= Write
 	}
+	if mask&unix.IN_OPEN == unix.IN_OPEN {
+		e.Op |= xUnportableOpen
+	}
+	if mask&unix.IN_ACCESS == unix.IN_ACCESS {
+		e.Op |= xUnportableRead
+	}
+	if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE {
+		e.Op |= xUnportableCloseWrite
+	}
+	if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE {
+		e.Op |= xUnportableCloseRead
+	}
 	if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
 		e.Op |= Rename
 	}
 	if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
 		e.Op |= Chmod
 	}
+
+	if cookie != 0 {
+		if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
+			w.cookiesMu.Lock()
+			w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name}
+			w.cookieIndex++
+			if w.cookieIndex > 9 {
+				w.cookieIndex = 0
+			}
+			w.cookiesMu.Unlock()
+		} else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
+			w.cookiesMu.Lock()
+			var prev string
+			for _, c := range w.cookies {
+				if c.cookie == cookie {
+					prev = c.path
+					break
+				}
+			}
+			w.cookiesMu.Unlock()
+			e.renamedFrom = prev
+		}
+	}
 	return e
 }
+
+func (w *inotify) xSupports(op Op) bool {
+	return true // Supports everything.
+}
+
+func (w *inotify) state() {
+	w.watches.mu.Lock()
+	defer w.watches.mu.Unlock()
+	for wd, ww := range w.watches.wd {
+		fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
+	}
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/notifier/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
index 29087469..d8de5ab7 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
@@ -1,155 +1,201 @@
 //go:build freebsd || openbsd || netbsd || dragonfly || darwin
-// +build freebsd openbsd netbsd dragonfly darwin
 
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
+	"runtime"
 	"sync"
+	"time"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type kqueue struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
-	done         chan struct{}
-	kq           int                         // File descriptor (as returned by the kqueue() syscall).
-	closepipe    [2]int                      // Pipe used for closing.
-	mu           sync.Mutex                  // Protects access to watcher data
-	watches      map[string]int              // Watched file descriptors (key: path).
-	watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)).
-	userWatches  map[string]struct{}         // Watches added with Watcher.Add()
-	dirFlags     map[string]uint32           // Watched directories to fflags used in kqueue.
-	paths        map[int]pathInfo            // File descriptors to path names for processing kqueue events.
-	fileExists   map[string]struct{}         // Keep track of if we know this file exists (to stop duplicate create events).
-	isClosed     bool                        // Set to true when Close() is first called
+	kq        int    // File descriptor (as returned by the kqueue() syscall).
+	closepipe [2]int // Pipe used for closing kq.
+	watches   *watches
+	done      chan struct{}
+	doneMu    sync.Mutex
 }
 
-type pathInfo struct {
-	name  string
-	isDir bool
+type (
+	watches struct {
+		mu     sync.RWMutex
+		wd     map[int]watch               // wd → watch
+		path   map[string]int              // pathname → wd
+		byDir  map[string]map[int]struct{} // dirname(path) → wd
+		seen   map[string]struct{}         // Keep track of if we know this file exists.
+		byUser map[string]struct{}         // Watches added with Watcher.Add()
+	}
+	watch struct {
+		wd       int
+		name     string
+		linkName string // In case of links; name is the target, and this is the link.
+		isDir    bool
+		dirFlags uint32
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:     make(map[int]watch),
+		path:   make(map[string]int),
+		byDir:  make(map[string]map[int]struct{}),
+		seen:   make(map[string]struct{}),
+		byUser: make(map[string]struct{}),
+	}
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func (w *watches) listPaths(userOnly bool) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	if userOnly {
+		l := make([]string, 0, len(w.byUser))
+		for p := range w.byUser {
+			l = append(l, p)
+		}
+		return l
+	}
+
+	l := make([]string, 0, len(w.path))
+	for p := range w.path {
+		l = append(l, p)
+	}
+	return l
+}
+
+func (w *watches) watchesInDir(path string) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	l := make([]string, 0, 4)
+	for fd := range w.byDir[path] {
+		info := w.wd[fd]
+		if _, ok := w.byUser[info.name]; !ok {
+			l = append(l, info.name)
+		}
+	}
+	return l
+}
+
+// Mark path as added by the user.
+func (w *watches) addUserWatch(path string) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.byUser[path] = struct{}{}
+}
+
+func (w *watches) addLink(path string, fd int) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.seen[path] = struct{}{}
+}
+
+func (w *watches) add(path, linkPath string, fd int, isDir bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir}
+
+	parent := filepath.Dir(path)
+	byDir, ok := w.byDir[parent]
+	if !ok {
+		byDir = make(map[int]struct{}, 1)
+		w.byDir[parent] = byDir
+	}
+	byDir[fd] = struct{}{}
+}
+
+func (w *watches) byWd(fd int) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[fd]
+	return info, ok
+}
+
+func (w *watches) byPath(path string) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[w.path[path]]
+	return info, ok
+}
+
+func (w *watches) updateDirFlags(path string, flags uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	fd := w.path[path]
+	info := w.wd[fd]
+	info.dirFlags = flags
+	w.wd[fd] = info
+}
+
+func (w *watches) remove(fd int, path string) bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	isDir := w.wd[fd].isDir
+	delete(w.path, path)
+	delete(w.byUser, path)
+
+	parent := filepath.Dir(path)
+	delete(w.byDir[parent], fd)
+
+	if len(w.byDir[parent]) == 0 {
+		delete(w.byDir, parent)
+	}
+
+	delete(w.wd, fd)
+	delete(w.seen, path)
+	return isDir
+}
+
+func (w *watches) markSeen(path string, exists bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if exists {
+		w.seen[path] = struct{}{}
+	} else {
+		delete(w.seen, path)
+	}
+}
+
+func (w *watches) seenBefore(path string) bool {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	_, ok := w.seen[path]
+	return ok
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	kq, closepipe, err := newKqueue()
 	if err != nil {
 		return nil, err
 	}
 
-	w := &Watcher{
-		kq:           kq,
-		closepipe:    closepipe,
-		watches:      make(map[string]int),
-		watchesByDir: make(map[string]map[int]struct{}),
-		dirFlags:     make(map[string]uint32),
-		paths:        make(map[int]pathInfo),
-		fileExists:   make(map[string]struct{}),
-		userWatches:  make(map[string]struct{}),
-		Events:       make(chan Event),
-		Errors:       make(chan error),
-		done:         make(chan struct{}),
+	w := &kqueue{
+		Events:    ev,
+		Errors:    errs,
+		kq:        kq,
+		closepipe: closepipe,
+		done:      make(chan struct{}),
+		watches:   newWatches(),
 	}
 
 	go w.readEvents()
@@ -174,6 +220,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 		unix.Close(kq)
 		return kq, closepipe, err
 	}
+	unix.CloseOnExec(closepipe[0])
+	unix.CloseOnExec(closepipe[1])
 
 	// Register changes to listen on the closepipe.
 	changes := make([]unix.Kevent_t, 1)
@@ -192,218 +240,172 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *kqueue) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *kqueue) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
+	case <-w.done:
+		return false
 	case w.Errors <- err:
 		return true
+	}
+}
+
+func (w *kqueue) isClosed() bool {
+	select {
 	case <-w.done:
+		return true
+	default:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *kqueue) Close() error {
+	w.doneMu.Lock()
+	if w.isClosed() {
+		w.doneMu.Unlock()
 		return nil
 	}
-	w.isClosed = true
+	close(w.done)
+	w.doneMu.Unlock()
 
-	// copy paths to remove while locked
-	pathsToRemove := make([]string, 0, len(w.watches))
-	for name := range w.watches {
-		pathsToRemove = append(pathsToRemove, name)
-	}
-	w.mu.Unlock() // Unlock before calling Remove, which also locks
+	pathsToRemove := w.watches.listPaths(false)
 	for _, name := range pathsToRemove {
 		w.Remove(name)
 	}
 
 	// Send "quit" message to the reader goroutine.
 	unix.Close(w.closepipe[1])
-	close(w.done)
-
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	w.userWatches[name] = struct{}{}
-	w.mu.Unlock()
+func (w *kqueue) Add(name string) error { return w.AddWith(name) }
+
+func (w *kqueue) AddWith(name string, opts ...addOpt) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
 	_, err := w.addWatch(name, noteAllEvents)
-	return err
+	if err != nil {
+		return err
+	}
+	w.watches.addUserWatch(name)
+	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *kqueue) Remove(name string) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(name, true)
+}
+
+func (w *kqueue) remove(name string, unwatchFiles bool) error {
+	if w.isClosed() {
+		return nil
+	}
+
 	name = filepath.Clean(name)
-	w.mu.Lock()
-	watchfd, ok := w.watches[name]
-	w.mu.Unlock()
+	info, ok := w.watches.byPath(name)
 	if !ok {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_DELETE, 0)
+	err := w.register([]int{info.wd}, unix.EV_DELETE, 0)
 	if err != nil {
 		return err
 	}
 
-	unix.Close(watchfd)
-
-	w.mu.Lock()
-	isDir := w.paths[watchfd].isDir
-	delete(w.watches, name)
-	delete(w.userWatches, name)
-
-	parentName := filepath.Dir(name)
-	delete(w.watchesByDir[parentName], watchfd)
-
-	if len(w.watchesByDir[parentName]) == 0 {
-		delete(w.watchesByDir, parentName)
-	}
+	unix.Close(info.wd)
 
-	delete(w.paths, watchfd)
-	delete(w.dirFlags, name)
-	delete(w.fileExists, name)
-	w.mu.Unlock()
+	isDir := w.watches.remove(info.wd, name)
 
 	// Find all watched paths that are in this directory that are not external.
-	if isDir {
-		var pathsToRemove []string
-		w.mu.Lock()
-		for fd := range w.watchesByDir[name] {
-			path := w.paths[fd]
-			if _, ok := w.userWatches[path.name]; !ok {
-				pathsToRemove = append(pathsToRemove, path.name)
-			}
-		}
-		w.mu.Unlock()
+	if unwatchFiles && isDir {
+		pathsToRemove := w.watches.watchesInDir(name)
 		for _, name := range pathsToRemove {
-			// Since these are internal, not much sense in propagating error
-			// to the user, as that will just confuse them with an error about
-			// a path they did not explicitly watch themselves.
+			// Since these are internal, not much sense in propagating error to
+			// the user, as that will just confuse them with an error about a
+			// path they did not explicitly watch themselves.
 			w.Remove(name)
 		}
 	}
-
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-
-	entries := make([]string, 0, len(w.userWatches))
-	for pathname := range w.userWatches {
-		entries = append(entries, pathname)
+func (w *kqueue) WatchList() []string {
+	if w.isClosed() {
+		return nil
 	}
-
-	return entries
+	return w.watches.listPaths(true)
 }
 
 // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
 const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
 
-// addWatch adds name to the watched file set.
-// The flags are interpreted as described in kevent(2).
-// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
-func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
-	var isDir bool
-	// Make ./name and name equivalent
-	name = filepath.Clean(name)
-
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return "", errors.New("kevent instance already closed")
-	}
-	watchfd, alreadyWatching := w.watches[name]
-	// We already have a watch, but we can still override flags.
-	if alreadyWatching {
-		isDir = w.paths[watchfd].isDir
+// addWatch adds name to the watched file set; the flags are interpreted as
+// described in kevent(2).
+//
+// Returns the real path to the file which was added, with symlinks resolved.
+func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
+	if w.isClosed() {
+		return "", ErrClosed
 	}
-	w.mu.Unlock()
 
+	name = filepath.Clean(name)
+
+	info, alreadyWatching := w.watches.byPath(name)
 	if !alreadyWatching {
 		fi, err := os.Lstat(name)
 		if err != nil {
 			return "", err
 		}
 
-		// Don't watch sockets or named pipes
+		// Don't watch sockets or named pipes.
 		if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) {
 			return "", nil
 		}
 
-		// Follow Symlinks
-		//
-		// Linux can add unresolvable symlinks to the watch list without issue,
-		// and Windows can't do symlinks period. To maintain consistency, we
-		// will act like everything is fine if the link can't be resolved.
-		// There will simply be no file events for broken symlinks. Hence the
-		// returns of nil on errors.
+		// Follow symlinks.
 		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
-			name, err = filepath.EvalSymlinks(name)
+			link, err := os.Readlink(name)
 			if err != nil {
+				// Return nil because Linux can add unresolvable symlinks to the
+				// watch list without problems, so maintain consistency with
+				// that. There will be no file events for broken symlinks.
+				// TODO: more specific check; returns os.PathError; ENOENT?
 				return "", nil
 			}
 
-			w.mu.Lock()
-			_, alreadyWatching = w.watches[name]
-			w.mu.Unlock()
-
+			_, alreadyWatching = w.watches.byPath(link)
 			if alreadyWatching {
-				return name, nil
+				// Add to watches so we don't get spurious Create events later
+				// on when we diff the directories.
+				w.watches.addLink(name, 0)
+				return link, nil
 			}
 
+			info.linkName = name
+			name = link
 			fi, err = os.Lstat(name)
 			if err != nil {
 				return "", nil
@@ -411,9 +413,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 		}
 
 		// Retry on EINTR; open() can return EINTR in practice on macOS.
-		// See #354, and go issues 11180 and 39237.
+		// See #354, and Go issues 11180 and 39237.
 		for {
-			watchfd, err = unix.Open(name, openMode, 0)
+			info.wd, err = unix.Open(name, openMode, 0)
 			if err == nil {
 				break
 			}
@@ -424,41 +426,25 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 			return "", err
 		}
 
-		isDir = fi.IsDir()
+		info.isDir = fi.IsDir()
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
+	err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
 	if err != nil {
-		unix.Close(watchfd)
+		unix.Close(info.wd)
 		return "", err
 	}
 
 	if !alreadyWatching {
-		w.mu.Lock()
-		parentName := filepath.Dir(name)
-		w.watches[name] = watchfd
-
-		watchesByDir, ok := w.watchesByDir[parentName]
-		if !ok {
-			watchesByDir = make(map[int]struct{}, 1)
-			w.watchesByDir[parentName] = watchesByDir
-		}
-		watchesByDir[watchfd] = struct{}{}
-
-		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
-		w.mu.Unlock()
+		w.watches.add(name, info.linkName, info.wd, info.isDir)
 	}
 
-	if isDir {
-		// Watch the directory if it has not been watched before,
-		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
-		w.mu.Lock()
-
+	// Watch the directory if it has not been watched before, or if it was
+	// watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
+	if info.isDir {
 		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
-			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
-		// Store flags so this watch can be updated later
-		w.dirFlags[name] = flags
-		w.mu.Unlock()
+			(!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
+		w.watches.updateDirFlags(name, flags)
 
 		if watchDir {
 			if err := w.watchDirectoryFiles(name); err != nil {
@@ -471,95 +457,110 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 
 // readEvents reads from kqueue and converts the received kevents into
 // Event values that it sends down the Events channel.
-func (w *Watcher) readEvents() {
+func (w *kqueue) readEvents() {
 	defer func() {
-		err := unix.Close(w.kq)
-		if err != nil {
-			w.Errors <- err
-		}
-		unix.Close(w.closepipe[0])
 		close(w.Events)
 		close(w.Errors)
+		_ = unix.Close(w.kq)
+		unix.Close(w.closepipe[0])
 	}()
 
 	eventBuffer := make([]unix.Kevent_t, 10)
-	for closed := false; !closed; {
+	for {
 		kevents, err := w.read(eventBuffer)
 		// EINTR is okay, the syscall was interrupted before timeout expired.
 		if err != nil && err != unix.EINTR {
 			if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) {
-				closed = true
+				return
 			}
-			continue
 		}
 
-		// Flush the events we received to the Events channel
 		for _, kevent := range kevents {
 			var (
-				watchfd = int(kevent.Ident)
-				mask    = uint32(kevent.Fflags)
+				wd   = int(kevent.Ident)
+				mask = uint32(kevent.Fflags)
 			)
 
 			// Shut down the loop when the pipe is closed, but only after all
 			// other events have been processed.
-			if watchfd == w.closepipe[0] {
-				closed = true
-				continue
+			if wd == w.closepipe[0] {
+				return
 			}
 
-			w.mu.Lock()
-			path := w.paths[watchfd]
-			w.mu.Unlock()
-
-			event := w.newEvent(path.name, mask)
+			path, ok := w.watches.byWd(wd)
+			if debug {
+				internal.Debug(path.name, &kevent)
+			}
 
-			if path.isDir && !event.Has(Remove) {
-				// Double check to make sure the directory exists. This can
-				// happen when we do a rm -fr on a recursively watched folders
-				// and we receive a modification event first but the folder has
-				// been deleted and later receive the delete event.
-				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
-					event.Op |= Remove
-				}
+			// On macOS it seems that sometimes an event with Ident=0 is
+			// delivered, and no other flags/information beyond that, even
+			// though we never saw such a file descriptor. For example in
+			// TestWatchSymlink/277 (usually at the end, but sometimes sooner):
+			//
+			// fmt.Printf("READ: %2d  %#v\n", kevent.Ident, kevent)
+			// unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			// unix.Kevent_t{Ident:0x0,  Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			//
+			// The first is a normal event, the second with Ident 0. No error
+			// flag, no data, no ... nothing.
+			//
+			// I read a bit through bsd/kern_event.c from the xnu source, but I
+			// don't really see an obvious location where this is triggered –
+			// this doesn't seem intentional, but idk...
+			//
+			// Technically fd 0 is a valid descriptor, so only skip it if
+			// there's no path, and if we're on macOS.
+			if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" {
+				continue
 			}
 
+			event := w.newEvent(path.name, path.linkName, mask)
+
 			if event.Has(Rename) || event.Has(Remove) {
-				w.Remove(event.Name)
-				w.mu.Lock()
-				delete(w.fileExists, event.Name)
-				w.mu.Unlock()
+				w.remove(event.Name, false)
+				w.watches.markSeen(event.Name, false)
 			}
 
 			if path.isDir && event.Has(Write) && !event.Has(Remove) {
-				w.sendDirectoryChangeEvents(event.Name)
-			} else {
-				if !w.sendEvent(event) {
-					closed = true
-					continue
-				}
+				w.dirChange(event.Name)
+			} else if !w.sendEvent(event) {
+				return
 			}
 
 			if event.Has(Remove) {
-				// Look for a file that may have overwritten this.
-				// For example, mv f1 f2 will delete f2, then create f2.
+				// Look for a file that may have overwritten this; for example,
+				// mv f1 f2 will delete f2, then create f2.
 				if path.isDir {
 					fileDir := filepath.Clean(event.Name)
-					w.mu.Lock()
-					_, found := w.watches[fileDir]
-					w.mu.Unlock()
+					_, found := w.watches.byPath(fileDir)
 					if found {
-						// make sure the directory exists before we watch for changes. When we
-						// do a recursive watch and perform rm -fr, the parent directory might
-						// have gone missing, ignore the missing directory and let the
-						// upcoming delete event remove the watch from the parent directory.
-						if _, err := os.Lstat(fileDir); err == nil {
-							w.sendDirectoryChangeEvents(fileDir)
+						// TODO: this branch is never triggered in any test.
+						// Added in d6220df (2012).
+						// isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111
+						//
+						// I don't really get how this can be triggered either.
+						// And it wasn't triggered in the patch that added it,
+						// either.
+						//
+						// Original also had a comment:
+						//   make sure the directory exists before we watch for
+						//   changes. When we do a recursive watch and perform
+						//   rm -rf, the parent directory might have gone
+						//   missing, ignore the missing directory and let the
+						//   upcoming delete event remove the watch from the
+						//   parent directory.
+						err := w.dirChange(fileDir)
+						if !w.sendError(err) {
+							return
 						}
 					}
 				} else {
-					filePath := filepath.Clean(event.Name)
-					if fileInfo, err := os.Lstat(filePath); err == nil {
-						w.sendFileCreatedEventIfNew(filePath, fileInfo)
+					path := filepath.Clean(event.Name)
+					if fi, err := os.Lstat(path); err == nil {
+						err := w.sendCreateIfNew(path, fi)
+						if !w.sendError(err) {
+							return
+						}
 					}
 				}
 			}
@@ -568,8 +569,14 @@ func (w *Watcher) readEvents() {
 }
 
 // newEvent returns an platform-independent Event based on kqueue Fflags.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *kqueue) newEvent(name, linkName string, mask uint32) Event {
 	e := Event{Name: name}
+	if linkName != "" {
+		// If the user watched "/path/link" then emit events as "/path/link"
+		// rather than "/path/target".
+		e.Name = linkName
+	}
+
 	if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
 		e.Op |= Remove
 	}
@@ -582,21 +589,30 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
 		e.Op |= Chmod
 	}
+	// No point sending a write and delete event at the same time: if it's gone,
+	// then it's gone.
+	if e.Op.Has(Write) && e.Op.Has(Remove) {
+		e.Op &^= Write
+	}
 	return e
 }
 
 // watchDirectoryFiles to mimic inotify when adding a watch on a directory
-func (w *Watcher) watchDirectoryFiles(dirPath string) error {
-	// Get all files
-	files, err := ioutil.ReadDir(dirPath)
+func (w *kqueue) watchDirectoryFiles(dirPath string) error {
+	files, err := os.ReadDir(dirPath)
 	if err != nil {
 		return err
 	}
 
-	for _, fileInfo := range files {
-		path := filepath.Join(dirPath, fileInfo.Name())
+	for _, f := range files {
+		path := filepath.Join(dirPath, f.Name())
 
-		cleanPath, err := w.internalWatch(path, fileInfo)
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("%q: %w", path, err)
+		}
+
+		cleanPath, err := w.internalWatch(path, fi)
 		if err != nil {
 			// No permission to read the file; that's not a problem: just skip.
 			// But do add it to w.fileExists to prevent it from being picked up
@@ -606,13 +622,11 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 			case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM):
 				cleanPath = filepath.Clean(path)
 			default:
-				return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err)
+				return fmt.Errorf("%q: %w", path, err)
 			}
 		}
 
-		w.mu.Lock()
-		w.fileExists[cleanPath] = struct{}{}
-		w.mu.Unlock()
+		w.watches.markSeen(cleanPath, true)
 	}
 
 	return nil
@@ -622,58 +636,59 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 //
 // This functionality is to have the BSD watcher match the inotify, which sends
 // a create event for files created in a watched directory.
-func (w *Watcher) sendDirectoryChangeEvents(dir string) {
-	// Get all files
-	files, err := ioutil.ReadDir(dir)
+func (w *kqueue) dirChange(dir string) error {
+	files, err := os.ReadDir(dir)
 	if err != nil {
-		if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) {
-			return
+		// Directory no longer exists: we can ignore this safely. kqueue will
+		// still give us the correct events.
+		if errors.Is(err, os.ErrNotExist) {
+			return nil
 		}
+		return fmt.Errorf("fsnotify.dirChange: %w", err)
 	}
 
-	// Search for new files
-	for _, fi := range files {
-		err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi)
+	for _, f := range files {
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
+		}
+
+		err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
 		if err != nil {
-			return
+			// Don't need to send an error if this file isn't readable.
+			if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) {
+				return nil
+			}
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
 		}
 	}
+	return nil
 }
 
-// sendFileCreatedEvent sends a create event if the file isn't already being tracked.
-func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) {
-	w.mu.Lock()
-	_, doesExist := w.fileExists[filePath]
-	w.mu.Unlock()
-	if !doesExist {
-		if !w.sendEvent(Event{Name: filePath, Op: Create}) {
-			return
+// Send a create event if the file isn't already being tracked, and start
+// watching this file.
+func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error {
+	if !w.watches.seenBefore(path) {
+		if !w.sendEvent(Event{Name: path, Op: Create}) {
+			return nil
 		}
 	}
 
-	// like watchDirectoryFiles (but without doing another ReadDir)
-	filePath, err = w.internalWatch(filePath, fileInfo)
+	// Like watchDirectoryFiles, but without doing another ReadDir.
+	path, err := w.internalWatch(path, fi)
 	if err != nil {
 		return err
 	}
-
-	w.mu.Lock()
-	w.fileExists[filePath] = struct{}{}
-	w.mu.Unlock()
-
+	w.watches.markSeen(path, true)
 	return nil
 }
 
-func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) {
-	if fileInfo.IsDir() {
-		// mimic Linux providing delete events for subdirectories
-		// but preserve the flags used if currently watching subdirectory
-		w.mu.Lock()
-		flags := w.dirFlags[name]
-		w.mu.Unlock()
-
-		flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
-		return w.addWatch(name, flags)
+func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) {
+	if fi.IsDir() {
+		// mimic Linux providing delete events for subdirectories, but preserve
+		// the flags used if currently watching subdirectory
+		info, _ := w.watches.byPath(name)
+		return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME)
 	}
 
 	// watch file to mimic Linux inotify
@@ -681,7 +696,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro
 }
 
 // Register events with the queue.
-func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
+func (w *kqueue) register(fds []int, flags int, fflags uint32) error {
 	changes := make([]unix.Kevent_t, len(fds))
 	for i, fd := range fds {
 		// SetKevent converts int to the platform-specific types.
@@ -698,10 +713,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
 }
 
 // read retrieves pending events, or waits until an event occurs.
-func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
+func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
 	n, err := unix.Kevent(w.kq, nil, events, nil)
 	if err != nil {
 		return nil, err
 	}
 	return events[0:n], nil
 }
+
+func (w *kqueue) xSupports(op Op) bool {
+	if runtime.GOOS == "freebsd" {
+		//return true // Supports everything.
+	}
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/backend_other.go b/notifier/vendor/github.com/fsnotify/fsnotify/backend_other.go
index a9bb1c3c..5eb5dbc6 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/backend_other.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/backend_other.go
@@ -1,66 +1,23 @@
-//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows
-// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
+//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
 
 package fsnotify
 
-import (
-	"fmt"
-	"runtime"
-)
+import "errors"
 
-// Watcher watches a set of files, delivering events to a channel.
-type Watcher struct{}
-
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	return nil
+type other struct {
+	Events chan Event
+	Errors chan error
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	return nil
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return nil, errors.New("fsnotify not supported on the current platform")
 }
-
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	return nil
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	return newBackend(ev, errs)
 }
+func (w *other) Close() error                              { return nil }
+func (w *other) WatchList() []string                       { return nil }
+func (w *other) Add(name string) error                     { return nil }
+func (w *other) AddWith(name string, opts ...addOpt) error { return nil }
+func (w *other) Remove(name string) error                  { return nil }
+func (w *other) xSupports(op Op) bool                      { return false }
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/notifier/vendor/github.com/fsnotify/fsnotify/backend_windows.go
index ae392867..c54a6308 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/backend_windows.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/backend_windows.go
@@ -1,5 +1,8 @@
 //go:build windows
-// +build windows
+
+// Windows backend based on ReadDirectoryChangesW()
+//
+// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
 
 package fsnotify
 
@@ -12,143 +15,60 @@ import (
 	"runtime"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/windows"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type readDirChangesW struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	port  windows.Handle // Handle to completion port
 	input chan *input    // Inputs to the reader are sent on this channel
 	quit  chan chan<- error
 
-	mu       sync.Mutex // Protects access to watches, isClosed
-	watches  watchMap   // Map of watches (key: i-number)
-	isClosed bool       // Set to true when Close() is first called
+	mu      sync.Mutex // Protects access to watches, closed
+	watches watchMap   // Map of watches (key: i-number)
+	closed  bool       // Set to true when Close() is first called
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(50, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
 	if err != nil {
 		return nil, os.NewSyscallError("CreateIoCompletionPort", err)
 	}
-	w := &Watcher{
+	w := &readDirChangesW{
+		Events:  ev,
+		Errors:  errs,
 		port:    port,
 		watches: make(watchMap),
 		input:   make(chan *input, 1),
-		Events:  make(chan Event, 50),
-		Errors:  make(chan error),
 		quit:    make(chan chan<- error, 1),
 	}
 	go w.readEvents()
 	return w, nil
 }
 
-func (w *Watcher) sendEvent(name string, mask uint64) bool {
+func (w *readDirChangesW) isClosed() bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	return w.closed
+}
+
+func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
 	if mask == 0 {
 		return false
 	}
 
 	event := w.newEvent(name, uint32(mask))
+	event.renamedFrom = renamedFrom
 	select {
 	case ch := <-w.quit:
 		w.quit <- ch
@@ -158,23 +78,25 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *readDirChangesW) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
 	case w.Errors <- err:
 		return true
 	case <-w.quit:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *readDirChangesW) Close() error {
+	if w.isClosed() {
 		return nil
 	}
-	w.isClosed = true
+
+	w.mu.Lock()
+	w.closed = true
 	w.mu.Unlock()
 
 	// Send "quit" message to the reader goroutine
@@ -186,49 +108,31 @@ func (w *Watcher) Close() error {
 	return <-ch
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return errors.New("watcher already closed")
+func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
+
+func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+	if with.bufsize < 4096 {
+		return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
 	}
-	w.mu.Unlock()
 
 	in := &input{
-		op:    opAddWatch,
-		path:  filepath.Clean(name),
-		flags: sysFSALLEVENTS,
-		reply: make(chan error),
+		op:      opAddWatch,
+		path:    filepath.Clean(name),
+		flags:   sysFSALLEVENTS,
+		reply:   make(chan error),
+		bufsize: with.bufsize,
 	}
 	w.input <- in
 	if err := w.wakeupReader(); err != nil {
@@ -237,13 +141,15 @@ func (w *Watcher) Add(name string) error {
 	return <-in.reply
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *readDirChangesW) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
 	in := &input{
 		op:    opRemoveWatch,
 		path:  filepath.Clean(name),
@@ -256,15 +162,24 @@ func (w *Watcher) Remove(name string) error {
 	return <-in.reply
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
+func (w *readDirChangesW) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
 	w.mu.Lock()
 	defer w.mu.Unlock()
 
 	entries := make([]string, 0, len(w.watches))
 	for _, entry := range w.watches {
 		for _, watchEntry := range entry {
-			entries = append(entries, watchEntry.path)
+			for name := range watchEntry.names {
+				entries = append(entries, filepath.Join(watchEntry.path, name))
+			}
+			// the directory itself is being watched
+			if watchEntry.mask != 0 {
+				entries = append(entries, watchEntry.path)
+			}
 		}
 	}
 
@@ -279,7 +194,6 @@ func (w *Watcher) WatchList() []string {
 // This should all be removed at some point, and just use windows.FILE_NOTIFY_*
 const (
 	sysFSALLEVENTS  = 0xfff
-	sysFSATTRIB     = 0x4
 	sysFSCREATE     = 0x100
 	sysFSDELETE     = 0x200
 	sysFSDELETESELF = 0x400
@@ -291,7 +205,7 @@ const (
 	sysFSIGNORED    = 0x8000
 )
 
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
 	e := Event{Name: name}
 	if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
 		e.Op |= Create
@@ -305,9 +219,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
 		e.Op |= Rename
 	}
-	if mask&sysFSATTRIB == sysFSATTRIB {
-		e.Op |= Chmod
-	}
 	return e
 }
 
@@ -321,10 +232,11 @@ const (
 )
 
 type input struct {
-	op    int
-	path  string
-	flags uint32
-	reply chan error
+	op      int
+	path    string
+	flags   uint32
+	bufsize int
+	reply   chan error
 }
 
 type inode struct {
@@ -334,13 +246,14 @@ type inode struct {
 }
 
 type watch struct {
-	ov     windows.Overlapped
-	ino    *inode            // i-number
-	path   string            // Directory path
-	mask   uint64            // Directory itself is being watched with these notify flags
-	names  map[string]uint64 // Map of names being watched and their notify flags
-	rename string            // Remembers the old name while renaming a file
-	buf    [65536]byte       // 64K buffer
+	ov      windows.Overlapped
+	ino     *inode            // i-number
+	recurse bool              // Recursive watch?
+	path    string            // Directory path
+	mask    uint64            // Directory itself is being watched with these notify flags
+	names   map[string]uint64 // Map of names being watched and their notify flags
+	rename  string            // Remembers the old name while renaming a file
+	buf     []byte            // buffer, allocated later
 }
 
 type (
@@ -348,7 +261,7 @@ type (
 	watchMap map[uint32]indexMap
 )
 
-func (w *Watcher) wakeupReader() error {
+func (w *readDirChangesW) wakeupReader() error {
 	err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
 	if err != nil {
 		return os.NewSyscallError("PostQueuedCompletionStatus", err)
@@ -356,7 +269,7 @@ func (w *Watcher) wakeupReader() error {
 	return nil
 }
 
-func (w *Watcher) getDir(pathname string) (dir string, err error) {
+func (w *readDirChangesW) getDir(pathname string) (dir string, err error) {
 	attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
 	if err != nil {
 		return "", os.NewSyscallError("GetFileAttributes", err)
@@ -370,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
 	return
 }
 
-func (w *Watcher) getIno(path string) (ino *inode, err error) {
+func (w *readDirChangesW) getIno(path string) (ino *inode, err error) {
 	h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
 		windows.FILE_LIST_DIRECTORY,
 		windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
@@ -413,7 +326,9 @@ func (m watchMap) set(ino *inode, watch *watch) {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) addWatch(pathname string, flags uint64) error {
+func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -433,9 +348,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 			return os.NewSyscallError("CreateIoCompletionPort", err)
 		}
 		watchEntry = &watch{
-			ino:   ino,
-			path:  dir,
-			names: make(map[string]uint64),
+			ino:     ino,
+			path:    dir,
+			names:   make(map[string]uint64),
+			recurse: recurse,
+			buf:     make([]byte, bufsize),
 		}
 		w.mu.Lock()
 		w.watches.set(ino, watchEntry)
@@ -464,7 +381,9 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) remWatch(pathname string) error {
+func (w *readDirChangesW) remWatch(pathname string) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -478,6 +397,10 @@ func (w *Watcher) remWatch(pathname string) error {
 	watch := w.watches.get(ino)
 	w.mu.Unlock()
 
+	if recurse && !watch.recurse {
+		return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname)
+	}
+
 	err = windows.CloseHandle(ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CloseHandle", err))
@@ -486,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
 	}
 	if pathname == dir {
-		w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+		w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		watch.mask = 0
 	} else {
 		name := filepath.Base(pathname)
-		w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
+		w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED)
 		delete(watch.names, name)
 	}
 
@@ -498,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) deleteWatch(watch *watch) {
+func (w *readDirChangesW) deleteWatch(watch *watch) {
 	for name, mask := range watch.names {
 		if mask&provisional == 0 {
-			w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
+			w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED)
 		}
 		delete(watch.names, name)
 	}
 	if watch.mask != 0 {
 		if watch.mask&provisional == 0 {
-			w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+			w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		}
 		watch.mask = 0
 	}
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) startRead(watch *watch) error {
+func (w *readDirChangesW) startRead(watch *watch) error {
 	err := windows.CancelIo(watch.ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CancelIo", err))
@@ -535,13 +458,16 @@ func (w *Watcher) startRead(watch *watch) error {
 		return nil
 	}
 
-	rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
-		uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+	// We need to pass the array, rather than the slice.
+	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf))
+	rdErr := windows.ReadDirectoryChanges(watch.ino.handle,
+		(*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len),
+		watch.recurse, mask, nil, &watch.ov, 0)
 	if rdErr != nil {
 		err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
 		if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			err = nil
 		}
 		w.deleteWatch(watch)
@@ -554,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error {
 // readEvents reads from the I/O completion port, converts the
 // received events into Event objects and sends them via the Events channel.
 // Entry point to the I/O thread.
-func (w *Watcher) readEvents() {
+func (w *readDirChangesW) readEvents() {
 	var (
 		n   uint32
 		key uintptr
@@ -563,9 +489,8 @@ func (w *Watcher) readEvents() {
 	runtime.LockOSThread()
 
 	for {
+		// This error is handled after the watch == nil check below.
 		qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE)
-		// This error is handled after the watch == nil check below. NOTE: this
-		// seems odd, note sure if it's correct.
 
 		watch := (*watch)(unsafe.Pointer(ov))
 		if watch == nil {
@@ -595,7 +520,7 @@ func (w *Watcher) readEvents() {
 			case in := <-w.input:
 				switch in.op {
 				case opAddWatch:
-					in.reply <- w.addWatch(in.path, uint64(in.flags))
+					in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize)
 				case opRemoveWatch:
 					in.reply <- w.remWatch(in.path)
 				}
@@ -605,6 +530,8 @@ func (w *Watcher) readEvents() {
 		}
 
 		switch qErr {
+		case nil:
+			// No error
 		case windows.ERROR_MORE_DATA:
 			if watch == nil {
 				w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer"))
@@ -616,7 +543,7 @@ func (w *Watcher) readEvents() {
 			}
 		case windows.ERROR_ACCESS_DENIED:
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			w.deleteWatch(watch)
 			w.startRead(watch)
 			continue
@@ -626,13 +553,12 @@ func (w *Watcher) readEvents() {
 		default:
 			w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr))
 			continue
-		case nil:
 		}
 
 		var offset uint32
 		for {
 			if n == 0 {
-				w.sendError(errors.New("short read in readEvents()"))
+				w.sendError(ErrEventOverflow)
 				break
 			}
 
@@ -650,6 +576,10 @@ func (w *Watcher) readEvents() {
 			name := windows.UTF16ToString(buf)
 			fullname := filepath.Join(watch.path, name)
 
+			if debug {
+				internal.Debug(fullname, raw.Action)
+			}
+
 			var mask uint64
 			switch raw.Action {
 			case windows.FILE_ACTION_REMOVED:
@@ -678,21 +608,22 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			sendNameEvent := func() {
-				w.sendEvent(fullname, watch.names[name]&mask)
-			}
 			if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
-				sendNameEvent()
+				w.sendEvent(fullname, "", watch.names[name]&mask)
 			}
 			if raw.Action == windows.FILE_ACTION_REMOVED {
-				w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
+				w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED)
 				delete(watch.names, name)
 			}
 
-			w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action))
+			if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
+				w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action))
+			} else {
+				w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action))
+			}
+
 			if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
-				fullname = filepath.Join(watch.path, watch.rename)
-				sendNameEvent()
+				w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
 			}
 
 			// Move to the next event in the buffer
@@ -703,8 +634,8 @@ func (w *Watcher) readEvents() {
 
 			// Error!
 			if offset >= n {
-				w.sendError(errors.New(
-					"Windows system assumed buffer larger than it is, events have likely been missed."))
+				//lint:ignore ST1005 Windows should be capitalized
+				w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed"))
 				break
 			}
 		}
@@ -715,21 +646,18 @@ func (w *Watcher) readEvents() {
 	}
 }
 
-func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
+func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
 	var m uint32
 	if mask&sysFSMODIFY != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
 	}
-	if mask&sysFSATTRIB != 0 {
-		m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES
-	}
 	if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
 	}
 	return m
 }
 
-func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
+func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
 	switch action {
 	case windows.FILE_ACTION_ADDED:
 		return sysFSCREATE
@@ -744,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
 	}
 	return 0
 }
+
+func (w *readDirChangesW) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/notifier/vendor/github.com/fsnotify/fsnotify/fsnotify.go
index 30a5bf0f..0760efe9 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/fsnotify.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/fsnotify.go
@@ -1,16 +1,148 @@
-//go:build !plan9
-// +build !plan9
-
 // Package fsnotify provides a cross-platform interface for file system
 // notifications.
+//
+// Currently supported systems:
+//
+//   - Linux      via inotify
+//   - BSD, macOS via kqueue
+//   - Windows    via ReadDirectoryChangesW
+//   - illumos    via FEN
+//
+// # FSNOTIFY_DEBUG
+//
+// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to
+// stderr. This can be useful to track down some problems, especially in cases
+// where fsnotify is used as an indirect dependency.
+//
+// Every event will be printed as soon as there's something useful to print,
+// with as little processing from fsnotify.
+//
+// Example output:
+//
+//	FSNOTIFY_DEBUG: 11:34:23.633087586   256:IN_CREATE            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:23.633202319     4:IN_ATTRIB            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:28.989728764   512:IN_DELETE            → "/tmp/file-1"
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
+	"os"
+	"path/filepath"
 	"strings"
 )
 
+// Watcher watches a set of paths, delivering events on a channel.
+//
+// A watcher should not be copied (e.g. pass it by pointer, rather than by
+// value).
+//
+// # Linux notes
+//
+// When a file is removed a Remove event won't be emitted until all file
+// descriptors are closed, and deletes will always emit a Chmod. For example:
+//
+//	fp := os.Open("file")
+//	os.Remove("file")        // Triggers Chmod
+//	fp.Close()               // Triggers Remove
+//
+// This is the event that inotify sends, so not much can be changed about this.
+//
+// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
+// for the number of watches per user, and fs.inotify.max_user_instances
+// specifies the maximum number of inotify instances per user. Every Watcher you
+// create is an "instance", and every path you add is a "watch".
+//
+// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
+// /proc/sys/fs/inotify/max_user_instances
+//
+// To increase them you can use sysctl or write the value to the /proc file:
+//
+//	# Default values on Linux 5.18
+//	sysctl fs.inotify.max_user_watches=124983
+//	sysctl fs.inotify.max_user_instances=128
+//
+// To make the changes persist on reboot edit /etc/sysctl.conf or
+// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
+// your distro's documentation):
+//
+//	fs.inotify.max_user_watches=124983
+//	fs.inotify.max_user_instances=128
+//
+// Reaching the limit will result in a "no space left on device" or "too many open
+// files" error.
+//
+// # kqueue notes (macOS, BSD)
+//
+// kqueue requires opening a file descriptor for every file that's being watched;
+// so if you're watching a directory with five files then that's six file
+// descriptors. You will run in to your system's "max open files" limit faster on
+// these platforms.
+//
+// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
+// control the maximum number of open files, as well as /etc/login.conf on BSD
+// systems.
+//
+// # Windows notes
+//
+// Paths can be added as "C:\\path\\to\\dir", but forward slashes
+// ("C:/path/to/dir") will also work.
+//
+// When a watched directory is removed it will always send an event for the
+// directory itself, but may not send events for all files in that directory.
+// Sometimes it will send events for all files, sometimes it will send no
+// events, and often only for some files.
+//
+// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest
+// value that is guaranteed to work with SMB filesystems. If you have many
+// events in quick succession this may not be enough, and you will have to use
+// [WithBufferSize] to increase the value.
+type Watcher struct {
+	b backend
+
+	// Events sends the filesystem change events.
+	//
+	// fsnotify can send the following events; a "path" here can refer to a
+	// file, directory, symbolic link, or special file like a FIFO.
+	//
+	//   fsnotify.Create    A new path was created; this may be followed by one
+	//                      or more Write events if data also gets written to a
+	//                      file.
+	//
+	//   fsnotify.Remove    A path was removed.
+	//
+	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
+	//                      old path as Event.Name, and a Create event will be
+	//                      sent with the new name. Renames are only sent for
+	//                      paths that are currently watched; e.g. moving an
+	//                      unmonitored file into a monitored directory will
+	//                      show up as just a Create. Similarly, renaming a file
+	//                      to outside a monitored directory will show up as
+	//                      only a Rename.
+	//
+	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
+	//                      also trigger a Write. A single "write action"
+	//                      initiated by the user may show up as one or multiple
+	//                      writes, depending on when the system syncs things to
+	//                      disk. For example when compiling a large Go program
+	//                      you may get hundreds of Write events, and you may
+	//                      want to wait until you've stopped receiving them
+	//                      (see the dedup example in cmd/fsnotify).
+	//
+	//                      Some systems may send Write event for directories
+	//                      when the directory content changes.
+	//
+	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
+	//                      when a file is removed (or more accurately, when a
+	//                      link to an inode is removed). On kqueue it's sent
+	//                      when a file is truncated. On Windows it's never
+	//                      sent.
+	Events chan Event
+
+	// Errors sends any errors.
+	Errors chan error
+}
+
 // Event represents a file system notification.
 type Event struct {
 	// Path to the file or directory.
@@ -25,6 +157,16 @@ type Event struct {
 	// This is a bitmask and some systems may send multiple operations at once.
 	// Use the Event.Has() method instead of comparing with ==.
 	Op Op
+
+	// Create events will have this set to the old path if it's a rename. This
+	// only works when both the source and destination are watched. It's not
+	// reliable when watching individual files, only directories.
+	//
+	// For example "mv /tmp/file /tmp/rename" will emit:
+	//
+	//   Event{Op: Rename, Name: "/tmp/file"}
+	//   Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"}
+	renamedFrom string
 }
 
 // Op describes a set of file operations.
@@ -33,34 +175,204 @@ type Op uint32
 // The operations fsnotify can trigger; see the documentation on [Watcher] for a
 // full description, and check them with [Event.Has].
 const (
+	// A new pathname was created.
 	Create Op = 1 << iota
+
+	// The pathname was written to; this does *not* mean the write has finished,
+	// and a write can be followed by more writes.
 	Write
+
+	// The path was removed; any watches on it will be removed. Some "remove"
+	// operations may trigger a Rename if the file is actually moved (for
+	// example "remove to trash" is often a rename).
 	Remove
+
+	// The path was renamed to something else; any watches on it will be
+	// removed.
 	Rename
+
+	// File attributes were changed.
+	//
+	// It's generally not recommended to take action on this event, as it may
+	// get triggered very frequently by some software. For example, Spotlight
+	// indexing on macOS, anti-virus software, backup software, etc.
 	Chmod
+
+	// File descriptor was opened.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableOpen
+
+	// File was read from.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableRead
+
+	// File opened for writing was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	//
+	// The advantage of using this over Write is that it's more reliable than
+	// waiting for Write events to stop. It's also faster (if you're not
+	// listening to Write events): copying a file of a few GB can easily
+	// generate tens of thousands of Write events in a short span of time.
+	xUnportableCloseWrite
+
+	// File opened for reading was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableCloseRead
 )
 
-// Common errors that can be reported by a watcher
 var (
-	ErrNonExistentWatch = errors.New("can't remove non-existent watcher")
-	ErrEventOverflow    = errors.New("fsnotify queue overflow")
+	// ErrNonExistentWatch is used when Remove() is called on a path that's not
+	// added.
+	ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
+
+	// ErrClosed is used when trying to operate on a closed Watcher.
+	ErrClosed = errors.New("fsnotify: watcher already closed")
+
+	// ErrEventOverflow is reported from the Errors channel when there are too
+	// many events:
+	//
+	//  - inotify:      inotify returns IN_Q_OVERFLOW – because there are too
+	//                  many queued events (the fs.inotify.max_queued_events
+	//                  sysctl can be used to increase this).
+	//  - windows:      The buffer size is too small; WithBufferSize() can be used to increase it.
+	//  - kqueue, fen:  Not used.
+	ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
+
+	// ErrUnsupported is returned by AddWith() when WithOps() specified an
+	// Unportable event that's not supported on this platform.
+	xErrUnsupported = errors.New("fsnotify: not supported with this backend")
 )
 
-func (op Op) String() string {
+// NewWatcher creates a new Watcher.
+func NewWatcher() (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBackend(ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
+// channel.
+//
+// The main use case for this is situations with a very large number of events
+// where the kernel buffer size can't be increased (e.g. due to lack of
+// permissions). An unbuffered Watcher will perform better for almost all use
+// cases, and whenever possible you will be better off increasing the kernel
+// buffers instead of adding a large userspace buffer.
+func NewBufferedWatcher(sz uint) (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBufferedBackend(sz, ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// Add starts monitoring the path for changes.
+//
+// A path can only be watched once; watching it more than once is a no-op and will
+// not return an error. Paths that do not yet exist on the filesystem cannot be
+// watched.
+//
+// A watch will be automatically removed if the watched path is deleted or
+// renamed. The exception is the Windows backend, which doesn't remove the
+// watcher on renames.
+//
+// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
+// filesystems (/proc, /sys, etc.) generally don't work.
+//
+// Returns [ErrClosed] if [Watcher.Close] was called.
+//
+// See [Watcher.AddWith] for a version that allows adding options.
+//
+// # Watching directories
+//
+// All files in a directory are monitored, including new files that are created
+// after the watcher is started. Subdirectories are not watched (i.e. it's
+// non-recursive).
+//
+// # Watching files
+//
+// Watching individual files (rather than directories) is generally not
+// recommended as many programs (especially editors) update files atomically: it
+// will write to a temporary file which is then moved to destination,
+// overwriting the original (or some variant thereof). The watcher on the
+// original file is now lost, as that no longer exists.
+//
+// The upshot of this is that a power failure or crash won't leave a
+// half-written file.
+//
+// Watch the parent directory and use Event.Name to filter out files you're not
+// interested in. There is an example of this in cmd/fsnotify/file.go.
+func (w *Watcher) Add(path string) error { return w.b.Add(path) }
+
+// AddWith is like [Watcher.Add], but allows adding options. When using Add()
+// the defaults described below are used.
+//
+// Possible options are:
+//
+//   - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
+//     other platforms. The default is 64K (65536 bytes).
+func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) }
+
+// Remove stops monitoring the path for changes.
+//
+// Directories are always removed non-recursively. For example, if you added
+// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
+//
+// Removing a path that has not yet been added returns [ErrNonExistentWatch].
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) Remove(path string) error { return w.b.Remove(path) }
+
+// Close removes all watches and closes the Events channel.
+func (w *Watcher) Close() error { return w.b.Close() }
+
+// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
+// yet removed).
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) WatchList() []string { return w.b.WatchList() }
+
+// Supports reports if all the listed operations are supported by this platform.
+//
+// Create, Write, Remove, Rename, and Chmod are always supported. It can only
+// return false for an Op starting with Unportable.
+func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) }
+
+func (o Op) String() string {
 	var b strings.Builder
-	if op.Has(Create) {
+	if o.Has(Create) {
 		b.WriteString("|CREATE")
 	}
-	if op.Has(Remove) {
+	if o.Has(Remove) {
 		b.WriteString("|REMOVE")
 	}
-	if op.Has(Write) {
+	if o.Has(Write) {
 		b.WriteString("|WRITE")
 	}
-	if op.Has(Rename) {
+	if o.Has(xUnportableOpen) {
+		b.WriteString("|OPEN")
+	}
+	if o.Has(xUnportableRead) {
+		b.WriteString("|READ")
+	}
+	if o.Has(xUnportableCloseWrite) {
+		b.WriteString("|CLOSE_WRITE")
+	}
+	if o.Has(xUnportableCloseRead) {
+		b.WriteString("|CLOSE_READ")
+	}
+	if o.Has(Rename) {
 		b.WriteString("|RENAME")
 	}
-	if op.Has(Chmod) {
+	if o.Has(Chmod) {
 		b.WriteString("|CHMOD")
 	}
 	if b.Len() == 0 {
@@ -70,12 +382,113 @@ func (op Op) String() string {
 }
 
 // Has reports if this operation has the given operation.
-func (o Op) Has(h Op) bool { return o&h == h }
+func (o Op) Has(h Op) bool { return o&h != 0 }
 
 // Has reports if this event has the given operation.
 func (e Event) Has(op Op) bool { return e.Op.Has(op) }
 
 // String returns a string representation of the event with their path.
 func (e Event) String() string {
+	if e.renamedFrom != "" {
+		return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom)
+	}
 	return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
 }
+
+type (
+	backend interface {
+		Add(string) error
+		AddWith(string, ...addOpt) error
+		Remove(string) error
+		WatchList() []string
+		Close() error
+		xSupports(Op) bool
+	}
+	addOpt   func(opt *withOpts)
+	withOpts struct {
+		bufsize    int
+		op         Op
+		noFollow   bool
+		sendCreate bool
+	}
+)
+
+var debug = func() bool {
+	// Check for exactly "1" (rather than mere existence) so we can add
+	// options/flags in the future. I don't know if we ever want that, but it's
+	// nice to leave the option open.
+	return os.Getenv("FSNOTIFY_DEBUG") == "1"
+}()
+
+var defaultOpts = withOpts{
+	bufsize: 65536, // 64K
+	op:      Create | Write | Remove | Rename | Chmod,
+}
+
+func getOptions(opts ...addOpt) withOpts {
+	with := defaultOpts
+	for _, o := range opts {
+		if o != nil {
+			o(&with)
+		}
+	}
+	return with
+}
+
+// WithBufferSize sets the [ReadDirectoryChangesW] buffer size.
+//
+// This only has effect on Windows systems, and is a no-op for other backends.
+//
+// The default value is 64K (65536 bytes) which is the highest value that works
+// on all filesystems and should be enough for most applications, but if you
+// have a large burst of events it may not be enough. You can increase it if
+// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]).
+//
+// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
+func WithBufferSize(bytes int) addOpt {
+	return func(opt *withOpts) { opt.bufsize = bytes }
+}
+
+// WithOps sets which operations to listen for. The default is [Create],
+// [Write], [Remove], [Rename], and [Chmod].
+//
+// Excluding operations you're not interested in can save quite a bit of CPU
+// time; in some use cases there may be hundreds of thousands of useless Write
+// or Chmod operations per second.
+//
+// This can also be used to add unportable operations not supported by all
+// platforms; unportable operations all start with "Unportable":
+// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and
+// [UnportableCloseRead].
+//
+// AddWith returns an error when using an unportable operation that's not
+// supported. Use [Watcher.Support] to check for support.
+func withOps(op Op) addOpt {
+	return func(opt *withOpts) { opt.op = op }
+}
+
+// WithNoFollow disables following symlinks, so the symlinks themselves are
+// watched.
+func withNoFollow() addOpt {
+	return func(opt *withOpts) { opt.noFollow = true }
+}
+
+// "Internal" option for recursive watches on inotify.
+func withCreate() addOpt {
+	return func(opt *withOpts) { opt.sendCreate = true }
+}
+
+var enableRecurse = false
+
+// Check if this path is recursive (ends with "/..." or "\..."), and return the
+// path with the /... stripped.
+func recursivePath(path string) (string, bool) {
+	path = filepath.Clean(path)
+	if !enableRecurse { // Only enabled in tests for now.
+		return path, false
+	}
+	if filepath.Base(path) == "..." {
+		return filepath.Dir(path), true
+	}
+	return path, false
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
new file mode 100644
index 00000000..b0eab100
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
@@ -0,0 +1,39 @@
+//go:build darwin
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+func SetRlimit() {
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = l.Cur
+
+	if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+
+	if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
new file mode 100644
index 00000000..928319fb
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
@@ -0,0 +1,57 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_BACKGROUND", unix.NOTE_BACKGROUND},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CRITICAL", unix.NOTE_CRITICAL},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS},
+	{"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR},
+	{"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL},
+	{"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL},
+	{"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK},
+	{"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY},
+	{"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_FUNLOCK", unix.NOTE_FUNLOCK},
+	{"NOTE_LEEWAY", unix.NOTE_LEEWAY},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MACHTIME", unix.NOTE_MACHTIME},
+	{"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME},
+	{"NOTE_NONE", unix.NOTE_NONE},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	//{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!)
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_REAP", unix.NOTE_REAP},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_SIGNAL", unix.NOTE_SIGNAL},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_VM_ERROR", unix.NOTE_VM_ERROR},
+	{"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE},
+	{"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE},
+	{"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
new file mode 100644
index 00000000..3186b0c3
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
@@ -0,0 +1,33 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
new file mode 100644
index 00000000..f69fdb93
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
@@ -0,0 +1,42 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSTIME", unix.NOTE_ABSTIME},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CLOSE", unix.NOTE_CLOSE},
+	{"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FILE_POLL", unix.NOTE_FILE_POLL},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MSECONDS", unix.NOTE_MSECONDS},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OPEN", unix.NOTE_OPEN},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_READ", unix.NOTE_READ},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
new file mode 100644
index 00000000..607e683b
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
@@ -0,0 +1,32 @@
+//go:build freebsd || openbsd || netbsd || dragonfly || darwin
+
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, kevent *unix.Kevent_t) {
+	mask := uint32(kevent.Fflags)
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-60s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
new file mode 100644
index 00000000..35c734be
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
@@ -0,0 +1,56 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask, cookie uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"IN_ACCESS", unix.IN_ACCESS},
+		{"IN_ATTRIB", unix.IN_ATTRIB},
+		{"IN_CLOSE", unix.IN_CLOSE},
+		{"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE},
+		{"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE},
+		{"IN_CREATE", unix.IN_CREATE},
+		{"IN_DELETE", unix.IN_DELETE},
+		{"IN_DELETE_SELF", unix.IN_DELETE_SELF},
+		{"IN_IGNORED", unix.IN_IGNORED},
+		{"IN_ISDIR", unix.IN_ISDIR},
+		{"IN_MODIFY", unix.IN_MODIFY},
+		{"IN_MOVE", unix.IN_MOVE},
+		{"IN_MOVED_FROM", unix.IN_MOVED_FROM},
+		{"IN_MOVED_TO", unix.IN_MOVED_TO},
+		{"IN_MOVE_SELF", unix.IN_MOVE_SELF},
+		{"IN_OPEN", unix.IN_OPEN},
+		{"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW},
+		{"IN_UNMOUNT", unix.IN_UNMOUNT},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	var c string
+	if cookie > 0 {
+		c = fmt.Sprintf("(cookie: %d) ", cookie)
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-30s → %s%q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name)
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
new file mode 100644
index 00000000..e5b3b6f6
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
@@ -0,0 +1,25 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
new file mode 100644
index 00000000..1dd455bc
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
@@ -0,0 +1,28 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	// {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386?
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EOF", unix.NOTE_EOF},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRUNCATE", unix.NOTE_TRUNCATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
new file mode 100644
index 00000000..f1b2e73b
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask int32) {
+	names := []struct {
+		n string
+		m int32
+	}{
+		{"FILE_ACCESS", unix.FILE_ACCESS},
+		{"FILE_MODIFIED", unix.FILE_MODIFIED},
+		{"FILE_ATTRIB", unix.FILE_ATTRIB},
+		{"FILE_TRUNC", unix.FILE_TRUNC},
+		{"FILE_NOFOLLOW", unix.FILE_NOFOLLOW},
+		{"FILE_DELETE", unix.FILE_DELETE},
+		{"FILE_RENAME_TO", unix.FILE_RENAME_TO},
+		{"FILE_RENAME_FROM", unix.FILE_RENAME_FROM},
+		{"UNMOUNTED", unix.UNMOUNTED},
+		{"MOUNTEDOVER", unix.MOUNTEDOVER},
+		{"FILE_EXCEPTION", unix.FILE_EXCEPTION},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-30s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
new file mode 100644
index 00000000..52bf4ce5
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
@@ -0,0 +1,40 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/windows"
+)
+
+func Debug(name string, mask uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED},
+		{"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED},
+		{"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED},
+		{"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME},
+		{"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-65s → %q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name))
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
new file mode 100644
index 00000000..547df1df
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
@@ -0,0 +1,31 @@
+//go:build freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) }
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/internal.go
new file mode 100644
index 00000000..7daa45e1
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/internal.go
@@ -0,0 +1,2 @@
+// Package internal contains some helpers.
+package internal
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix.go
new file mode 100644
index 00000000..30976ce9
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix.go
@@ -0,0 +1,31 @@
+//go:build !windows && !darwin && !freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
new file mode 100644
index 00000000..37dfeddc
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
@@ -0,0 +1,7 @@
+//go:build !windows
+
+package internal
+
+func HasPrivilegesForSymlink() bool {
+	return true
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/notifier/vendor/github.com/fsnotify/fsnotify/internal/windows.go
new file mode 100644
index 00000000..a72c6495
--- /dev/null
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/internal/windows.go
@@ -0,0 +1,41 @@
+//go:build windows
+
+package internal
+
+import (
+	"errors"
+
+	"golang.org/x/sys/windows"
+)
+
+// Just a dummy.
+var (
+	SyscallEACCES = errors.New("dummy")
+	UnixEACCES    = errors.New("dummy")
+)
+
+func SetRlimit()                                    {}
+func Maxfiles() uint64                              { return 1<<64 - 1 }
+func Mkfifo(path string, mode uint32) error         { return errors.New("no FIFOs on Windows") }
+func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") }
+
+func HasPrivilegesForSymlink() bool {
+	var sid *windows.SID
+	err := windows.AllocateAndInitializeSid(
+		&windows.SECURITY_NT_AUTHORITY,
+		2,
+		windows.SECURITY_BUILTIN_DOMAIN_RID,
+		windows.DOMAIN_ALIAS_RID_ADMINS,
+		0, 0, 0, 0, 0, 0,
+		&sid)
+	if err != nil {
+		return false
+	}
+	defer windows.FreeSid(sid)
+	token := windows.Token(0)
+	member, err := token.IsMember(sid)
+	if err != nil {
+		return false
+	}
+	return member || token.IsElevated()
+}
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/notifier/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
deleted file mode 100644
index b09ef768..00000000
--- a/notifier/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env zsh
-[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1
-setopt err_exit no_unset pipefail extended_glob
-
-# Simple script to update the godoc comments on all watchers. Probably took me
-# more time to write this than doing it manually, but ah well 🙃
-
-watcher=$(</tmp/x
-		print -r -- $cmt                >>/tmp/x
-		tail -n+$(( end + 1 ))   $file  >>/tmp/x
-		mv /tmp/x $file
-	done
-}
-
-set-cmt '^type Watcher struct '             $watcher
-set-cmt '^func NewWatcher('                 $new
-set-cmt '^func (w \*Watcher) Add('          $add
-set-cmt '^func (w \*Watcher) Remove('       $remove
-set-cmt '^func (w \*Watcher) Close('        $close
-set-cmt '^func (w \*Watcher) WatchList('    $watchlist
-set-cmt '^[[:space:]]*Events *chan Event$'  $events
-set-cmt '^[[:space:]]*Errors *chan error$'  $errors
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/notifier/vendor/github.com/fsnotify/fsnotify/system_bsd.go
index 4322b0b8..f65e8fe3 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/system_bsd.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/system_bsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd || openbsd || netbsd || dragonfly
-// +build freebsd openbsd netbsd dragonfly
 
 package fsnotify
 
diff --git a/notifier/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/notifier/vendor/github.com/fsnotify/fsnotify/system_darwin.go
index 5da5ffa7..a29fc7aa 100644
--- a/notifier/vendor/github.com/fsnotify/fsnotify/system_darwin.go
+++ b/notifier/vendor/github.com/fsnotify/fsnotify/system_darwin.go
@@ -1,5 +1,4 @@
 //go:build darwin
-// +build darwin
 
 package fsnotify
 
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/notifier/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
index 1f664d13..faef0c91 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
@@ -16,3 +16,6 @@ indent_style = tab
 
 [*.nix]
 indent_size = 2
+
+[.golangci.yaml]
+indent_size = 2
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/notifier/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
index 763143aa..bda96256 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
@@ -1,23 +1,48 @@
-run:
-  timeout: 5m
+version: "2"
 
-linters-settings:
-  gci:
-    sections:
-      - standard
-      - default
-      - prefix(github.com/go-viper/mapstructure)
-  golint:
-    min-confidence: 0
-  goimports:
-    local-prefixes: github.com/go-viper/maptstructure
+run:
+  timeout: 10m
 
 linters:
-  disable-all: true
+  enable:
+    - govet
+    - ineffassign
+    # - misspell
+    - nolintlint
+    # - revive
+
+  disable:
+    - errcheck
+    - staticcheck
+    - unused
+
+  settings:
+    misspell:
+      locale: US
+    nolintlint:
+      allow-unused: false # report any unused nolint directives
+      require-specific: false # don't require nolint directives to be specific about which linter is being skipped
+
+formatters:
   enable:
     - gci
     - gofmt
     - gofumpt
     - goimports
-    - staticcheck
-    # - stylecheck
+    # - golines
+
+  settings:
+    gci:
+      sections:
+        - standard
+        - default
+        - localmodule
+    gofmt:
+      simplify: true
+      rewrite-rules:
+        - pattern: interface{}
+          replacement: any
+
+  exclusions:
+    paths:
+      - internal/
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/README.md b/notifier/vendor/github.com/go-viper/mapstructure/v2/README.md
index dd5ec69d..45db7197 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/README.md
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/README.md
@@ -1,8 +1,9 @@
 # mapstructure
 
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
 [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square)
+![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)
 
 mapstructure is a Go library for decoding generic map values to structures
 and vice versa, while providing helpful error handling.
@@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else.
 Here is a script that can help you with the migration:
 
 ```shell
-sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go')
+sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go')
 ```
 
 If you need more time to migrate your code, that is absolutely fine.
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/notifier/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
index 1f3c69d4..a852a0a0 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
@@ -13,7 +13,7 @@ import (
 	"time"
 )
 
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
 func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	// Create variables here so we can reference them with the reflect pkg
@@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 
 	// Fill in the variables into this interface and the rest is done
 	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
+	potential := []any{f1, f2, f3}
 
 	v := reflect.ValueOf(h)
 	vt := v.Type()
@@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	return nil
 }
 
-// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into a closure to be used directly
 // if the type fails to convert we return a closure always erroring to keep the previous behaviour
-func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) {
+func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Type(), to.Type(), from.Interface())
 		}
 	case DecodeHookFuncKind:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Kind(), to.Kind(), from.Interface())
 		}
 	case DecodeHookFuncValue:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from, to)
 		}
 	default:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return nil, errors.New("invalid decode hook signature")
 		}
 	}
@@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
 func DecodeHookExec(
 	raw DecodeHookFunc,
 	from reflect.Value, to reflect.Value,
-) (interface{}, error) {
+) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
 		return f(from.Type(), to.Type(), from.Interface())
@@ -86,11 +86,11 @@ func DecodeHookExec(
 // The composed funcs are called in order, with the result of the
 // previous transformation.
 func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs))
 	for _, f := range fs {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		var err error
 		data := f.Interface()
 
@@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 			if err != nil {
 				return nil, err
 			}
-			newFrom = reflect.ValueOf(data)
+			if v, ok := data.(reflect.Value); ok {
+				newFrom = v
+			} else {
+				newFrom = reflect.ValueOf(data)
+			}
 		}
 
 		return data, nil
@@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
 // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
 func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff))
 	for _, f := range ff {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(a, b reflect.Value) (interface{}, error) {
+	return func(a, b reflect.Value) (any, error) {
 		var allErrs string
-		var out interface{}
+		var out any
 		var err error
 
 		for _, c := range cached {
@@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	}
 }
 
+// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
+//
+// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
+// This function removes that check.
+func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
 // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
 // strings to time.Duration.
 func StringToTimeDurationHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.ParseDuration(data.(string))
+		d, err := time.ParseDuration(data.(string))
+
+		return d, wrapTimeParseDurationError(err)
+	}
+}
+
+// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
+// strings to *time.Location.
+func StringToTimeLocationHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(time.Local) {
+			return data, nil
+		}
+		d, err := time.LoadLocation(data.(string))
+
+		return d, wrapTimeParseLocationError(err)
 	}
 }
 
@@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return url.Parse(data.(string))
+		u, err := url.Parse(data.(string))
+
+		return u, wrapUrlError(err)
 	}
 }
 
@@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc {
 		// Convert it by parsing
 		ip := net.ParseIP(data.(string))
 		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
+			return net.IP{}, fmt.Errorf("failed parsing ip")
 		}
 
 		return ip, nil
@@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 
 		// Convert it by parsing
 		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
+		return net, wrapNetParseError(err)
 	}
 }
 
@@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.Parse(layout, data.(string))
+		ti, err := time.Parse(layout, data.(string))
+
+		return ti, wrapTimeParseError(err)
 	}
 }
 
@@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 func WeaklyTypedHook(
 	f reflect.Kind,
 	t reflect.Kind,
-	data interface{},
-) (interface{}, error) {
+	data any,
+) (any, error) {
 	dataVal := reflect.ValueOf(data)
 	switch t {
 	case reflect.String:
@@ -301,17 +354,17 @@ func WeaklyTypedHook(
 }
 
 func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		if f.Kind() != reflect.Struct {
 			return f.Interface(), nil
 		}
 
-		var i interface{} = struct{}{}
+		var i any = struct{}{}
 		if t.Type() != reflect.TypeOf(&i).Elem() {
 			return f.Interface(), nil
 		}
 
-		m := make(map[string]interface{})
+		m := make(map[string]any)
 		t.Set(reflect.ValueOf(m))
 
 		return f.Interface(), nil
@@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddr(data.(string))
+		addr, err := netip.ParseAddr(data.(string))
+
+		return addr, wrapNetIPParseAddrError(err)
 	}
 }
 
@@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddrPort(data.(string))
+		addrPort, err := netip.ParseAddrPort(data.(string))
+
+		return addrPort, wrapNetIPParseAddrPortError(err)
+	}
+}
+
+// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts
+// strings to netip.Prefix.
+func StringToNetIPPrefixHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(netip.Prefix{}) {
+			return data, nil
+		}
+
+		// Convert it by parsing
+		prefix, err := netip.ParsePrefix(data.(string))
+
+		return prefix, wrapNetIPParsePrefixError(err)
 	}
 }
 
@@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc {
 // StringToInt8HookFunc returns a DecodeHookFunc that converts
 // strings to int8.
 func StringToInt8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 8)
-		return int8(i64), err
+		return int8(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint8HookFunc returns a DecodeHookFunc that converts
 // strings to uint8.
 func StringToUint8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 8)
-		return uint8(u64), err
+		return uint8(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt16HookFunc returns a DecodeHookFunc that converts
 // strings to int16.
 func StringToInt16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 16)
-		return int16(i64), err
+		return int16(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint16HookFunc returns a DecodeHookFunc that converts
 // strings to uint16.
 func StringToUint16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 16)
-		return uint16(u64), err
+		return uint16(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt32HookFunc returns a DecodeHookFunc that converts
 // strings to int32.
 func StringToInt32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 32)
-		return int32(i64), err
+		return int32(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint32HookFunc returns a DecodeHookFunc that converts
 // strings to uint32.
 func StringToUint32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 32)
-		return uint32(u64), err
+		return uint32(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt64HookFunc returns a DecodeHookFunc that converts
 // strings to int64.
 func StringToInt64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseInt(data.(string), 0, 64)
+		i64, err := strconv.ParseInt(data.(string), 0, 64)
+		return int64(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint64HookFunc returns a DecodeHookFunc that converts
 // strings to uint64.
 func StringToUint64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseUint(data.(string), 0, 64)
+		u64, err := strconv.ParseUint(data.(string), 0, 64)
+		return uint64(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToIntHookFunc returns a DecodeHookFunc that converts
 // strings to int.
 func StringToIntHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 0)
-		return int(i64), err
+		return int(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUintHookFunc returns a DecodeHookFunc that converts
 // strings to uint.
 func StringToUintHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 0)
-		return uint(u64), err
+		return uint(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat32HookFunc returns a DecodeHookFunc that converts
 // strings to float32.
 func StringToFloat32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		f64, err := strconv.ParseFloat(data.(string), 32)
-		return float32(f64), err
+		return float32(f64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat64HookFunc returns a DecodeHookFunc that converts
 // strings to float64.
 func StringToFloat64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseFloat(data.(string), 64)
+		f64, err := strconv.ParseFloat(data.(string), 64)
+		return f64, wrapStrconvNumError(err)
 	}
 }
 
 // StringToBoolHookFunc returns a DecodeHookFunc that converts
 // strings to bool.
 func StringToBoolHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseBool(data.(string))
+		b, err := strconv.ParseBool(data.(string))
+		return b, wrapStrconvNumError(err)
 	}
 }
 
@@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc {
 // StringToComplex64HookFunc returns a DecodeHookFunc that converts
 // strings to complex64.
 func StringToComplex64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		c128, err := strconv.ParseComplex(data.(string), 64)
-		return complex64(c128), err
+		return complex64(c128), wrapStrconvNumError(err)
 	}
 }
 
 // StringToComplex128HookFunc returns a DecodeHookFunc that converts
 // strings to complex128.
 func StringToComplex128HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseComplex(data.(string), 128)
+		c128, err := strconv.ParseComplex(data.(string), 128)
+		return c128, wrapStrconvNumError(err)
 	}
 }
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/errors.go b/notifier/vendor/github.com/go-viper/mapstructure/v2/errors.go
new file mode 100644
index 00000000..07d31c22
--- /dev/null
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/errors.go
@@ -0,0 +1,244 @@
+package mapstructure
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// Error interface is implemented by all errors emitted by mapstructure.
+//
+// Use [errors.As] to check if an error implements this interface.
+type Error interface {
+	error
+
+	mapstructure()
+}
+
+// DecodeError is a generic error type that holds information about
+// a decoding error together with the name of the field that caused the error.
+type DecodeError struct {
+	name string
+	err  error
+}
+
+func newDecodeError(name string, err error) *DecodeError {
+	return &DecodeError{
+		name: name,
+		err:  err,
+	}
+}
+
+func (e *DecodeError) Name() string {
+	return e.name
+}
+
+func (e *DecodeError) Unwrap() error {
+	return e.err
+}
+
+func (e *DecodeError) Error() string {
+	return fmt.Sprintf("'%s' %s", e.name, e.err)
+}
+
+func (*DecodeError) mapstructure() {}
+
+// ParseError is an error type that indicates a value could not be parsed
+// into the expected type.
+type ParseError struct {
+	Expected reflect.Value
+	Value    any
+	Err      error
+}
+
+func (e *ParseError) Error() string {
+	return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err)
+}
+
+func (*ParseError) mapstructure() {}
+
+// UnconvertibleTypeError is an error type that indicates a value could not be
+// converted to the expected type.
+type UnconvertibleTypeError struct {
+	Expected reflect.Value
+	Value    any
+}
+
+func (e *UnconvertibleTypeError) Error() string {
+	return fmt.Sprintf(
+		"expected type '%s', got unconvertible type '%s'",
+		e.Expected.Type(),
+		reflect.TypeOf(e.Value),
+	)
+}
+
+func (*UnconvertibleTypeError) mapstructure() {}
+
+func wrapStrconvNumError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*strconv.NumError); ok {
+		return &strconvNumError{Err: err}
+	}
+
+	return err
+}
+
+type strconvNumError struct {
+	Err *strconv.NumError
+}
+
+func (e *strconvNumError) Error() string {
+	return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
+}
+
+func (e *strconvNumError) Unwrap() error { return e.Err }
+
+func wrapUrlError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*url.Error); ok {
+		return &urlError{Err: err}
+	}
+
+	return err
+}
+
+type urlError struct {
+	Err *url.Error
+}
+
+func (e *urlError) Error() string {
+	return fmt.Sprintf("%s", e.Err.Err)
+}
+
+func (e *urlError) Unwrap() error { return e.Err }
+
+func wrapNetParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*net.ParseError); ok {
+		return &netParseError{Err: err}
+	}
+
+	return err
+}
+
+type netParseError struct {
+	Err *net.ParseError
+}
+
+func (e *netParseError) Error() string {
+	return "invalid " + e.Err.Type
+}
+
+func (e *netParseError) Unwrap() error { return e.Err }
+
+func wrapTimeParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*time.ParseError); ok {
+		return &timeParseError{Err: err}
+	}
+
+	return err
+}
+
+type timeParseError struct {
+	Err *time.ParseError
+}
+
+func (e *timeParseError) Error() string {
+	if e.Err.Message == "" {
+		return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
+	}
+
+	return "parsing time " + e.Err.Message
+}
+
+func (e *timeParseError) Unwrap() error { return e.Err }
+
+func wrapNetIPParseAddrError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapNetIPParseAddrPortError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "invalid port ") {
+		return errors.New("invalid port")
+	} else if strings.HasPrefix(errMsg, "invalid ip:port ") {
+		return errors.New("invalid ip:port")
+	}
+
+	return err
+}
+
+func wrapNetIPParsePrefixError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapTimeParseDurationError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "time: unknown unit ") {
+		return errors.New("time: unknown unit")
+	} else if strings.HasPrefix(errMsg, "time: ") {
+		idx := strings.LastIndex(errMsg, " ")
+
+		return errors.New(errMsg[:idx])
+	}
+
+	return err
+}
+
+func wrapTimeParseLocationError(err error) error {
+	if err == nil {
+		return nil
+	}
+	errMsg := err.Error()
+	if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
+		return fmt.Errorf("invalid time zone format: %w", err)
+	}
+
+	return err
+}
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.lock
index 4bea8154..5e67bdd6 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.lock
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.lock
@@ -2,30 +2,28 @@
   "nodes": {
     "cachix": {
       "inputs": {
-        "devenv": "devenv_2",
+        "devenv": [
+          "devenv"
+        ],
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "git-hooks": [
+          "devenv"
         ],
-        "pre-commit-hooks": [
-          "devenv",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs"
       },
       "locked": {
-        "lastModified": 1712055811,
-        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "lastModified": 1742042642,
+        "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
         "owner": "cachix",
         "repo": "cachix",
-        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "latest",
         "repo": "cachix",
         "type": "github"
       }
@@ -33,52 +31,21 @@
     "devenv": {
       "inputs": {
         "cachix": "cachix",
-        "flake-compat": "flake-compat_2",
-        "nix": "nix_2",
-        "nixpkgs": "nixpkgs_2",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1717245169,
-        "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "devenv_2": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "cachix",
-          "flake-compat"
-        ],
+        "flake-compat": "flake-compat",
+        "git-hooks": "git-hooks",
         "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "poetry2nix": "poetry2nix",
-        "pre-commit-hooks": [
-          "devenv",
-          "cachix",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs_3"
       },
       "locked": {
-        "lastModified": 1708704632,
-        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
+        "lastModified": 1744876578,
+        "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
+        "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
-        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -86,27 +53,11 @@
     "flake-compat": {
       "flake": false,
       "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-compat_2": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "lastModified": 1733328505,
+        "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
         "type": "github"
       },
       "original": {
@@ -117,14 +68,18 @@
     },
     "flake-parts": {
       "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
+        "nixpkgs-lib": [
+          "devenv",
+          "nix",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1717285511,
-        "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
+        "lastModified": 1712014858,
+        "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
+        "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
         "type": "github"
       },
       "original": {
@@ -133,39 +88,46 @@
         "type": "github"
       }
     },
-    "flake-utils": {
+    "flake-parts_2": {
       "inputs": {
-        "systems": "systems"
+        "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1689068808,
-        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "lastModified": 1743550720,
+        "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "c621e8422220273271f52058f618c94e405bb0f5",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
         "type": "github"
       }
     },
-    "flake-utils_2": {
+    "git-hooks": {
       "inputs": {
-        "systems": "systems_2"
+        "flake-compat": [
+          "devenv"
+        ],
+        "gitignore": "gitignore",
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1710146030,
-        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "lastModified": 1742649964,
+        "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
         "type": "github"
       }
     },
@@ -173,7 +135,7 @@
       "inputs": {
         "nixpkgs": [
           "devenv",
-          "pre-commit-hooks",
+          "git-hooks",
           "nixpkgs"
         ]
       },
@@ -191,166 +153,109 @@
         "type": "github"
       }
     },
-    "nix": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "devenv-2.21",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nix-github-actions": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "poetry2nix",
-          "nixpkgs"
-        ]
-      },
+    "libgit2": {
+      "flake": false,
       "locked": {
-        "lastModified": 1688870561,
-        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
-        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "lastModified": 1697646580,
+        "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
+        "owner": "libgit2",
+        "repo": "libgit2",
+        "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
         "type": "github"
       },
       "original": {
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
+        "owner": "libgit2",
+        "repo": "libgit2",
         "type": "github"
       }
     },
-    "nix_2": {
+    "nix": {
       "inputs": {
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "flake-parts": "flake-parts",
+        "libgit2": "libgit2",
+        "nixpkgs": "nixpkgs_2",
+        "nixpkgs-23-11": [
+          "devenv"
+        ],
+        "nixpkgs-regression": [
+          "devenv"
         ],
-        "nixpkgs-regression": "nixpkgs-regression_2"
+        "pre-commit-hooks": [
+          "devenv"
+        ]
       },
       "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "lastModified": 1741798497,
+        "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
+        "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "devenv-2.21",
+        "ref": "devenv-2.24",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1692808169,
-        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
+        "lastModified": 1733212471,
+        "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
+        "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
+        "ref": "nixos-unstable",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs-lib": {
       "locked": {
-        "lastModified": 1717284937,
-        "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      },
-      "original": {
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression_2": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "lastModified": 1743296961,
+        "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
+        "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
         "type": "github"
       },
       "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
         "type": "github"
       }
     },
-    "nixpkgs-stable": {
+    "nixpkgs_2": {
       "locked": {
-        "lastModified": 1710695816,
-        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
+        "lastModified": 1717432640,
+        "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
+        "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.11",
+        "ref": "release-24.05",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "nixpkgs_2": {
+    "nixpkgs_3": {
       "locked": {
-        "lastModified": 1713361204,
-        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "lastModified": 1733477122,
+        "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
         "owner": "cachix",
         "repo": "devenv-nixpkgs",
-        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
         "type": "github"
       },
       "original": {
@@ -360,13 +265,13 @@
         "type": "github"
       }
     },
-    "nixpkgs_3": {
+    "nixpkgs_4": {
       "locked": {
-        "lastModified": 1717112898,
-        "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=",
+        "lastModified": 1744536153,
+        "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0",
+        "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
         "type": "github"
       },
       "original": {
@@ -376,94 +281,11 @@
         "type": "github"
       }
     },
-    "poetry2nix": {
-      "inputs": {
-        "flake-utils": "flake-utils",
-        "nix-github-actions": "nix-github-actions",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1692876271,
-        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils_2",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1713775815,
-        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
     "root": {
       "inputs": {
         "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_3"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
+        "flake-parts": "flake-parts_2",
+        "nixpkgs": "nixpkgs_4"
       }
     }
   },
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.nix
index 4ed0f533..3b116f42 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.nix
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/flake.nix
@@ -5,35 +5,42 @@
     devenv.url = "github:cachix/devenv";
   };
 
-  outputs = inputs@{ flake-parts, ... }:
+  outputs =
+    inputs@{ flake-parts, ... }:
     flake-parts.lib.mkFlake { inherit inputs; } {
       imports = [
         inputs.devenv.flakeModule
       ];
 
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
+      systems = [
+        "x86_64-linux"
+        "x86_64-darwin"
+        "aarch64-darwin"
+      ];
 
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-            };
+      perSystem =
+        { pkgs, ... }:
+        rec {
+          devenv.shells = {
+            default = {
+              languages = {
+                go.enable = true;
+              };
 
-            pre-commit.hooks = {
-              nixpkgs-fmt.enable = true;
-            };
+              pre-commit.hooks = {
+                nixpkgs-fmt.enable = true;
+              };
 
-            packages = with pkgs; [
-              golangci-lint
-            ];
+              packages = with pkgs; [
+                golangci-lint
+              ];
 
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
+              # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
+              containers = pkgs.lib.mkForce { };
+            };
 
-          ci = devenv.shells.default;
+            ci = devenv.shells.default;
+          };
         };
-      };
     };
 }
diff --git a/notifier/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/notifier/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
index e77e63ba..7c35bce0 100644
--- a/notifier/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
+++ b/notifier/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
@@ -1,5 +1,5 @@
 // Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
+// Go type into another, typically to convert a map[string]any
 // into a native Go structure.
 //
 // The Go structure can be arbitrarily complex, containing slices,
@@ -54,8 +54,8 @@
 //
 // This would require an input that looks like below:
 //
-//	map[string]interface{}{
-//	    "person": map[string]interface{}{"name": "alice"},
+//	map[string]any{
+//	    "person": map[string]any{"name": "alice"},
 //	}
 //
 // If your "person" value is NOT nested, then you can append ",squash" to
@@ -68,7 +68,7 @@
 //
 // Now the following input would be accepted:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -79,7 +79,7 @@
 //
 // Will be decoded into a map:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -95,18 +95,18 @@
 //
 // You can also use the ",remain" suffix on your tag to collect all unused
 // values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
+// probably be a "map[string]any" or "map[any]any".
 // See example below:
 //
 //	type Friend struct {
 //	    Name  string
-//	    Other map[string]interface{} `mapstructure:",remain"`
+//	    Other map[string]any `mapstructure:",remain"`
 //	}
 //
 // Given the input below, Other would be populated with the other
 // values that weren't used (everything but "name"):
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name":    "bob",
 //	    "address": "123 Maple St.",
 //	}
@@ -115,15 +115,36 @@
 //
 // When decoding from a struct to any other value, you may use the
 // ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
+// the zero value, or a zero-length element. The zero value of all types is
+// specified in the Go specification.
 //
 // For example, the zero type of a numeric type is zero ("0"). If the struct
 // field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil or empty, it won't be encoded into the destination type.
 //
 //	type Source struct {
-//	    Age int `mapstructure:",omitempty"`
+//	    Age  int      `mapstructure:",omitempty"`
+//	    URLs []string `mapstructure:",omitempty"`
+//	}
+//
+// # Omit Zero Values
+//
+// When decoding from a struct to any other value, you may use the
+// ",omitzero" suffix on your tag to omit that value if it equates to the zero
+// value. The zero value of all types is specified in the Go specification.
+//
+// For example, the zero type of a numeric type is zero ("0"). If the struct
+// field value is zero and a numeric type, the field is empty, and it won't
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil, it won't be encoded into the destination type.
+//
+// Note that if the field is a slice, and it is empty but not nil, it will
+// still be encoded into the destination type.
+//
+//	type Source struct {
+//	    Age  int      `mapstructure:",omitzero"`
+//	    URLs []string `mapstructure:",omitzero"`
 //	}
 //
 // # Unexported fields
@@ -140,7 +161,7 @@
 //
 // Using this map as input:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "private": "I will be ignored",
 //	    "Public":  "I made it through!",
 //	}
@@ -183,19 +204,19 @@ import (
 // we started with Kinds and then realized Types were the better solution,
 // but have a promise to not break backwards compat so we now support
 // both.
-type DecodeHookFunc interface{}
+type DecodeHookFunc any
 
 // DecodeHookFuncType is a DecodeHookFunc which has complete information about
 // the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
+type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
 
 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
 // source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
+type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
 
 // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
 // values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
+type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
 
 // DecoderConfig is the configuration that is used to create a new decoder
 // and allows customization of various aspects of decoding.
@@ -222,6 +243,12 @@ type DecoderConfig struct {
 	// will affect all nested structs as well.
 	ErrorUnset bool
 
+	// AllowUnsetPointer, if set to true, will prevent fields with pointer types
+	// from being reported as unset, even if ErrorUnset is true and the field was
+	// not present in the input data. This allows pointer fields to be optional
+	// without triggering an error when they are missing.
+	AllowUnsetPointer bool
+
 	// ZeroFields, if set to true, will zero fields before writing them.
 	// For example, a map will be emptied before decoded values are put in
 	// it. If this is false, a map will be merged.
@@ -260,7 +287,7 @@ type DecoderConfig struct {
 
 	// Result is a pointer to the struct that will contain the decoded
 	// value.
-	Result interface{}
+	Result any
 
 	// The tag name that mapstructure reads for field names. This
 	// defaults to "mapstructure"
@@ -292,7 +319,7 @@ type DecoderConfig struct {
 // up the most basic Decoder.
 type Decoder struct {
 	config           *DecoderConfig
-	cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
+	cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
 }
 
 // Metadata contains information about decoding a structure that
@@ -313,7 +340,7 @@ type Metadata struct {
 
 // Decode takes an input structure and uses reflection to translate it to
 // the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
+func Decode(input any, output any) error {
 	config := &DecoderConfig{
 		Metadata: nil,
 		Result:   output,
@@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error {
 
 // WeakDecode is the same as Decode but is shorthand to enable
 // WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
+func WeakDecode(input, output any) error {
 	config := &DecoderConfig{
 		Metadata:         nil,
 		Result:           output,
@@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error {
 
 // DecodeMetadata is the same as Decode, but is shorthand to
 // enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func DecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata: metadata,
 		Result:   output,
@@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e
 // WeakDecodeMetadata is the same as Decode, but is shorthand to
 // enable both WeaklyTypedInput and metadata collection. See
 // DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata:         metadata,
 		Result:           output,
@@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
 
 // Decode decodes the given raw interface to the target pointer specified
 // by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
+func (d *Decoder) Decode(input any) error {
 	err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
 
 	// Retain some of the original behavior when multiple errors ocurr
@@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error {
 }
 
 // isNil returns true if the input is nil or a typed nil pointer.
-func isNil(input interface{}) bool {
+func isNil(input any) bool {
 	if input == nil {
 		return true
 	}
@@ -452,7 +479,7 @@ func isNil(input interface{}) bool {
 }
 
 // Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
+func (d *Decoder) decode(name string, input any, outVal reflect.Value) error {
 	var (
 		inputVal   = reflect.ValueOf(input)
 		outputKind = getKind(outVal)
@@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		// Hooks need a valid inputVal, so reset it to zero value of outVal type.
 		switch outputKind {
 		case reflect.Struct, reflect.Map:
-			var mapVal map[string]interface{}
+			var mapVal map[string]any
 			inputVal = reflect.ValueOf(mapVal) // create nil map pointer
 		case reflect.Slice, reflect.Array:
-			var sliceVal []interface{}
+			var sliceVal []any
 			inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
 		default:
 			inputVal = reflect.Zero(outVal.Type())
@@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		var err error
 		input, err = d.cachedDecodeHook(inputVal, outVal)
 		if err != nil {
-			return fmt.Errorf("error decoding '%s': %w", name, err)
+			return newDecodeError(name, err)
 		}
 	}
 	if isNil(input) {
@@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		err = d.decodeFunc(name, input, outVal)
 	default:
 		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
+		return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind))
 	}
 
 	// If we reached here, then we successfully decoded SOMETHING, so
@@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 
 // This decodes a basic type (bool, int, string, etc.) and sets the
 // value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
 	if val.IsValid() && val.Elem().IsValid() {
 		elem := val.Elem()
 
@@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value)
 
 	dataValType := dataVal.Type()
 	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
 	}
 
 	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
 		if err == nil {
 			val.SetInt(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Int64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetInt(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Int:
 		i := dataVal.Int()
 		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%d overflows uint", i),
+			})
 		}
 		val.SetUint(uint64(i))
 	case dataKind == reflect.Uint:
@@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Float32:
 		f := dataVal.Float()
 		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%f overflows uint", f),
+			})
 		}
 		val.SetUint(uint64(f))
 	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
@@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		if err == nil {
 			val.SetUint(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := strconv.ParseUint(string(jn), 0, 64)
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 		val.SetUint(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
 		} else if dataVal.String() == "" {
 			val.SetBool(false)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'",
-			name, val, dataVal, data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
 		if err == nil {
 			val.SetFloat(f)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Float64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetFloat(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value
 	case dataKind == reflect.Complex64:
 		val.SetComplex(dataVal.Complex())
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
 	valType := val.Type()
 	valKeyType := valType.Key()
 	valElemType := valType.Elem()
@@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
 		fallthrough
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 }
 
@@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 		// to the map value.
 		v := dataVal.Field(i)
 		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
+			return newDecodeError(
+				name+"."+f.Name,
+				fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()),
+			)
 		}
 
 		tagValue := f.Tag.Get(d.config.TagName)
@@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 				continue
 			}
 
+			// If "omitzero" is specified in the tag, it ignores zero values.
+			if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() {
+				continue
+			}
+
 			// If "squash" is specified in the tag, we squash the field down.
 			squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
 			if squash {
@@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 
 				// The final type must be a struct
 				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
+					return newDecodeError(
+						name+"."+f.Name,
+						fmt.Errorf("cannot squash non-struct type %q", v.Type()),
+					)
 				}
 			} else {
 				if strings.Index(tagValue[index+1:], "remain") != -1 {
 					if v.Kind() != reflect.Map {
-						return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type())
+						return newDecodeError(
+							name+"."+f.Name,
+							fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()),
+						)
 					}
 
 					ptr := v.MapRange()
@@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 	return nil
 }
 
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
+func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
 	// If the input data is nil, then we want to just set the output
 	// pointer to be nil as well.
 	isNil := data == nil
@@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
 	return false, nil
 }
 
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error {
 	// Create an element of the concrete (non pointer) type and decode
 	// into that. Then set the value of the pointer to this type.
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 					return nil
 				}
 				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 
 			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
 				return d.decodeSlice(name, []byte(dataVal.String()), val)
@@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 			// and "lift" it into it. i.e. a string becomes a string slice.
 			default:
 				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 			}
 		}
 
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
+		return newDecodeError(name,
+			fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 	}
 
 	// If the input value is nil, then don't allocate since empty != nil
@@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 				// and "lift" it into it. i.e. a string becomes a string array.
 				default:
 					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
+					return d.decodeArray(name, []any{data}, val)
 				}
 			}
 
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
+			return newDecodeError(name,
+				fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 
 		}
 		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
+			return newDecodeError(name,
+				fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len()))
 		}
 
 		// Make a new array to hold our result, same size as the original data.
@@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 
 	// If the type of the value to write to and the data match directly,
@@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		// as an intermediary.
 
 		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
+		mapType := reflect.TypeOf((map[string]any)(nil))
 		mval := reflect.MakeMap(mapType)
 
 		// Creating a pointer to a map so that other methods can completely
@@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		return result
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name,
+			fmt.Errorf("expected a map or struct, got %q", dataValKind))
 	}
 }
 
 func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
 	dataValType := dataVal.Type()
 	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
+		return newDecodeError(name,
+			fmt.Errorf("needs a map with string keys, has %q keys", kind))
 	}
 
 	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
+	dataValKeysUnused := make(map[any]struct{})
 	for _, dataValKey := range dataVal.MapKeys() {
 		dataValKeys[dataValKey] = struct{}{}
 		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
 	}
 
-	targetValKeysUnused := make(map[interface{}]struct{})
+	targetValKeysUnused := make(map[any]struct{})
 
 	var errs []error
 
@@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 						structs = append(structs, fieldVal.Elem().Elem())
 					}
 				default:
-					errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
+					errs = append(errs, newDecodeError(
+						name+"."+fieldType.Name,
+						fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()),
+					))
 				}
 				continue
 			}
@@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 			if !rawMapVal.IsValid() {
 				// There was no matching key in the map for the value in
 				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
+				if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) {
+					targetValKeysUnused[fieldName] = struct{}{}
+				}
 				continue
 			}
 		}
@@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 	// we put the unused keys directly into the remain field.
 	if remainField != nil && len(dataValKeysUnused) > 0 {
 		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
+		remain := map[any]any{}
 		for key := range dataValKeysUnused {
 			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
 		}
@@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
@@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if err := errors.Join(errs...); err != nil {
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
index 8766d38f..475699b5 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/BUILD.bazel
@@ -13,6 +13,7 @@ go_library(
     deps = [
         "@org_golang_google_protobuf//compiler/protogen",
         "@org_golang_google_protobuf//proto",
+        "@org_golang_google_protobuf//types/descriptorpb",
         "@org_golang_google_protobuf//types/pluginpb",
     ],
 )
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
index 18c6cf07..dd476abf 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator/supported_features.go
@@ -2,18 +2,25 @@ package codegenerator
 
 import (
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/types/descriptorpb"
 	"google.golang.org/protobuf/types/pluginpb"
 )
 
 func supportedCodeGeneratorFeatures() uint64 {
-	// Enable support for optional keyword in proto3.
-	return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
+	// Enable support for Protobuf Editions
+	return uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS)
+}
+
+func supportedEditions() (descriptorpb.Edition, descriptorpb.Edition) {
+	// Declare support for edition 2023 only
+	return descriptorpb.Edition_EDITION_2023, descriptorpb.Edition_EDITION_2023
 }
 
 // SetSupportedFeaturesOnPluginGen sets supported proto3 features
 // on protogen.Plugin.
 func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) {
 	gen.SupportedFeatures = supportedCodeGeneratorFeatures()
+	gen.SupportedEditionsMinimum, gen.SupportedEditionsMaximum = supportedEditions()
 }
 
 // SetSupportedFeaturesOnCodeGeneratorResponse sets supported proto3 features
@@ -21,4 +28,7 @@ func SetSupportedFeaturesOnPluginGen(gen *protogen.Plugin) {
 func SetSupportedFeaturesOnCodeGeneratorResponse(resp *pluginpb.CodeGeneratorResponse) {
 	sf := supportedCodeGeneratorFeatures()
 	resp.SupportedFeatures = &sf
+	minE, maxE := supportedEditions()
+	minEN, maxEN := int32(minE.Number()), int32(maxE.Number())
+	resp.MinimumEdition, resp.MaximumEdition = &minEN, &maxEN
 }
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
index 28b6e258..84b73d08 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/BUILD.bazel
@@ -19,7 +19,7 @@ go_library(
         "//internal/descriptor/openapiconfig",
         "//internal/httprule",
         "//protoc-gen-openapiv2/options",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_grpc//grpclog",
         "@org_golang_google_protobuf//compiler/protogen",
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
index 4f4a31c1..dea0605c 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go
@@ -7,8 +7,8 @@ import (
 	"strings"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/apiconfig"
+	"go.yaml.in/yaml/v3"
 	"google.golang.org/protobuf/encoding/protojson"
-	"gopkg.in/yaml.v3"
 )
 
 func loadGrpcAPIServiceFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*apiconfig.GrpcAPIService, error) {
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
index d48a7c81..8b540165 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapi_configuration.go
@@ -6,8 +6,8 @@ import (
 	"os"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/openapiconfig"
+	"go.yaml.in/yaml/v3"
 	"google.golang.org/protobuf/encoding/protojson"
-	"gopkg.in/yaml.v3"
 )
 
 func loadOpenAPIConfigFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*openapiconfig.OpenAPIConfig, error) {
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
index 06537035..e6e48130 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/BUILD.bazel
@@ -34,3 +34,20 @@ go_proto_compiler(
         "@org_golang_google_grpc//metadata:go_default_library",
     ],
 )
+
+go_proto_compiler(
+    name = "go_gen_grpc_gateway_opaque",
+    options = [
+        "paths=source_relative",
+        "use_opaque_api=true",
+    ],
+    plugin = ":protoc-gen-grpc-gateway",
+    suffix = ".pb.gw.go",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//runtime:go_default_library",
+        "//utilities:go_default_library",
+        "@org_golang_google_grpc//grpclog:go_default_library",
+        "@org_golang_google_grpc//metadata:go_default_library",
+    ],
+)
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
index 819cbf55..5a58625c 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/generator.go
@@ -22,11 +22,12 @@ type generator struct {
 	registerFuncSuffix string
 	allowPatchFeature  bool
 	standalone         bool
+	useOpaqueAPI       bool
 }
 
 // New returns a new generator which generates grpc gateway files.
 func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix string,
-	allowPatchFeature, standalone bool) gen.Generator {
+	allowPatchFeature, standalone bool, useOpaqueAPI bool) gen.Generator {
 	var imports []descriptor.GoPackage
 	for _, pkgpath := range []string{
 		"context",
@@ -66,6 +67,7 @@ func New(reg *descriptor.Registry, useRequestContext bool, registerFuncSuffix st
 		registerFuncSuffix: registerFuncSuffix,
 		allowPatchFeature:  allowPatchFeature,
 		standalone:         standalone,
+		useOpaqueAPI:       useOpaqueAPI,
 	}
 }
 
@@ -132,6 +134,7 @@ func (g *generator) generate(file *descriptor.File) (string, error) {
 		UseRequestContext:  g.useRequestContext,
 		RegisterFuncSuffix: g.registerFuncSuffix,
 		AllowPatchFeature:  g.allowPatchFeature,
+		UseOpaqueAPI:       g.useOpaqueAPI,
 	}
 	if g.reg != nil {
 		params.OmitPackageDoc = g.reg.GetOmitPackageDoc()
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
index 80df6a0b..b647e1df 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/internal/gengateway/template.go
@@ -21,12 +21,14 @@ type param struct {
 	RegisterFuncSuffix string
 	AllowPatchFeature  bool
 	OmitPackageDoc     bool
+	UseOpaqueAPI       bool
 }
 
 type binding struct {
 	*descriptor.Binding
 	Registry          *descriptor.Registry
 	AllowPatchFeature bool
+	UseOpaqueAPI      bool
 }
 
 // GetBodyFieldPath returns the binding body's field path.
@@ -147,6 +149,7 @@ type trailerParams struct {
 	Services           []*descriptor.Service
 	UseRequestContext  bool
 	RegisterFuncSuffix string
+	UseOpaqueAPI       bool
 }
 
 func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
@@ -182,6 +185,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 					Binding:           b,
 					Registry:          reg,
 					AllowPatchFeature: p.AllowPatchFeature,
+					UseOpaqueAPI:      p.UseOpaqueAPI,
 				}); err != nil {
 					return "", err
 				}
@@ -191,6 +195,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 					Binding:           b,
 					Registry:          reg,
 					AllowPatchFeature: p.AllowPatchFeature,
+					UseOpaqueAPI:      p.UseOpaqueAPI,
 				}); err != nil {
 					return "", err
 				}
@@ -208,6 +213,7 @@ func applyTemplate(p param, reg *descriptor.Registry) (string, error) {
 		Services:           targetServices,
 		UseRequestContext:  p.UseRequestContext,
 		RegisterFuncSuffix: p.RegisterFuncSuffix,
+		UseOpaqueAPI:       p.UseOpaqueAPI,
 	}
 	// Local
 	if err := localTrailerTemplate.Execute(w, tp); err != nil {
@@ -335,6 +341,7 @@ func request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }}(ct
 
 	_ = template.Must(handlerTemplate.New("client-rpc-request-func").Funcs(funcMap).Parse(`
 {{ $AllowPatchFeature := .AllowPatchFeature }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{ if .HasQueryParam }}
 var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{ .QueryParamFilter }}
 {{ end }}
@@ -365,20 +372,53 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 	{{printf "%s" $protoReq }}
 	{{- end }}
 	{{- if not $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(req.Body).Decode(&{{.Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path}}); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
 	}
 	{{- end }}
 	{{- if $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
 	}
+	{{- if $UseOpaqueAPI }}
+	if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 {
+			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil {
+				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+			} else {
+				protoReq.Set{{ .FieldMaskField }}(fieldMask)
+			}
+	}
+	{{- else }}
 	if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 {
 			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil {
 				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
@@ -387,6 +427,7 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 			}
 	}
 	{{- end }}
+	{{- end }}
 {{- else }}
 	if req.Body != nil {
 		_, _  = io.Copy(io.Discard, req.Body)
@@ -421,19 +462,35 @@ var filter_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index }} = {{
 	{{- if ne "" $protoReq }}
 	{{ printf "%s" $protoReq }}
 	{{- end}}
+	{{- if $UseOpaqueAPI }}
+	converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
+	}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }})
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
 	}
+	{{- end }}
 {{- end}}
 {{- if and $enum $param.IsRepeated }}
 	s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es))
 	for i, v := range es {
 		s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path}}(v)
 	}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s)
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s
+	{{- end }}
 {{- else if $enum}}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e))
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)
+	{{- end }}
 {{- end}}
 	{{- end }}
 {{- end }}
@@ -524,6 +581,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 
 	_ = template.Must(localHandlerTemplate.New("local-client-rpc-request-func").Funcs(funcMap).Parse(`
 {{ $AllowPatchFeature := .AllowPatchFeature }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{ template "local-request-func-signature" . }} {
 	var (
 		protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
@@ -551,14 +609,47 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 	{{ printf "%s" $protoReq }}
 	{{- end }}
 	{{- if not $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(req.Body).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(req.Body).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF)  {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	{{- end }}
+	{{- end }}
 	{{- if $isFieldMask }}
+	{{- if $UseOpaqueAPI }}
+	var bodyData {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
+	if err := marshaler.NewDecoder(newReader()).Decode(&bodyData); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	{{- if eq "*" .GetBodyFieldPath }}
+	protoReq = bodyData
+	{{- else }}
+	protoReq.Set{{ .GetBodyFieldStructName }}(bodyData.Get{{ .GetBodyFieldStructName }}())
+	{{- end }}
+	{{- else }}
 	if err := marshaler.NewDecoder(newReader()).Decode(&{{ .Body.AssignableExpr "protoReq" .Method.Service.File.GoPkg.Path }}); err != nil && !errors.Is(err, io.EOF)  {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
+	{{- end }}
+	{{- if $UseOpaqueAPI }}
+	if !protoReq.Has{{ .FieldMaskField }}() || len(protoReq.Get{{ .FieldMaskField }}().GetPaths()) == 0 {
+			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Get{{ .GetBodyFieldStructName }}()); err != nil {
+				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+			} else {
+				protoReq.Set{{ .FieldMaskField }}(fieldMask)
+			}
+	}
+	{{- else }}
 	if protoReq.{{ .FieldMaskField }} == nil || len(protoReq.{{ .FieldMaskField }}.GetPaths()) == 0 {
 			if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.{{ .GetBodyFieldStructName }}); err != nil {
 				return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
@@ -567,6 +658,7 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 			}
 	}
 	{{- end }}
+	{{- end }}
 {{- end }}
 {{- if .PathParams}}
 	{{- $binding := .}}
@@ -596,20 +688,36 @@ func local_request_{{ .Method.Service.GetName }}_{{ .Method.GetName }}_{{ .Index
 	{{- $protoReq := $param.AssignableExprPrep "protoReq" $binding.Method.Service.File.GoPkg.Path -}}
 	{{- if ne "" $protoReq }}
 	{{ printf "%s" $protoReq }}
-	{{- end }}
+	{{- end}}
+	{{- if $UseOpaqueAPI }}
+	converted{{ $param.FieldPath.String | camelIdentifier }}, err := {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
+	if err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q"}}, err)
+	}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(converted{{ $param.FieldPath.String | camelIdentifier }})
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }}, err = {{ $param.ConvertFuncExpr }}(val{{ if $param.IsRepeated }}, {{ $binding.Registry.GetRepeatedPathParamSeparator | printf "%c" | printf "%q" }}{{ end }})
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", {{ $param | printf "%q" }}, err)
 	}
+	{{- end }}
 {{- end}}
 {{- if and $enum $param.IsRepeated }}
 	s := make([]{{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}, len(es))
 	for i, v := range es {
 		s[i] = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path }}(v)
 	}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}(s)
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = s
+	{{- end }}
 {{- else if $enum }}
+	{{- if $UseOpaqueAPI }}
+	protoReq.Set{{ $param.FieldPath.String | camelIdentifier }}({{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e))
+	{{- else }}
 	{{ $param.AssignableExpr "protoReq" $binding.Method.Service.File.GoPkg.Path }} = {{ $enum.GoType $param.Method.Service.File.GoPkg.Path | camelIdentifier }}(e)
+	{{- end }}
 {{- end }}
 	{{- end }}
 {{- end }}
@@ -689,6 +797,7 @@ func Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}Server(ctx context.Cont
 
 	trailerTemplate = template.Must(template.New("trailer").Funcs(funcMap).Parse(`
 {{ $UseRequestContext := .UseRequestContext }}
+{{ $UseOpaqueAPI := .UseOpaqueAPI }}
 {{range $svc := .Services}}
 // Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }}FromEndpoint is same as Register{{ $svc.GetName }}{{ $.RegisterFuncSuffix }} but
 // automatically dials to "endpoint" and closes the connection when "ctx" gets done.
@@ -782,7 +891,15 @@ type response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }} struct {
 
 func (m response_{{ $svc.GetName }}_{{ $m.GetName }}_{{ $b.Index }}) XXX_ResponseBody() interface{} {
 	response := m.{{ $m.ResponseType.GetName }}
+	{{- if $UseOpaqueAPI }}
+	{{- if eq "*" $b.ResponseBody.FieldPath.String }}
+	return response
+	{{- else }}
+	return response.Get{{ $b.ResponseBody.FieldPath.String | camelIdentifier }}()
+	{{- end }}
+	{{- else }}
 	return {{ $b.ResponseBody.AssignableExpr "response" $m.Service.File.GoPkg.Path }}
+	{{- end }}
 }
 {{ end }}
 {{ end }}
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
index 086a4624..862a8fc0 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway/main.go
@@ -36,6 +36,7 @@ var (
 	versionFlag                = flag.Bool("version", false, "print the current version")
 	warnOnUnboundMethods       = flag.Bool("warn_on_unbound_methods", false, "emit a warning message if an RPC method has no HttpRule annotation")
 	generateUnboundMethods     = flag.Bool("generate_unbound_methods", false, "generate proxy methods even for RPC methods that have no HttpRule annotation")
+	useOpaqueAPI               = flag.Bool("use_opaque_api", false, "generate code compatible with the new Opaque API instead of the older Open Struct API")
 
 	_ = flag.Bool("logtostderr", false, "Legacy glog compatibility. This flag is a no-op, you can safely remove it")
 )
@@ -80,7 +81,7 @@ func main() {
 
 		codegenerator.SetSupportedFeaturesOnPluginGen(gen)
 
-		generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone)
+		generator := gengateway.New(reg, *useRequestContext, *registerFuncSuffix, *allowPatchFeature, *standalone, *useOpaqueAPI)
 
 		if grpclog.V(1) {
 			grpclog.Infof("Parsing code generator request")
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
index 7be6a90e..cef5f808 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/BUILD.bazel
@@ -20,7 +20,7 @@ go_library(
         "//internal/descriptor",
         "//internal/generator",
         "//protoc-gen-openapiv2/options",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_genproto_googleapis_api//visibility",
         "@org_golang_google_genproto_googleapis_rpc//status",
@@ -59,7 +59,7 @@ go_test(
         "//protoc-gen-openapiv2/options",
         "//runtime",
         "@com_github_google_go_cmp//cmp",
-        "@in_gopkg_yaml_v3//:yaml_v3",
+        "@in_yaml_go_yaml_v3//:yaml",
         "@org_golang_google_genproto_googleapis_api//annotations",
         "@org_golang_google_genproto_googleapis_api//visibility",
         "@org_golang_google_protobuf//encoding/protojson",
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
index 6f0faa8e..30cf7dac 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/format.go
@@ -5,7 +5,7 @@ import (
 	"errors"
 	"io"
 
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 type Format string
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
index 6795cf71..69f69b9a 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/generator.go
@@ -13,6 +13,7 @@ import (
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
 	gen "github.com/grpc-ecosystem/grpc-gateway/v2/internal/generator"
 	openapioptions "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
+	"go.yaml.in/yaml/v3"
 	statuspb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/protobuf/proto"
@@ -20,7 +21,6 @@ import (
 	"google.golang.org/protobuf/types/descriptorpb"
 	"google.golang.org/protobuf/types/known/anypb"
 	"google.golang.org/protobuf/types/pluginpb"
-	"gopkg.in/yaml.v3"
 )
 
 var errNoTargetService = errors.New("no target service defined in the file")
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
index 84831c28..6265da8f 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/template.go
@@ -771,8 +771,8 @@ func filterOutExcludedFields(fields []string, excluded []descriptor.Parameter) [
 	return filtered
 }
 
-// schemaOfField returns a OpenAPI Schema Object for a protobuf field.
-func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
+// schemaOfFieldBase returns a base Schema Object for a protobuf field.
+func schemaOfFieldBase(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
 	const (
 		singular = 0
 		array    = 1
@@ -828,7 +828,7 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o
 		}
 	}
 
-	ret := openapiSchemaObject{}
+	var ret openapiSchemaObject
 
 	switch aggregate {
 	case array:
@@ -854,6 +854,12 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o
 			Properties: props,
 		}
 	}
+	return ret
+}
+
+// schemaOfField returns a OpenAPI Schema Object for a protobuf field.
+func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) openapiSchemaObject {
+	ret := schemaOfFieldBase(f, reg, refs)
 
 	if j, err := getFieldOpenAPIOption(reg, f); err == nil {
 		updateswaggerObjectFromJSONSchema(&ret, j, reg, f)
@@ -1037,7 +1043,7 @@ func resolveFullyQualifiedNameToOpenAPINames(messages []string, namingStrategy s
 	return strategyFn(messages)
 }
 
-var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.]*)([^}]*)}")
+var canRegexp = regexp.MustCompile("{([a-zA-Z][a-zA-Z0-9_.-]*)([^}]*)}")
 
 // templateToParts splits a URL template into path segments for use by `partsToOpenAPIPath` and `partsToRegexpMap`.
 //
@@ -1534,10 +1540,17 @@ func renderServices(services []*descriptor.Service, paths *openapiPathsObject, r
 						}
 						// Align pathParams with body field path.
 						pathParams := subPathParams(bodyField.Name, b.PathParams)
-						var err error
-						schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams)
-						if err != nil {
-							return err
+
+						if len(pathParams) == 0 {
+							// When there are no path parameters, we only need the base schema of the field.
+							// https://github.com/grpc-ecosystem/grpc-gateway/issues/3058
+							schema = schemaOfFieldBase(bodyField.Target, reg, customRefs)
+						} else {
+							var err error
+							schema, err = renderFieldAsDefinition(bodyField.Target, reg, customRefs, pathParams)
+							if err != nil {
+								return err
+							}
 						}
 						if schema.Title != "" {
 							desc = mergeDescription(schema)
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
index 02c85784..db9be4de 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopenapi/types.go
@@ -6,7 +6,7 @@ import (
 	"fmt"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 type param struct {
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
index a65d88eb..04b4bebf 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
@@ -27,6 +27,7 @@ go_library(
         "//internal/httprule",
         "//utilities",
         "@org_golang_google_genproto_googleapis_api//httpbody",
+        "@org_golang_google_grpc//:grpc",
         "@org_golang_google_grpc//codes",
         "@org_golang_google_grpc//grpclog",
         "@org_golang_google_grpc//health/grpc_health_v1",
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
index 2f2b3424..00b2228a 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
@@ -201,13 +201,13 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
 	if timeout != 0 {
 		ctx, _ = context.WithTimeout(ctx, timeout)
 	}
-	if len(pairs) == 0 {
-		return ctx, nil, nil
-	}
 	md := metadata.Pairs(pairs...)
 	for _, mda := range mux.metadataAnnotators {
 		md = metadata.Join(md, mda(ctx, req))
 	}
+	if len(md) == 0 {
+		return ctx, nil, nil
+	}
 	return ctx, md, nil
 }
 
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
index 8376d1e0..3d070630 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
@@ -66,7 +66,7 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
 
 var (
 	// protoMessageType is stored to prevent constant lookup of the same type at runtime.
-	protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
+	protoMessageType = reflect.TypeFor[proto.Message]()
 )
 
 // marshalNonProto marshals a non-message field of a protobuf message.
@@ -325,9 +325,9 @@ type protoEnum interface {
 	EnumDescriptor() ([]byte, []int)
 }
 
-var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem()
+var typeProtoEnum = reflect.TypeFor[protoEnum]()
 
-var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
+var typeProtoMessage = reflect.TypeFor[proto.Message]()
 
 // Delimiter for newline encoded JSON streams.
 func (j *JSONPb) Delimiter() []byte {
diff --git a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
index 19255ec4..3eb16167 100644
--- a/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
+++ b/notifier/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule"
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/health/grpc_health_v1"
@@ -281,12 +282,19 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 			http.MethodGet, endpointPath, func(w http.ResponseWriter, r *http.Request, _ map[string]string,
 			) {
 				_, outboundMarshaler := MarshalerForRequest(s, r)
+				annotatedContext, err := AnnotateContext(r.Context(), s, r, grpc_health_v1.Health_Check_FullMethodName, WithHTTPPathPattern(endpointPath))
+				if err != nil {
+					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					return
+				}
 
-				resp, err := healthCheckClient.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{
+				var md ServerMetadata
+				resp, err := healthCheckClient.Check(annotatedContext, &grpc_health_v1.HealthCheckRequest{
 					Service: r.URL.Query().Get("service"),
-				})
+				}, grpc.Header(&md.HeaderMD), grpc.Trailer(&md.TrailerMD))
+				annotatedContext = NewServerMetadataContext(annotatedContext, md)
 				if err != nil {
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
@@ -300,7 +308,7 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 						err = status.Error(codes.NotFound, resp.String())
 					}
 
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
diff --git a/notifier/vendor/github.com/hashicorp/hcl/.gitignore b/notifier/vendor/github.com/hashicorp/hcl/.gitignore
deleted file mode 100644
index 15586a2b..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-y.output
-
-# ignore intellij files
-.idea
-*.iml
-*.ipr
-*.iws
-
-*.test
diff --git a/notifier/vendor/github.com/hashicorp/hcl/.travis.yml b/notifier/vendor/github.com/hashicorp/hcl/.travis.yml
deleted file mode 100644
index cb63a321..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-sudo: false
-
-language: go
-
-go:
-  - 1.x
-  - tip
-
-branches:
-  only:
-    - master
-
-script: make test
diff --git a/notifier/vendor/github.com/hashicorp/hcl/LICENSE b/notifier/vendor/github.com/hashicorp/hcl/LICENSE
deleted file mode 100644
index c33dcc7c..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/LICENSE
+++ /dev/null
@@ -1,354 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. “Contributor”
-
-     means each individual or legal entity that creates, contributes to the
-     creation of, or owns Covered Software.
-
-1.2. “Contributor Version”
-
-     means the combination of the Contributions of others (if any) used by a
-     Contributor and that particular Contributor’s Contribution.
-
-1.3. “Contribution”
-
-     means Covered Software of a particular Contributor.
-
-1.4. “Covered Software”
-
-     means Source Code Form to which the initial Contributor has attached the
-     notice in Exhibit A, the Executable Form of such Source Code Form, and
-     Modifications of such Source Code Form, in each case including portions
-     thereof.
-
-1.5. “Incompatible With Secondary Licenses”
-     means
-
-     a. that the initial Contributor has attached the notice described in
-        Exhibit B to the Covered Software; or
-
-     b. that the Covered Software was made available under the terms of version
-        1.1 or earlier of the License, but not also under the terms of a
-        Secondary License.
-
-1.6. “Executable Form”
-
-     means any form of the work other than Source Code Form.
-
-1.7. “Larger Work”
-
-     means a work that combines Covered Software with other material, in a separate
-     file or files, that is not Covered Software.
-
-1.8. “License”
-
-     means this document.
-
-1.9. “Licensable”
-
-     means having the right to grant, to the maximum extent possible, whether at the
-     time of the initial grant or subsequently, any and all of the rights conveyed by
-     this License.
-
-1.10. “Modifications”
-
-     means any of the following:
-
-     a. any file in Source Code Form that results from an addition to, deletion
-        from, or modification of the contents of Covered Software; or
-
-     b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. “Patent Claims” of a Contributor
-
-      means any patent claim(s), including without limitation, method, process,
-      and apparatus claims, in any patent Licensable by such Contributor that
-      would be infringed, but for the grant of the License, by the making,
-      using, selling, offering for sale, having made, import, or transfer of
-      either its Contributions or its Contributor Version.
-
-1.12. “Secondary License”
-
-      means either the GNU General Public License, Version 2.0, the GNU Lesser
-      General Public License, Version 2.1, the GNU Affero General Public
-      License, Version 3.0, or any later versions of those licenses.
-
-1.13. “Source Code Form”
-
-      means the form of the work preferred for making modifications.
-
-1.14. “You” (or “Your”)
-
-      means an individual or a legal entity exercising rights under this
-      License. For legal entities, “You” includes any entity that controls, is
-      controlled by, or is under common control with You. For purposes of this
-      definition, “control” means (a) the power, direct or indirect, to cause
-      the direction or management of such entity, whether by contract or
-      otherwise, or (b) ownership of more than fifty percent (50%) of the
-      outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
-     Each Contributor hereby grants You a world-wide, royalty-free,
-     non-exclusive license:
-
-     a. under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or as
-        part of a Larger Work; and
-
-     b. under Patent Claims of such Contributor to make, use, sell, offer for
-        sale, have made, import, and otherwise transfer either its Contributions
-        or its Contributor Version.
-
-2.2. Effective Date
-
-     The licenses granted in Section 2.1 with respect to any Contribution become
-     effective for each Contribution on the date the Contributor first distributes
-     such Contribution.
-
-2.3. Limitations on Grant Scope
-
-     The licenses granted in this Section 2 are the only rights granted under this
-     License. No additional rights or licenses will be implied from the distribution
-     or licensing of Covered Software under this License. Notwithstanding Section
-     2.1(b) above, no patent license is granted by a Contributor:
-
-     a. for any code that a Contributor has removed from Covered Software; or
-
-     b. for infringements caused by: (i) Your and any other third party’s
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-     c. under Patent Claims infringed by Covered Software in the absence of its
-        Contributions.
-
-     This License does not grant any rights in the trademarks, service marks, or
-     logos of any Contributor (except as may be necessary to comply with the
-     notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-     No Contributor makes additional grants as a result of Your choice to
-     distribute the Covered Software under a subsequent version of this License
-     (see Section 10.2) or under the terms of a Secondary License (if permitted
-     under the terms of Section 3.3).
-
-2.5. Representation
-
-     Each Contributor represents that the Contributor believes its Contributions
-     are its original creation(s) or it has sufficient rights to grant the
-     rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-     This License is not intended to limit any rights You have under applicable
-     copyright doctrines of fair use, fair dealing, or other equivalents.
-
-2.7. Conditions
-
-     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
-     Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
-     All distribution of Covered Software in Source Code Form, including any
-     Modifications that You create or to which You contribute, must be under the
-     terms of this License. You must inform recipients that the Source Code Form
-     of the Covered Software is governed by the terms of this License, and how
-     they can obtain a copy of this License. You may not attempt to alter or
-     restrict the recipients’ rights in the Source Code Form.
-
-3.2. Distribution of Executable Form
-
-     If You distribute Covered Software in Executable Form then:
-
-     a. such Covered Software must also be made available in Source Code Form,
-        as described in Section 3.1, and You must inform recipients of the
-        Executable Form how they can obtain a copy of such Source Code Form by
-        reasonable means in a timely manner, at a charge no more than the cost
-        of distribution to the recipient; and
-
-     b. You may distribute such Executable Form under the terms of this License,
-        or sublicense it under different terms, provided that the license for
-        the Executable Form does not attempt to limit or alter the recipients’
-        rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-     You may create and distribute a Larger Work under terms of Your choice,
-     provided that You also comply with the requirements of this License for the
-     Covered Software. If the Larger Work is a combination of Covered Software
-     with a work governed by one or more Secondary Licenses, and the Covered
-     Software is not Incompatible With Secondary Licenses, this License permits
-     You to additionally distribute such Covered Software under the terms of
-     such Secondary License(s), so that the recipient of the Larger Work may, at
-     their option, further distribute the Covered Software under the terms of
-     either this License or such Secondary License(s).
-
-3.4. Notices
-
-     You may not remove or alter the substance of any license notices (including
-     copyright notices, patent notices, disclaimers of warranty, or limitations
-     of liability) contained within the Source Code Form of the Covered
-     Software, except that You may alter any license notices to the extent
-     required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-     You may choose to offer, and to charge a fee for, warranty, support,
-     indemnity or liability obligations to one or more recipients of Covered
-     Software. However, You may do so only on Your own behalf, and not on behalf
-     of any Contributor. You must make it absolutely clear that any such
-     warranty, support, indemnity, or liability obligation is offered by You
-     alone, and You hereby agree to indemnify every Contributor for any
-     liability incurred by such Contributor as a result of warranty, support,
-     indemnity or liability terms You offer. You may include additional
-     disclaimers of warranty and limitations of liability specific to any
-     jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
-   If it is impossible for You to comply with any of the terms of this License
-   with respect to some or all of the Covered Software due to statute, judicial
-   order, or regulation then You must: (a) comply with the terms of this License
-   to the maximum extent possible; and (b) describe the limitations and the code
-   they affect. Such description must be placed in a text file included with all
-   distributions of the Covered Software under this License. Except to the
-   extent prohibited by statute or regulation, such description must be
-   sufficiently detailed for a recipient of ordinary skill to be able to
-   understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
-     fail to comply with any of its terms. However, if You become compliant,
-     then the rights granted under this License from a particular Contributor
-     are reinstated (a) provisionally, unless and until such Contributor
-     explicitly and finally terminates Your grants, and (b) on an ongoing basis,
-     if such Contributor fails to notify You of the non-compliance by some
-     reasonable means prior to 60 days after You have come back into compliance.
-     Moreover, Your grants from a particular Contributor are reinstated on an
-     ongoing basis if such Contributor notifies You of the non-compliance by
-     some reasonable means, this is the first time You have received notice of
-     non-compliance with this License from such Contributor, and You become
-     compliant prior to 30 days after Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-     infringement claim (excluding declaratory judgment actions, counter-claims,
-     and cross-claims) alleging that a Contributor Version directly or
-     indirectly infringes any patent, then the rights granted to You by any and
-     all Contributors for the Covered Software under Section 2.1 of this License
-     shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
-     license agreements (excluding distributors and resellers) which have been
-     validly granted by You or Your distributors under this License prior to
-     termination shall survive termination.
-
-6. Disclaimer of Warranty
-
-   Covered Software is provided under this License on an “as is” basis, without
-   warranty of any kind, either expressed, implied, or statutory, including,
-   without limitation, warranties that the Covered Software is free of defects,
-   merchantable, fit for a particular purpose or non-infringing. The entire
-   risk as to the quality and performance of the Covered Software is with You.
-   Should any Covered Software prove defective in any respect, You (not any
-   Contributor) assume the cost of any necessary servicing, repair, or
-   correction. This disclaimer of warranty constitutes an essential part of this
-   License. No use of  any Covered Software is authorized under this License
-   except under this disclaimer.
-
-7. Limitation of Liability
-
-   Under no circumstances and under no legal theory, whether tort (including
-   negligence), contract, or otherwise, shall any Contributor, or anyone who
-   distributes Covered Software as permitted above, be liable to You for any
-   direct, indirect, special, incidental, or consequential damages of any
-   character including, without limitation, damages for lost profits, loss of
-   goodwill, work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses, even if such party shall have been
-   informed of the possibility of such damages. This limitation of liability
-   shall not apply to liability for death or personal injury resulting from such
-   party’s negligence to the extent applicable law prohibits such limitation.
-   Some jurisdictions do not allow the exclusion or limitation of incidental or
-   consequential damages, so this exclusion and limitation may not apply to You.
-
-8. Litigation
-
-   Any litigation relating to this License may be brought only in the courts of
-   a jurisdiction where the defendant maintains its principal place of business
-   and such litigation shall be governed by laws of that jurisdiction, without
-   reference to its conflict-of-law provisions. Nothing in this Section shall
-   prevent a party’s ability to bring cross-claims or counter-claims.
-
-9. Miscellaneous
-
-   This License represents the complete agreement concerning the subject matter
-   hereof. If any provision of this License is held to be unenforceable, such
-   provision shall be reformed only to the extent necessary to make it
-   enforceable. Any law or regulation which provides that the language of a
-   contract shall be construed against the drafter shall not be used to construe
-   this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
-      Mozilla Foundation is the license steward. Except as provided in Section
-      10.3, no one other than the license steward has the right to modify or
-      publish new versions of this License. Each version will be given a
-      distinguishing version number.
-
-10.2. Effect of New Versions
-
-      You may distribute the Covered Software under the terms of the version of
-      the License under which You originally received the Covered Software, or
-      under the terms of any subsequent version published by the license
-      steward.
-
-10.3. Modified Versions
-
-      If you create software not governed by this License, and you want to
-      create a new license for such software, you may create and use a modified
-      version of this License if you rename the license and remove any
-      references to the name of the license steward (except to note that such
-      modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
-      If You choose to distribute Source Code Form that is Incompatible With
-      Secondary Licenses under the terms of this version of the License, the
-      notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
-
-      This Source Code Form is subject to the
-      terms of the Mozilla Public License, v.
-      2.0. If a copy of the MPL was not
-      distributed with this file, You can
-      obtain one at
-      http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file, then
-You may include the notice in a location (such as a LICENSE file in a relevant
-directory) where a recipient would be likely to look for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - “Incompatible With Secondary Licenses” Notice
-
-      This Source Code Form is “Incompatible
-      With Secondary Licenses”, as defined by
-      the Mozilla Public License, v. 2.0.
-
diff --git a/notifier/vendor/github.com/hashicorp/hcl/Makefile b/notifier/vendor/github.com/hashicorp/hcl/Makefile
deleted file mode 100644
index 84fd743f..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TEST?=./...
-
-default: test
-
-fmt: generate
-	go fmt ./...
-
-test: generate
-	go get -t ./...
-	go test $(TEST) $(TESTARGS)
-
-generate:
-	go generate ./...
-
-updatedeps:
-	go get -u golang.org/x/tools/cmd/stringer
-
-.PHONY: default generate test updatedeps
diff --git a/notifier/vendor/github.com/hashicorp/hcl/README.md b/notifier/vendor/github.com/hashicorp/hcl/README.md
deleted file mode 100644
index c8223326..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/README.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# HCL
-
-[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl)
-
-HCL (HashiCorp Configuration Language) is a configuration language built
-by HashiCorp. The goal of HCL is to build a structured configuration language
-that is both human and machine friendly for use with command-line tools, but
-specifically targeted towards DevOps tools, servers, etc.
-
-HCL is also fully JSON compatible. That is, JSON can be used as completely
-valid input to a system expecting HCL. This helps makes systems
-interoperable with other systems.
-
-HCL is heavily inspired by
-[libucl](https://github.com/vstakhov/libucl),
-nginx configuration, and others similar.
-
-## Why?
-
-A common question when viewing HCL is to ask the question: why not
-JSON, YAML, etc.?
-
-Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com)
-used a variety of configuration languages from full programming languages
-such as Ruby to complete data structure languages such as JSON. What we
-learned is that some people wanted human-friendly configuration languages
-and some people wanted machine-friendly languages.
-
-JSON fits a nice balance in this, but is fairly verbose and most
-importantly doesn't support comments. With YAML, we found that beginners
-had a really hard time determining what the actual structure was, and
-ended up guessing more often than not whether to use a hyphen, colon, etc.
-in order to represent some configuration key.
-
-Full programming languages such as Ruby enable complex behavior
-a configuration language shouldn't usually allow, and also forces
-people to learn some set of Ruby.
-
-Because of this, we decided to create our own configuration language
-that is JSON-compatible. Our configuration language (HCL) is designed
-to be written and modified by humans. The API for HCL allows JSON
-as an input so that it is also machine-friendly (machines can generate
-JSON instead of trying to generate HCL).
-
-Our goal with HCL is not to alienate other configuration languages.
-It is instead to provide HCL as a specialized language for our tools,
-and JSON as the interoperability layer.
-
-## Syntax
-
-For a complete grammar, please see the parser itself. A high-level overview
-of the syntax and grammar is listed here.
-
-  * Single line comments start with `#` or `//`
-
-  * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments
-    are not allowed. A multi-line comment (also known as a block comment)
-    terminates at the first `*/` found.
-
-  * Values are assigned with the syntax `key = value` (whitespace doesn't
-    matter). The value can be any primitive: a string, number, boolean,
-    object, or list.
-
-  * Strings are double-quoted and can contain any UTF-8 characters.
-    Example: `"Hello, World"`
-
-  * Multi-line strings start with `<-
-    echo %Path%
-
-    go version
-
-    go env
-
-    go get -t ./...
-
-build_script:
-- cmd: go test -v ./...
diff --git a/notifier/vendor/github.com/hashicorp/hcl/decoder.go b/notifier/vendor/github.com/hashicorp/hcl/decoder.go
deleted file mode 100644
index bed9ebbe..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/decoder.go
+++ /dev/null
@@ -1,729 +0,0 @@
-package hcl
-
-import (
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// This is the tag to use with structures to have settings for HCL
-const tagName = "hcl"
-
-var (
-	// nodeType holds a reference to the type of ast.Node
-	nodeType reflect.Type = findNodeType()
-)
-
-// Unmarshal accepts a byte slice as input and writes the
-// data to the value pointed to by v.
-func Unmarshal(bs []byte, v interface{}) error {
-	root, err := parse(bs)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(v, root)
-}
-
-// Decode reads the given input and decodes it into the structure
-// given by `out`.
-func Decode(out interface{}, in string) error {
-	obj, err := Parse(in)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(out, obj)
-}
-
-// DecodeObject is a lower-level version of Decode. It decodes a
-// raw Object into the given output.
-func DecodeObject(out interface{}, n ast.Node) error {
-	val := reflect.ValueOf(out)
-	if val.Kind() != reflect.Ptr {
-		return errors.New("result must be a pointer")
-	}
-
-	// If we have the file, we really decode the root node
-	if f, ok := n.(*ast.File); ok {
-		n = f.Node
-	}
-
-	var d decoder
-	return d.decode("root", n, val.Elem())
-}
-
-type decoder struct {
-	stack []reflect.Kind
-}
-
-func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
-	k := result
-
-	// If we have an interface with a valid value, we use that
-	// for the check.
-	if result.Kind() == reflect.Interface {
-		elem := result.Elem()
-		if elem.IsValid() {
-			k = elem
-		}
-	}
-
-	// Push current onto stack unless it is an interface.
-	if k.Kind() != reflect.Interface {
-		d.stack = append(d.stack, k.Kind())
-
-		// Schedule a pop
-		defer func() {
-			d.stack = d.stack[:len(d.stack)-1]
-		}()
-	}
-
-	switch k.Kind() {
-	case reflect.Bool:
-		return d.decodeBool(name, node, result)
-	case reflect.Float32, reflect.Float64:
-		return d.decodeFloat(name, node, result)
-	case reflect.Int, reflect.Int32, reflect.Int64:
-		return d.decodeInt(name, node, result)
-	case reflect.Interface:
-		// When we see an interface, we make our own thing
-		return d.decodeInterface(name, node, result)
-	case reflect.Map:
-		return d.decodeMap(name, node, result)
-	case reflect.Ptr:
-		return d.decodePtr(name, node, result)
-	case reflect.Slice:
-		return d.decodeSlice(name, node, result)
-	case reflect.String:
-		return d.decodeString(name, node, result)
-	case reflect.Struct:
-		return d.decodeStruct(name, node, result)
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
-		}
-	}
-}
-
-func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.BOOL {
-			v, err := strconv.ParseBool(n.Token.Text)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
-			v, err := strconv.ParseFloat(n.Token.Text, 64)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			v, err := strconv.ParseInt(n.Token.Text, 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		case token.STRING:
-			v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
-	// When we see an ast.Node, we retain the value to enable deferred decoding.
-	// Very useful in situations where we want to preserve ast.Node information
-	// like Pos
-	if result.Type() == nodeType && result.CanSet() {
-		result.Set(reflect.ValueOf(node))
-		return nil
-	}
-
-	var set reflect.Value
-	redecode := true
-
-	// For testing types, ObjectType should just be treated as a list. We
-	// set this to a temporary var because we want to pass in the real node.
-	testNode := node
-	if ot, ok := node.(*ast.ObjectType); ok {
-		testNode = ot.List
-	}
-
-	switch n := testNode.(type) {
-	case *ast.ObjectList:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
-			set = result
-		}
-	case *ast.ObjectType:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
-			set = result
-		}
-	case *ast.ListType:
-		var temp []interface{}
-		tempVal := reflect.ValueOf(temp)
-		result := reflect.MakeSlice(
-			reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
-		set = result
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.BOOL:
-			var result bool
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.FLOAT:
-			var result float64
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.NUMBER:
-			var result int
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.STRING, token.HEREDOC:
-			set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
-		default:
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
-			}
-		}
-	default:
-		return fmt.Errorf(
-			"%s: cannot decode into interface: %T",
-			name, node)
-	}
-
-	// Set the result to what its supposed to be, then reset
-	// result so we don't reflect into this method anymore.
-	result.Set(set)
-
-	if redecode {
-		// Revisit the node so that we can use the newly instantiated
-		// thing and populate it.
-		if err := d.decode(name, node, result); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
-	if item, ok := node.(*ast.ObjectItem); ok {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	n, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
-		}
-	}
-
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	resultKeyType := resultType.Key()
-	if resultKeyType.Kind() != reflect.String {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: map must have string keys", name),
-		}
-	}
-
-	// Make a map if it is nil
-	resultMap := result
-	if result.IsNil() {
-		resultMap = reflect.MakeMap(
-			reflect.MapOf(resultKeyType, resultElemType))
-	}
-
-	// Go through each element and decode it.
-	done := make(map[string]struct{})
-	for _, item := range n.Items {
-		if item.Val == nil {
-			continue
-		}
-
-		// github.com/hashicorp/terraform/issue/5740
-		if len(item.Keys) == 0 {
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: map must have string keys", name),
-			}
-		}
-
-		// Get the key we're dealing with, which is the first item
-		keyStr := item.Keys[0].Token.Value().(string)
-
-		// If we've already processed this key, then ignore it
-		if _, ok := done[keyStr]; ok {
-			continue
-		}
-
-		// Determine the value. If we have more than one key, then we
-		// get the objectlist of only these keys.
-		itemVal := item.Val
-		if len(item.Keys) > 1 {
-			itemVal = n.Filter(keyStr)
-			done[keyStr] = struct{}{}
-		}
-
-		// Make the field name
-		fieldName := fmt.Sprintf("%s.%s", name, keyStr)
-
-		// Get the key/value as reflection values
-		key := reflect.ValueOf(keyStr)
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// If we have a pre-existing value in the map, use that
-		oldVal := resultMap.MapIndex(key)
-		if oldVal.IsValid() {
-			val.Set(oldVal)
-		}
-
-		// Decode!
-		if err := d.decode(fieldName, itemVal, val); err != nil {
-			return err
-		}
-
-		// Set the value on the map
-		resultMap.SetMapIndex(key, val)
-	}
-
-	// Set the final map if we can
-	set.Set(resultMap)
-	return nil
-}
-
-func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	val := reflect.New(resultElemType)
-	if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
-		return err
-	}
-
-	result.Set(val)
-	return nil
-}
-
-func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-	// Create the slice if it isn't nil
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	if result.IsNil() {
-		resultSliceType := reflect.SliceOf(resultElemType)
-		result = reflect.MakeSlice(
-			resultSliceType, 0, 0)
-	}
-
-	// Figure out the items we'll be copying into the slice
-	var items []ast.Node
-	switch n := node.(type) {
-	case *ast.ObjectList:
-		items = make([]ast.Node, len(n.Items))
-		for i, item := range n.Items {
-			items[i] = item
-		}
-	case *ast.ObjectType:
-		items = []ast.Node{n}
-	case *ast.ListType:
-		items = n.List
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("unknown slice type: %T", node),
-		}
-	}
-
-	for i, item := range items {
-		fieldName := fmt.Sprintf("%s[%d]", name, i)
-
-		// Decode
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// if item is an object that was decoded from ambiguous JSON and
-		// flattened, make sure it's expanded if it needs to decode into a
-		// defined structure.
-		item := expandObject(item, val)
-
-		if err := d.decode(fieldName, item, val); err != nil {
-			return err
-		}
-
-		// Append it onto the slice
-		result = reflect.Append(result, val)
-	}
-
-	set.Set(result)
-	return nil
-}
-
-// expandObject detects if an ambiguous JSON object was flattened to a List which
-// should be decoded into a struct, and expands the ast to properly deocode.
-func expandObject(node ast.Node, result reflect.Value) ast.Node {
-	item, ok := node.(*ast.ObjectItem)
-	if !ok {
-		return node
-	}
-
-	elemType := result.Type()
-
-	// our target type must be a struct
-	switch elemType.Kind() {
-	case reflect.Ptr:
-		switch elemType.Elem().Kind() {
-		case reflect.Struct:
-			//OK
-		default:
-			return node
-		}
-	case reflect.Struct:
-		//OK
-	default:
-		return node
-	}
-
-	// A list value will have a key and field name. If it had more fields,
-	// it wouldn't have been flattened.
-	if len(item.Keys) != 2 {
-		return node
-	}
-
-	keyToken := item.Keys[0].Token
-	item.Keys = item.Keys[1:]
-
-	// we need to un-flatten the ast enough to decode
-	newNode := &ast.ObjectItem{
-		Keys: []*ast.ObjectKey{
-			&ast.ObjectKey{
-				Token: keyToken,
-			},
-		},
-		Val: &ast.ObjectType{
-			List: &ast.ObjectList{
-				Items: []*ast.ObjectItem{item},
-			},
-		},
-	}
-
-	return newNode
-}
-
-func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
-			return nil
-		case token.STRING, token.HEREDOC:
-			result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type for string %T", name, node),
-	}
-}
-
-func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
-	var item *ast.ObjectItem
-	if it, ok := node.(*ast.ObjectItem); ok {
-		item = it
-		node = it.Val
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	// Handle the special case where the object itself is a literal. Previously
-	// the yacc parser would always ensure top-level elements were arrays. The new
-	// parser does not make the same guarantees, thus we need to convert any
-	// top-level literal elements into a list.
-	if _, ok := node.(*ast.LiteralType); ok && item != nil {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	list, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
-		}
-	}
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = result
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
-
-			// Ignore fields with tag name "-"
-			if tagParts[0] == "-" {
-				continue
-			}
-
-			if fieldType.Anonymous {
-				fieldKind := fieldType.Type.Kind()
-				if fieldKind != reflect.Struct {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: unsupported type to struct: %s",
-							fieldType.Name, fieldKind),
-					}
-				}
-
-				// We have an embedded field. We "squash" the fields down
-				// if specified in the tag.
-				squash := false
-				for _, tag := range tagParts[1:] {
-					if tag == "squash" {
-						squash = true
-						break
-					}
-				}
-
-				if squash {
-					structs = append(
-						structs, result.FieldByName(fieldType.Name))
-					continue
-				}
-			}
-
-			// Normal struct field, store it away
-			fields = append(fields, field{fieldType, structVal.Field(i)})
-		}
-	}
-
-	usedKeys := make(map[string]struct{})
-	decodedFields := make([]string, 0, len(fields))
-	decodedFieldsVal := make([]reflect.Value, 0)
-	unusedKeysVal := make([]reflect.Value, 0)
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(tagName)
-		tagParts := strings.SplitN(tagValue, ",", 2)
-		if len(tagParts) >= 2 {
-			switch tagParts[1] {
-			case "decodedFields":
-				decodedFieldsVal = append(decodedFieldsVal, fieldValue)
-				continue
-			case "key":
-				if item == nil {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: %s asked for 'key', impossible",
-							name, fieldName),
-					}
-				}
-
-				fieldValue.SetString(item.Keys[0].Token.Value().(string))
-				continue
-			case "unusedKeys":
-				unusedKeysVal = append(unusedKeysVal, fieldValue)
-				continue
-			}
-		}
-
-		if tagParts[0] != "" {
-			fieldName = tagParts[0]
-		}
-
-		// Determine the element we'll use to decode. If it is a single
-		// match (only object with the field), then we decode it exactly.
-		// If it is a prefix match, then we decode the matches.
-		filter := list.Filter(fieldName)
-
-		prefixMatches := filter.Children()
-		matches := filter.Elem()
-		if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
-			continue
-		}
-
-		// Track the used key
-		usedKeys[fieldName] = struct{}{}
-
-		// Create the field name and decode. We range over the elements
-		// because we actually want the value.
-		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
-		if len(prefixMatches.Items) > 0 {
-			if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
-				return err
-			}
-		}
-		for _, match := range matches.Items {
-			var decodeNode ast.Node = match.Val
-			if ot, ok := decodeNode.(*ast.ObjectType); ok {
-				decodeNode = &ast.ObjectList{Items: ot.List.Items}
-			}
-
-			if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
-				return err
-			}
-		}
-
-		decodedFields = append(decodedFields, field.Name)
-	}
-
-	if len(decodedFieldsVal) > 0 {
-		// Sort it so that it is deterministic
-		sort.Strings(decodedFields)
-
-		for _, v := range decodedFieldsVal {
-			v.Set(reflect.ValueOf(decodedFields))
-		}
-	}
-
-	return nil
-}
-
-// findNodeType returns the type of ast.Node
-func findNodeType() reflect.Type {
-	var nodeContainer struct {
-		Node ast.Node
-	}
-	value := reflect.ValueOf(nodeContainer).FieldByName("Node")
-	return value.Type()
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl.go b/notifier/vendor/github.com/hashicorp/hcl/hcl.go
deleted file mode 100644
index 575a20b5..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Package hcl decodes HCL into usable Go structures.
-//
-// hcl input can come in either pure HCL format or JSON format.
-// It can be parsed into an AST, and then decoded into a structure,
-// or it can be decoded directly from a string into a structure.
-//
-// If you choose to parse HCL into a raw AST, the benefit is that you
-// can write custom visitor implementations to implement custom
-// semantic checks. By default, HCL does not perform any semantic
-// checks.
-package hcl
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
deleted file mode 100644
index 6e5ef654..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package ast declares the types used to represent syntax trees for HCL
-// (HashiCorp Configuration Language)
-package ast
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// Node is an element in the abstract syntax tree.
-type Node interface {
-	node()
-	Pos() token.Pos
-}
-
-func (File) node()         {}
-func (ObjectList) node()   {}
-func (ObjectKey) node()    {}
-func (ObjectItem) node()   {}
-func (Comment) node()      {}
-func (CommentGroup) node() {}
-func (ObjectType) node()   {}
-func (LiteralType) node()  {}
-func (ListType) node()     {}
-
-// File represents a single HCL file
-type File struct {
-	Node     Node            // usually a *ObjectList
-	Comments []*CommentGroup // list of all comments in the source
-}
-
-func (f *File) Pos() token.Pos {
-	return f.Node.Pos()
-}
-
-// ObjectList represents a list of ObjectItems. An HCL file itself is an
-// ObjectList.
-type ObjectList struct {
-	Items []*ObjectItem
-}
-
-func (o *ObjectList) Add(item *ObjectItem) {
-	o.Items = append(o.Items, item)
-}
-
-// Filter filters out the objects with the given key list as a prefix.
-//
-// The returned list of objects contain ObjectItems where the keys have
-// this prefix already stripped off. This might result in objects with
-// zero-length key lists if they have no children.
-//
-// If no matches are found, an empty ObjectList (non-nil) is returned.
-func (o *ObjectList) Filter(keys ...string) *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		// If there aren't enough keys, then ignore this
-		if len(item.Keys) < len(keys) {
-			continue
-		}
-
-		match := true
-		for i, key := range item.Keys[:len(keys)] {
-			key := key.Token.Value().(string)
-			if key != keys[i] && !strings.EqualFold(key, keys[i]) {
-				match = false
-				break
-			}
-		}
-		if !match {
-			continue
-		}
-
-		// Strip off the prefix from the children
-		newItem := *item
-		newItem.Keys = newItem.Keys[len(keys):]
-		result.Add(&newItem)
-	}
-
-	return &result
-}
-
-// Children returns further nested objects (key length > 0) within this
-// ObjectList. This should be used with Filter to get at child items.
-func (o *ObjectList) Children() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) > 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-// Elem returns items in the list that are direct element assignments
-// (key length == 0). This should be used with Filter to get at elements.
-func (o *ObjectList) Elem() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) == 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-func (o *ObjectList) Pos() token.Pos {
-	// always returns the uninitiliazed position
-	return o.Items[0].Pos()
-}
-
-// ObjectItem represents a HCL Object Item. An item is represented with a key
-// (or keys). It can be an assignment or an object (both normal and nested)
-type ObjectItem struct {
-	// keys is only one length long if it's of type assignment. If it's a
-	// nested object it can be larger than one. In that case "assign" is
-	// invalid as there is no assignments for a nested object.
-	Keys []*ObjectKey
-
-	// assign contains the position of "=", if any
-	Assign token.Pos
-
-	// val is the item itself. It can be an object,list, number, bool or a
-	// string. If key length is larger than one, val can be only of type
-	// Object.
-	Val Node
-
-	LeadComment *CommentGroup // associated lead comment
-	LineComment *CommentGroup // associated line comment
-}
-
-func (o *ObjectItem) Pos() token.Pos {
-	// I'm not entirely sure what causes this, but removing this causes
-	// a test failure. We should investigate at some point.
-	if len(o.Keys) == 0 {
-		return token.Pos{}
-	}
-
-	return o.Keys[0].Pos()
-}
-
-// ObjectKeys are either an identifier or of type string.
-type ObjectKey struct {
-	Token token.Token
-}
-
-func (o *ObjectKey) Pos() token.Pos {
-	return o.Token.Pos
-}
-
-// LiteralType represents a literal of basic type. Valid types are:
-// token.NUMBER, token.FLOAT, token.BOOL and token.STRING
-type LiteralType struct {
-	Token token.Token
-
-	// comment types, only used when in a list
-	LeadComment *CommentGroup
-	LineComment *CommentGroup
-}
-
-func (l *LiteralType) Pos() token.Pos {
-	return l.Token.Pos
-}
-
-// ListStatement represents a HCL List type
-type ListType struct {
-	Lbrack token.Pos // position of "["
-	Rbrack token.Pos // position of "]"
-	List   []Node    // the elements in lexical order
-}
-
-func (l *ListType) Pos() token.Pos {
-	return l.Lbrack
-}
-
-func (l *ListType) Add(node Node) {
-	l.List = append(l.List, node)
-}
-
-// ObjectType represents a HCL Object Type
-type ObjectType struct {
-	Lbrace token.Pos   // position of "{"
-	Rbrace token.Pos   // position of "}"
-	List   *ObjectList // the nodes in lexical order
-}
-
-func (o *ObjectType) Pos() token.Pos {
-	return o.Lbrace
-}
-
-// Comment node represents a single //, # style or /*- style commment
-type Comment struct {
-	Start token.Pos // position of / or #
-	Text  string
-}
-
-func (c *Comment) Pos() token.Pos {
-	return c.Start
-}
-
-// CommentGroup node represents a sequence of comments with no other tokens and
-// no empty lines between.
-type CommentGroup struct {
-	List []*Comment // len(List) > 0
-}
-
-func (c *CommentGroup) Pos() token.Pos {
-	return c.List[0].Pos()
-}
-
-//-------------------------------------------------------------------
-// GoStringer
-//-------------------------------------------------------------------
-
-func (o *ObjectKey) GoString() string  { return fmt.Sprintf("*%#v", *o) }
-func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) }
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
deleted file mode 100644
index ba07ad42..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package ast
-
-import "fmt"
-
-// WalkFunc describes a function to be called for each node during a Walk. The
-// returned node can be used to rewrite the AST. Walking stops the returned
-// bool is false.
-type WalkFunc func(Node) (Node, bool)
-
-// Walk traverses an AST in depth-first order: It starts by calling fn(node);
-// node must not be nil. If fn returns true, Walk invokes fn recursively for
-// each of the non-nil children of node, followed by a call of fn(nil). The
-// returned node of fn can be used to rewrite the passed node to fn.
-func Walk(node Node, fn WalkFunc) Node {
-	rewritten, ok := fn(node)
-	if !ok {
-		return rewritten
-	}
-
-	switch n := node.(type) {
-	case *File:
-		n.Node = Walk(n.Node, fn)
-	case *ObjectList:
-		for i, item := range n.Items {
-			n.Items[i] = Walk(item, fn).(*ObjectItem)
-		}
-	case *ObjectKey:
-		// nothing to do
-	case *ObjectItem:
-		for i, k := range n.Keys {
-			n.Keys[i] = Walk(k, fn).(*ObjectKey)
-		}
-
-		if n.Val != nil {
-			n.Val = Walk(n.Val, fn)
-		}
-	case *LiteralType:
-		// nothing to do
-	case *ListType:
-		for i, l := range n.List {
-			n.List[i] = Walk(l, fn)
-		}
-	case *ObjectType:
-		n.List = Walk(n.List, fn).(*ObjectList)
-	default:
-		// should we panic here?
-		fmt.Printf("unknown type: %T\n", n)
-	}
-
-	fn(nil)
-	return rewritten
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
deleted file mode 100644
index 5c99381d..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package parser
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// PosError is a parse error that contains a position.
-type PosError struct {
-	Pos token.Pos
-	Err error
-}
-
-func (e *PosError) Error() string {
-	return fmt.Sprintf("At %s: %s", e.Pos, e.Err)
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
deleted file mode 100644
index 64c83bcf..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
+++ /dev/null
@@ -1,532 +0,0 @@
-// Package parser implements a parser for HCL (HashiCorp Configuration
-// Language)
-package parser
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/scanner"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	comments    []*ast.CommentGroup
-	leadComment *ast.CommentGroup // last lead comment
-	lineComment *ast.CommentGroup // last line comment
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	// normalize all line endings
-	// since the scanner and output only work with "\n" line endings, we may
-	// end up with dangling "\r" characters in the parsed data.
-	src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1)
-
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = &PosError{Pos: pos, Err: errors.New(msg)}
-	}
-
-	f.Node, err = p.objectList(false)
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	f.Comments = p.comments
-	return f, nil
-}
-
-// objectList parses a list of items within an object (generally k/v pairs).
-// The parameter" obj" tells this whether to we are within an object (braces:
-// '{', '}') or just at the top level. If we're within an object, we end
-// at an RBRACE.
-func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		if obj {
-			tok := p.scan()
-			p.unscan()
-			if tok.Type == token.RBRACE {
-				break
-			}
-		}
-
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// object lists can be optionally comma-delimited e.g. when a list of maps
-		// is being expressed, so a comma is allowed here - it's simply consumed
-		tok := p.scan()
-		if tok.Type != token.COMMA {
-			p.unscan()
-		}
-	}
-	return node, nil
-}
-
-func (p *Parser) consumeComment() (comment *ast.Comment, endline int) {
-	endline = p.tok.Pos.Line
-
-	// count the endline if it's multiline comment, ie starting with /*
-	if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' {
-		// don't use range here - no need to decode Unicode code points
-		for i := 0; i < len(p.tok.Text); i++ {
-			if p.tok.Text[i] == '\n' {
-				endline++
-			}
-		}
-	}
-
-	comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text}
-	p.tok = p.sc.Scan()
-	return
-}
-
-func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
-	var list []*ast.Comment
-	endline = p.tok.Pos.Line
-
-	for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n {
-		var comment *ast.Comment
-		comment, endline = p.consumeComment()
-		list = append(list, comment)
-	}
-
-	// add comment group to the comments list
-	comments = &ast.CommentGroup{List: list}
-	p.comments = append(p.comments, comments)
-
-	return
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if len(keys) > 0 && err == errEofToken {
-		// We ignore eof token here since it is an error if we didn't
-		// receive a value (but we did receive a key) for the item.
-		err = nil
-	}
-	if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE {
-		// This is a strange boolean statement, but what it means is:
-		// We have keys with no value, and we're likely in an object
-		// (since RBrace ends an object). For this, we set err to nil so
-		// we continue and get the error below of having the wrong value
-		// type.
-		err = nil
-
-		// Reset the token type so we don't think it completed fine. See
-		// objectType which uses p.tok.Type to check if we're done with
-		// the object.
-		p.tok.Type = token.EOF
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	if p.leadComment != nil {
-		o.LeadComment = p.leadComment
-		p.leadComment = nil
-	}
-
-	switch p.tok.Type {
-	case token.ASSIGN:
-		o.Assign = p.tok.Pos
-		o.Val, err = p.object()
-		if err != nil {
-			return nil, err
-		}
-	case token.LBRACE:
-		o.Val, err = p.objectType()
-		if err != nil {
-			return nil, err
-		}
-	default:
-		keyStr := make([]string, 0, len(keys))
-		for _, k := range keys {
-			keyStr = append(keyStr, k.Token.Text)
-		}
-
-		return nil, &PosError{
-			Pos: p.tok.Pos,
-			Err: fmt.Errorf(
-				"key '%s' expected start of object ('{') or assignment ('=')",
-				strings.Join(keyStr, " ")),
-		}
-	}
-
-	// key=#comment
-	// val
-	if p.lineComment != nil {
-		o.LineComment, p.lineComment = p.lineComment, nil
-	}
-
-	// do a look-ahead for line comment
-	p.scan()
-	if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil {
-		o.LineComment = p.lineComment
-		p.lineComment = nil
-	}
-	p.unscan()
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			// It is very important to also return the keys here as well as
-			// the error. This is because we need to be able to tell if we
-			// did parse keys prior to finding the EOF, or if we just found
-			// a bare EOF.
-			return keys, errEofToken
-		case token.ASSIGN:
-			// assignment or object only, but not nested objects. this is not
-			// allowed: `foo bar = {}`
-			if keyCount > 1 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type),
-				}
-			}
-
-			if keyCount == 0 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: errors.New("no object keys found!"),
-				}
-			}
-
-			return keys, nil
-		case token.LBRACE:
-			var err error
-
-			// If we have no keys, then it is a syntax error. i.e. {{}} is not
-			// allowed.
-			if len(keys) == 0 {
-				err = &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type),
-				}
-			}
-
-			// object
-			return keys, err
-		case token.IDENT, token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{Token: p.tok})
-		case token.ILLEGAL:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("illegal character"),
-			}
-		default:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type),
-			}
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (ast.Node, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.COMMENT:
-		// implement comment
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, &PosError{
-		Pos: tok.Pos,
-		Err: fmt.Errorf("Unknown token: %+v", tok),
-	}
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{
-		Lbrace: p.tok.Pos,
-	}
-
-	l, err := p.objectList(true)
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	// No error, scan and expect the ending to be a brace
-	if tok := p.scan(); tok.Type != token.RBRACE {
-		return nil, &PosError{
-			Pos: tok.Pos,
-			Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type),
-		}
-	}
-
-	o.List = l
-	o.Rbrace = p.tok.Pos // advanced via parseObjectList
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{
-		Lbrack: p.tok.Pos,
-	}
-
-	needComma := false
-	for {
-		tok := p.scan()
-		if needComma {
-			switch tok.Type {
-			case token.COMMA, token.RBRACK:
-			default:
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error parsing list, expected comma or list end, got: %s",
-						tok.Type),
-				}
-			}
-		}
-		switch tok.Type {
-		case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			// If there is a lead comment, apply it
-			if p.leadComment != nil {
-				node.LeadComment = p.leadComment
-				p.leadComment = nil
-			}
-
-			l.Add(node)
-			needComma = true
-		case token.COMMA:
-			// get next list item or we are at the end
-			// do a look-ahead for line comment
-			p.scan()
-			if p.lineComment != nil && len(l.List) > 0 {
-				lit, ok := l.List[len(l.List)-1].(*ast.LiteralType)
-				if ok {
-					lit.LineComment = p.lineComment
-					l.List[len(l.List)-1] = lit
-					p.lineComment = nil
-				}
-			}
-			p.unscan()
-
-			needComma = false
-			continue
-		case token.LBRACE:
-			// Looks like a nested object, so parse it out
-			node, err := p.objectType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse object within list: %s", err),
-				}
-			}
-			l.Add(node)
-			needComma = true
-		case token.LBRACK:
-			node, err := p.listType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse list within list: %s", err),
-				}
-			}
-			l.Add(node)
-		case token.RBRACK:
-			// finished
-			l.Rbrack = p.tok.Pos
-			return l, nil
-		default:
-			return nil, &PosError{
-				Pos: tok.Pos,
-				Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type),
-			}
-		}
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok,
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead. In the process, it collects any
-// comment groups encountered, and remembers the last lead and line comments.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	// Otherwise read the next token from the scanner and Save it to the buffer
-	// in case we unscan later.
-	prev := p.tok
-	p.tok = p.sc.Scan()
-
-	if p.tok.Type == token.COMMENT {
-		var comment *ast.CommentGroup
-		var endline int
-
-		// fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n",
-		// p.tok.Pos.Line, prev.Pos.Line, endline)
-		if p.tok.Pos.Line == prev.Pos.Line {
-			// The comment is on same line as the previous token; it
-			// cannot be a lead comment but may be a line comment.
-			comment, endline = p.consumeCommentGroup(0)
-			if p.tok.Pos.Line != endline {
-				// The next token is on a different line, thus
-				// the last comment group is a line comment.
-				p.lineComment = comment
-			}
-		}
-
-		// consume successor comments, if any
-		endline = -1
-		for p.tok.Type == token.COMMENT {
-			comment, endline = p.consumeCommentGroup(1)
-		}
-
-		if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE {
-			switch p.tok.Type {
-			case token.RBRACE, token.RBRACK:
-				// Do not count for these cases
-			default:
-				// The next token is following on the line immediately after the
-				// comment group, thus the last comment group is a lead comment.
-				p.leadComment = comment
-			}
-		}
-
-	}
-
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
deleted file mode 100644
index 7c038d12..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
+++ /dev/null
@@ -1,789 +0,0 @@
-package printer
-
-import (
-	"bytes"
-	"fmt"
-	"sort"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-const (
-	blank    = byte(' ')
-	newline  = byte('\n')
-	tab      = byte('\t')
-	infinity = 1 << 30 // offset or line
-)
-
-var (
-	unindent = []byte("\uE123") // in the private use space
-)
-
-type printer struct {
-	cfg  Config
-	prev token.Pos
-
-	comments           []*ast.CommentGroup // may be nil, contains all comments
-	standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node)
-
-	enableTrace bool
-	indentTrace int
-}
-
-type ByPosition []*ast.CommentGroup
-
-func (b ByPosition) Len() int           { return len(b) }
-func (b ByPosition) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
-func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) }
-
-// collectComments comments all standalone comments which are not lead or line
-// comment
-func (p *printer) collectComments(node ast.Node) {
-	// first collect all comments. This is already stored in
-	// ast.File.(comments)
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.File:
-			p.comments = t.Comments
-			return nn, false
-		}
-		return nn, true
-	})
-
-	standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0)
-	for _, c := range p.comments {
-		standaloneComments[c.Pos()] = c
-	}
-
-	// next remove all lead and line comments from the overall comment map.
-	// This will give us comments which are standalone, comments which are not
-	// assigned to any kind of node.
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.LiteralType:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		case *ast.ObjectItem:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		}
-
-		return nn, true
-	})
-
-	for _, c := range standaloneComments {
-		p.standaloneComments = append(p.standaloneComments, c)
-	}
-
-	sort.Sort(ByPosition(p.standaloneComments))
-}
-
-// output prints creates b printable HCL output and returns it.
-func (p *printer) output(n interface{}) []byte {
-	var buf bytes.Buffer
-
-	switch t := n.(type) {
-	case *ast.File:
-		// File doesn't trace so we add the tracing here
-		defer un(trace(p, "File"))
-		return p.output(t.Node)
-	case *ast.ObjectList:
-		defer un(trace(p, "ObjectList"))
-
-		var index int
-		for {
-			// Determine the location of the next actual non-comment
-			// item. If we're at the end, the next item is at "infinity"
-			var nextItem token.Pos
-			if index != len(t.Items) {
-				nextItem = t.Items[index].Pos()
-			} else {
-				nextItem = token.Pos{Offset: infinity, Line: infinity}
-			}
-
-			// Go through the standalone comments in the file and print out
-			// the comments that we should be for this object item.
-			for _, c := range p.standaloneComments {
-				// Go through all the comments in the group. The group
-				// should be printed together, not separated by double newlines.
-				printed := false
-				newlinePrinted := false
-				for _, comment := range c.List {
-					// We only care about comments after the previous item
-					// we've printed so that comments are printed in the
-					// correct locations (between two objects for example).
-					// And before the next item.
-					if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-						// if we hit the end add newlines so we can print the comment
-						// we don't do this if prev is invalid which means the
-						// beginning of the file since the first comment should
-						// be at the first line.
-						if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) {
-							buf.Write([]byte{newline, newline})
-							newlinePrinted = true
-						}
-
-						// Write the actual comment.
-						buf.WriteString(comment.Text)
-						buf.WriteByte(newline)
-
-						// Set printed to true to note that we printed something
-						printed = true
-					}
-				}
-
-				// If we're not at the last item, write a new line so
-				// that there is a newline separating this comment from
-				// the next object.
-				if printed && index != len(t.Items) {
-					buf.WriteByte(newline)
-				}
-			}
-
-			if index == len(t.Items) {
-				break
-			}
-
-			buf.Write(p.output(t.Items[index]))
-			if index != len(t.Items)-1 {
-				// Always write a newline to separate us from the next item
-				buf.WriteByte(newline)
-
-				// Need to determine if we're going to separate the next item
-				// with a blank line. The logic here is simple, though there
-				// are a few conditions:
-				//
-				//   1. The next object is more than one line away anyways,
-				//      so we need an empty line.
-				//
-				//   2. The next object is not a "single line" object, so
-				//      we need an empty line.
-				//
-				//   3. This current object is not a single line object,
-				//      so we need an empty line.
-				current := t.Items[index]
-				next := t.Items[index+1]
-				if next.Pos().Line != t.Items[index].Pos().Line+1 ||
-					!p.isSingleLineObject(next) ||
-					!p.isSingleLineObject(current) {
-					buf.WriteByte(newline)
-				}
-			}
-			index++
-		}
-	case *ast.ObjectKey:
-		buf.WriteString(t.Token.Text)
-	case *ast.ObjectItem:
-		p.prev = t.Pos()
-		buf.Write(p.objectItem(t))
-	case *ast.LiteralType:
-		buf.Write(p.literalType(t))
-	case *ast.ListType:
-		buf.Write(p.list(t))
-	case *ast.ObjectType:
-		buf.Write(p.objectType(t))
-	default:
-		fmt.Printf(" unknown type: %T\n", n)
-	}
-
-	return buf.Bytes()
-}
-
-func (p *printer) literalType(lit *ast.LiteralType) []byte {
-	result := []byte(lit.Token.Text)
-	switch lit.Token.Type {
-	case token.HEREDOC:
-		// Clear the trailing newline from heredocs
-		if result[len(result)-1] == '\n' {
-			result = result[:len(result)-1]
-		}
-
-		// Poison lines 2+ so that we don't indent them
-		result = p.heredocIndent(result)
-	case token.STRING:
-		// If this is a multiline string, poison lines 2+ so we don't
-		// indent them.
-		if bytes.IndexRune(result, '\n') >= 0 {
-			result = p.heredocIndent(result)
-		}
-	}
-
-	return result
-}
-
-// objectItem returns the printable HCL form of an object item. An object type
-// starts with one/multiple keys and has a value. The value might be of any
-// type.
-func (p *printer) objectItem(o *ast.ObjectItem) []byte {
-	defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text)))
-	var buf bytes.Buffer
-
-	if o.LeadComment != nil {
-		for _, comment := range o.LeadComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	// If key and val are on different lines, treat line comments like lead comments.
-	if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line {
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	for i, k := range o.Keys {
-		buf.WriteString(k.Token.Text)
-		buf.WriteByte(blank)
-
-		// reach end of key
-		if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 {
-			buf.WriteString("=")
-			buf.WriteByte(blank)
-		}
-	}
-
-	buf.Write(p.output(o.Val))
-
-	if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line {
-		buf.WriteByte(blank)
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// objectType returns the printable HCL form of an object type. An object type
-// begins with a brace and ends with a brace.
-func (p *printer) objectType(o *ast.ObjectType) []byte {
-	defer un(trace(p, "ObjectType"))
-	var buf bytes.Buffer
-	buf.WriteString("{")
-
-	var index int
-	var nextItem token.Pos
-	var commented, newlinePrinted bool
-	for {
-		// Determine the location of the next actual non-comment
-		// item. If we're at the end, the next item is the closing brace
-		if index != len(o.List.Items) {
-			nextItem = o.List.Items[index].Pos()
-		} else {
-			nextItem = o.Rbrace
-		}
-
-		// Go through the standalone comments in the file and print out
-		// the comments that we should be for this object item.
-		for _, c := range p.standaloneComments {
-			printed := false
-			var lastCommentPos token.Pos
-			for _, comment := range c.List {
-				// We only care about comments after the previous item
-				// we've printed so that comments are printed in the
-				// correct locations (between two objects for example).
-				// And before the next item.
-				if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-					// If there are standalone comments and the initial newline has not
-					// been printed yet, do it now.
-					if !newlinePrinted {
-						newlinePrinted = true
-						buf.WriteByte(newline)
-					}
-
-					// add newline if it's between other printed nodes
-					if index > 0 {
-						commented = true
-						buf.WriteByte(newline)
-					}
-
-					// Store this position
-					lastCommentPos = comment.Pos()
-
-					// output the comment itself
-					buf.Write(p.indent(p.heredocIndent([]byte(comment.Text))))
-
-					// Set printed to true to note that we printed something
-					printed = true
-
-					/*
-						if index != len(o.List.Items) {
-							buf.WriteByte(newline) // do not print on the end
-						}
-					*/
-				}
-			}
-
-			// Stuff to do if we had comments
-			if printed {
-				// Always write a newline
-				buf.WriteByte(newline)
-
-				// If there is another item in the object and our comment
-				// didn't hug it directly, then make sure there is a blank
-				// line separating them.
-				if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 {
-					buf.WriteByte(newline)
-				}
-			}
-		}
-
-		if index == len(o.List.Items) {
-			p.prev = o.Rbrace
-			break
-		}
-
-		// At this point we are sure that it's not a totally empty block: print
-		// the initial newline if it hasn't been printed yet by the previous
-		// block about standalone comments.
-		if !newlinePrinted {
-			buf.WriteByte(newline)
-			newlinePrinted = true
-		}
-
-		// check if we have adjacent one liner items. If yes we'll going to align
-		// the comments.
-		var aligned []*ast.ObjectItem
-		for _, item := range o.List.Items[index:] {
-			// we don't group one line lists
-			if len(o.List.Items) == 1 {
-				break
-			}
-
-			// one means a oneliner with out any lead comment
-			// two means a oneliner with lead comment
-			// anything else might be something else
-			cur := lines(string(p.objectItem(item)))
-			if cur > 2 {
-				break
-			}
-
-			curPos := item.Pos()
-
-			nextPos := token.Pos{}
-			if index != len(o.List.Items)-1 {
-				nextPos = o.List.Items[index+1].Pos()
-			}
-
-			prevPos := token.Pos{}
-			if index != 0 {
-				prevPos = o.List.Items[index-1].Pos()
-			}
-
-			// fmt.Println("DEBUG ----------------")
-			// fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos)
-			// fmt.Printf("cur = %+v curPos: %s\n", cur, curPos)
-			// fmt.Printf("next = %+v nextPos: %s\n", next, nextPos)
-
-			if curPos.Line+1 == nextPos.Line {
-				aligned = append(aligned, item)
-				index++
-				continue
-			}
-
-			if curPos.Line-1 == prevPos.Line {
-				aligned = append(aligned, item)
-				index++
-
-				// finish if we have a new line or comment next. This happens
-				// if the next item is not adjacent
-				if curPos.Line+1 != nextPos.Line {
-					break
-				}
-				continue
-			}
-
-			break
-		}
-
-		// put newlines if the items are between other non aligned items.
-		// newlines are also added if there is a standalone comment already, so
-		// check it too
-		if !commented && index != len(aligned) {
-			buf.WriteByte(newline)
-		}
-
-		if len(aligned) >= 1 {
-			p.prev = aligned[len(aligned)-1].Pos()
-
-			items := p.alignedItems(aligned)
-			buf.Write(p.indent(items))
-		} else {
-			p.prev = o.List.Items[index].Pos()
-
-			buf.Write(p.indent(p.objectItem(o.List.Items[index])))
-			index++
-		}
-
-		buf.WriteByte(newline)
-	}
-
-	buf.WriteString("}")
-	return buf.Bytes()
-}
-
-func (p *printer) alignedItems(items []*ast.ObjectItem) []byte {
-	var buf bytes.Buffer
-
-	// find the longest key and value length, needed for alignment
-	var longestKeyLen int // longest key length
-	var longestValLen int // longest value length
-	for _, item := range items {
-		key := len(item.Keys[0].Token.Text)
-		val := len(p.output(item.Val))
-
-		if key > longestKeyLen {
-			longestKeyLen = key
-		}
-
-		if val > longestValLen {
-			longestValLen = val
-		}
-	}
-
-	for i, item := range items {
-		if item.LeadComment != nil {
-			for _, comment := range item.LeadComment.List {
-				buf.WriteString(comment.Text)
-				buf.WriteByte(newline)
-			}
-		}
-
-		for i, k := range item.Keys {
-			keyLen := len(k.Token.Text)
-			buf.WriteString(k.Token.Text)
-			for i := 0; i < longestKeyLen-keyLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			// reach end of key
-			if i == len(item.Keys)-1 && len(item.Keys) == 1 {
-				buf.WriteString("=")
-				buf.WriteByte(blank)
-			}
-		}
-
-		val := p.output(item.Val)
-		valLen := len(val)
-		buf.Write(val)
-
-		if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil {
-			for i := 0; i < longestValLen-valLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range item.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		// do not print for the last item
-		if i != len(items)-1 {
-			buf.WriteByte(newline)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// list returns the printable HCL form of an list type.
-func (p *printer) list(l *ast.ListType) []byte {
-	if p.isSingleLineList(l) {
-		return p.singleLineList(l)
-	}
-
-	var buf bytes.Buffer
-	buf.WriteString("[")
-	buf.WriteByte(newline)
-
-	var longestLine int
-	for _, item := range l.List {
-		// for now we assume that the list only contains literal types
-		if lit, ok := item.(*ast.LiteralType); ok {
-			lineLen := len(lit.Token.Text)
-			if lineLen > longestLine {
-				longestLine = lineLen
-			}
-		}
-	}
-
-	haveEmptyLine := false
-	for i, item := range l.List {
-		// If we have a lead comment, then we want to write that first
-		leadComment := false
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil {
-			leadComment = true
-
-			// Ensure an empty line before every element with a
-			// lead comment (except the first item in a list).
-			if !haveEmptyLine && i != 0 {
-				buf.WriteByte(newline)
-			}
-
-			for _, comment := range lit.LeadComment.List {
-				buf.Write(p.indent([]byte(comment.Text)))
-				buf.WriteByte(newline)
-			}
-		}
-
-		// also indent each line
-		val := p.output(item)
-		curLen := len(val)
-		buf.Write(p.indent(val))
-
-		// if this item is a heredoc, then we output the comma on
-		// the next line. This is the only case this happens.
-		comma := []byte{','}
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-			comma = p.indent(comma)
-		}
-
-		buf.Write(comma)
-
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil {
-			// if the next item doesn't have any comments, do not align
-			buf.WriteByte(blank) // align one space
-			for i := 0; i < longestLine-curLen; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range lit.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		buf.WriteByte(newline)
-
-		// Ensure an empty line after every element with a
-		// lead comment (except the first item in a list).
-		haveEmptyLine = leadComment && i != len(l.List)-1
-		if haveEmptyLine {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// isSingleLineList returns true if:
-// * they were previously formatted entirely on one line
-// * they consist entirely of literals
-// * there are either no heredoc strings or the list has exactly one element
-// * there are no line comments
-func (printer) isSingleLineList(l *ast.ListType) bool {
-	for _, item := range l.List {
-		if item.Pos().Line != l.Lbrack.Line {
-			return false
-		}
-
-		lit, ok := item.(*ast.LiteralType)
-		if !ok {
-			return false
-		}
-
-		if lit.Token.Type == token.HEREDOC && len(l.List) != 1 {
-			return false
-		}
-
-		if lit.LineComment != nil {
-			return false
-		}
-	}
-
-	return true
-}
-
-// singleLineList prints a simple single line list.
-// For a definition of "simple", see isSingleLineList above.
-func (p *printer) singleLineList(l *ast.ListType) []byte {
-	buf := &bytes.Buffer{}
-
-	buf.WriteString("[")
-	for i, item := range l.List {
-		if i != 0 {
-			buf.WriteString(", ")
-		}
-
-		// Output the item itself
-		buf.Write(p.output(item))
-
-		// The heredoc marker needs to be at the end of line.
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// indent indents the lines of the given buffer for each non-empty line
-func (p *printer) indent(buf []byte) []byte {
-	var prefix []byte
-	if p.cfg.SpacesWidth != 0 {
-		for i := 0; i < p.cfg.SpacesWidth; i++ {
-			prefix = append(prefix, blank)
-		}
-	} else {
-		prefix = []byte{tab}
-	}
-
-	var res []byte
-	bol := true
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, prefix...)
-		}
-
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// unindent removes all the indentation from the tombstoned lines
-func (p *printer) unindent(buf []byte) []byte {
-	var res []byte
-	for i := 0; i < len(buf); i++ {
-		skip := len(buf)-i <= len(unindent)
-		if !skip {
-			skip = !bytes.Equal(unindent, buf[i:i+len(unindent)])
-		}
-		if skip {
-			res = append(res, buf[i])
-			continue
-		}
-
-		// We have a marker. we have to backtrace here and clean out
-		// any whitespace ahead of our tombstone up to a \n
-		for j := len(res) - 1; j >= 0; j-- {
-			if res[j] == '\n' {
-				break
-			}
-
-			res = res[:j]
-		}
-
-		// Skip the entire unindent marker
-		i += len(unindent) - 1
-	}
-
-	return res
-}
-
-// heredocIndent marks all the 2nd and further lines as unindentable
-func (p *printer) heredocIndent(buf []byte) []byte {
-	var res []byte
-	bol := false
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, unindent...)
-		}
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// isSingleLineObject tells whether the given object item is a single
-// line object such as "obj {}".
-//
-// A single line object:
-//
-//   * has no lead comments (hence multi-line)
-//   * has no assignment
-//   * has no values in the stanza (within {})
-//
-func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool {
-	// If there is a lead comment, can't be one line
-	if val.LeadComment != nil {
-		return false
-	}
-
-	// If there is assignment, we always break by line
-	if val.Assign.IsValid() {
-		return false
-	}
-
-	// If it isn't an object type, then its not a single line object
-	ot, ok := val.Val.(*ast.ObjectType)
-	if !ok {
-		return false
-	}
-
-	// If the object has no items, it is single line!
-	return len(ot.List.Items) == 0
-}
-
-func lines(txt string) int {
-	endline := 1
-	for i := 0; i < len(txt); i++ {
-		if txt[i] == '\n' {
-			endline++
-		}
-	}
-	return endline
-}
-
-// ----------------------------------------------------------------------------
-// Tracing support
-
-func (p *printer) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	i := 2 * p.indentTrace
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *printer, msg string) *printer {
-	p.printTrace(msg, "(")
-	p.indentTrace++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *printer) {
-	p.indentTrace--
-	p.printTrace(")")
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
deleted file mode 100644
index 6617ab8e..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Package printer implements printing of AST nodes to HCL format.
-package printer
-
-import (
-	"bytes"
-	"io"
-	"text/tabwriter"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-)
-
-var DefaultConfig = Config{
-	SpacesWidth: 2,
-}
-
-// A Config node controls the output of Fprint.
-type Config struct {
-	SpacesWidth int // if set, it will use spaces instead of tabs for alignment
-}
-
-func (c *Config) Fprint(output io.Writer, node ast.Node) error {
-	p := &printer{
-		cfg:                *c,
-		comments:           make([]*ast.CommentGroup, 0),
-		standaloneComments: make([]*ast.CommentGroup, 0),
-		// enableTrace:        true,
-	}
-
-	p.collectComments(node)
-
-	if _, err := output.Write(p.unindent(p.output(node))); err != nil {
-		return err
-	}
-
-	// flush tabwriter, if any
-	var err error
-	if tw, _ := output.(*tabwriter.Writer); tw != nil {
-		err = tw.Flush()
-	}
-
-	return err
-}
-
-// Fprint "pretty-prints" an HCL node to output
-// It calls Config.Fprint with default settings.
-func Fprint(output io.Writer, node ast.Node) error {
-	return DefaultConfig.Fprint(output, node)
-}
-
-// Format formats src HCL and returns the result.
-func Format(src []byte) ([]byte, error) {
-	node, err := parser.Parse(src)
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-	if err := DefaultConfig.Fprint(&buf, node); err != nil {
-		return nil, err
-	}
-
-	// Add trailing newline to result
-	buf.WriteString("\n")
-	return buf.Bytes(), nil
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
deleted file mode 100644
index 624a18fe..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
+++ /dev/null
@@ -1,652 +0,0 @@
-// Package scanner implements a scanner for HCL (HashiCorp Configuration
-// Language) source text.
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"regexp"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == utf8.RuneError && size == 1 {
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	if ch == '\x00' {
-		s.err("unexpected null character (0x00)")
-		return eof
-	}
-
-	if ch == '\uE123' {
-		s.err("unicode code point U+E123 reserved for internal use")
-		return utf8.RuneError
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		tok = token.IDENT
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '#', '/':
-			tok = token.COMMENT
-			s.scanComment(ch)
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '<':
-			tok = token.HEREDOC
-			s.scanHeredoc()
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case '=':
-			tok = token.ASSIGN
-		case '+':
-			tok = token.ADD
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				tok = token.SUB
-			}
-		default:
-			s.err("illegal char")
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-func (s *Scanner) scanComment(ch rune) {
-	// single line comments
-	if ch == '#' || (ch == '/' && s.peek() != '*') {
-		if ch == '/' && s.peek() != '/' {
-			s.err("expected '/' for comment")
-			return
-		}
-
-		ch = s.next()
-		for ch != '\n' && ch >= 0 && ch != eof {
-			ch = s.next()
-		}
-		if ch != eof && ch >= 0 {
-			s.unread()
-		}
-		return
-	}
-
-	// be sure we get the character after /* This allows us to find comment's
-	// that are not erminated
-	if ch == '/' {
-		s.next()
-		ch = s.next() // read character after "/*"
-	}
-
-	// look for /* - style comments
-	for {
-		if ch < 0 || ch == eof {
-			s.err("comment not terminated")
-			break
-		}
-
-		ch0 := ch
-		ch = s.next()
-		if ch0 == '*' && ch == '/' {
-			break
-		}
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	if ch == '0' {
-		// check for hexadecimal, octal or float
-		ch = s.next()
-		if ch == 'x' || ch == 'X' {
-			// hexadecimal
-			ch = s.next()
-			found := false
-			for isHexadecimal(ch) {
-				ch = s.next()
-				found = true
-			}
-
-			if !found {
-				s.err("illegal hexadecimal number")
-			}
-
-			if ch != eof {
-				s.unread()
-			}
-
-			return token.NUMBER
-		}
-
-		// now it's either something like: 0421(octal) or 0.1231(float)
-		illegalOctal := false
-		for isDecimal(ch) {
-			ch = s.next()
-			if ch == '8' || ch == '9' {
-				// this is just a possibility. For example 0159 is illegal, but
-				// 0159.23 is valid. So we mark a possible illegal octal. If
-				// the next character is not a period, we'll print the error.
-				illegalOctal = true
-			}
-		}
-
-		if ch == 'e' || ch == 'E' {
-			ch = s.scanExponent(ch)
-			return token.FLOAT
-		}
-
-		if ch == '.' {
-			ch = s.scanFraction(ch)
-
-			if ch == 'e' || ch == 'E' {
-				ch = s.next()
-				ch = s.scanExponent(ch)
-			}
-			return token.FLOAT
-		}
-
-		if illegalOctal {
-			s.err("illegal octal number")
-		}
-
-		if ch != eof {
-			s.unread()
-		}
-		return token.NUMBER
-	}
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanHeredoc scans a heredoc string
-func (s *Scanner) scanHeredoc() {
-	// Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) {
-				break
-			}
-
-			// Not an anchor match, record the start of a new line
-			lineStart = s.srcPos.Offset
-		}
-
-		if ch == eof {
-			s.err("heredoc not terminated")
-			return
-		}
-	}
-
-	return
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if (ch == '\n' && braces == 0) || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' && braces == 0 {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	start := n
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		if ch == eof {
-			// If we see an EOF, we halt any more scanning of digits
-			// immediately.
-			break
-		}
-
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	if n != start && ch != eof {
-		// we scanned all digits, put the last non digit char back,
-		// only if we read anything at all
-		s.unread()
-	}
-
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isDigit returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isDecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
deleted file mode 100644
index 5f981eaa..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package strconv
-
-import (
-	"errors"
-	"unicode/utf8"
-)
-
-// ErrSyntax indicates that a value does not have the right syntax for the target type.
-var ErrSyntax = errors.New("invalid syntax")
-
-// Unquote interprets s as a single-quoted, double-quoted,
-// or backquoted Go string literal, returning the string value
-// that s quotes.  (If s is single-quoted, it would be a Go
-// character literal; Unquote returns the corresponding
-// one-character string.)
-func Unquote(s string) (t string, err error) {
-	n := len(s)
-	if n < 2 {
-		return "", ErrSyntax
-	}
-	quote := s[0]
-	if quote != s[n-1] {
-		return "", ErrSyntax
-	}
-	s = s[1 : n-1]
-
-	if quote != '"' {
-		return "", ErrSyntax
-	}
-	if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') {
-		return "", ErrSyntax
-	}
-
-	// Is it trivial?  Avoid allocation.
-	if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
-		switch quote {
-		case '"':
-			return s, nil
-		case '\'':
-			r, size := utf8.DecodeRuneInString(s)
-			if size == len(s) && (r != utf8.RuneError || size != 1) {
-				return s, nil
-			}
-		}
-	}
-
-	var runeTmp [utf8.UTFMax]byte
-	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
-	for len(s) > 0 {
-		// If we're starting a '${}' then let it through un-unquoted.
-		// Specifically: we don't unquote any characters within the `${}`
-		// section.
-		if s[0] == '$' && len(s) > 1 && s[1] == '{' {
-			buf = append(buf, '$', '{')
-			s = s[2:]
-
-			// Continue reading until we find the closing brace, copying as-is
-			braces := 1
-			for len(s) > 0 && braces > 0 {
-				r, size := utf8.DecodeRuneInString(s)
-				if r == utf8.RuneError {
-					return "", ErrSyntax
-				}
-
-				s = s[size:]
-
-				n := utf8.EncodeRune(runeTmp[:], r)
-				buf = append(buf, runeTmp[:n]...)
-
-				switch r {
-				case '{':
-					braces++
-				case '}':
-					braces--
-				}
-			}
-			if braces != 0 {
-				return "", ErrSyntax
-			}
-			if len(s) == 0 {
-				// If there's no string left, we're done!
-				break
-			} else {
-				// If there's more left, we need to pop back up to the top of the loop
-				// in case there's another interpolation in this string.
-				continue
-			}
-		}
-
-		if s[0] == '\n' {
-			return "", ErrSyntax
-		}
-
-		c, multibyte, ss, err := unquoteChar(s, quote)
-		if err != nil {
-			return "", err
-		}
-		s = ss
-		if c < utf8.RuneSelf || !multibyte {
-			buf = append(buf, byte(c))
-		} else {
-			n := utf8.EncodeRune(runeTmp[:], c)
-			buf = append(buf, runeTmp[:n]...)
-		}
-		if quote == '\'' && len(s) != 0 {
-			// single-quoted must be single character
-			return "", ErrSyntax
-		}
-	}
-	return string(buf), nil
-}
-
-// contains reports whether the string contains the byte c.
-func contains(s string, c byte) bool {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			return true
-		}
-	}
-	return false
-}
-
-func unhex(b byte) (v rune, ok bool) {
-	c := rune(b)
-	switch {
-	case '0' <= c && c <= '9':
-		return c - '0', true
-	case 'a' <= c && c <= 'f':
-		return c - 'a' + 10, true
-	case 'A' <= c && c <= 'F':
-		return c - 'A' + 10, true
-	}
-	return
-}
-
-func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
-	// easy cases
-	switch c := s[0]; {
-	case c == quote && (quote == '\'' || quote == '"'):
-		err = ErrSyntax
-		return
-	case c >= utf8.RuneSelf:
-		r, size := utf8.DecodeRuneInString(s)
-		return r, true, s[size:], nil
-	case c != '\\':
-		return rune(s[0]), false, s[1:], nil
-	}
-
-	// hard case: c is backslash
-	if len(s) <= 1 {
-		err = ErrSyntax
-		return
-	}
-	c := s[1]
-	s = s[2:]
-
-	switch c {
-	case 'a':
-		value = '\a'
-	case 'b':
-		value = '\b'
-	case 'f':
-		value = '\f'
-	case 'n':
-		value = '\n'
-	case 'r':
-		value = '\r'
-	case 't':
-		value = '\t'
-	case 'v':
-		value = '\v'
-	case 'x', 'u', 'U':
-		n := 0
-		switch c {
-		case 'x':
-			n = 2
-		case 'u':
-			n = 4
-		case 'U':
-			n = 8
-		}
-		var v rune
-		if len(s) < n {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < n; j++ {
-			x, ok := unhex(s[j])
-			if !ok {
-				err = ErrSyntax
-				return
-			}
-			v = v<<4 | x
-		}
-		s = s[n:]
-		if c == 'x' {
-			// single-byte string, possibly not UTF-8
-			value = v
-			break
-		}
-		if v > utf8.MaxRune {
-			err = ErrSyntax
-			return
-		}
-		value = v
-		multibyte = true
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		v := rune(c) - '0'
-		if len(s) < 2 {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < 2; j++ { // one digit already; two more
-			x := rune(s[j]) - '0'
-			if x < 0 || x > 7 {
-				err = ErrSyntax
-				return
-			}
-			v = (v << 3) | x
-		}
-		s = s[2:]
-		if v > 255 {
-			err = ErrSyntax
-			return
-		}
-		value = v
-	case '\\':
-		value = '\\'
-	case '\'', '"':
-		if c != quote {
-			err = ErrSyntax
-			return
-		}
-		value = rune(c)
-	default:
-		err = ErrSyntax
-		return
-	}
-	tail = s
-	return
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/notifier/vendor/github.com/hashicorp/hcl/hcl/token/token.go
deleted file mode 100644
index e37c0664..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/hcl/token/token.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package token defines constants representing the lexical tokens for HCL
-// (HashiCorp Configuration Language)
-package token
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-
-	hclstrconv "github.com/hashicorp/hcl/hcl/strconv"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-	JSON bool
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-	COMMENT
-
-	identifier_beg
-	IDENT // literals
-	literal_beg
-	NUMBER  // 12345
-	FLOAT   // 123.45
-	BOOL    // true,false
-	STRING  // "abc"
-	HEREDOC // < 0 {
-			// Pop the current item
-			n := len(frontier)
-			item := frontier[n-1]
-			frontier = frontier[:n-1]
-
-			switch v := item.Val.(type) {
-			case *ast.ObjectType:
-				items, frontier = flattenObjectType(v, item, items, frontier)
-			case *ast.ListType:
-				items, frontier = flattenListType(v, item, items, frontier)
-			default:
-				items = append(items, item)
-			}
-		}
-
-		// Reverse the list since the frontier model runs things backwards
-		for i := len(items)/2 - 1; i >= 0; i-- {
-			opp := len(items) - 1 - i
-			items[i], items[opp] = items[opp], items[i]
-		}
-
-		// Done! Set the original items
-		list.Items = items
-		return n, true
-	})
-}
-
-func flattenListType(
-	ot *ast.ListType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list is empty, keep the original list
-	if len(ot.List) == 0 {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List {
-		if _, ok := subitem.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, elem := range ot.List {
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        item.Keys,
-			Assign:      item.Assign,
-			Val:         elem,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
-
-func flattenObjectType(
-	ot *ast.ObjectType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list has no items we do not have to flatten anything
-	if ot.List.Items == nil {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List.Items {
-		if _, ok := subitem.Val.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, subitem := range ot.List.Items {
-		// Copy the new key
-		keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
-		copy(keys, item.Keys)
-		copy(keys[len(item.Keys):], subitem.Keys)
-
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        keys,
-			Assign:      item.Assign,
-			Val:         subitem.Val,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/notifier/vendor/github.com/hashicorp/hcl/json/parser/parser.go
deleted file mode 100644
index 125a5f07..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/json/parser/parser.go
+++ /dev/null
@@ -1,313 +0,0 @@
-package parser
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-	"github.com/hashicorp/hcl/json/scanner"
-	"github.com/hashicorp/hcl/json/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = fmt.Errorf("%s: %s", pos, msg)
-	}
-
-	// The root must be an object in JSON
-	object, err := p.object()
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	// We make our final node an object list so it is more HCL compatible
-	f.Node = object.List
-
-	// Flatten it, which finds patterns and turns them into more HCL-like
-	// AST trees.
-	flattenObjects(f.Node)
-
-	return f, nil
-}
-
-func (p *Parser) objectList() (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// Check for a followup comma. If it isn't a comma, then we're done
-		if tok := p.scan(); tok.Type != token.COMMA {
-			break
-		}
-	}
-
-	return node, nil
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	switch p.tok.Type {
-	case token.COLON:
-		pos := p.tok.Pos
-		o.Assign = hcltoken.Pos{
-			Filename: pos.Filename,
-			Offset:   pos.Offset,
-			Line:     pos.Line,
-			Column:   pos.Column,
-		}
-
-		o.Val, err = p.objectValue()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			return nil, errEofToken
-		case token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{
-				Token: p.tok.HCLToken(),
-			})
-		case token.COLON:
-			// If we have a zero keycount it means that we never got
-			// an object key, i.e. `{ :`. This is a syntax error.
-			if keyCount == 0 {
-				return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-			}
-
-			// Done
-			return keys, nil
-		case token.ILLEGAL:
-			return nil, errors.New("illegal")
-		default:
-			return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) objectValue() (ast.Node, error) {
-	defer un(trace(p, "ParseObjectValue"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok)
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.LBRACE:
-		return p.objectType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok)
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{}
-
-	l, err := p.objectList()
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	o.List = l
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{}
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.NUMBER, token.FLOAT, token.STRING:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.COMMA:
-			continue
-		case token.LBRACE:
-			node, err := p.objectType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.BOOL:
-			// TODO(arslan) should we support? not supported by HCL yet
-		case token.LBRACK:
-			// TODO(arslan) should we support nested lists? Even though it's
-			// written in README of HCL, it's not a part of the grammar
-			// (not defined in parse.y)
-		case token.RBRACK:
-			// finished
-			return l, nil
-		default:
-			return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type)
-		}
-
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok.HCLToken(),
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	p.tok = p.sc.Scan()
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/notifier/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
deleted file mode 100644
index fe3f0f09..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
+++ /dev/null
@@ -1,451 +0,0 @@
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/json/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	if ch == utf8.RuneError && size == 1 {
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		} else if lit == "null" {
-			tok = token.NULL
-		} else {
-			s.err("illegal char")
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case ':':
-			tok = token.COLON
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				s.err("illegal char")
-			}
-		default:
-			s.err("illegal char: " + string(ch))
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	zero := ch == '0'
-	pos := s.srcPos
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-
-	// If we have a larger number and this is zero, error
-	if zero && pos != s.srcPos {
-		s.err("numbers cannot start with 0")
-	}
-
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if ch == '\n' || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	// we scanned all digits, put the last non digit char back
-	s.unread()
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/json/token/position.go b/notifier/vendor/github.com/hashicorp/hcl/json/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/json/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/json/token/token.go b/notifier/vendor/github.com/hashicorp/hcl/json/token/token.go
deleted file mode 100644
index 95a0c3ee..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/json/token/token.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package token
-
-import (
-	"fmt"
-	"strconv"
-
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-
-	identifier_beg
-	literal_beg
-	NUMBER // 12345
-	FLOAT  // 123.45
-	BOOL   // true,false
-	STRING // "abc"
-	NULL   // null
-	literal_end
-	identifier_end
-
-	operator_beg
-	LBRACK // [
-	LBRACE // {
-	COMMA  // ,
-	PERIOD // .
-	COLON  // :
-
-	RBRACK // ]
-	RBRACE // }
-
-	operator_end
-)
-
-var tokens = [...]string{
-	ILLEGAL: "ILLEGAL",
-
-	EOF: "EOF",
-
-	NUMBER: "NUMBER",
-	FLOAT:  "FLOAT",
-	BOOL:   "BOOL",
-	STRING: "STRING",
-	NULL:   "NULL",
-
-	LBRACK: "LBRACK",
-	LBRACE: "LBRACE",
-	COMMA:  "COMMA",
-	PERIOD: "PERIOD",
-	COLON:  "COLON",
-
-	RBRACK: "RBRACK",
-	RBRACE: "RBRACE",
-}
-
-// String returns the string corresponding to the token tok.
-func (t Type) String() string {
-	s := ""
-	if 0 <= t && t < Type(len(tokens)) {
-		s = tokens[t]
-	}
-	if s == "" {
-		s = "token(" + strconv.Itoa(int(t)) + ")"
-	}
-	return s
-}
-
-// IsIdentifier returns true for tokens corresponding to identifiers and basic
-// type literals; it returns false otherwise.
-func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end }
-
-// IsLiteral returns true for tokens corresponding to basic type literals; it
-// returns false otherwise.
-func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end }
-
-// IsOperator returns true for tokens corresponding to operators and
-// delimiters; it returns false otherwise.
-func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end }
-
-// String returns the token's literal text. Note that this is only
-// applicable for certain token types, such as token.IDENT,
-// token.STRING, etc..
-func (t Token) String() string {
-	return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
-}
-
-// HCLToken converts this token to an HCL token.
-//
-// The token type must be a literal type or this will panic.
-func (t Token) HCLToken() hcltoken.Token {
-	switch t.Type {
-	case BOOL:
-		return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text}
-	case FLOAT:
-		return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text}
-	case NULL:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: ""}
-	case NUMBER:
-		return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text}
-	case STRING:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true}
-	default:
-		panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type))
-	}
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/lex.go b/notifier/vendor/github.com/hashicorp/hcl/lex.go
deleted file mode 100644
index d9993c29..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/lex.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package hcl
-
-import (
-	"unicode"
-	"unicode/utf8"
-)
-
-type lexModeValue byte
-
-const (
-	lexModeUnknown lexModeValue = iota
-	lexModeHcl
-	lexModeJson
-)
-
-// lexMode returns whether we're going to be parsing in JSON
-// mode or HCL mode.
-func lexMode(v []byte) lexModeValue {
-	var (
-		r      rune
-		w      int
-		offset int
-	)
-
-	for {
-		r, w = utf8.DecodeRune(v[offset:])
-		offset += w
-		if unicode.IsSpace(r) {
-			continue
-		}
-		if r == '{' {
-			return lexModeJson
-		}
-		break
-	}
-
-	return lexModeHcl
-}
diff --git a/notifier/vendor/github.com/hashicorp/hcl/parse.go b/notifier/vendor/github.com/hashicorp/hcl/parse.go
deleted file mode 100644
index 1fca53c4..00000000
--- a/notifier/vendor/github.com/hashicorp/hcl/parse.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package hcl
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hclParser "github.com/hashicorp/hcl/hcl/parser"
-	jsonParser "github.com/hashicorp/hcl/json/parser"
-)
-
-// ParseBytes accepts as input byte slice and returns ast tree.
-//
-// Input can be either JSON or HCL
-func ParseBytes(in []byte) (*ast.File, error) {
-	return parse(in)
-}
-
-// ParseString accepts input as a string and returns ast tree.
-func ParseString(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
-
-func parse(in []byte) (*ast.File, error) {
-	switch lexMode(in) {
-	case lexModeHcl:
-		return hclParser.Parse(in)
-	case lexModeJson:
-		return jsonParser.Parse(in)
-	}
-
-	return nil, fmt.Errorf("unknown config format")
-}
-
-// Parse parses the given input and returns the root object.
-//
-// The input format can be either HCL or JSON.
-func Parse(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/.golangci.yml b/notifier/vendor/github.com/jackc/pgx/v5/.golangci.yml
new file mode 100644
index 00000000..ca74c703
--- /dev/null
+++ b/notifier/vendor/github.com/jackc/pgx/v5/.golangci.yml
@@ -0,0 +1,21 @@
+# See for configurations: https://golangci-lint.run/usage/configuration/
+version: 2
+
+# See: https://golangci-lint.run/usage/formatters/
+formatters:
+  default: none
+  enable:
+    - gofmt # https://pkg.go.dev/cmd/gofmt
+    - gofumpt # https://github.com/mvdan/gofumpt
+
+  settings:
+    gofmt:
+      simplify: true # Simplify code: gofmt with `-s` option.
+
+    gofumpt:
+      # Module path which contains the source code being formatted.
+      # Default: ""
+      module-path: github.com/jackc/pgx/v5 # Should match with module in go.mod
+      # Choose whether to use the extra rules.
+      # Default: false
+      extra-rules: true
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/CHANGELOG.md b/notifier/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
index a0ff9ba3..6c9c99b5 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
+++ b/notifier/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
@@ -1,3 +1,54 @@
+# 5.7.6 (September 8, 2025)
+
+* Use ParseConfigError in pgx.ParseConfig and pgxpool.ParseConfig (Yurasov Ilia)
+* Add PrepareConn hook to pgxpool (Jonathan Hall)
+* Reduce allocations in QueryContext (Dominique Lefevre)
+* Add MarshalJSON and UnmarshalJSON for pgtype.Uint32 (Panos Koutsovasilis)
+* Configure ping behavior on pgxpool with ShouldPing (Christian Kiely)
+* zeronull int types implement Int64Valuer and Int64Scanner (Li Zeghong)
+* Fix panic when receiving terminate connection message during CopyFrom (Michal Drausowski)
+* Fix statement cache not being invalidated on error during batch (Muhammadali Nazarov)
+
+# 5.7.5 (May 17, 2025)
+
+* Support sslnegotiation connection option (divyam234)
+* Update golang.org/x/crypto to v0.37.0. This placates security scanners that were unable to see that pgx did not use the behavior affected by https://pkg.go.dev/vuln/GO-2025-3487.
+* TraceLog now logs Acquire and Release at the debug level (dave sinclair)
+* Add support for PGTZ environment variable
+* Add support for PGOPTIONS environment variable
+* Unpin memory used by Rows quicker
+* Remove PlanScan memoization. This resolves a rare issue where scanning could be broken for one type by first scanning another. The problem was in the memoization system and benchmarking revealed that memoization was not providing any meaningful benefit.
+
+# 5.7.4 (March 24, 2025)
+
+* Fix / revert change to scanning JSON `null` (Felix Röhrich)
+
+# 5.7.3 (March 21, 2025)
+
+* Expose EmptyAcquireWaitTime in pgxpool.Stat (vamshiaruru32)
+* Improve SQL sanitizer performance (ninedraft)
+* Fix Scan confusion with json(b), sql.Scanner, and automatic dereferencing (moukoublen, felix-roehrich)
+* Fix Values() for xml type always returning nil instead of []byte
+* Add ability to send Flush message in pipeline mode (zenkovev)
+* Fix pgtype.Timestamp's JSON behavior to match PostgreSQL (pconstantinou)
+* Better error messages when scanning structs (logicbomb)
+* Fix handling of error on batch write (bonnefoa)
+* Match libpq's connection fallback behavior more closely (felix-roehrich)
+* Add MinIdleConns to pgxpool (djahandarie)
+
+# 5.7.2 (December 21, 2024)
+
+* Fix prepared statement already exists on batch prepare failure
+* Add commit query to tx options (Lucas Hild)
+* Fix pgtype.Timestamp json unmarshal (Shean de Montigny-Desautels)
+* Add message body size limits in frontend and backend (zene)
+* Add xid8 type
+* Ensure planning encodes and scans cannot infinitely recurse
+* Implement pgtype.UUID.String() (Konstantin Grachev)
+* Switch from ExecParams to Exec in ValidateConnectTargetSessionAttrs functions (Alexander Rumyantsev)
+* Update golang.org/x/crypto
+* Fix json(b) columns prefer sql.Scanner interface like database/sql (Ludovico Russo)
+
 # 5.7.1 (September 10, 2024)
 
 * Fix data race in tracelog.TraceLog
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/README.md b/notifier/vendor/github.com/jackc/pgx/v5/README.md
index 0cf2c291..cb709e21 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/README.md
+++ b/notifier/vendor/github.com/jackc/pgx/v5/README.md
@@ -84,7 +84,7 @@ It is also possible to use the `database/sql` interface and convert a connection
 
 ## Testing
 
-See CONTRIBUTING.md for setup instructions.
+See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions.
 
 ## Architecture
 
@@ -92,7 +92,7 @@ See the presentation at Golang Estonia, [PGX Top to Bottom](https://www.youtube.
 
 ## Supported Go and PostgreSQL Versions
 
-pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.21 and higher and PostgreSQL 12 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
+pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.23 and higher and PostgreSQL 13 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
 
 ## Version Policy
 
@@ -126,7 +126,8 @@ pgerrcode contains constants for the PostgreSQL error codes.
 
 ## Adapters for 3rd Party Tracers
 
-* [https://github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx)
 
 ## Adapters for 3rd Party Loggers
 
@@ -156,7 +157,7 @@ Library for scanning data from a database into Go structs and more.
 A carefully designed SQL client for making using SQL easier,
 more productive, and less error-prone on Golang.
 
-### [https://github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
+### [github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
 
 Adds GSSAPI / Kerberos authentication support.
 
@@ -169,6 +170,22 @@ Explicit data mapping and scanning library for Go structs and slices.
 Type safe and flexible package for scanning database data into Go types.
 Supports, structs, maps, slices and custom mapping functions.
 
-### [https://github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
+### [github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
 
 Code first migration library for native pgx (no database/sql abstraction).
+
+### [github.com/amirsalarsafaei/sqlc-pgx-monitoring](https://github.com/amirsalarsafaei/sqlc-pgx-monitoring)
+
+A database monitoring/metrics library for pgx and sqlc. Trace, log and monitor your sqlc query performance using OpenTelemetry.
+
+### [https://github.com/nikolayk812/pgx-outbox](https://github.com/nikolayk812/pgx-outbox)
+
+Simple Golang implementation for transactional outbox pattern for PostgreSQL using jackc/pgx driver.
+
+### [https://github.com/Arlandaren/pgxWrappy](https://github.com/Arlandaren/pgxWrappy)
+
+Simplifies working with the pgx library, providing convenient scanning of nested structures.
+
+## [https://github.com/KoNekoD/pgx-colon-query-rewriter](https://github.com/KoNekoD/pgx-colon-query-rewriter)
+
+Implementation of the pgx query rewriter to use ':' instead of '@' in named query parameters.
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/Rakefile b/notifier/vendor/github.com/jackc/pgx/v5/Rakefile
index d957573e..3e3aa503 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/Rakefile
+++ b/notifier/vendor/github.com/jackc/pgx/v5/Rakefile
@@ -2,7 +2,7 @@ require "erb"
 
 rule '.go' => '.go.erb' do |task|
   erb = ERB.new(File.read(task.source))
-  File.write(task.name, "// Do not edit. Generated from #{task.source}\n" + erb.result(binding))
+  File.write(task.name, "// Code generated from #{task.source}. DO NOT EDIT.\n\n" + erb.result(binding))
   sh "goimports", "-w", task.name
 end
 
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/batch.go b/notifier/vendor/github.com/jackc/pgx/v5/batch.go
index c3c2834f..1b1cbd84 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/batch.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/batch.go
@@ -43,6 +43,10 @@ func (qq *QueuedQuery) QueryRow(fn func(row Row) error) {
 }
 
 // Exec sets fn to be called when the response to qq is received.
+//
+// Note: for simple batch insert uses where it is not required to handle
+// each potential error individually, it's sufficient to not set any callbacks,
+// and just handle the return value of BatchResults.Close.
 func (qq *QueuedQuery) Exec(fn func(ct pgconn.CommandTag) error) {
 	qq.Fn = func(br BatchResults) error {
 		ct, err := br.Exec()
@@ -83,7 +87,7 @@ func (b *Batch) Len() int {
 
 type BatchResults interface {
 	// Exec reads the results from the next query in the batch as if the query has been sent with Conn.Exec. Prefer
-	// calling Exec on the QueuedQuery.
+	// calling Exec on the QueuedQuery, or just calling Close.
 	Exec() (pgconn.CommandTag, error)
 
 	// Query reads the results from the next query in the batch as if the query has been sent with Conn.Query. Prefer
@@ -98,6 +102,9 @@ type BatchResults interface {
 	// QueuedQuery.Query, QueuedQuery.QueryRow, or QueuedQuery.Exec will be called. If a callback function returns an
 	// error or the batch encounters an error subsequent callback functions will not be called.
 	//
+	// For simple batch inserts inside a transaction or similar queries, it's sufficient to not set any callbacks,
+	// and just handle the return value of Close.
+	//
 	// Close must be called before the underlying connection can be used again. Any error that occurred during a batch
 	// operation may have made it impossible to resyncronize the connection with the server. In this case the underlying
 	// connection will have been closed.
@@ -207,7 +214,6 @@ func (br *batchResults) Query() (Rows, error) {
 func (br *batchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -220,6 +226,8 @@ func (br *batchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err != nil {
@@ -378,7 +386,6 @@ func (br *pipelineBatchResults) Query() (Rows, error) {
 func (br *pipelineBatchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -391,6 +398,8 @@ func (br *pipelineBatchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err == nil && br.lastRows != nil && br.lastRows.err != nil {
@@ -441,3 +450,20 @@ func (br *pipelineBatchResults) nextQueryAndArgs() (query string, args []any, er
 	br.qqIdx++
 	return bi.SQL, bi.Arguments, nil
 }
+
+// invalidates statement and description caches on batch results error
+func invalidateCachesOnBatchResultsError(conn *Conn, b *Batch, err error) {
+	if err != nil && conn != nil && b != nil {
+		if sc := conn.statementCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+
+		if sc := conn.descriptionCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+	}
+}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/conn.go b/notifier/vendor/github.com/jackc/pgx/v5/conn.go
index 187b3dd5..67b22529 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/conn.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/conn.go
@@ -172,7 +172,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "statement_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse statement_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse statement_cache_capacity", err)
 		}
 		statementCacheCapacity = int(n)
 	}
@@ -182,7 +182,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "description_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse description_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse description_cache_capacity", err)
 		}
 		descriptionCacheCapacity = int(n)
 	}
@@ -202,7 +202,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		case "simple_protocol":
 			defaultQueryExecMode = QueryExecModeSimpleProtocol
 		default:
-			return nil, fmt.Errorf("invalid default_query_exec_mode: %s", s)
+			return nil, pgconn.NewParseConfigError(connString, "invalid default_query_exec_mode", err)
 		}
 	}
 
@@ -420,7 +420,7 @@ func (c *Conn) IsClosed() bool {
 	return c.pgConn.IsClosed()
 }
 
-func (c *Conn) die(err error) {
+func (c *Conn) die() {
 	if c.IsClosed() {
 		return
 	}
@@ -588,14 +588,6 @@ func (c *Conn) execPrepared(ctx context.Context, sd *pgconn.StatementDescription
 	return result.CommandTag, result.Err
 }
 
-type unknownArgumentTypeQueryExecModeExecError struct {
-	arg any
-}
-
-func (e *unknownArgumentTypeQueryExecModeExecError) Error() string {
-	return fmt.Sprintf("cannot use unregistered type %T as query argument in QueryExecModeExec", e.arg)
-}
-
 func (c *Conn) execSQLParams(ctx context.Context, sql string, args []any) (pgconn.CommandTag, error) {
 	err := c.eqb.Build(c.typeMap, nil, args)
 	if err != nil {
@@ -650,21 +642,33 @@ const (
 	// registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are
 	// unregistered or ambiguous. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know
 	// the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot.
+	//
+	// On rare occasions user defined types may behave differently when encoded in the text format instead of the binary
+	// format. For example, this could happen if a "type RomanNumeral int32" implements fmt.Stringer to format integers as
+	// Roman numerals (e.g. 7 is VII). The binary format would properly encode the integer 7 as the binary value for 7.
+	// But the text format would encode the integer 7 as the string "VII". As QueryExecModeExec uses the text format, it
+	// is possible that changing query mode from another mode to QueryExecModeExec could change the behavior of the query.
+	// This should not occur with types pgx supports directly and can be avoided by registering the types with
+	// pgtype.Map.RegisterDefaultPgType and implementing the appropriate type interfaces. In the cas of RomanNumeral, it
+	// should implement pgtype.Int64Valuer.
 	QueryExecModeExec
 
-	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments.
-	// Queries are executed in a single round trip. Type mappings can be registered with
+	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments. This is
+	// especially significant for []byte values. []byte values are encoded as PostgreSQL bytea. string must be used
+	// instead for text type values including json and jsonb. Type mappings can be registered with
 	// pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambiguous.
-	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use
-	// a map[string]string directly as an argument. This mode cannot.
+	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use a
+	// map[string]string directly as an argument. This mode cannot. Queries are executed in a single round trip.
 	//
-	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec with minor
-	// exceptions such as behavior when multiple result returning queries are erroneously sent in a single string.
+	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec. This includes
+	// the warning regarding differences in text format and binary format encoding with user defined types. There may be
+	// other minor exceptions such as behavior when multiple result returning queries are erroneously sent in a single
+	// string.
 	//
 	// QueryExecModeSimpleProtocol uses client side parameter interpolation. All values are quoted and escaped. Prefer
-	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol
-	// should only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does
-	// not support the extended protocol.
+	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol should
+	// only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does not
+	// support the extended protocol.
 	QueryExecModeSimpleProtocol
 )
 
@@ -904,6 +908,9 @@ func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) Row {
 // SendBatch sends all queued queries to the server at once. All queries are run in an implicit transaction unless
 // explicit transaction control statements are executed. The returned BatchResults must be closed before the connection
 // is used again.
+//
+// Depending on the QueryExecMode, all queries may be prepared before any are executed. This means that creating a table
+// and using it in a subsequent query in the same batch can fail.
 func (c *Conn) SendBatch(ctx context.Context, b *Batch) (br BatchResults) {
 	if c.batchTracer != nil {
 		ctx = c.batchTracer.TraceBatchStart(ctx, c, TraceBatchStartData{Batch: b})
@@ -1126,47 +1133,64 @@ func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, d
 
 	// Prepare any needed queries
 	if len(distinctNewQueries) > 0 {
-		for _, sd := range distinctNewQueries {
-			pipeline.SendPrepare(sd.Name, sd.SQL, nil)
-		}
+		err := func() (err error) {
+			for _, sd := range distinctNewQueries {
+				pipeline.SendPrepare(sd.Name, sd.SQL, nil)
+			}
 
-		err := pipeline.Sync()
-		if err != nil {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
-		}
+			// Store all statements we are preparing into the cache. It's fine if it overflows because HandleInvalidated will
+			// clean them up later.
+			if sdCache != nil {
+				for _, sd := range distinctNewQueries {
+					sdCache.Put(sd)
+				}
+			}
+
+			// If something goes wrong preparing the statements, we need to invalidate the cache entries we just added.
+			defer func() {
+				if err != nil && sdCache != nil {
+					for _, sd := range distinctNewQueries {
+						sdCache.Invalidate(sd.SQL)
+					}
+				}
+			}()
+
+			err = pipeline.Sync()
+			if err != nil {
+				return err
+			}
+
+			for _, sd := range distinctNewQueries {
+				results, err := pipeline.GetResults()
+				if err != nil {
+					return err
+				}
+
+				resultSD, ok := results.(*pgconn.StatementDescription)
+				if !ok {
+					return fmt.Errorf("expected statement description, got %T", results)
+				}
+
+				// Fill in the previously empty / pending statement descriptions.
+				sd.ParamOIDs = resultSD.ParamOIDs
+				sd.Fields = resultSD.Fields
+			}
 
-		for _, sd := range distinctNewQueries {
 			results, err := pipeline.GetResults()
 			if err != nil {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
+				return err
 			}
 
-			resultSD, ok := results.(*pgconn.StatementDescription)
+			_, ok := results.(*pgconn.PipelineSync)
 			if !ok {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected statement description, got %T", results), closed: true}
+				return fmt.Errorf("expected sync, got %T", results)
 			}
 
-			// Fill in the previously empty / pending statement descriptions.
-			sd.ParamOIDs = resultSD.ParamOIDs
-			sd.Fields = resultSD.Fields
-		}
-
-		results, err := pipeline.GetResults()
+			return nil
+		}()
 		if err != nil {
 			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
 		}
-
-		_, ok := results.(*pgconn.PipelineSync)
-		if !ok {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected sync, got %T", results), closed: true}
-		}
-	}
-
-	// Put all statements into the cache. It's fine if it overflows because HandleInvalidated will clean them up later.
-	if sdCache != nil {
-		for _, sd := range distinctNewQueries {
-			sdCache.Put(sd)
-		}
 	}
 
 	// Queue the queries.
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/derived_types.go b/notifier/vendor/github.com/jackc/pgx/v5/derived_types.go
index 22ab069c..72c0a242 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/derived_types.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/derived_types.go
@@ -161,7 +161,7 @@ type derivedTypeInfo struct {
 // The result of this call can be passed into RegisterTypes to complete the process.
 func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Type, error) {
 	m := c.TypeMap()
-	if typeNames == nil || len(typeNames) == 0 {
+	if len(typeNames) == 0 {
 		return nil, fmt.Errorf("No type names were supplied.")
 	}
 
@@ -169,13 +169,7 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 	// the SQL not support recent structures such as multirange
 	serverVersion, _ := serverVersion(c)
 	sql := buildLoadDerivedTypesSQL(serverVersion, typeNames)
-	var rows Rows
-	var err error
-	if typeNames == nil {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol)
-	} else {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
-	}
+	rows, err := c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
 	if err != nil {
 		return nil, fmt.Errorf("While generating load types query: %w", err)
 	}
@@ -232,15 +226,15 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 		default:
 			return nil, fmt.Errorf("Unknown typtype %q was found while registering %q", ti.Typtype, ti.TypeName)
 		}
-		if type_ != nil {
-			m.RegisterType(type_)
-			if ti.NspName != "" {
-				nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
-				m.RegisterType(nspType)
-				result = append(result, nspType)
-			}
-			result = append(result, type_)
+
+		// the type_ is imposible to be null
+		m.RegisterType(type_)
+		if ti.NspName != "" {
+			nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
+			m.RegisterType(nspType)
+			result = append(result, nspType)
 		}
+		result = append(result, type_)
 	}
 	return result, nil
 }
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/doc.go b/notifier/vendor/github.com/jackc/pgx/v5/doc.go
index 0e91d64e..5d2ae388 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/doc.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/doc.go
@@ -183,7 +183,7 @@ For debug tracing of the actual PostgreSQL wire protocol messages see github.com
 
 Lower Level PostgreSQL Functionality
 
-github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn in
+github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn is
 implemented on top of pgconn. The Conn.PgConn() method can be used to access this lower layer.
 
 PgBouncer
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh b/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
new file mode 100644
index 00000000..ec0f7b03
--- /dev/null
+++ b/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+current_branch=$(git rev-parse --abbrev-ref HEAD)
+if [ "$current_branch" == "HEAD" ]; then
+    current_branch=$(git rev-parse HEAD)
+fi
+
+restore_branch() {
+    echo "Restoring original branch/commit: $current_branch"
+    git checkout "$current_branch"
+}
+trap restore_branch EXIT
+
+# Check if there are uncommitted changes
+if ! git diff --quiet || ! git diff --cached --quiet; then
+    echo "There are uncommitted changes. Please commit or stash them before running this script."
+    exit 1
+fi
+
+# Ensure that at least one commit argument is passed
+if [ "$#" -lt 1 ]; then
+    echo "Usage: $0   ... "
+    exit 1
+fi
+
+commits=("$@")
+benchmarks_dir=benchmarks
+
+if ! mkdir -p "${benchmarks_dir}"; then
+    echo "Unable to create dir for benchmarks data"
+    exit 1
+fi
+
+# Benchmark results
+bench_files=()
+
+# Run benchmark for each listed commit
+for i in "${!commits[@]}"; do
+    commit="${commits[i]}"
+    git checkout "$commit" || {
+        echo "Failed to checkout $commit"
+        exit 1
+    }
+
+    # Sanitized commmit message
+    commit_message=$(git log -1 --pretty=format:"%s" | tr -c '[:alnum:]-_' '_')
+
+    # Benchmark data will go there
+    bench_file="${benchmarks_dir}/${i}_${commit_message}.bench"
+
+    if ! go test -bench=. -count=10 >"$bench_file"; then
+        echo "Benchmarking failed for commit $commit"
+        exit 1
+    fi
+
+    bench_files+=("$bench_file")
+done
+
+# go install golang.org/x/perf/cmd/benchstat[@latest]
+benchstat "${bench_files[@]}"
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
index df58c448..b516817c 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
@@ -4,8 +4,10 @@ import (
 	"bytes"
 	"encoding/hex"
 	"fmt"
+	"slices"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 	"unicode/utf8"
 )
@@ -24,18 +26,33 @@ type Query struct {
 // https://github.com/jackc/pgx/issues/1380
 const replacementcharacterwidth = 3
 
+const maxBufSize = 16384 // 16 Ki
+
+var bufPool = &pool[*bytes.Buffer]{
+	new: func() *bytes.Buffer {
+		return &bytes.Buffer{}
+	},
+	reset: func(b *bytes.Buffer) bool {
+		n := b.Len()
+		b.Reset()
+		return n < maxBufSize
+	},
+}
+
+var null = []byte("null")
+
 func (q *Query) Sanitize(args ...any) (string, error) {
 	argUse := make([]bool, len(args))
-	buf := &bytes.Buffer{}
+	buf := bufPool.get()
+	defer bufPool.put(buf)
 
 	for _, part := range q.Parts {
-		var str string
 		switch part := part.(type) {
 		case string:
-			str = part
+			buf.WriteString(part)
 		case int:
 			argIdx := part - 1
-
+			var p []byte
 			if argIdx < 0 {
 				return "", fmt.Errorf("first sql argument must be > 0")
 			}
@@ -43,34 +60,41 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 			if argIdx >= len(args) {
 				return "", fmt.Errorf("insufficient arguments")
 			}
+
+			// Prevent SQL injection via Line Comment Creation
+			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
+			buf.WriteByte(' ')
+
 			arg := args[argIdx]
 			switch arg := arg.(type) {
 			case nil:
-				str = "null"
+				p = null
 			case int64:
-				str = strconv.FormatInt(arg, 10)
+				p = strconv.AppendInt(buf.AvailableBuffer(), arg, 10)
 			case float64:
-				str = strconv.FormatFloat(arg, 'f', -1, 64)
+				p = strconv.AppendFloat(buf.AvailableBuffer(), arg, 'f', -1, 64)
 			case bool:
-				str = strconv.FormatBool(arg)
+				p = strconv.AppendBool(buf.AvailableBuffer(), arg)
 			case []byte:
-				str = QuoteBytes(arg)
+				p = QuoteBytes(buf.AvailableBuffer(), arg)
 			case string:
-				str = QuoteString(arg)
+				p = QuoteString(buf.AvailableBuffer(), arg)
 			case time.Time:
-				str = arg.Truncate(time.Microsecond).Format("'2006-01-02 15:04:05.999999999Z07:00:00'")
+				p = arg.Truncate(time.Microsecond).
+					AppendFormat(buf.AvailableBuffer(), "'2006-01-02 15:04:05.999999999Z07:00:00'")
 			default:
 				return "", fmt.Errorf("invalid arg type: %T", arg)
 			}
 			argUse[argIdx] = true
 
+			buf.Write(p)
+
 			// Prevent SQL injection via Line Comment Creation
 			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
-			str = " " + str + " "
+			buf.WriteByte(' ')
 		default:
 			return "", fmt.Errorf("invalid Part type: %T", part)
 		}
-		buf.WriteString(str)
 	}
 
 	for i, used := range argUse {
@@ -82,26 +106,99 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 }
 
 func NewQuery(sql string) (*Query, error) {
-	l := &sqlLexer{
-		src:     sql,
-		stateFn: rawState,
+	query := &Query{}
+	query.init(sql)
+
+	return query, nil
+}
+
+var sqlLexerPool = &pool[*sqlLexer]{
+	new: func() *sqlLexer {
+		return &sqlLexer{}
+	},
+	reset: func(sl *sqlLexer) bool {
+		*sl = sqlLexer{}
+		return true
+	},
+}
+
+func (q *Query) init(sql string) {
+	parts := q.Parts[:0]
+	if parts == nil {
+		// dirty, but fast heuristic to preallocate for ~90% usecases
+		n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1
+		parts = make([]Part, 0, n)
 	}
 
+	l := sqlLexerPool.get()
+	defer sqlLexerPool.put(l)
+
+	l.src = sql
+	l.stateFn = rawState
+	l.parts = parts
+
 	for l.stateFn != nil {
 		l.stateFn = l.stateFn(l)
 	}
 
-	query := &Query{Parts: l.parts}
-
-	return query, nil
+	q.Parts = l.parts
 }
 
-func QuoteString(str string) string {
-	return "'" + strings.ReplaceAll(str, "'", "''") + "'"
+func QuoteString(dst []byte, str string) []byte {
+	const quote = '\''
+
+	// Preallocate space for the worst case scenario
+	dst = slices.Grow(dst, len(str)*2+2)
+
+	// Add opening quote
+	dst = append(dst, quote)
+
+	// Iterate through the string without allocating
+	for i := 0; i < len(str); i++ {
+		if str[i] == quote {
+			dst = append(dst, quote, quote)
+		} else {
+			dst = append(dst, str[i])
+		}
+	}
+
+	// Add closing quote
+	dst = append(dst, quote)
+
+	return dst
 }
 
-func QuoteBytes(buf []byte) string {
-	return `'\x` + hex.EncodeToString(buf) + "'"
+func QuoteBytes(dst, buf []byte) []byte {
+	if len(buf) == 0 {
+		return append(dst, `'\x'`...)
+	}
+
+	// Calculate required length
+	requiredLen := 3 + hex.EncodedLen(len(buf)) + 1
+
+	// Ensure dst has enough capacity
+	if cap(dst)-len(dst) < requiredLen {
+		newDst := make([]byte, len(dst), len(dst)+requiredLen)
+		copy(newDst, dst)
+		dst = newDst
+	}
+
+	// Record original length and extend slice
+	origLen := len(dst)
+	dst = dst[:origLen+requiredLen]
+
+	// Add prefix
+	dst[origLen] = '\''
+	dst[origLen+1] = '\\'
+	dst[origLen+2] = 'x'
+
+	// Encode bytes directly into dst
+	hex.Encode(dst[origLen+3:len(dst)-1], buf)
+
+	// Add suffix
+	dst[len(dst)-1] = '\''
+
+	return dst
 }
 
 type sqlLexer struct {
@@ -319,13 +416,45 @@ func multilineCommentState(l *sqlLexer) stateFn {
 	}
 }
 
+var queryPool = &pool[*Query]{
+	new: func() *Query {
+		return &Query{}
+	},
+	reset: func(q *Query) bool {
+		n := len(q.Parts)
+		q.Parts = q.Parts[:0]
+		return n < 64 // drop too large queries
+	},
+}
+
 // SanitizeSQL replaces placeholder values with args. It quotes and escapes args
 // as necessary. This function is only safe when standard_conforming_strings is
 // on.
 func SanitizeSQL(sql string, args ...any) (string, error) {
-	query, err := NewQuery(sql)
-	if err != nil {
-		return "", err
-	}
+	query := queryPool.get()
+	query.init(sql)
+	defer queryPool.put(query)
+
 	return query.Sanitize(args...)
 }
+
+type pool[E any] struct {
+	p     sync.Pool
+	new   func() E
+	reset func(E) bool
+}
+
+func (pool *pool[E]) get() E {
+	v, ok := pool.p.Get().(E)
+	if !ok {
+		v = pool.new()
+	}
+
+	return v
+}
+
+func (p *pool[E]) put(v E) {
+	if p.reset(v) {
+		p.p.Put(v)
+	}
+}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go b/notifier/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
index dec83f47..17fec937 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
@@ -31,7 +31,6 @@ func (c *LRUCache) Get(key string) *pgconn.StatementDescription {
 	}
 
 	return nil
-
 }
 
 // Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache or
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
index 06498361..f846ba81 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
@@ -263,7 +263,7 @@ func computeClientProof(saltedPassword, authMessage []byte) []byte {
 	return buf
 }
 
-func computeServerSignature(saltedPassword []byte, authMessage []byte) []byte {
+func computeServerSignature(saltedPassword, authMessage []byte) []byte {
 	serverKey := computeHMAC(saltedPassword, []byte("Server Key"))
 	serverSignature := computeHMAC(serverKey, authMessage)
 	buf := make([]byte, base64.StdEncoding.EncodedLen(len(serverSignature)))
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/config.go b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/config.go
index 6a198e67..3937dc40 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/config.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/config.go
@@ -23,9 +23,11 @@ import (
 	"github.com/jackc/pgx/v5/pgproto3"
 )
 
-type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type GetSSLPasswordFunc func(ctx context.Context) string
+type (
+	AfterConnectFunc    func(ctx context.Context, pgconn *PgConn) error
+	ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
+	GetSSLPasswordFunc  func(ctx context.Context) string
+)
 
 // Config is the settings used to establish a connection to a PostgreSQL server. It must be created by [ParseConfig]. A
 // manually initialized Config will cause ConnectConfig to panic.
@@ -51,6 +53,8 @@ type Config struct {
 	KerberosSpn     string
 	Fallbacks       []*FallbackConfig
 
+	SSLNegotiation string // sslnegotiation=postgres or sslnegotiation=direct
+
 	// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
 	// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
 	// fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs.
@@ -177,7 +181,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //
 // ParseConfig supports specifying multiple hosts in similar manner to libpq. Host and port may include comma separated
 // values that will be tried in order. This can be used as part of a high availability system. See
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
 //
 //	# Example URL
 //	postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb
@@ -198,13 +202,15 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //	PGSSLKEY
 //	PGSSLROOTCERT
 //	PGSSLPASSWORD
+//	PGOPTIONS
 //	PGAPPNAME
 //	PGCONNECT_TIMEOUT
 //	PGTARGETSESSIONATTRS
+//	PGTZ
 //
-// See http://www.postgresql.org/docs/11/static/libpq-envars.html for details on the meaning of environment variables.
+// See http://www.postgresql.org/docs/current/static/libpq-envars.html for details on the meaning of environment variables.
 //
-// See https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
+// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
 // usually but not always the environment variable name downcased and without the "PG" prefix.
 //
 // Important Security Notes:
@@ -212,7 +218,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 // ParseConfig tries to match libpq behavior with regard to PGSSLMODE. This includes defaulting to "prefer" behavior if
 // not set.
 //
-// See http://www.postgresql.org/docs/11/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
+// See http://www.postgresql.org/docs/current/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
 // security each sslmode provides.
 //
 // The sslmode "prefer" (the default), sslmode "allow", and multiple hosts are implemented via the Fallbacks field of
@@ -318,6 +324,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		"sslkey":               {},
 		"sslcert":              {},
 		"sslrootcert":          {},
+		"sslnegotiation":       {},
 		"sslpassword":          {},
 		"sslsni":               {},
 		"krbspn":               {},
@@ -386,6 +393,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 	config.Port = fallbacks[0].Port
 	config.TLSConfig = fallbacks[0].TLSConfig
 	config.Fallbacks = fallbacks[1:]
+	config.SSLNegotiation = settings["sslnegotiation"]
 
 	passfile, err := pgpassfile.ReadPassfile(settings["passfile"])
 	if err == nil {
@@ -449,9 +457,12 @@ func parseEnvSettings() map[string]string {
 		"PGSSLSNI":             "sslsni",
 		"PGSSLROOTCERT":        "sslrootcert",
 		"PGSSLPASSWORD":        "sslpassword",
+		"PGSSLNEGOTIATION":     "sslnegotiation",
 		"PGTARGETSESSIONATTRS": "target_session_attrs",
 		"PGSERVICE":            "service",
 		"PGSERVICEFILE":        "servicefile",
+		"PGTZ":                 "timezone",
+		"PGOPTIONS":            "options",
 	}
 
 	for envname, realname := range nameMap {
@@ -646,6 +657,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 	sslkey := settings["sslkey"]
 	sslpassword := settings["sslpassword"]
 	sslsni := settings["sslsni"]
+	sslnegotiation := settings["sslnegotiation"]
 
 	// Match libpq default behavior
 	if sslmode == "" {
@@ -657,6 +669,13 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 
 	tlsConfig := &tls.Config{}
 
+	if sslnegotiation == "direct" {
+		tlsConfig.NextProtos = []string{"postgresql"}
+		if sslmode == "prefer" {
+			sslmode = "require"
+		}
+	}
+
 	if sslrootcert != "" {
 		var caCertPool *x509.CertPool
 
@@ -696,7 +715,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 		// According to PostgreSQL documentation, if a root CA file exists,
 		// the behavior of sslmode=require should be the same as that of verify-ca
 		//
-		// See https://www.postgresql.org/docs/12/libpq-ssl.html
+		// See https://www.postgresql.org/docs/current/libpq-ssl.html
 		if sslrootcert != "" {
 			goto nextCase
 		}
@@ -767,8 +786,8 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 			if sslpassword != "" {
 				decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
 			}
-			//if sslpassword not provided or has decryption error when use it
-			//try to find sslpassword with callback function
+			// if sslpassword not provided or has decryption error when use it
+			// try to find sslpassword with callback function
 			if sslpassword == "" || decryptedError != nil {
 				if parseConfigOptions.GetSSLPassword != nil {
 					sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
@@ -861,12 +880,12 @@ func makeConnectTimeoutDialFunc(timeout time.Duration) DialFunc {
 // ValidateConnectTargetSessionAttrsReadWrite is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-write.
 func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "on" {
+	if string(result[0].Rows[0][0]) == "on" {
 		return errors.New("read only connection")
 	}
 
@@ -876,12 +895,12 @@ func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgC
 // ValidateConnectTargetSessionAttrsReadOnly is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-only.
 func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "on" {
+	if string(result[0].Rows[0][0]) != "on" {
 		return errors.New("connection is not read only")
 	}
 
@@ -891,12 +910,12 @@ func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgCo
 // ValidateConnectTargetSessionAttrsStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=standby.
 func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return errors.New("server is not in hot standby mode")
 	}
 
@@ -906,12 +925,12 @@ func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPrimary is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=primary.
 func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "t" {
+	if string(result[0].Rows[0][0]) == "t" {
 		return errors.New("server is in standby mode")
 	}
 
@@ -921,12 +940,12 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPreferStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=prefer-standby.
 func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return &NotPreferredError{err: errors.New("server is not in hot standby mode")}
 	}
 
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/errors.go b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
index ec4a6d47..d968d3f0 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
@@ -27,7 +27,7 @@ func Timeout(err error) bool {
 }
 
 // PgError represents an error reported by the PostgreSQL server. See
-// http://www.postgresql.org/docs/11/static/protocol-error-fields.html for
+// http://www.postgresql.org/docs/current/static/protocol-error-fields.html for
 // detailed field description.
 type PgError struct {
 	Severity            string
@@ -112,6 +112,14 @@ type ParseConfigError struct {
 	err        error
 }
 
+func NewParseConfigError(conn, msg string, err error) error {
+	return &ParseConfigError{
+		ConnString: conn,
+		msg:        msg,
+		err:        err,
+	}
+}
+
 func (e *ParseConfigError) Error() string {
 	// Now that ParseConfigError is public and ConnString is available to the developer, perhaps it would be better only
 	// return a static string. That would ensure that the error message cannot leak a password. The ConnString field would
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
index 3c1af347..efb0d61b 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
@@ -28,7 +28,7 @@ func RegisterGSSProvider(newGSSArg NewGSSFunc) {
 
 // GSS provides GSSAPI authentication (e.g., Kerberos).
 type GSS interface {
-	GetInitToken(host string, service string) ([]byte, error)
+	GetInitToken(host, service string) ([]byte, error)
 	GetInitTokenFromSPN(spn string) ([]byte, error)
 	Continue(inToken []byte) (done bool, outToken []byte, err error)
 }
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
index 7efb522a..97141c64 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
@@ -1,6 +1,7 @@
 package pgconn
 
 import (
+	"container/list"
 	"context"
 	"crypto/md5"
 	"crypto/tls"
@@ -134,7 +135,7 @@ func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptio
 //
 // If config.Fallbacks are present they will sequentially be tried in case of error establishing network connection. An
 // authentication error will terminate the chain of attempts (like libpq:
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
 func ConnectConfig(ctx context.Context, config *Config) (*PgConn, error) {
 	// Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from
 	// zero values.
@@ -267,12 +268,15 @@ func connectPreferred(ctx context.Context, config *Config, connectOneConfigs []*
 
 		var pgErr *PgError
 		if errors.As(err, &pgErr) {
-			const ERRCODE_INVALID_PASSWORD = "28P01"                    // wrong password
-			const ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION = "28000" // wrong password or bad pg_hba.conf settings
-			const ERRCODE_INVALID_CATALOG_NAME = "3D000"                // db does not exist
-			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501"              // missing connect privilege
+			// pgx will try next host even if libpq does not in certain cases (see #2246)
+			// consider change for the next major version
+
+			const ERRCODE_INVALID_PASSWORD = "28P01"
+			const ERRCODE_INVALID_CATALOG_NAME = "3D000"   // db does not exist
+			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501" // missing connect privilege
+
+			// auth failed due to invalid password, db does not exist or user has no permission
 			if pgErr.Code == ERRCODE_INVALID_PASSWORD ||
-				pgErr.Code == ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION && c.tlsConfig != nil ||
 				pgErr.Code == ERRCODE_INVALID_CATALOG_NAME ||
 				pgErr.Code == ERRCODE_INSUFFICIENT_PRIVILEGE {
 				return nil, allErrors
@@ -321,7 +325,15 @@ func connectOne(ctx context.Context, config *Config, connectConfig *connectOneCo
 	if connectConfig.tlsConfig != nil {
 		pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn})
 		pgConn.contextWatcher.Watch(ctx)
-		tlsConn, err := startTLS(pgConn.conn, connectConfig.tlsConfig)
+		var (
+			tlsConn net.Conn
+			err     error
+		)
+		if config.SSLNegotiation == "direct" {
+			tlsConn = tls.Client(pgConn.conn, connectConfig.tlsConfig)
+		} else {
+			tlsConn, err = startTLS(pgConn.conn, connectConfig.tlsConfig)
+		}
 		pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
 		if err != nil {
 			pgConn.conn.Close()
@@ -979,7 +991,8 @@ func noticeResponseToNotice(msg *pgproto3.NoticeResponse) *Notice {
 
 // CancelRequest sends a cancel request to the PostgreSQL server. It returns an error if unable to deliver the cancel
 // request, but lack of an error does not ensure that the query was canceled. As specified in the documentation, there
-// is no way to be sure a query was canceled. See https://www.postgresql.org/docs/11/protocol-flow.html#id-1.10.5.7.9
+// is no way to be sure a query was canceled.
+// See https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-CANCELING-REQUESTS
 func (pgConn *PgConn) CancelRequest(ctx context.Context) error {
 	// Open a cancellation request to the same server. The address is taken from the net.Conn directly instead of reusing
 	// the connection config. This is important in high availability configurations where fallback connections may be
@@ -1128,7 +1141,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader {
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1154,7 +1167,7 @@ func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues []
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1361,7 +1374,14 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 				close(pgConn.cleanupDone)
 				return CommandTag{}, normalizeTimeoutError(ctx, err)
 			}
-			msg, _ := pgConn.receiveMessage()
+			// peekMessage never returns err in the bufferingReceive mode - it only forwards the bufferingReceive variables.
+			// Therefore, the only case for receiveMessage to return err is during handling of the ErrorResponse message type
+			// and using pgOnError handler to determine the connection is no longer valid (and thus closing the conn).
+			msg, serverError := pgConn.receiveMessage()
+			if serverError != nil {
+				close(abortCopyChan)
+				return CommandTag{}, serverError
+			}
 
 			switch msg := msg.(type) {
 			case *pgproto3.ErrorResponse:
@@ -1408,9 +1428,8 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 
 // MultiResultReader is a reader for a command that could return multiple results such as Exec or ExecBatch.
 type MultiResultReader struct {
-	pgConn   *PgConn
-	ctx      context.Context
-	pipeline *Pipeline
+	pgConn *PgConn
+	ctx    context.Context
 
 	rr *ResultReader
 
@@ -1443,12 +1462,8 @@ func (mrr *MultiResultReader) receiveMessage() (pgproto3.BackendMessage, error)
 	switch msg := msg.(type) {
 	case *pgproto3.ReadyForQuery:
 		mrr.closed = true
-		if mrr.pipeline != nil {
-			mrr.pipeline.expectedReadyForQueryCount--
-		} else {
-			mrr.pgConn.contextWatcher.Unwatch()
-			mrr.pgConn.unlock()
-		}
+		mrr.pgConn.contextWatcher.Unwatch()
+		mrr.pgConn.unlock()
 	case *pgproto3.ErrorResponse:
 		mrr.err = ErrorResponseToPgError(msg)
 	}
@@ -1672,7 +1687,11 @@ func (rr *ResultReader) receiveMessage() (msg pgproto3.BackendMessage, err error
 	case *pgproto3.EmptyQueryResponse:
 		rr.concludeCommand(CommandTag{}, nil)
 	case *pgproto3.ErrorResponse:
-		rr.concludeCommand(CommandTag{}, ErrorResponseToPgError(msg))
+		pgErr := ErrorResponseToPgError(msg)
+		if rr.pipeline != nil {
+			rr.pipeline.state.HandleError(pgErr)
+		}
+		rr.concludeCommand(CommandTag{}, pgErr)
 	}
 
 	return msg, nil
@@ -1701,7 +1720,7 @@ type Batch struct {
 }
 
 // ExecParams appends an ExecParams command to the batch. See PgConn.ExecParams for parameter descriptions.
-func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1714,7 +1733,7 @@ func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uin
 }
 
 // ExecPrepared appends an ExecPrepared e command to the batch. See PgConn.ExecPrepared for parameter descriptions.
-func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1773,9 +1792,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 
 	batch.buf, batch.err = (&pgproto3.Sync{}).Encode(batch.buf)
 	if batch.err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, batch.err)
 		multiResult.closed = true
-		multiResult.err = batch.err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1783,9 +1803,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 	defer pgConn.exitPotentialWriteReadDeadlock()
 	_, err := pgConn.conn.Write(batch.buf)
 	if err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, err)
 		multiResult.closed = true
-		multiResult.err = err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1999,9 +2020,7 @@ type Pipeline struct {
 	conn *PgConn
 	ctx  context.Context
 
-	expectedReadyForQueryCount int
-	pendingSync                bool
-
+	state  pipelineState
 	err    error
 	closed bool
 }
@@ -2012,6 +2031,122 @@ type PipelineSync struct{}
 // CloseComplete is returned by GetResults when a CloseComplete message is received.
 type CloseComplete struct{}
 
+type pipelineRequestType int
+
+const (
+	pipelineNil pipelineRequestType = iota
+	pipelinePrepare
+	pipelineQueryParams
+	pipelineQueryPrepared
+	pipelineDeallocate
+	pipelineSyncRequest
+	pipelineFlushRequest
+)
+
+type pipelineRequestEvent struct {
+	RequestType       pipelineRequestType
+	WasSentToServer   bool
+	BeforeFlushOrSync bool
+}
+
+type pipelineState struct {
+	requestEventQueue          list.List
+	lastRequestType            pipelineRequestType
+	pgErr                      *PgError
+	expectedReadyForQueryCount int
+}
+
+func (s *pipelineState) Init() {
+	s.requestEventQueue.Init()
+	s.lastRequestType = pipelineNil
+}
+
+func (s *pipelineState) RegisterSendingToServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.WasSentToServer {
+			return
+		}
+		val.WasSentToServer = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) registerFlushingBufferOnServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.BeforeFlushOrSync {
+			return
+		}
+		val.BeforeFlushOrSync = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) PushBackRequestType(req pipelineRequestType) {
+	if req == pipelineNil {
+		return
+	}
+
+	if req != pipelineFlushRequest {
+		s.requestEventQueue.PushBack(pipelineRequestEvent{RequestType: req})
+	}
+	if req == pipelineFlushRequest || req == pipelineSyncRequest {
+		s.registerFlushingBufferOnServer()
+	}
+	s.lastRequestType = req
+
+	if req == pipelineSyncRequest {
+		s.expectedReadyForQueryCount++
+	}
+}
+
+func (s *pipelineState) ExtractFrontRequestType() pipelineRequestType {
+	for {
+		elem := s.requestEventQueue.Front()
+		if elem == nil {
+			return pipelineNil
+		}
+		val := elem.Value.(pipelineRequestEvent)
+		if !(val.WasSentToServer && val.BeforeFlushOrSync) {
+			return pipelineNil
+		}
+
+		s.requestEventQueue.Remove(elem)
+		if val.RequestType == pipelineSyncRequest {
+			s.pgErr = nil
+		}
+		if s.pgErr == nil {
+			return val.RequestType
+		}
+	}
+}
+
+func (s *pipelineState) HandleError(err *PgError) {
+	s.pgErr = err
+}
+
+func (s *pipelineState) HandleReadyForQuery() {
+	s.expectedReadyForQueryCount--
+}
+
+func (s *pipelineState) PendingSync() bool {
+	var notPendingSync bool
+
+	if elem := s.requestEventQueue.Back(); elem != nil {
+		val := elem.Value.(pipelineRequestEvent)
+		notPendingSync = (val.RequestType == pipelineSyncRequest) && val.WasSentToServer
+	} else {
+		notPendingSync = (s.lastRequestType == pipelineSyncRequest) || (s.lastRequestType == pipelineNil)
+	}
+
+	return !notPendingSync
+}
+
+func (s *pipelineState) ExpectedReadyForQuery() int {
+	return s.expectedReadyForQueryCount
+}
+
 // StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
 // to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
 // to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
@@ -2020,16 +2155,21 @@ type CloseComplete struct{}
 // Prefer ExecBatch when only sending one group of queries at once.
 func (pgConn *PgConn) StartPipeline(ctx context.Context) *Pipeline {
 	if err := pgConn.lock(); err != nil {
-		return &Pipeline{
+		pipeline := &Pipeline{
 			closed: true,
 			err:    err,
 		}
+		pipeline.state.Init()
+
+		return pipeline
 	}
 
 	pgConn.pipeline = Pipeline{
 		conn: pgConn,
 		ctx:  ctx,
 	}
+	pgConn.pipeline.state.Init()
+
 	pipeline := &pgConn.pipeline
 
 	if ctx != context.Background() {
@@ -2052,10 +2192,10 @@ func (p *Pipeline) SendPrepare(name, sql string, paramOIDs []uint32) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Name: name, Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelinePrepare)
 }
 
 // SendDeallocate deallocates a prepared statement.
@@ -2063,34 +2203,65 @@ func (p *Pipeline) SendDeallocate(name string) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelineDeallocate)
 }
 
 // SendQueryParams is the pipeline version of *PgConn.QueryParams.
-func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryParams)
 }
 
 // SendQueryPrepared is the pipeline version of *PgConn.QueryPrepared.
-func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendBind(&pgproto3.Bind{PreparedStatement: stmtName, ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryPrepared)
+}
+
+// SendFlushRequest sends a request for the server to flush its output buffer.
+//
+// The server flushes its output buffer automatically as a result of Sync being called,
+// or on any request when not in pipeline mode; this function is useful to cause the server
+// to flush its output buffer in pipeline mode without establishing a synchronization point.
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendFlushRequest.
+func (p *Pipeline) SendFlushRequest() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.Send(&pgproto3.Flush{})
+	p.state.PushBackRequestType(pipelineFlushRequest)
+}
+
+// SendPipelineSync marks a synchronization point in a pipeline by sending a sync message
+// without flushing the send buffer. This serves as the delimiter of an implicit
+// transaction and an error recovery point.
+//
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendPipelineSync.
+func (p *Pipeline) SendPipelineSync() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.SendSync(&pgproto3.Sync{})
+	p.state.PushBackRequestType(pipelineSyncRequest)
 }
 
 // Flush flushes the queued requests without establishing a synchronization point.
@@ -2115,28 +2286,14 @@ func (p *Pipeline) Flush() error {
 		return err
 	}
 
+	p.state.RegisterSendingToServer()
 	return nil
 }
 
 // Sync establishes a synchronization point and flushes the queued requests.
 func (p *Pipeline) Sync() error {
-	if p.closed {
-		if p.err != nil {
-			return p.err
-		}
-		return errors.New("pipeline closed")
-	}
-
-	p.conn.frontend.SendSync(&pgproto3.Sync{})
-	err := p.Flush()
-	if err != nil {
-		return err
-	}
-
-	p.pendingSync = false
-	p.expectedReadyForQueryCount++
-
-	return nil
+	p.SendPipelineSync()
+	return p.Flush()
 }
 
 // GetResults gets the next results. If results are present, results may be a *ResultReader, *StatementDescription, or
@@ -2150,7 +2307,7 @@ func (p *Pipeline) GetResults() (results any, err error) {
 		return nil, errors.New("pipeline closed")
 	}
 
-	if p.expectedReadyForQueryCount == 0 {
+	if p.state.ExtractFrontRequestType() == pipelineNil {
 		return nil, nil
 	}
 
@@ -2195,13 +2352,13 @@ func (p *Pipeline) getResults() (results any, err error) {
 		case *pgproto3.CloseComplete:
 			return &CloseComplete{}, nil
 		case *pgproto3.ReadyForQuery:
-			p.expectedReadyForQueryCount--
+			p.state.HandleReadyForQuery()
 			return &PipelineSync{}, nil
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		}
-
 	}
 }
 
@@ -2231,6 +2388,7 @@ func (p *Pipeline) getResultsPrepare() (*StatementDescription, error) {
 		// These should never happen here. But don't take chances that could lead to a deadlock.
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		case *pgproto3.CommandComplete:
 			p.conn.asyncClose()
@@ -2250,7 +2408,7 @@ func (p *Pipeline) Close() error {
 
 	p.closed = true
 
-	if p.pendingSync {
+	if p.state.PendingSync() {
 		p.conn.asyncClose()
 		p.err = errors.New("pipeline has unsynced requests")
 		p.conn.contextWatcher.Unwatch()
@@ -2259,7 +2417,7 @@ func (p *Pipeline) Close() error {
 		return p.err
 	}
 
-	for p.expectedReadyForQueryCount > 0 {
+	for p.state.ExpectedReadyForQuery() > 0 {
 		_, err := p.getResults()
 		if err != nil {
 			p.err = err
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
index ac2962e9..415e1a24 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationCleartextPassword is a message sent from the backend indicating that a clear-text password is required.
-type AuthenticationCleartextPassword struct {
-}
+type AuthenticationCleartextPassword struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationCleartextPassword) Backend() {}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
index ec11d39f..98c0b2d6 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationOk is a message sent from the backend indicating that authentication was successful.
-type AuthenticationOk struct {
-}
+type AuthenticationOk struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationOk) Backend() {}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
index d146c338..28cff049 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
@@ -175,7 +175,13 @@ func (b *Backend) Receive() (FrontendMessage, error) {
 		}
 
 		b.msgType = header[0]
-		b.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4
+
+		msgLength := int(binary.BigEndian.Uint32(header[1:]))
+		if msgLength < 4 {
+			return nil, fmt.Errorf("invalid message length: %d", msgLength)
+		}
+
+		b.bodyLen = msgLength - 4
 		if b.maxBodyLen > 0 && b.bodyLen > b.maxBodyLen {
 			return nil, &ExceededMaxBodyLenErr{b.maxBodyLen, b.bodyLen}
 		}
@@ -282,9 +288,10 @@ func (b *Backend) SetAuthType(authType uint32) error {
 	return nil
 }
 
-// SetMaxBodyLen sets the maximum length of a message body in octets. If a message body exceeds this length, Receive will return
-// an error. This is useful for protecting against malicious clients that send large messages with the intent of
-// causing memory exhaustion.
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against malicious clients that send
+// large messages with the intent of causing memory exhaustion.
 // The default value is 0.
 // If maxBodyLen is 0, then no maximum is enforced.
 func (b *Backend) SetMaxBodyLen(maxBodyLen int) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
index 040814db..c3421a9b 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
@@ -4,8 +4,7 @@ import (
 	"encoding/json"
 )
 
-type CopyDone struct {
-}
+type CopyDone struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*CopyDone) Backend() {}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
index b41abbe1..056e547c 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
@@ -54,6 +54,7 @@ type Frontend struct {
 	portalSuspended                 PortalSuspended
 
 	bodyLen    int
+	maxBodyLen int // maxBodyLen is the maximum length of a message body in octets. If a message body exceeds this length, Receive will return an error.
 	msgType    byte
 	partialMsg bool
 	authType   uint32
@@ -317,6 +318,9 @@ func (f *Frontend) Receive() (BackendMessage, error) {
 		}
 
 		f.bodyLen = msgLength - 4
+		if f.maxBodyLen > 0 && f.bodyLen > f.maxBodyLen {
+			return nil, &ExceededMaxBodyLenErr{f.maxBodyLen, f.bodyLen}
+		}
 		f.partialMsg = true
 	}
 
@@ -452,3 +456,13 @@ func (f *Frontend) GetAuthType() uint32 {
 func (f *Frontend) ReadBufferLen() int {
 	return f.cr.wp - f.cr.rp
 }
+
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against a corrupted server that sends
+// messages with incorrect length, which can cause memory exhaustion.
+// The default value is 0.
+// If maxBodyLen is 0, then no maximum is enforced.
+func (f *Frontend) SetMaxBodyLen(maxBodyLen int) {
+	f.maxBodyLen = maxBodyLen
+}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
index 70cb20cd..122d1341 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
@@ -10,8 +10,7 @@ import (
 
 const gssEncReqNumber = 80877104
 
-type GSSEncRequest struct {
-}
+type GSSEncRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*GSSEncRequest) Frontend() {}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
index d820d327..67b78515 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
@@ -12,7 +12,7 @@ type PasswordMessage struct {
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*PasswordMessage) Frontend() {}
 
-// Frontend identifies this message as an authentication response.
+// InitialResponse identifies this message as an authentication response.
 func (*PasswordMessage) InitialResponse() {}
 
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
index dc2a4ddf..c40a2261 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
@@ -56,7 +56,6 @@ func (*RowDescription) Backend() {}
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
 // type identifier and 4 byte message length.
 func (dst *RowDescription) Decode(src []byte) error {
-
 	if len(src) < 2 {
 		return &invalidMessageFormatErr{messageType: "RowDescription"}
 	}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
index b0fc2847..bdfc7c42 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
@@ -10,8 +10,7 @@ import (
 
 const sslRequestNumber = 80877103
 
-type SSLRequest struct {
-}
+type SSLRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*SSLRequest) Frontend() {}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/array.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/array.go
index 06b824ad..872a0889 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/array.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/array.go
@@ -374,8 +374,8 @@ func quoteArrayElementIfNeeded(src string) string {
 	return src
 }
 
-// Array represents a PostgreSQL array for T. It implements the ArrayGetter and ArraySetter interfaces. It preserves
-// PostgreSQL dimensions and custom lower bounds. Use FlatArray if these are not needed.
+// Array represents a PostgreSQL array for T. It implements the [ArrayGetter] and [ArraySetter] interfaces. It preserves
+// PostgreSQL dimensions and custom lower bounds. Use [FlatArray] if these are not needed.
 type Array[T any] struct {
 	Elements []T
 	Dims     []ArrayDimension
@@ -419,8 +419,8 @@ func (a Array[T]) ScanIndexType() any {
 	return new(T)
 }
 
-// FlatArray implements the ArrayGetter and ArraySetter interfaces for any slice of T. It ignores PostgreSQL dimensions
-// and custom lower bounds. Use Array to preserve these.
+// FlatArray implements the [ArrayGetter] and [ArraySetter] interfaces for any slice of T. It ignores PostgreSQL dimensions
+// and custom lower bounds. Use [Array] to preserve these.
 type FlatArray[T any] []T
 
 func (a FlatArray[T]) Dimensions() []ArrayDimension {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bits.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
index e7a1d016..2a48e354 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
@@ -23,16 +23,18 @@ type Bits struct {
 	Valid bool
 }
 
+// ScanBits implements the [BitsScanner] interface.
 func (b *Bits) ScanBits(v Bits) error {
 	*b = v
 	return nil
 }
 
+// BitsValue implements the [BitsValuer] interface.
 func (b Bits) BitsValue() (Bits, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bits) Scan(src any) error {
 	if src == nil {
 		*dst = Bits{}
@@ -47,7 +49,7 @@ func (dst *Bits) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bits) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBitsCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BitsCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bool.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
index 71caffa7..955f01fe 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
@@ -22,16 +22,18 @@ type Bool struct {
 	Valid bool
 }
 
+// ScanBool implements the [BoolScanner] interface.
 func (b *Bool) ScanBool(v Bool) error {
 	*b = v
 	return nil
 }
 
+// BoolValue implements the [BoolValuer] interface.
 func (b Bool) BoolValue() (Bool, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bool) Scan(src any) error {
 	if src == nil {
 		*dst = Bool{}
@@ -61,7 +63,7 @@ func (dst *Bool) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bool) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Bool) Value() (driver.Value, error) {
 	return src.Bool, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Bool) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -82,6 +85,7 @@ func (src Bool) MarshalJSON() ([]byte, error) {
 	}
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Bool) UnmarshalJSON(b []byte) error {
 	var v *bool
 	err := json.Unmarshal(b, &v)
@@ -200,7 +204,6 @@ func (encodePlanBoolCodecTextBool) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (BoolCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -328,7 +331,7 @@ func (scanPlanTextAnyToBoolScanner) Scan(src []byte, dst any) error {
 	return s.ScanBool(Bool{Bool: v, Valid: true})
 }
 
-// https://www.postgresql.org/docs/11/datatype-boolean.html
+// https://www.postgresql.org/docs/current/datatype-boolean.html
 func planTextToBool(src []byte) (bool, error) {
 	s := string(bytes.ToLower(bytes.TrimSpace(src)))
 
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/box.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/box.go
index 887d268b..d243f58e 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/box.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/box.go
@@ -24,16 +24,18 @@ type Box struct {
 	Valid bool
 }
 
+// ScanBox implements the [BoxScanner] interface.
 func (b *Box) ScanBox(v Box) error {
 	*b = v
 	return nil
 }
 
+// BoxValue implements the [BoxValuer] interface.
 func (b Box) BoxValue() (Box, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Box) Scan(src any) error {
 	if src == nil {
 		*dst = Box{}
@@ -48,7 +50,7 @@ func (dst *Box) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Box) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBoxCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BoxCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
index b39d3fa1..84964425 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
@@ -527,6 +527,7 @@ func (w *netIPNetWrapper) ScanNetipPrefix(v netip.Prefix) error {
 
 	return nil
 }
+
 func (w netIPNetWrapper) NetipPrefixValue() (netip.Prefix, error) {
 	ip, ok := netip.AddrFromSlice(w.IP)
 	if !ok {
@@ -881,7 +882,6 @@ func (a *anyMultiDimSliceArray) SetDimensions(dimensions []ArrayDimension) error
 
 		return nil
 	}
-
 }
 
 func (a *anyMultiDimSliceArray) makeMultidimensionalSlice(sliceType reflect.Type, dimensions []ArrayDimension, flatSlice reflect.Value, flatSliceIdx int) reflect.Value {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
index a247705e..6c4f0c5e 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
@@ -148,7 +148,6 @@ func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf
 }
 
 func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/circle.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
index e8f118cc..fb9b4c11 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
@@ -25,16 +25,18 @@ type Circle struct {
 	Valid bool
 }
 
+// ScanCircle implements the [CircleScanner] interface.
 func (c *Circle) ScanCircle(v Circle) error {
 	*c = v
 	return nil
 }
 
+// CircleValue implements the [CircleValuer] interface.
 func (c Circle) CircleValue() (Circle, error) {
 	return c, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Circle) Scan(src any) error {
 	if src == nil {
 		*dst = Circle{}
@@ -49,7 +51,7 @@ func (dst *Circle) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Circle) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/composite.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
index fb372325..598cf7af 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
@@ -276,7 +276,6 @@ func (c *CompositeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byt
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
 
 type CompositeBinaryScanner struct {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/date.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/date.go
index 784b16de..44705686 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/date.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/date.go
@@ -26,11 +26,13 @@ type Date struct {
 	Valid            bool
 }
 
+// ScanDate implements the [DateScanner] interface.
 func (d *Date) ScanDate(v Date) error {
 	*d = v
 	return nil
 }
 
+// DateValue implements the [DateValuer] interface.
 func (d Date) DateValue() (Date, error) {
 	return d, nil
 }
@@ -40,7 +42,7 @@ const (
 	infinityDayOffset         = 2147483647
 )
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Date) Scan(src any) error {
 	if src == nil {
 		*dst = Date{}
@@ -58,7 +60,7 @@ func (dst *Date) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Date) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Date) Value() (driver.Value, error) {
 	return src.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Date) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -89,6 +92,7 @@ func (src Date) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Date) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -223,7 +227,6 @@ func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/doc.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
index 7687ea8f..83dfc5de 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
@@ -53,8 +53,8 @@ similar fashion to database/sql. The second is to use a pointer to a pointer.
         return err
     }
 
-When using nullable pgtype types as parameters for queries, one has to remember
-to explicitly set their Valid field to true, otherwise the parameter's value will be NULL.
+When using nullable pgtype types as parameters for queries, one has to remember to explicitly set their Valid field to
+true, otherwise the parameter's value will be NULL.
 
 JSON Support
 
@@ -159,11 +159,16 @@ example_child_records_test.go for an example.
 
 Overview of Scanning Implementation
 
-The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID
-from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for
-scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are
-interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner and
-PointValuer interfaces.
+The first step is to use the OID to lookup the correct Codec. The Map will call the Codec's PlanScan method to get a
+plan for scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types
+are interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner
+and PointValuer interfaces.
+
+If a Go value is not supported directly by a Codec then Map will try see if it is a sql.Scanner. If is then that
+interface will be used to scan the value. Most sql.Scanners require the input to be in the text format (e.g. UUIDs and
+numeric). However, pgx will typically have received the value in the binary format. In this case the binary value will be
+parsed, reencoded as text, and then passed to the sql.Scanner. This may incur additional overhead for query results with
+a large number of affected values.
 
 If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again.
 For example, Int8Codec does not support scanning into a renamed type (e.g. type myInt64 int64). But Map will detect that
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float4.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
index 8646d9d2..241a25ad 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
@@ -16,26 +16,29 @@ type Float4 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float4) ScanFloat64(n Float8) error {
 	*f = Float4{Float32: float32(n.Float64), Valid: n.Valid}
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float4) Float64Value() (Float8, error) {
 	return Float8{Float64: float64(f.Float32), Valid: f.Valid}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float4) ScanInt64(n Int8) error {
 	*f = Float4{Float32: float32(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float32), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float4) Scan(src any) error {
 	if src == nil {
 		*f = Float4{}
@@ -58,7 +61,7 @@ func (f *Float4) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float4) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -66,6 +69,7 @@ func (f Float4) Value() (driver.Value, error) {
 	return float64(f.Float32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float4) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -73,6 +77,7 @@ func (f Float4) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float32)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float4) UnmarshalJSON(b []byte) error {
 	var n *float32
 	err := json.Unmarshal(b, &n)
@@ -170,7 +175,6 @@ func (encodePlanFloat4CodecBinaryInt64Valuer) Encode(value any, buf []byte) (new
 }
 
 func (Float4Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float8.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
index 9c923c9a..54d6781e 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
@@ -24,26 +24,29 @@ type Float8 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float8) ScanFloat64(n Float8) error {
 	*f = n
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float8) Float64Value() (Float8, error) {
 	return f, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float8) ScanInt64(n Int8) error {
 	*f = Float8{Float64: float64(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float64), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float8) Scan(src any) error {
 	if src == nil {
 		*f = Float8{}
@@ -66,7 +69,7 @@ func (f *Float8) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float8) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -74,6 +77,7 @@ func (f Float8) Value() (driver.Value, error) {
 	return f.Float64, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float8) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -81,6 +85,7 @@ func (f Float8) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float64)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float8) UnmarshalJSON(b []byte) error {
 	var n *float64
 	err := json.Unmarshal(b, &n)
@@ -208,7 +213,6 @@ func (encodePlanTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (Float8Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
index 2f34f4c9..ef864928 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
@@ -22,16 +22,18 @@ type HstoreValuer interface {
 // associated with its keys.
 type Hstore map[string]*string
 
+// ScanHstore implements the [HstoreScanner] interface.
 func (h *Hstore) ScanHstore(v Hstore) error {
 	*h = v
 	return nil
 }
 
+// HstoreValue implements the [HstoreValuer] interface.
 func (h Hstore) HstoreValue() (Hstore, error) {
 	return h, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (h *Hstore) Scan(src any) error {
 	if src == nil {
 		*h = nil
@@ -46,7 +48,7 @@ func (h *Hstore) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (h Hstore) Value() (driver.Value, error) {
 	if h == nil {
 		return nil, nil
@@ -162,7 +164,6 @@ func (encodePlanHstoreCodecText) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (HstoreCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -298,7 +299,7 @@ func (p *hstoreParser) consume() (b byte, end bool) {
 	return b, false
 }
 
-func unexpectedByteErr(actualB byte, expectedB byte) error {
+func unexpectedByteErr(actualB, expectedB byte) error {
 	return fmt.Errorf("expected '%c' ('%#v'); found '%c' ('%#v')", expectedB, expectedB, actualB, actualB)
 }
 
@@ -316,7 +317,7 @@ func (p *hstoreParser) consumeExpectedByte(expectedB byte) error {
 
 // consumeExpected2 consumes two expected bytes or returns an error.
 // This was a bit faster than using a string argument (better inlining? Not sure).
-func (p *hstoreParser) consumeExpected2(one byte, two byte) error {
+func (p *hstoreParser) consumeExpected2(one, two byte) error {
 	if p.pos+2 > len(p.str) {
 		return errors.New("unexpected end of string")
 	}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/inet.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
index 6ca10ea0..b92edb23 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
@@ -24,7 +24,7 @@ type NetipPrefixValuer interface {
 	NetipPrefixValue() (netip.Prefix, error)
 }
 
-// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are netip.Prefix and netip.Addr. If
+// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are [netip.Prefix] and [netip.Addr]. If
 // IsValid() is false then they are treated as SQL NULL.
 type InetCodec struct{}
 
@@ -107,7 +107,6 @@ func (encodePlanInetCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (InetCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go
index 90a20a26..d1b8eb61 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go
@@ -1,4 +1,5 @@
-// Do not edit. Generated from pgtype/int.go.erb
+// Code generated from pgtype/int.go.erb. DO NOT EDIT.
+
 package pgtype
 
 import (
@@ -25,7 +26,7 @@ type Int2 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int2) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int2{}
@@ -43,11 +44,12 @@ func (dst *Int2) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int2) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int16), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int2) Scan(src any) error {
 	if src == nil {
 		*dst = Int2{}
@@ -86,7 +88,7 @@ func (dst *Int2) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int2) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -94,6 +96,7 @@ func (src Int2) Value() (driver.Value, error) {
 	return int64(src.Int16), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int2) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -101,6 +104,7 @@ func (src Int2) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int16), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int2) UnmarshalJSON(b []byte) error {
 	var n *int16
 	err := json.Unmarshal(b, &n)
@@ -585,7 +589,7 @@ type Int4 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int4) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int4{}
@@ -603,11 +607,12 @@ func (dst *Int4) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int32), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int4) Scan(src any) error {
 	if src == nil {
 		*dst = Int4{}
@@ -646,7 +651,7 @@ func (dst *Int4) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int4) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -654,6 +659,7 @@ func (src Int4) Value() (driver.Value, error) {
 	return int64(src.Int32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int4) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -661,6 +667,7 @@ func (src Int4) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int32), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int4) UnmarshalJSON(b []byte) error {
 	var n *int32
 	err := json.Unmarshal(b, &n)
@@ -1156,7 +1163,7 @@ type Int8 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int8) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int8{}
@@ -1174,11 +1181,12 @@ func (dst *Int8) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int64), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int8) Scan(src any) error {
 	if src == nil {
 		*dst = Int8{}
@@ -1217,7 +1225,7 @@ func (dst *Int8) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int8) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -1225,6 +1233,7 @@ func (src Int8) Value() (driver.Value, error) {
 	return int64(src.Int64), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int8) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -1232,6 +1241,7 @@ func (src Int8) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int64), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int8) UnmarshalJSON(b []byte) error {
 	var n *int64
 	err := json.Unmarshal(b, &n)
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
index e0c8b7a3..c2d40f60 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
@@ -27,7 +27,7 @@ type Int<%= pg_byte_size %> struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int<%= pg_byte_size %>{}
@@ -45,11 +45,12 @@ func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	if src == nil {
 		*dst = Int<%= pg_byte_size %>{}
@@ -88,7 +89,7 @@ func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +97,7 @@ func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	return int64(src.Int<%= pg_bit_size %>), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -103,6 +105,7 @@ func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error {
 	var n *int<%= pg_bit_size %>
 	err := json.Unmarshal(b, &n)
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
index 0175700a..6f401153 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
@@ -25,7 +25,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go
       rows, _ := conn.Query(
         ctx,
         `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>},  func() error { return nil })
       if err != nil {
@@ -49,7 +49,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array
       rows, _ := conn.Query(
         ctx,
         `select array_agg(n) from generate_series(1, <%= array_size %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{&v},  func() error { return nil })
       if err != nil {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/interval.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
index 4b511629..ba5e818f 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
@@ -33,16 +33,18 @@ type Interval struct {
 	Valid        bool
 }
 
+// ScanInterval implements the [IntervalScanner] interface.
 func (interval *Interval) ScanInterval(v Interval) error {
 	*interval = v
 	return nil
 }
 
+// IntervalValue implements the [IntervalValuer] interface.
 func (interval Interval) IntervalValue() (Interval, error) {
 	return interval, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (interval *Interval) Scan(src any) error {
 	if src == nil {
 		*interval = Interval{}
@@ -57,7 +59,7 @@ func (interval *Interval) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (interval Interval) Value() (driver.Value, error) {
 	if !interval.Valid {
 		return nil, nil
@@ -157,7 +159,6 @@ func (encodePlanIntervalCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (IntervalCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/json.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/json.go
index c2aa0d3b..60aa2b71 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/json.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/json.go
@@ -71,6 +71,27 @@ func (c *JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Enco
 	}
 }
 
+// JSON needs its on scan plan for pointers to handle 'null'::json(b).
+// Consider making pointerPointerScanPlan more flexible in the future.
+type jsonPointerScanPlan struct {
+	next ScanPlan
+}
+
+func (p jsonPointerScanPlan) Scan(src []byte, dst any) error {
+	el := reflect.ValueOf(dst).Elem()
+	if src == nil || string(src) == "null" {
+		el.SetZero()
+		return nil
+	}
+
+	el.Set(reflect.New(el.Type().Elem()))
+	if p.next != nil {
+		return p.next.Scan(src, el.Interface())
+	}
+
+	return nil
+}
+
 type encodePlanJSONCodecEitherFormatString struct{}
 
 func (encodePlanJSONCodecEitherFormatString) Encode(value any, buf []byte) (newBuf []byte, err error) {
@@ -117,41 +138,35 @@ func (e *encodePlanJSONCodecEitherFormatMarshal) Encode(value any, buf []byte) (
 	return buf, nil
 }
 
-func (c *JSONCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+func (c *JSONCodec) PlanScan(m *Map, oid uint32, formatCode int16, target any) ScanPlan {
+	return c.planScan(m, oid, formatCode, target, 0)
+}
+
+// JSON cannot fallback to pointerPointerScanPlan because of 'null'::json(b),
+// so we need to duplicate the logic here.
+func (c *JSONCodec) planScan(m *Map, oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	switch target.(type) {
 	case *string:
-		return scanPlanAnyToString{}
-
-	case **string:
-		// This is to fix **string scanning. It seems wrong to special case **string, but it's not clear what a better
-		// solution would be.
-		//
-		// https://github.com/jackc/pgx/issues/1470 -- **string
-		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
-
-		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
-				if _, failed := nextPlan.(*scanPlanFail); !failed {
-					wrapperPlan.SetNext(nextPlan)
-					return wrapperPlan
-				}
-			}
-		}
-
+		return &scanPlanAnyToString{}
 	case *[]byte:
-		return scanPlanJSONToByteSlice{}
+		return &scanPlanJSONToByteSlice{}
 	case BytesScanner:
-		return scanPlanBinaryBytesToBytesScanner{}
-
-	// Cannot rely on sql.Scanner being handled later because scanPlanJSONToJSONUnmarshal will take precedence.
-	//
-	// https://github.com/jackc/pgx/issues/1418
+		return &scanPlanBinaryBytesToBytesScanner{}
 	case sql.Scanner:
-		return &scanPlanSQLScanner{formatCode: format}
+		return &scanPlanSQLScanner{formatCode: formatCode}
 	}
 
-	return &scanPlanJSONToJSONUnmarshal{
-		unmarshal: c.Unmarshal,
+	rv := reflect.ValueOf(target)
+	if rv.Kind() == reflect.Pointer && rv.Elem().Kind() == reflect.Pointer {
+		var plan jsonPointerScanPlan
+		plan.next = c.planScan(m, oid, formatCode, rv.Elem().Interface(), depth+1)
+		return plan
+	} else {
+		return &scanPlanJSONToJSONUnmarshal{unmarshal: c.Unmarshal}
 	}
 }
 
@@ -196,7 +211,12 @@ func (s *scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error {
 		return fmt.Errorf("cannot scan NULL into %T", dst)
 	}
 
-	elem := reflect.ValueOf(dst).Elem()
+	v := reflect.ValueOf(dst)
+	if v.Kind() != reflect.Pointer || v.IsNil() {
+		return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", dst)
+	}
+
+	elem := v.Elem()
 	elem.Set(reflect.Zero(elem.Type()))
 
 	return s.unmarshal(src, dst)
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/line.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/line.go
index 4ae8003e..10efc8ce 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/line.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/line.go
@@ -24,11 +24,13 @@ type Line struct {
 	Valid   bool
 }
 
+// ScanLine implements the [LineScanner] interface.
 func (line *Line) ScanLine(v Line) error {
 	*line = v
 	return nil
 }
 
+// LineValue implements the [LineValuer] interface.
 func (line Line) LineValue() (Line, error) {
 	return line, nil
 }
@@ -37,7 +39,7 @@ func (line *Line) Set(src any) error {
 	return fmt.Errorf("cannot convert %v to Line", src)
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (line *Line) Scan(src any) error {
 	if src == nil {
 		*line = Line{}
@@ -52,7 +54,7 @@ func (line *Line) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (line Line) Value() (driver.Value, error) {
 	if !line.Valid {
 		return nil, nil
@@ -129,7 +131,6 @@ func (encodePlanLineCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LineCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
index 05a86e1c..ed0d40d2 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
@@ -24,16 +24,18 @@ type Lseg struct {
 	Valid bool
 }
 
+// ScanLseg implements the [LsegScanner] interface.
 func (lseg *Lseg) ScanLseg(v Lseg) error {
 	*lseg = v
 	return nil
 }
 
+// LsegValue implements the [LsegValuer] interface.
 func (lseg Lseg) LsegValue() (Lseg, error) {
 	return lseg, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (lseg *Lseg) Scan(src any) error {
 	if src == nil {
 		*lseg = Lseg{}
@@ -48,7 +50,7 @@ func (lseg *Lseg) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (lseg Lseg) Value() (driver.Value, error) {
 	if !lseg.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanLsegCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LsegCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
index e5763788..4fe6dd40 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
@@ -374,7 +374,6 @@ parseValueLoop:
 	}
 
 	return elements, nil
-
 }
 
 func parseRange(buf *bytes.Buffer) (string, error) {
@@ -403,8 +402,8 @@ func parseRange(buf *bytes.Buffer) (string, error) {
 
 // Multirange is a generic multirange type.
 //
-// T should implement RangeValuer and *T should implement RangeScanner. However, there does not appear to be a way to
-// enforce the RangeScanner constraint.
+// T should implement [RangeValuer] and *T should implement [RangeScanner]. However, there does not appear to be a way to
+// enforce the [RangeScanner] constraint.
 type Multirange[T RangeValuer] []T
 
 func (r Multirange[T]) IsNull() bool {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
index 4dbec786..7d236902 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
@@ -27,16 +27,20 @@ const (
 	pgNumericNegInfSign = 0xf000
 )
 
-var big0 *big.Int = big.NewInt(0)
-var big1 *big.Int = big.NewInt(1)
-var big10 *big.Int = big.NewInt(10)
-var big100 *big.Int = big.NewInt(100)
-var big1000 *big.Int = big.NewInt(1000)
+var (
+	big0    *big.Int = big.NewInt(0)
+	big1    *big.Int = big.NewInt(1)
+	big10   *big.Int = big.NewInt(10)
+	big100  *big.Int = big.NewInt(100)
+	big1000 *big.Int = big.NewInt(1000)
+)
 
-var bigNBase *big.Int = big.NewInt(nbase)
-var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
-var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
-var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+var (
+	bigNBase   *big.Int = big.NewInt(nbase)
+	bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
+	bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
+	bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+)
 
 type NumericScanner interface {
 	ScanNumeric(v Numeric) error
@@ -54,15 +58,18 @@ type Numeric struct {
 	Valid            bool
 }
 
+// ScanNumeric implements the [NumericScanner] interface.
 func (n *Numeric) ScanNumeric(v Numeric) error {
 	*n = v
 	return nil
 }
 
+// NumericValue implements the [NumericValuer] interface.
 func (n Numeric) NumericValue() (Numeric, error) {
 	return n, nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (n Numeric) Float64Value() (Float8, error) {
 	if !n.Valid {
 		return Float8{}, nil
@@ -92,6 +99,7 @@ func (n Numeric) Float64Value() (Float8, error) {
 	return Float8{Float64: f, Valid: true}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (n *Numeric) ScanInt64(v Int8) error {
 	if !v.Valid {
 		*n = Numeric{}
@@ -102,6 +110,7 @@ func (n *Numeric) ScanInt64(v Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Numeric) Int64Value() (Int8, error) {
 	if !n.Valid {
 		return Int8{}, nil
@@ -203,7 +212,7 @@ func nbaseDigitsToInt64(src []byte) (accum int64, bytesRead, digitsRead int) {
 	return accum, rp, digits
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (n *Numeric) Scan(src any) error {
 	if src == nil {
 		*n = Numeric{}
@@ -218,7 +227,7 @@ func (n *Numeric) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (n Numeric) Value() (driver.Value, error) {
 	if !n.Valid {
 		return nil, nil
@@ -231,6 +240,7 @@ func (n Numeric) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (n Numeric) MarshalJSON() ([]byte, error) {
 	if !n.Valid {
 		return []byte("null"), nil
@@ -243,6 +253,7 @@ func (n Numeric) MarshalJSON() ([]byte, error) {
 	return n.numberTextBytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (n *Numeric) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte(`null`)) {
 		*n = Numeric{}
@@ -553,7 +564,6 @@ func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) {
 }
 
 func (NumericCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/path.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/path.go
index 73e0ec52..81dc1e5b 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/path.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/path.go
@@ -25,16 +25,18 @@ type Path struct {
 	Valid  bool
 }
 
+// ScanPath implements the [PathScanner] interface.
 func (path *Path) ScanPath(v Path) error {
 	*path = v
 	return nil
 }
 
+// PathValue implements the [PathValuer] interface.
 func (path Path) PathValue() (Path, error) {
 	return path, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (path *Path) Scan(src any) error {
 	if src == nil {
 		*path = Path{}
@@ -49,7 +51,7 @@ func (path *Path) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (path Path) Value() (driver.Value, error) {
 	if !path.Valid {
 		return nil, nil
@@ -154,7 +156,6 @@ func (encodePlanPathCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (PathCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
index bdd9f05c..b3ef3207 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
@@ -29,6 +29,7 @@ const (
 	XMLOID                 = 142
 	XMLArrayOID            = 143
 	JSONArrayOID           = 199
+	XID8ArrayOID           = 271
 	PointOID               = 600
 	LsegOID                = 601
 	PathOID                = 602
@@ -117,6 +118,7 @@ const (
 	TstzmultirangeOID      = 4534
 	DatemultirangeOID      = 4535
 	Int8multirangeOID      = 4536
+	XID8OID                = 5069
 	Int4multirangeArrayOID = 6150
 	NummultirangeArrayOID  = 6151
 	TsmultirangeArrayOID   = 6152
@@ -200,7 +202,6 @@ type Map struct {
 
 	reflectTypeToType map[reflect.Type]*Type
 
-	memoizedScanPlans   map[uint32]map[reflect.Type][2]ScanPlan
 	memoizedEncodePlans map[uint32]map[reflect.Type][2]EncodePlan
 
 	// TryWrapEncodePlanFuncs is a slice of functions that will wrap a value that cannot be encoded by the Codec. Every
@@ -234,7 +235,6 @@ func NewMap() *Map {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -274,9 +274,6 @@ func (m *Map) RegisterType(t *Type) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -290,9 +287,6 @@ func (m *Map) RegisterDefaultPgType(value any, name string) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -395,6 +389,7 @@ type scanPlanSQLScanner struct {
 
 func (plan *scanPlanSQLScanner) Scan(src []byte, dst any) error {
 	scanner := dst.(sql.Scanner)
+
 	if src == nil {
 		// This is necessary because interface value []byte:nil does not equal nil:nil for the binary format path and the
 		// text format path would be converted to empty string.
@@ -449,14 +444,14 @@ func (plan *scanPlanFail) Scan(src []byte, dst any) error {
 		// As a horrible hack try all types to find anything that can scan into dst.
 		for oid := range plan.m.oidToType {
 			// using planScan instead of Scan or PlanScan to avoid polluting the planned scan cache.
-			plan := plan.m.planScan(oid, plan.formatCode, dst)
+			plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 			if _, ok := plan.(*scanPlanFail); !ok {
 				return plan.Scan(src, dst)
 			}
 		}
 		for oid := range defaultMap.oidToType {
 			if _, ok := plan.m.oidToType[oid]; !ok {
-				plan := plan.m.planScan(oid, plan.formatCode, dst)
+				plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 				if _, ok := plan.(*scanPlanFail); !ok {
 					return plan.Scan(src, dst)
 				}
@@ -1064,24 +1059,14 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error {
 
 // PlanScan prepares a plan to scan a value into target.
 func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan {
-	oidMemo := m.memoizedScanPlans[oid]
-	if oidMemo == nil {
-		oidMemo = make(map[reflect.Type][2]ScanPlan)
-		m.memoizedScanPlans[oid] = oidMemo
-	}
-	targetReflectType := reflect.TypeOf(target)
-	typeMemo := oidMemo[targetReflectType]
-	plan := typeMemo[formatCode]
-	if plan == nil {
-		plan = m.planScan(oid, formatCode, target)
-		typeMemo[formatCode] = plan
-		oidMemo[targetReflectType] = typeMemo
-	}
-
-	return plan
+	return m.planScan(oid, formatCode, target, 0)
 }
 
-func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
+func (m *Map) planScan(oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	if target == nil {
 		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
 	}
@@ -1141,7 +1126,7 @@ func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
 
 	for _, f := range m.TryWrapScanPlanFuncs {
 		if wrapperPlan, nextDst, ok := f(target); ok {
-			if nextPlan := m.planScan(oid, formatCode, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, formatCode, nextDst, depth+1); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
@@ -1198,9 +1183,18 @@ func codecDecodeToTextFormat(codec Codec, m *Map, oid uint32, format int16, src
 	}
 }
 
-// PlanEncode returns an Encode plan for encoding value into PostgreSQL format for oid and format. If no plan can be
+// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be
 // found then nil is returned.
 func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
+	return m.planEncodeDepth(oid, format, value, 0)
+}
+
+func (m *Map) planEncodeDepth(oid uint32, format int16, value any, depth int) EncodePlan {
+	// Guard against infinite recursion.
+	if depth > 8 {
+		return nil
+	}
+
 	oidMemo := m.memoizedEncodePlans[oid]
 	if oidMemo == nil {
 		oidMemo = make(map[reflect.Type][2]EncodePlan)
@@ -1210,7 +1204,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	typeMemo := oidMemo[targetReflectType]
 	plan := typeMemo[format]
 	if plan == nil {
-		plan = m.planEncode(oid, format, value)
+		plan = m.planEncode(oid, format, value, depth)
 		typeMemo[format] = plan
 		oidMemo[targetReflectType] = typeMemo
 	}
@@ -1218,7 +1212,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	return plan
 }
 
-func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
+func (m *Map) planEncode(oid uint32, format int16, value any, depth int) EncodePlan {
 	if format == TextFormatCode {
 		switch value.(type) {
 		case string:
@@ -1249,7 +1243,7 @@ func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
 
 	for _, f := range m.TryWrapEncodePlanFuncs {
 		if wrapperPlan, nextValue, ok := f(value); ok {
-			if nextPlan := m.PlanEncode(oid, format, nextValue); nextPlan != nil {
+			if nextPlan := m.planEncodeDepth(oid, format, nextValue, depth+1); nextPlan != nil {
 				wrapperPlan.SetNext(nextPlan)
 				return wrapperPlan
 			}
@@ -2012,30 +2006,11 @@ func (w *sqlScannerWrapper) Scan(src any) error {
 	return w.m.Scan(t.OID, TextFormatCode, bufSrc, w.v)
 }
 
-// canBeNil returns true if value can be nil.
-func canBeNil(value any) bool {
-	refVal := reflect.ValueOf(value)
-	kind := refVal.Kind()
-	switch kind {
-	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
-		return true
-	default:
-		return false
-	}
-}
-
-// valuerReflectType is a reflect.Type for driver.Valuer. It has confusing syntax because reflect.TypeOf returns nil
-// when it's argument is a nil interface value. So we use a pointer to the interface and call Elem to get the actual
-// type. Yuck.
-//
-// This can be simplified in Go 1.22 with reflect.TypeFor.
-//
-// var valuerReflectType = reflect.TypeFor[driver.Valuer]()
-var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+var valuerReflectType = reflect.TypeFor[driver.Valuer]()
 
 // isNilDriverValuer returns true if value is any type of nil unless it implements driver.Valuer. *T is not considered to implement
 // driver.Valuer if it is only implemented by T.
-func isNilDriverValuer(value any) (isNil bool, callNilDriverValuer bool) {
+func isNilDriverValuer(value any) (isNil, callNilDriverValuer bool) {
 	if value == nil {
 		return true, false
 	}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
index c8125731..5648d89b 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
@@ -23,7 +23,6 @@ func initDefaultMap() {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -90,7 +89,26 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "varbit", OID: VarbitOID, Codec: BitsCodec{}})
 	defaultMap.RegisterType(&Type{Name: "varchar", OID: VarcharOID, Codec: TextCodec{}})
 	defaultMap.RegisterType(&Type{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}})
-	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{Marshal: xml.Marshal, Unmarshal: xml.Unmarshal}})
+	defaultMap.RegisterType(&Type{Name: "xid8", OID: XID8OID, Codec: Uint64Codec{}})
+	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{
+		Marshal: xml.Marshal,
+		// xml.Unmarshal does not support unmarshalling into *any. However, XMLCodec.DecodeValue calls Unmarshal with a
+		// *any. Wrap xml.Marshal with a function that copies the data into a new byte slice in this case. Not implementing
+		// directly in XMLCodec.DecodeValue to allow for the unlikely possibility that someone uses an alternative XML
+		// unmarshaler that does support unmarshalling into *any.
+		//
+		// https://github.com/jackc/pgx/issues/2227
+		// https://github.com/jackc/pgx/pull/2228
+		Unmarshal: func(data []byte, v any) error {
+			if v, ok := v.(*any); ok {
+				dstBuf := make([]byte, len(data))
+				copy(dstBuf, data)
+				*v = dstBuf
+				return nil
+			}
+			return xml.Unmarshal(data, v)
+		},
+	}})
 
 	// Range types
 	defaultMap.RegisterType(&Type{Name: "daterange", OID: DaterangeOID, Codec: &RangeCodec{ElementType: defaultMap.oidToType[DateOID]}})
@@ -155,6 +173,7 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "_varbit", OID: VarbitArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarbitOID]}})
 	defaultMap.RegisterType(&Type{Name: "_varchar", OID: VarcharArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarcharOID]}})
 	defaultMap.RegisterType(&Type{Name: "_xid", OID: XIDArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XIDOID]}})
+	defaultMap.RegisterType(&Type{Name: "_xid8", OID: XID8ArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XID8OID]}})
 	defaultMap.RegisterType(&Type{Name: "_xml", OID: XMLArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XMLOID]}})
 
 	// Integer types that directly map to a PostgreSQL type
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/point.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/point.go
index 09b19bb5..b701513d 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/point.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/point.go
@@ -30,11 +30,13 @@ type Point struct {
 	Valid bool
 }
 
+// ScanPoint implements the [PointScanner] interface.
 func (p *Point) ScanPoint(v Point) error {
 	*p = v
 	return nil
 }
 
+// PointValue implements the [PointValuer] interface.
 func (p Point) PointValue() (Point, error) {
 	return p, nil
 }
@@ -68,7 +70,7 @@ func parsePoint(src []byte) (*Point, error) {
 	return &Point{P: Vec2{x, y}, Valid: true}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Point) Scan(src any) error {
 	if src == nil {
 		*dst = Point{}
@@ -83,7 +85,7 @@ func (dst *Point) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Point) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,7 @@ func (src Point) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Point) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +111,7 @@ func (src Point) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Point) UnmarshalJSON(point []byte) error {
 	p, err := parsePoint(point)
 	if err != nil {
@@ -178,7 +182,6 @@ func (encodePlanPointCodecText) Encode(value any, buf []byte) (newBuf []byte, er
 }
 
 func (PointCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
index 04b0ba6b..a84b25fe 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
@@ -24,16 +24,18 @@ type Polygon struct {
 	Valid bool
 }
 
+// ScanPolygon implements the [PolygonScanner] interface.
 func (p *Polygon) ScanPolygon(v Polygon) error {
 	*p = v
 	return nil
 }
 
+// PolygonValue implements the [PolygonValuer] interface.
 func (p Polygon) PolygonValue() (Polygon, error) {
 	return p, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (p *Polygon) Scan(src any) error {
 	if src == nil {
 		*p = Polygon{}
@@ -48,7 +50,7 @@ func (p *Polygon) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (p Polygon) Value() (driver.Value, error) {
 	if !p.Valid {
 		return nil, nil
@@ -139,7 +141,6 @@ func (encodePlanPolygonCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (PolygonCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/range.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/range.go
index 16427ccc..62d69990 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/range.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/range.go
@@ -191,11 +191,13 @@ type untypedBinaryRange struct {
 // 18 = [      = 10010
 // 24 =        = 11000
 
-const emptyMask = 1
-const lowerInclusiveMask = 2
-const upperInclusiveMask = 4
-const lowerUnboundedMask = 8
-const upperUnboundedMask = 16
+const (
+	emptyMask          = 1
+	lowerInclusiveMask = 2
+	upperInclusiveMask = 4
+	lowerUnboundedMask = 8
+	upperUnboundedMask = 16
+)
 
 func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	ubr := &untypedBinaryRange{}
@@ -273,7 +275,6 @@ func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	}
 
 	return ubr, nil
-
 }
 
 // Range is a generic range type.
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
index b3b16604..90b9bd4b 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
@@ -121,5 +121,4 @@ func (RecordCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (an
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/text.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/text.go
index 021ee331..e08b1254 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/text.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/text.go
@@ -19,16 +19,18 @@ type Text struct {
 	Valid  bool
 }
 
+// ScanText implements the [TextScanner] interface.
 func (t *Text) ScanText(v Text) error {
 	*t = v
 	return nil
 }
 
+// TextValue implements the [TextValuer] interface.
 func (t Text) TextValue() (Text, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Text) Scan(src any) error {
 	if src == nil {
 		*dst = Text{}
@@ -47,7 +49,7 @@ func (dst *Text) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Text) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -55,6 +57,7 @@ func (src Text) Value() (driver.Value, error) {
 	return src.String, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Text) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -63,6 +66,7 @@ func (src Text) MarshalJSON() ([]byte, error) {
 	return json.Marshal(src.String)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Text) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -146,7 +150,6 @@ func (encodePlanTextCodecTextValuer) Encode(value any, buf []byte) (newBuf []byt
 }
 
 func (TextCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case TextFormatCode, BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/tid.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
index 9bc2c2a1..05c9e6d9 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
@@ -35,16 +35,18 @@ type TID struct {
 	Valid        bool
 }
 
+// ScanTID implements the [TIDScanner] interface.
 func (b *TID) ScanTID(v TID) error {
 	*b = v
 	return nil
 }
 
+// TIDValue implements the [TIDValuer] interface.
 func (b TID) TIDValue() (TID, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *TID) Scan(src any) error {
 	if src == nil {
 		*dst = TID{}
@@ -59,7 +61,7 @@ func (dst *TID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src TID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -131,7 +133,6 @@ func (encodePlanTIDCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TIDCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/time.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/time.go
index f8fd9489..4b8f6908 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/time.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/time.go
@@ -29,16 +29,18 @@ type Time struct {
 	Valid        bool
 }
 
+// ScanTime implements the [TimeScanner] interface.
 func (t *Time) ScanTime(v Time) error {
 	*t = v
 	return nil
 }
 
+// TimeValue implements the [TimeValuer] interface.
 func (t Time) TimeValue() (Time, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (t *Time) Scan(src any) error {
 	if src == nil {
 		*t = Time{}
@@ -58,7 +60,7 @@ func (t *Time) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (t Time) Value() (driver.Value, error) {
 	if !t.Valid {
 		return nil, nil
@@ -137,7 +139,6 @@ func (encodePlanTimeCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TimeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
index 677a2c6e..861fa883 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
@@ -11,7 +11,10 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+const (
+	pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+	jsonISO8601       = "2006-01-02T15:04:05.999999999"
+)
 
 type TimestampScanner interface {
 	ScanTimestamp(v Timestamp) error
@@ -28,16 +31,18 @@ type Timestamp struct {
 	Valid            bool
 }
 
+// ScanTimestamp implements the [TimestampScanner] interface.
 func (ts *Timestamp) ScanTimestamp(v Timestamp) error {
 	*ts = v
 	return nil
 }
 
+// TimestampValue implements the [TimestampValuer] interface.
 func (ts Timestamp) TimestampValue() (Timestamp, error) {
 	return ts, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (ts *Timestamp) Scan(src any) error {
 	if src == nil {
 		*ts = Timestamp{}
@@ -55,7 +60,7 @@ func (ts *Timestamp) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (ts Timestamp) Value() (driver.Value, error) {
 	if !ts.Valid {
 		return nil, nil
@@ -67,6 +72,7 @@ func (ts Timestamp) Value() (driver.Value, error) {
 	return ts.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	if !ts.Valid {
 		return []byte("null"), nil
@@ -76,7 +82,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 
 	switch ts.InfinityModifier {
 	case Finite:
-		s = ts.Time.Format(time.RFC3339Nano)
+		s = ts.Time.Format(jsonISO8601)
 	case Infinity:
 		s = "infinity"
 	case NegativeInfinity:
@@ -86,6 +92,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -104,15 +111,23 @@ func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	case "-infinity":
 		*ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
 	default:
-		// PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz
-		tim, err := time.Parse(time.RFC3339Nano, *s)
-		if err != nil {
-			return err
+		// Parse time with or without timezonr
+		tss := *s
+		//		PostgreSQL uses ISO 8601 without timezone for to_json function and casting from a string to timestampt
+		tim, err := time.Parse(time.RFC3339Nano, tss)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
 		}
-
-		*ts = Timestamp{Time: tim, Valid: true}
+		tim, err = time.ParseInLocation(jsonISO8601, tss, time.UTC)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
+		}
+		ts.Valid = false
+		return fmt.Errorf("cannot unmarshal %s to timestamp with layout %s or %s (%w)",
+			*s, time.RFC3339Nano, jsonISO8601, err)
 	}
-
 	return nil
 }
 
@@ -225,7 +240,6 @@ func discardTimeZone(t time.Time) time.Time {
 }
 
 func (c *TimestampCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
index 7efbcffd..5d67e47f 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
@@ -11,10 +11,12 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07"
-const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00"
-const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00"
-const microsecFromUnixEpochToY2K = 946684800 * 1000000
+const (
+	pgTimestamptzHourFormat    = "2006-01-02 15:04:05.999999999Z07"
+	pgTimestamptzMinuteFormat  = "2006-01-02 15:04:05.999999999Z07:00"
+	pgTimestamptzSecondFormat  = "2006-01-02 15:04:05.999999999Z07:00:00"
+	microsecFromUnixEpochToY2K = 946684800 * 1000000
+)
 
 const (
 	negativeInfinityMicrosecondOffset = -9223372036854775808
@@ -36,16 +38,18 @@ type Timestamptz struct {
 	Valid            bool
 }
 
+// ScanTimestamptz implements the [TimestamptzScanner] interface.
 func (tstz *Timestamptz) ScanTimestamptz(v Timestamptz) error {
 	*tstz = v
 	return nil
 }
 
+// TimestamptzValue implements the [TimestamptzValuer] interface.
 func (tstz Timestamptz) TimestamptzValue() (Timestamptz, error) {
 	return tstz, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (tstz *Timestamptz) Scan(src any) error {
 	if src == nil {
 		*tstz = Timestamptz{}
@@ -63,7 +67,7 @@ func (tstz *Timestamptz) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (tstz Timestamptz) Value() (driver.Value, error) {
 	if !tstz.Valid {
 		return nil, nil
@@ -75,6 +79,7 @@ func (tstz Timestamptz) Value() (driver.Value, error) {
 	return tstz.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	if !tstz.Valid {
 		return []byte("null"), nil
@@ -94,6 +99,7 @@ func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (tstz *Timestamptz) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -225,7 +231,6 @@ func (encodePlanTimestamptzCodecText) Encode(value any, buf []byte) (newBuf []by
 }
 
 func (c *TimestamptzCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
index f2b2fa6d..e6d4b1cf 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
@@ -3,6 +3,7 @@ package pgtype
 import (
 	"database/sql/driver"
 	"encoding/binary"
+	"encoding/json"
 	"fmt"
 	"math"
 	"strconv"
@@ -24,16 +25,18 @@ type Uint32 struct {
 	Valid  bool
 }
 
+// ScanUint32 implements the [Uint32Scanner] interface.
 func (n *Uint32) ScanUint32(v Uint32) error {
 	*n = v
 	return nil
 }
 
+// Uint32Value implements the [Uint32Valuer] interface.
 func (n Uint32) Uint32Value() (Uint32, error) {
 	return n, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Uint32) Scan(src any) error {
 	if src == nil {
 		*dst = Uint32{}
@@ -67,7 +70,7 @@ func (dst *Uint32) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Uint32) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -75,6 +78,31 @@ func (src Uint32) Value() (driver.Value, error) {
 	return int64(src.Uint32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
+func (src Uint32) MarshalJSON() ([]byte, error) {
+	if !src.Valid {
+		return []byte("null"), nil
+	}
+	return json.Marshal(src.Uint32)
+}
+
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
+func (dst *Uint32) UnmarshalJSON(b []byte) error {
+	var n *uint32
+	err := json.Unmarshal(b, &n)
+	if err != nil {
+		return err
+	}
+
+	if n == nil {
+		*dst = Uint32{}
+	} else {
+		*dst = Uint32{Uint32: *n, Valid: true}
+	}
+
+	return nil
+}
+
 type Uint32Codec struct{}
 
 func (Uint32Codec) FormatSupported(format int16) bool {
@@ -197,7 +225,6 @@ func (encodePlanUint32CodecTextInt64Valuer) Encode(value any, buf []byte) (newBu
 }
 
 func (Uint32Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
new file mode 100644
index 00000000..68fd1661
--- /dev/null
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
@@ -0,0 +1,323 @@
+package pgtype
+
+import (
+	"database/sql/driver"
+	"encoding/binary"
+	"fmt"
+	"math"
+	"strconv"
+
+	"github.com/jackc/pgx/v5/internal/pgio"
+)
+
+type Uint64Scanner interface {
+	ScanUint64(v Uint64) error
+}
+
+type Uint64Valuer interface {
+	Uint64Value() (Uint64, error)
+}
+
+// Uint64 is the core type that is used to represent PostgreSQL types such as XID8.
+type Uint64 struct {
+	Uint64 uint64
+	Valid  bool
+}
+
+// ScanUint64 implements the [Uint64Scanner] interface.
+func (n *Uint64) ScanUint64(v Uint64) error {
+	*n = v
+	return nil
+}
+
+// Uint64Value implements the [Uint64Valuer] interface.
+func (n Uint64) Uint64Value() (Uint64, error) {
+	return n, nil
+}
+
+// Scan implements the [database/sql.Scanner] interface.
+func (dst *Uint64) Scan(src any) error {
+	if src == nil {
+		*dst = Uint64{}
+		return nil
+	}
+
+	var n uint64
+
+	switch src := src.(type) {
+	case int64:
+		if src < 0 {
+			return fmt.Errorf("%d is less than the minimum value for Uint64", src)
+		}
+		n = uint64(src)
+	case string:
+		un, err := strconv.ParseUint(src, 10, 64)
+		if err != nil {
+			return err
+		}
+		n = un
+	default:
+		return fmt.Errorf("cannot scan %T", src)
+	}
+
+	*dst = Uint64{Uint64: n, Valid: true}
+
+	return nil
+}
+
+// Value implements the [database/sql/driver.Valuer] interface.
+func (src Uint64) Value() (driver.Value, error) {
+	if !src.Valid {
+		return nil, nil
+	}
+
+	// If the value is greater than the maximum value for int64, return it as a string instead of losing data or returning
+	// an error.
+	if src.Uint64 > math.MaxInt64 {
+		return strconv.FormatUint(src.Uint64, 10), nil
+	}
+
+	return int64(src.Uint64), nil
+}
+
+type Uint64Codec struct{}
+
+func (Uint64Codec) FormatSupported(format int16) bool {
+	return format == TextFormatCode || format == BinaryFormatCode
+}
+
+func (Uint64Codec) PreferredFormat() int16 {
+	return BinaryFormatCode
+}
+
+func (Uint64Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
+	switch format {
+	case BinaryFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecBinaryUint64{}
+		case Uint64Valuer:
+			return encodePlanUint64CodecBinaryUint64Valuer{}
+		case Int64Valuer:
+			return encodePlanUint64CodecBinaryInt64Valuer{}
+		}
+	case TextFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecTextUint64{}
+		case Int64Valuer:
+			return encodePlanUint64CodecTextInt64Valuer{}
+		}
+	}
+
+	return nil
+}
+
+type encodePlanUint64CodecBinaryUint64 struct{}
+
+func (encodePlanUint64CodecBinaryUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return pgio.AppendUint64(buf, v), nil
+}
+
+type encodePlanUint64CodecBinaryUint64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return pgio.AppendUint64(buf, v.Uint64), nil
+}
+
+type encodePlanUint64CodecBinaryInt64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return pgio.AppendUint64(buf, uint64(v.Int64)), nil
+}
+
+type encodePlanUint64CodecTextUint64 struct{}
+
+func (encodePlanUint64CodecTextUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return append(buf, strconv.FormatUint(uint64(v), 10)...), nil
+}
+
+type encodePlanUint64CodecTextUint64Valuer struct{}
+
+func (encodePlanUint64CodecTextUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return append(buf, strconv.FormatUint(v.Uint64, 10)...), nil
+}
+
+type encodePlanUint64CodecTextInt64Valuer struct{}
+
+func (encodePlanUint64CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return append(buf, strconv.FormatInt(v.Int64, 10)...), nil
+}
+
+func (Uint64Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+	switch format {
+	case BinaryFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanBinaryUint64ToUint64{}
+		case Uint64Scanner:
+			return scanPlanBinaryUint64ToUint64Scanner{}
+		case TextScanner:
+			return scanPlanBinaryUint64ToTextScanner{}
+		}
+	case TextFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanTextAnyToUint64{}
+		case Uint64Scanner:
+			return scanPlanTextAnyToUint64Scanner{}
+		}
+	}
+
+	return nil
+}
+
+func (c Uint64Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return int64(n), nil
+}
+
+func (c Uint64Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return n, nil
+}
+
+type scanPlanBinaryUint64ToUint64 struct{}
+
+func (scanPlanBinaryUint64ToUint64) Scan(src []byte, dst any) error {
+	if src == nil {
+		return fmt.Errorf("cannot scan NULL into %T", dst)
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	p := (dst).(*uint64)
+	*p = binary.BigEndian.Uint64(src)
+
+	return nil
+}
+
+type scanPlanBinaryUint64ToUint64Scanner struct{}
+
+func (scanPlanBinaryUint64ToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := binary.BigEndian.Uint64(src)
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
+
+type scanPlanBinaryUint64ToTextScanner struct{}
+
+func (scanPlanBinaryUint64ToTextScanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(TextScanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanText(Text{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := uint64(binary.BigEndian.Uint64(src))
+	return s.ScanText(Text{String: strconv.FormatUint(n, 10), Valid: true})
+}
+
+type scanPlanTextAnyToUint64Scanner struct{}
+
+func (scanPlanTextAnyToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	n, err := strconv.ParseUint(string(src), 10, 64)
+	if err != nil {
+		return err
+	}
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
index d57c0f2f..83d0c412 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
@@ -20,11 +20,13 @@ type UUID struct {
 	Valid bool
 }
 
+// ScanUUID implements the [UUIDScanner] interface.
 func (b *UUID) ScanUUID(v UUID) error {
 	*b = v
 	return nil
 }
 
+// UUIDValue implements the [UUIDValuer] interface.
 func (b UUID) UUIDValue() (UUID, error) {
 	return b, nil
 }
@@ -67,7 +69,7 @@ func encodeUUID(src [16]byte) string {
 	return string(buf[:])
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *UUID) Scan(src any) error {
 	if src == nil {
 		*dst = UUID{}
@@ -87,7 +89,7 @@ func (dst *UUID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src UUID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,15 @@ func (src UUID) Value() (driver.Value, error) {
 	return encodeUUID(src.Bytes), nil
 }
 
+func (src UUID) String() string {
+	if !src.Valid {
+		return ""
+	}
+
+	return encodeUUID(src.Bytes)
+}
+
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src UUID) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +119,7 @@ func (src UUID) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *UUID) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte("null")) {
 		*dst = UUID{}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/xml.go b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
index fb4c49ad..79e3698a 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
@@ -113,7 +113,7 @@ func (c *XMLCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPl
 		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
 
 		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, format, nextDst, 0); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go b/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
index fdcba724..addfb412 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
@@ -2,7 +2,7 @@ package pgxpool
 
 import (
 	"context"
-	"fmt"
+	"errors"
 	"math/rand"
 	"runtime"
 	"strconv"
@@ -15,11 +15,14 @@ import (
 	"github.com/jackc/puddle/v2"
 )
 
-var defaultMaxConns = int32(4)
-var defaultMinConns = int32(0)
-var defaultMaxConnLifetime = time.Hour
-var defaultMaxConnIdleTime = time.Minute * 30
-var defaultHealthCheckPeriod = time.Minute
+var (
+	defaultMaxConns          = int32(4)
+	defaultMinConns          = int32(0)
+	defaultMinIdleConns      = int32(0)
+	defaultMaxConnLifetime   = time.Hour
+	defaultMaxConnIdleTime   = time.Minute * 30
+	defaultHealthCheckPeriod = time.Minute
+)
 
 type connResource struct {
 	conn       *pgx.Conn
@@ -83,10 +86,12 @@ type Pool struct {
 	config                *Config
 	beforeConnect         func(context.Context, *pgx.ConnConfig) error
 	afterConnect          func(context.Context, *pgx.Conn) error
-	beforeAcquire         func(context.Context, *pgx.Conn) bool
+	prepareConn           func(context.Context, *pgx.Conn) (bool, error)
 	afterRelease          func(*pgx.Conn) bool
 	beforeClose           func(*pgx.Conn)
+	shouldPing            func(context.Context, ShouldPingParams) bool
 	minConns              int32
+	minIdleConns          int32
 	maxConns              int32
 	maxConnLifetime       time.Duration
 	maxConnLifetimeJitter time.Duration
@@ -102,6 +107,12 @@ type Pool struct {
 	closeChan chan struct{}
 }
 
+// ShouldPingParams are the parameters passed to ShouldPing.
+type ShouldPingParams struct {
+	Conn         *pgx.Conn
+	IdleDuration time.Duration
+}
+
 // Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
 // modified.
 type Config struct {
@@ -117,8 +128,23 @@ type Config struct {
 	// BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the
 	// acquisition or false to indicate that the connection should be destroyed and a different connection should be
 	// acquired.
+	//
+	// Deprecated: Use PrepareConn instead. If both PrepareConn and BeforeAcquire are set, PrepareConn will take
+	// precedence, ignoring BeforeAcquire.
 	BeforeAcquire func(context.Context, *pgx.Conn) bool
 
+	// PrepareConn is called before a connection is acquired from the pool. If this function returns true, the connection
+	// is considered valid, otherwise the connection is destroyed. If the function returns a non-nil error, the instigating
+	// query will fail with the returned error.
+	//
+	// Specifically, this means that:
+	//
+	// 	- If it returns true and a nil error, the query proceeds as normal.
+	// 	- If it returns true and an error, the connection will be returned to the pool, and the instigating query will fail with the returned error.
+	// 	- If it returns false, and an error, the connection will be destroyed, and the query will fail with the returned error.
+	// 	- If it returns false and a nil error, the connection will be destroyed, and the instigating query will be retried on a new connection.
+	PrepareConn func(context.Context, *pgx.Conn) (bool, error)
+
 	// AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to
 	// return the connection to the pool or false to destroy the connection.
 	AfterRelease func(*pgx.Conn) bool
@@ -126,6 +152,10 @@ type Config struct {
 	// BeforeClose is called right before a connection is closed and removed from the pool.
 	BeforeClose func(*pgx.Conn)
 
+	// ShouldPing is called after a connection is acquired from the pool. If it returns true, the connection is pinged to check for liveness.
+	// If this func is not set, the default behavior is to ping connections that have been idle for at least 1 second.
+	ShouldPing func(context.Context, ShouldPingParams) bool
+
 	// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
 	MaxConnLifetime time.Duration
 
@@ -144,6 +174,13 @@ type Config struct {
 	// to create new connections.
 	MinConns int32
 
+	// MinIdleConns is the minimum number of idle connections in the pool. You can increase this to ensure that
+	// there are always idle connections available. This can help reduce tail latencies during request processing,
+	// as you can avoid the latency of establishing a new connection while handling requests. It is superior
+	// to MinConns for this purpose.
+	// Similar to MinConns, the pool might temporarily dip below MinIdleConns after connection closes.
+	MinIdleConns int32
+
 	// HealthCheckPeriod is the duration between checks of the health of idle connections.
 	HealthCheckPeriod time.Duration
 
@@ -181,14 +218,22 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		panic("config must be created by ParseConfig")
 	}
 
+	prepareConn := config.PrepareConn
+	if prepareConn == nil && config.BeforeAcquire != nil {
+		prepareConn = func(ctx context.Context, conn *pgx.Conn) (bool, error) {
+			return config.BeforeAcquire(ctx, conn), nil
+		}
+	}
+
 	p := &Pool{
 		config:                config,
 		beforeConnect:         config.BeforeConnect,
 		afterConnect:          config.AfterConnect,
-		beforeAcquire:         config.BeforeAcquire,
+		prepareConn:           prepareConn,
 		afterRelease:          config.AfterRelease,
 		beforeClose:           config.BeforeClose,
 		minConns:              config.MinConns,
+		minIdleConns:          config.MinIdleConns,
 		maxConns:              config.MaxConns,
 		maxConnLifetime:       config.MaxConnLifetime,
 		maxConnLifetimeJitter: config.MaxConnLifetimeJitter,
@@ -206,6 +251,14 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		p.releaseTracer = t
 	}
 
+	if config.ShouldPing != nil {
+		p.shouldPing = config.ShouldPing
+	} else {
+		p.shouldPing = func(ctx context.Context, params ShouldPingParams) bool {
+			return params.IdleDuration > time.Second
+		}
+	}
+
 	var err error
 	p.p, err = puddle.NewPool(
 		&puddle.Config[*connResource]{
@@ -271,7 +324,8 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 	}
 
 	go func() {
-		p.createIdleResources(ctx, int(p.minConns))
+		targetIdleResources := max(int(p.minConns), int(p.minIdleConns))
+		p.createIdleResources(ctx, targetIdleResources)
 		p.backgroundHealthCheck()
 	}()
 
@@ -281,20 +335,20 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 // ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the
 // addition of the following variables:
 //
-//   - pool_max_conns: integer greater than 0
-//   - pool_min_conns: integer 0 or greater
-//   - pool_max_conn_lifetime: duration string
-//   - pool_max_conn_idle_time: duration string
-//   - pool_health_check_period: duration string
-//   - pool_max_conn_lifetime_jitter: duration string
+//   - pool_max_conns: integer greater than 0 (default 4)
+//   - pool_min_conns: integer 0 or greater (default 0)
+//   - pool_max_conn_lifetime: duration string (default 1 hour)
+//   - pool_max_conn_idle_time: duration string (default 30 minutes)
+//   - pool_health_check_period: duration string (default 1 minute)
+//   - pool_max_conn_lifetime_jitter: duration string (default 0)
 //
 // See Config for definitions of these arguments.
 //
 //	# Example Keyword/Value
-//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
+//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 pool_max_conn_lifetime=1h30m
 //
 //	# Example URL
-//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
+//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10&pool_max_conn_lifetime=1h30m
 func ParseConfig(connString string) (*Config, error) {
 	connConfig, err := pgx.ParseConfig(connString)
 	if err != nil {
@@ -310,10 +364,10 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_max_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conns", err)
 		}
 		if n < 1 {
-			return nil, fmt.Errorf("pool_max_conns too small: %d", n)
+			return nil, pgconn.NewParseConfigError(connString, "pool_max_conns too small", err)
 		}
 		config.MaxConns = int32(n)
 	} else {
@@ -327,18 +381,29 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_min_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_min_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_conns", err)
 		}
 		config.MinConns = int32(n)
 	} else {
 		config.MinConns = defaultMinConns
 	}
 
+	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_idle_conns"]; ok {
+		delete(connConfig.Config.RuntimeParams, "pool_min_idle_conns")
+		n, err := strconv.ParseInt(s, 10, 32)
+		if err != nil {
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_idle_conns", err)
+		}
+		config.MinIdleConns = int32(n)
+	} else {
+		config.MinIdleConns = defaultMinIdleConns
+	}
+
 	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime", err)
 		}
 		config.MaxConnLifetime = d
 	} else {
@@ -349,7 +414,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_idle_time")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_idle_time: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_idle_time", err)
 		}
 		config.MaxConnIdleTime = d
 	} else {
@@ -360,7 +425,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_health_check_period")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_health_check_period: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_health_check_period", err)
 		}
 		config.HealthCheckPeriod = d
 	} else {
@@ -371,7 +436,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime_jitter", err)
 		}
 		config.MaxConnLifetimeJitter = d
 	}
@@ -472,7 +537,9 @@ func (p *Pool) checkMinConns() error {
 	// TotalConns can include ones that are being destroyed but we should have
 	// sleep(500ms) around all of the destroys to help prevent that from throwing
 	// off this check
-	toCreate := p.minConns - p.Stat().TotalConns()
+
+	// Create the number of connections needed to get to both minConns and minIdleConns
+	toCreate := max(p.minConns-p.Stat().TotalConns(), p.minIdleConns-p.Stat().IdleConns())
 	if toCreate > 0 {
 		return p.createIdleResources(context.Background(), int(toCreate))
 	}
@@ -521,7 +588,10 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 		}()
 	}
 
-	for {
+	// Try to acquire from the connection pool up to maxConns + 1 times, so that
+	// any that fatal errors would empty the pool and still at least try 1 fresh
+	// connection.
+	for range p.maxConns + 1 {
 		res, err := p.p.Acquire(ctx)
 		if err != nil {
 			return nil, err
@@ -529,7 +599,8 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 
 		cr := res.Value()
 
-		if res.IdleDuration() > time.Second {
+		shouldPingParams := ShouldPingParams{Conn: cr.conn, IdleDuration: res.IdleDuration()}
+		if p.shouldPing(ctx, shouldPingParams) {
 			err := cr.conn.Ping(ctx)
 			if err != nil {
 				res.Destroy()
@@ -537,12 +608,25 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 			}
 		}
 
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			return cr.getConn(p, res), nil
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok {
+				res.Destroy()
+			}
+			if err != nil {
+				if ok {
+					res.Release()
+				}
+				return nil, err
+			}
+			if !ok {
+				continue
+			}
 		}
 
-		res.Destroy()
+		return cr.getConn(p, res), nil
 	}
+	return nil, errors.New("pgxpool: detected infinite loop acquiring connection; likely bug in PrepareConn or BeforeAcquire hook")
 }
 
 // AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the
@@ -565,11 +649,14 @@ func (p *Pool) AcquireAllIdle(ctx context.Context) []*Conn {
 	conns := make([]*Conn, 0, len(resources))
 	for _, res := range resources {
 		cr := res.Value()
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			conns = append(conns, cr.getConn(p, res))
-		} else {
-			res.Destroy()
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok || err != nil {
+				res.Destroy()
+				continue
+			}
 		}
+		conns = append(conns, cr.getConn(p, res))
 	}
 
 	return conns
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go b/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
index cfa0c4c5..e02b6ac3 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
@@ -82,3 +82,10 @@ func (s *Stat) MaxLifetimeDestroyCount() int64 {
 func (s *Stat) MaxIdleDestroyCount() int64 {
 	return s.idleDestroyCount
 }
+
+// EmptyAcquireWaitTime returns the cumulative time waited for successful acquires
+// from the pool for a resource to be released or constructed because the pool was
+// empty.
+func (s *Stat) EmptyAcquireWaitTime() time.Duration {
+	return s.s.EmptyAcquireWaitTime()
+}
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/rows.go b/notifier/vendor/github.com/jackc/pgx/v5/rows.go
index f23625d4..a5725fdd 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/rows.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/rows.go
@@ -41,22 +41,19 @@ type Rows interface {
 	// when there was an error executing the query.
 	FieldDescriptions() []pgconn.FieldDescription
 
-	// Next prepares the next row for reading. It returns true if there is another
-	// row and false if no more rows are available or a fatal error has occurred.
-	// It automatically closes rows when all rows are read.
+	// Next prepares the next row for reading. It returns true if there is another row and false if no more rows are
+	// available or a fatal error has occurred. It automatically closes rows upon returning false (whether due to all rows
+	// having been read or due to an error).
 	//
-	// Callers should check rows.Err() after rows.Next() returns false to detect
-	// whether result-set reading ended prematurely due to an error. See
-	// Conn.Query for details.
+	// Callers should check rows.Err() after rows.Next() returns false to detect whether result-set reading ended
+	// prematurely due to an error. See Conn.Query for details.
 	//
-	// For simpler error handling, consider using the higher-level pgx v5
-	// CollectRows() and ForEachRow() helpers instead.
+	// For simpler error handling, consider using the higher-level pgx v5 CollectRows() and ForEachRow() helpers instead.
 	Next() bool
 
-	// Scan reads the values from the current row into dest values positionally.
-	// dest can include pointers to core types, values implementing the Scanner
-	// interface, and nil. nil will skip the value entirely. It is an error to
-	// call Scan without first calling Next() and checking that it returned true.
+	// Scan reads the values from the current row into dest values positionally. dest can include pointers to core types,
+	// values implementing the Scanner interface, and nil. nil will skip the value entirely. It is an error to call Scan
+	// without first calling Next() and checking that it returned true. Rows is automatically closed upon error.
 	Scan(dest ...any) error
 
 	// Values returns the decoded row values. As with Scan(), it is an error to
@@ -188,6 +185,17 @@ func (rows *baseRows) Close() {
 	} else if rows.queryTracer != nil {
 		rows.queryTracer.TraceQueryEnd(rows.ctx, rows.conn, TraceQueryEndData{rows.commandTag, rows.err})
 	}
+
+	// Zero references to other memory allocations. This allows them to be GC'd even when the Rows still referenced. In
+	// particular, when using pgxpool GC could be delayed as pgxpool.poolRows are allocated in large slices.
+	//
+	// https://github.com/jackc/pgx/pull/2269
+	rows.values = nil
+	rows.scanPlans = nil
+	rows.scanTypes = nil
+	rows.ctx = nil
+	rows.sql = ""
+	rows.args = nil
 }
 
 func (rows *baseRows) CommandTag() pgconn.CommandTag {
@@ -272,7 +280,7 @@ func (rows *baseRows) Scan(dest ...any) error {
 
 		err := rows.scanPlans[i].Scan(values[i], dst)
 		if err != nil {
-			err = ScanArgError{ColumnIndex: i, Err: err}
+			err = ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 			rows.fatal(err)
 			return err
 		}
@@ -334,11 +342,16 @@ func (rows *baseRows) Conn() *Conn {
 
 type ScanArgError struct {
 	ColumnIndex int
+	FieldName   string
 	Err         error
 }
 
 func (e ScanArgError) Error() string {
-	return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	if e.FieldName == "?column?" { // Don't include the fieldname if it's unknown
+		return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	}
+
+	return fmt.Sprintf("can't scan into dest[%d] (col: %s): %v", e.ColumnIndex, e.FieldName, e.Err)
 }
 
 func (e ScanArgError) Unwrap() error {
@@ -366,7 +379,7 @@ func ScanRow(typeMap *pgtype.Map, fieldDescriptions []pgconn.FieldDescription, v
 
 		err := typeMap.Scan(fieldDescriptions[i].DataTypeOID, fieldDescriptions[i].Format, values[i], d)
 		if err != nil {
-			return ScanArgError{ColumnIndex: i, Err: err}
+			return ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 		}
 	}
 
@@ -468,6 +481,8 @@ func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
 		return value, err
 	}
 
+	// The defer rows.Close() won't have executed yet. If the query returned more than one row, rows would still be open.
+	// rows.Close() must be called before rows.Err() so we explicitly call it here.
 	rows.Close()
 	return value, rows.Err()
 }
@@ -545,7 +560,7 @@ func (rs *mapRowScanner) ScanRow(rows Rows) error {
 	return nil
 }
 
-// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row
+// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number of public fields as row
 // has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then the field will be
 // ignored.
 func RowToStructByPos[T any](row CollectableRow) (T, error) {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/stdlib/sql.go b/notifier/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
index c1d00ab4..939b9636 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
@@ -216,7 +216,8 @@ func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB {
 
 // OpenDBFromPool creates a new *sql.DB from the given *pgxpool.Pool. Note that this method automatically sets the
 // maximum number of idle connections in *sql.DB to zero, since they must be managed from the *pgxpool.Pool. This is
-// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool.
+// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool. Note
+// that closing the returned *sql.DB will not close the *pgxpool.Pool.
 func OpenDBFromPool(pool *pgxpool.Pool, opts ...OptionOpenDB) *sql.DB {
 	c := GetPoolConnector(pool, opts...)
 	db := sql.OpenDB(c)
@@ -470,7 +471,8 @@ func (c *Conn) ExecContext(ctx context.Context, query string, argsV []driver.Nam
 		return nil, driver.ErrBadConn
 	}
 
-	args := namedValueToInterface(argsV)
+	args := make([]any, len(argsV))
+	convertNamedArguments(args, argsV)
 
 	commandTag, err := c.conn.Exec(ctx, query, args...)
 	// if we got a network error before we had a chance to send the query, retry
@@ -487,8 +489,9 @@ func (c *Conn) QueryContext(ctx context.Context, query string, argsV []driver.Na
 		return nil, driver.ErrBadConn
 	}
 
-	args := []any{databaseSQLResultFormats}
-	args = append(args, namedValueToInterface(argsV)...)
+	args := make([]any, 1+len(argsV))
+	args[0] = databaseSQLResultFormats
+	convertNamedArguments(args[1:], argsV)
 
 	rows, err := c.conn.Query(ctx, query, args...)
 	if err != nil {
@@ -847,28 +850,14 @@ func (r *Rows) Next(dest []driver.Value) error {
 	return nil
 }
 
-func valueToInterface(argsV []driver.Value) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
-		if v != nil {
-			args = append(args, v.(any))
-		} else {
-			args = append(args, nil)
-		}
-	}
-	return args
-}
-
-func namedValueToInterface(argsV []driver.NamedValue) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
+func convertNamedArguments(args []any, argsV []driver.NamedValue) {
+	for i, v := range argsV {
 		if v.Value != nil {
-			args = append(args, v.Value.(any))
+			args[i] = v.Value.(any)
 		} else {
-			args = append(args, nil)
+			args[i] = nil
 		}
 	}
-	return args
 }
 
 type wrapTx struct {
diff --git a/notifier/vendor/github.com/jackc/pgx/v5/tx.go b/notifier/vendor/github.com/jackc/pgx/v5/tx.go
index 8feeb512..571e5e00 100644
--- a/notifier/vendor/github.com/jackc/pgx/v5/tx.go
+++ b/notifier/vendor/github.com/jackc/pgx/v5/tx.go
@@ -3,7 +3,6 @@ package pgx
 import (
 	"context"
 	"errors"
-	"fmt"
 	"strconv"
 	"strings"
 
@@ -48,6 +47,8 @@ type TxOptions struct {
 	// BeginQuery is the SQL query that will be executed to begin the transaction. This allows using non-standard syntax
 	// such as BEGIN PRIORITY HIGH with CockroachDB. If set this will override the other settings.
 	BeginQuery string
+	// CommitQuery is the SQL query that will be executed to commit the transaction.
+	CommitQuery string
 }
 
 var emptyTxOptions TxOptions
@@ -101,11 +102,14 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (Tx, error) {
 	if err != nil {
 		// begin should never fail unless there is an underlying connection issue or
 		// a context timeout. In either case, the connection is possibly broken.
-		c.die(errors.New("failed to begin transaction"))
+		c.die()
 		return nil, err
 	}
 
-	return &dbTx{conn: c}, nil
+	return &dbTx{
+		conn:        c,
+		commitQuery: txOptions.CommitQuery,
+	}, nil
 }
 
 // Tx represents a database transaction.
@@ -154,6 +158,7 @@ type dbTx struct {
 	conn         *Conn
 	savepointNum int64
 	closed       bool
+	commitQuery  string
 }
 
 // Begin starts a pseudo nested transaction implemented with a savepoint.
@@ -177,7 +182,12 @@ func (tx *dbTx) Commit(ctx context.Context) error {
 		return ErrTxClosed
 	}
 
-	commandTag, err := tx.conn.Exec(ctx, "commit")
+	commandSQL := "commit"
+	if tx.commitQuery != "" {
+		commandSQL = tx.commitQuery
+	}
+
+	commandTag, err := tx.conn.Exec(ctx, commandSQL)
 	tx.closed = true
 	if err != nil {
 		if tx.conn.PgConn().TxStatus() != 'I' {
@@ -205,7 +215,7 @@ func (tx *dbTx) Rollback(ctx context.Context) error {
 	tx.closed = true
 	if err != nil {
 		// A rollback failure leaves the connection in an undefined state
-		tx.conn.die(fmt.Errorf("rollback failed: %w", err))
+		tx.conn.die()
 		return err
 	}
 
diff --git a/notifier/vendor/github.com/magiconair/properties/.gitignore b/notifier/vendor/github.com/magiconair/properties/.gitignore
deleted file mode 100644
index e7081ff5..00000000
--- a/notifier/vendor/github.com/magiconair/properties/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-*.sublime-project
-*.sublime-workspace
-*.un~
-*.swp
-.idea/
-*.iml
diff --git a/notifier/vendor/github.com/magiconair/properties/CHANGELOG.md b/notifier/vendor/github.com/magiconair/properties/CHANGELOG.md
deleted file mode 100644
index 842e8e24..00000000
--- a/notifier/vendor/github.com/magiconair/properties/CHANGELOG.md
+++ /dev/null
@@ -1,205 +0,0 @@
-## Changelog
-
-### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
-
- * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
-
-   Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
-
- * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
-
-### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
-
- * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
-
-   Thanks to [@ellie](https://github.com/ellie) for the patch.
-
- * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
-
-   This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
-   author happy until it affects real users.
-
-   Thanks to [@maage](https://github.com/maage) for the patch.
-
-### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
-
- * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
-
-   When reading comments \ are loaded correctly, but when writing they are then
-   replaced by \\. This leads to wrong comments when writing and reading multiple times.
-
-   Thanks to [@doxsch](https://github.com/doxsch) for the patch.
-
-### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
-
- * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
-
-   Thanks to [@sriv](https://github.com/sriv) for the patch.
-
-### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
-
- * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
-
-   The change is include the key in the error message which is causing the circular
-   reference when parsing/loading the properties files.
-
-   Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
-
-### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
-
- * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
-
-   This patch ensures that backslashes are escaped on write. Existing applications which
-   rely on the old behavior may need to be updated.
-
-   Thanks to [@apesternikov](https://github.com/apesternikov) for the patch.
-
- * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL()
-
-   Thanks to [@aliras1](https://github.com/aliras1) for the patch.
-
- * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write()
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
- * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
-### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
-
- * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request
-
-   This patch ensures that in `LoadURL` the response body is always closed.
-
-   Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
-
-### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
-
- * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
-
-   This adds the option to disable property expansion during loading.
-
-   Thanks to [@kmala](https://github.com/kmala) for the patch.
-
-### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
-
- * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
-
-   See PR for an example.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
-
- * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
-
-   Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
-   with a `circular reference error`.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
-
- * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
-
- * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
-
-   Thanks to [@mgurov](https://github.com/mgurov) for the fix.
-
-### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
-
- * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
- * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
-
-### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
-
- * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
- * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
-
-### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
-
- * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
- * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
- * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
- * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
-
-### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
-
- * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
- * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
- * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
-
-### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
-
- * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
-
-### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
-
- * Vendored in gopkg.in/check.v1
-
-### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
-
- * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
-
-### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
-
- * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
-
-### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
-
- * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
-
-### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
-
- * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
- * Add clickable links to README
-
-### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
-
- * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
-   [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
-
-### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
-
- * Added support for single and multi-line comments (reading, writing and updating)
- * The order of keys is now preserved
- * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
- * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
- * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
-
-### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
-
- * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
-
-### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
-
- * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
-
-### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
-
- * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
- * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
-
-### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
-
-* Added support for time.Duration
-* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
-* Changed default of MustXXX() failure from panic to log.Fatal
-
-### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
-
-* Added MustGet... functions
-* Added support for int and uint with range checks on 32 bit platforms
-
-### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
-
-* Renamed from goproperties to properties
-* Added support for expansion of environment vars in
-  filenames and value expressions
-* Fixed bug where value expressions were not at the
-  start of the string
-
-### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
-
-* Initial release
diff --git a/notifier/vendor/github.com/magiconair/properties/LICENSE.md b/notifier/vendor/github.com/magiconair/properties/LICENSE.md
deleted file mode 100644
index 79c87e3e..00000000
--- a/notifier/vendor/github.com/magiconair/properties/LICENSE.md
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2013-2020, Frank Schroeder
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/notifier/vendor/github.com/magiconair/properties/README.md b/notifier/vendor/github.com/magiconair/properties/README.md
deleted file mode 100644
index e2edda02..00000000
--- a/notifier/vendor/github.com/magiconair/properties/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
-[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
-[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
-[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-# Overview
-
-#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
-
-properties is a Go library for reading and writing properties files.
-
-It supports reading from multiple files or URLs and Spring style recursive
-property expansion of expressions like `${key}` to their corresponding value.
-Value expressions can refer to other keys like in `${key}` or to environment
-variables like in `${USER}`.  Filenames can also contain environment variables
-like in `/home/${USER}/myapp.properties`.
-
-Properties can be decoded into structs, maps, arrays and values through
-struct tags.
-
-Comments and the order of keys are preserved. Comments can be modified
-and can be written to the output.
-
-The properties library supports both ISO-8859-1 and UTF-8 encoded data.
-
-Starting from version 1.3.0 the behavior of the MustXXX() functions is
-configurable by providing a custom `ErrorHandler` function. The default has
-changed from `panic` to `log.Fatal` but this is configurable and custom
-error handling functions can be provided. See the package documentation for
-details.
-
-Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-## Getting Started
-
-```go
-import (
-	"flag"
-	"github.com/magiconair/properties"
-)
-
-func main() {
-	// init from a file
-	p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8)
-
-	// or multiple files
-	p = properties.MustLoadFiles([]string{
-			"${HOME}/config.properties",
-			"${HOME}/config-${USER}.properties",
-		}, properties.UTF8, true)
-
-	// or from a map
-	p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"})
-
-	// or from a string
-	p = properties.MustLoadString("key=value\nabc=def")
-
-	// or from a URL
-	p = properties.MustLoadURL("http://host/path")
-
-	// or from multiple URLs
-	p = properties.MustLoadURL([]string{
-			"http://host/config",
-			"http://host/config-${USER}",
-		}, true)
-
-	// or from flags
-	p.MustFlag(flag.CommandLine)
-
-	// get values through getters
-	host := p.MustGetString("host")
-	port := p.GetInt("port", 8080)
-
-	// or through Decode
-	type Config struct {
-		Host    string        `properties:"host"`
-		Port    int           `properties:"port,default=9000"`
-		Accept  []string      `properties:"accept,default=image/png;image;gif"`
-		Timeout time.Duration `properties:"timeout,default=5s"`
-	}
-	var cfg Config
-	if err := p.Decode(&cfg); err != nil {
-		log.Fatal(err)
-	}
-}
-
-```
-
-## Installation and Upgrade
-
-```
-$ go get -u github.com/magiconair/properties
-```
-
-## License
-
-2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details.
-
-## ToDo
-
-* Dump contents with passwords and secrets obscured
-
-## Updated Git tags
-
-#### 13 Feb 2018
-
-I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
-and I've only recently learned that this doesn't play well with `git describe` 😞
-
-I have replaced all lightweight tags with signed tags using this script which should
-retain the commit date, name and email address. Please run `git pull --tags` to update them.
-
-Worst case you have to reclone the repo.
-
-```shell
-#!/bin/bash
-tag=$1
-echo "Updating $tag"
-date=$(git show ${tag}^0 --format=%aD | head -1)
-email=$(git show ${tag}^0 --format=%aE | head -1)
-name=$(git show ${tag}^0 --format=%aN | head -1)
-GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
-```
-
-I apologize for the inconvenience.
-
-Frank
-
diff --git a/notifier/vendor/github.com/magiconair/properties/decode.go b/notifier/vendor/github.com/magiconair/properties/decode.go
deleted file mode 100644
index 8e6aa441..00000000
--- a/notifier/vendor/github.com/magiconair/properties/decode.go
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Decode assigns property values to exported fields of a struct.
-//
-// Decode traverses v recursively and returns an error if a value cannot be
-// converted to the field type or a required value is missing for a field.
-//
-// The following type dependent decodings are used:
-//
-// String, boolean, numeric fields have the value of the property key assigned.
-// The property key name is the name of the field. A different key and a default
-// value can be set in the field's tag. Fields without default value are
-// required. If the value cannot be converted to the field type an error is
-// returned.
-//
-// time.Duration fields have the result of time.ParseDuration() assigned.
-//
-// time.Time fields have the vaule of time.Parse() assigned. The default layout
-// is time.RFC3339 but can be set in the field's tag.
-//
-// Arrays and slices of string, boolean, numeric, time.Duration and time.Time
-// fields have the value interpreted as a comma separated list of values. The
-// individual values are trimmed of whitespace and empty values are ignored. A
-// default value can be provided as a semicolon separated list in the field's
-// tag.
-//
-// Struct fields are decoded recursively using the field name plus "." as
-// prefix. The prefix (without dot) can be overridden in the field's tag.
-// Default values are not supported in the field's tag. Specify them on the
-// fields of the inner struct instead.
-//
-// Map fields must have a key of type string and are decoded recursively by
-// using the field's name plus ".' as prefix and the next element of the key
-// name as map key. The prefix (without dot) can be overridden in the field's
-// tag. Default values are not supported.
-//
-// Examples:
-//
-//	// Field is ignored.
-//	Field int `properties:"-"`
-//
-//	// Field is assigned value of 'Field'.
-//	Field int
-//
-//	// Field is assigned value of 'myName'.
-//	Field int `properties:"myName"`
-//
-//	// Field is assigned value of key 'myName' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:"myName,default=15"`
-//
-//	// Field is assigned value of key 'Field' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:",default=15"`
-//
-//	// Field is assigned value of key 'date' and the date
-//	// is in format 2006-01-02
-//	Field time.Time `properties:"date,layout=2006-01-02"`
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas.
-//	Field []string
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas and has a default
-//	// value ["a", "b", "c"] if the key does not exist.
-//	Field []string `properties:",default=a;b;c"`
-//
-//	// Field is decoded recursively with "Field." as key prefix.
-//	Field SomeStruct
-//
-//	// Field is decoded recursively with "myName." as key prefix.
-//	Field SomeStruct `properties:"myName"`
-//
-//	// Field is decoded recursively with "Field." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string
-//
-//	// Field is decoded recursively with "myName." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string `properties:"myName"`
-func (p *Properties) Decode(x interface{}) error {
-	t, v := reflect.TypeOf(x), reflect.ValueOf(x)
-	if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct {
-		return fmt.Errorf("not a pointer to struct: %s", t)
-	}
-	if err := dec(p, "", nil, nil, v); err != nil {
-		return err
-	}
-	return nil
-}
-
-func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
-	t := v.Type()
-
-	// value returns the property value for key or the default if provided.
-	value := func() (string, error) {
-		if val, ok := p.Get(key); ok {
-			return val, nil
-		}
-		if def != nil {
-			return *def, nil
-		}
-		return "", fmt.Errorf("missing required key %s", key)
-	}
-
-	// conv converts a string to a value of the given type.
-	conv := func(s string, t reflect.Type) (val reflect.Value, err error) {
-		var v interface{}
-
-		switch {
-		case isDuration(t):
-			v, err = time.ParseDuration(s)
-
-		case isTime(t):
-			layout := opts["layout"]
-			if layout == "" {
-				layout = time.RFC3339
-			}
-			v, err = time.Parse(layout, s)
-
-		case isBool(t):
-			v, err = boolVal(s), nil
-
-		case isString(t):
-			v, err = s, nil
-
-		case isFloat(t):
-			v, err = strconv.ParseFloat(s, 64)
-
-		case isInt(t):
-			v, err = strconv.ParseInt(s, 10, 64)
-
-		case isUint(t):
-			v, err = strconv.ParseUint(s, 10, 64)
-
-		default:
-			return reflect.Zero(t), fmt.Errorf("unsupported type %s", t)
-		}
-		if err != nil {
-			return reflect.Zero(t), err
-		}
-		return reflect.ValueOf(v).Convert(t), nil
-	}
-
-	// keydef returns the property key and the default value based on the
-	// name of the struct field and the options in the tag.
-	keydef := func(f reflect.StructField) (string, *string, map[string]string) {
-		_key, _opts := parseTag(f.Tag.Get("properties"))
-
-		var _def *string
-		if d, ok := _opts["default"]; ok {
-			_def = &d
-		}
-		if _key != "" {
-			return _key, _def, _opts
-		}
-		return f.Name, _def, _opts
-	}
-
-	switch {
-	case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t):
-		s, err := value()
-		if err != nil {
-			return err
-		}
-		val, err := conv(s, t)
-		if err != nil {
-			return err
-		}
-		v.Set(val)
-
-	case isPtr(t):
-		return dec(p, key, def, opts, v.Elem())
-
-	case isStruct(t):
-		for i := 0; i < v.NumField(); i++ {
-			fv := v.Field(i)
-			fk, def, opts := keydef(t.Field(i))
-			if !fv.CanSet() {
-				return fmt.Errorf("cannot set %s", t.Field(i).Name)
-			}
-			if fk == "-" {
-				continue
-			}
-			if key != "" {
-				fk = key + "." + fk
-			}
-			if err := dec(p, fk, def, opts, fv); err != nil {
-				return err
-			}
-		}
-		return nil
-
-	case isArray(t):
-		val, err := value()
-		if err != nil {
-			return err
-		}
-		vals := split(val, ";")
-		a := reflect.MakeSlice(t, 0, len(vals))
-		for _, s := range vals {
-			val, err := conv(s, t.Elem())
-			if err != nil {
-				return err
-			}
-			a = reflect.Append(a, val)
-		}
-		v.Set(a)
-
-	case isMap(t):
-		valT := t.Elem()
-		m := reflect.MakeMap(t)
-		for postfix := range p.FilterStripPrefix(key + ".").m {
-			pp := strings.SplitN(postfix, ".", 2)
-			mk, mv := pp[0], reflect.New(valT)
-			if err := dec(p, key+"."+mk, nil, nil, mv); err != nil {
-				return err
-			}
-			m.SetMapIndex(reflect.ValueOf(mk), mv.Elem())
-		}
-		v.Set(m)
-
-	default:
-		return fmt.Errorf("unsupported type %s", t)
-	}
-	return nil
-}
-
-// split splits a string on sep, trims whitespace of elements
-// and omits empty elements
-func split(s string, sep string) []string {
-	var a []string
-	for _, v := range strings.Split(s, sep) {
-		if v = strings.TrimSpace(v); v != "" {
-			a = append(a, v)
-		}
-	}
-	return a
-}
-
-// parseTag parses a "key,k=v,k=v,..."
-func parseTag(tag string) (key string, opts map[string]string) {
-	opts = map[string]string{}
-	for i, s := range strings.Split(tag, ",") {
-		if i == 0 {
-			key = s
-			continue
-		}
-
-		pp := strings.SplitN(s, "=", 2)
-		if len(pp) == 1 {
-			opts[pp[0]] = ""
-		} else {
-			opts[pp[0]] = pp[1]
-		}
-	}
-	return key, opts
-}
-
-func isArray(t reflect.Type) bool    { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice }
-func isBool(t reflect.Type) bool     { return t.Kind() == reflect.Bool }
-func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) }
-func isMap(t reflect.Type) bool      { return t.Kind() == reflect.Map }
-func isPtr(t reflect.Type) bool      { return t.Kind() == reflect.Ptr }
-func isString(t reflect.Type) bool   { return t.Kind() == reflect.String }
-func isStruct(t reflect.Type) bool   { return t.Kind() == reflect.Struct }
-func isTime(t reflect.Type) bool     { return t == reflect.TypeOf(time.Time{}) }
-func isFloat(t reflect.Type) bool {
-	return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64
-}
-func isInt(t reflect.Type) bool {
-	return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64
-}
-func isUint(t reflect.Type) bool {
-	return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/doc.go b/notifier/vendor/github.com/magiconair/properties/doc.go
deleted file mode 100644
index 7c797931..00000000
--- a/notifier/vendor/github.com/magiconair/properties/doc.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package properties provides functions for reading and writing
-// ISO-8859-1 and UTF-8 encoded .properties files and has
-// support for recursive property expansion.
-//
-// Java properties files are ISO-8859-1 encoded and use Unicode
-// literals for characters outside the ISO character set. Unicode
-// literals can be used in UTF-8 encoded properties files but
-// aren't necessary.
-//
-// To load a single properties file use MustLoadFile():
-//
-//	p := properties.MustLoadFile(filename, properties.UTF8)
-//
-// To load multiple properties files use MustLoadFiles()
-// which loads the files in the given order and merges the
-// result. Missing properties files can be ignored if the
-// 'ignoreMissing' flag is set to true.
-//
-// Filenames can contain environment variables which are expanded
-// before loading.
-//
-//	f1 := "/etc/myapp/myapp.conf"
-//	f2 := "/home/${USER}/myapp.conf"
-//	p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)
-//
-// All of the different key/value delimiters ' ', ':' and '=' are
-// supported as well as the comment characters '!' and '#' and
-// multi-line values.
-//
-//	! this is a comment
-//	# and so is this
-//
-//	# the following expressions are equal
-//	key value
-//	key=value
-//	key:value
-//	key = value
-//	key : value
-//	key = val\
-//	      ue
-//
-// Properties stores all comments preceding a key and provides
-// GetComments() and SetComments() methods to retrieve and
-// update them. The convenience functions GetComment() and
-// SetComment() allow access to the last comment. The
-// WriteComment() method writes properties files including
-// the comments and with the keys in the original order.
-// This can be used for sanitizing properties files.
-//
-// Property expansion is recursive and circular references
-// and malformed expressions are not allowed and cause an
-// error. Expansion of environment variables is supported.
-//
-//	# standard property
-//	key = value
-//
-//	# property expansion: key2 = value
-//	key2 = ${key}
-//
-//	# recursive expansion: key3 = value
-//	key3 = ${key2}
-//
-//	# circular reference (error)
-//	key = ${key}
-//
-//	# malformed expression (error)
-//	key = ${ke
-//
-//	# refers to the users' home dir
-//	home = ${HOME}
-//
-//	# local key takes precedence over env var: u = foo
-//	USER = foo
-//	u = ${USER}
-//
-// The default property expansion format is ${key} but can be
-// changed by setting different pre- and postfix values on the
-// Properties object.
-//
-//	p := properties.NewProperties()
-//	p.Prefix = "#["
-//	p.Postfix = "]#"
-//
-// Properties provides convenience functions for getting typed
-// values with default values if the key does not exist or the
-// type conversion failed.
-//
-//	# Returns true if the value is either "1", "on", "yes" or "true"
-//	# Returns false for every other value and the default value if
-//	# the key does not exist.
-//	v = p.GetBool("key", false)
-//
-//	# Returns the value if the key exists and the format conversion
-//	# was successful. Otherwise, the default value is returned.
-//	v = p.GetInt64("key", 999)
-//	v = p.GetUint64("key", 999)
-//	v = p.GetFloat64("key", 123.0)
-//	v = p.GetString("key", "def")
-//	v = p.GetDuration("key", 999)
-//
-// As an alternative properties may be applied with the standard
-// library's flag implementation at any time.
-//
-//	# Standard configuration
-//	v = flag.Int("key", 999, "help message")
-//	flag.Parse()
-//
-//	# Merge p into the flag set
-//	p.MustFlag(flag.CommandLine)
-//
-// Properties provides several MustXXX() convenience functions
-// which will terminate the app if an error occurs. The behavior
-// of the failure is configurable and the default is to call
-// log.Fatal(err). To have the MustXXX() functions panic instead
-// of logging the error set a different ErrorHandler before
-// you use the Properties package.
-//
-//	properties.ErrorHandler = properties.PanicHandler
-//
-//	# Will panic instead of logging an error
-//	p := properties.MustLoadFile("config.properties")
-//
-// You can also provide your own ErrorHandler function. The only requirement
-// is that the error handler function must exit after handling the error.
-//
-//	  properties.ErrorHandler = func(err error) {
-//		     fmt.Println(err)
-//	      os.Exit(1)
-//	  }
-//
-//	  # Will write to stdout and then exit
-//	  p := properties.MustLoadFile("config.properties")
-//
-// Properties can also be loaded into a struct via the `Decode`
-// method, e.g.
-//
-//	type S struct {
-//	    A string        `properties:"a,default=foo"`
-//	    D time.Duration `properties:"timeout,default=5s"`
-//	    E time.Time     `properties:"expires,layout=2006-01-02,default=2015-01-01"`
-//	}
-//
-// See `Decode()` method for the full documentation.
-//
-// The following documents provide a description of the properties
-// file format.
-//
-// http://en.wikipedia.org/wiki/.properties
-//
-// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29
-package properties
diff --git a/notifier/vendor/github.com/magiconair/properties/integrate.go b/notifier/vendor/github.com/magiconair/properties/integrate.go
deleted file mode 100644
index 35d0ae97..00000000
--- a/notifier/vendor/github.com/magiconair/properties/integrate.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import "flag"
-
-// MustFlag sets flags that are skipped by dst.Parse when p contains
-// the respective key for flag.Flag.Name.
-//
-// It's use is recommended with command line arguments as in:
-//
-//	flag.Parse()
-//	p.MustFlag(flag.CommandLine)
-func (p *Properties) MustFlag(dst *flag.FlagSet) {
-	m := make(map[string]*flag.Flag)
-	dst.VisitAll(func(f *flag.Flag) {
-		m[f.Name] = f
-	})
-	dst.Visit(func(f *flag.Flag) {
-		delete(m, f.Name) // overridden
-	})
-
-	for name, f := range m {
-		v, ok := p.Get(name)
-		if !ok {
-			continue
-		}
-
-		if err := f.Value.Set(v); err != nil {
-			ErrorHandler(err)
-		}
-	}
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/lex.go b/notifier/vendor/github.com/magiconair/properties/lex.go
deleted file mode 100644
index 3d15a1f6..00000000
--- a/notifier/vendor/github.com/magiconair/properties/lex.go
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// Parts of the lexer are from the template/text/parser package
-// For these parts the following applies:
-//
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file of the go 1.2
-// distribution.
-
-package properties
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-	"unicode/utf8"
-)
-
-// item represents a token or text string returned from the scanner.
-type item struct {
-	typ itemType // The type of this item.
-	pos int      // The starting position, in bytes, of this item in the input string.
-	val string   // The value of this item.
-}
-
-func (i item) String() string {
-	switch {
-	case i.typ == itemEOF:
-		return "EOF"
-	case i.typ == itemError:
-		return i.val
-	case len(i.val) > 10:
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError itemType = iota // error occurred; value is text of error
-	itemEOF
-	itemKey     // a key
-	itemValue   // a value
-	itemComment // a comment
-)
-
-// defines a constant for EOF
-const eof = -1
-
-// permitted whitespace characters space, FF and TAB
-const whitespace = " \f\t"
-
-// stateFn represents the state of the scanner as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	input   string    // the string being scanned
-	state   stateFn   // the next lexing function to enter
-	pos     int       // current position in the input
-	start   int       // start position of this item
-	width   int       // width of last rune read from input
-	lastPos int       // position of most recent item returned by nextItem
-	runes   []rune    // scanned runes for this item
-	items   chan item // channel of scanned items
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() rune {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
-	l.width = w
-	l.pos += l.width
-	return r
-}
-
-// peek returns but does not consume the next rune in the input.
-func (l *lexer) peek() rune {
-	r := l.next()
-	l.backup()
-	return r
-}
-
-// backup steps back one rune. Can only be called once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	i := item{t, l.start, string(l.runes)}
-	l.items <- i
-	l.start = l.pos
-	l.runes = l.runes[:0]
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// appends the rune to the current value
-func (l *lexer) appendRune(r rune) {
-	l.runes = append(l.runes, r)
-}
-
-// accept consumes the next rune if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.ContainsRune(valid, l.next()) {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.ContainsRune(valid, l.next()) {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on, based on the position of
-// the previous item returned by nextItem. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.lastPos], "\n")
-}
-
-// errorf returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.nextItem.
-func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
-	return nil
-}
-
-// nextItem returns the next item from the input.
-func (l *lexer) nextItem() item {
-	i := <-l.items
-	l.lastPos = i.pos
-	return i
-}
-
-// lex creates a new scanner for the input string.
-func lex(input string) *lexer {
-	l := &lexer{
-		input: input,
-		items: make(chan item),
-		runes: make([]rune, 0, 32),
-	}
-	go l.run()
-	return l
-}
-
-// run runs the state machine for the lexer.
-func (l *lexer) run() {
-	for l.state = lexBeforeKey(l); l.state != nil; {
-		l.state = l.state(l)
-	}
-}
-
-// state functions
-
-// lexBeforeKey scans until a key begins.
-func lexBeforeKey(l *lexer) stateFn {
-	switch r := l.next(); {
-	case isEOF(r):
-		l.emit(itemEOF)
-		return nil
-
-	case isEOL(r):
-		l.ignore()
-		return lexBeforeKey
-
-	case isComment(r):
-		return lexComment
-
-	case isWhitespace(r):
-		l.ignore()
-		return lexBeforeKey
-
-	default:
-		l.backup()
-		return lexKey
-	}
-}
-
-// lexComment scans a comment line. The comment character has already been scanned.
-func lexComment(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.ignore()
-	for {
-		switch r := l.next(); {
-		case isEOF(r):
-			l.ignore()
-			l.emit(itemEOF)
-			return nil
-		case isEOL(r):
-			l.emit(itemComment)
-			return lexBeforeKey
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// lexKey scans the key up to a delimiter
-func lexKey(l *lexer) stateFn {
-	var r rune
-
-Loop:
-	for {
-		switch r = l.next(); {
-
-		case isEscape(r):
-			err := l.scanEscapeSequence()
-			if err != nil {
-				return l.errorf(err.Error())
-			}
-
-		case isEndOfKey(r):
-			l.backup()
-			break Loop
-
-		case isEOF(r):
-			break Loop
-
-		default:
-			l.appendRune(r)
-		}
-	}
-
-	if len(l.runes) > 0 {
-		l.emit(itemKey)
-	}
-
-	if isEOF(r) {
-		l.emit(itemEOF)
-		return nil
-	}
-
-	return lexBeforeValue
-}
-
-// lexBeforeValue scans the delimiter between key and value.
-// Leading and trailing whitespace is ignored.
-// We expect to be just after the key.
-func lexBeforeValue(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.accept(":=")
-	l.acceptRun(whitespace)
-	l.ignore()
-	return lexValue
-}
-
-// lexValue scans text until the end of the line. We expect to be just after the delimiter.
-func lexValue(l *lexer) stateFn {
-	for {
-		switch r := l.next(); {
-		case isEscape(r):
-			if isEOL(l.peek()) {
-				l.next()
-				l.acceptRun(whitespace)
-			} else {
-				err := l.scanEscapeSequence()
-				if err != nil {
-					return l.errorf(err.Error())
-				}
-			}
-
-		case isEOL(r):
-			l.emit(itemValue)
-			l.ignore()
-			return lexBeforeKey
-
-		case isEOF(r):
-			l.emit(itemValue)
-			l.emit(itemEOF)
-			return nil
-
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// scanEscapeSequence scans either one of the escaped characters
-// or a unicode literal. We expect to be after the escape character.
-func (l *lexer) scanEscapeSequence() error {
-	switch r := l.next(); {
-
-	case isEscapedCharacter(r):
-		l.appendRune(decodeEscapedCharacter(r))
-		return nil
-
-	case atUnicodeLiteral(r):
-		return l.scanUnicodeLiteral()
-
-	case isEOF(r):
-		return fmt.Errorf("premature EOF")
-
-	// silently drop the escape character and append the rune as is
-	default:
-		l.appendRune(r)
-		return nil
-	}
-}
-
-// scans a unicode literal in the form \uXXXX. We expect to be after the \u.
-func (l *lexer) scanUnicodeLiteral() error {
-	// scan the digits
-	d := make([]rune, 4)
-	for i := 0; i < 4; i++ {
-		d[i] = l.next()
-		if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) {
-			return fmt.Errorf("invalid unicode literal")
-		}
-	}
-
-	// decode the digits into a rune
-	r, err := strconv.ParseInt(string(d), 16, 0)
-	if err != nil {
-		return err
-	}
-
-	l.appendRune(rune(r))
-	return nil
-}
-
-// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character.
-func decodeEscapedCharacter(r rune) rune {
-	switch r {
-	case 'f':
-		return '\f'
-	case 'n':
-		return '\n'
-	case 'r':
-		return '\r'
-	case 't':
-		return '\t'
-	default:
-		return r
-	}
-}
-
-// atUnicodeLiteral reports whether we are at a unicode literal.
-// The escape character has already been consumed.
-func atUnicodeLiteral(r rune) bool {
-	return r == 'u'
-}
-
-// isComment reports whether we are at the start of a comment.
-func isComment(r rune) bool {
-	return r == '#' || r == '!'
-}
-
-// isEndOfKey reports whether the rune terminates the current key.
-func isEndOfKey(r rune) bool {
-	return strings.ContainsRune(" \f\t\r\n:=", r)
-}
-
-// isEOF reports whether we are at EOF.
-func isEOF(r rune) bool {
-	return r == eof
-}
-
-// isEOL reports whether we are at a new line character.
-func isEOL(r rune) bool {
-	return r == '\n' || r == '\r'
-}
-
-// isEscape reports whether the rune is the escape character which
-// prefixes unicode literals and other escaped characters.
-func isEscape(r rune) bool {
-	return r == '\\'
-}
-
-// isEscapedCharacter reports whether we are at one of the characters that need escaping.
-// The escape character has already been consumed.
-func isEscapedCharacter(r rune) bool {
-	return strings.ContainsRune(" :=fnrt", r)
-}
-
-// isWhitespace reports whether the rune is a whitespace character.
-func isWhitespace(r rune) bool {
-	return strings.ContainsRune(whitespace, r)
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/load.go b/notifier/vendor/github.com/magiconair/properties/load.go
deleted file mode 100644
index 635368dc..00000000
--- a/notifier/vendor/github.com/magiconair/properties/load.go
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"strings"
-)
-
-// Encoding specifies encoding of the input data.
-type Encoding uint
-
-const (
-	// utf8Default is a private placeholder for the zero value of Encoding to
-	// ensure that it has the correct meaning. UTF8 is the default encoding but
-	// was assigned a non-zero value which cannot be changed without breaking
-	// existing code. Clients should continue to use the public constants.
-	utf8Default Encoding = iota
-
-	// UTF8 interprets the input data as UTF-8.
-	UTF8
-
-	// ISO_8859_1 interprets the input data as ISO-8859-1.
-	ISO_8859_1
-)
-
-type Loader struct {
-	// Encoding determines how the data from files and byte buffers
-	// is interpreted. For URLs the Content-Type header is used
-	// to determine the encoding of the data.
-	Encoding Encoding
-
-	// DisableExpansion configures the property expansion of the
-	// returned property object. When set to true, the property values
-	// will not be expanded and the Property object will not be checked
-	// for invalid expansion expressions.
-	DisableExpansion bool
-
-	// IgnoreMissing configures whether missing files or URLs which return
-	// 404 are reported as errors. When set to true, missing files and 404
-	// status codes are not reported as errors.
-	IgnoreMissing bool
-}
-
-// Load reads a buffer into a Properties struct.
-func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
-	return l.loadBytes(buf, l.Encoding)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into
-// a Properties struct. If IgnoreMissing is true then a 404 status code or
-// missing file will not be reported as error. Encoding sets the encoding for
-// files. For the URLs see LoadURL for the Content-Type header and the
-// encoding.
-func (l *Loader) LoadAll(names []string) (*Properties, error) {
-	all := NewProperties()
-	for _, name := range names {
-		n, err := expandName(name)
-		if err != nil {
-			return nil, err
-		}
-
-		var p *Properties
-		switch {
-		case strings.HasPrefix(n, "http://"):
-			p, err = l.LoadURL(n)
-		case strings.HasPrefix(n, "https://"):
-			p, err = l.LoadURL(n)
-		default:
-			p, err = l.LoadFile(n)
-		}
-		if err != nil {
-			return nil, err
-		}
-		all.Merge(p)
-	}
-
-	all.DisableExpansion = l.DisableExpansion
-	if all.DisableExpansion {
-		return all, nil
-	}
-	return all, all.check()
-}
-
-// LoadFile reads a file into a Properties struct.
-// If IgnoreMissing is true then a missing file will not be
-// reported as error.
-func (l *Loader) LoadFile(filename string) (*Properties, error) {
-	data, err := ioutil.ReadFile(filename)
-	if err != nil {
-		if l.IgnoreMissing && os.IsNotExist(err) {
-			LogPrintf("properties: %s not found. skipping", filename)
-			return NewProperties(), nil
-		}
-		return nil, err
-	}
-	return l.loadBytes(data, l.Encoding)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-//
-// The encoding is determined via the Content-Type header which
-// should be set to 'text/plain'. If the 'charset' parameter is
-// missing, 'iso-8859-1' or 'latin1' the encoding is set to
-// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
-// encoding is set to UTF-8. A missing content type header is
-// interpreted as 'text/plain; charset=utf-8'.
-func (l *Loader) LoadURL(url string) (*Properties, error) {
-	resp, err := http.Get(url)
-	if err != nil {
-		return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode == 404 && l.IgnoreMissing {
-		LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
-		return NewProperties(), nil
-	}
-
-	if resp.StatusCode != 200 {
-		return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
-	}
-
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
-	}
-
-	ct := resp.Header.Get("Content-Type")
-	ct = strings.Join(strings.Fields(ct), "")
-	var enc Encoding
-	switch strings.ToLower(ct) {
-	case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1":
-		enc = ISO_8859_1
-	case "", "text/plain;charset=utf-8":
-		enc = UTF8
-	default:
-		return nil, fmt.Errorf("properties: invalid content type %s", ct)
-	}
-
-	return l.loadBytes(body, enc)
-}
-
-func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) {
-	p, err := parse(convert(buf, enc))
-	if err != nil {
-		return nil, err
-	}
-	p.DisableExpansion = l.DisableExpansion
-	if p.DisableExpansion {
-		return p, nil
-	}
-	return p, p.check()
-}
-
-// Load reads a buffer into a Properties struct.
-func Load(buf []byte, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadBytes(buf)
-}
-
-// LoadString reads an UTF8 string into a properties struct.
-func LoadString(s string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadBytes([]byte(s))
-}
-
-// LoadMap creates a new Properties struct from a string map.
-func LoadMap(m map[string]string) *Properties {
-	p := NewProperties()
-	for k, v := range m {
-		p.Set(k, v)
-	}
-	return p
-}
-
-// LoadFile reads a file into a Properties struct.
-func LoadFile(filename string, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadAll([]string{filename})
-}
-
-// LoadFiles reads multiple files in the given order into
-// a Properties struct. If 'ignoreMissing' is true then
-// non-existent files will not be reported as error.
-func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(filenames)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-// See Loader#LoadURL for details.
-func LoadURL(url string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadAll([]string{url})
-}
-
-// LoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct. If IgnoreMissing is true then a 404 status code will
-// not be reported as error. See Loader#LoadURL for the Content-Type header
-// and the encoding.
-func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(urls)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding.
-func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(names)
-}
-
-// MustLoadString reads an UTF8 string into a Properties struct and
-// panics on error.
-func MustLoadString(s string) *Properties {
-	return must(LoadString(s))
-}
-
-// MustLoadFile reads a file into a Properties struct and
-// panics on error.
-func MustLoadFile(filename string, enc Encoding) *Properties {
-	return must(LoadFile(filename, enc))
-}
-
-// MustLoadFiles reads multiple files in the given order into
-// a Properties struct and panics on error. If 'ignoreMissing'
-// is true then non-existent files will not be reported as error.
-func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadFiles(filenames, enc, ignoreMissing))
-}
-
-// MustLoadURL reads the content of a URL into a Properties struct and
-// panics on error.
-func MustLoadURL(url string) *Properties {
-	return must(LoadURL(url))
-}
-
-// MustLoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct and panics on error. If 'ignoreMissing' is true then a 404
-// status code will not be reported as error.
-func MustLoadURLs(urls []string, ignoreMissing bool) *Properties {
-	return must(LoadURLs(urls, ignoreMissing))
-}
-
-// MustLoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding. It panics on error.
-func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadAll(names, enc, ignoreMissing))
-}
-
-func must(p *Properties, err error) *Properties {
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return p
-}
-
-// expandName expands ${ENV_VAR} expressions in a name.
-// If the environment variable does not exist then it will be replaced
-// with an empty string. Malformed expressions like "${ENV_VAR" will
-// be reported as error.
-func expandName(name string) (string, error) {
-	return expand(name, []string{}, "${", "}", make(map[string]string))
-}
-
-// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
-// For ISO-8859-1 we can convert each byte straight into a rune since the
-// first 256 unicode code points cover ISO-8859-1.
-func convert(buf []byte, enc Encoding) string {
-	switch enc {
-	case utf8Default, UTF8:
-		return string(buf)
-	case ISO_8859_1:
-		runes := make([]rune, len(buf))
-		for i, b := range buf {
-			runes[i] = rune(b)
-		}
-		return string(runes)
-	default:
-		ErrorHandler(fmt.Errorf("unsupported encoding %v", enc))
-	}
-	panic("ErrorHandler should exit")
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/parser.go b/notifier/vendor/github.com/magiconair/properties/parser.go
deleted file mode 100644
index fccfd39f..00000000
--- a/notifier/vendor/github.com/magiconair/properties/parser.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"runtime"
-)
-
-type parser struct {
-	lex *lexer
-}
-
-func parse(input string) (properties *Properties, err error) {
-	p := &parser{lex: lex(input)}
-	defer p.recover(&err)
-
-	properties = NewProperties()
-	key := ""
-	comments := []string{}
-
-	for {
-		token := p.expectOneOf(itemComment, itemKey, itemEOF)
-		switch token.typ {
-		case itemEOF:
-			goto done
-		case itemComment:
-			comments = append(comments, token.val)
-			continue
-		case itemKey:
-			key = token.val
-			if _, ok := properties.m[key]; !ok {
-				properties.k = append(properties.k, key)
-			}
-		}
-
-		token = p.expectOneOf(itemValue, itemEOF)
-		if len(comments) > 0 {
-			properties.c[key] = comments
-			comments = []string{}
-		}
-		switch token.typ {
-		case itemEOF:
-			properties.m[key] = ""
-			goto done
-		case itemValue:
-			properties.m[key] = token.val
-		}
-	}
-
-done:
-	return properties, nil
-}
-
-func (p *parser) errorf(format string, args ...interface{}) {
-	format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
-	panic(fmt.Errorf(format, args...))
-}
-
-func (p *parser) expectOneOf(expected ...itemType) (token item) {
-	token = p.lex.nextItem()
-	for _, v := range expected {
-		if token.typ == v {
-			return token
-		}
-	}
-	p.unexpected(token)
-	panic("unexpected token")
-}
-
-func (p *parser) unexpected(token item) {
-	p.errorf(token.String())
-}
-
-// recover is the handler that turns panics into returns from the top level of Parse.
-func (p *parser) recover(errp *error) {
-	e := recover()
-	if e != nil {
-		if _, ok := e.(runtime.Error); ok {
-			panic(e)
-		}
-		*errp = e.(error)
-	}
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/properties.go b/notifier/vendor/github.com/magiconair/properties/properties.go
deleted file mode 100644
index fb2f7b40..00000000
--- a/notifier/vendor/github.com/magiconair/properties/properties.go
+++ /dev/null
@@ -1,848 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer.
-// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used.
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"regexp"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-	"unicode/utf8"
-)
-
-const maxExpansionDepth = 64
-
-// ErrorHandlerFunc defines the type of function which handles failures
-// of the MustXXX() functions. An error handler function must exit
-// the application after handling the error.
-type ErrorHandlerFunc func(error)
-
-// ErrorHandler is the function which handles failures of the MustXXX()
-// functions. The default is LogFatalHandler.
-var ErrorHandler ErrorHandlerFunc = LogFatalHandler
-
-// LogHandlerFunc defines the function prototype for logging errors.
-type LogHandlerFunc func(fmt string, args ...interface{})
-
-// LogPrintf defines a log handler which uses log.Printf.
-var LogPrintf LogHandlerFunc = log.Printf
-
-// LogFatalHandler handles the error by logging a fatal error and exiting.
-func LogFatalHandler(err error) {
-	log.Fatal(err)
-}
-
-// PanicHandler handles the error by panicking.
-func PanicHandler(err error) {
-	panic(err)
-}
-
-// -----------------------------------------------------------------------------
-
-// A Properties contains the key/value pairs from the properties input.
-// All values are stored in unexpanded form and are expanded at runtime
-type Properties struct {
-	// Pre-/Postfix for property expansion.
-	Prefix  string
-	Postfix string
-
-	// DisableExpansion controls the expansion of properties on Get()
-	// and the check for circular references on Set(). When set to
-	// true Properties behaves like a simple key/value store and does
-	// not check for circular references on Get() or on Set().
-	DisableExpansion bool
-
-	// Stores the key/value pairs
-	m map[string]string
-
-	// Stores the comments per key.
-	c map[string][]string
-
-	// Stores the keys in order of appearance.
-	k []string
-
-	// WriteSeparator specifies the separator of key and value while writing the properties.
-	WriteSeparator string
-}
-
-// NewProperties creates a new Properties struct with the default
-// configuration for "${key}" expressions.
-func NewProperties() *Properties {
-	return &Properties{
-		Prefix:  "${",
-		Postfix: "}",
-		m:       map[string]string{},
-		c:       map[string][]string{},
-		k:       []string{},
-	}
-}
-
-// Load reads a buffer into the given Properties struct.
-func (p *Properties) Load(buf []byte, enc Encoding) error {
-	l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion}
-	newProperties, err := l.LoadBytes(buf)
-	if err != nil {
-		return err
-	}
-	p.Merge(newProperties)
-	return nil
-}
-
-// Get returns the expanded value for the given key if exists.
-// Otherwise, ok is false.
-func (p *Properties) Get(key string) (value string, ok bool) {
-	v, ok := p.m[key]
-	if p.DisableExpansion {
-		return v, ok
-	}
-	if !ok {
-		return "", false
-	}
-
-	expanded, err := p.expand(key, v)
-
-	// we guarantee that the expanded value is free of
-	// circular references and malformed expressions
-	// so we panic if we still get an error here.
-	if err != nil {
-		ErrorHandler(err)
-	}
-
-	return expanded, true
-}
-
-// MustGet returns the expanded value for the given key if exists.
-// Otherwise, it panics.
-func (p *Properties) MustGet(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// ClearComments removes the comments for all keys.
-func (p *Properties) ClearComments() {
-	p.c = map[string][]string{}
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComment returns the last comment before the given key or an empty string.
-func (p *Properties) GetComment(key string) string {
-	comments, ok := p.c[key]
-	if !ok || len(comments) == 0 {
-		return ""
-	}
-	return comments[len(comments)-1]
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComments returns all comments that appeared before the given key or nil.
-func (p *Properties) GetComments(key string) []string {
-	if comments, ok := p.c[key]; ok {
-		return comments
-	}
-	return nil
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComment sets the comment for the key.
-func (p *Properties) SetComment(key, comment string) {
-	p.c[key] = []string{comment}
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComments sets the comments for the key. If the comments are nil then
-// all comments for this key are deleted.
-func (p *Properties) SetComments(key string, comments []string) {
-	if comments == nil {
-		delete(p.c, key)
-		return
-	}
-	p.c[key] = comments
-}
-
-// ----------------------------------------------------------------------------
-
-// GetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the default value is returned.
-func (p *Properties) GetBool(key string, def bool) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the function panics.
-func (p *Properties) MustGetBool(key string) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getBool(key string) (value bool, err error) {
-	if v, ok := p.Get(key); ok {
-		return boolVal(v), nil
-	}
-	return false, invalidKeyError(key)
-}
-
-func boolVal(v string) bool {
-	v = strings.ToLower(v)
-	return v == "1" || v == "true" || v == "yes" || v == "on"
-}
-
-// ----------------------------------------------------------------------------
-
-// GetDuration parses the expanded value as an time.Duration (in ns) if the
-// key exists. If key does not exist or the value cannot be parsed the default
-// value is returned. In almost all cases you want to use GetParsedDuration().
-func (p *Properties) GetDuration(key string, def time.Duration) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return time.Duration(v)
-}
-
-// MustGetDuration parses the expanded value as an time.Duration (in ns) if
-// the key exists. If key does not exist or the value cannot be parsed the
-// function panics. In almost all cases you want to use MustGetParsedDuration().
-func (p *Properties) MustGetDuration(key string) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return time.Duration(v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		return def
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetParsedDuration(key string) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		ErrorHandler(invalidKeyError(key))
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-// ----------------------------------------------------------------------------
-
-// GetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetFloat64(key string, def float64) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetFloat64(key string) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getFloat64(key string) (value float64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseFloat(v, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetInt(key string, def int) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return intRangeCheck(key, v)
-}
-
-// MustGetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetInt(key string) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return intRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt64 parses the expanded value as an int64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetInt64(key string, def int64) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetInt64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetInt64(key string) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getInt64(key string) (value int64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseInt(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint parses the expanded value as an uint if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetUint(key string, def uint) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return uintRangeCheck(key, v)
-}
-
-// MustGetUint parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetUint(key string) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return uintRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint64 parses the expanded value as an uint64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetUint64(key string, def uint64) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetUint64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetUint64(key string) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getUint64(key string) (value uint64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseUint(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetString returns the expanded value for the given key if exists or
-// the default value otherwise.
-func (p *Properties) GetString(key, def string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	return def
-}
-
-// MustGetString returns the expanded value for the given key if exists or
-// panics otherwise.
-func (p *Properties) MustGetString(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// Filter returns a new properties object which contains all properties
-// for which the key matches the pattern.
-func (p *Properties) Filter(pattern string) (*Properties, error) {
-	re, err := regexp.Compile(pattern)
-	if err != nil {
-		return nil, err
-	}
-
-	return p.FilterRegexp(re), nil
-}
-
-// FilterRegexp returns a new properties object which contains all properties
-// for which the key matches the regular expression.
-func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if re.MatchString(k) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterPrefix returns a new properties object with a subset of all keys
-// with the given prefix.
-func (p *Properties) FilterPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterStripPrefix returns a new properties object with a subset of all keys
-// with the given prefix and the prefix removed from the keys.
-func (p *Properties) FilterStripPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	n := len(prefix)
-	for _, k := range p.k {
-		if len(k) > len(prefix) && strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference
-			// TODO(fs): this function should probably return an error but the signature is fixed
-			pp.Set(k[n:], p.m[k])
-		}
-	}
-	return pp
-}
-
-// Len returns the number of keys.
-func (p *Properties) Len() int {
-	return len(p.m)
-}
-
-// Keys returns all keys in the same order as in the input.
-func (p *Properties) Keys() []string {
-	keys := make([]string, len(p.k))
-	copy(keys, p.k)
-	return keys
-}
-
-// Set sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. If the value contains a
-// circular reference or a malformed expression then
-// an error is returned.
-// An empty key is silently ignored.
-func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
-	if key == "" {
-		return "", false, nil
-	}
-
-	// if expansion is disabled we allow circular references
-	if p.DisableExpansion {
-		prev, ok = p.Get(key)
-		p.m[key] = value
-		if !ok {
-			p.k = append(p.k, key)
-		}
-		return prev, ok, nil
-	}
-
-	// to check for a circular reference we temporarily need
-	// to set the new value. If there is an error then revert
-	// to the previous state. Only if all tests are successful
-	// then we add the key to the p.k list.
-	prev, ok = p.Get(key)
-	p.m[key] = value
-
-	// now check for a circular reference
-	_, err = p.expand(key, value)
-	if err != nil {
-
-		// revert to the previous state
-		if ok {
-			p.m[key] = prev
-		} else {
-			delete(p.m, key)
-		}
-
-		return "", false, err
-	}
-
-	if !ok {
-		p.k = append(p.k, key)
-	}
-
-	return prev, ok, nil
-}
-
-// SetValue sets property key to the default string value
-// as defined by fmt.Sprintf("%v").
-func (p *Properties) SetValue(key string, value interface{}) error {
-	_, _, err := p.Set(key, fmt.Sprintf("%v", value))
-	return err
-}
-
-// MustSet sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. An empty key is silently ignored.
-func (p *Properties) MustSet(key, value string) (prev string, ok bool) {
-	prev, ok, err := p.Set(key, value)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return prev, ok
-}
-
-// String returns a string of all expanded 'key = value' pairs.
-func (p *Properties) String() string {
-	var s string
-	for _, key := range p.k {
-		value, _ := p.Get(key)
-		s = fmt.Sprintf("%s%s = %s\n", s, key, value)
-	}
-	return s
-}
-
-// Sort sorts the properties keys in alphabetical order.
-// This is helpfully before writing the properties.
-func (p *Properties) Sort() {
-	sort.Strings(p.k)
-}
-
-// Write writes all unexpanded 'key = value' pairs to the given writer.
-// Write returns the number of bytes written and any write error encountered.
-func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) {
-	return p.WriteComment(w, "", enc)
-}
-
-// WriteComment writes all unexpanced 'key = value' pairs to the given writer.
-// If prefix is not empty then comments are written with a blank line and the
-// given prefix. The prefix should be either "# " or "! " to be compatible with
-// the properties file format. Otherwise, the properties parser will not be
-// able to read the file back in. It returns the number of bytes written and
-// any write error encountered.
-func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) {
-	var x int
-
-	for _, key := range p.k {
-		value := p.m[key]
-
-		if prefix != "" {
-			if comments, ok := p.c[key]; ok {
-				// don't print comments if they are all empty
-				allEmpty := true
-				for _, c := range comments {
-					if c != "" {
-						allEmpty = false
-						break
-					}
-				}
-
-				if !allEmpty {
-					// add a blank line between entries but not at the top
-					if len(comments) > 0 && n > 0 {
-						x, err = fmt.Fprintln(w)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-
-					for _, c := range comments {
-						x, err = fmt.Fprintf(w, "%s%s\n", prefix, c)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-				}
-			}
-		}
-		sep := " = "
-		if p.WriteSeparator != "" {
-			sep = p.WriteSeparator
-		}
-		x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc))
-		if err != nil {
-			return
-		}
-		n += x
-	}
-	return
-}
-
-// Map returns a copy of the properties as a map.
-func (p *Properties) Map() map[string]string {
-	m := make(map[string]string)
-	for k, v := range p.m {
-		m[k] = v
-	}
-	return m
-}
-
-// FilterFunc returns a copy of the properties which includes the values which passed all filters.
-func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties {
-	pp := NewProperties()
-outer:
-	for k, v := range p.m {
-		for _, f := range filters {
-			if !f(k, v) {
-				continue outer
-			}
-			pp.Set(k, v)
-		}
-	}
-	return pp
-}
-
-// ----------------------------------------------------------------------------
-
-// Delete removes the key and its comments.
-func (p *Properties) Delete(key string) {
-	delete(p.m, key)
-	delete(p.c, key)
-	newKeys := []string{}
-	for _, k := range p.k {
-		if k != key {
-			newKeys = append(newKeys, k)
-		}
-	}
-	p.k = newKeys
-}
-
-// Merge merges properties, comments and keys from other *Properties into p
-func (p *Properties) Merge(other *Properties) {
-	for _, k := range other.k {
-		if _, ok := p.m[k]; !ok {
-			p.k = append(p.k, k)
-		}
-	}
-	for k, v := range other.m {
-		p.m[k] = v
-	}
-	for k, v := range other.c {
-		p.c[k] = v
-	}
-}
-
-// ----------------------------------------------------------------------------
-
-// check expands all values and returns an error if a circular reference or
-// a malformed expression was found.
-func (p *Properties) check() error {
-	for key, value := range p.m {
-		if _, err := p.expand(key, value); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (p *Properties) expand(key, input string) (string, error) {
-	// no pre/postfix -> nothing to expand
-	if p.Prefix == "" && p.Postfix == "" {
-		return input, nil
-	}
-
-	return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
-}
-
-// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
-// The function keeps track of the keys that were already expanded and stops if it
-// detects a circular reference or a malformed expression of the form '(prefix)key'.
-func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
-	if len(keys) > maxExpansionDepth {
-		return "", fmt.Errorf("expansion too deep")
-	}
-
-	for {
-		start := strings.Index(s, prefix)
-		if start == -1 {
-			return s, nil
-		}
-
-		keyStart := start + len(prefix)
-		keyLen := strings.Index(s[keyStart:], postfix)
-		if keyLen == -1 {
-			return "", fmt.Errorf("malformed expression")
-		}
-
-		end := keyStart + keyLen + len(postfix) - 1
-		key := s[keyStart : keyStart+keyLen]
-
-		// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
-
-		for _, k := range keys {
-			if key == k {
-				var b bytes.Buffer
-				b.WriteString("circular reference in:\n")
-				for _, k1 := range keys {
-					fmt.Fprintf(&b, "%s=%s\n", k1, values[k1])
-				}
-				return "", fmt.Errorf(b.String())
-			}
-		}
-
-		val, ok := values[key]
-		if !ok {
-			val = os.Getenv(key)
-		}
-		new_val, err := expand(val, append(keys, key), prefix, postfix, values)
-		if err != nil {
-			return "", err
-		}
-		s = s[:start] + new_val + s[end+1:]
-	}
-}
-
-// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
-func encode(s string, special string, enc Encoding) string {
-	switch enc {
-	case UTF8:
-		return encodeUtf8(s, special)
-	case ISO_8859_1:
-		return encodeIso(s, special)
-	default:
-		panic(fmt.Sprintf("unsupported encoding %v", enc))
-	}
-}
-
-func encodeUtf8(s string, special string) string {
-	v := ""
-	for pos := 0; pos < len(s); {
-		r, w := utf8.DecodeRuneInString(s[pos:])
-		pos += w
-		v += escape(r, special)
-	}
-	return v
-}
-
-func encodeIso(s string, special string) string {
-	var r rune
-	var w int
-	var v string
-	for pos := 0; pos < len(s); {
-		switch r, w = utf8.DecodeRuneInString(s[pos:]); {
-		case r < 1<<8: // single byte rune -> escape special chars only
-			v += escape(r, special)
-		case r < 1<<16: // two byte rune -> unicode literal
-			v += fmt.Sprintf("\\u%04x", r)
-		default: // more than two bytes per rune -> can't encode
-			v += "?"
-		}
-		pos += w
-	}
-	return v
-}
-
-func escape(r rune, special string) string {
-	switch r {
-	case '\f':
-		return "\\f"
-	case '\n':
-		return "\\n"
-	case '\r':
-		return "\\r"
-	case '\t':
-		return "\\t"
-	case '\\':
-		return "\\\\"
-	default:
-		if strings.ContainsRune(special, r) {
-			return "\\" + string(r)
-		}
-		return string(r)
-	}
-}
-
-func invalidKeyError(key string) error {
-	return fmt.Errorf("unknown property: %s", key)
-}
diff --git a/notifier/vendor/github.com/magiconair/properties/rangecheck.go b/notifier/vendor/github.com/magiconair/properties/rangecheck.go
deleted file mode 100644
index dbd60b36..00000000
--- a/notifier/vendor/github.com/magiconair/properties/rangecheck.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"math"
-)
-
-// make this a var to overwrite it in a test
-var is32Bit = ^uint(0) == math.MaxUint32
-
-// intRangeCheck checks if the value fits into the int type and
-// panics if it does not.
-func intRangeCheck(key string, v int64) int {
-	if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return int(v)
-}
-
-// uintRangeCheck checks if the value fits into the uint type and
-// panics if it does not.
-func uintRangeCheck(key string, v uint64) uint {
-	if is32Bit && v > math.MaxUint32 {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return uint(v)
-}
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/notifier/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
deleted file mode 100644
index c7582349..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ /dev/null
@@ -1,96 +0,0 @@
-## 1.5.0
-
-* New option `IgnoreUntaggedFields` to ignore decoding to any fields
-  without `mapstructure` (or the configured tag name) set [GH-277]
-* New option `ErrorUnset` which makes it an error if any fields
-  in a target struct are not set by the decoding process. [GH-225]
-* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
-* Decoding to slice from array no longer crashes [GH-265]
-* Decode nested struct pointers to map [GH-271]
-* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
-* Fix issue where fields with `,omitempty` would sometimes decode
-  into a map with an empty string key [GH-281]
-
-## 1.4.3
-
-* Fix cases where `json.Number` didn't decode properly [GH-261]
-
-## 1.4.2
-
-* Custom name matchers to support any sort of casing, formatting, etc. for
-  field names. [GH-250]
-* Fix possible panic in ComposeDecodeHookFunc [GH-251]
-
-## 1.4.1
-
-* Fix regression where `*time.Time` value would be set to empty and not be sent
-  to decode hooks properly [GH-232]
-
-## 1.4.0
-
-* A new decode hook type `DecodeHookFuncValue` has been added that has
-  access to the full values. [GH-183]
-* Squash is now supported with embedded fields that are struct pointers [GH-205]
-* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206]
-
-## 1.3.3
-
-* Decoding maps from maps creates a settable value for decode hooks [GH-203]
-
-## 1.3.2
-
-* Decode into interface type with a struct value is supported [GH-187]
-
-## 1.3.1
-
-* Squash should only squash embedded structs. [GH-194]
-
-## 1.3.0
-
-* Added `",omitempty"` support. This will ignore zero values in the source
-  structure when encoding. [GH-145]
-
-## 1.2.3
-
-* Fix duplicate entries in Keys list with pointer values. [GH-185]
-
-## 1.2.2
-
-* Do not add unsettable (unexported) values to the unused metadata key
-  or "remain" value. [GH-150]
-
-## 1.2.1
-
-* Go modules checksum mismatch fix
-
-## 1.2.0
-
-* Added support to capture unused values in a field using the `",remain"` value
-  in the mapstructure tag. There is an example to showcase usage.
-* Added `DecoderConfig` option to always squash embedded structs
-* `json.Number` can decode into `uint` types
-* Empty slices are preserved and not replaced with nil slices
-* Fix panic that can occur in when decoding a map into a nil slice of structs
-* Improved package documentation for godoc
-
-## 1.1.2
-
-* Fix error when decode hook decodes interface implementation into interface
-  type. [GH-140]
-
-## 1.1.1
-
-* Fix panic that can happen in `decodePtr`
-
-## 1.1.0
-
-* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133]
-* Support struct to struct decoding [GH-137]
-* If source map value is nil, then destination map value is nil (instead of empty)
-* If source slice value is nil, then destination slice value is nil (instead of empty)
-* If source pointer is nil, then destination pointer is set to nil (instead of
-  allocated zero value of type)
-
-## 1.0.0
-
-* Initial tagged stable release.
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/LICENSE b/notifier/vendor/github.com/mitchellh/mapstructure/LICENSE
deleted file mode 100644
index f9c841a5..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Mitchell Hashimoto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/README.md b/notifier/vendor/github.com/mitchellh/mapstructure/README.md
deleted file mode 100644
index 0018dc7d..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure)
-
-mapstructure is a Go library for decoding generic map values to structures
-and vice versa, while providing helpful error handling.
-
-This library is most useful when decoding values from some data stream (JSON,
-Gob, etc.) where you don't _quite_ know the structure of the underlying data
-until you read a part of it. You can therefore read a `map[string]interface{}`
-and use this library to decode it into the proper underlying native Go
-structure.
-
-## Installation
-
-Standard `go get`:
-
-```
-$ go get github.com/mitchellh/mapstructure
-```
-
-## Usage & Example
-
-For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).
-
-The `Decode` function has examples associated with it there.
-
-## But Why?!
-
-Go offers fantastic standard libraries for decoding formats such as JSON.
-The standard method is to have a struct pre-created, and populate that struct
-from the bytes of the encoded format. This is great, but the problem is if
-you have configuration or an encoding that changes slightly depending on
-specific fields. For example, consider this JSON:
-
-```json
-{
-  "type": "person",
-  "name": "Mitchell"
-}
-```
-
-Perhaps we can't populate a specific structure without first reading
-the "type" field from the JSON. We could always do two passes over the
-decoding of the JSON (reading the "type" first, and the rest later).
-However, it is much simpler to just decode this into a `map[string]interface{}`
-structure, read the "type" key, then use something like this library
-to decode it into the proper structure.
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/notifier/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
deleted file mode 100644
index 3a754ca7..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package mapstructure
-
-import (
-	"encoding"
-	"errors"
-	"fmt"
-	"net"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
-// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
-func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
-	// Create variables here so we can reference them with the reflect pkg
-	var f1 DecodeHookFuncType
-	var f2 DecodeHookFuncKind
-	var f3 DecodeHookFuncValue
-
-	// Fill in the variables into this interface and the rest is done
-	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
-
-	v := reflect.ValueOf(h)
-	vt := v.Type()
-	for _, raw := range potential {
-		pt := reflect.ValueOf(raw).Type()
-		if vt.ConvertibleTo(pt) {
-			return v.Convert(pt).Interface()
-		}
-	}
-
-	return nil
-}
-
-// DecodeHookExec executes the given decode hook. This should be used
-// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
-// that took reflect.Kind instead of reflect.Type.
-func DecodeHookExec(
-	raw DecodeHookFunc,
-	from reflect.Value, to reflect.Value) (interface{}, error) {
-
-	switch f := typedDecodeHook(raw).(type) {
-	case DecodeHookFuncType:
-		return f(from.Type(), to.Type(), from.Interface())
-	case DecodeHookFuncKind:
-		return f(from.Kind(), to.Kind(), from.Interface())
-	case DecodeHookFuncValue:
-		return f(from, to)
-	default:
-		return nil, errors.New("invalid decode hook signature")
-	}
-}
-
-// ComposeDecodeHookFunc creates a single DecodeHookFunc that
-// automatically composes multiple DecodeHookFuncs.
-//
-// The composed funcs are called in order, with the result of the
-// previous transformation.
-func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		var err error
-		data := f.Interface()
-
-		newFrom := f
-		for _, f1 := range fs {
-			data, err = DecodeHookExec(f1, newFrom, t)
-			if err != nil {
-				return nil, err
-			}
-			newFrom = reflect.ValueOf(data)
-		}
-
-		return data, nil
-	}
-}
-
-// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
-// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
-func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	return func(a, b reflect.Value) (interface{}, error) {
-		var allErrs string
-		var out interface{}
-		var err error
-
-		for _, f := range ff {
-			out, err = DecodeHookExec(f, a, b)
-			if err != nil {
-				allErrs += err.Error() + "\n"
-				continue
-			}
-
-			return out, nil
-		}
-
-		return nil, errors.New(allErrs)
-	}
-}
-
-// StringToSliceHookFunc returns a DecodeHookFunc that converts
-// string to []string by splitting on the given sep.
-func StringToSliceHookFunc(sep string) DecodeHookFunc {
-	return func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		if f != reflect.String || t != reflect.Slice {
-			return data, nil
-		}
-
-		raw := data.(string)
-		if raw == "" {
-			return []string{}, nil
-		}
-
-		return strings.Split(raw, sep), nil
-	}
-}
-
-// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
-// strings to time.Duration.
-func StringToTimeDurationHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Duration(5)) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.ParseDuration(data.(string))
-	}
-}
-
-// StringToIPHookFunc returns a DecodeHookFunc that converts
-// strings to net.IP
-func StringToIPHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IP{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		ip := net.ParseIP(data.(string))
-		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
-		}
-
-		return ip, nil
-	}
-}
-
-// StringToIPNetHookFunc returns a DecodeHookFunc that converts
-// strings to net.IPNet
-func StringToIPNetHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IPNet{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
-	}
-}
-
-// StringToTimeHookFunc returns a DecodeHookFunc that converts
-// strings to time.Time.
-func StringToTimeHookFunc(layout string) DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Time{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.Parse(layout, data.(string))
-	}
-}
-
-// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
-// the decoder.
-//
-// Note that this is significantly different from the WeaklyTypedInput option
-// of the DecoderConfig.
-func WeaklyTypedHook(
-	f reflect.Kind,
-	t reflect.Kind,
-	data interface{}) (interface{}, error) {
-	dataVal := reflect.ValueOf(data)
-	switch t {
-	case reflect.String:
-		switch f {
-		case reflect.Bool:
-			if dataVal.Bool() {
-				return "1", nil
-			}
-			return "0", nil
-		case reflect.Float32:
-			return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
-		case reflect.Int:
-			return strconv.FormatInt(dataVal.Int(), 10), nil
-		case reflect.Slice:
-			dataType := dataVal.Type()
-			elemKind := dataType.Elem().Kind()
-			if elemKind == reflect.Uint8 {
-				return string(dataVal.Interface().([]uint8)), nil
-			}
-		case reflect.Uint:
-			return strconv.FormatUint(dataVal.Uint(), 10), nil
-		}
-	}
-
-	return data, nil
-}
-
-func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		if f.Kind() != reflect.Struct {
-			return f.Interface(), nil
-		}
-
-		var i interface{} = struct{}{}
-		if t.Type() != reflect.TypeOf(&i).Elem() {
-			return f.Interface(), nil
-		}
-
-		m := make(map[string]interface{})
-		t.Set(reflect.ValueOf(m))
-
-		return f.Interface(), nil
-	}
-}
-
-// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
-// strings to the UnmarshalText function, when the target type
-// implements the encoding.TextUnmarshaler interface
-func TextUnmarshallerHookFunc() DecodeHookFuncType {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		result := reflect.New(t).Interface()
-		unmarshaller, ok := result.(encoding.TextUnmarshaler)
-		if !ok {
-			return data, nil
-		}
-		if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
-			return nil, err
-		}
-		return result, nil
-	}
-}
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/error.go b/notifier/vendor/github.com/mitchellh/mapstructure/error.go
deleted file mode 100644
index 47a99e5a..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/error.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package mapstructure
-
-import (
-	"errors"
-	"fmt"
-	"sort"
-	"strings"
-)
-
-// Error implements the error interface and can represents multiple
-// errors that occur in the course of a single decode.
-type Error struct {
-	Errors []string
-}
-
-func (e *Error) Error() string {
-	points := make([]string, len(e.Errors))
-	for i, err := range e.Errors {
-		points[i] = fmt.Sprintf("* %s", err)
-	}
-
-	sort.Strings(points)
-	return fmt.Sprintf(
-		"%d error(s) decoding:\n\n%s",
-		len(e.Errors), strings.Join(points, "\n"))
-}
-
-// WrappedErrors implements the errwrap.Wrapper interface to make this
-// return value more useful with the errwrap and go-multierror libraries.
-func (e *Error) WrappedErrors() []error {
-	if e == nil {
-		return nil
-	}
-
-	result := make([]error, len(e.Errors))
-	for i, e := range e.Errors {
-		result[i] = errors.New(e)
-	}
-
-	return result
-}
-
-func appendErrors(errors []string, err error) []string {
-	switch e := err.(type) {
-	case *Error:
-		return append(errors, e.Errors...)
-	default:
-		return append(errors, e.Error())
-	}
-}
diff --git a/notifier/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/notifier/vendor/github.com/mitchellh/mapstructure/mapstructure.go
deleted file mode 100644
index 1efb22ac..00000000
--- a/notifier/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ /dev/null
@@ -1,1540 +0,0 @@
-// Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
-// into a native Go structure.
-//
-// The Go structure can be arbitrarily complex, containing slices,
-// other structs, etc. and the decoder will properly decode nested
-// maps and so on into the proper structures in the native Go struct.
-// See the examples to see what the decoder is capable of.
-//
-// The simplest function to start with is Decode.
-//
-// Field Tags
-//
-// When decoding to a struct, mapstructure will use the field name by
-// default to perform the mapping. For example, if a struct has a field
-// "Username" then mapstructure will look for a key in the source value
-// of "username" (case insensitive).
-//
-//     type User struct {
-//         Username string
-//     }
-//
-// You can change the behavior of mapstructure by using struct tags.
-// The default struct tag that mapstructure looks for is "mapstructure"
-// but you can customize it using DecoderConfig.
-//
-// Renaming Fields
-//
-// To rename the key that mapstructure looks for, use the "mapstructure"
-// tag and set a value directly. For example, to change the "username" example
-// above to "user":
-//
-//     type User struct {
-//         Username string `mapstructure:"user"`
-//     }
-//
-// Embedded Structs and Squashing
-//
-// Embedded structs are treated as if they're another field with that name.
-// By default, the two structs below are equivalent when decoding with
-// mapstructure:
-//
-//     type Person struct {
-//         Name string
-//     }
-//
-//     type Friend struct {
-//         Person
-//     }
-//
-//     type Friend struct {
-//         Person Person
-//     }
-//
-// This would require an input that looks like below:
-//
-//     map[string]interface{}{
-//         "person": map[string]interface{}{"name": "alice"},
-//     }
-//
-// If your "person" value is NOT nested, then you can append ",squash" to
-// your tag value and mapstructure will treat it as if the embedded struct
-// were part of the struct directly. Example:
-//
-//     type Friend struct {
-//         Person `mapstructure:",squash"`
-//     }
-//
-// Now the following input would be accepted:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// When decoding from a struct to a map, the squash tag squashes the struct
-// fields into a single map. Using the example structs from above:
-//
-//     Friend{Person: Person{Name: "alice"}}
-//
-// Will be decoded into a map:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// DecoderConfig has a field that changes the behavior of mapstructure
-// to always squash embedded structs.
-//
-// Remainder Values
-//
-// If there are any unmapped keys in the source value, mapstructure by
-// default will silently ignore them. You can error by setting ErrorUnused
-// in DecoderConfig. If you're using Metadata you can also maintain a slice
-// of the unused keys.
-//
-// You can also use the ",remain" suffix on your tag to collect all unused
-// values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
-// See example below:
-//
-//     type Friend struct {
-//         Name  string
-//         Other map[string]interface{} `mapstructure:",remain"`
-//     }
-//
-// Given the input below, Other would be populated with the other
-// values that weren't used (everything but "name"):
-//
-//     map[string]interface{}{
-//         "name":    "bob",
-//         "address": "123 Maple St.",
-//     }
-//
-// Omit Empty Values
-//
-// When decoding from a struct to any other value, you may use the
-// ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
-//
-// For example, the zero type of a numeric type is zero ("0"). If the struct
-// field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
-//
-//     type Source struct {
-//         Age int `mapstructure:",omitempty"`
-//     }
-//
-// Unexported fields
-//
-// Since unexported (private) struct fields cannot be set outside the package
-// where they are defined, the decoder will simply skip them.
-//
-// For this output type definition:
-//
-//     type Exported struct {
-//         private string // this unexported field will be skipped
-//         Public string
-//     }
-//
-// Using this map as input:
-//
-//     map[string]interface{}{
-//         "private": "I will be ignored",
-//         "Public":  "I made it through!",
-//     }
-//
-// The following struct will be decoded:
-//
-//     type Exported struct {
-//         private: "" // field is left with an empty string (zero value)
-//         Public: "I made it through!"
-//     }
-//
-// Other Configuration
-//
-// mapstructure is highly configurable. See the DecoderConfig struct
-// for other features and options that are supported.
-package mapstructure
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-)
-
-// DecodeHookFunc is the callback function that can be used for
-// data transformations. See "DecodeHook" in the DecoderConfig
-// struct.
-//
-// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or
-// DecodeHookFuncValue.
-// Values are a superset of Types (Values can return types), and Types are a
-// superset of Kinds (Types can return Kinds) and are generally a richer thing
-// to use, but Kinds are simpler if you only need those.
-//
-// The reason DecodeHookFunc is multi-typed is for backwards compatibility:
-// we started with Kinds and then realized Types were the better solution,
-// but have a promise to not break backwards compat so we now support
-// both.
-type DecodeHookFunc interface{}
-
-// DecodeHookFuncType is a DecodeHookFunc which has complete information about
-// the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
-
-// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
-// source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
-
-// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
-// values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
-
-// DecoderConfig is the configuration that is used to create a new decoder
-// and allows customization of various aspects of decoding.
-type DecoderConfig struct {
-	// DecodeHook, if set, will be called before any decoding and any
-	// type conversion (if WeaklyTypedInput is on). This lets you modify
-	// the values before they're set down onto the resulting struct. The
-	// DecodeHook is called for every map and value in the input. This means
-	// that if a struct has embedded fields with squash tags the decode hook
-	// is called only once with all of the input data, not once for each
-	// embedded struct.
-	//
-	// If an error is returned, the entire decode will fail with that error.
-	DecodeHook DecodeHookFunc
-
-	// If ErrorUnused is true, then it is an error for there to exist
-	// keys in the original map that were unused in the decoding process
-	// (extra keys).
-	ErrorUnused bool
-
-	// If ErrorUnset is true, then it is an error for there to exist
-	// fields in the result that were not set in the decoding process
-	// (extra fields). This only applies to decoding to a struct. This
-	// will affect all nested structs as well.
-	ErrorUnset bool
-
-	// ZeroFields, if set to true, will zero fields before writing them.
-	// For example, a map will be emptied before decoded values are put in
-	// it. If this is false, a map will be merged.
-	ZeroFields bool
-
-	// If WeaklyTypedInput is true, the decoder will make the following
-	// "weak" conversions:
-	//
-	//   - bools to string (true = "1", false = "0")
-	//   - numbers to string (base 10)
-	//   - bools to int/uint (true = 1, false = 0)
-	//   - strings to int/uint (base implied by prefix)
-	//   - int to bool (true if value != 0)
-	//   - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
-	//     FALSE, false, False. Anything else is an error)
-	//   - empty array = empty map and vice versa
-	//   - negative numbers to overflowed uint values (base 10)
-	//   - slice of maps to a merged map
-	//   - single values are converted to slices if required. Each
-	//     element is weakly decoded. For example: "4" can become []int{4}
-	//     if the target type is an int slice.
-	//
-	WeaklyTypedInput bool
-
-	// Squash will squash embedded structs.  A squash tag may also be
-	// added to an individual struct field using a tag.  For example:
-	//
-	//  type Parent struct {
-	//      Child `mapstructure:",squash"`
-	//  }
-	Squash bool
-
-	// Metadata is the struct that will contain extra metadata about
-	// the decoding. If this is nil, then no metadata will be tracked.
-	Metadata *Metadata
-
-	// Result is a pointer to the struct that will contain the decoded
-	// value.
-	Result interface{}
-
-	// The tag name that mapstructure reads for field names. This
-	// defaults to "mapstructure"
-	TagName string
-
-	// IgnoreUntaggedFields ignores all struct fields without explicit
-	// TagName, comparable to `mapstructure:"-"` as default behaviour.
-	IgnoreUntaggedFields bool
-
-	// MatchName is the function used to match the map key to the struct
-	// field name or tag. Defaults to `strings.EqualFold`. This can be used
-	// to implement case-sensitive tag values, support snake casing, etc.
-	MatchName func(mapKey, fieldName string) bool
-}
-
-// A Decoder takes a raw interface value and turns it into structured
-// data, keeping track of rich error information along the way in case
-// anything goes wrong. Unlike the basic top-level Decode method, you can
-// more finely control how the Decoder behaves using the DecoderConfig
-// structure. The top-level Decode method is just a convenience that sets
-// up the most basic Decoder.
-type Decoder struct {
-	config *DecoderConfig
-}
-
-// Metadata contains information about decoding a structure that
-// is tedious or difficult to get otherwise.
-type Metadata struct {
-	// Keys are the keys of the structure which were successfully decoded
-	Keys []string
-
-	// Unused is a slice of keys that were found in the raw value but
-	// weren't decoded since there was no matching field in the result interface
-	Unused []string
-
-	// Unset is a slice of field names that were found in the result interface
-	// but weren't set in the decoding process since there was no matching value
-	// in the input
-	Unset []string
-}
-
-// Decode takes an input structure and uses reflection to translate it to
-// the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata: nil,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecode is the same as Decode but is shorthand to enable
-// WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata:         nil,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// DecodeMetadata is the same as Decode, but is shorthand to
-// enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata: metadata,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecodeMetadata is the same as Decode, but is shorthand to
-// enable both WeaklyTypedInput and metadata collection. See
-// DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata:         metadata,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// NewDecoder returns a new decoder for the given configuration. Once
-// a decoder has been returned, the same configuration must not be used
-// again.
-func NewDecoder(config *DecoderConfig) (*Decoder, error) {
-	val := reflect.ValueOf(config.Result)
-	if val.Kind() != reflect.Ptr {
-		return nil, errors.New("result must be a pointer")
-	}
-
-	val = val.Elem()
-	if !val.CanAddr() {
-		return nil, errors.New("result must be addressable (a pointer)")
-	}
-
-	if config.Metadata != nil {
-		if config.Metadata.Keys == nil {
-			config.Metadata.Keys = make([]string, 0)
-		}
-
-		if config.Metadata.Unused == nil {
-			config.Metadata.Unused = make([]string, 0)
-		}
-
-		if config.Metadata.Unset == nil {
-			config.Metadata.Unset = make([]string, 0)
-		}
-	}
-
-	if config.TagName == "" {
-		config.TagName = "mapstructure"
-	}
-
-	if config.MatchName == nil {
-		config.MatchName = strings.EqualFold
-	}
-
-	result := &Decoder{
-		config: config,
-	}
-
-	return result, nil
-}
-
-// Decode decodes the given raw interface to the target pointer specified
-// by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
-	return d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
-}
-
-// Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
-	var inputVal reflect.Value
-	if input != nil {
-		inputVal = reflect.ValueOf(input)
-
-		// We need to check here if input is a typed nil. Typed nils won't
-		// match the "input == nil" below so we check that here.
-		if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() {
-			input = nil
-		}
-	}
-
-	if input == nil {
-		// If the data is nil, then we don't set anything, unless ZeroFields is set
-		// to true.
-		if d.config.ZeroFields {
-			outVal.Set(reflect.Zero(outVal.Type()))
-
-			if d.config.Metadata != nil && name != "" {
-				d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-			}
-		}
-		return nil
-	}
-
-	if !inputVal.IsValid() {
-		// If the input value is invalid, then we just set the value
-		// to be the zero value.
-		outVal.Set(reflect.Zero(outVal.Type()))
-		if d.config.Metadata != nil && name != "" {
-			d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-		}
-		return nil
-	}
-
-	if d.config.DecodeHook != nil {
-		// We have a DecodeHook, so let's pre-process the input.
-		var err error
-		input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal)
-		if err != nil {
-			return fmt.Errorf("error decoding '%s': %s", name, err)
-		}
-	}
-
-	var err error
-	outputKind := getKind(outVal)
-	addMetaKey := true
-	switch outputKind {
-	case reflect.Bool:
-		err = d.decodeBool(name, input, outVal)
-	case reflect.Interface:
-		err = d.decodeBasic(name, input, outVal)
-	case reflect.String:
-		err = d.decodeString(name, input, outVal)
-	case reflect.Int:
-		err = d.decodeInt(name, input, outVal)
-	case reflect.Uint:
-		err = d.decodeUint(name, input, outVal)
-	case reflect.Float32:
-		err = d.decodeFloat(name, input, outVal)
-	case reflect.Struct:
-		err = d.decodeStruct(name, input, outVal)
-	case reflect.Map:
-		err = d.decodeMap(name, input, outVal)
-	case reflect.Ptr:
-		addMetaKey, err = d.decodePtr(name, input, outVal)
-	case reflect.Slice:
-		err = d.decodeSlice(name, input, outVal)
-	case reflect.Array:
-		err = d.decodeArray(name, input, outVal)
-	case reflect.Func:
-		err = d.decodeFunc(name, input, outVal)
-	default:
-		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
-	}
-
-	// If we reached here, then we successfully decoded SOMETHING, so
-	// mark the key as used if we're tracking metainput.
-	if addMetaKey && d.config.Metadata != nil && name != "" {
-		d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-	}
-
-	return err
-}
-
-// This decodes a basic type (bool, int, string, etc.) and sets the
-// value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
-	if val.IsValid() && val.Elem().IsValid() {
-		elem := val.Elem()
-
-		// If we can't address this element, then its not writable. Instead,
-		// we make a copy of the value (which is a pointer and therefore
-		// writable), decode into that, and replace the whole value.
-		copied := false
-		if !elem.CanAddr() {
-			copied = true
-
-			// Make *T
-			copy := reflect.New(elem.Type())
-
-			// *T = elem
-			copy.Elem().Set(elem)
-
-			// Set elem so we decode into it
-			elem = copy
-		}
-
-		// Decode. If we have an error then return. We also return right
-		// away if we're not a copy because that means we decoded directly.
-		if err := d.decode(name, data, elem); err != nil || !copied {
-			return err
-		}
-
-		// If we're a copy, we need to set te final result
-		val.Set(elem.Elem())
-		return nil
-	}
-
-	dataVal := reflect.ValueOf(data)
-
-	// If the input data is a pointer, and the assigned type is the dereference
-	// of that exact pointer, then indirect it so that we can assign it.
-	// Example: *string to string
-	if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() {
-		dataVal = reflect.Indirect(dataVal)
-	}
-
-	if !dataVal.IsValid() {
-		dataVal = reflect.Zero(val.Type())
-	}
-
-	dataValType := dataVal.Type()
-	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
-	}
-
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	converted := true
-	switch {
-	case dataKind == reflect.String:
-		val.SetString(dataVal.String())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetString("1")
-		} else {
-			val.SetString("0")
-		}
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatInt(dataVal.Int(), 10))
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
-	case dataKind == reflect.Slice && d.config.WeaklyTypedInput,
-		dataKind == reflect.Array && d.config.WeaklyTypedInput:
-		dataType := dataVal.Type()
-		elemKind := dataType.Elem().Kind()
-		switch elemKind {
-		case reflect.Uint8:
-			var uints []uint8
-			if dataKind == reflect.Array {
-				uints = make([]uint8, dataVal.Len(), dataVal.Len())
-				for i := range uints {
-					uints[i] = dataVal.Index(i).Interface().(uint8)
-				}
-			} else {
-				uints = dataVal.Interface().([]uint8)
-			}
-			val.SetString(string(uints))
-		default:
-			converted = false
-		}
-	default:
-		converted = false
-	}
-
-	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetInt(dataVal.Int())
-	case dataKind == reflect.Uint:
-		val.SetInt(int64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetInt(int64(dataVal.Float()))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetInt(1)
-		} else {
-			val.SetInt(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseInt(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetInt(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Int64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetInt(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		i := dataVal.Int()
-		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
-		}
-		val.SetUint(uint64(i))
-	case dataKind == reflect.Uint:
-		val.SetUint(dataVal.Uint())
-	case dataKind == reflect.Float32:
-		f := dataVal.Float()
-		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
-		}
-		val.SetUint(uint64(f))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetUint(1)
-		} else {
-			val.SetUint(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseUint(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetUint(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := strconv.ParseUint(string(jn), 0, 64)
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetUint(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	switch {
-	case dataKind == reflect.Bool:
-		val.SetBool(dataVal.Bool())
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Int() != 0)
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Uint() != 0)
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Float() != 0)
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		b, err := strconv.ParseBool(dataVal.String())
-		if err == nil {
-			val.SetBool(b)
-		} else if dataVal.String() == "" {
-			val.SetBool(false)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
-		}
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetFloat(float64(dataVal.Int()))
-	case dataKind == reflect.Uint:
-		val.SetFloat(float64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetFloat(dataVal.Float())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetFloat(1)
-		} else {
-			val.SetFloat(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		f, err := strconv.ParseFloat(str, val.Type().Bits())
-		if err == nil {
-			val.SetFloat(f)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Float64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetFloat(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// By default we overwrite keys in the current map
-	valMap := val
-
-	// If the map is nil or we're purposely zeroing fields, make a new map
-	if valMap.IsNil() || d.config.ZeroFields {
-		// Make a new map to hold our result
-		mapType := reflect.MapOf(valKeyType, valElemType)
-		valMap = reflect.MakeMap(mapType)
-	}
-
-	// Check input type and based on the input type jump to the proper func
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	switch dataVal.Kind() {
-	case reflect.Map:
-		return d.decodeMapFromMap(name, dataVal, val, valMap)
-
-	case reflect.Struct:
-		return d.decodeMapFromStruct(name, dataVal, val, valMap)
-
-	case reflect.Array, reflect.Slice:
-		if d.config.WeaklyTypedInput {
-			return d.decodeMapFromSlice(name, dataVal, val, valMap)
-		}
-
-		fallthrough
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	// Special case for BC reasons (covered by tests)
-	if dataVal.Len() == 0 {
-		val.Set(valMap)
-		return nil
-	}
-
-	for i := 0; i < dataVal.Len(); i++ {
-		err := d.decode(
-			name+"["+strconv.Itoa(i)+"]",
-			dataVal.Index(i).Interface(), val)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// Accumulate errors
-	errors := make([]string, 0)
-
-	// If the input data is empty, then we just match what the input data is.
-	if dataVal.Len() == 0 {
-		if dataVal.IsNil() {
-			if !val.IsNil() {
-				val.Set(dataVal)
-			}
-		} else {
-			// Set to empty allocated value
-			val.Set(valMap)
-		}
-
-		return nil
-	}
-
-	for _, k := range dataVal.MapKeys() {
-		fieldName := name + "[" + k.String() + "]"
-
-		// First decode the key into the proper type
-		currentKey := reflect.Indirect(reflect.New(valKeyType))
-		if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		// Next decode the data into the proper type
-		v := dataVal.MapIndex(k).Interface()
-		currentVal := reflect.Indirect(reflect.New(valElemType))
-		if err := d.decode(fieldName, v, currentVal); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		valMap.SetMapIndex(currentKey, currentVal)
-	}
-
-	// Set the built up map to the value
-	val.Set(valMap)
-
-	// If we had errors, return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	typ := dataVal.Type()
-	for i := 0; i < typ.NumField(); i++ {
-		// Get the StructField first since this is a cheap operation. If the
-		// field is unexported, then ignore it.
-		f := typ.Field(i)
-		if f.PkgPath != "" {
-			continue
-		}
-
-		// Next get the actual value of this field and verify it is assignable
-		// to the map value.
-		v := dataVal.Field(i)
-		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
-		}
-
-		tagValue := f.Tag.Get(d.config.TagName)
-		keyName := f.Name
-
-		if tagValue == "" && d.config.IgnoreUntaggedFields {
-			continue
-		}
-
-		// If Squash is set in the config, we squash the field down.
-		squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
-
-		v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
-
-		// Determine the name of the key in the map
-		if index := strings.Index(tagValue, ","); index != -1 {
-			if tagValue[:index] == "-" {
-				continue
-			}
-			// If "omitempty" is specified in the tag, it ignores empty values.
-			if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) {
-				continue
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
-			if squash {
-				// When squashing, the embedded type can be a pointer to a struct.
-				if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
-					v = v.Elem()
-				}
-
-				// The final type must be a struct
-				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
-				}
-			}
-			if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
-				keyName = keyNameTagValue
-			}
-		} else if len(tagValue) > 0 {
-			if tagValue == "-" {
-				continue
-			}
-			keyName = tagValue
-		}
-
-		switch v.Kind() {
-		// this is an embedded struct, so handle it differently
-		case reflect.Struct:
-			x := reflect.New(v.Type())
-			x.Elem().Set(v)
-
-			vType := valMap.Type()
-			vKeyType := vType.Key()
-			vElemType := vType.Elem()
-			mType := reflect.MapOf(vKeyType, vElemType)
-			vMap := reflect.MakeMap(mType)
-
-			// Creating a pointer to a map so that other methods can completely
-			// overwrite the map if need be (looking at you decodeMapFromMap). The
-			// indirection allows the underlying map to be settable (CanSet() == true)
-			// where as reflect.MakeMap returns an unsettable map.
-			addrVal := reflect.New(vMap.Type())
-			reflect.Indirect(addrVal).Set(vMap)
-
-			err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal))
-			if err != nil {
-				return err
-			}
-
-			// the underlying map may have been completely overwritten so pull
-			// it indirectly out of the enclosing value.
-			vMap = reflect.Indirect(addrVal)
-
-			if squash {
-				for _, k := range vMap.MapKeys() {
-					valMap.SetMapIndex(k, vMap.MapIndex(k))
-				}
-			} else {
-				valMap.SetMapIndex(reflect.ValueOf(keyName), vMap)
-			}
-
-		default:
-			valMap.SetMapIndex(reflect.ValueOf(keyName), v)
-		}
-	}
-
-	if val.CanAddr() {
-		val.Set(valMap)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
-	// If the input data is nil, then we want to just set the output
-	// pointer to be nil as well.
-	isNil := data == nil
-	if !isNil {
-		switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
-		case reflect.Chan,
-			reflect.Func,
-			reflect.Interface,
-			reflect.Map,
-			reflect.Ptr,
-			reflect.Slice:
-			isNil = v.IsNil()
-		}
-	}
-	if isNil {
-		if !val.IsNil() && val.CanSet() {
-			nilValue := reflect.New(val.Type()).Elem()
-			val.Set(nilValue)
-		}
-
-		return true, nil
-	}
-
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	valType := val.Type()
-	valElemType := valType.Elem()
-	if val.CanSet() {
-		realVal := val
-		if realVal.IsNil() || d.config.ZeroFields {
-			realVal = reflect.New(valElemType)
-		}
-
-		if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
-			return false, err
-		}
-
-		val.Set(realVal)
-	} else {
-		if err := d.decode(name, data, reflect.Indirect(val)); err != nil {
-			return false, err
-		}
-	}
-	return false, nil
-}
-
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	sliceType := reflect.SliceOf(valElemType)
-
-	// If we have a non array/slice type then we first attempt to convert.
-	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-		if d.config.WeaklyTypedInput {
-			switch {
-			// Slice and array we use the normal logic
-			case dataValKind == reflect.Slice, dataValKind == reflect.Array:
-				break
-
-			// Empty maps turn into empty slices
-			case dataValKind == reflect.Map:
-				if dataVal.Len() == 0 {
-					val.Set(reflect.MakeSlice(sliceType, 0, 0))
-					return nil
-				}
-				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
-
-			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
-				return d.decodeSlice(name, []byte(dataVal.String()), val)
-
-			// All other types we try to convert to the slice type
-			// and "lift" it into it. i.e. a string becomes a string slice.
-			default:
-				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
-			}
-		}
-
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
-	}
-
-	// If the input value is nil, then don't allocate since empty != nil
-	if dataValKind != reflect.Array && dataVal.IsNil() {
-		return nil
-	}
-
-	valSlice := val
-	if valSlice.IsNil() || d.config.ZeroFields {
-		// Make a new slice to hold our result, same size as the original data.
-		valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		for valSlice.Len() <= i {
-			valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
-		}
-		currentField := valSlice.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the slice we built up
-	val.Set(valSlice)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	arrayType := reflect.ArrayOf(valType.Len(), valElemType)
-
-	valArray := val
-
-	if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields {
-		// Check input type
-		if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-			if d.config.WeaklyTypedInput {
-				switch {
-				// Empty maps turn into empty arrays
-				case dataValKind == reflect.Map:
-					if dataVal.Len() == 0 {
-						val.Set(reflect.Zero(arrayType))
-						return nil
-					}
-
-				// All other types we try to convert to the array type
-				// and "lift" it into it. i.e. a string becomes a string array.
-				default:
-					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
-				}
-			}
-
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
-
-		}
-		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
-
-		}
-
-		// Make a new array to hold our result, same size as the original data.
-		valArray = reflect.New(arrayType).Elem()
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		currentField := valArray.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the array we built up
-	val.Set(valArray)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-
-	// If the type of the value to write to and the data match directly,
-	// then we just set it directly instead of recursing into the structure.
-	if dataVal.Type() == val.Type() {
-		val.Set(dataVal)
-		return nil
-	}
-
-	dataValKind := dataVal.Kind()
-	switch dataValKind {
-	case reflect.Map:
-		return d.decodeStructFromMap(name, dataVal, val)
-
-	case reflect.Struct:
-		// Not the most efficient way to do this but we can optimize later if
-		// we want to. To convert from struct to struct we go to map first
-		// as an intermediary.
-
-		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
-		mval := reflect.MakeMap(mapType)
-
-		// Creating a pointer to a map so that other methods can completely
-		// overwrite the map if need be (looking at you decodeMapFromMap). The
-		// indirection allows the underlying map to be settable (CanSet() == true)
-		// where as reflect.MakeMap returns an unsettable map.
-		addrVal := reflect.New(mval.Type())
-
-		reflect.Indirect(addrVal).Set(mval)
-		if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil {
-			return err
-		}
-
-		result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val)
-		return result
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
-	dataValType := dataVal.Type()
-	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
-	}
-
-	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
-	for _, dataValKey := range dataVal.MapKeys() {
-		dataValKeys[dataValKey] = struct{}{}
-		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
-	}
-
-	targetValKeysUnused := make(map[interface{}]struct{})
-	errors := make([]string, 0)
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = val
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-
-	// remainField is set to a valid field set with the "remain" tag if
-	// we are keeping track of remaining values.
-	var remainField *field
-
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			fieldVal := structVal.Field(i)
-			if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct {
-				// Handle embedded struct pointers as embedded structs.
-				fieldVal = fieldVal.Elem()
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous
-			remain := false
-
-			// We always parse the tags cause we're looking for other tags too
-			tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
-			for _, tag := range tagParts[1:] {
-				if tag == "squash" {
-					squash = true
-					break
-				}
-
-				if tag == "remain" {
-					remain = true
-					break
-				}
-			}
-
-			if squash {
-				if fieldVal.Kind() != reflect.Struct {
-					errors = appendErrors(errors,
-						fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
-				} else {
-					structs = append(structs, fieldVal)
-				}
-				continue
-			}
-
-			// Build our field
-			if remain {
-				remainField = &field{fieldType, fieldVal}
-			} else {
-				// Normal struct field, store it away
-				fields = append(fields, field{fieldType, fieldVal})
-			}
-		}
-	}
-
-	// for fieldType, field := range fields {
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(d.config.TagName)
-		tagValue = strings.SplitN(tagValue, ",", 2)[0]
-		if tagValue != "" {
-			fieldName = tagValue
-		}
-
-		rawMapKey := reflect.ValueOf(fieldName)
-		rawMapVal := dataVal.MapIndex(rawMapKey)
-		if !rawMapVal.IsValid() {
-			// Do a slower search by iterating over each key and
-			// doing case-insensitive search.
-			for dataValKey := range dataValKeys {
-				mK, ok := dataValKey.Interface().(string)
-				if !ok {
-					// Not a string key
-					continue
-				}
-
-				if d.config.MatchName(mK, fieldName) {
-					rawMapKey = dataValKey
-					rawMapVal = dataVal.MapIndex(dataValKey)
-					break
-				}
-			}
-
-			if !rawMapVal.IsValid() {
-				// There was no matching key in the map for the value in
-				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
-				continue
-			}
-		}
-
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		// Delete the key we're using from the unused map so we stop tracking
-		delete(dataValKeysUnused, rawMapKey.Interface())
-
-		// If the name is empty string, then we're at the root, and we
-		// don't dot-join the fields.
-		if name != "" {
-			fieldName = name + "." + fieldName
-		}
-
-		if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// If we have a "remain"-tagged field and we have unused keys then
-	// we put the unused keys directly into the remain field.
-	if remainField != nil && len(dataValKeysUnused) > 0 {
-		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
-		for key := range dataValKeysUnused {
-			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
-		}
-
-		// Decode it as-if we were just decoding this map onto our map.
-		if err := d.decodeMap(name, remain, remainField.val); err != nil {
-			errors = appendErrors(errors, err)
-		}
-
-		// Set the map to nil so we have none so that the next check will
-		// not error (ErrorUnused)
-		dataValKeysUnused = nil
-	}
-
-	if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
-		keys := make([]string, 0, len(dataValKeysUnused))
-		for rawKey := range dataValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
-		keys := make([]string, 0, len(targetValKeysUnused))
-		for rawKey := range targetValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	// Add the unused keys to the list of unused keys if we're tracking metadata
-	if d.config.Metadata != nil {
-		for rawKey := range dataValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
-		}
-		for rawKey := range targetValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
-		}
-	}
-
-	return nil
-}
-
-func isEmptyValue(v reflect.Value) bool {
-	switch getKind(v) {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	}
-	return false
-}
-
-func getKind(val reflect.Value) reflect.Kind {
-	kind := val.Kind()
-
-	switch {
-	case kind >= reflect.Int && kind <= reflect.Int64:
-		return reflect.Int
-	case kind >= reflect.Uint && kind <= reflect.Uint64:
-		return reflect.Uint
-	case kind >= reflect.Float32 && kind <= reflect.Float64:
-		return reflect.Float32
-	default:
-		return kind
-	}
-}
-
-func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
-	for i := 0; i < typ.NumField(); i++ {
-		f := typ.Field(i)
-		if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
-			return true
-		}
-		if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
-			return true
-		}
-	}
-	return false
-}
-
-func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
-	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
-		return v
-	}
-	deref := v.Elem()
-	derefT := deref.Type()
-	if isStructTypeConvertibleToMap(derefT, true, tagName) {
-		return deref
-	}
-	return v
-}
diff --git a/notifier/vendor/github.com/prometheus/procfs/.golangci.yml b/notifier/vendor/github.com/prometheus/procfs/.golangci.yml
index 126df9e6..3c3bf910 100644
--- a/notifier/vendor/github.com/prometheus/procfs/.golangci.yml
+++ b/notifier/vendor/github.com/prometheus/procfs/.golangci.yml
@@ -1,22 +1,45 @@
----
+version: "2"
 linters:
   enable:
-  - errcheck
-  - godot
-  - gosimple
-  - govet
-  - ineffassign
-  - misspell
-  - revive
-  - staticcheck
-  - testifylint
-  - unused
-
-linter-settings:
-  godot:
-    capital: true
-    exclude:
-    # Ignore "See: URL"
-    - 'See:'
-  misspell:
-    locale: US
+    - forbidigo
+    - godot
+    - misspell
+    - revive
+    - testifylint
+  settings:
+    forbidigo:
+      forbid:
+        - pattern: ^fmt\.Print.*$
+          msg: Do not commit print statements.
+    godot:
+      exclude:
+        # Ignore "See: URL".
+        - 'See:'
+      capital: true
+    misspell:
+      locale: US
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
+formatters:
+  enable:
+    - gofmt
+    - goimports
+  settings:
+    goimports:
+      local-prefixes:
+        - github.com/prometheus/procfs
+  exclusions:
+    generated: lax
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/notifier/vendor/github.com/prometheus/procfs/Makefile.common b/notifier/vendor/github.com/prometheus/procfs/Makefile.common
index 16172923..4de21512 100644
--- a/notifier/vendor/github.com/prometheus/procfs/Makefile.common
+++ b/notifier/vendor/github.com/prometheus/procfs/Makefile.common
@@ -61,7 +61,8 @@ PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_
 SKIP_GOLANGCI_LINT :=
 GOLANGCI_LINT :=
 GOLANGCI_LINT_OPTS ?=
-GOLANGCI_LINT_VERSION ?= v1.59.0
+GOLANGCI_LINT_VERSION ?= v2.1.5
+GOLANGCI_FMT_OPTS ?=
 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
 # windows isn't included here because of the path separator being different.
 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
@@ -156,9 +157,13 @@ $(GOTEST_DIR):
 	@mkdir -p $@
 
 .PHONY: common-format
-common-format:
+common-format: $(GOLANGCI_LINT)
 	@echo ">> formatting code"
 	$(GO) fmt $(pkgs)
+ifdef GOLANGCI_LINT
+	@echo ">> formatting code with golangci-lint"
+	$(GOLANGCI_LINT) fmt $(GOLANGCI_FMT_OPTS)
+endif
 
 .PHONY: common-vet
 common-vet:
@@ -248,8 +253,8 @@ $(PROMU):
 	cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu
 	rm -r $(PROMU_TMP)
 
-.PHONY: proto
-proto:
+.PHONY: common-proto
+common-proto:
 	@echo ">> generating code from proto files"
 	@./scripts/genproto.sh
 
@@ -275,3 +280,9 @@ $(1)_precheck:
 		exit 1; \
 	fi
 endef
+
+govulncheck: install-govulncheck
+	govulncheck ./...
+
+install-govulncheck:
+	command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest
diff --git a/notifier/vendor/github.com/prometheus/procfs/README.md b/notifier/vendor/github.com/prometheus/procfs/README.md
index 1224816c..0718239c 100644
--- a/notifier/vendor/github.com/prometheus/procfs/README.md
+++ b/notifier/vendor/github.com/prometheus/procfs/README.md
@@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`.
 The procfs library includes a set of test fixtures which include many example files from
 the `/proc` and `/sys` filesystems.  These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
 which is extracted automatically during testing.  To add/update the test fixtures, first
-ensure the `fixtures` directory is up to date by removing the existing directory and then
-extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
+ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then
+extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`.
 
 ```bash
 rm -rf testdata/fixtures
 make test
 ```
 
-Next, make the required changes to the extracted files in the `fixtures` directory.  When
+Next, make the required changes to the extracted files in the `testdata/fixtures` directory.  When
 the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file
 based on the updated `fixtures` directory.  And finally, verify the changes using
 `git diff testdata/fixtures.ttar`.
diff --git a/notifier/vendor/github.com/prometheus/procfs/arp.go b/notifier/vendor/github.com/prometheus/procfs/arp.go
index cdcc8a7c..2e533441 100644
--- a/notifier/vendor/github.com/prometheus/procfs/arp.go
+++ b/notifier/vendor/github.com/prometheus/procfs/arp.go
@@ -23,9 +23,9 @@ import (
 
 // Learned from include/uapi/linux/if_arp.h.
 const (
-	// completed entry (ha valid).
+	// Completed entry (ha valid).
 	ATFComplete = 0x02
-	// permanent entry.
+	// Permanent entry.
 	ATFPermanent = 0x04
 	// Publish entry.
 	ATFPublish = 0x08
diff --git a/notifier/vendor/github.com/prometheus/procfs/fs.go b/notifier/vendor/github.com/prometheus/procfs/fs.go
index 4980c875..9bdaccc7 100644
--- a/notifier/vendor/github.com/prometheus/procfs/fs.go
+++ b/notifier/vendor/github.com/prometheus/procfs/fs.go
@@ -24,8 +24,14 @@ type FS struct {
 	isReal bool
 }
 
-// DefaultMountPoint is the common mount point of the proc filesystem.
-const DefaultMountPoint = fs.DefaultProcMountPoint
+const (
+	// DefaultMountPoint is the common mount point of the proc filesystem.
+	DefaultMountPoint = fs.DefaultProcMountPoint
+
+	// SectorSize represents the size of a sector in bytes.
+	// It is specific to Linux block I/O operations.
+	SectorSize = 512
+)
 
 // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
 // It will error if the mount point directory can't be read or is a file.
diff --git a/notifier/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/notifier/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
index 134767d6..1b5bdbdf 100644
--- a/notifier/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
+++ b/notifier/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
@@ -17,7 +17,7 @@
 package procfs
 
 // isRealProc returns true on architectures that don't have a Type argument
-// in their Statfs_t struct
-func isRealProc(mountPoint string) (bool, error) {
+// in their Statfs_t struct.
+func isRealProc(_ string) (bool, error) {
 	return true, nil
 }
diff --git a/notifier/vendor/github.com/prometheus/procfs/fscache.go b/notifier/vendor/github.com/prometheus/procfs/fscache.go
index cf2e3eaa..7db86330 100644
--- a/notifier/vendor/github.com/prometheus/procfs/fscache.go
+++ b/notifier/vendor/github.com/prometheus/procfs/fscache.go
@@ -162,7 +162,7 @@ type Fscacheinfo struct {
 	ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
 	// Number of release reqs ignored due to in-progress store
 	ReleaseRequestsIgnoredDueToInProgressStore uint64
-	// Number of page stores cancelled due to release req
+	// Number of page stores canceled due to release req
 	PageStoresCancelledByReleaseRequests uint64
 	VmscanWaiting                        uint64
 	// Number of times async ops added to pending queues
@@ -171,11 +171,11 @@ type Fscacheinfo struct {
 	OpsRunning uint64
 	// Number of times async ops queued for processing
 	OpsEnqueued uint64
-	// Number of async ops cancelled
+	// Number of async ops canceled
 	OpsCancelled uint64
 	// Number of async ops rejected due to object lookup/create failure
 	OpsRejected uint64
-	// Number of async ops initialised
+	// Number of async ops initialized
 	OpsInitialised uint64
 	// Number of async ops queued for deferred release
 	OpsDeferred uint64
diff --git a/notifier/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/notifier/vendor/github.com/prometheus/procfs/internal/fs/fs.go
index 3c18c761..3a43e839 100644
--- a/notifier/vendor/github.com/prometheus/procfs/internal/fs/fs.go
+++ b/notifier/vendor/github.com/prometheus/procfs/internal/fs/fs.go
@@ -28,6 +28,9 @@ const (
 
 	// DefaultConfigfsMountPoint is the common mount point of the configfs.
 	DefaultConfigfsMountPoint = "/sys/kernel/config"
+
+	// DefaultSelinuxMountPoint is the common mount point of the selinuxfs.
+	DefaultSelinuxMountPoint = "/sys/fs/selinux"
 )
 
 // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
diff --git a/notifier/vendor/github.com/prometheus/procfs/internal/util/parse.go b/notifier/vendor/github.com/prometheus/procfs/internal/util/parse.go
index 14272dc7..5a7d2df0 100644
--- a/notifier/vendor/github.com/prometheus/procfs/internal/util/parse.go
+++ b/notifier/vendor/github.com/prometheus/procfs/internal/util/parse.go
@@ -14,6 +14,7 @@
 package util
 
 import (
+	"errors"
 	"os"
 	"strconv"
 	"strings"
@@ -110,3 +111,16 @@ func ParseBool(b string) *bool {
 	}
 	return &truth
 }
+
+// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX.
+func ReadHexFromFile(path string) (uint64, error) {
+	data, err := os.ReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	hexString := strings.TrimSpace(string(data))
+	if !strings.HasPrefix(hexString, "0x") {
+		return 0, errors.New("invalid format: hex string does not start with '0x'")
+	}
+	return strconv.ParseUint(hexString[2:], 16, 64)
+}
diff --git a/notifier/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/notifier/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
index 1ab875ce..d5404a6d 100644
--- a/notifier/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
+++ b/notifier/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
@@ -20,6 +20,8 @@ package util
 import (
 	"bytes"
 	"os"
+	"strconv"
+	"strings"
 	"syscall"
 )
 
@@ -48,3 +50,21 @@ func SysReadFile(file string) (string, error) {
 
 	return string(bytes.TrimSpace(b[:n])), nil
 }
+
+// SysReadUintFromFile reads a file using SysReadFile and attempts to parse a uint64 from it.
+func SysReadUintFromFile(path string) (uint64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
+}
+
+// SysReadIntFromFile reads a file using SysReadFile and attempts to parse a int64 from it.
+func SysReadIntFromFile(path string) (int64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
+}
diff --git a/notifier/vendor/github.com/prometheus/procfs/mdstat.go b/notifier/vendor/github.com/prometheus/procfs/mdstat.go
index 67a9d2b4..1fd4381b 100644
--- a/notifier/vendor/github.com/prometheus/procfs/mdstat.go
+++ b/notifier/vendor/github.com/prometheus/procfs/mdstat.go
@@ -123,13 +123,16 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
 		finish := float64(0)
 		pct := float64(0)
 		recovering := strings.Contains(lines[syncLineIdx], "recovery")
+		reshaping := strings.Contains(lines[syncLineIdx], "reshape")
 		resyncing := strings.Contains(lines[syncLineIdx], "resync")
 		checking := strings.Contains(lines[syncLineIdx], "check")
 
 		// Append recovery and resyncing state info.
-		if recovering || resyncing || checking {
+		if recovering || resyncing || checking || reshaping {
 			if recovering {
 				state = "recovering"
+			} else if reshaping {
+				state = "reshaping"
 			} else if checking {
 				state = "checking"
 			} else {
diff --git a/notifier/vendor/github.com/prometheus/procfs/meminfo.go b/notifier/vendor/github.com/prometheus/procfs/meminfo.go
index 4b2c4050..937e1f96 100644
--- a/notifier/vendor/github.com/prometheus/procfs/meminfo.go
+++ b/notifier/vendor/github.com/prometheus/procfs/meminfo.go
@@ -66,6 +66,10 @@ type Meminfo struct {
 	// Memory which has been evicted from RAM, and is temporarily
 	// on the disk
 	SwapFree *uint64
+	// Memory consumed by the zswap backend (compressed size)
+	Zswap *uint64
+	// Amount of anonymous memory stored in zswap (original size)
+	Zswapped *uint64
 	// Memory which is waiting to get written back to the disk
 	Dirty *uint64
 	// Memory which is actively being written back to the disk
@@ -85,6 +89,8 @@ type Meminfo struct {
 	// amount of memory dedicated to the lowest level of page
 	// tables.
 	PageTables *uint64
+	// secondary page tables.
+	SecPageTables *uint64
 	// NFS pages sent to the server, but not yet committed to
 	// stable storage
 	NFSUnstable *uint64
@@ -129,15 +135,18 @@ type Meminfo struct {
 	Percpu            *uint64
 	HardwareCorrupted *uint64
 	AnonHugePages     *uint64
+	FileHugePages     *uint64
 	ShmemHugePages    *uint64
 	ShmemPmdMapped    *uint64
 	CmaTotal          *uint64
 	CmaFree           *uint64
+	Unaccepted        *uint64
 	HugePagesTotal    *uint64
 	HugePagesFree     *uint64
 	HugePagesRsvd     *uint64
 	HugePagesSurp     *uint64
 	Hugepagesize      *uint64
+	Hugetlb           *uint64
 	DirectMap4k       *uint64
 	DirectMap2M       *uint64
 	DirectMap1G       *uint64
@@ -161,6 +170,8 @@ type Meminfo struct {
 	MlockedBytes           *uint64
 	SwapTotalBytes         *uint64
 	SwapFreeBytes          *uint64
+	ZswapBytes             *uint64
+	ZswappedBytes          *uint64
 	DirtyBytes             *uint64
 	WritebackBytes         *uint64
 	AnonPagesBytes         *uint64
@@ -171,6 +182,7 @@ type Meminfo struct {
 	SUnreclaimBytes        *uint64
 	KernelStackBytes       *uint64
 	PageTablesBytes        *uint64
+	SecPageTablesBytes     *uint64
 	NFSUnstableBytes       *uint64
 	BounceBytes            *uint64
 	WritebackTmpBytes      *uint64
@@ -182,11 +194,14 @@ type Meminfo struct {
 	PercpuBytes            *uint64
 	HardwareCorruptedBytes *uint64
 	AnonHugePagesBytes     *uint64
+	FileHugePagesBytes     *uint64
 	ShmemHugePagesBytes    *uint64
 	ShmemPmdMappedBytes    *uint64
 	CmaTotalBytes          *uint64
 	CmaFreeBytes           *uint64
+	UnacceptedBytes        *uint64
 	HugepagesizeBytes      *uint64
+	HugetlbBytes           *uint64
 	DirectMap4kBytes       *uint64
 	DirectMap2MBytes       *uint64
 	DirectMap1GBytes       *uint64
@@ -287,6 +302,12 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "SwapFree:":
 			m.SwapFree = &val
 			m.SwapFreeBytes = &valBytes
+		case "Zswap:":
+			m.Zswap = &val
+			m.ZswapBytes = &valBytes
+		case "Zswapped:":
+			m.Zswapped = &val
+			m.ZswapBytes = &valBytes
 		case "Dirty:":
 			m.Dirty = &val
 			m.DirtyBytes = &valBytes
@@ -317,6 +338,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "PageTables:":
 			m.PageTables = &val
 			m.PageTablesBytes = &valBytes
+		case "SecPageTables:":
+			m.SecPageTables = &val
+			m.SecPageTablesBytes = &valBytes
 		case "NFS_Unstable:":
 			m.NFSUnstable = &val
 			m.NFSUnstableBytes = &valBytes
@@ -350,6 +374,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "AnonHugePages:":
 			m.AnonHugePages = &val
 			m.AnonHugePagesBytes = &valBytes
+		case "FileHugePages:":
+			m.FileHugePages = &val
+			m.FileHugePagesBytes = &valBytes
 		case "ShmemHugePages:":
 			m.ShmemHugePages = &val
 			m.ShmemHugePagesBytes = &valBytes
@@ -362,6 +389,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "CmaFree:":
 			m.CmaFree = &val
 			m.CmaFreeBytes = &valBytes
+		case "Unaccepted:":
+			m.Unaccepted = &val
+			m.UnacceptedBytes = &valBytes
 		case "HugePages_Total:":
 			m.HugePagesTotal = &val
 		case "HugePages_Free:":
@@ -373,6 +403,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "Hugepagesize:":
 			m.Hugepagesize = &val
 			m.HugepagesizeBytes = &valBytes
+		case "Hugetlb:":
+			m.Hugetlb = &val
+			m.HugetlbBytes = &valBytes
 		case "DirectMap4k:":
 			m.DirectMap4k = &val
 			m.DirectMap4kBytes = &valBytes
diff --git a/notifier/vendor/github.com/prometheus/procfs/mountstats.go b/notifier/vendor/github.com/prometheus/procfs/mountstats.go
index 75a3b6c8..50caa732 100644
--- a/notifier/vendor/github.com/prometheus/procfs/mountstats.go
+++ b/notifier/vendor/github.com/prometheus/procfs/mountstats.go
@@ -45,11 +45,11 @@ const (
 	fieldTransport11TCPLen = 13
 	fieldTransport11UDPLen = 10
 
-	// kernel version >= 4.14 MaxLen
+	// Kernel version >= 4.14 MaxLen
 	// See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
 	fieldTransport11RDMAMaxLen = 28
 
-	// kernel version <= 4.2 MinLen
+	// Kernel version <= 4.2 MinLen
 	// See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
 	fieldTransport11RDMAMinLen = 20
 )
@@ -601,11 +601,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	switch statVersion {
 	case statVersion10:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport10TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport10UDPLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if len(ss) != expectedLength {
@@ -613,13 +614,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 		}
 	case statVersion11:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport11TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport11UDPLen
-		} else if protocol == "rdma" {
+		case "rdma":
 			expectedLength = fieldTransport11RDMAMinLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) ||
@@ -655,11 +657,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	// For the udp RPC transport there is no connection count, connect idle time,
 	// or idle time (fields #3, #4, and #5); all other fields are the same. So
 	// we set them to 0 here.
-	if protocol == "udp" {
+	switch protocol {
+	case "udp":
 		ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
-	} else if protocol == "tcp" {
+	case "tcp":
 		ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...)
-	} else if protocol == "rdma" {
+	case "rdma":
 		ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...)
 	}
 
diff --git a/notifier/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/notifier/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
new file mode 100644
index 00000000..f50b38e3
--- /dev/null
+++ b/notifier/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
@@ -0,0 +1,96 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc//net/dev_snmp6/.
+// The outer map's keys are interface names and the inner map's keys are stat names.
+//
+// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type.
+type NetDevSNMP6 map[string]map[string]uint64
+
+// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/
+// directory.
+func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6"))
+}
+
+// Returns kernel/system statistics read from interface files within the /proc//net/dev_snmp6/
+// directory.
+func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(p.path("net/dev_snmp6"))
+}
+
+// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory.
+func newNetDevSNMP6(dir string) (NetDevSNMP6, error) {
+	netDevSNMP6 := make(NetDevSNMP6)
+
+	// The net/dev_snmp6 folders contain one file per interface
+	ifaceFiles, err := os.ReadDir(dir)
+	if err != nil {
+		// On systems with IPv6 disabled, this directory won't exist.
+		// Do nothing.
+		if errors.Is(err, os.ErrNotExist) {
+			return netDevSNMP6, err
+		}
+		return netDevSNMP6, err
+	}
+
+	for _, iFaceFile := range ifaceFiles {
+		f, err := os.Open(dir + "/" + iFaceFile.Name())
+		if err != nil {
+			return netDevSNMP6, err
+		}
+		defer f.Close()
+
+		netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f)
+		if err != nil {
+			return netDevSNMP6, err
+		}
+	}
+
+	return netDevSNMP6, nil
+}
+
+func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) {
+	m := make(map[string]uint64)
+
+	scanner := bufio.NewScanner(r)
+	for scanner.Scan() {
+		stat := strings.Fields(scanner.Text())
+		if len(stat) < 2 {
+			continue
+		}
+		key, val := stat[0], stat[1]
+
+		// Expect stat name to contain "6" or be "ifIndex"
+		if strings.Contains(key, "6") || key == "ifIndex" {
+			v, err := strconv.ParseUint(val, 10, 64)
+			if err != nil {
+				return m, err
+			}
+
+			m[key] = v
+		}
+	}
+	return m, scanner.Err()
+}
diff --git a/notifier/vendor/github.com/prometheus/procfs/net_ip_socket.go b/notifier/vendor/github.com/prometheus/procfs/net_ip_socket.go
index b70f1fc7..19e3378f 100644
--- a/notifier/vendor/github.com/prometheus/procfs/net_ip_socket.go
+++ b/notifier/vendor/github.com/prometheus/procfs/net_ip_socket.go
@@ -25,7 +25,7 @@ import (
 )
 
 const (
-	// readLimit is used by io.LimitReader while reading the content of the
+	// Maximum size limit used by io.LimitReader while reading the content of the
 	// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
 	// as each line represents a single used socket.
 	// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
@@ -50,12 +50,12 @@ type (
 		// UsedSockets shows the total number of parsed lines representing the
 		// number of used sockets.
 		UsedSockets uint64
-		// Drops shows the total number of dropped packets of all UPD sockets.
+		// Drops shows the total number of dropped packets of all UDP sockets.
 		Drops *uint64
 	}
 
-	// netIPSocketLine represents the fields parsed from a single line
-	// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
+	// A single line parser for fields from /proc/net/{t,u}dp{,6}.
+	// Fields which are not used by IPSocket are skipped.
 	// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
 	// For the proc file format details, see https://linux.die.net/man/5/proc.
 	netIPSocketLine struct {
diff --git a/notifier/vendor/github.com/prometheus/procfs/net_protocols.go b/notifier/vendor/github.com/prometheus/procfs/net_protocols.go
index b6c77b70..8d4b1ac0 100644
--- a/notifier/vendor/github.com/prometheus/procfs/net_protocols.go
+++ b/notifier/vendor/github.com/prometheus/procfs/net_protocols.go
@@ -115,22 +115,24 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro
 	if err != nil {
 		return nil, err
 	}
-	if fields[4] == enabled {
+	switch fields[4] {
+	case enabled:
 		line.Pressure = 1
-	} else if fields[4] == disabled {
+	case disabled:
 		line.Pressure = 0
-	} else {
+	default:
 		line.Pressure = -1
 	}
 	line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	if fields[6] == enabled {
+	switch fields[6] {
+	case enabled:
 		line.Slab = true
-	} else if fields[6] == disabled {
+	case disabled:
 		line.Slab = false
-	} else {
+	default:
 		return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name)
 	}
 	line.ModuleName = fields[7]
@@ -168,11 +170,12 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro
 	}
 
 	for i := 0; i < len(capabilities); i++ {
-		if capabilities[i] == "y" {
+		switch capabilities[i] {
+		case "y":
 			*capabilityFields[i] = true
-		} else if capabilities[i] == "n" {
+		case "n":
 			*capabilityFields[i] = false
-		} else {
+		default:
 			return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i)
 		}
 	}
diff --git a/notifier/vendor/github.com/prometheus/procfs/net_tcp.go b/notifier/vendor/github.com/prometheus/procfs/net_tcp.go
index 52776295..0396d720 100644
--- a/notifier/vendor/github.com/prometheus/procfs/net_tcp.go
+++ b/notifier/vendor/github.com/prometheus/procfs/net_tcp.go
@@ -25,24 +25,28 @@ type (
 
 // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCP() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp6"))
 }
 
 // NetTCPSummary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6Summary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp6"))
 }
diff --git a/notifier/vendor/github.com/prometheus/procfs/net_unix.go b/notifier/vendor/github.com/prometheus/procfs/net_unix.go
index d868cebd..d7e0cacb 100644
--- a/notifier/vendor/github.com/prometheus/procfs/net_unix.go
+++ b/notifier/vendor/github.com/prometheus/procfs/net_unix.go
@@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
 	return &nu, nil
 }
 
-func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) {
+func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) {
 	fields := strings.Fields(line)
 
 	l := len(fields)
-	if l < min {
-		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l)
+	if l < minFields {
+		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l)
 	}
 
 	// Field offsets are as follows:
@@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine,
 	}
 
 	// Path field is optional.
-	if l > min {
+	if l > minFields {
 		// Path occurs at either index 6 or 7 depending on whether inode is
 		// already present.
 		pathIdx := 7
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc.go b/notifier/vendor/github.com/prometheus/procfs/proc.go
index 14279636..368187fa 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc.go
@@ -37,9 +37,9 @@ type Proc struct {
 type Procs []Proc
 
 var (
-	ErrFileParse  = errors.New("Error Parsing File")
-	ErrFileRead   = errors.New("Error Reading File")
-	ErrMountPoint = errors.New("Error Accessing Mount point")
+	ErrFileParse  = errors.New("error parsing file")
+	ErrFileRead   = errors.New("error reading file")
+	ErrMountPoint = errors.New("error accessing mount point")
 )
 
 func (p Procs) Len() int           { return len(p) }
@@ -79,7 +79,7 @@ func (fs FS) Self() (Proc, error) {
 	if err != nil {
 		return Proc{}, err
 	}
-	pid, err := strconv.Atoi(strings.Replace(p, string(fs.proc), "", -1))
+	pid, err := strconv.Atoi(strings.ReplaceAll(p, string(fs.proc), ""))
 	if err != nil {
 		return Proc{}, err
 	}
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_cgroup.go b/notifier/vendor/github.com/prometheus/procfs/proc_cgroup.go
index daeed7f5..4a64347c 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_cgroup.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_cgroup.go
@@ -24,7 +24,7 @@ import (
 )
 
 // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a
-// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource
+// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource
 // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies
 // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in
 // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_io.go b/notifier/vendor/github.com/prometheus/procfs/proc_io.go
index 776f3497..d15b66dd 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_io.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_io.go
@@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) {
 
 	ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
 		"read_bytes: %d\nwrite_bytes: %d\n" +
-		"cancelled_write_bytes: %d\n"
+		"cancelled_write_bytes: %d\n" //nolint:misspell
 
 	_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
 		&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_netstat.go b/notifier/vendor/github.com/prometheus/procfs/proc_netstat.go
index 8e3ff4d7..4248c171 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_netstat.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_netstat.go
@@ -209,232 +209,232 @@ func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
 			case "TcpExt":
 				switch key {
 				case "SyncookiesSent":
-					procNetstat.TcpExt.SyncookiesSent = &value
+					procNetstat.SyncookiesSent = &value
 				case "SyncookiesRecv":
-					procNetstat.TcpExt.SyncookiesRecv = &value
+					procNetstat.SyncookiesRecv = &value
 				case "SyncookiesFailed":
-					procNetstat.TcpExt.SyncookiesFailed = &value
+					procNetstat.SyncookiesFailed = &value
 				case "EmbryonicRsts":
-					procNetstat.TcpExt.EmbryonicRsts = &value
+					procNetstat.EmbryonicRsts = &value
 				case "PruneCalled":
-					procNetstat.TcpExt.PruneCalled = &value
+					procNetstat.PruneCalled = &value
 				case "RcvPruned":
-					procNetstat.TcpExt.RcvPruned = &value
+					procNetstat.RcvPruned = &value
 				case "OfoPruned":
-					procNetstat.TcpExt.OfoPruned = &value
+					procNetstat.OfoPruned = &value
 				case "OutOfWindowIcmps":
-					procNetstat.TcpExt.OutOfWindowIcmps = &value
+					procNetstat.OutOfWindowIcmps = &value
 				case "LockDroppedIcmps":
-					procNetstat.TcpExt.LockDroppedIcmps = &value
+					procNetstat.LockDroppedIcmps = &value
 				case "ArpFilter":
-					procNetstat.TcpExt.ArpFilter = &value
+					procNetstat.ArpFilter = &value
 				case "TW":
-					procNetstat.TcpExt.TW = &value
+					procNetstat.TW = &value
 				case "TWRecycled":
-					procNetstat.TcpExt.TWRecycled = &value
+					procNetstat.TWRecycled = &value
 				case "TWKilled":
-					procNetstat.TcpExt.TWKilled = &value
+					procNetstat.TWKilled = &value
 				case "PAWSActive":
-					procNetstat.TcpExt.PAWSActive = &value
+					procNetstat.PAWSActive = &value
 				case "PAWSEstab":
-					procNetstat.TcpExt.PAWSEstab = &value
+					procNetstat.PAWSEstab = &value
 				case "DelayedACKs":
-					procNetstat.TcpExt.DelayedACKs = &value
+					procNetstat.DelayedACKs = &value
 				case "DelayedACKLocked":
-					procNetstat.TcpExt.DelayedACKLocked = &value
+					procNetstat.DelayedACKLocked = &value
 				case "DelayedACKLost":
-					procNetstat.TcpExt.DelayedACKLost = &value
+					procNetstat.DelayedACKLost = &value
 				case "ListenOverflows":
-					procNetstat.TcpExt.ListenOverflows = &value
+					procNetstat.ListenOverflows = &value
 				case "ListenDrops":
-					procNetstat.TcpExt.ListenDrops = &value
+					procNetstat.ListenDrops = &value
 				case "TCPHPHits":
-					procNetstat.TcpExt.TCPHPHits = &value
+					procNetstat.TCPHPHits = &value
 				case "TCPPureAcks":
-					procNetstat.TcpExt.TCPPureAcks = &value
+					procNetstat.TCPPureAcks = &value
 				case "TCPHPAcks":
-					procNetstat.TcpExt.TCPHPAcks = &value
+					procNetstat.TCPHPAcks = &value
 				case "TCPRenoRecovery":
-					procNetstat.TcpExt.TCPRenoRecovery = &value
+					procNetstat.TCPRenoRecovery = &value
 				case "TCPSackRecovery":
-					procNetstat.TcpExt.TCPSackRecovery = &value
+					procNetstat.TCPSackRecovery = &value
 				case "TCPSACKReneging":
-					procNetstat.TcpExt.TCPSACKReneging = &value
+					procNetstat.TCPSACKReneging = &value
 				case "TCPSACKReorder":
-					procNetstat.TcpExt.TCPSACKReorder = &value
+					procNetstat.TCPSACKReorder = &value
 				case "TCPRenoReorder":
-					procNetstat.TcpExt.TCPRenoReorder = &value
+					procNetstat.TCPRenoReorder = &value
 				case "TCPTSReorder":
-					procNetstat.TcpExt.TCPTSReorder = &value
+					procNetstat.TCPTSReorder = &value
 				case "TCPFullUndo":
-					procNetstat.TcpExt.TCPFullUndo = &value
+					procNetstat.TCPFullUndo = &value
 				case "TCPPartialUndo":
-					procNetstat.TcpExt.TCPPartialUndo = &value
+					procNetstat.TCPPartialUndo = &value
 				case "TCPDSACKUndo":
-					procNetstat.TcpExt.TCPDSACKUndo = &value
+					procNetstat.TCPDSACKUndo = &value
 				case "TCPLossUndo":
-					procNetstat.TcpExt.TCPLossUndo = &value
+					procNetstat.TCPLossUndo = &value
 				case "TCPLostRetransmit":
-					procNetstat.TcpExt.TCPLostRetransmit = &value
+					procNetstat.TCPLostRetransmit = &value
 				case "TCPRenoFailures":
-					procNetstat.TcpExt.TCPRenoFailures = &value
+					procNetstat.TCPRenoFailures = &value
 				case "TCPSackFailures":
-					procNetstat.TcpExt.TCPSackFailures = &value
+					procNetstat.TCPSackFailures = &value
 				case "TCPLossFailures":
-					procNetstat.TcpExt.TCPLossFailures = &value
+					procNetstat.TCPLossFailures = &value
 				case "TCPFastRetrans":
-					procNetstat.TcpExt.TCPFastRetrans = &value
+					procNetstat.TCPFastRetrans = &value
 				case "TCPSlowStartRetrans":
-					procNetstat.TcpExt.TCPSlowStartRetrans = &value
+					procNetstat.TCPSlowStartRetrans = &value
 				case "TCPTimeouts":
-					procNetstat.TcpExt.TCPTimeouts = &value
+					procNetstat.TCPTimeouts = &value
 				case "TCPLossProbes":
-					procNetstat.TcpExt.TCPLossProbes = &value
+					procNetstat.TCPLossProbes = &value
 				case "TCPLossProbeRecovery":
-					procNetstat.TcpExt.TCPLossProbeRecovery = &value
+					procNetstat.TCPLossProbeRecovery = &value
 				case "TCPRenoRecoveryFail":
-					procNetstat.TcpExt.TCPRenoRecoveryFail = &value
+					procNetstat.TCPRenoRecoveryFail = &value
 				case "TCPSackRecoveryFail":
-					procNetstat.TcpExt.TCPSackRecoveryFail = &value
+					procNetstat.TCPSackRecoveryFail = &value
 				case "TCPRcvCollapsed":
-					procNetstat.TcpExt.TCPRcvCollapsed = &value
+					procNetstat.TCPRcvCollapsed = &value
 				case "TCPDSACKOldSent":
-					procNetstat.TcpExt.TCPDSACKOldSent = &value
+					procNetstat.TCPDSACKOldSent = &value
 				case "TCPDSACKOfoSent":
-					procNetstat.TcpExt.TCPDSACKOfoSent = &value
+					procNetstat.TCPDSACKOfoSent = &value
 				case "TCPDSACKRecv":
-					procNetstat.TcpExt.TCPDSACKRecv = &value
+					procNetstat.TCPDSACKRecv = &value
 				case "TCPDSACKOfoRecv":
-					procNetstat.TcpExt.TCPDSACKOfoRecv = &value
+					procNetstat.TCPDSACKOfoRecv = &value
 				case "TCPAbortOnData":
-					procNetstat.TcpExt.TCPAbortOnData = &value
+					procNetstat.TCPAbortOnData = &value
 				case "TCPAbortOnClose":
-					procNetstat.TcpExt.TCPAbortOnClose = &value
+					procNetstat.TCPAbortOnClose = &value
 				case "TCPDeferAcceptDrop":
-					procNetstat.TcpExt.TCPDeferAcceptDrop = &value
+					procNetstat.TCPDeferAcceptDrop = &value
 				case "IPReversePathFilter":
-					procNetstat.TcpExt.IPReversePathFilter = &value
+					procNetstat.IPReversePathFilter = &value
 				case "TCPTimeWaitOverflow":
-					procNetstat.TcpExt.TCPTimeWaitOverflow = &value
+					procNetstat.TCPTimeWaitOverflow = &value
 				case "TCPReqQFullDoCookies":
-					procNetstat.TcpExt.TCPReqQFullDoCookies = &value
+					procNetstat.TCPReqQFullDoCookies = &value
 				case "TCPReqQFullDrop":
-					procNetstat.TcpExt.TCPReqQFullDrop = &value
+					procNetstat.TCPReqQFullDrop = &value
 				case "TCPRetransFail":
-					procNetstat.TcpExt.TCPRetransFail = &value
+					procNetstat.TCPRetransFail = &value
 				case "TCPRcvCoalesce":
-					procNetstat.TcpExt.TCPRcvCoalesce = &value
+					procNetstat.TCPRcvCoalesce = &value
 				case "TCPRcvQDrop":
-					procNetstat.TcpExt.TCPRcvQDrop = &value
+					procNetstat.TCPRcvQDrop = &value
 				case "TCPOFOQueue":
-					procNetstat.TcpExt.TCPOFOQueue = &value
+					procNetstat.TCPOFOQueue = &value
 				case "TCPOFODrop":
-					procNetstat.TcpExt.TCPOFODrop = &value
+					procNetstat.TCPOFODrop = &value
 				case "TCPOFOMerge":
-					procNetstat.TcpExt.TCPOFOMerge = &value
+					procNetstat.TCPOFOMerge = &value
 				case "TCPChallengeACK":
-					procNetstat.TcpExt.TCPChallengeACK = &value
+					procNetstat.TCPChallengeACK = &value
 				case "TCPSYNChallenge":
-					procNetstat.TcpExt.TCPSYNChallenge = &value
+					procNetstat.TCPSYNChallenge = &value
 				case "TCPFastOpenActive":
-					procNetstat.TcpExt.TCPFastOpenActive = &value
+					procNetstat.TCPFastOpenActive = &value
 				case "TCPFastOpenActiveFail":
-					procNetstat.TcpExt.TCPFastOpenActiveFail = &value
+					procNetstat.TCPFastOpenActiveFail = &value
 				case "TCPFastOpenPassive":
-					procNetstat.TcpExt.TCPFastOpenPassive = &value
+					procNetstat.TCPFastOpenPassive = &value
 				case "TCPFastOpenPassiveFail":
-					procNetstat.TcpExt.TCPFastOpenPassiveFail = &value
+					procNetstat.TCPFastOpenPassiveFail = &value
 				case "TCPFastOpenListenOverflow":
-					procNetstat.TcpExt.TCPFastOpenListenOverflow = &value
+					procNetstat.TCPFastOpenListenOverflow = &value
 				case "TCPFastOpenCookieReqd":
-					procNetstat.TcpExt.TCPFastOpenCookieReqd = &value
+					procNetstat.TCPFastOpenCookieReqd = &value
 				case "TCPFastOpenBlackhole":
-					procNetstat.TcpExt.TCPFastOpenBlackhole = &value
+					procNetstat.TCPFastOpenBlackhole = &value
 				case "TCPSpuriousRtxHostQueues":
-					procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value
+					procNetstat.TCPSpuriousRtxHostQueues = &value
 				case "BusyPollRxPackets":
-					procNetstat.TcpExt.BusyPollRxPackets = &value
+					procNetstat.BusyPollRxPackets = &value
 				case "TCPAutoCorking":
-					procNetstat.TcpExt.TCPAutoCorking = &value
+					procNetstat.TCPAutoCorking = &value
 				case "TCPFromZeroWindowAdv":
-					procNetstat.TcpExt.TCPFromZeroWindowAdv = &value
+					procNetstat.TCPFromZeroWindowAdv = &value
 				case "TCPToZeroWindowAdv":
-					procNetstat.TcpExt.TCPToZeroWindowAdv = &value
+					procNetstat.TCPToZeroWindowAdv = &value
 				case "TCPWantZeroWindowAdv":
-					procNetstat.TcpExt.TCPWantZeroWindowAdv = &value
+					procNetstat.TCPWantZeroWindowAdv = &value
 				case "TCPSynRetrans":
-					procNetstat.TcpExt.TCPSynRetrans = &value
+					procNetstat.TCPSynRetrans = &value
 				case "TCPOrigDataSent":
-					procNetstat.TcpExt.TCPOrigDataSent = &value
+					procNetstat.TCPOrigDataSent = &value
 				case "TCPHystartTrainDetect":
-					procNetstat.TcpExt.TCPHystartTrainDetect = &value
+					procNetstat.TCPHystartTrainDetect = &value
 				case "TCPHystartTrainCwnd":
-					procNetstat.TcpExt.TCPHystartTrainCwnd = &value
+					procNetstat.TCPHystartTrainCwnd = &value
 				case "TCPHystartDelayDetect":
-					procNetstat.TcpExt.TCPHystartDelayDetect = &value
+					procNetstat.TCPHystartDelayDetect = &value
 				case "TCPHystartDelayCwnd":
-					procNetstat.TcpExt.TCPHystartDelayCwnd = &value
+					procNetstat.TCPHystartDelayCwnd = &value
 				case "TCPACKSkippedSynRecv":
-					procNetstat.TcpExt.TCPACKSkippedSynRecv = &value
+					procNetstat.TCPACKSkippedSynRecv = &value
 				case "TCPACKSkippedPAWS":
-					procNetstat.TcpExt.TCPACKSkippedPAWS = &value
+					procNetstat.TCPACKSkippedPAWS = &value
 				case "TCPACKSkippedSeq":
-					procNetstat.TcpExt.TCPACKSkippedSeq = &value
+					procNetstat.TCPACKSkippedSeq = &value
 				case "TCPACKSkippedFinWait2":
-					procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value
+					procNetstat.TCPACKSkippedFinWait2 = &value
 				case "TCPACKSkippedTimeWait":
-					procNetstat.TcpExt.TCPACKSkippedTimeWait = &value
+					procNetstat.TCPACKSkippedTimeWait = &value
 				case "TCPACKSkippedChallenge":
-					procNetstat.TcpExt.TCPACKSkippedChallenge = &value
+					procNetstat.TCPACKSkippedChallenge = &value
 				case "TCPWinProbe":
-					procNetstat.TcpExt.TCPWinProbe = &value
+					procNetstat.TCPWinProbe = &value
 				case "TCPKeepAlive":
-					procNetstat.TcpExt.TCPKeepAlive = &value
+					procNetstat.TCPKeepAlive = &value
 				case "TCPMTUPFail":
-					procNetstat.TcpExt.TCPMTUPFail = &value
+					procNetstat.TCPMTUPFail = &value
 				case "TCPMTUPSuccess":
-					procNetstat.TcpExt.TCPMTUPSuccess = &value
+					procNetstat.TCPMTUPSuccess = &value
 				case "TCPWqueueTooBig":
-					procNetstat.TcpExt.TCPWqueueTooBig = &value
+					procNetstat.TCPWqueueTooBig = &value
 				}
 			case "IpExt":
 				switch key {
 				case "InNoRoutes":
-					procNetstat.IpExt.InNoRoutes = &value
+					procNetstat.InNoRoutes = &value
 				case "InTruncatedPkts":
-					procNetstat.IpExt.InTruncatedPkts = &value
+					procNetstat.InTruncatedPkts = &value
 				case "InMcastPkts":
-					procNetstat.IpExt.InMcastPkts = &value
+					procNetstat.InMcastPkts = &value
 				case "OutMcastPkts":
-					procNetstat.IpExt.OutMcastPkts = &value
+					procNetstat.OutMcastPkts = &value
 				case "InBcastPkts":
-					procNetstat.IpExt.InBcastPkts = &value
+					procNetstat.InBcastPkts = &value
 				case "OutBcastPkts":
-					procNetstat.IpExt.OutBcastPkts = &value
+					procNetstat.OutBcastPkts = &value
 				case "InOctets":
-					procNetstat.IpExt.InOctets = &value
+					procNetstat.InOctets = &value
 				case "OutOctets":
-					procNetstat.IpExt.OutOctets = &value
+					procNetstat.OutOctets = &value
 				case "InMcastOctets":
-					procNetstat.IpExt.InMcastOctets = &value
+					procNetstat.InMcastOctets = &value
 				case "OutMcastOctets":
-					procNetstat.IpExt.OutMcastOctets = &value
+					procNetstat.OutMcastOctets = &value
 				case "InBcastOctets":
-					procNetstat.IpExt.InBcastOctets = &value
+					procNetstat.InBcastOctets = &value
 				case "OutBcastOctets":
-					procNetstat.IpExt.OutBcastOctets = &value
+					procNetstat.OutBcastOctets = &value
 				case "InCsumErrors":
-					procNetstat.IpExt.InCsumErrors = &value
+					procNetstat.InCsumErrors = &value
 				case "InNoECTPkts":
-					procNetstat.IpExt.InNoECTPkts = &value
+					procNetstat.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procNetstat.IpExt.InECT1Pkts = &value
+					procNetstat.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procNetstat.IpExt.InECT0Pkts = &value
+					procNetstat.InECT0Pkts = &value
 				case "InCEPkts":
-					procNetstat.IpExt.InCEPkts = &value
+					procNetstat.InCEPkts = &value
 				case "ReasmOverlaps":
-					procNetstat.IpExt.ReasmOverlaps = &value
+					procNetstat.ReasmOverlaps = &value
 				}
 			}
 		}
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_smaps.go b/notifier/vendor/github.com/prometheus/procfs/proc_smaps.go
index 09060e82..9a297afc 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_smaps.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_smaps.go
@@ -19,7 +19,6 @@ package procfs
 import (
 	"bufio"
 	"errors"
-	"fmt"
 	"os"
 	"regexp"
 	"strconv"
@@ -29,7 +28,7 @@ import (
 )
 
 var (
-	// match the header line before each mapped zone in `/proc/pid/smaps`.
+	// Match the header line before each mapped zone in `/proc/pid/smaps`.
 	procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`)
 )
 
@@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) {
 func (s *ProcSMapsRollup) parseLine(line string) error {
 	kv := strings.SplitN(line, ":", 2)
 	if len(kv) != 2 {
-		fmt.Println(line)
 		return errors.New("invalid net/dev line, missing colon")
 	}
 
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_snmp.go b/notifier/vendor/github.com/prometheus/procfs/proc_snmp.go
index b9d2cf64..4bdc90b0 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_snmp.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_snmp.go
@@ -173,138 +173,138 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) {
 			case "Ip":
 				switch key {
 				case "Forwarding":
-					procSnmp.Ip.Forwarding = &value
+					procSnmp.Forwarding = &value
 				case "DefaultTTL":
-					procSnmp.Ip.DefaultTTL = &value
+					procSnmp.DefaultTTL = &value
 				case "InReceives":
-					procSnmp.Ip.InReceives = &value
+					procSnmp.InReceives = &value
 				case "InHdrErrors":
-					procSnmp.Ip.InHdrErrors = &value
+					procSnmp.InHdrErrors = &value
 				case "InAddrErrors":
-					procSnmp.Ip.InAddrErrors = &value
+					procSnmp.InAddrErrors = &value
 				case "ForwDatagrams":
-					procSnmp.Ip.ForwDatagrams = &value
+					procSnmp.ForwDatagrams = &value
 				case "InUnknownProtos":
-					procSnmp.Ip.InUnknownProtos = &value
+					procSnmp.InUnknownProtos = &value
 				case "InDiscards":
-					procSnmp.Ip.InDiscards = &value
+					procSnmp.InDiscards = &value
 				case "InDelivers":
-					procSnmp.Ip.InDelivers = &value
+					procSnmp.InDelivers = &value
 				case "OutRequests":
-					procSnmp.Ip.OutRequests = &value
+					procSnmp.OutRequests = &value
 				case "OutDiscards":
-					procSnmp.Ip.OutDiscards = &value
+					procSnmp.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp.Ip.OutNoRoutes = &value
+					procSnmp.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp.Ip.ReasmTimeout = &value
+					procSnmp.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp.Ip.ReasmReqds = &value
+					procSnmp.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp.Ip.ReasmOKs = &value
+					procSnmp.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp.Ip.ReasmFails = &value
+					procSnmp.ReasmFails = &value
 				case "FragOKs":
-					procSnmp.Ip.FragOKs = &value
+					procSnmp.FragOKs = &value
 				case "FragFails":
-					procSnmp.Ip.FragFails = &value
+					procSnmp.FragFails = &value
 				case "FragCreates":
-					procSnmp.Ip.FragCreates = &value
+					procSnmp.FragCreates = &value
 				}
 			case "Icmp":
 				switch key {
 				case "InMsgs":
-					procSnmp.Icmp.InMsgs = &value
+					procSnmp.InMsgs = &value
 				case "InErrors":
 					procSnmp.Icmp.InErrors = &value
 				case "InCsumErrors":
 					procSnmp.Icmp.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp.Icmp.InDestUnreachs = &value
+					procSnmp.InDestUnreachs = &value
 				case "InTimeExcds":
-					procSnmp.Icmp.InTimeExcds = &value
+					procSnmp.InTimeExcds = &value
 				case "InParmProbs":
-					procSnmp.Icmp.InParmProbs = &value
+					procSnmp.InParmProbs = &value
 				case "InSrcQuenchs":
-					procSnmp.Icmp.InSrcQuenchs = &value
+					procSnmp.InSrcQuenchs = &value
 				case "InRedirects":
-					procSnmp.Icmp.InRedirects = &value
+					procSnmp.InRedirects = &value
 				case "InEchos":
-					procSnmp.Icmp.InEchos = &value
+					procSnmp.InEchos = &value
 				case "InEchoReps":
-					procSnmp.Icmp.InEchoReps = &value
+					procSnmp.InEchoReps = &value
 				case "InTimestamps":
-					procSnmp.Icmp.InTimestamps = &value
+					procSnmp.InTimestamps = &value
 				case "InTimestampReps":
-					procSnmp.Icmp.InTimestampReps = &value
+					procSnmp.InTimestampReps = &value
 				case "InAddrMasks":
-					procSnmp.Icmp.InAddrMasks = &value
+					procSnmp.InAddrMasks = &value
 				case "InAddrMaskReps":
-					procSnmp.Icmp.InAddrMaskReps = &value
+					procSnmp.InAddrMaskReps = &value
 				case "OutMsgs":
-					procSnmp.Icmp.OutMsgs = &value
+					procSnmp.OutMsgs = &value
 				case "OutErrors":
-					procSnmp.Icmp.OutErrors = &value
+					procSnmp.OutErrors = &value
 				case "OutDestUnreachs":
-					procSnmp.Icmp.OutDestUnreachs = &value
+					procSnmp.OutDestUnreachs = &value
 				case "OutTimeExcds":
-					procSnmp.Icmp.OutTimeExcds = &value
+					procSnmp.OutTimeExcds = &value
 				case "OutParmProbs":
-					procSnmp.Icmp.OutParmProbs = &value
+					procSnmp.OutParmProbs = &value
 				case "OutSrcQuenchs":
-					procSnmp.Icmp.OutSrcQuenchs = &value
+					procSnmp.OutSrcQuenchs = &value
 				case "OutRedirects":
-					procSnmp.Icmp.OutRedirects = &value
+					procSnmp.OutRedirects = &value
 				case "OutEchos":
-					procSnmp.Icmp.OutEchos = &value
+					procSnmp.OutEchos = &value
 				case "OutEchoReps":
-					procSnmp.Icmp.OutEchoReps = &value
+					procSnmp.OutEchoReps = &value
 				case "OutTimestamps":
-					procSnmp.Icmp.OutTimestamps = &value
+					procSnmp.OutTimestamps = &value
 				case "OutTimestampReps":
-					procSnmp.Icmp.OutTimestampReps = &value
+					procSnmp.OutTimestampReps = &value
 				case "OutAddrMasks":
-					procSnmp.Icmp.OutAddrMasks = &value
+					procSnmp.OutAddrMasks = &value
 				case "OutAddrMaskReps":
-					procSnmp.Icmp.OutAddrMaskReps = &value
+					procSnmp.OutAddrMaskReps = &value
 				}
 			case "IcmpMsg":
 				switch key {
 				case "InType3":
-					procSnmp.IcmpMsg.InType3 = &value
+					procSnmp.InType3 = &value
 				case "OutType3":
-					procSnmp.IcmpMsg.OutType3 = &value
+					procSnmp.OutType3 = &value
 				}
 			case "Tcp":
 				switch key {
 				case "RtoAlgorithm":
-					procSnmp.Tcp.RtoAlgorithm = &value
+					procSnmp.RtoAlgorithm = &value
 				case "RtoMin":
-					procSnmp.Tcp.RtoMin = &value
+					procSnmp.RtoMin = &value
 				case "RtoMax":
-					procSnmp.Tcp.RtoMax = &value
+					procSnmp.RtoMax = &value
 				case "MaxConn":
-					procSnmp.Tcp.MaxConn = &value
+					procSnmp.MaxConn = &value
 				case "ActiveOpens":
-					procSnmp.Tcp.ActiveOpens = &value
+					procSnmp.ActiveOpens = &value
 				case "PassiveOpens":
-					procSnmp.Tcp.PassiveOpens = &value
+					procSnmp.PassiveOpens = &value
 				case "AttemptFails":
-					procSnmp.Tcp.AttemptFails = &value
+					procSnmp.AttemptFails = &value
 				case "EstabResets":
-					procSnmp.Tcp.EstabResets = &value
+					procSnmp.EstabResets = &value
 				case "CurrEstab":
-					procSnmp.Tcp.CurrEstab = &value
+					procSnmp.CurrEstab = &value
 				case "InSegs":
-					procSnmp.Tcp.InSegs = &value
+					procSnmp.InSegs = &value
 				case "OutSegs":
-					procSnmp.Tcp.OutSegs = &value
+					procSnmp.OutSegs = &value
 				case "RetransSegs":
-					procSnmp.Tcp.RetransSegs = &value
+					procSnmp.RetransSegs = &value
 				case "InErrs":
-					procSnmp.Tcp.InErrs = &value
+					procSnmp.InErrs = &value
 				case "OutRsts":
-					procSnmp.Tcp.OutRsts = &value
+					procSnmp.OutRsts = &value
 				case "InCsumErrors":
 					procSnmp.Tcp.InCsumErrors = &value
 				}
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_snmp6.go b/notifier/vendor/github.com/prometheus/procfs/proc_snmp6.go
index 3059cc6a..fb7fd399 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_snmp6.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_snmp6.go
@@ -182,161 +182,161 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 			case "Ip6":
 				switch key {
 				case "InReceives":
-					procSnmp6.Ip6.InReceives = &value
+					procSnmp6.InReceives = &value
 				case "InHdrErrors":
-					procSnmp6.Ip6.InHdrErrors = &value
+					procSnmp6.InHdrErrors = &value
 				case "InTooBigErrors":
-					procSnmp6.Ip6.InTooBigErrors = &value
+					procSnmp6.InTooBigErrors = &value
 				case "InNoRoutes":
-					procSnmp6.Ip6.InNoRoutes = &value
+					procSnmp6.InNoRoutes = &value
 				case "InAddrErrors":
-					procSnmp6.Ip6.InAddrErrors = &value
+					procSnmp6.InAddrErrors = &value
 				case "InUnknownProtos":
-					procSnmp6.Ip6.InUnknownProtos = &value
+					procSnmp6.InUnknownProtos = &value
 				case "InTruncatedPkts":
-					procSnmp6.Ip6.InTruncatedPkts = &value
+					procSnmp6.InTruncatedPkts = &value
 				case "InDiscards":
-					procSnmp6.Ip6.InDiscards = &value
+					procSnmp6.InDiscards = &value
 				case "InDelivers":
-					procSnmp6.Ip6.InDelivers = &value
+					procSnmp6.InDelivers = &value
 				case "OutForwDatagrams":
-					procSnmp6.Ip6.OutForwDatagrams = &value
+					procSnmp6.OutForwDatagrams = &value
 				case "OutRequests":
-					procSnmp6.Ip6.OutRequests = &value
+					procSnmp6.OutRequests = &value
 				case "OutDiscards":
-					procSnmp6.Ip6.OutDiscards = &value
+					procSnmp6.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp6.Ip6.OutNoRoutes = &value
+					procSnmp6.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp6.Ip6.ReasmTimeout = &value
+					procSnmp6.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp6.Ip6.ReasmReqds = &value
+					procSnmp6.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp6.Ip6.ReasmOKs = &value
+					procSnmp6.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp6.Ip6.ReasmFails = &value
+					procSnmp6.ReasmFails = &value
 				case "FragOKs":
-					procSnmp6.Ip6.FragOKs = &value
+					procSnmp6.FragOKs = &value
 				case "FragFails":
-					procSnmp6.Ip6.FragFails = &value
+					procSnmp6.FragFails = &value
 				case "FragCreates":
-					procSnmp6.Ip6.FragCreates = &value
+					procSnmp6.FragCreates = &value
 				case "InMcastPkts":
-					procSnmp6.Ip6.InMcastPkts = &value
+					procSnmp6.InMcastPkts = &value
 				case "OutMcastPkts":
-					procSnmp6.Ip6.OutMcastPkts = &value
+					procSnmp6.OutMcastPkts = &value
 				case "InOctets":
-					procSnmp6.Ip6.InOctets = &value
+					procSnmp6.InOctets = &value
 				case "OutOctets":
-					procSnmp6.Ip6.OutOctets = &value
+					procSnmp6.OutOctets = &value
 				case "InMcastOctets":
-					procSnmp6.Ip6.InMcastOctets = &value
+					procSnmp6.InMcastOctets = &value
 				case "OutMcastOctets":
-					procSnmp6.Ip6.OutMcastOctets = &value
+					procSnmp6.OutMcastOctets = &value
 				case "InBcastOctets":
-					procSnmp6.Ip6.InBcastOctets = &value
+					procSnmp6.InBcastOctets = &value
 				case "OutBcastOctets":
-					procSnmp6.Ip6.OutBcastOctets = &value
+					procSnmp6.OutBcastOctets = &value
 				case "InNoECTPkts":
-					procSnmp6.Ip6.InNoECTPkts = &value
+					procSnmp6.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procSnmp6.Ip6.InECT1Pkts = &value
+					procSnmp6.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procSnmp6.Ip6.InECT0Pkts = &value
+					procSnmp6.InECT0Pkts = &value
 				case "InCEPkts":
-					procSnmp6.Ip6.InCEPkts = &value
+					procSnmp6.InCEPkts = &value
 
 				}
 			case "Icmp6":
 				switch key {
 				case "InMsgs":
-					procSnmp6.Icmp6.InMsgs = &value
+					procSnmp6.InMsgs = &value
 				case "InErrors":
 					procSnmp6.Icmp6.InErrors = &value
 				case "OutMsgs":
-					procSnmp6.Icmp6.OutMsgs = &value
+					procSnmp6.OutMsgs = &value
 				case "OutErrors":
-					procSnmp6.Icmp6.OutErrors = &value
+					procSnmp6.OutErrors = &value
 				case "InCsumErrors":
 					procSnmp6.Icmp6.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp6.Icmp6.InDestUnreachs = &value
+					procSnmp6.InDestUnreachs = &value
 				case "InPktTooBigs":
-					procSnmp6.Icmp6.InPktTooBigs = &value
+					procSnmp6.InPktTooBigs = &value
 				case "InTimeExcds":
-					procSnmp6.Icmp6.InTimeExcds = &value
+					procSnmp6.InTimeExcds = &value
 				case "InParmProblems":
-					procSnmp6.Icmp6.InParmProblems = &value
+					procSnmp6.InParmProblems = &value
 				case "InEchos":
-					procSnmp6.Icmp6.InEchos = &value
+					procSnmp6.InEchos = &value
 				case "InEchoReplies":
-					procSnmp6.Icmp6.InEchoReplies = &value
+					procSnmp6.InEchoReplies = &value
 				case "InGroupMembQueries":
-					procSnmp6.Icmp6.InGroupMembQueries = &value
+					procSnmp6.InGroupMembQueries = &value
 				case "InGroupMembResponses":
-					procSnmp6.Icmp6.InGroupMembResponses = &value
+					procSnmp6.InGroupMembResponses = &value
 				case "InGroupMembReductions":
-					procSnmp6.Icmp6.InGroupMembReductions = &value
+					procSnmp6.InGroupMembReductions = &value
 				case "InRouterSolicits":
-					procSnmp6.Icmp6.InRouterSolicits = &value
+					procSnmp6.InRouterSolicits = &value
 				case "InRouterAdvertisements":
-					procSnmp6.Icmp6.InRouterAdvertisements = &value
+					procSnmp6.InRouterAdvertisements = &value
 				case "InNeighborSolicits":
-					procSnmp6.Icmp6.InNeighborSolicits = &value
+					procSnmp6.InNeighborSolicits = &value
 				case "InNeighborAdvertisements":
-					procSnmp6.Icmp6.InNeighborAdvertisements = &value
+					procSnmp6.InNeighborAdvertisements = &value
 				case "InRedirects":
-					procSnmp6.Icmp6.InRedirects = &value
+					procSnmp6.InRedirects = &value
 				case "InMLDv2Reports":
-					procSnmp6.Icmp6.InMLDv2Reports = &value
+					procSnmp6.InMLDv2Reports = &value
 				case "OutDestUnreachs":
-					procSnmp6.Icmp6.OutDestUnreachs = &value
+					procSnmp6.OutDestUnreachs = &value
 				case "OutPktTooBigs":
-					procSnmp6.Icmp6.OutPktTooBigs = &value
+					procSnmp6.OutPktTooBigs = &value
 				case "OutTimeExcds":
-					procSnmp6.Icmp6.OutTimeExcds = &value
+					procSnmp6.OutTimeExcds = &value
 				case "OutParmProblems":
-					procSnmp6.Icmp6.OutParmProblems = &value
+					procSnmp6.OutParmProblems = &value
 				case "OutEchos":
-					procSnmp6.Icmp6.OutEchos = &value
+					procSnmp6.OutEchos = &value
 				case "OutEchoReplies":
-					procSnmp6.Icmp6.OutEchoReplies = &value
+					procSnmp6.OutEchoReplies = &value
 				case "OutGroupMembQueries":
-					procSnmp6.Icmp6.OutGroupMembQueries = &value
+					procSnmp6.OutGroupMembQueries = &value
 				case "OutGroupMembResponses":
-					procSnmp6.Icmp6.OutGroupMembResponses = &value
+					procSnmp6.OutGroupMembResponses = &value
 				case "OutGroupMembReductions":
-					procSnmp6.Icmp6.OutGroupMembReductions = &value
+					procSnmp6.OutGroupMembReductions = &value
 				case "OutRouterSolicits":
-					procSnmp6.Icmp6.OutRouterSolicits = &value
+					procSnmp6.OutRouterSolicits = &value
 				case "OutRouterAdvertisements":
-					procSnmp6.Icmp6.OutRouterAdvertisements = &value
+					procSnmp6.OutRouterAdvertisements = &value
 				case "OutNeighborSolicits":
-					procSnmp6.Icmp6.OutNeighborSolicits = &value
+					procSnmp6.OutNeighborSolicits = &value
 				case "OutNeighborAdvertisements":
-					procSnmp6.Icmp6.OutNeighborAdvertisements = &value
+					procSnmp6.OutNeighborAdvertisements = &value
 				case "OutRedirects":
-					procSnmp6.Icmp6.OutRedirects = &value
+					procSnmp6.OutRedirects = &value
 				case "OutMLDv2Reports":
-					procSnmp6.Icmp6.OutMLDv2Reports = &value
+					procSnmp6.OutMLDv2Reports = &value
 				case "InType1":
-					procSnmp6.Icmp6.InType1 = &value
+					procSnmp6.InType1 = &value
 				case "InType134":
-					procSnmp6.Icmp6.InType134 = &value
+					procSnmp6.InType134 = &value
 				case "InType135":
-					procSnmp6.Icmp6.InType135 = &value
+					procSnmp6.InType135 = &value
 				case "InType136":
-					procSnmp6.Icmp6.InType136 = &value
+					procSnmp6.InType136 = &value
 				case "InType143":
-					procSnmp6.Icmp6.InType143 = &value
+					procSnmp6.InType143 = &value
 				case "OutType133":
-					procSnmp6.Icmp6.OutType133 = &value
+					procSnmp6.OutType133 = &value
 				case "OutType135":
-					procSnmp6.Icmp6.OutType135 = &value
+					procSnmp6.OutType135 = &value
 				case "OutType136":
-					procSnmp6.Icmp6.OutType136 = &value
+					procSnmp6.OutType136 = &value
 				case "OutType143":
-					procSnmp6.Icmp6.OutType143 = &value
+					procSnmp6.OutType143 = &value
 				}
 			case "Udp6":
 				switch key {
@@ -355,7 +355,7 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 				case "InCsumErrors":
 					procSnmp6.Udp6.InCsumErrors = &value
 				case "IgnoredMulti":
-					procSnmp6.Udp6.IgnoredMulti = &value
+					procSnmp6.IgnoredMulti = &value
 				}
 			case "UdpLite6":
 				switch key {
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_stat.go b/notifier/vendor/github.com/prometheus/procfs/proc_stat.go
index 06a8d931..3328556b 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_stat.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_stat.go
@@ -101,6 +101,12 @@ type ProcStat struct {
 	RSS int
 	// Soft limit in bytes on the rss of the process.
 	RSSLimit uint64
+	// The address above which program text can run.
+	StartCode uint64
+	// The address below which program text can run.
+	EndCode uint64
+	// The address of the start (i.e., bottom) of the stack.
+	StartStack uint64
 	// CPU number last executed on.
 	Processor uint
 	// Real-time scheduling priority, a number in the range 1 to 99 for processes
@@ -177,9 +183,9 @@ func (p Proc) Stat() (ProcStat, error) {
 		&s.VSize,
 		&s.RSS,
 		&s.RSSLimit,
-		&ignoreUint64,
-		&ignoreUint64,
-		&ignoreUint64,
+		&s.StartCode,
+		&s.EndCode,
+		&s.StartStack,
 		&ignoreUint64,
 		&ignoreUint64,
 		&ignoreUint64,
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_statm.go b/notifier/vendor/github.com/prometheus/procfs/proc_statm.go
new file mode 100644
index 00000000..ed579842
--- /dev/null
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_statm.go
@@ -0,0 +1,116 @@
+// Copyright 2025 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/prometheus/procfs/internal/util"
+)
+
+// - https://man7.org/linux/man-pages/man5/proc_pid_statm.5.html
+
+// ProcStatm Provides memory usage information for a process, measured in memory pages.
+// Read from /proc/[pid]/statm.
+type ProcStatm struct {
+	// The process ID.
+	PID int
+	// total program size (same as VmSize in status)
+	Size uint64
+	// resident set size (same as VmRSS in status)
+	Resident uint64
+	// number of resident shared pages (i.e., backed by a file)
+	Shared uint64
+	// text (code)
+	Text uint64
+	// library (unused since Linux 2.6; always 0)
+	Lib uint64
+	// data + stack
+	Data uint64
+	// dirty pages (unused since Linux 2.6; always 0)
+	Dt uint64
+}
+
+// NewStatm returns the current status information of the process.
+// Deprecated: Use p.Statm() instead.
+func (p Proc) NewStatm() (ProcStatm, error) {
+	return p.Statm()
+}
+
+// Statm returns the current memory usage information of the process.
+func (p Proc) Statm() (ProcStatm, error) {
+	data, err := util.ReadFileNoStat(p.path("statm"))
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	statmSlice, err := parseStatm(data)
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	procStatm := ProcStatm{
+		PID:      p.PID,
+		Size:     statmSlice[0],
+		Resident: statmSlice[1],
+		Shared:   statmSlice[2],
+		Text:     statmSlice[3],
+		Lib:      statmSlice[4],
+		Data:     statmSlice[5],
+		Dt:       statmSlice[6],
+	}
+
+	return procStatm, nil
+}
+
+// parseStatm return /proc/[pid]/statm data to uint64 slice.
+func parseStatm(data []byte) ([]uint64, error) {
+	var statmSlice []uint64
+	statmItems := strings.Fields(string(data))
+	for i := 0; i < len(statmItems); i++ {
+		statmItem, err := strconv.ParseUint(statmItems[i], 10, 64)
+		if err != nil {
+			return nil, err
+		}
+		statmSlice = append(statmSlice, statmItem)
+	}
+	return statmSlice, nil
+}
+
+// SizeBytes returns the process of total program size in bytes.
+func (s ProcStatm) SizeBytes() uint64 {
+	return s.Size * uint64(os.Getpagesize())
+}
+
+// ResidentBytes returns the process of resident set size in bytes.
+func (s ProcStatm) ResidentBytes() uint64 {
+	return s.Resident * uint64(os.Getpagesize())
+}
+
+// SHRBytes returns the process of share memory size in bytes.
+func (s ProcStatm) SHRBytes() uint64 {
+	return s.Shared * uint64(os.Getpagesize())
+}
+
+// TextBytes returns the process of text (code) size in bytes.
+func (s ProcStatm) TextBytes() uint64 {
+	return s.Text * uint64(os.Getpagesize())
+}
+
+// DataBytes returns the process of data + stack size in bytes.
+func (s ProcStatm) DataBytes() uint64 {
+	return s.Data * uint64(os.Getpagesize())
+}
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_status.go b/notifier/vendor/github.com/prometheus/procfs/proc_status.go
index a055197c..dd8aa568 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_status.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_status.go
@@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
 			}
 		}
 	case "NSpid":
-		s.NSpids = calcNSPidsList(vString)
+		nspids, err := calcNSPidsList(vString)
+		if err != nil {
+			return err
+		}
+		s.NSpids = nspids
 	case "VmPeak":
 		s.VmPeak = vUintBytes
 	case "VmSize":
@@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 {
 	return g
 }
 
-func calcNSPidsList(nspidsString string) []uint64 {
-	s := strings.Split(nspidsString, " ")
+func calcNSPidsList(nspidsString string) ([]uint64, error) {
+	s := strings.Split(nspidsString, "\t")
 	var nspids []uint64
 
 	for _, nspid := range s {
-		nspid, _ := strconv.ParseUint(nspid, 10, 64)
-		if nspid == 0 {
-			continue
+		nspid, err := strconv.ParseUint(nspid, 10, 64)
+		if err != nil {
+			return nil, err
 		}
 		nspids = append(nspids, nspid)
 	}
 
-	return nspids
+	return nspids, nil
 }
diff --git a/notifier/vendor/github.com/prometheus/procfs/proc_sys.go b/notifier/vendor/github.com/prometheus/procfs/proc_sys.go
index 5eefbe2e..3810d1ac 100644
--- a/notifier/vendor/github.com/prometheus/procfs/proc_sys.go
+++ b/notifier/vendor/github.com/prometheus/procfs/proc_sys.go
@@ -21,7 +21,7 @@ import (
 )
 
 func sysctlToPath(sysctl string) string {
-	return strings.Replace(sysctl, ".", "/", -1)
+	return strings.ReplaceAll(sysctl, ".", "/")
 }
 
 func (fs FS) SysctlStrings(sysctl string) ([]string, error) {
diff --git a/notifier/vendor/github.com/prometheus/procfs/softirqs.go b/notifier/vendor/github.com/prometheus/procfs/softirqs.go
index 28708e07..403e6ae7 100644
--- a/notifier/vendor/github.com/prometheus/procfs/softirqs.go
+++ b/notifier/vendor/github.com/prometheus/procfs/softirqs.go
@@ -68,8 +68,8 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 		if len(parts) < 2 {
 			continue
 		}
-		switch {
-		case parts[0] == "HI:":
+		switch parts[0] {
+		case "HI:":
 			perCPU := parts[1:]
 			softirqs.Hi = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -77,7 +77,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TIMER:":
+		case "TIMER:":
 			perCPU := parts[1:]
 			softirqs.Timer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -85,7 +85,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_TX:":
+		case "NET_TX:":
 			perCPU := parts[1:]
 			softirqs.NetTx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -93,7 +93,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_RX:":
+		case "NET_RX:":
 			perCPU := parts[1:]
 			softirqs.NetRx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -101,7 +101,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "BLOCK:":
+		case "BLOCK:":
 			perCPU := parts[1:]
 			softirqs.Block = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -109,7 +109,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "IRQ_POLL:":
+		case "IRQ_POLL:":
 			perCPU := parts[1:]
 			softirqs.IRQPoll = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -117,7 +117,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TASKLET:":
+		case "TASKLET:":
 			perCPU := parts[1:]
 			softirqs.Tasklet = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -125,7 +125,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "SCHED:":
+		case "SCHED:":
 			perCPU := parts[1:]
 			softirqs.Sched = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -133,7 +133,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "HRTIMER:":
+		case "HRTIMER:":
 			perCPU := parts[1:]
 			softirqs.HRTimer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -141,7 +141,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "RCU:":
+		case "RCU:":
 			perCPU := parts[1:]
 			softirqs.RCU = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
diff --git a/notifier/vendor/github.com/rs/cors/cors.go b/notifier/vendor/github.com/rs/cors/cors.go
index da80d343..724f242a 100644
--- a/notifier/vendor/github.com/rs/cors/cors.go
+++ b/notifier/vendor/github.com/rs/cors/cors.go
@@ -364,9 +364,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	// Note: the Fetch standard guarantees that at most one
 	// Access-Control-Request-Headers header is present in the preflight request;
 	// see step 5.2 in https://fetch.spec.whatwg.org/#cors-preflight-fetch-0.
-	reqHeaders, found := first(r.Header, "Access-Control-Request-Headers")
-	if found && !c.allowedHeadersAll && !c.allowedHeaders.Subsumes(reqHeaders[0]) {
-		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders[0])
+	// However, some gateways split that header into multiple headers of the same name;
+	// see https://github.com/rs/cors/issues/184.
+	reqHeaders, found := r.Header["Access-Control-Request-Headers"]
+	if found && !c.allowedHeadersAll && !c.allowedHeaders.Accepts(reqHeaders) {
+		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders)
 		return
 	}
 	if c.allowedOriginsAll {
@@ -391,9 +393,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	if len(c.maxAge) > 0 {
 		headers["Access-Control-Max-Age"] = c.maxAge
 	}
-	if c.Log != nil {
-		c.logf("  Preflight response headers: %v", headers)
-	}
+	c.logf("  Preflight response headers: %v", headers)
 }
 
 // handleActualRequest handles simple cross-origin requests, actual request or redirects
@@ -440,9 +440,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
 	if c.allowCredentials {
 		headers["Access-Control-Allow-Credentials"] = headerTrue
 	}
-	if c.Log != nil {
-		c.logf("  Actual response added headers: %v", headers)
-	}
+	c.logf("  Actual response added headers: %v", headers)
 }
 
 // convenience method. checks if a logger is set.
diff --git a/notifier/vendor/github.com/rs/cors/internal/sortedset.go b/notifier/vendor/github.com/rs/cors/internal/sortedset.go
index 513da20f..844f3f9e 100644
--- a/notifier/vendor/github.com/rs/cors/internal/sortedset.go
+++ b/notifier/vendor/github.com/rs/cors/internal/sortedset.go
@@ -52,46 +52,134 @@ func (set SortedSet) String() string {
 	return strings.Join(elems, ",")
 }
 
-// Subsumes reports whether csv is a sequence of comma-separated names that are
-//   - all elements of set,
-//   - sorted in lexicographically order,
+// Accepts reports whether values is a sequence of list-based field values
+// whose elements are
+//   - all members of set,
+//   - sorted in lexicographical order,
 //   - unique.
-func (set SortedSet) Subsumes(csv string) bool {
-	if csv == "" {
-		return true
+func (set SortedSet) Accepts(values []string) bool {
+	var ( // effectively constant
+		maxLen = maxOWSBytes + set.maxLen + maxOWSBytes + 1 // +1 for comma
+	)
+	var (
+		posOfLastNameSeen = -1
+		name              string
+		commaFound        bool
+		emptyElements     int
+		ok                bool
+	)
+	for _, s := range values {
+		for {
+			// As a defense against maliciously long names in s,
+			// we process only a small number of s's leading bytes per iteration.
+			name, s, commaFound = cutAtComma(s, maxLen)
+			name, ok = trimOWS(name, maxOWSBytes)
+			if !ok {
+				return false
+			}
+			if name == "" {
+				// RFC 9110 requires recipients to tolerate
+				// "a reasonable number of empty list elements"; see
+				// https://httpwg.org/specs/rfc9110.html#abnf.extension.recipient.
+				emptyElements++
+				if emptyElements > maxEmptyElements {
+					return false
+				}
+				if !commaFound { // We have now exhausted the names in s.
+					break
+				}
+				continue
+			}
+			pos, ok := set.m[name]
+			if !ok {
+				return false
+			}
+			// The names in s are expected to be sorted in lexicographical order
+			// and to each appear at most once.
+			// Therefore, the positions (in set) of the names that
+			// appear in s should form a strictly increasing sequence.
+			// If that's not actually the case, bail out.
+			if pos <= posOfLastNameSeen {
+				return false
+			}
+			posOfLastNameSeen = pos
+			if !commaFound { // We have now exhausted the names in s.
+				break
+			}
+		}
+	}
+	return true
+}
+
+const (
+	maxOWSBytes      = 1  // number of leading/trailing OWS bytes tolerated
+	maxEmptyElements = 16 // number of empty list elements tolerated
+)
+
+func cutAtComma(s string, n int) (before, after string, found bool) {
+	// Note: this implementation draws inspiration from strings.Cut's.
+	end := min(len(s), n)
+	if i := strings.IndexByte(s[:end], ','); i >= 0 {
+		after = s[i+1:] // deal with this first to save one bounds check
+		return s[:i], after, true
+	}
+	return s, "", false
+}
+
+// TrimOWS trims up to n bytes of [optional whitespace (OWS)]
+// from the start of and/or the end of s.
+// If no more than n bytes of OWS are found at the start of s
+// and no more than n bytes of OWS are found at the end of s,
+// it returns the trimmed result and true.
+// Otherwise, it returns the original string and false.
+//
+// [optional whitespace (OWS)]: https://httpwg.org/specs/rfc9110.html#whitespace
+func trimOWS(s string, n int) (trimmed string, ok bool) {
+	if s == "" {
+		return s, true
+	}
+	trimmed, ok = trimRightOWS(s, n)
+	if !ok {
+		return s, false
 	}
-	posOfLastNameSeen := -1
-	chunkSize := set.maxLen + 1 // (to accommodate for at least one comma)
-	for {
-		// As a defense against maliciously long names in csv,
-		// we only process at most chunkSize bytes per iteration.
-		end := min(len(csv), chunkSize)
-		comma := strings.IndexByte(csv[:end], ',')
-		var name string
-		if comma == -1 {
-			name = csv
-		} else {
-			name = csv[:comma]
+	trimmed, ok = trimLeftOWS(trimmed, n)
+	if !ok {
+		return s, false
+	}
+	return trimmed, true
+}
+
+func trimLeftOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		pos, found := set.m[name]
-		if !found {
-			return false
+		if !(s[0] == ' ' || s[0] == '\t') {
+			break
 		}
-		// The names in csv are expected to be sorted in lexicographical order
-		// and appear at most once in csv.
-		// Therefore, the positions (in set) of the names that
-		// appear in csv should form a strictly increasing sequence.
-		// If that's not actually the case, bail out.
-		if pos <= posOfLastNameSeen {
-			return false
+		s = s[1:]
+		i++
+	}
+	return s, true
+}
+
+func trimRightOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		posOfLastNameSeen = pos
-		if comma < 0 { // We've now processed all the names in csv.
+		last := len(s) - 1
+		if !(s[last] == ' ' || s[last] == '\t') {
 			break
 		}
-		csv = csv[comma+1:]
+		s = s[:last]
+		i++
 	}
-	return true
+	return s, true
 }
 
 // TODO: when updating go directive to 1.21 or later,
diff --git a/notifier/vendor/github.com/rs/cors/utils.go b/notifier/vendor/github.com/rs/cors/utils.go
index 7019f45c..41b0c283 100644
--- a/notifier/vendor/github.com/rs/cors/utils.go
+++ b/notifier/vendor/github.com/rs/cors/utils.go
@@ -1,7 +1,6 @@
 package cors
 
 import (
-	"net/http"
 	"strings"
 )
 
@@ -24,11 +23,3 @@ func convert(s []string, f func(string) string) []string {
 	}
 	return out
 }
-
-func first(hdrs http.Header, k string) ([]string, bool) {
-	v, found := hdrs[k]
-	if !found || len(v) == 0 {
-		return nil, false
-	}
-	return v[:1], true
-}
diff --git a/notifier/vendor/github.com/rs/zerolog/CNAME b/notifier/vendor/github.com/rs/zerolog/CNAME
deleted file mode 100644
index 9ce57a6e..00000000
--- a/notifier/vendor/github.com/rs/zerolog/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-zerolog.io
\ No newline at end of file
diff --git a/notifier/vendor/github.com/rs/zerolog/CONTRIBUTING.md b/notifier/vendor/github.com/rs/zerolog/CONTRIBUTING.md
new file mode 100644
index 00000000..a09e9e21
--- /dev/null
+++ b/notifier/vendor/github.com/rs/zerolog/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contributing to Zerolog
+
+Thank you for your interest in contributing to **Zerolog**!
+
+Zerolog is a **feature-complete**, high-performance logging library designed to be **lean** and **non-bloated**. The focus of ongoing development is on **bug fixes**, **performance improvements**, and **modernization efforts** (such as keeping up with Go best practices and compatibility with newer Go versions).
+
+## What We're Looking For
+
+We welcome contributions in the following areas:
+
+- **Bug Fixes**: If you find an issue or unexpected behavior, please open an issue and/or submit a fix.
+- **Performance Optimizations**: Improvements that reduce memory usage, allocation count, or CPU cycles without introducing complexity are appreciated.
+- **Modernization**: Compatibility updates for newer Go versions or idiomatic improvements that do not increase library size or complexity.
+- **Documentation Enhancements**: Corrections, clarifications, and improvements to documentation or code comments.
+
+## What We're *Not* Looking For
+
+Zerolog is intended to remain **minimalistic and efficient**. Therefore, we are **not accepting**:
+
+- New features that add optional behaviors or extend API surface area.
+- Built-in support for frameworks or external systems (e.g., bindings, integrations).
+- General-purpose abstractions or configuration helpers.
+
+If you're unsure whether a change aligns with the project's philosophy, feel free to open an issue for discussion before submitting a PR.
+
+## Contributing Guidelines
+
+1. **Fork the repository**
+2. **Create a branch** for your fix or improvement
+3. **Write tests** to cover your changes
+4. Ensure `go test ./...` passes
+5. Run `go fmt` and `go vet` to ensure code consistency
+6. **Submit a pull request** with a clear explanation of the motivation and impact
+
+## Code Style
+
+- Keep the code simple, efficient, and idiomatic.
+- Avoid introducing new dependencies.
+- Preserve backwards compatibility unless explicitly discussed.
+
+---
+
+We appreciate your effort in helping us keep Zerolog fast, minimal, and reliable!
diff --git a/notifier/vendor/github.com/rs/zerolog/README.md b/notifier/vendor/github.com/rs/zerolog/README.md
index 1306a6c1..9d4e8e8d 100644
--- a/notifier/vendor/github.com/rs/zerolog/README.md
+++ b/notifier/vendor/github.com/rs/zerolog/README.md
@@ -366,6 +366,37 @@ log.Info().Str("foo", "bar").Msg("Hello World")
 // Output: 2006-01-02T15:04:05Z07:00 | INFO  | ***Hello World**** foo:BAR
 ```
 
+To use custom advanced formatting:
+
+```go
+output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true,
+    PartsOrder:    []string{"level", "one", "two", "three", "message"},
+    FieldsExclude: []string{"one", "two", "three"}}
+output.FormatLevel = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%-6s", i)) }
+output.FormatFieldName = func(i interface{}) string { return fmt.Sprintf("%s:", i) }
+output.FormatPartValueByName = func(i interface{}, s string) string {
+    var ret string
+    switch s {
+    case "one":
+        ret = strings.ToUpper(fmt.Sprintf("%s", i))
+    case "two":
+        ret = strings.ToLower(fmt.Sprintf("%s", i))
+    case "three":
+        ret = strings.ToLower(fmt.Sprintf("(%s)", i))
+    }
+    return ret
+}
+log := zerolog.New(output)
+
+log.Info().Str("foo", "bar").
+    Str("two", "TEST_TWO").
+    Str("one", "test_one").
+    Str("three", "test_three").
+    Msg("Hello World")
+    
+// Output: INFO   TEST_ONE test_two (test_three) Hello World foo:bar
+```
+
 ### Sub dictionary
 
 ```go
diff --git a/notifier/vendor/github.com/rs/zerolog/_config.yml b/notifier/vendor/github.com/rs/zerolog/_config.yml
deleted file mode 100644
index a1e896d7..00000000
--- a/notifier/vendor/github.com/rs/zerolog/_config.yml
+++ /dev/null
@@ -1 +0,0 @@
-remote_theme: rs/gh-readme
diff --git a/notifier/vendor/github.com/rs/zerolog/console.go b/notifier/vendor/github.com/rs/zerolog/console.go
index 7e65e86f..6c881ef6 100644
--- a/notifier/vendor/github.com/rs/zerolog/console.go
+++ b/notifier/vendor/github.com/rs/zerolog/console.go
@@ -47,6 +47,10 @@ const (
 // Formatter transforms the input into a formatted string.
 type Formatter func(interface{}) string
 
+// FormatterByFieldName transforms the input into a formatted string,
+// being able to differentiate formatting based on field name.
+type FormatterByFieldName func(interface{}, string) string
+
 // ConsoleWriter parses the JSON input and writes it in an
 // (optionally) colorized, human-friendly format to Out.
 type ConsoleWriter struct {
@@ -85,6 +89,9 @@ type ConsoleWriter struct {
 	FormatFieldValue    Formatter
 	FormatErrFieldName  Formatter
 	FormatErrFieldValue Formatter
+	// If this is configured it is used for "part" values and
+	// has precedence on FormatFieldValue
+	FormatPartValueByName FormatterByFieldName
 
 	FormatExtra func(map[string]interface{}, *bytes.Buffer) error
 
@@ -282,8 +289,9 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
 // writePart appends a formatted part to buf.
 func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{}, p string) {
 	var f Formatter
+	var fvn FormatterByFieldName
 
-	if w.PartsExclude != nil && len(w.PartsExclude) > 0 {
+	if len(w.PartsExclude) > 0 {
 		for _, exclude := range w.PartsExclude {
 			if exclude == p {
 				return
@@ -317,14 +325,21 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
 			f = w.FormatCaller
 		}
 	default:
-		if w.FormatFieldValue == nil {
-			f = consoleDefaultFormatFieldValue
-		} else {
+		if w.FormatPartValueByName != nil {
+			fvn = w.FormatPartValueByName
+		} else if w.FormatFieldValue != nil {
 			f = w.FormatFieldValue
+		} else {
+			f = consoleDefaultFormatFieldValue
 		}
 	}
 
-	var s = f(evt[p])
+	var s string
+	if f == nil {
+		s = fvn(evt[p], p)
+	} else {
+		s = f(evt[p])
+	}
 
 	if len(s) > 0 {
 		if buf.Len() > 0 {
diff --git a/notifier/vendor/github.com/rs/zerolog/log.go b/notifier/vendor/github.com/rs/zerolog/log.go
index 6c1d4ead..ea2cd62b 100644
--- a/notifier/vendor/github.com/rs/zerolog/log.go
+++ b/notifier/vendor/github.com/rs/zerolog/log.go
@@ -494,7 +494,7 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event {
 	if level != NoLevel && LevelFieldName != "" {
 		e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
 	}
-	if l.context != nil && len(l.context) > 1 {
+	if len(l.context) > 1 {
 		e.buf = enc.AppendObjectData(e.buf, l.context)
 	}
 	if l.stack {
diff --git a/notifier/vendor/github.com/rs/zerolog/sampler.go b/notifier/vendor/github.com/rs/zerolog/sampler.go
index 83ce2ed3..19e04bd4 100644
--- a/notifier/vendor/github.com/rs/zerolog/sampler.go
+++ b/notifier/vendor/github.com/rs/zerolog/sampler.go
@@ -47,6 +47,9 @@ type BasicSampler struct {
 // Sample implements the Sampler interface.
 func (s *BasicSampler) Sample(lvl Level) bool {
 	n := s.N
+	if n == 0 {
+		return false
+	}
 	if n == 1 {
 		return true
 	}
@@ -87,7 +90,7 @@ func (s *BurstSampler) inc() uint32 {
 	now := TimestampFunc().UnixNano()
 	resetAt := atomic.LoadInt64(&s.resetAt)
 	var c uint32
-	if now > resetAt {
+	if now >= resetAt {
 		c = 1
 		atomic.StoreUint32(&s.counter, c)
 		newResetAt := now + s.Period.Nanoseconds()
diff --git a/notifier/vendor/github.com/rs/zerolog/writer.go b/notifier/vendor/github.com/rs/zerolog/writer.go
index 41b394d7..0fc5ff59 100644
--- a/notifier/vendor/github.com/rs/zerolog/writer.go
+++ b/notifier/vendor/github.com/rs/zerolog/writer.go
@@ -213,6 +213,15 @@ func (w *FilteredLevelWriter) WriteLevel(level Level, p []byte) (int, error) {
 	return len(p), nil
 }
 
+// Call the underlying writer's Close method if it is an io.Closer. Otherwise
+// does nothing.
+func (w *FilteredLevelWriter) Close() error {
+	if closer, ok := w.Writer.(io.Closer); ok {
+		return closer.Close()
+	}
+	return nil
+}
+
 var triggerWriterPool = &sync.Pool{
 	New: func() interface{} {
 		return bytes.NewBuffer(make([]byte, 0, 1024))
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
index 0b8155aa..f13675ed 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -25,72 +26,77 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Add(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Add(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
 	msg, err := server.Read(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterConfigControllerHandlerServer registers the http handlers for service ConfigController to "mux".
 // UnaryRPC     :call ConfigControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterConfigControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ConfigControllerServer) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -102,20 +108,15 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -127,9 +128,7 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -156,7 +155,6 @@ func RegisterConfigControllerHandlerFromEndpoint(ctx context.Context, mux *runti
 			}
 		}()
 	}()
-
 	return RegisterConfigControllerHandler(ctx, mux, conn)
 }
 
@@ -170,16 +168,13 @@ func RegisterConfigControllerHandler(ctx context.Context, mux *runtime.ServeMux,
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ConfigControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ConfigControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "ConfigControllerClient" to call the correct interceptors.
+// "ConfigControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ConfigControllerClient) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -190,18 +185,13 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -212,22 +202,17 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_ConfigController_Add_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
-
+	pattern_ConfigController_Add_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 	pattern_ConfigController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 )
 
 var (
-	forward_ConfigController_Add_0 = runtime.ForwardResponseMessage
-
+	forward_ConfigController_Add_0  = runtime.ForwardResponseMessage
 	forward_ConfigController_Read_0 = runtime.ForwardResponseMessage
 )
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
index 6246b4bf..c5b245fe 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,160 +25,144 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Create(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Delete(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ListPage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ListPage(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterDetectorControllerHandlerServer registers the http handlers for service DetectorController to "mux".
 // UnaryRPC     :call DetectorControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDetectorControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DetectorControllerServer) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -189,20 +174,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -214,20 +194,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -239,9 +214,7 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -268,7 +241,6 @@ func RegisterDetectorControllerHandlerFromEndpoint(ctx context.Context, mux *run
 			}
 		}()
 	}()
-
 	return RegisterDetectorControllerHandler(ctx, mux, conn)
 }
 
@@ -282,16 +254,13 @@ func RegisterDetectorControllerHandler(ctx context.Context, mux *runtime.ServeMu
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DetectorControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DetectorControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "DetectorControllerClient" to call the correct interceptors.
+// "DetectorControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DetectorControllerClient) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -302,18 +271,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -324,18 +288,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -346,26 +305,19 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_DetectorController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
-	pattern_DetectorController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
+	pattern_DetectorController_Create_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
+	pattern_DetectorController_Delete_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
 	pattern_DetectorController_ListPage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "detector", "event-processor", "page", "page_num"}, ""))
 )
 
 var (
-	forward_DetectorController_Create_0 = runtime.ForwardResponseMessage
-
-	forward_DetectorController_Delete_0 = runtime.ForwardResponseMessage
-
+	forward_DetectorController_Create_0   = runtime.ForwardResponseMessage
+	forward_DetectorController_Delete_0   = runtime.ForwardResponseMessage
 	forward_DetectorController_ListPage_0 = runtime.ForwardResponseMessage
 )
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
index fb4087d9..3604294e 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
@@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
+func (jt JSONTime) String() string {
+	return time.Time(jt).String()
+}
+
 type Token struct {
 	Username              string    `json:"username"`
 	UserID                string    `json:"user_id"`
@@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) {
 		return nil, errors.New("unknown authorization format")
 	}
 
-	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) {
+	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) {
 		return key, nil
 	})
 	if err != nil {
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
index 79432fec..24b0d6e3 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
@@ -27,7 +27,7 @@ func SetReady() {
 }
 
 // ReadyHandler handles ready probes.
-func ReadyHandler(w http.ResponseWriter, r *http.Request) {
+func ReadyHandler(w http.ResponseWriter, _ *http.Request) {
 	if IsReady() {
 		// Make it simple: do nothing and have 200 OK
 		return
@@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // LiveHandler handles live probes.
-func LiveHandler(w http.ResponseWriter, r *http.Request) {
+func LiveHandler(http.ResponseWriter, *http.Request) {
 	// Make it simple: do nothing and have 200 OK
 }
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
index cb9487d6..822eb440 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
@@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
 
 const CorrelationHeader = "correlation-id"
 
-func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	var corrID string
 
 	md, ok := metadata.FromIncomingContext(ctx)
diff --git a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/util/retry/retry.go b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/util/retry/retry.go
index cd1b6689..c453781a 100644
--- a/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/util/retry/retry.go
+++ b/notifier/vendor/github.com/runtime-radar/runtime-radar/lib/util/retry/retry.go
@@ -21,7 +21,7 @@ type Config struct {
 func NewDefaultConfig() *Config {
 	return &Config{
 		1,
-		func(err error) bool { return true },
+		func(error) bool { return true },
 		time.Millisecond * 100,
 	}
 }
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/.envrc b/notifier/vendor/github.com/sagikazarmark/locafero/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/notifier/vendor/github.com/sagikazarmark/locafero/.envrc
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/finder.go b/notifier/vendor/github.com/sagikazarmark/locafero/finder.go
index 754c8b26..ef8d5471 100644
--- a/notifier/vendor/github.com/sagikazarmark/locafero/finder.go
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/finder.go
@@ -27,7 +27,7 @@ type Finder struct {
 	// It provides the capability to search for entries with depth,
 	// meaning it can target deeper locations within the directory structure.
 	//
-	// It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns.
+	// It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns.
 	//
 	// Examples:
 	//   - config.yaml
@@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 			// pool.Go(func() ([]string, error) {
 			// 	// If the name contains any glob character, perform a glob match
-			// 	if strings.ContainsAny(searchName, "*?[]\\^") {
+			// 	if strings.ContainsAny(searchName, globMatch) {
 			// 		return globWalkSearch(fsys, searchPath, searchName, f.Type)
 			// 	}
 			//
@@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 	allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
 		// If the name contains any glob character, perform a glob match
-		if strings.ContainsAny(item.name, "*?[]\\^") {
+		if strings.ContainsAny(item.name, globMatch) {
 			return globWalkSearch(fsys, item.path, item.name, f.Type)
 		}
 
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/flake.lock b/notifier/vendor/github.com/sagikazarmark/locafero/flake.lock
index 46d28f80..df2a8cce 100644
--- a/notifier/vendor/github.com/sagikazarmark/locafero/flake.lock
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1725907707,
+        "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "2bbbbc468fc02257265a79652a8350651cca495a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
+        "lastModified": 1725234343,
+        "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
+        "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6",
         "type": "github"
       },
       "original": {
@@ -60,11 +138,29 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -82,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -95,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
+      "inputs": {
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
         "nixpkgs": [
           "devenv",
           "nixpkgs"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -153,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
+        "lastModified": 1725233747,
+        "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -187,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.05",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1694343207,
-        "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1725910328,
+        "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "78058d810644f5ed276804ce7ea9e82d92bee293",
+        "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4",
         "type": "github"
       },
       "original": {
@@ -217,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -232,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -249,7 +433,7 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
       }
     },
     "systems": {
@@ -266,6 +450,21 @@
         "repo": "default",
         "type": "github"
       }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/flake.nix b/notifier/vendor/github.com/sagikazarmark/locafero/flake.nix
index 209ecf28..312f1ec8 100644
--- a/notifier/vendor/github.com/sagikazarmark/locafero/flake.nix
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.lib.mkDefault pkgs.go_1_23;
             };
 
             packages = with pkgs; [
@@ -34,11 +35,27 @@
 
           ci = devenv.shells.default;
 
-          ci_1_20 = {
+          ci_1_21 = {
             imports = [ devenv.shells.ci ];
 
             languages = {
-              go.package = pkgs.go_1_20;
+              go.package = pkgs.go_1_21;
+            };
+          };
+
+          ci_1_22 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_22;
+            };
+          };
+
+          ci_1_23 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_23;
             };
           };
         };
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/glob.go b/notifier/vendor/github.com/sagikazarmark/locafero/glob.go
new file mode 100644
index 00000000..00f833e9
--- /dev/null
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/glob.go
@@ -0,0 +1,5 @@
+//go:build !windows
+
+package locafero
+
+const globMatch = "*?[]\\^"
diff --git a/notifier/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/notifier/vendor/github.com/sagikazarmark/locafero/glob_windows.go
new file mode 100644
index 00000000..7aec2b24
--- /dev/null
+++ b/notifier/vendor/github.com/sagikazarmark/locafero/glob_windows.go
@@ -0,0 +1,8 @@
+//go:build windows
+
+package locafero
+
+// See [filepath.Match]:
+//
+//	On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
+const globMatch = "*?[]^"
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/notifier/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
deleted file mode 100644
index 1fb0e1be..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.nix]
-indent_size = 2
-
-[{Makefile,*.mk}]
-indent_style = tab
-
-[Taskfile.yaml]
-indent_size = 2
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/.envrc b/notifier/vendor/github.com/sagikazarmark/slog-shim/.envrc
deleted file mode 100644
index 3ce7171a..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/.envrc
+++ /dev/null
@@ -1,4 +0,0 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
-fi
-use flake . --impure
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/notifier/vendor/github.com/sagikazarmark/slog-shim/.gitignore
deleted file mode 100644
index dc6d8b58..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/.devenv/
-/.direnv/
-/.task/
-/build/
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/notifier/vendor/github.com/sagikazarmark/slog-shim/LICENSE
deleted file mode 100644
index 6a66aea5..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/README.md b/notifier/vendor/github.com/sagikazarmark/slog-shim/README.md
deleted file mode 100644
index 1f5be85e..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# [slog](https://pkg.go.dev/log/slog) shim
-
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml)
-[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square)
-[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org)
-
-Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library.
-Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately,
-especially since updating to Go 1.21 is a decision that most libraries won't make overnight.
-
-Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog).
-While it's generally advised against using experimental packages in production,
-this one served as a sort of backport package for the last few years,
-incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`).
-
-This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`.
-
-**How does it achieve backwards compatibility?**
-
-Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is.
-(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.)
-
-This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`.
-Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly.
-
-For older Go versions, the library might become unstable after removing the shim.
-However, since those older versions are no longer supported, the promise of backward compatibility remains intact.
-
-## Installation
-
-```shell
-go get github.com/sagikazarmark/slog-shim
-```
-
-## Usage
-
-Import this package into your library and use it in your public API:
-
-```go
-package mylib
-
-import slog "github.com/sagikazarmark/slog-shim"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21):
-
-```go
-package main
-
-import "log/slog"
-
-// OR
-
-import "golang.org/x/exp/slog"
-
-mylib.New(slog.Default())
-```
-
-**Make sure consumers are aware that your API behaves differently on different Go versions.**
-
-Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code:
-
-```diff
-package mylib
-
-- import slog "github.com/sagikazarmark/slog-shim"
-+ import "log/slog"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-## License
-
-The project is licensed under a [BSD-style license](LICENSE).
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/attr.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/attr.go
deleted file mode 100644
index 89608bf3..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/attr.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
deleted file mode 100644
index b6648133..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.lock
deleted file mode 100644
index 7e8898e9..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.lock
+++ /dev/null
@@ -1,273 +0,0 @@
-{
-  "nodes": {
-    "devenv": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "flake-compat": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-parts": {
-      "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
-      },
-      "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "type": "github"
-      }
-    },
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "gitignore": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "pre-commit-hooks",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "type": "github"
-      }
-    },
-    "lowdown-src": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
-        "type": "github"
-      },
-      "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "type": "github"
-      }
-    },
-    "nix": {
-      "inputs": {
-        "lowdown-src": "lowdown-src",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "relaxed-flakes",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nixpkgs": {
-      "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-lib": {
-      "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
-        "type": "github"
-      },
-      "original": {
-        "dir": "lib",
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-stable": {
-      "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-23.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1694345580,
-        "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "master",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
-    "root": {
-      "inputs": {
-        "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    }
-  },
-  "root": "root",
-  "version": 7
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.nix
deleted file mode 100644
index 7239bbc2..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/flake.nix
+++ /dev/null
@@ -1,57 +0,0 @@
-{
-  inputs = {
-    # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
-    nixpkgs.url = "github:NixOS/nixpkgs/master";
-    flake-parts.url = "github:hercules-ci/flake-parts";
-    devenv.url = "github:cachix/devenv";
-  };
-
-  outputs = inputs@{ flake-parts, ... }:
-    flake-parts.lib.mkFlake { inherit inputs; } {
-      imports = [
-        inputs.devenv.flakeModule
-      ];
-
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
-
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-              go.package = pkgs.lib.mkDefault pkgs.go_1_21;
-            };
-
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
-
-          ci = devenv.shells.default;
-
-          ci_1_19 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_19;
-            };
-          };
-
-          ci_1_20 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_20;
-            };
-          };
-
-          ci_1_21 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_21;
-            };
-          };
-        };
-      };
-    };
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/handler.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/handler.go
deleted file mode 100644
index f55556ae..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/handler.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
deleted file mode 100644
index 67005757..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
deleted file mode 100644
index 7c22bd81..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
deleted file mode 100644
index 7b14f10b..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/level.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/level.go
deleted file mode 100644
index 07288cf8..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/level.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/level_120.go
deleted file mode 100644
index d3feb942..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/level_120.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/logger.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/logger.go
deleted file mode 100644
index e80036be..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/logger.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-	"log/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
deleted file mode 100644
index 97ebdd5e..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-
-	"golang.org/x/exp/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/record.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/record.go
deleted file mode 100644
index 85ad1f78..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/record.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/record_120.go
deleted file mode 100644
index c2eaf4e7..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/record_120.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
deleted file mode 100644
index 45f6cfcb..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
deleted file mode 100644
index a69d63cc..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/value.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/value.go
deleted file mode 100644
index 61173eb9..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/value.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/notifier/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/notifier/vendor/github.com/sagikazarmark/slog-shim/value_120.go
deleted file mode 100644
index 0f9f871e..00000000
--- a/notifier/vendor/github.com/sagikazarmark/slog-shim/value_120.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/notifier/vendor/github.com/spf13/cast/README.md b/notifier/vendor/github.com/spf13/cast/README.md
index 58141f02..1be666a4 100644
--- a/notifier/vendor/github.com/spf13/cast/README.md
+++ b/notifier/vendor/github.com/spf13/cast/README.md
@@ -1,9 +1,9 @@
 # cast
 
-[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast)
 ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
-[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast)
+[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast)
 
 Easy and safe casting from one type to another in Go
 
diff --git a/notifier/vendor/github.com/spf13/cast/caste.go b/notifier/vendor/github.com/spf13/cast/caste.go
index d49bbf83..4181a2e7 100644
--- a/notifier/vendor/github.com/spf13/cast/caste.go
+++ b/notifier/vendor/github.com/spf13/cast/caste.go
@@ -18,6 +18,14 @@ import (
 
 var errNegativeNotAllowed = errors.New("unable to cast negative value")
 
+type float64EProvider interface {
+	Float64() (float64, error)
+}
+
+type float64Provider interface {
+	Float64() float64
+}
+
 // ToTimeE casts an interface to a time.Time type.
 func ToTimeE(i interface{}) (tim time.Time, err error) {
 	return ToTimeInDefaultLocationE(i, time.UTC)
@@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
 			d, err = time.ParseDuration(s + "ns")
 		}
 		return
-	case json.Number:
+	case float64EProvider:
 		var v float64
 		v, err = s.Float64()
 		d = time.Duration(v)
 		return
+	case float64Provider:
+		d = time.Duration(s.Float64())
+		return
 	default:
 		err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
 		return
@@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
+	case float64Provider:
+		return s.Float64(), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
+	case float64Provider:
+		return float32(s.Float64()), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) {
 
 	switch s := i.(type) {
 	case string:
-		v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
+		v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0)
 		if err == nil {
 			if v < 0 {
 				return 0, errNegativeNotAllowed
 			}
-			return uint64(v), nil
+			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
 	case json.Number:
@@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
 		return nil
 	}
 
-	var errorType = reflect.TypeOf((*error)(nil)).Elem()
-	var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+	errorType := reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
 
 	v := reflect.ValueOf(a)
 	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
@@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
 
 // ToStringMapStringE casts an interface to a map[string]string type.
 func ToStringMapStringE(i interface{}) (map[string]string, error) {
-	var m = map[string]string{}
+	m := map[string]string{}
 
 	switch v := i.(type) {
 	case map[string]string:
@@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
 
 // ToStringMapStringSliceE casts an interface to a map[string][]string type.
 func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
-	var m = map[string][]string{}
+	m := map[string][]string{}
 
 	switch v := i.(type) {
 	case map[string][]string:
@@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
 
 // ToStringMapBoolE casts an interface to a map[string]bool type.
 func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
-	var m = map[string]bool{}
+	m := map[string]bool{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
 
 // ToStringMapE casts an interface to a map[string]interface{} type.
 func ToStringMapE(i interface{}) (map[string]interface{}, error) {
-	var m = map[string]interface{}{}
+	m := map[string]interface{}{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
 
 // ToStringMapIntE casts an interface to a map[string]int{} type.
 func ToStringMapIntE(i interface{}) (map[string]int, error) {
-	var m = map[string]int{}
+	m := map[string]int{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
 	}
@@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
 
 // ToStringMapInt64E casts an interface to a map[string]int64{} type.
 func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
-	var m = map[string]int64{}
+	m := map[string]int64{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
 	}
@@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
 	return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
 }
 
-var (
-	timeFormats = []timeFormat{
-		// Keep common formats at the top.
-		{"2006-01-02", timeFormatNoTimezone},
-		{time.RFC3339, timeFormatNumericTimezone},
-		{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
-		{time.RFC1123Z, timeFormatNumericTimezone},
-		{time.RFC1123, timeFormatNamedTimezone},
-		{time.RFC822Z, timeFormatNumericTimezone},
-		{time.RFC822, timeFormatNamedTimezone},
-		{time.RFC850, timeFormatNamedTimezone},
-		{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
-		{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
-		{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
-		{"2006-01-02 15:04:05", timeFormatNoTimezone},
-		{time.ANSIC, timeFormatNoTimezone},
-		{time.UnixDate, timeFormatNamedTimezone},
-		{time.RubyDate, timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
-		{"02 Jan 2006", timeFormatNoTimezone},
-		{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
-		{time.Kitchen, timeFormatTimeOnly},
-		{time.Stamp, timeFormatTimeOnly},
-		{time.StampMilli, timeFormatTimeOnly},
-		{time.StampMicro, timeFormatTimeOnly},
-		{time.StampNano, timeFormatTimeOnly},
-	}
-)
+var timeFormats = []timeFormat{
+	// Keep common formats at the top.
+	{"2006-01-02", timeFormatNoTimezone},
+	{time.RFC3339, timeFormatNumericTimezone},
+	{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
+	{time.RFC1123Z, timeFormatNumericTimezone},
+	{time.RFC1123, timeFormatNamedTimezone},
+	{time.RFC822Z, timeFormatNumericTimezone},
+	{time.RFC822, timeFormatNamedTimezone},
+	{time.RFC850, timeFormatNamedTimezone},
+	{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
+	{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
+	{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
+	{"2006-01-02 15:04:05", timeFormatNoTimezone},
+	{time.ANSIC, timeFormatNoTimezone},
+	{time.UnixDate, timeFormatNamedTimezone},
+	{time.RubyDate, timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
+	{"02 Jan 2006", timeFormatNoTimezone},
+	{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
+	{time.Kitchen, timeFormatTimeOnly},
+	{time.Stamp, timeFormatTimeOnly},
+	{time.StampMilli, timeFormatTimeOnly},
+	{time.StampMicro, timeFormatTimeOnly},
+	{time.StampNano, timeFormatTimeOnly},
+}
 
 func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
-
 	for _, format := range formats {
 		if d, e = time.Parse(format.format, s); e == nil {
 
diff --git a/notifier/vendor/github.com/spf13/pflag/README.md b/notifier/vendor/github.com/spf13/pflag/README.md
index 7eacc5bd..388c4e5e 100644
--- a/notifier/vendor/github.com/spf13/pflag/README.md
+++ b/notifier/vendor/github.com/spf13/pflag/README.md
@@ -284,6 +284,33 @@ func main() {
 }
 ```
 
+### Using pflag with go test
+`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`).
+For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details.
+
+For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this:
+```bash
+go test /your/tests -run ^YourTest -v --your-test-pflags
+```
+will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
+To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
+
+**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
+```go
+import (
+	goflag "flag"
+	flag "github.com/spf13/pflag"
+)
+
+var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+
+func main() {
+	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
+    flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
+	flag.Parse()
+}
+```
+
 ## More info
 
 You can see the full reference documentation of the pflag package
diff --git a/notifier/vendor/github.com/spf13/pflag/bool_func.go b/notifier/vendor/github.com/spf13/pflag/bool_func.go
new file mode 100644
index 00000000..83d77afa
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/pflag/bool_func.go
@@ -0,0 +1,40 @@
+package pflag
+
+// -- func Value
+type boolfuncValue func(string) error
+
+func (f boolfuncValue) Set(s string) error { return f(s) }
+
+func (f boolfuncValue) Type() string { return "boolfunc" }
+
+func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+func (f boolfuncValue) IsBoolFlag() bool { return true }
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) {
+	f.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	var val Value = boolfuncValue(fn)
+	flag := f.VarPF(val, name, shorthand, usage)
+	flag.NoOptDefVal = "true"
+}
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func BoolFunc(name string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, shorthand, usage, fn)
+}
diff --git a/notifier/vendor/github.com/spf13/pflag/count.go b/notifier/vendor/github.com/spf13/pflag/count.go
index a0b2679f..d49c0143 100644
--- a/notifier/vendor/github.com/spf13/pflag/count.go
+++ b/notifier/vendor/github.com/spf13/pflag/count.go
@@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
 
 // Count defines a count flag with specified name, default value, and usage string.
 // The return value is the address of an int variable that stores the value of the flag.
-// A count flag will add 1 to its value evey time it is found on the command line
+// A count flag will add 1 to its value every time it is found on the command line
 func Count(name string, usage string) *int {
 	return CommandLine.CountP(name, "", usage)
 }
diff --git a/notifier/vendor/github.com/spf13/pflag/errors.go b/notifier/vendor/github.com/spf13/pflag/errors.go
new file mode 100644
index 00000000..ff11b66b
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/pflag/errors.go
@@ -0,0 +1,149 @@
+package pflag
+
+import "fmt"
+
+// notExistErrorMessageType specifies which flavor of "flag does not exist"
+// is printed by NotExistError. This allows the related errors to be grouped
+// under a single NotExistError struct without making a breaking change to
+// the error message text.
+type notExistErrorMessageType int
+
+const (
+	flagNotExistMessage notExistErrorMessageType = iota
+	flagNotDefinedMessage
+	flagNoSuchFlagMessage
+	flagUnknownFlagMessage
+	flagUnknownShorthandFlagMessage
+)
+
+// NotExistError is the error returned when trying to access a flag that
+// does not exist in the FlagSet.
+type NotExistError struct {
+	name                string
+	specifiedShorthands string
+	messageType         notExistErrorMessageType
+}
+
+// Error implements error.
+func (e *NotExistError) Error() string {
+	switch e.messageType {
+	case flagNotExistMessage:
+		return fmt.Sprintf("flag %q does not exist", e.name)
+
+	case flagNotDefinedMessage:
+		return fmt.Sprintf("flag accessed but not defined: %s", e.name)
+
+	case flagNoSuchFlagMessage:
+		return fmt.Sprintf("no such flag -%v", e.name)
+
+	case flagUnknownFlagMessage:
+		return fmt.Sprintf("unknown flag: --%s", e.name)
+
+	case flagUnknownShorthandFlagMessage:
+		c := rune(e.name[0])
+		return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *NotExistError) GetSpecifiedName() string {
+	return e.name
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *NotExistError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// ValueRequiredError is the error returned when a flag needs an argument but
+// no argument was provided.
+type ValueRequiredError struct {
+	flag                *Flag
+	specifiedName       string
+	specifiedShorthands string
+}
+
+// Error implements error.
+func (e *ValueRequiredError) Error() string {
+	if len(e.specifiedShorthands) > 0 {
+		c := rune(e.specifiedName[0])
+		return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *ValueRequiredError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *ValueRequiredError) GetSpecifiedName() string {
+	return e.specifiedName
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *ValueRequiredError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// InvalidValueError is the error returned when an invalid value is used
+// for a flag.
+type InvalidValueError struct {
+	flag  *Flag
+	value string
+	cause error
+}
+
+// Error implements error.
+func (e *InvalidValueError) Error() string {
+	flag := e.flag
+	var flagName string
+	if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
+		flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
+	} else {
+		flagName = fmt.Sprintf("--%s", flag.Name)
+	}
+	return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
+}
+
+// Unwrap implements errors.Unwrap.
+func (e *InvalidValueError) Unwrap() error {
+	return e.cause
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *InvalidValueError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetValue returns the invalid value that was provided.
+func (e *InvalidValueError) GetValue() string {
+	return e.value
+}
+
+// InvalidSyntaxError is the error returned when a bad flag name is passed on
+// the command line.
+type InvalidSyntaxError struct {
+	specifiedFlag string
+}
+
+// Error implements error.
+func (e *InvalidSyntaxError) Error() string {
+	return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
+}
+
+// GetSpecifiedName returns the exact flag (with dashes) as it
+// appeared in the parsed arguments.
+func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
+	return e.specifiedFlag
+}
diff --git a/notifier/vendor/github.com/spf13/pflag/flag.go b/notifier/vendor/github.com/spf13/pflag/flag.go
index 7c058de3..d4dfbc5e 100644
--- a/notifier/vendor/github.com/spf13/pflag/flag.go
+++ b/notifier/vendor/github.com/spf13/pflag/flag.go
@@ -27,23 +27,32 @@ unaffected.
 Define flags using flag.String(), Bool(), Int(), etc.
 
 This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
+
 	var ip = flag.Int("flagname", 1234, "help message for flagname")
+
 If you like, you can bind the flag to a variable using the Var() functions.
+
 	var flagvar int
 	func init() {
 		flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
 	}
+
 Or you can create custom flags that satisfy the Value interface (with
 pointer receivers) and couple them to flag parsing by
+
 	flag.Var(&flagVal, "name", "help message for flagname")
+
 For such flags, the default value is just the initial value of the variable.
 
 After all flags are defined, call
+
 	flag.Parse()
+
 to parse the command line into the defined flags.
 
 Flags may then be used directly. If you're using the flags themselves,
 they are all pointers; if you bind to variables, they're values.
+
 	fmt.Println("ip has value ", *ip)
 	fmt.Println("flagvar has value ", flagvar)
 
@@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1.
 The pflag package also defines some new functions that are not in flag,
 that give one-letter shorthands for flags. You can use these by appending
 'P' to the name of any function that defines a flag.
+
 	var ip = flag.IntP("flagname", "f", 1234, "help message")
 	var flagvar bool
 	func init() {
 		flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
 	}
 	flag.VarP(&flagval, "varname", "v", "help message")
+
 Shorthand letters can be used with single dashes on the command line.
 Boolean shorthand flags can be combined with other shorthand flags.
 
 Command line flag syntax:
+
 	--flag    // boolean flags only
 	--flag=x
 
 Unlike the flag package, a single dash before an option means something
 different than a double dash. Single dashes signify a series of shorthand
 letters for flags. All but the last shorthand letter must be boolean flags.
+
 	// boolean flags
 	-f
 	-abc
@@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
 func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
 	flag := f.Lookup(name)
 	if flag == nil {
-		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
 		return nil, err
 	}
 
@@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
 func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
 func (f *FlagSet) MarkHidden(name string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	flag.Hidden = true
 	return nil
@@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 
 	err := flag.Value.Set(value)
 	if err != nil {
-		var flagName string
-		if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
-			flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
-		} else {
-			flagName = fmt.Sprintf("--%s", flag.Name)
+		return &InvalidValueError{
+			flag:  flag,
+			value: value,
+			cause: err,
 		}
-		return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
 	}
 
 	if !flag.Changed {
@@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 	if flag.Annotations == nil {
 		flag.Annotations = map[string][]string{}
@@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() {
 func (f *Flag) defaultIsZeroValue() bool {
 	switch f.Value.(type) {
 	case boolFlag:
-		return f.DefValue == "false"
+		return f.DefValue == "false" || f.DefValue == ""
 	case *durationValue:
 		// Beginning in Go 1.7, duration zero values are "0s"
 		return f.DefValue == "0" || f.DefValue == "0s"
@@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool {
 	case *intSliceValue, *stringSliceValue, *stringArrayValue:
 		return f.DefValue == "[]"
 	default:
-		switch f.Value.String() {
+		switch f.DefValue {
 		case "false":
 			return true
 		case "":
@@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
 
 	name = flag.Value.Type()
 	switch name {
-	case "bool":
+	case "bool", "boolfunc":
 		name = ""
+	case "func":
+		name = "value"
 	case "float64":
 		name = "float"
 	case "int64":
@@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 			switch flag.Value.Type() {
 			case "string":
 				line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
-			case "bool":
+			case "bool", "boolfunc":
 				if flag.NoOptDefVal != "true" {
 					line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
 				}
@@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) {
 	CommandLine.VarP(value, name, shorthand, usage)
 }
 
-// failf prints to standard error a formatted error and usage message and
+// fail prints an error message and usage message to standard error and
 // returns the error.
-func (f *FlagSet) failf(format string, a ...interface{}) error {
-	err := fmt.Errorf(format, a...)
+func (f *FlagSet) fail(err error) error {
 	if f.errorHandling != ContinueOnError {
 		fmt.Fprintln(f.Output(), err)
 		f.usage()
@@ -934,9 +946,9 @@ func (f *FlagSet) usage() {
 	}
 }
 
-//--unknown (args will be empty)
-//--unknown --next-flag ... (args will be --next-flag ...)
-//--unknown arg ... (args will be arg ...)
+// --unknown (args will be empty)
+// --unknown --next-flag ... (args will be --next-flag ...)
+// --unknown arg ... (args will be arg ...)
 func stripUnknownFlagValue(args []string) []string {
 	if len(args) == 0 {
 		//--unknown
@@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 	a = args
 	name := s[2:]
 	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
-		err = f.failf("bad flag syntax: %s", s)
+		err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
 		return
 	}
 
@@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 
 			return stripUnknownFlagValue(a), nil
 		default:
-			err = f.failf("unknown flag: --%s", name)
+			err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
 			return
 		}
 	}
@@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 		a = a[1:]
 	} else {
 		// '--flag' (arg was required)
-		err = f.failf("flag needs an argument: %s", s)
+		err = f.fail(&ValueRequiredError{
+			flag:          flag,
+			specifiedName: name,
+		})
 		return
 	}
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
 	outArgs = args
 
-	if strings.HasPrefix(shorthands, "test.") {
+	if isGotestShorthandFlag(shorthands) {
 		return
 	}
 
@@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 			outArgs = stripUnknownFlagValue(outArgs)
 			return
 		default:
-			err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
+			err = f.fail(&NotExistError{
+				name:                string(c),
+				specifiedShorthands: shorthands,
+				messageType:         flagUnknownShorthandFlagMessage,
+			})
 			return
 		}
 	}
@@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 		outArgs = args[1:]
 	} else {
 		// '-f' (arg was required)
-		err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
+		err = f.fail(&ValueRequiredError{
+			flag:                flag,
+			specifiedName:       string(c),
+			specifiedShorthands: shorthands,
+		})
 		return
 	}
 
@@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error {
 	}
 	f.parsed = true
 
-	if len(arguments) < 0 {
+	if len(arguments) == 0 {
 		return nil
 	}
 
diff --git a/notifier/vendor/github.com/spf13/pflag/func.go b/notifier/vendor/github.com/spf13/pflag/func.go
new file mode 100644
index 00000000..9f4d88f2
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/pflag/func.go
@@ -0,0 +1,37 @@
+package pflag
+
+// -- func Value
+type funcValue func(string) error
+
+func (f funcValue) Set(s string) error { return f(s) }
+
+func (f funcValue) Type() string { return "func" }
+
+func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func (f *FlagSet) Func(name string, usage string, fn func(string) error) {
+	f.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) {
+	var val Value = funcValue(fn)
+	f.VarP(val, name, shorthand, usage)
+}
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func Func(name string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func FuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, shorthand, usage, fn)
+}
diff --git a/notifier/vendor/github.com/spf13/pflag/golangflag.go b/notifier/vendor/github.com/spf13/pflag/golangflag.go
index d3dd72b7..f563907e 100644
--- a/notifier/vendor/github.com/spf13/pflag/golangflag.go
+++ b/notifier/vendor/github.com/spf13/pflag/golangflag.go
@@ -10,6 +10,15 @@ import (
 	"strings"
 )
 
+// go test flags prefixes
+func isGotestFlag(flag string) bool {
+	return strings.HasPrefix(flag, "-test.")
+}
+
+func isGotestShorthandFlag(flag string) bool {
+	return strings.HasPrefix(flag, "test.")
+}
+
 // flagValueWrapper implements pflag.Value around a flag.Value.  The main
 // difference here is the addition of the Type method that returns a string
 // name of the type.  As this is generally unknown, we approximate that with
@@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
 	}
 	f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
 }
+
+// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(),
+// since by default those are skipped by pflag.Parse().
+// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)`
+func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
+	var skippedFlags []string
+	for _, f := range osArgs {
+		if isGotestFlag(f) {
+			skippedFlags = append(skippedFlags, f)
+		}
+	}
+	return goFlagSet.Parse(skippedFlags)
+}
diff --git a/notifier/vendor/github.com/spf13/pflag/ipnet_slice.go b/notifier/vendor/github.com/spf13/pflag/ipnet_slice.go
index 6b541aa8..c6e89da1 100644
--- a/notifier/vendor/github.com/spf13/pflag/ipnet_slice.go
+++ b/notifier/vendor/github.com/spf13/pflag/ipnet_slice.go
@@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string {
 
 func ipNetSliceConv(val string) (interface{}, error) {
 	val = strings.Trim(val, "[]")
-	// Emtpy string would cause a slice with one (empty) entry
+	// Empty string would cause a slice with one (empty) entry
 	if len(val) == 0 {
 		return []net.IPNet{}, nil
 	}
diff --git a/notifier/vendor/github.com/spf13/pflag/text.go b/notifier/vendor/github.com/spf13/pflag/text.go
new file mode 100644
index 00000000..886d5a3d
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/pflag/text.go
@@ -0,0 +1,81 @@
+package pflag
+
+import (
+	"encoding"
+	"fmt"
+	"reflect"
+)
+
+// following is copied from go 1.23.4 flag.go
+type textValue struct{ p encoding.TextUnmarshaler }
+
+func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
+	ptrVal := reflect.ValueOf(p)
+	if ptrVal.Kind() != reflect.Ptr {
+		panic("variable value type must be a pointer")
+	}
+	defVal := reflect.ValueOf(val)
+	if defVal.Kind() == reflect.Ptr {
+		defVal = defVal.Elem()
+	}
+	if defVal.Type() != ptrVal.Type().Elem() {
+		panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
+	}
+	ptrVal.Elem().Set(defVal)
+	return textValue{p}
+}
+
+func (v textValue) Set(s string) error {
+	return v.p.UnmarshalText([]byte(s))
+}
+
+func (v textValue) Get() interface{} {
+	return v.p
+}
+
+func (v textValue) String() string {
+	if m, ok := v.p.(encoding.TextMarshaler); ok {
+		if b, err := m.MarshalText(); err == nil {
+			return string(b)
+		}
+	}
+	return ""
+}
+
+//end of copy
+
+func (v textValue) Type() string {
+	return reflect.ValueOf(v.p).Type().Name()
+}
+
+// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
+func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
+	flag := f.Lookup(name)
+	if flag == nil {
+		return fmt.Errorf("flag accessed but not defined: %s", name)
+	}
+	if flag.Value.Type() != reflect.TypeOf(out).Name() {
+		return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
+	}
+	return out.UnmarshalText([]byte(flag.Value.String()))
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, shorthand, usage)
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, shorthand, usage)
+}
diff --git a/notifier/vendor/github.com/spf13/pflag/time.go b/notifier/vendor/github.com/spf13/pflag/time.go
new file mode 100644
index 00000000..dc024807
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/pflag/time.go
@@ -0,0 +1,118 @@
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"time"
+)
+
+// TimeValue adapts time.Time for use as a flag.
+type timeValue struct {
+	*time.Time
+	formats []string
+}
+
+func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue {
+	*p = val
+	return &timeValue{
+		Time:    p,
+		formats: formats,
+	}
+}
+
+// Set time.Time value from string based on accepted formats.
+func (d *timeValue) Set(s string) error {
+	s = strings.TrimSpace(s)
+	for _, f := range d.formats {
+		v, err := time.Parse(f, s)
+		if err != nil {
+			continue
+		}
+		*d.Time = v
+		return nil
+	}
+
+	formatsString := ""
+	for i, f := range d.formats {
+		if i > 0 {
+			formatsString += ", "
+		}
+		formatsString += fmt.Sprintf("`%s`", f)
+	}
+
+	return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString)
+}
+
+// Type name for time.Time flags.
+func (d *timeValue) Type() string {
+	return "time"
+}
+
+func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) }
+
+// GetTime return the time value of a flag with the given name
+func (f *FlagSet) GetTime(name string) (time.Time, error) {
+	flag := f.Lookup(name)
+	if flag == nil {
+		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		return time.Time{}, err
+	}
+
+	if flag.Value.Type() != "time" {
+		err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type())
+		return time.Time{}, err
+	}
+
+	val, ok := flag.Value.(*timeValue)
+	if !ok {
+		return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value)
+	}
+
+	return *val.Time, nil
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	f.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	f.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	CommandLine.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return f.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	p := new(time.Time)
+	f.TimeVarP(p, name, shorthand, value, formats, usage)
+	return p
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, shorthand, value, formats, usage)
+}
diff --git a/notifier/vendor/github.com/spf13/viper/.envrc b/notifier/vendor/github.com/spf13/viper/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/notifier/vendor/github.com/spf13/viper/.envrc
+++ b/notifier/vendor/github.com/spf13/viper/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/notifier/vendor/github.com/spf13/viper/.golangci.yaml b/notifier/vendor/github.com/spf13/viper/.golangci.yaml
index acd9eeba..474f4163 100644
--- a/notifier/vendor/github.com/spf13/viper/.golangci.yaml
+++ b/notifier/vendor/github.com/spf13/viper/.golangci.yaml
@@ -7,8 +7,16 @@ linters-settings:
             - standard
             - default
             - prefix(github.com/spf13/viper)
-    golint:
-        min-confidence: 0
+    gocritic:
+        # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
+        enabled-tags:
+            - diagnostic
+            - experimental
+            - opinionated
+            - style
+        disabled-checks:
+            - importShadow
+            - unnamedResult
     goimports:
         local-prefixes: github.com/spf13/viper
 
@@ -20,8 +28,9 @@ linters:
         - dupl
         - durationcheck
         - exhaustive
-        - exportloopref
         - gci
+        - gocritic
+        - godot
         - gofmt
         - gofumpt
         - goimports
@@ -62,9 +71,7 @@ linters:
         # - gochecknoinits
         # - gocognit
         # - goconst
-        # - gocritic
         # - gocyclo
-        # - godot
         # - gosec
         # - gosimple
         # - ifshort
diff --git a/notifier/vendor/github.com/spf13/viper/README.md b/notifier/vendor/github.com/spf13/viper/README.md
index 78102fbe..769a5d90 100644
--- a/notifier/vendor/github.com/spf13/viper/README.md
+++ b/notifier/vendor/github.com/spf13/viper/README.md
@@ -3,7 +3,8 @@
 >
 > **Thank you!**
 
-![Viper](.github/logo.png?raw=true)
+![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e)
+
 
 [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
 [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
@@ -11,7 +12,7 @@
 [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
 [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-61CFDD.svg?style=flat-square)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
 
 **Go configuration with fangs!**
@@ -39,7 +40,7 @@ Many Go projects are built using Viper including:
 go get github.com/spf13/viper
 ```
 
-**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
+**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
 
 
 ## What is Viper?
@@ -418,7 +419,9 @@ in a Key/Value store such as etcd or Consul.  These values take precedence over
 default values, but are overridden by configuration values retrieved from disk,
 flags, or environment variables.
 
-Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
+Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
+
+Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
 configuration from the K/V store, which means that you can store your
 configuration values encrypted and have them automatically decrypted if you have
 the correct gpg keyring.  Encryption is optional.
@@ -430,7 +433,7 @@ independently of it.
 K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
 
 ```bash
-$ go get github.com/bketelsen/crypt/bin/crypt
+$ go get github.com/sagikazarmark/crypt/bin/crypt
 $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
 ```
 
@@ -563,6 +566,9 @@ 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
 has been provided.
 
+The zero value will also be returned if the value is set, but fails to parse
+as the requested type.
+
 Example:
 ```go
 viper.GetString("logfile") // case-insensitive Setting & Getting
@@ -797,7 +803,7 @@ if err != nil {
 }
 ```
 
-Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
+Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
 
 ### Decoding custom formats
 
@@ -831,13 +837,15 @@ func yamlStringSettings() string {
 
 ## Viper or Vipers?
 
-Viper comes ready to use out of the box. There is no configuration or
-initialization needed to begin using Viper. Since most applications will want
-to use a single central repository for their configuration, the viper package
-provides this. It is similar to a singleton.
+Viper comes with a global instance (singleton) out of the box.
+
+Although it makes setting up configuration easy,
+using it is generally discouraged as it makes testing harder and can lead to unexpected behavior.
+
+The best practice is to initialize a Viper instance and pass that around when necessary.
 
-In all of the examples above, they demonstrate using viper in its singleton
-style approach.
+The global instance _MAY_ be deprecated in the future.
+See [#1855](https://github.com/spf13/viper/issues/1855) for more details.
 
 ### Working with multiple vipers
 
diff --git a/notifier/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/notifier/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
index c4e36c68..b68993d4 100644
--- a/notifier/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
+++ b/notifier/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
@@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
 ```
 
 As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
-Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
+Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
 
 The solution is easy: switch to using Go Modules.
-Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that.
+Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
 
 **tl;dr* `export GO111MODULE=on`
 
diff --git a/notifier/vendor/github.com/spf13/viper/UPDATES.md b/notifier/vendor/github.com/spf13/viper/UPDATES.md
new file mode 100644
index 00000000..ccf413ed
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/UPDATES.md
@@ -0,0 +1,126 @@
+# Update Log
+
+**This document details any major updates required to use new features or improvements in Viper.**
+
+## v1.20.x
+
+### New file searching API
+
+Viper now includes a new file searching API that allows users to customize how Viper looks for config files.
+
+Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation:
+
+```go
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+```
+
+It is supposed to return a list of paths to config files.
+
+The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood.
+
+You can supply your own implementation using `WithFinder`:
+
+```go
+v := viper.NewWithOptions(
+    viper.WithFinder(&MyFinder{}),
+)
+```
+
+For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder)
+and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package.
+
+### New encoding API
+
+Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data:
+
+```go
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+```
+
+By default, Viper includes the following codecs:
+
+- JSON
+- TOML
+- YAML
+- Dotenv
+
+The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding)
+
+Customizing the encoding layer is possible by providing a custom registry of codecs:
+
+- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry)
+- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry)
+- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry)
+
+You can supply the registry of codecs to Viper using the appropriate `With*Registry` function:
+
+```go
+codecRegistry := viper.NewCodecRegistry()
+
+codecRegistry.RegisterCodec("myformat", &MyCodec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
+
+### BREAKING: HCL, Java properties, INI removed from core
+
+In order to reduce third-party dependencies, Viper dropped support for the following formats from the core:
+
+- HCL
+- Java properties
+- INI
+
+You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding):
+
+```go
+import (
+    "github.com/go-viper/encoding/hcl"
+    "github.com/go-viper/encoding/javaproperties"
+    "github.com/go-viper/encoding/ini"
+)
+
+codecRegistry := viper.NewCodecRegistry()
+
+{
+    codec := hcl.Codec{}
+
+    codecRegistry.RegisterCodec("hcl", codec)
+    codecRegistry.RegisterCodec("tfvars", codec)
+
+}
+
+{
+    codec := &javaproperties.Codec{}
+
+    codecRegistry.RegisterCodec("properties", codec)
+    codecRegistry.RegisterCodec("props", codec)
+    codecRegistry.RegisterCodec("prop", codec)
+}
+
+codecRegistry.RegisterCodec("ini", ini.Codec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
diff --git a/notifier/vendor/github.com/spf13/viper/encoding.go b/notifier/vendor/github.com/spf13/viper/encoding.go
new file mode 100644
index 00000000..a7da5586
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/encoding.go
@@ -0,0 +1,181 @@
+package viper
+
+import (
+	"errors"
+	"strings"
+	"sync"
+
+	"github.com/spf13/viper/internal/encoding/dotenv"
+	"github.com/spf13/viper/internal/encoding/json"
+	"github.com/spf13/viper/internal/encoding/toml"
+	"github.com/spf13/viper/internal/encoding/yaml"
+)
+
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+
+// TODO: consider adding specific errors for not found scenarios
+
+// EncoderRegistry returns an [Encoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [EncoderRegistry] returns an error if no [Encoder] is registered for the format.
+type EncoderRegistry interface {
+	Encoder(format string) (Encoder, error)
+}
+
+// DecoderRegistry returns an [Decoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [DecoderRegistry] returns an error if no [Decoder] is registered for the format.
+type DecoderRegistry interface {
+	Decoder(format string) (Decoder, error)
+}
+
+// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces.
+type CodecRegistry interface {
+	EncoderRegistry
+	DecoderRegistry
+}
+
+// WithEncoderRegistry sets a custom [EncoderRegistry].
+func WithEncoderRegistry(r EncoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+	})
+}
+
+// WithDecoderRegistry sets a custom [DecoderRegistry].
+func WithDecoderRegistry(r DecoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.decoderRegistry = r
+	})
+}
+
+// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry].
+func WithCodecRegistry(r CodecRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+		v.decoderRegistry = r
+	})
+}
+
+// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s.
+type DefaultCodecRegistry struct {
+	codecs map[string]Codec
+
+	mu   sync.RWMutex
+	once sync.Once
+}
+
+// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s.
+func NewCodecRegistry() *DefaultCodecRegistry {
+	r := &DefaultCodecRegistry{}
+
+	r.init()
+
+	return r
+}
+
+func (r *DefaultCodecRegistry) init() {
+	r.once.Do(func() {
+		r.codecs = map[string]Codec{}
+	})
+}
+
+// RegisterCodec registers a custom [Codec].
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error {
+	r.init()
+
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	r.codecs[strings.ToLower(format)] = codec
+
+	return nil
+}
+
+// Encoder implements the [EncoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) {
+	encoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("encoder not found for this format")
+	}
+
+	return encoder, nil
+}
+
+// Decoder implements the [DecoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) {
+	decoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("decoder not found for this format")
+	}
+
+	return decoder, nil
+}
+
+func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	format = strings.ToLower(format)
+
+	if r.codecs != nil {
+		codec, ok := r.codecs[format]
+		if ok {
+			return codec, true
+		}
+	}
+
+	switch format {
+	case "yaml", "yml":
+		return yaml.Codec{}, true
+
+	case "json":
+		return json.Codec{}, true
+
+	case "toml":
+		return toml.Codec{}, true
+
+	case "dotenv", "env":
+		return &dotenv.Codec{}, true
+	}
+
+	return nil, false
+}
diff --git a/notifier/vendor/github.com/spf13/viper/experimental.go b/notifier/vendor/github.com/spf13/viper/experimental.go
new file mode 100644
index 00000000..6e19e8a1
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/experimental.go
@@ -0,0 +1,8 @@
+package viper
+
+// ExperimentalBindStruct tells Viper to use the new bind struct feature.
+func ExperimentalBindStruct() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalBindStruct = true
+	})
+}
diff --git a/notifier/vendor/github.com/spf13/viper/file.go b/notifier/vendor/github.com/spf13/viper/file.go
new file mode 100644
index 00000000..50a40581
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/file.go
@@ -0,0 +1,104 @@
+package viper
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/sagikazarmark/locafero"
+	"github.com/spf13/afero"
+)
+
+// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files.
+func ExperimentalFinder() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalFinder = true
+	})
+}
+
+// Search for a config file.
+func (v *Viper) findConfigFile() (string, error) {
+	finder := v.finder
+
+	if finder == nil && v.experimentalFinder {
+		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,
+		}
+	}
+
+	if finder != nil {
+		return v.findConfigFileWithFinder(finder)
+	}
+
+	return v.findConfigFileOld()
+}
+
+func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) {
+	results, err := finder.Find(v.fs)
+	if err != nil {
+		return "", err
+	}
+
+	if len(results) == 0 {
+		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+	}
+
+	// We call clean on the final result to ensure that the path is in its canonical form.
+	// This is mostly for consistent path handling and to make sure tests pass.
+	return results[0], nil
+}
+
+// Search all configPaths for any config file.
+// Returns the first path that exists (and is a config file).
+func (v *Viper) findConfigFileOld() (string, error) {
+	v.logger.Info("searching for config in paths", "paths", v.configPaths)
+
+	for _, cp := range v.configPaths {
+		file := v.searchInPath(cp)
+		if file != "" {
+			return file, nil
+		}
+	}
+	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+}
+
+func (v *Viper) searchInPath(in string) (filename string) {
+	v.logger.Debug("searching for config in path", "path", in)
+	for _, ext := range SupportedExts {
+		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
+			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
+			return filepath.Join(in, v.configName+"."+ext)
+		}
+	}
+
+	if v.configType != "" {
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
+			return filepath.Join(in, v.configName)
+		}
+	}
+
+	return ""
+}
+
+// exists checks if file exists.
+func exists(fs afero.Fs, path string) (bool, error) {
+	stat, err := fs.Stat(path)
+	if err == nil {
+		return !stat.IsDir(), nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
diff --git a/notifier/vendor/github.com/spf13/viper/finder.go b/notifier/vendor/github.com/spf13/viper/finder.go
new file mode 100644
index 00000000..9b203ea6
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/finder.go
@@ -0,0 +1,55 @@
+package viper
+
+import (
+	"errors"
+
+	"github.com/spf13/afero"
+)
+
+// WithFinder sets a custom [Finder].
+func WithFinder(f Finder) Option {
+	return optionFunc(func(v *Viper) {
+		if f == nil {
+			return
+		}
+
+		v.finder = f
+	})
+}
+
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+
+// Finders combines multiple finders into one.
+func Finders(finders ...Finder) Finder {
+	return &combinedFinder{finders: finders}
+}
+
+// combinedFinder is a Finder that combines multiple finders.
+type combinedFinder struct {
+	finders []Finder
+}
+
+// Find implements the [Finder] interface.
+func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) {
+	var results []string
+	var errs []error
+
+	for _, finder := range c.finders {
+		if finder == nil {
+			continue
+		}
+
+		r, err := finder.Find(fsys)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		results = append(results, r...)
+	}
+
+	return results, errors.Join(errs...)
+}
diff --git a/notifier/vendor/github.com/spf13/viper/flags.go b/notifier/vendor/github.com/spf13/viper/flags.go
index ddb4da60..de033ed5 100644
--- a/notifier/vendor/github.com/spf13/viper/flags.go
+++ b/notifier/vendor/github.com/spf13/viper/flags.go
@@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
 }
 
 // pflagValue is a wrapper around *pflag.flag
-// that implements FlagValue
+// that implements FlagValue.
 type pflagValue struct {
 	flag *pflag.Flag
 }
diff --git a/notifier/vendor/github.com/spf13/viper/flake.lock b/notifier/vendor/github.com/spf13/viper/flake.lock
index 78da5109..d76dfbdd 100644
--- a/notifier/vendor/github.com/spf13/viper/flake.lock
+++ b/notifier/vendor/github.com/spf13/viper/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1724763216,
+        "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1687972261,
-        "narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "e85df562088573305e55906eaa964341f8cb0d9f",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1687762428,
-        "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=",
+        "lastModified": 1722555600,
+        "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836",
+        "rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
         "type": "github"
       },
       "original": {
@@ -56,12 +134,33 @@
       }
     },
     "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
       "locked": {
-        "lastModified": 1667395993,
-        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -79,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -92,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
         "nixpkgs": [
           "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
           "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -150,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1685564631,
-        "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=",
+        "lastModified": 1722555339,
+        "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -184,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1678872516,
-        "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-22.11",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1687886075,
-        "narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1724748588,
+        "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "a565059a348422af5af9026b5174dc5c0dcefdae",
+        "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99",
         "type": "github"
       },
       "original": {
@@ -214,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -229,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1686050334,
-        "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -246,7 +433,37 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
       }
     }
   },
diff --git a/notifier/vendor/github.com/spf13/viper/flake.nix b/notifier/vendor/github.com/spf13/viper/flake.nix
index 9b26c3fc..52ad7d58 100644
--- a/notifier/vendor/github.com/spf13/viper/flake.nix
+++ b/notifier/vendor/github.com/spf13/viper/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.go_1_23;
             };
 
             pre-commit.hooks = {
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/decoder.go
deleted file mode 100644
index 8a7b1dbc..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/decoder.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Decoder decodes the contents of b into v.
-// It's primarily used for decoding contents of a file into a map[string]any.
-type Decoder interface {
-	Decode(b []byte, v map[string]any) error
-}
-
-const (
-	// ErrDecoderNotFound is returned when there is no decoder registered for a format.
-	ErrDecoderNotFound = encodingError("decoder not found for this format")
-
-	// ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
-	ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
-)
-
-// DecoderRegistry can choose an appropriate Decoder based on the provided format.
-type DecoderRegistry struct {
-	decoders map[string]Decoder
-
-	mu sync.RWMutex
-}
-
-// NewDecoderRegistry returns a new, initialized DecoderRegistry.
-func NewDecoderRegistry() *DecoderRegistry {
-	return &DecoderRegistry{
-		decoders: make(map[string]Decoder),
-	}
-}
-
-// RegisterDecoder registers a Decoder for a format.
-// Registering a Decoder for an already existing format is not supported.
-func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.decoders[format]; ok {
-		return ErrDecoderFormatAlreadyRegistered
-	}
-
-	e.decoders[format] = enc
-
-	return nil
-}
-
-// Decode calls the underlying Decoder based on the format.
-func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
-	e.mu.RLock()
-	decoder, ok := e.decoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return ErrDecoderNotFound
-	}
-
-	return decoder.Decode(b, v)
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
index 1340c730..8bfe0a9d 100644
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
+++ b/notifier/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
@@ -8,8 +8,8 @@ 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]any, m map[string]any, prefix string, delimiter string) map[string]any {
+// TODO: move it to a common place.
+func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/encoder.go
deleted file mode 100644
index 65958596..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/encoder.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Encoder encodes the contents of v into a byte representation.
-// It's primarily used for encoding a map[string]any into a file format.
-type Encoder interface {
-	Encode(v map[string]any) ([]byte, error)
-}
-
-const (
-	// ErrEncoderNotFound is returned when there is no encoder registered for a format.
-	ErrEncoderNotFound = encodingError("encoder not found for this format")
-
-	// ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format.
-	ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format")
-)
-
-// EncoderRegistry can choose an appropriate Encoder based on the provided format.
-type EncoderRegistry struct {
-	encoders map[string]Encoder
-
-	mu sync.RWMutex
-}
-
-// NewEncoderRegistry returns a new, initialized EncoderRegistry.
-func NewEncoderRegistry() *EncoderRegistry {
-	return &EncoderRegistry{
-		encoders: make(map[string]Encoder),
-	}
-}
-
-// RegisterEncoder registers an Encoder for a format.
-// Registering a Encoder for an already existing format is not supported.
-func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.encoders[format]; ok {
-		return ErrEncoderFormatAlreadyRegistered
-	}
-
-	e.encoders[format] = enc
-
-	return nil
-}
-
-func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
-	e.mu.RLock()
-	encoder, ok := e.encoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return nil, ErrEncoderNotFound
-	}
-
-	return encoder.Encode(v)
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/error.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/error.go
deleted file mode 100644
index e4cde02d..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/error.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package encoding
-
-type encodingError string
-
-func (e encodingError) Error() string {
-	return string(e)
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
deleted file mode 100644
index d7fa8a1b..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package hcl
-
-import (
-	"bytes"
-	"encoding/json"
-
-	"github.com/hashicorp/hcl"
-	"github.com/hashicorp/hcl/hcl/printer"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding.
-// TODO: add printer config to the codec?
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
-	b, err := json.Marshal(v)
-	if err != nil {
-		return nil, err
-	}
-
-	// TODO: use printer.Format? Is the trailing newline an issue?
-
-	ast, err := hcl.Parse(string(b))
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-
-	err = printer.Fprint(&buf, ast.Node)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
-	return hcl.Unmarshal(b, &v)
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
deleted file mode 100644
index d91cf59d..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package ini
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/spf13/cast"
-	"gopkg.in/ini.v1"
-)
-
-// LoadOptions contains all customized options used for load data source(s).
-// This type is added here for convenience: this way consumers can import a single package called "ini".
-type LoadOptions = ini.LoadOptions
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding.
-type Codec struct {
-	KeyDelimiter string
-	LoadOptions  LoadOptions
-}
-
-func (c Codec) Encode(v map[string]any) ([]byte, error) {
-	cfg := ini.Empty()
-	ini.PrettyFormat = false
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		sectionName, keyName := "", key
-
-		lastSep := strings.LastIndex(key, ".")
-		if lastSep != -1 {
-			sectionName = key[:(lastSep)]
-			keyName = key[(lastSep + 1):]
-		}
-
-		// TODO: is this a good idea?
-		if sectionName == "default" {
-			sectionName = ""
-		}
-
-		cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
-	}
-
-	var buf bytes.Buffer
-
-	_, err := cfg.WriteTo(&buf)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (c Codec) Decode(b []byte, v map[string]any) error {
-	cfg := ini.Empty(c.LoadOptions)
-
-	err := cfg.Append(b)
-	if err != nil {
-		return err
-	}
-
-	sections := cfg.Sections()
-
-	for i := 0; i < len(sections); i++ {
-		section := sections[i]
-		keys := section.Keys()
-
-		for j := 0; j < len(keys); j++ {
-			key := keys[j]
-			value := cfg.Section(section.Name()).Key(key.Name()).String()
-
-			deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
-
-			// set innermost value
-			deepestMap[key.Name()] = value
-		}
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
deleted file mode 100644
index c1919a38..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package ini
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
deleted file mode 100644
index e92e5172..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package javaproperties
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/magiconair/properties"
-	"github.com/spf13/cast"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
-type Codec struct {
-	KeyDelimiter string
-
-	// Store read properties on the object so that we can write back in order with comments.
-	// This will only be used if the configuration read is a properties file.
-	// TODO: drop this feature in v2
-	// TODO: make use of the global properties object optional
-	Properties *properties.Properties
-}
-
-func (c *Codec) Encode(v map[string]any) ([]byte, error) {
-	if c.Properties == nil {
-		c.Properties = properties.NewProperties()
-	}
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		_, _, err := c.Properties.Set(key, cast.ToString(flattened[key]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	var buf bytes.Buffer
-
-	_, err := c.Properties.WriteComment(&buf, "#", properties.UTF8)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-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 {
-		return err
-	}
-
-	for _, key := range c.Properties.Keys() {
-		// ignore existence check: we know it's there
-		value, _ := c.Properties.Get(key)
-
-		// recursively build nested maps
-		path := strings.Split(key, c.keyDelimiter())
-		lastKey := strings.ToLower(path[len(path)-1])
-		deepestMap := deepSearch(v, path[0:len(path)-1])
-
-		// set innermost value
-		deepestMap[lastKey] = value
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
deleted file mode 100644
index 8386920a..00000000
--- a/notifier/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package javaproperties
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct.go b/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct.go
new file mode 100644
index 00000000..89302c21
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct.go
@@ -0,0 +1,5 @@
+//go:build viper_bind_struct
+
+package features
+
+const BindStruct = true
diff --git a/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go b/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
new file mode 100644
index 00000000..edfaf73b
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_bind_struct
+
+package features
+
+const BindStruct = false
diff --git a/notifier/vendor/github.com/spf13/viper/internal/features/finder.go b/notifier/vendor/github.com/spf13/viper/internal/features/finder.go
new file mode 100644
index 00000000..983ea3a9
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/internal/features/finder.go
@@ -0,0 +1,5 @@
+//go:build viper_finder
+
+package features
+
+const Finder = true
diff --git a/notifier/vendor/github.com/spf13/viper/internal/features/finder_default.go b/notifier/vendor/github.com/spf13/viper/internal/features/finder_default.go
new file mode 100644
index 00000000..89bcb06e
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/internal/features/finder_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_finder
+
+package features
+
+const Finder = false
diff --git a/notifier/vendor/github.com/spf13/viper/logger.go b/notifier/vendor/github.com/spf13/viper/logger.go
index 8938053b..828042f2 100644
--- a/notifier/vendor/github.com/spf13/viper/logger.go
+++ b/notifier/vendor/github.com/spf13/viper/logger.go
@@ -2,46 +2,9 @@ package viper
 
 import (
 	"context"
-
-	slog "github.com/sagikazarmark/slog-shim"
+	"log/slog"
 )
 
-// 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 ...any)
-
-	// Debug logs a Debug event.
-	//
-	// A verbose series of information events.
-	// They are useful when debugging the system.
-	Debug(msg string, keyvals ...any)
-
-	// Info logs an Info event.
-	//
-	// General information about what's happening inside the system.
-	Info(msg string, keyvals ...any)
-
-	// Warn logs a Warn(ing) event.
-	//
-	// Non-critical events that should be looked at.
-	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 ...any)
-}
-
 // WithLogger sets a custom logger.
 func WithLogger(l *slog.Logger) Option {
 	return optionFunc(func(v *Viper) {
diff --git a/notifier/vendor/github.com/spf13/viper/remote.go b/notifier/vendor/github.com/spf13/viper/remote.go
new file mode 100644
index 00000000..bdde7de2
--- /dev/null
+++ b/notifier/vendor/github.com/spf13/viper/remote.go
@@ -0,0 +1,256 @@
+package viper
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"slices"
+)
+
+// SupportedRemoteProviders are universally supported remote providers.
+var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+
+func resetRemote() {
+	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+}
+
+type remoteConfigFactory interface {
+	Get(rp RemoteProvider) (io.Reader, error)
+	Watch(rp RemoteProvider) (io.Reader, error)
+	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
+}
+
+type RemoteResponse struct {
+	Value []byte
+	Error error
+}
+
+// RemoteConfig is optional, see the remote package.
+var RemoteConfig remoteConfigFactory
+
+// UnsupportedRemoteProviderError denotes encountering an unsupported remote
+// provider. Currently only etcd and Consul are supported.
+type UnsupportedRemoteProviderError string
+
+// Error returns the formatted remote provider error.
+func (str UnsupportedRemoteProviderError) Error() string {
+	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
+}
+
+// RemoteConfigError denotes encountering an error while trying to
+// pull the configuration from the remote provider.
+type RemoteConfigError string
+
+// Error returns the formatted remote provider error.
+func (rce RemoteConfigError) Error() string {
+	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
+}
+
+type defaultRemoteProvider struct {
+	provider      string
+	endpoint      string
+	path          string
+	secretKeyring string
+}
+
+func (rp defaultRemoteProvider) Provider() string {
+	return rp.provider
+}
+
+func (rp defaultRemoteProvider) Endpoint() string {
+	return rp.endpoint
+}
+
+func (rp defaultRemoteProvider) Path() string {
+	return rp.path
+}
+
+func (rp defaultRemoteProvider) SecretKeyring() string {
+	return rp.secretKeyring
+}
+
+// RemoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type RemoteProvider interface {
+	Provider() string
+	Endpoint() string
+	Path() string
+	SecretKeyring() string
+}
+
+// AddRemoteProvider adds a remote configuration source.
+// Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+func AddRemoteProvider(provider, endpoint, path string) error {
+	return v.AddRemoteProvider(provider, endpoint, path)
+}
+
+func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint: endpoint,
+			provider: provider,
+			path:     path,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+// AddSecureRemoteProvider adds a remote configuration source.
+// Secure Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
+// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
+func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
+}
+
+func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint:      endpoint,
+			provider:      provider,
+			path:          path,
+			secretKeyring: secretkeyring,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
+	for _, y := range v.remoteProviders {
+		if reflect.DeepEqual(y, p) {
+			return true
+		}
+	}
+	return false
+}
+
+// ReadRemoteConfig attempts to get configuration from a remote source
+// and read it in the remote configuration registry.
+func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
+
+func (v *Viper) ReadRemoteConfig() error {
+	return v.getKeyValueConfig()
+}
+
+func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
+func (v *Viper) WatchRemoteConfig() error {
+	return v.watchKeyValueConfig()
+}
+
+func (v *Viper) WatchRemoteConfigOnChannel() error {
+	return v.watchKeyValueConfigOnChannel()
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) getKeyValueConfig() error {
+	if RemoteConfig == nil {
+		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
+	}
+
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.getRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
+
+			continue
+		}
+
+		v.kvstore = val
+
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Get(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfigOnChannel() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		respc, _ := RemoteConfig.WatchChannel(rp)
+		// Todo: Add quit channel
+		go func(rc <-chan *RemoteResponse) {
+			for {
+				b := <-rc
+				reader := bytes.NewReader(b.Value)
+				v.unmarshalReader(reader, v.kvstore)
+			}
+		}(respc)
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfig() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.watchRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
+
+			continue
+		}
+		v.kvstore = val
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Watch(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
diff --git a/notifier/vendor/github.com/spf13/viper/util.go b/notifier/vendor/github.com/spf13/viper/util.go
index 52116ac4..2a08074b 100644
--- a/notifier/vendor/github.com/spf13/viper/util.go
+++ b/notifier/vendor/github.com/spf13/viper/util.go
@@ -12,13 +12,13 @@ package viper
 
 import (
 	"fmt"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"runtime"
 	"strings"
 	"unicode"
 
-	slog "github.com/sagikazarmark/slog-shim"
 	"github.com/spf13/cast"
 )
 
@@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string {
 	return ""
 }
 
-func stringInSlice(a string, list []string) bool {
-	for _, b := range list {
-		if b == a {
-			return true
-		}
-	}
-	return false
-}
-
 func userHomeDir() string {
 	if runtime.GOOS == "windows" {
 		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
@@ -156,7 +147,7 @@ func safeMul(a, b uint) uint {
 	return c
 }
 
-// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
+// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
 func parseSizeInBytes(sizeStr string) uint {
 	sizeStr = strings.TrimSpace(sizeStr)
 	lastChar := len(sizeStr) - 1
diff --git a/notifier/vendor/github.com/spf13/viper/viper.go b/notifier/vendor/github.com/spf13/viper/viper.go
index c1eab71b..a58d757b 100644
--- a/notifier/vendor/github.com/spf13/viper/viper.go
+++ b/notifier/vendor/github.com/spf13/viper/viper.go
@@ -25,29 +25,23 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"reflect"
+	"slices"
 	"strconv"
 	"strings"
 	"sync"
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"github.com/mitchellh/mapstructure"
-	slog "github.com/sagikazarmark/slog-shim"
+	"github.com/go-viper/mapstructure/v2"
 	"github.com/spf13/afero"
 	"github.com/spf13/cast"
 	"github.com/spf13/pflag"
 
-	"github.com/spf13/viper/internal/encoding"
-	"github.com/spf13/viper/internal/encoding/dotenv"
-	"github.com/spf13/viper/internal/encoding/hcl"
-	"github.com/spf13/viper/internal/encoding/ini"
-	"github.com/spf13/viper/internal/encoding/javaproperties"
-	"github.com/spf13/viper/internal/encoding/json"
-	"github.com/spf13/viper/internal/encoding/toml"
-	"github.com/spf13/viper/internal/encoding/yaml"
+	"github.com/spf13/viper/internal/features"
 )
 
 // ConfigMarshalError happens when failing to marshal the configuration.
@@ -62,24 +56,10 @@ func (e ConfigMarshalError) Error() string {
 
 var v *Viper
 
-type RemoteResponse struct {
-	Value []byte
-	Error error
-}
-
 func init() {
 	v = New()
 }
 
-type remoteConfigFactory interface {
-	Get(rp RemoteProvider) (io.Reader, error)
-	Watch(rp RemoteProvider) (io.Reader, error)
-	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
-}
-
-// RemoteConfig is optional, see the remote package
-var RemoteConfig remoteConfigFactory
-
 // UnsupportedConfigError denotes encountering an unsupported
 // configuration filetype.
 type UnsupportedConfigError string
@@ -89,24 +69,6 @@ func (str UnsupportedConfigError) Error() string {
 	return fmt.Sprintf("Unsupported Config Type %q", string(str))
 }
 
-// UnsupportedRemoteProviderError denotes encountering an unsupported remote
-// provider. Currently only etcd and Consul are supported.
-type UnsupportedRemoteProviderError string
-
-// Error returns the formatted remote provider error.
-func (str UnsupportedRemoteProviderError) Error() string {
-	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
-}
-
-// RemoteConfigError denotes encountering an error while trying to
-// pull the configuration from the remote provider.
-type RemoteConfigError string
-
-// Error returns the formatted remote provider error
-func (rce RemoteConfigError) Error() string {
-	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
-}
-
 // ConfigFileNotFoundError denotes failing to find configuration file.
 type ConfigFileNotFoundError struct {
 	name, locations string
@@ -126,7 +88,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string {
 }
 
 // A DecoderConfigOption can be passed to viper.Unmarshal to configure
-// mapstructure.DecoderConfig options
+// mapstructure.DecoderConfig options.
 type DecoderConfigOption func(*mapstructure.DecoderConfig)
 
 // DecodeHook returns a DecoderConfigOption which overrides the default
@@ -189,6 +151,8 @@ type Viper struct {
 	// The filesystem to read config from.
 	fs afero.Fs
 
+	finder Finder
+
 	// A set of remote providers to search for the configuration
 	remoteProviders []*defaultRemoteProvider
 
@@ -199,9 +163,6 @@ type Viper struct {
 	configPermissions os.FileMode
 	envPrefix         string
 
-	// Specific commands for ini parsing
-	iniLoadOptions ini.LoadOptions
-
 	automaticEnvApplied bool
 	envKeyReplacer      StringReplacer
 	allowEmptyEnv       bool
@@ -220,9 +181,13 @@ type Viper struct {
 
 	logger *slog.Logger
 
-	// TODO: should probably be protected with a mutex
-	encoderRegistry *encoding.EncoderRegistry
-	decoderRegistry *encoding.DecoderRegistry
+	encoderRegistry EncoderRegistry
+	decoderRegistry DecoderRegistry
+
+	decodeHook mapstructure.DecodeHookFunc
+
+	experimentalFinder     bool
+	experimentalBindStruct bool
 }
 
 // New returns an initialized Viper instance.
@@ -243,7 +208,13 @@ func New() *Viper {
 	v.typeByDefValue = false
 	v.logger = slog.New(&discardHandler{})
 
-	v.resetEncoding()
+	codecRegistry := NewCodecRegistry()
+
+	v.encoderRegistry = codecRegistry
+	v.decoderRegistry = codecRegistry
+
+	v.experimentalFinder = features.Finder
+	v.experimentalBindStruct = features.BindStruct
 
 	return v
 }
@@ -279,10 +250,25 @@ type StringReplacer interface {
 // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys.
 func EnvKeyReplacer(r StringReplacer) Option {
 	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
 		v.envKeyReplacer = r
 	})
 }
 
+// WithDecodeHook sets a default decode hook for mapstructure.
+func WithDecodeHook(h mapstructure.DecodeHookFunc) Option {
+	return optionFunc(func(v *Viper) {
+		if h == nil {
+			return
+		}
+
+		v.decodeHook = h
+	})
+}
+
 // NewWithOptions creates a new Viper instance.
 func NewWithOptions(opts ...Option) *Viper {
 	v := New()
@@ -291,138 +277,32 @@ func NewWithOptions(opts ...Option) *Viper {
 		opt.apply(v)
 	}
 
-	v.resetEncoding()
-
 	return v
 }
 
+// SetOptions sets the options on the global Viper instance.
+//
+// Be careful when using this function: subsequent calls may override options you set.
+// It's always better to use a local Viper instance.
+func SetOptions(opts ...Option) {
+	for _, opt := range opts {
+		opt.apply(v)
+	}
+}
+
 // Reset is intended for testing, will reset all to default settings.
 // In the public interface for the viper package so applications
 // can use it in their testing as well.
 func Reset() {
 	v = New()
 	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
-	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-}
-
-// TODO: make this lazy initialization instead
-func (v *Viper) resetEncoding() {
-	encoderRegistry := encoding.NewEncoderRegistry()
-	decoderRegistry := encoding.NewDecoderRegistry()
-
-	{
-		codec := yaml.Codec{}
-
-		encoderRegistry.RegisterEncoder("yaml", codec)
-		decoderRegistry.RegisterDecoder("yaml", codec)
-
-		encoderRegistry.RegisterEncoder("yml", codec)
-		decoderRegistry.RegisterDecoder("yml", codec)
-	}
-
-	{
-		codec := json.Codec{}
-
-		encoderRegistry.RegisterEncoder("json", codec)
-		decoderRegistry.RegisterDecoder("json", codec)
-	}
-
-	{
-		codec := toml.Codec{}
-
-		encoderRegistry.RegisterEncoder("toml", codec)
-		decoderRegistry.RegisterDecoder("toml", codec)
-	}
-
-	{
-		codec := hcl.Codec{}
-
-		encoderRegistry.RegisterEncoder("hcl", codec)
-		decoderRegistry.RegisterDecoder("hcl", codec)
-
-		encoderRegistry.RegisterEncoder("tfvars", codec)
-		decoderRegistry.RegisterDecoder("tfvars", codec)
-	}
-
-	{
-		codec := ini.Codec{
-			KeyDelimiter: v.keyDelim,
-			LoadOptions:  v.iniLoadOptions,
-		}
-
-		encoderRegistry.RegisterEncoder("ini", codec)
-		decoderRegistry.RegisterDecoder("ini", codec)
-	}
-
-	{
-		codec := &javaproperties.Codec{
-			KeyDelimiter: v.keyDelim,
-		}
-
-		encoderRegistry.RegisterEncoder("properties", codec)
-		decoderRegistry.RegisterDecoder("properties", codec)
-
-		encoderRegistry.RegisterEncoder("props", codec)
-		decoderRegistry.RegisterDecoder("props", codec)
-
-		encoderRegistry.RegisterEncoder("prop", codec)
-		decoderRegistry.RegisterDecoder("prop", codec)
-	}
-
-	{
-		codec := &dotenv.Codec{}
 
-		encoderRegistry.RegisterEncoder("dotenv", codec)
-		decoderRegistry.RegisterDecoder("dotenv", codec)
-
-		encoderRegistry.RegisterEncoder("env", codec)
-		decoderRegistry.RegisterDecoder("env", codec)
-	}
-
-	v.encoderRegistry = encoderRegistry
-	v.decoderRegistry = decoderRegistry
-}
-
-type defaultRemoteProvider struct {
-	provider      string
-	endpoint      string
-	path          string
-	secretKeyring string
-}
-
-func (rp defaultRemoteProvider) Provider() string {
-	return rp.provider
-}
-
-func (rp defaultRemoteProvider) Endpoint() string {
-	return rp.endpoint
-}
-
-func (rp defaultRemoteProvider) Path() string {
-	return rp.path
-}
-
-func (rp defaultRemoteProvider) SecretKeyring() string {
-	return rp.secretKeyring
-}
-
-// RemoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type RemoteProvider interface {
-	Provider() string
-	Endpoint() string
-	Path() string
-	SecretKeyring() string
+	resetRemote()
 }
 
 // SupportedExts are universally supported extensions.
 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
 
-// SupportedRemoteProviders are universally supported remote providers.
-var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-
 // OnConfigChange sets the event handler that is called when a config file changes.
 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
 
@@ -439,7 +319,7 @@ func (v *Viper) WatchConfig() {
 	initWG := sync.WaitGroup{}
 	initWG.Add(1)
 	go func() {
-		watcher, err := newWatcher()
+		watcher, err := fsnotify.NewWatcher()
 		if err != nil {
 			v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
 			os.Exit(1)
@@ -573,90 +453,20 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile }
 func AddConfigPath(in string) { v.AddConfigPath(in) }
 
 func (v *Viper) AddConfigPath(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath"))
+	}
+
 	if in != "" {
 		absin := absPathify(v.logger, in)
 
 		v.logger.Info("adding path to search paths", "path", absin)
-		if !stringInSlice(absin, v.configPaths) {
+		if !slices.Contains(v.configPaths, absin) {
 			v.configPaths = append(v.configPaths, absin)
 		}
 	}
 }
 
-// AddRemoteProvider adds a remote configuration source.
-// Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-func AddRemoteProvider(provider, endpoint, path string) error {
-	return v.AddRemoteProvider(provider, endpoint, path)
-}
-
-func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint: endpoint,
-			provider: provider,
-			path:     path,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-// AddSecureRemoteProvider adds a remote configuration source.
-// Secure Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
-// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-// Secure Remote Providers are implemented with github.com/bketelsen/crypt
-func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
-}
-
-func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint:      endpoint,
-			provider:      provider,
-			path:          path,
-			secretKeyring: secretkeyring,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
-	for _, y := range v.remoteProviders {
-		if reflect.DeepEqual(y, p) {
-			return true
-		}
-	}
-	return false
-}
-
 // 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.
@@ -827,10 +637,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string
 //	"foo.bar.baz" in a lower-priority map
 func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
 	// unify input map
-	var m map[string]any
-	switch mi.(type) {
-	case map[string]string, map[string]FlagValue:
-		m = cast.ToStringMap(mi)
+	var m map[string]interface{}
+	switch miv := mi.(type) {
+	case map[string]string:
+		m = castMapStringToMapInterface(miv)
+	case map[string]FlagValue:
+		m = castMapFlagToMapInterface(miv)
 	default:
 		return ""
 	}
@@ -957,10 +769,12 @@ func (v *Viper) Sub(key string) *Viper {
 	}
 
 	if reflect.TypeOf(data).Kind() == reflect.Map {
-		subv.parents = append(v.parents, strings.ToLower(key))
+		subv.parents = append([]string(nil), v.parents...)
+		subv.parents = append(subv.parents, strings.ToLower(key))
 		subv.automaticEnvApplied = v.automaticEnvApplied
 		subv.envPrefix = v.envPrefix
 		subv.envKeyReplacer = v.envKeyReplacer
+		subv.keyDelim = v.keyDelim
 		subv.config = cast.ToStringMap(data)
 		return subv
 	}
@@ -1002,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 {
 	return cast.ToInt64(v.Get(key))
 }
 
+// GetUint8 returns the value associated with the key as an unsigned integer.
+func GetUint8(key string) uint8 { return v.GetUint8(key) }
+
+func (v *Viper) GetUint8(key string) uint8 {
+	return cast.ToUint8(v.Get(key))
+}
+
 // GetUint returns the value associated with the key as an unsigned integer.
 func GetUint(key string) uint { return v.GetUint(key) }
 
@@ -1101,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
+	return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...))
 }
 
 // Unmarshal unmarshals the config into a Struct. Make sure that the tags
@@ -1111,28 +932,91 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...))
+}
+
+func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
+	var structKeyMap map[string]any
+
+	err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...))
+	if err != nil {
+		return nil, err
+	}
+
+	flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
+
+	r := make([]string, 0, len(flattenedStructKeyMap))
+	for v := range flattenedStructKeyMap {
+		r = append(r, v)
+	}
+
+	return r, nil
 }
 
 // defaultDecoderConfig returns default mapstructure.DecoderConfig with support
-// of time.Duration values & string slices
-func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+// of time.Duration values & string slices.
+func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+	decodeHook := v.decodeHook
+	if decodeHook == nil {
+		decodeHook = mapstructure.ComposeDecodeHookFunc(
+			mapstructure.StringToTimeDurationHookFunc(),
+			// mapstructure.StringToSliceHookFunc(","),
+			stringToWeakSliceHookFunc(","),
+		)
+	}
+
 	c := &mapstructure.DecoderConfig{
 		Metadata:         nil,
-		Result:           output,
 		WeaklyTypedInput: true,
-		DecodeHook: mapstructure.ComposeDecodeHookFunc(
-			mapstructure.StringToTimeDurationHookFunc(),
-			mapstructure.StringToSliceHookFunc(","),
-		),
+		DecodeHook:       decodeHook,
 	}
+
 	for _, opt := range opts {
 		opt(c)
 	}
+
+	// Do not allow overwriting the output
+	c.Result = output
+
 	return c
 }
 
-// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
+// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice.
+// This function removes that check.
+// TODO: implement a function that checks if the value can be converted to the return type and use it instead.
+func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data interface{},
+	) (interface{}, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
+// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
 func decode(input any, config *mapstructure.DecoderConfig) error {
 	decoder, err := mapstructure.NewDecoder(config)
 	if err != nil {
@@ -1148,10 +1032,23 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
-	config := defaultDecoderConfig(rawVal, opts...)
+	config := v.defaultDecoderConfig(rawVal, opts...)
 	config.ErrorUnused = true
 
-	return decode(v.AllSettings(), config)
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), config)
 }
 
 // BindPFlags binds a full flag set to the configuration, using each flag's long
@@ -1405,11 +1302,11 @@ 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	r := csv.NewReader(strings.NewReader(val))
@@ -1429,11 +1326,11 @@ func stringToStringConv(val string) any {
 }
 
 // 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	ss := strings.Split(val, ",")
@@ -1481,13 +1378,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
 
 // RegisterAlias creates an alias that provides another accessor for the same key.
 // This enables one to change a name without breaking the application.
-func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
+func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
 
-func (v *Viper) RegisterAlias(alias string, key string) {
+func (v *Viper) RegisterAlias(alias, key string) {
 	v.registerAlias(alias, strings.ToLower(key))
 }
 
-func (v *Viper) registerAlias(alias string, key string) {
+func (v *Viper) registerAlias(alias, key string) {
 	alias = strings.ToLower(alias)
 	if alias != key && alias != v.realKey(key) {
 		_, exists := v.aliases[alias]
@@ -1590,7 +1487,7 @@ func (v *Viper) ReadInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1621,7 +1518,7 @@ func (v *Viper) MergeInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1638,19 +1535,29 @@ 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]any)
-	return v.unmarshalReader(in, v.config)
+	config := make(map[string]any)
+
+	err := v.unmarshalReader(in, config)
+	if err != nil {
+		return err
+	}
+
+	v.config = config
+
+	return nil
 }
 
 // MergeConfig merges a new configuration with an existing config.
 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
 
 func (v *Viper) MergeConfig(in io.Reader) error {
-	cfg := make(map[string]any)
-	if err := v.unmarshalReader(in, cfg); err != nil {
+	config := make(map[string]any)
+
+	if err := v.unmarshalReader(in, config); err != nil {
 		return err
 	}
-	return v.MergeConfigMap(cfg)
+
+	return v.MergeConfigMap(config)
 }
 
 // MergeConfigMap merges the configuration from the map given with an existing config.
@@ -1694,6 +1601,19 @@ func (v *Viper) WriteConfigAs(filename string) error {
 	return v.writeConfig(filename, true)
 }
 
+// WriteConfigTo writes current configuration to an [io.Writer].
+func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) }
+
+func (v *Viper) WriteConfigTo(w io.Writer) error {
+	format := strings.ToLower(v.getConfigType())
+
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	return v.marshalWriter(w, format)
+}
+
 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
 
@@ -1720,7 +1640,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 		return fmt.Errorf("config type could not be determined for %s", filename)
 	}
 
-	if !stringInSlice(configType, SupportedExts) {
+	if !slices.Contains(SupportedExts, configType) {
 		return UnsupportedConfigError(configType)
 	}
 	if v.config == nil {
@@ -1743,22 +1663,30 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 	return f.Sync()
 }
 
-// Unmarshal a Reader into a map.
-// Should probably be an unexported function.
-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]any) error {
+	format := strings.ToLower(v.getConfigType())
+	if format == "" {
+		return errors.New("cannot decode configuration: unable to determine config type")
+	}
+
 	buf := new(bytes.Buffer)
 	buf.ReadFrom(in)
 
-	switch format := strings.ToLower(v.getConfigType()); format {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
-		err := v.decoderRegistry.Decode(format, buf.Bytes(), c)
-		if err != nil {
-			return ConfigParseError{err}
-		}
+	// TODO: remove this once SupportedExts is deprecated/removed
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	// TODO: return [UnsupportedConfigError] if the registry does not contain the format
+	// TODO: consider deprecating this error type
+	decoder, err := v.decoderRegistry.Decoder(format)
+	if err != nil {
+		return ConfigParseError{err}
+	}
+
+	err = decoder.Decode(buf.Bytes(), c)
+	if err != nil {
+		return ConfigParseError{err}
 	}
 
 	insensitiviseMap(c)
@@ -1766,20 +1694,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
 }
 
 // Marshal a map into Writer.
-func (v *Viper) marshalWriter(f afero.File, configType string) error {
+func (v *Viper) marshalWriter(w io.Writer, configType string) error {
 	c := v.AllSettings()
-	switch configType {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
-		b, err := v.encoderRegistry.Encode(configType, c)
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
 
-		_, err = f.WriteString(string(b))
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
+	encoder, err := v.encoderRegistry.Encoder(configType)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	b, err := encoder.Encode(c)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	_, err = w.Write(b)
+	if err != nil {
+		return ConfigMarshalError{err}
 	}
+
 	return nil
 }
 
@@ -1911,108 +1843,8 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
 	}
 }
 
-// ReadRemoteConfig attempts to get configuration from a remote source
-// and read it in the remote configuration registry.
-func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
-
-func (v *Viper) ReadRemoteConfig() error {
-	return v.getKeyValueConfig()
-}
-
-func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
-func (v *Viper) WatchRemoteConfig() error {
-	return v.watchKeyValueConfig()
-}
-
-func (v *Viper) WatchRemoteConfigOnChannel() error {
-	return v.watchKeyValueConfigOnChannel()
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) getKeyValueConfig() error {
-	if RemoteConfig == nil {
-		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
-	}
-
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.getRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
-
-			continue
-		}
-
-		v.kvstore = val
-
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Get(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfigOnChannel() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		respc, _ := RemoteConfig.WatchChannel(rp)
-		// Todo: Add quit channel
-		go func(rc <-chan *RemoteResponse) {
-			for {
-				b := <-rc
-				reader := bytes.NewReader(b.Value)
-				v.unmarshalReader(reader, v.kvstore)
-			}
-		}(respc)
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfig() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.watchRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
-
-			continue
-		}
-		v.kvstore = val
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Watch(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
 // AllKeys returns all keys holding a value, regardless of where they are set.
-// Nested keys are returned with a v.keyDelim separator
+// Nested keys are returned with a v.keyDelim separator.
 func AllKeys() []string { return v.AllKeys() }
 
 func (v *Viper) AllKeys() []string {
@@ -2098,9 +1930,13 @@ outer:
 func AllSettings() map[string]any { return v.AllSettings() }
 
 func (v *Viper) AllSettings() map[string]any {
+	return v.getSettings(v.AllKeys())
+}
+
+func (v *Viper) getSettings(keys []string) 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() {
+	for _, k := range keys {
 		value := v.Get(k)
 		if value == nil {
 			// should not happen, since AllKeys() returns only keys holding a value,
@@ -2128,6 +1964,10 @@ func (v *Viper) SetFs(fs afero.Fs) {
 func SetConfigName(in string) { v.SetConfigName(in) }
 
 func (v *Viper) SetConfigName(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName"))
+	}
+
 	if in != "" {
 		v.configName = in
 		v.configFile = ""
@@ -2151,13 +1991,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) {
 	v.configPermissions = perm.Perm()
 }
 
-// IniLoadOptions sets the load options for ini parsing.
-func IniLoadOptions(in ini.LoadOptions) Option {
-	return optionFunc(func(v *Viper) {
-		v.iniLoadOptions = in
-	})
-}
-
 func (v *Viper) getConfigType() string {
 	if v.configType != "" {
 		return v.configType
diff --git a/notifier/vendor/github.com/spf13/viper/viper_go1_15.go b/notifier/vendor/github.com/spf13/viper/viper_go1_15.go
deleted file mode 100644
index 7fc6aff3..00000000
--- a/notifier/vendor/github.com/spf13/viper/viper_go1_15.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build !finder
-
-package viper
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-
-	"github.com/spf13/afero"
-)
-
-// Search all configPaths for any config file.
-// Returns the first path that exists (and is a config file).
-func (v *Viper) findConfigFile() (string, error) {
-	v.logger.Info("searching for config in paths", "paths", v.configPaths)
-
-	for _, cp := range v.configPaths {
-		file := v.searchInPath(cp)
-		if file != "" {
-			return file, nil
-		}
-	}
-	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-}
-
-func (v *Viper) searchInPath(in string) (filename string) {
-	v.logger.Debug("searching for config in path", "path", in)
-	for _, ext := range SupportedExts {
-		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
-			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
-			return filepath.Join(in, v.configName+"."+ext)
-		}
-	}
-
-	if v.configType != "" {
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
-			return filepath.Join(in, v.configName)
-		}
-	}
-
-	return ""
-}
-
-// Check if file Exists
-func exists(fs afero.Fs, path string) (bool, error) {
-	stat, err := fs.Stat(path)
-	if err == nil {
-		return !stat.IsDir(), nil
-	}
-	if os.IsNotExist(err) {
-		return false, nil
-	}
-	return false, err
-}
diff --git a/notifier/vendor/github.com/spf13/viper/viper_go1_16.go b/notifier/vendor/github.com/spf13/viper/viper_go1_16.go
deleted file mode 100644
index d96a1bd2..00000000
--- a/notifier/vendor/github.com/spf13/viper/viper_go1_16.go
+++ /dev/null
@@ -1,38 +0,0 @@
-//go:build finder
-
-package viper
-
-import (
-	"fmt"
-
-	"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) {
-	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,
-	}
-
-	results, err := finder.Find(v.fs)
-	if err != nil {
-		return "", err
-	}
-
-	if len(results) == 0 {
-		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-	}
-
-	return results[0], nil
-}
diff --git a/notifier/vendor/github.com/spf13/viper/watch.go b/notifier/vendor/github.com/spf13/viper/watch.go
deleted file mode 100644
index e98fce89..00000000
--- a/notifier/vendor/github.com/spf13/viper/watch.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
-
-package viper
-
-import "github.com/fsnotify/fsnotify"
-
-type watcher = fsnotify.Watcher
-
-func newWatcher() (*watcher, error) {
-	return fsnotify.NewWatcher()
-}
diff --git a/notifier/vendor/github.com/spf13/viper/watch_unsupported.go b/notifier/vendor/github.com/spf13/viper/watch_unsupported.go
deleted file mode 100644
index 70764056..00000000
--- a/notifier/vendor/github.com/spf13/viper/watch_unsupported.go
+++ /dev/null
@@ -1,31 +0,0 @@
-//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
-
-package viper
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/fsnotify/fsnotify"
-)
-
-func newWatcher() (*watcher, error) {
-	return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-type watcher struct {
-	Events chan fsnotify.Event
-	Errors chan error
-}
-
-func (*watcher) Close() error {
-	return nil
-}
-
-func (*watcher) Add(name string) error {
-	return nil
-}
-
-func (*watcher) Remove(name string) error {
-	return nil
-}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/LICENSE b/notifier/vendor/go.yaml.in/yaml/v3/LICENSE
new file mode 100644
index 00000000..2683e4bb
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/LICENSE
@@ -0,0 +1,50 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
+
+    apic.go emitterc.go parserc.go readerc.go scannerc.go
+    writerc.go yamlh.go yamlprivateh.go
+
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/NOTICE b/notifier/vendor/go.yaml.in/yaml/v3/NOTICE
new file mode 100644
index 00000000..866d74a7
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/README.md b/notifier/vendor/go.yaml.in/yaml/v3/README.md
new file mode 100644
index 00000000..15a85a63
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/README.md
@@ -0,0 +1,171 @@
+go.yaml.in/yaml
+===============
+
+YAML Support for the Go Language
+
+
+## Introduction
+
+The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode
+and decode [YAML](https://yaml.org/) values.
+
+It was originally developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go
+port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to
+parse and generate YAML data quickly and reliably.
+
+
+## Project Status
+
+This project started as a fork of the extremely popular [go-yaml](
+https://github.com/go-yaml/yaml/)
+project, and is being maintained by the official [YAML organization](
+https://github.com/yaml/).
+
+The YAML team took over ongoing maintenance and development of the project after
+discussion with go-yaml's author, @niemeyer, following his decision to
+[label the project repository as "unmaintained"](
+https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025.
+
+We have put together a team of dedicated maintainers including representatives
+of go-yaml's most important downstream projects.
+
+We will strive to earn the trust of the various go-yaml forks to switch back to
+this repository as their upstream.
+
+Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you
+would like to contribute or be involved.
+
+
+## Compatibility
+
+The `yaml` package supports most of YAML 1.2, but preserves some behavior from
+1.1 for backwards compatibility.
+
+Specifically, v3 of the `yaml` package:
+
+* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being
+  decoded into a typed bool value.
+  Otherwise they behave as a string.
+  Booleans in YAML 1.2 are `true`/`false` only.
+* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than
+  `0o777` as specified in YAML 1.2, because most parsers still use the old
+  format.
+  Octals in the `0o777` format are supported though, so new files work.
+* Does not support base-60 floats.
+  These are gone from YAML 1.2, and were actually never supported by this
+  package as it's clearly a poor choice.
+
+
+## Installation and Usage
+
+The import path for the package is *go.yaml.in/yaml/v3*.
+
+To install it, run:
+
+```bash
+go get go.yaml.in/yaml/v3
+```
+
+
+## API Documentation
+
+See: 
+
+
+## API Stability
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](
+https://gopkg.in).
+
+
+## Example
+
+```go
+package main
+
+import (
+	"fmt"
+	"log"
+
+	"go.yaml.in/yaml/v3"
+)
+
+var data = `
+a: Easy!
+b:
+  c: 2
+  d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+	A string
+	B struct {
+		RenamedC int   `yaml:"c"`
+		D	[]int `yaml:",flow"`
+	}
+}
+
+func main() {
+	t := T{}
+
+	err := yaml.Unmarshal([]byte(data), &t)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- t:\n%v\n\n", t)
+
+	d, err := yaml.Marshal(&t)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+	m := make(map[interface{}]interface{})
+
+	err = yaml.Unmarshal([]byte(data), &m)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- m:\n%v\n\n", m)
+
+	d, err = yaml.Marshal(&m)
+	if err != nil {
+		log.Fatalf("error: %v", err)
+	}
+	fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+  c: 2
+  d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+  c: 2
+  d:
+  - 3
+  - 4
+```
+
+
+## License
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/apic.go b/notifier/vendor/go.yaml.in/yaml/v3/apic.go
new file mode 100644
index 00000000..05fd305d
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/apic.go
@@ -0,0 +1,747 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+	//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+	// Check if we can move the queue at the beginning of the buffer.
+	if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+		if parser.tokens_head != len(parser.tokens) {
+			copy(parser.tokens, parser.tokens[parser.tokens_head:])
+		}
+		parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+		parser.tokens_head = 0
+	}
+	parser.tokens = append(parser.tokens, *token)
+	if pos < 0 {
+		return
+	}
+	copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+	parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+	*parser = yaml_parser_t{
+		raw_buffer: make([]byte, 0, input_raw_buffer_size),
+		buffer:     make([]byte, 0, input_buffer_size),
+	}
+	return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+	*parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+	if parser.input_pos == len(parser.input) {
+		return 0, io.EOF
+	}
+	n = copy(buffer, parser.input[parser.input_pos:])
+	parser.input_pos += n
+	return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+	return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+	if parser.read_handler != nil {
+		panic("must set the input source only once")
+	}
+	parser.read_handler = yaml_string_read_handler
+	parser.input = input
+	parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+	if parser.read_handler != nil {
+		panic("must set the input source only once")
+	}
+	parser.read_handler = yaml_reader_read_handler
+	parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+	if parser.encoding != yaml_ANY_ENCODING {
+		panic("must set the encoding only once")
+	}
+	parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+	*emitter = yaml_emitter_t{
+		buffer:     make([]byte, output_buffer_size),
+		raw_buffer: make([]byte, 0, output_raw_buffer_size),
+		states:     make([]yaml_emitter_state_t, 0, initial_stack_size),
+		events:     make([]yaml_event_t, 0, initial_queue_size),
+		best_width: -1,
+	}
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+	*emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+	*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+	return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+	_, err := emitter.output_writer.Write(buffer)
+	return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+	if emitter.write_handler != nil {
+		panic("must set the output target only once")
+	}
+	emitter.write_handler = yaml_string_write_handler
+	emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+	if emitter.write_handler != nil {
+		panic("must set the output target only once")
+	}
+	emitter.write_handler = yaml_writer_write_handler
+	emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+	if emitter.encoding != yaml_ANY_ENCODING {
+		panic("must set the output encoding only once")
+	}
+	emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+	emitter.canonical = canonical
+}
+
+// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+	if indent < 2 || indent > 9 {
+		indent = 2
+	}
+	emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+	if width < 0 {
+		width = -1
+	}
+	emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+	emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+	emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+//    assert(token);  // Non-NULL token object expected.
+//
+//    switch (token.type)
+//    {
+//        case YAML_TAG_DIRECTIVE_TOKEN:
+//            yaml_free(token.data.tag_directive.handle);
+//            yaml_free(token.data.tag_directive.prefix);
+//            break;
+//
+//        case YAML_ALIAS_TOKEN:
+//            yaml_free(token.data.alias.value);
+//            break;
+//
+//        case YAML_ANCHOR_TOKEN:
+//            yaml_free(token.data.anchor.value);
+//            break;
+//
+//        case YAML_TAG_TOKEN:
+//            yaml_free(token.data.tag.handle);
+//            yaml_free(token.data.tag.suffix);
+//            break;
+//
+//        case YAML_SCALAR_TOKEN:
+//            yaml_free(token.data.scalar.value);
+//            break;
+//
+//        default:
+//            break;
+//    }
+//
+//    memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+//    yaml_char_t *end = start+length;
+//    yaml_char_t *pointer = start;
+//
+//    while (pointer < end) {
+//        unsigned char octet;
+//        unsigned int width;
+//        unsigned int value;
+//        size_t k;
+//
+//        octet = pointer[0];
+//        width = (octet & 0x80) == 0x00 ? 1 :
+//                (octet & 0xE0) == 0xC0 ? 2 :
+//                (octet & 0xF0) == 0xE0 ? 3 :
+//                (octet & 0xF8) == 0xF0 ? 4 : 0;
+//        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+//                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+//                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+//                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+//        if (!width) return 0;
+//        if (pointer+width > end) return 0;
+//        for (k = 1; k < width; k ++) {
+//            octet = pointer[k];
+//            if ((octet & 0xC0) != 0x80) return 0;
+//            value = (value << 6) + (octet & 0x3F);
+//        }
+//        if (!((width == 1) ||
+//            (width == 2 && value >= 0x80) ||
+//            (width == 3 && value >= 0x800) ||
+//            (width == 4 && value >= 0x10000))) return 0;
+//
+//        pointer += width;
+//    }
+//
+//    return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+	*event = yaml_event_t{
+		typ:      yaml_STREAM_START_EVENT,
+		encoding: encoding,
+	}
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+	*event = yaml_event_t{
+		typ: yaml_STREAM_END_EVENT,
+	}
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+	event *yaml_event_t,
+	version_directive *yaml_version_directive_t,
+	tag_directives []yaml_tag_directive_t,
+	implicit bool,
+) {
+	*event = yaml_event_t{
+		typ:               yaml_DOCUMENT_START_EVENT,
+		version_directive: version_directive,
+		tag_directives:    tag_directives,
+		implicit:          implicit,
+	}
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+	*event = yaml_event_t{
+		typ:      yaml_DOCUMENT_END_EVENT,
+		implicit: implicit,
+	}
+}
+
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+	*event = yaml_event_t{
+		typ:    yaml_ALIAS_EVENT,
+		anchor: anchor,
+	}
+	return true
+}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+	*event = yaml_event_t{
+		typ:             yaml_SCALAR_EVENT,
+		anchor:          anchor,
+		tag:             tag,
+		value:           value,
+		implicit:        plain_implicit,
+		quoted_implicit: quoted_implicit,
+		style:           yaml_style_t(style),
+	}
+	return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+	*event = yaml_event_t{
+		typ:      yaml_SEQUENCE_START_EVENT,
+		anchor:   anchor,
+		tag:      tag,
+		implicit: implicit,
+		style:    yaml_style_t(style),
+	}
+	return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+	*event = yaml_event_t{
+		typ: yaml_SEQUENCE_END_EVENT,
+	}
+	return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+	*event = yaml_event_t{
+		typ:      yaml_MAPPING_START_EVENT,
+		anchor:   anchor,
+		tag:      tag,
+		implicit: implicit,
+		style:    yaml_style_t(style),
+	}
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+	*event = yaml_event_t{
+		typ: yaml_MAPPING_END_EVENT,
+	}
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+	*event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+//        version_directive *yaml_version_directive_t,
+//        tag_directives_start *yaml_tag_directive_t,
+//        tag_directives_end *yaml_tag_directive_t,
+//        start_implicit int, end_implicit int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    struct {
+//        start *yaml_node_t
+//        end *yaml_node_t
+//        top *yaml_node_t
+//    } nodes = { NULL, NULL, NULL }
+//    version_directive_copy *yaml_version_directive_t = NULL
+//    struct {
+//        start *yaml_tag_directive_t
+//        end *yaml_tag_directive_t
+//        top *yaml_tag_directive_t
+//    } tag_directives_copy = { NULL, NULL, NULL }
+//    value yaml_tag_directive_t = { NULL, NULL }
+//    mark yaml_mark_t = { 0, 0, 0 }
+//
+//    assert(document) // Non-NULL document object is expected.
+//    assert((tag_directives_start && tag_directives_end) ||
+//            (tag_directives_start == tag_directives_end))
+//                            // Valid tag directives are expected.
+//
+//    if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+//    if (version_directive) {
+//        version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+//        if (!version_directive_copy) goto error
+//        version_directive_copy.major = version_directive.major
+//        version_directive_copy.minor = version_directive.minor
+//    }
+//
+//    if (tag_directives_start != tag_directives_end) {
+//        tag_directive *yaml_tag_directive_t
+//        if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+//            goto error
+//        for (tag_directive = tag_directives_start
+//                tag_directive != tag_directives_end; tag_directive ++) {
+//            assert(tag_directive.handle)
+//            assert(tag_directive.prefix)
+//            if (!yaml_check_utf8(tag_directive.handle,
+//                        strlen((char *)tag_directive.handle)))
+//                goto error
+//            if (!yaml_check_utf8(tag_directive.prefix,
+//                        strlen((char *)tag_directive.prefix)))
+//                goto error
+//            value.handle = yaml_strdup(tag_directive.handle)
+//            value.prefix = yaml_strdup(tag_directive.prefix)
+//            if (!value.handle || !value.prefix) goto error
+//            if (!PUSH(&context, tag_directives_copy, value))
+//                goto error
+//            value.handle = NULL
+//            value.prefix = NULL
+//        }
+//    }
+//
+//    DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+//            tag_directives_copy.start, tag_directives_copy.top,
+//            start_implicit, end_implicit, mark, mark)
+//
+//    return 1
+//
+//error:
+//    STACK_DEL(&context, nodes)
+//    yaml_free(version_directive_copy)
+//    while (!STACK_EMPTY(&context, tag_directives_copy)) {
+//        value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+//        yaml_free(value.handle)
+//        yaml_free(value.prefix)
+//    }
+//    STACK_DEL(&context, tag_directives_copy)
+//    yaml_free(value.handle)
+//    yaml_free(value.prefix)
+//
+//    return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    tag_directive *yaml_tag_directive_t
+//
+//    context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    while (!STACK_EMPTY(&context, document.nodes)) {
+//        node yaml_node_t = POP(&context, document.nodes)
+//        yaml_free(node.tag)
+//        switch (node.type) {
+//            case YAML_SCALAR_NODE:
+//                yaml_free(node.data.scalar.value)
+//                break
+//            case YAML_SEQUENCE_NODE:
+//                STACK_DEL(&context, node.data.sequence.items)
+//                break
+//            case YAML_MAPPING_NODE:
+//                STACK_DEL(&context, node.data.mapping.pairs)
+//                break
+//            default:
+//                assert(0) // Should not happen.
+//        }
+//    }
+//    STACK_DEL(&context, document.nodes)
+//
+//    yaml_free(document.version_directive)
+//    for (tag_directive = document.tag_directives.start
+//            tag_directive != document.tag_directives.end
+//            tag_directive++) {
+//        yaml_free(tag_directive.handle)
+//        yaml_free(tag_directive.prefix)
+//    }
+//    yaml_free(document.tag_directives.start)
+//
+//    memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+//        return document.nodes.start + index - 1
+//    }
+//    return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (document.nodes.top != document.nodes.start) {
+//        return document.nodes.start
+//    }
+//    return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+//        tag *yaml_char_t, value *yaml_char_t, length int,
+//        style yaml_scalar_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    value_copy *yaml_char_t = NULL
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//    assert(value) // Non-NULL value is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (length < 0) {
+//        length = strlen((char *)value)
+//    }
+//
+//    if (!yaml_check_utf8(value, length)) goto error
+//    value_copy = yaml_malloc(length+1)
+//    if (!value_copy) goto error
+//    memcpy(value_copy, value, length)
+//    value_copy[length] = '\0'
+//
+//    SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    yaml_free(tag_copy)
+//    yaml_free(value_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+//        tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    struct {
+//        start *yaml_node_item_t
+//        end *yaml_node_item_t
+//        top *yaml_node_item_t
+//    } items = { NULL, NULL, NULL }
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+//    SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+//            style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    STACK_DEL(&context, items)
+//    yaml_free(tag_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+//        tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//    mark yaml_mark_t = { 0, 0, 0 }
+//    tag_copy *yaml_char_t = NULL
+//    struct {
+//        start *yaml_node_pair_t
+//        end *yaml_node_pair_t
+//        top *yaml_node_pair_t
+//    } pairs = { NULL, NULL, NULL }
+//    node yaml_node_t
+//
+//    assert(document) // Non-NULL document object is expected.
+//
+//    if (!tag) {
+//        tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+//    }
+//
+//    if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+//    tag_copy = yaml_strdup(tag)
+//    if (!tag_copy) goto error
+//
+//    if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+//    MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+//            style, mark, mark)
+//    if (!PUSH(&context, document.nodes, node)) goto error
+//
+//    return document.nodes.top - document.nodes.start
+//
+//error:
+//    STACK_DEL(&context, pairs)
+//    yaml_free(tag_copy)
+//
+//    return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+//        sequence int, item int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//
+//    assert(document) // Non-NULL document is required.
+//    assert(sequence > 0
+//            && document.nodes.start + sequence <= document.nodes.top)
+//                            // Valid sequence id is required.
+//    assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+//                            // A sequence node is required.
+//    assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+//                            // Valid item id is required.
+//
+//    if (!PUSH(&context,
+//                document.nodes.start[sequence-1].data.sequence.items, item))
+//        return 0
+//
+//    return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+//        mapping int, key int, value int)
+//{
+//    struct {
+//        error yaml_error_type_t
+//    } context
+//
+//    pair yaml_node_pair_t
+//
+//    assert(document) // Non-NULL document is required.
+//    assert(mapping > 0
+//            && document.nodes.start + mapping <= document.nodes.top)
+//                            // Valid mapping id is required.
+//    assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+//                            // A mapping node is required.
+//    assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+//                            // Valid key id is required.
+//    assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+//                            // Valid value id is required.
+//
+//    pair.key = key
+//    pair.value = value
+//
+//    if (!PUSH(&context,
+//                document.nodes.start[mapping-1].data.mapping.pairs, pair))
+//        return 0
+//
+//    return 1
+//}
+//
+//
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/decode.go b/notifier/vendor/go.yaml.in/yaml/v3/decode.go
new file mode 100644
index 00000000..02e2b17b
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/decode.go
@@ -0,0 +1,1018 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding"
+	"encoding/base64"
+	"fmt"
+	"io"
+	"math"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+	parser   yaml_parser_t
+	event    yaml_event_t
+	doc      *Node
+	anchors  map[string]*Node
+	doneInit bool
+	textless bool
+}
+
+func newParser(b []byte) *parser {
+	p := parser{}
+	if !yaml_parser_initialize(&p.parser) {
+		panic("failed to initialize YAML emitter")
+	}
+	if len(b) == 0 {
+		b = []byte{'\n'}
+	}
+	yaml_parser_set_input_string(&p.parser, b)
+	return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+	p := parser{}
+	if !yaml_parser_initialize(&p.parser) {
+		panic("failed to initialize YAML emitter")
+	}
+	yaml_parser_set_input_reader(&p.parser, r)
+	return &p
+}
+
+func (p *parser) init() {
+	if p.doneInit {
+		return
+	}
+	p.anchors = make(map[string]*Node)
+	p.expect(yaml_STREAM_START_EVENT)
+	p.doneInit = true
+}
+
+func (p *parser) destroy() {
+	if p.event.typ != yaml_NO_EVENT {
+		yaml_event_delete(&p.event)
+	}
+	yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+	if p.event.typ == yaml_NO_EVENT {
+		if !yaml_parser_parse(&p.parser, &p.event) {
+			p.fail()
+		}
+	}
+	if p.event.typ == yaml_STREAM_END_EVENT {
+		failf("attempted to go past the end of stream; corrupted value?")
+	}
+	if p.event.typ != e {
+		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+		p.fail()
+	}
+	yaml_event_delete(&p.event)
+	p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+	if p.event.typ != yaml_NO_EVENT {
+		return p.event.typ
+	}
+	// It's curious choice from the underlying API to generally return a
+	// positive result on success, but on this case return true in an error
+	// scenario. This was the source of bugs in the past (issue #666).
+	if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
+		p.fail()
+	}
+	return p.event.typ
+}
+
+func (p *parser) fail() {
+	var where string
+	var line int
+	if p.parser.context_mark.line != 0 {
+		line = p.parser.context_mark.line
+		// Scanner errors don't iterate line before returning error
+		if p.parser.error == yaml_SCANNER_ERROR {
+			line++
+		}
+	} else if p.parser.problem_mark.line != 0 {
+		line = p.parser.problem_mark.line
+		// Scanner errors don't iterate line before returning error
+		if p.parser.error == yaml_SCANNER_ERROR {
+			line++
+		}
+	}
+	if line != 0 {
+		where = "line " + strconv.Itoa(line) + ": "
+	}
+	var msg string
+	if len(p.parser.problem) > 0 {
+		msg = p.parser.problem
+	} else {
+		msg = "unknown problem parsing YAML content"
+	}
+	failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *Node, anchor []byte) {
+	if anchor != nil {
+		n.Anchor = string(anchor)
+		p.anchors[n.Anchor] = n
+	}
+}
+
+func (p *parser) parse() *Node {
+	p.init()
+	switch p.peek() {
+	case yaml_SCALAR_EVENT:
+		return p.scalar()
+	case yaml_ALIAS_EVENT:
+		return p.alias()
+	case yaml_MAPPING_START_EVENT:
+		return p.mapping()
+	case yaml_SEQUENCE_START_EVENT:
+		return p.sequence()
+	case yaml_DOCUMENT_START_EVENT:
+		return p.document()
+	case yaml_STREAM_END_EVENT:
+		// Happens when attempting to decode an empty buffer.
+		return nil
+	case yaml_TAIL_COMMENT_EVENT:
+		panic("internal error: unexpected tail comment event (please report)")
+	default:
+		panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
+	}
+}
+
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+	var style Style
+	if tag != "" && tag != "!" {
+		tag = shortTag(tag)
+		style = TaggedStyle
+	} else if defaultTag != "" {
+		tag = defaultTag
+	} else if kind == ScalarNode {
+		tag, _ = resolve("", value)
+	}
+	n := &Node{
+		Kind:  kind,
+		Tag:   tag,
+		Value: value,
+		Style: style,
+	}
+	if !p.textless {
+		n.Line = p.event.start_mark.line + 1
+		n.Column = p.event.start_mark.column + 1
+		n.HeadComment = string(p.event.head_comment)
+		n.LineComment = string(p.event.line_comment)
+		n.FootComment = string(p.event.foot_comment)
+	}
+	return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+	child := p.parse()
+	parent.Content = append(parent.Content, child)
+	return child
+}
+
+func (p *parser) document() *Node {
+	n := p.node(DocumentNode, "", "", "")
+	p.doc = n
+	p.expect(yaml_DOCUMENT_START_EVENT)
+	p.parseChild(n)
+	if p.peek() == yaml_DOCUMENT_END_EVENT {
+		n.FootComment = string(p.event.foot_comment)
+	}
+	p.expect(yaml_DOCUMENT_END_EVENT)
+	return n
+}
+
+func (p *parser) alias() *Node {
+	n := p.node(AliasNode, "", "", string(p.event.anchor))
+	n.Alias = p.anchors[n.Value]
+	if n.Alias == nil {
+		failf("unknown anchor '%s' referenced", n.Value)
+	}
+	p.expect(yaml_ALIAS_EVENT)
+	return n
+}
+
+func (p *parser) scalar() *Node {
+	var parsedStyle = p.event.scalar_style()
+	var nodeStyle Style
+	switch {
+	case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+		nodeStyle = DoubleQuotedStyle
+	case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+		nodeStyle = SingleQuotedStyle
+	case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+		nodeStyle = LiteralStyle
+	case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+		nodeStyle = FoldedStyle
+	}
+	var nodeValue = string(p.event.value)
+	var nodeTag = string(p.event.tag)
+	var defaultTag string
+	if nodeStyle == 0 {
+		if nodeValue == "<<" {
+			defaultTag = mergeTag
+		}
+	} else {
+		defaultTag = strTag
+	}
+	n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+	n.Style |= nodeStyle
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_SCALAR_EVENT)
+	return n
+}
+
+func (p *parser) sequence() *Node {
+	n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+	if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+		n.Style |= FlowStyle
+	}
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_SEQUENCE_START_EVENT)
+	for p.peek() != yaml_SEQUENCE_END_EVENT {
+		p.parseChild(n)
+	}
+	n.LineComment = string(p.event.line_comment)
+	n.FootComment = string(p.event.foot_comment)
+	p.expect(yaml_SEQUENCE_END_EVENT)
+	return n
+}
+
+func (p *parser) mapping() *Node {
+	n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+	block := true
+	if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+		block = false
+		n.Style |= FlowStyle
+	}
+	p.anchor(n, p.event.anchor)
+	p.expect(yaml_MAPPING_START_EVENT)
+	for p.peek() != yaml_MAPPING_END_EVENT {
+		k := p.parseChild(n)
+		if block && k.FootComment != "" {
+			// Must be a foot comment for the prior value when being dedented.
+			if len(n.Content) > 2 {
+				n.Content[len(n.Content)-3].FootComment = k.FootComment
+				k.FootComment = ""
+			}
+		}
+		v := p.parseChild(n)
+		if k.FootComment == "" && v.FootComment != "" {
+			k.FootComment = v.FootComment
+			v.FootComment = ""
+		}
+		if p.peek() == yaml_TAIL_COMMENT_EVENT {
+			if k.FootComment == "" {
+				k.FootComment = string(p.event.foot_comment)
+			}
+			p.expect(yaml_TAIL_COMMENT_EVENT)
+		}
+	}
+	n.LineComment = string(p.event.line_comment)
+	n.FootComment = string(p.event.foot_comment)
+	if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+		n.Content[len(n.Content)-2].FootComment = n.FootComment
+		n.FootComment = ""
+	}
+	p.expect(yaml_MAPPING_END_EVENT)
+	return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+	doc     *Node
+	aliases map[*Node]bool
+	terrors []string
+
+	stringMapType  reflect.Type
+	generalMapType reflect.Type
+
+	knownFields bool
+	uniqueKeys  bool
+	decodeCount int
+	aliasCount  int
+	aliasDepth  int
+
+	mergedFields map[interface{}]bool
+}
+
+var (
+	nodeType       = reflect.TypeOf(Node{})
+	durationType   = reflect.TypeOf(time.Duration(0))
+	stringMapType  = reflect.TypeOf(map[string]interface{}{})
+	generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+	ifaceType      = generalMapType.Elem()
+	timeType       = reflect.TypeOf(time.Time{})
+	ptrTimeType    = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder() *decoder {
+	d := &decoder{
+		stringMapType:  stringMapType,
+		generalMapType: generalMapType,
+		uniqueKeys:     true,
+	}
+	d.aliases = make(map[*Node]bool)
+	return d
+}
+
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+	if n.Tag != "" {
+		tag = n.Tag
+	}
+	value := n.Value
+	if tag != seqTag && tag != mapTag {
+		if len(value) > 10 {
+			value = " `" + value[:7] + "...`"
+		} else {
+			value = " `" + value + "`"
+		}
+	}
+	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+	err := u.UnmarshalYAML(n)
+	if e, ok := err.(*TypeError); ok {
+		d.terrors = append(d.terrors, e.Errors...)
+		return false
+	}
+	if err != nil {
+		fail(err)
+	}
+	return true
+}
+
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
+	terrlen := len(d.terrors)
+	err := u.UnmarshalYAML(func(v interface{}) (err error) {
+		defer handleErr(&err)
+		d.unmarshal(n, reflect.ValueOf(v))
+		if len(d.terrors) > terrlen {
+			issues := d.terrors[terrlen:]
+			d.terrors = d.terrors[:terrlen]
+			return &TypeError{issues}
+		}
+		return nil
+	})
+	if e, ok := err.(*TypeError); ok {
+		d.terrors = append(d.terrors, e.Errors...)
+		return false
+	}
+	if err != nil {
+		fail(err)
+	}
+	return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+	if n.ShortTag() == nullTag {
+		return out, false, false
+	}
+	again := true
+	for again {
+		again = false
+		if out.Kind() == reflect.Ptr {
+			if out.IsNil() {
+				out.Set(reflect.New(out.Type().Elem()))
+			}
+			out = out.Elem()
+			again = true
+		}
+		if out.CanAddr() {
+			outi := out.Addr().Interface()
+			if u, ok := outi.(Unmarshaler); ok {
+				good = d.callUnmarshaler(n, u)
+				return out, true, good
+			}
+			if u, ok := outi.(obsoleteUnmarshaler); ok {
+				good = d.callObsoleteUnmarshaler(n, u)
+				return out, true, good
+			}
+		}
+	}
+	return out, false, false
+}
+
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+	if n.ShortTag() == nullTag {
+		return reflect.Value{}
+	}
+	for _, num := range index {
+		for {
+			if v.Kind() == reflect.Ptr {
+				if v.IsNil() {
+					v.Set(reflect.New(v.Type().Elem()))
+				}
+				v = v.Elem()
+				continue
+			}
+			break
+		}
+		v = v.Field(num)
+	}
+	return v
+}
+
+const (
+	// 400,000 decode operations is ~500kb of dense object declarations, or
+	// ~5kb of dense object declarations with 10000% alias expansion
+	alias_ratio_range_low = 400000
+
+	// 4,000,000 decode operations is ~5MB of dense object declarations, or
+	// ~4.5MB of dense object declarations with 10% alias expansion
+	alias_ratio_range_high = 4000000
+
+	// alias_ratio_range is the range over which we scale allowed alias ratios
+	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+	switch {
+	case decodeCount <= alias_ratio_range_low:
+		// allow 99% to come from alias expansion for small-to-medium documents
+		return 0.99
+	case decodeCount >= alias_ratio_range_high:
+		// allow 10% to come from alias expansion for very large documents
+		return 0.10
+	default:
+		// scale smoothly from 99% down to 10% over the range.
+		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+		return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+	}
+}
+
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
+	d.decodeCount++
+	if d.aliasDepth > 0 {
+		d.aliasCount++
+	}
+	if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+		failf("document contains excessive aliasing")
+	}
+	if out.Type() == nodeType {
+		out.Set(reflect.ValueOf(n).Elem())
+		return true
+	}
+	switch n.Kind {
+	case DocumentNode:
+		return d.document(n, out)
+	case AliasNode:
+		return d.alias(n, out)
+	}
+	out, unmarshaled, good := d.prepare(n, out)
+	if unmarshaled {
+		return good
+	}
+	switch n.Kind {
+	case ScalarNode:
+		good = d.scalar(n, out)
+	case MappingNode:
+		good = d.mapping(n, out)
+	case SequenceNode:
+		good = d.sequence(n, out)
+	case 0:
+		if n.IsZero() {
+			return d.null(out)
+		}
+		fallthrough
+	default:
+		failf("cannot decode node with unknown kind %d", n.Kind)
+	}
+	return good
+}
+
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+	if len(n.Content) == 1 {
+		d.doc = n
+		d.unmarshal(n.Content[0], out)
+		return true
+	}
+	return false
+}
+
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
+	if d.aliases[n] {
+		// TODO this could actually be allowed in some circumstances.
+		failf("anchor '%s' value contains itself", n.Value)
+	}
+	d.aliases[n] = true
+	d.aliasDepth++
+	good = d.unmarshal(n.Alias, out)
+	d.aliasDepth--
+	delete(d.aliases, n)
+	return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+	for _, k := range out.MapKeys() {
+		out.SetMapIndex(k, zeroValue)
+	}
+}
+
+func (d *decoder) null(out reflect.Value) bool {
+	if out.CanAddr() {
+		switch out.Kind() {
+		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+			out.Set(reflect.Zero(out.Type()))
+			return true
+		}
+	}
+	return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
+	var tag string
+	var resolved interface{}
+	if n.indicatedString() {
+		tag = strTag
+		resolved = n.Value
+	} else {
+		tag, resolved = resolve(n.Tag, n.Value)
+		if tag == binaryTag {
+			data, err := base64.StdEncoding.DecodeString(resolved.(string))
+			if err != nil {
+				failf("!!binary value contains invalid base64 data")
+			}
+			resolved = string(data)
+		}
+	}
+	if resolved == nil {
+		return d.null(out)
+	}
+	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+		// We've resolved to exactly the type we want, so use that.
+		out.Set(resolvedv)
+		return true
+	}
+	// Perhaps we can use the value as a TextUnmarshaler to
+	// set its value.
+	if out.CanAddr() {
+		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+		if ok {
+			var text []byte
+			if tag == binaryTag {
+				text = []byte(resolved.(string))
+			} else {
+				// We let any value be unmarshaled into TextUnmarshaler.
+				// That might be more lax than we'd like, but the
+				// TextUnmarshaler itself should bowl out any dubious values.
+				text = []byte(n.Value)
+			}
+			err := u.UnmarshalText(text)
+			if err != nil {
+				fail(err)
+			}
+			return true
+		}
+	}
+	switch out.Kind() {
+	case reflect.String:
+		if tag == binaryTag {
+			out.SetString(resolved.(string))
+			return true
+		}
+		out.SetString(n.Value)
+		return true
+	case reflect.Interface:
+		out.Set(reflect.ValueOf(resolved))
+		return true
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		// This used to work in v2, but it's very unfriendly.
+		isDuration := out.Type() == durationType
+
+		switch resolved := resolved.(type) {
+		case int:
+			if !isDuration && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case int64:
+			if !isDuration && !out.OverflowInt(resolved) {
+				out.SetInt(resolved)
+				return true
+			}
+		case uint64:
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case float64:
+			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+				out.SetInt(int64(resolved))
+				return true
+			}
+		case string:
+			if out.Type() == durationType {
+				d, err := time.ParseDuration(resolved)
+				if err == nil {
+					out.SetInt(int64(d))
+					return true
+				}
+			}
+		}
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		switch resolved := resolved.(type) {
+		case int:
+			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case int64:
+			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case uint64:
+			if !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		case float64:
+			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+				out.SetUint(uint64(resolved))
+				return true
+			}
+		}
+	case reflect.Bool:
+		switch resolved := resolved.(type) {
+		case bool:
+			out.SetBool(resolved)
+			return true
+		case string:
+			// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+			// It only works if explicitly attempting to unmarshal into a typed bool value.
+			switch resolved {
+			case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+				out.SetBool(true)
+				return true
+			case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+				out.SetBool(false)
+				return true
+			}
+		}
+	case reflect.Float32, reflect.Float64:
+		switch resolved := resolved.(type) {
+		case int:
+			out.SetFloat(float64(resolved))
+			return true
+		case int64:
+			out.SetFloat(float64(resolved))
+			return true
+		case uint64:
+			out.SetFloat(float64(resolved))
+			return true
+		case float64:
+			out.SetFloat(resolved)
+			return true
+		}
+	case reflect.Struct:
+		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+			out.Set(resolvedv)
+			return true
+		}
+	case reflect.Ptr:
+		panic("yaml internal error: please report the issue")
+	}
+	d.terror(n, tag, out)
+	return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+	v := reflect.ValueOf(i)
+	sv := reflect.New(v.Type()).Elem()
+	sv.Set(v)
+	return sv
+}
+
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+	l := len(n.Content)
+
+	var iface reflect.Value
+	switch out.Kind() {
+	case reflect.Slice:
+		out.Set(reflect.MakeSlice(out.Type(), l, l))
+	case reflect.Array:
+		if l != out.Len() {
+			failf("invalid array: want %d elements but got %d", out.Len(), l)
+		}
+	case reflect.Interface:
+		// No type hints. Will have to use a generic sequence.
+		iface = out
+		out = settableValueOf(make([]interface{}, l))
+	default:
+		d.terror(n, seqTag, out)
+		return false
+	}
+	et := out.Type().Elem()
+
+	j := 0
+	for i := 0; i < l; i++ {
+		e := reflect.New(et).Elem()
+		if ok := d.unmarshal(n.Content[i], e); ok {
+			out.Index(j).Set(e)
+			j++
+		}
+	}
+	if out.Kind() != reflect.Array {
+		out.Set(out.Slice(0, j))
+	}
+	if iface.IsValid() {
+		iface.Set(out)
+	}
+	return true
+}
+
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+	l := len(n.Content)
+	if d.uniqueKeys {
+		nerrs := len(d.terrors)
+		for i := 0; i < l; i += 2 {
+			ni := n.Content[i]
+			for j := i + 2; j < l; j += 2 {
+				nj := n.Content[j]
+				if ni.Kind == nj.Kind && ni.Value == nj.Value {
+					d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+				}
+			}
+		}
+		if len(d.terrors) > nerrs {
+			return false
+		}
+	}
+	switch out.Kind() {
+	case reflect.Struct:
+		return d.mappingStruct(n, out)
+	case reflect.Map:
+		// okay
+	case reflect.Interface:
+		iface := out
+		if isStringMap(n) {
+			out = reflect.MakeMap(d.stringMapType)
+		} else {
+			out = reflect.MakeMap(d.generalMapType)
+		}
+		iface.Set(out)
+	default:
+		d.terror(n, mapTag, out)
+		return false
+	}
+
+	outt := out.Type()
+	kt := outt.Key()
+	et := outt.Elem()
+
+	stringMapType := d.stringMapType
+	generalMapType := d.generalMapType
+	if outt.Elem() == ifaceType {
+		if outt.Key().Kind() == reflect.String {
+			d.stringMapType = outt
+		} else if outt.Key() == ifaceType {
+			d.generalMapType = outt
+		}
+	}
+
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+
+	var mergeNode *Node
+
+	mapIsNew := false
+	if out.IsNil() {
+		out.Set(reflect.MakeMap(outt))
+		mapIsNew = true
+	}
+	for i := 0; i < l; i += 2 {
+		if isMerge(n.Content[i]) {
+			mergeNode = n.Content[i+1]
+			continue
+		}
+		k := reflect.New(kt).Elem()
+		if d.unmarshal(n.Content[i], k) {
+			if mergedFields != nil {
+				ki := k.Interface()
+				if d.getPossiblyUnhashableKey(mergedFields, ki) {
+					continue
+				}
+				d.setPossiblyUnhashableKey(mergedFields, ki, true)
+			}
+			kkind := k.Kind()
+			if kkind == reflect.Interface {
+				kkind = k.Elem().Kind()
+			}
+			if kkind == reflect.Map || kkind == reflect.Slice {
+				failf("invalid map key: %#v", k.Interface())
+			}
+			e := reflect.New(et).Elem()
+			if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+				out.SetMapIndex(k, e)
+			}
+		}
+	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
+
+	d.stringMapType = stringMapType
+	d.generalMapType = generalMapType
+	return true
+}
+
+func isStringMap(n *Node) bool {
+	if n.Kind != MappingNode {
+		return false
+	}
+	l := len(n.Content)
+	for i := 0; i < l; i += 2 {
+		shortTag := n.Content[i].ShortTag()
+		if shortTag != strTag && shortTag != mergeTag {
+			return false
+		}
+	}
+	return true
+}
+
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
+	sinfo, err := getStructInfo(out.Type())
+	if err != nil {
+		panic(err)
+	}
+
+	var inlineMap reflect.Value
+	var elemType reflect.Type
+	if sinfo.InlineMap != -1 {
+		inlineMap = out.Field(sinfo.InlineMap)
+		elemType = inlineMap.Type().Elem()
+	}
+
+	for _, index := range sinfo.InlineUnmarshalers {
+		field := d.fieldByIndex(n, out, index)
+		d.prepare(n, field)
+	}
+
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+	var mergeNode *Node
+	var doneFields []bool
+	if d.uniqueKeys {
+		doneFields = make([]bool, len(sinfo.FieldsList))
+	}
+	name := settableValueOf("")
+	l := len(n.Content)
+	for i := 0; i < l; i += 2 {
+		ni := n.Content[i]
+		if isMerge(ni) {
+			mergeNode = n.Content[i+1]
+			continue
+		}
+		if !d.unmarshal(ni, name) {
+			continue
+		}
+		sname := name.String()
+		if mergedFields != nil {
+			if mergedFields[sname] {
+				continue
+			}
+			mergedFields[sname] = true
+		}
+		if info, ok := sinfo.FieldsMap[sname]; ok {
+			if d.uniqueKeys {
+				if doneFields[info.Id] {
+					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
+					continue
+				}
+				doneFields[info.Id] = true
+			}
+			var field reflect.Value
+			if info.Inline == nil {
+				field = out.Field(info.Num)
+			} else {
+				field = d.fieldByIndex(n, out, info.Inline)
+			}
+			d.unmarshal(n.Content[i+1], field)
+		} else if sinfo.InlineMap != -1 {
+			if inlineMap.IsNil() {
+				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+			}
+			value := reflect.New(elemType).Elem()
+			d.unmarshal(n.Content[i+1], value)
+			inlineMap.SetMapIndex(name, value)
+		} else if d.knownFields {
+			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
+		}
+	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
+	return true
+}
+
+func failWantMap() {
+	failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) setPossiblyUnhashableKey(m map[interface{}]bool, key interface{}, value bool) {
+	defer func() {
+		if err := recover(); err != nil {
+			failf("%v", err)
+		}
+	}()
+	m[key] = value
+}
+
+func (d *decoder) getPossiblyUnhashableKey(m map[interface{}]bool, key interface{}) bool {
+	defer func() {
+		if err := recover(); err != nil {
+			failf("%v", err)
+		}
+	}()
+	return m[key]
+}
+
+func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
+	mergedFields := d.mergedFields
+	if mergedFields == nil {
+		d.mergedFields = make(map[interface{}]bool)
+		for i := 0; i < len(parent.Content); i += 2 {
+			k := reflect.New(ifaceType).Elem()
+			if d.unmarshal(parent.Content[i], k) {
+				d.setPossiblyUnhashableKey(d.mergedFields, k.Interface(), true)
+			}
+		}
+	}
+
+	switch merge.Kind {
+	case MappingNode:
+		d.unmarshal(merge, out)
+	case AliasNode:
+		if merge.Alias != nil && merge.Alias.Kind != MappingNode {
+			failWantMap()
+		}
+		d.unmarshal(merge, out)
+	case SequenceNode:
+		for i := 0; i < len(merge.Content); i++ {
+			ni := merge.Content[i]
+			if ni.Kind == AliasNode {
+				if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+					failWantMap()
+				}
+			} else if ni.Kind != MappingNode {
+				failWantMap()
+			}
+			d.unmarshal(ni, out)
+		}
+	default:
+		failWantMap()
+	}
+
+	d.mergedFields = mergedFields
+}
+
+func isMerge(n *Node) bool {
+	return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/emitterc.go b/notifier/vendor/go.yaml.in/yaml/v3/emitterc.go
new file mode 100644
index 00000000..ab4e03ba
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/emitterc.go
@@ -0,0 +1,2054 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) {
+		return yaml_emitter_flush(emitter)
+	}
+	return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	emitter.buffer[emitter.buffer_pos] = value
+	emitter.buffer_pos++
+	emitter.column++
+	return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	switch emitter.line_break {
+	case yaml_CR_BREAK:
+		emitter.buffer[emitter.buffer_pos] = '\r'
+		emitter.buffer_pos += 1
+	case yaml_LN_BREAK:
+		emitter.buffer[emitter.buffer_pos] = '\n'
+		emitter.buffer_pos += 1
+	case yaml_CRLN_BREAK:
+		emitter.buffer[emitter.buffer_pos+0] = '\r'
+		emitter.buffer[emitter.buffer_pos+1] = '\n'
+		emitter.buffer_pos += 2
+	default:
+		panic("unknown line break setting")
+	}
+	if emitter.column == 0 {
+		emitter.space_above = true
+	}
+	emitter.column = 0
+	emitter.line++
+	// [Go] Do this here and below and drop from everywhere else (see commented lines).
+	emitter.indention = true
+	return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+		return false
+	}
+	p := emitter.buffer_pos
+	w := width(s[*i])
+	switch w {
+	case 4:
+		emitter.buffer[p+3] = s[*i+3]
+		fallthrough
+	case 3:
+		emitter.buffer[p+2] = s[*i+2]
+		fallthrough
+	case 2:
+		emitter.buffer[p+1] = s[*i+1]
+		fallthrough
+	case 1:
+		emitter.buffer[p+0] = s[*i+0]
+	default:
+		panic("unknown character width")
+	}
+	emitter.column++
+	emitter.buffer_pos += w
+	*i += w
+	return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+	for i := 0; i < len(s); {
+		if !write(emitter, s, &i) {
+			return false
+		}
+	}
+	return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+	if s[*i] == '\n' {
+		if !put_break(emitter) {
+			return false
+		}
+		*i++
+	} else {
+		if !write(emitter, s, i) {
+			return false
+		}
+		if emitter.column == 0 {
+			emitter.space_above = true
+		}
+		emitter.column = 0
+		emitter.line++
+		// [Go] Do this here and above and drop from everywhere else (see commented lines).
+		emitter.indention = true
+	}
+	return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+	emitter.error = yaml_EMITTER_ERROR
+	emitter.problem = problem
+	return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	emitter.events = append(emitter.events, *event)
+	for !yaml_emitter_need_more_events(emitter) {
+		event := &emitter.events[emitter.events_head]
+		if !yaml_emitter_analyze_event(emitter, event) {
+			return false
+		}
+		if !yaml_emitter_state_machine(emitter, event) {
+			return false
+		}
+		yaml_event_delete(event)
+		emitter.events_head++
+	}
+	return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+//   - 1 event for DOCUMENT-START
+//   - 2 events for SEQUENCE-START
+//   - 3 events for MAPPING-START
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+	if emitter.events_head == len(emitter.events) {
+		return true
+	}
+	var accumulate int
+	switch emitter.events[emitter.events_head].typ {
+	case yaml_DOCUMENT_START_EVENT:
+		accumulate = 1
+		break
+	case yaml_SEQUENCE_START_EVENT:
+		accumulate = 2
+		break
+	case yaml_MAPPING_START_EVENT:
+		accumulate = 3
+		break
+	default:
+		return false
+	}
+	if len(emitter.events)-emitter.events_head > accumulate {
+		return false
+	}
+	var level int
+	for i := emitter.events_head; i < len(emitter.events); i++ {
+		switch emitter.events[i].typ {
+		case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+			level++
+		case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+			level--
+		}
+		if level == 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+	for i := 0; i < len(emitter.tag_directives); i++ {
+		if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+			if allow_duplicates {
+				return true
+			}
+			return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+		}
+	}
+
+	// [Go] Do we actually need to copy this given garbage collection
+	// and the lack of deallocating destructors?
+	tag_copy := yaml_tag_directive_t{
+		handle: make([]byte, len(value.handle)),
+		prefix: make([]byte, len(value.prefix)),
+	}
+	copy(tag_copy.handle, value.handle)
+	copy(tag_copy.prefix, value.prefix)
+	emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+	return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent_compact(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool {
+	emitter.indents = append(emitter.indents, emitter.indent)
+	if emitter.indent < 0 {
+		if flow {
+			emitter.indent = emitter.best_indent
+		} else {
+			emitter.indent = 0
+		}
+	} else if !indentless {
+		// [Go] This was changed so that indentations are more regular.
+		if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+			// The first indent inside a sequence will just skip the "- " indicator.
+			emitter.indent += 2
+		} else {
+			// Everything else aligns to the chosen indentation.
+			emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent)
+			if compact_seq {
+				// The value compact_seq passed in is almost always set to `false` when this function is called,
+				// except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we
+				// are increasing the indent to account for sequence nodes, which will be correct because we need to
+				// subtract 2 to account for the - at the beginning of the sequence node.
+				emitter.indent = emitter.indent - 2
+			}
+		}
+	}
+	return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	switch emitter.state {
+	default:
+	case yaml_EMIT_STREAM_START_STATE:
+		return yaml_emitter_emit_stream_start(emitter, event)
+
+	case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+		return yaml_emitter_emit_document_start(emitter, event, true)
+
+	case yaml_EMIT_DOCUMENT_START_STATE:
+		return yaml_emitter_emit_document_start(emitter, event, false)
+
+	case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+		return yaml_emitter_emit_document_content(emitter, event)
+
+	case yaml_EMIT_DOCUMENT_END_STATE:
+		return yaml_emitter_emit_document_end(emitter, event)
+
+	case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+	case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
+
+	case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+		return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
+
+	case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+	case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
+
+	case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+		return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
+
+	case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+		return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+	case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+		return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+		return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+		return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+		return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+	case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+		return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+	case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+		return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+	case yaml_EMIT_END_STATE:
+		return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+	}
+	panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if event.typ != yaml_STREAM_START_EVENT {
+		return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+	}
+	if emitter.encoding == yaml_ANY_ENCODING {
+		emitter.encoding = event.encoding
+		if emitter.encoding == yaml_ANY_ENCODING {
+			emitter.encoding = yaml_UTF8_ENCODING
+		}
+	}
+	if emitter.best_indent < 2 || emitter.best_indent > 9 {
+		emitter.best_indent = 2
+	}
+	if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+		emitter.best_width = 80
+	}
+	if emitter.best_width < 0 {
+		emitter.best_width = 1<<31 - 1
+	}
+	if emitter.line_break == yaml_ANY_BREAK {
+		emitter.line_break = yaml_LN_BREAK
+	}
+
+	emitter.indent = -1
+	emitter.line = 0
+	emitter.column = 0
+	emitter.whitespace = true
+	emitter.indention = true
+	emitter.space_above = true
+	emitter.foot_indent = -1
+
+	if emitter.encoding != yaml_UTF8_ENCODING {
+		if !yaml_emitter_write_bom(emitter) {
+			return false
+		}
+	}
+	emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+	return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+	if event.typ == yaml_DOCUMENT_START_EVENT {
+
+		if event.version_directive != nil {
+			if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+				return false
+			}
+		}
+
+		for i := 0; i < len(event.tag_directives); i++ {
+			tag_directive := &event.tag_directives[i]
+			if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+				return false
+			}
+			if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+				return false
+			}
+		}
+
+		for i := 0; i < len(default_tag_directives); i++ {
+			tag_directive := &default_tag_directives[i]
+			if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+				return false
+			}
+		}
+
+		implicit := event.implicit
+		if !first || emitter.canonical {
+			implicit = false
+		}
+
+		if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+
+		if event.version_directive != nil {
+			implicit = false
+			if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+
+		if len(event.tag_directives) > 0 {
+			implicit = false
+			for i := 0; i < len(event.tag_directives); i++ {
+				tag_directive := &event.tag_directives[i]
+				if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+					return false
+				}
+				if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+					return false
+				}
+				if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+					return false
+				}
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+		}
+
+		if yaml_emitter_check_empty_document(emitter) {
+			implicit = false
+		}
+		if !implicit {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+			if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+				return false
+			}
+			if emitter.canonical || true {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+		}
+
+		if len(emitter.head_comment) > 0 {
+			if !yaml_emitter_process_head_comment(emitter) {
+				return false
+			}
+			if !put_break(emitter) {
+				return false
+			}
+		}
+
+		emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+		return true
+	}
+
+	if event.typ == yaml_STREAM_END_EVENT {
+		if emitter.open_ended {
+			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+				return false
+			}
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_flush(emitter) {
+			return false
+		}
+		emitter.state = yaml_EMIT_END_STATE
+		return true
+	}
+
+	return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// yaml_emitter_increase_indent preserves the original signature and delegates to
+// yaml_emitter_increase_indent_compact without compact-sequence indentation
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+	return yaml_emitter_increase_indent_compact(emitter, flow, indentless, false)
+}
+
+// yaml_emitter_process_line_comment preserves the original signature and delegates to
+// yaml_emitter_process_line_comment_linebreak passing false for linebreak
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+	return yaml_emitter_process_line_comment_linebreak(emitter, false)
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if event.typ != yaml_DOCUMENT_END_EVENT {
+		return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+	}
+	// [Go] Force document foot separation.
+	emitter.foot_indent = 0
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	emitter.foot_indent = -1
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !event.implicit {
+		// [Go] Allocate the slice elsewhere.
+		if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+			return false
+		}
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+	if !yaml_emitter_flush(emitter) {
+		return false
+	}
+	emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+	emitter.tag_directives = emitter.tag_directives[:0]
+	return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+	if first {
+		if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+			return false
+		}
+		if !yaml_emitter_increase_indent(emitter, true, false) {
+			return false
+		}
+		emitter.flow_level++
+	}
+
+	if event.typ == yaml_SEQUENCE_END_EVENT {
+		if emitter.canonical && !first && !trail {
+			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+				return false
+			}
+		}
+		emitter.flow_level--
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		if emitter.column == 0 || emitter.canonical && !first {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+			return false
+		}
+		if !yaml_emitter_process_line_comment(emitter) {
+			return false
+		}
+		if !yaml_emitter_process_foot_comment(emitter) {
+			return false
+		}
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+
+		return true
+	}
+
+	if !first && !trail {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if emitter.column == 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if emitter.canonical || emitter.column > emitter.best_width {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+	} else {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+	}
+	if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+		return false
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+	if first {
+		if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+			return false
+		}
+		if !yaml_emitter_increase_indent(emitter, true, false) {
+			return false
+		}
+		emitter.flow_level++
+	}
+
+	if event.typ == yaml_MAPPING_END_EVENT {
+		if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+				return false
+			}
+		}
+		if !yaml_emitter_process_head_comment(emitter) {
+			return false
+		}
+		emitter.flow_level--
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		if emitter.canonical && !first {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+			return false
+		}
+		if !yaml_emitter_process_line_comment(emitter) {
+			return false
+		}
+		if !yaml_emitter_process_foot_comment(emitter) {
+			return false
+		}
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+
+	if !first && !trail {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+
+	if emitter.column == 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if emitter.canonical || emitter.column > emitter.best_width {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+	}
+
+	if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+	if simple {
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+			return false
+		}
+	} else {
+		if emitter.canonical || emitter.column > emitter.best_width {
+			if !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+			return false
+		}
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+	} else {
+		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+	}
+	if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+		return false
+	}
+	if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+	if first {
+		// emitter.mapping context tells us if we are currently in a mapping context.
+		// emiiter.column tells us which column we are in in the yaml output. 0 is the first char of the column.
+		// emitter.indentation tells us if the last character was an indentation character.
+		// emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements.
+		// So, `seq` means that we are in a mapping context, and we are either at the first char of the column or
+		//  the last character was not an indentation character, and we consider '- ' part of the indentation
+		//  for sequence elements.
+		seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
+			emitter.compact_sequence_indent
+		if !yaml_emitter_increase_indent_compact(emitter, false, false, seq) {
+			return false
+		}
+	}
+	if event.typ == yaml_SEQUENCE_END_EVENT {
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+	if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+	if first {
+		if !yaml_emitter_increase_indent(emitter, false, false) {
+			return false
+		}
+	}
+	if !yaml_emitter_process_head_comment(emitter) {
+		return false
+	}
+	if event.typ == yaml_MAPPING_END_EVENT {
+		emitter.indent = emitter.indents[len(emitter.indents)-1]
+		emitter.indents = emitter.indents[:len(emitter.indents)-1]
+		emitter.state = emitter.states[len(emitter.states)-1]
+		emitter.states = emitter.states[:len(emitter.states)-1]
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if len(emitter.line_comment) > 0 {
+		// [Go] A line comment was provided for the key. That's unusual as the
+		//      scanner associates line comments with the value. Either way,
+		//      save the line comment and render it appropriately later.
+		emitter.key_line_comment = emitter.line_comment
+		emitter.line_comment = nil
+	}
+	if yaml_emitter_check_simple_key(emitter) {
+		emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+		return false
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+	if simple {
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+			return false
+		}
+	} else {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+			return false
+		}
+	}
+	if len(emitter.key_line_comment) > 0 {
+		// [Go] Line comments are generally associated with the value, but when there's
+		//      no value on the same line as a mapping key they end up attached to the
+		//      key itself.
+		if event.typ == yaml_SCALAR_EVENT {
+			if len(emitter.line_comment) == 0 {
+				// A scalar is coming and it has no line comments by itself yet,
+				// so just let it handle the line comment as usual. If it has a
+				// line comment, we can't have both so the one from the key is lost.
+				emitter.line_comment = emitter.key_line_comment
+				emitter.key_line_comment = nil
+			}
+		} else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+			// An indented block follows, so write the comment right now.
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+			if !yaml_emitter_process_line_comment(emitter) {
+				return false
+			}
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+		}
+	}
+	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+	if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_foot_comment(emitter) {
+		return false
+	}
+	return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+	root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+	emitter.root_context = root
+	emitter.sequence_context = sequence
+	emitter.mapping_context = mapping
+	emitter.simple_key_context = simple_key
+
+	switch event.typ {
+	case yaml_ALIAS_EVENT:
+		return yaml_emitter_emit_alias(emitter, event)
+	case yaml_SCALAR_EVENT:
+		return yaml_emitter_emit_scalar(emitter, event)
+	case yaml_SEQUENCE_START_EVENT:
+		return yaml_emitter_emit_sequence_start(emitter, event)
+	case yaml_MAPPING_START_EVENT:
+		return yaml_emitter_emit_mapping_start(emitter, event)
+	default:
+		return yaml_emitter_set_emitter_error(emitter,
+			fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+	}
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	emitter.state = emitter.states[len(emitter.states)-1]
+	emitter.states = emitter.states[:len(emitter.states)-1]
+	return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_select_scalar_style(emitter, event) {
+		return false
+	}
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if !yaml_emitter_increase_indent(emitter, true, false) {
+		return false
+	}
+	if !yaml_emitter_process_scalar(emitter) {
+		return false
+	}
+	emitter.indent = emitter.indents[len(emitter.indents)-1]
+	emitter.indents = emitter.indents[:len(emitter.indents)-1]
+	emitter.state = emitter.states[len(emitter.states)-1]
+	emitter.states = emitter.states[:len(emitter.states)-1]
+	return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+		yaml_emitter_check_empty_sequence(emitter) {
+		emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+	} else {
+		emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+	}
+	return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	if !yaml_emitter_process_anchor(emitter) {
+		return false
+	}
+	if !yaml_emitter_process_tag(emitter) {
+		return false
+	}
+	if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+		yaml_emitter_check_empty_mapping(emitter) {
+		emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+	} else {
+		emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+	}
+	return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+	return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+	if len(emitter.events)-emitter.events_head < 2 {
+		return false
+	}
+	return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+		emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+	if len(emitter.events)-emitter.events_head < 2 {
+		return false
+	}
+	return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+		emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+	length := 0
+	switch emitter.events[emitter.events_head].typ {
+	case yaml_ALIAS_EVENT:
+		length += len(emitter.anchor_data.anchor)
+	case yaml_SCALAR_EVENT:
+		if emitter.scalar_data.multiline {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix) +
+			len(emitter.scalar_data.value)
+	case yaml_SEQUENCE_START_EVENT:
+		if !yaml_emitter_check_empty_sequence(emitter) {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix)
+	case yaml_MAPPING_START_EVENT:
+		if !yaml_emitter_check_empty_mapping(emitter) {
+			return false
+		}
+		length += len(emitter.anchor_data.anchor) +
+			len(emitter.tag_data.handle) +
+			len(emitter.tag_data.suffix)
+	default:
+		return false
+	}
+	return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+	no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+	if no_tag && !event.implicit && !event.quoted_implicit {
+		return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+	}
+
+	style := event.scalar_style()
+	if style == yaml_ANY_SCALAR_STYLE {
+		style = yaml_PLAIN_SCALAR_STYLE
+	}
+	if emitter.canonical {
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	if emitter.simple_key_context && emitter.scalar_data.multiline {
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+
+	if style == yaml_PLAIN_SCALAR_STYLE {
+		if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+			emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+		if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+		if no_tag && !event.implicit {
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		}
+	}
+	if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+		if !emitter.scalar_data.single_quoted_allowed {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+	}
+	if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+		if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+	}
+
+	if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+		emitter.tag_data.handle = []byte{'!'}
+	}
+	emitter.scalar_data.style = style
+	return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+	if emitter.anchor_data.anchor == nil {
+		return true
+	}
+	c := []byte{'&'}
+	if emitter.anchor_data.alias {
+		c[0] = '*'
+	}
+	if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+		return false
+	}
+	return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+	if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+		return true
+	}
+	if len(emitter.tag_data.handle) > 0 {
+		if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+			return false
+		}
+		if len(emitter.tag_data.suffix) > 0 {
+			if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+				return false
+			}
+		}
+	} else {
+		// [Go] Allocate these slices elsewhere.
+		if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+			return false
+		}
+		if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+			return false
+		}
+		if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+			return false
+		}
+	}
+	return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+	switch emitter.scalar_data.style {
+	case yaml_PLAIN_SCALAR_STYLE:
+		return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+		return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+		return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+	case yaml_LITERAL_SCALAR_STYLE:
+		return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+	case yaml_FOLDED_SCALAR_STYLE:
+		return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+	}
+	panic("unknown scalar style")
+}
+
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+	if len(emitter.tail_comment) > 0 {
+		if !yaml_emitter_write_indent(emitter) {
+			return false
+		}
+		if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+			return false
+		}
+		emitter.tail_comment = emitter.tail_comment[:0]
+		emitter.foot_indent = emitter.indent
+		if emitter.foot_indent < 0 {
+			emitter.foot_indent = 0
+		}
+	}
+
+	if len(emitter.head_comment) == 0 {
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+		return false
+	}
+	emitter.head_comment = emitter.head_comment[:0]
+	return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment_linebreak(emitter *yaml_emitter_t, linebreak bool) bool {
+	if len(emitter.line_comment) == 0 {
+		// The next 3 lines are needed to resolve an issue with leading newlines
+		// See https://github.com/go-yaml/yaml/issues/755
+		// When linebreak is set to true, put_break will be called and will add
+		// the needed newline.
+		if linebreak && !put_break(emitter) {
+			return false
+		}
+		return true
+	}
+	if !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+		return false
+	}
+	emitter.line_comment = emitter.line_comment[:0]
+	return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+	if len(emitter.foot_comment) == 0 {
+		return true
+	}
+	if !yaml_emitter_write_indent(emitter) {
+		return false
+	}
+	if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+		return false
+	}
+	emitter.foot_comment = emitter.foot_comment[:0]
+	emitter.foot_indent = emitter.indent
+	if emitter.foot_indent < 0 {
+		emitter.foot_indent = 0
+	}
+	return true
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+	if version_directive.major != 1 || version_directive.minor != 1 {
+		return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+	}
+	return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+	handle := tag_directive.handle
+	prefix := tag_directive.prefix
+	if len(handle) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+	}
+	if handle[0] != '!' {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+	}
+	if handle[len(handle)-1] != '!' {
+		return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+	}
+	for i := 1; i < len(handle)-1; i += width(handle[i]) {
+		if !is_alpha(handle, i) {
+			return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+		}
+	}
+	if len(prefix) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+	}
+	return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+	if len(anchor) == 0 {
+		problem := "anchor value must not be empty"
+		if alias {
+			problem = "alias value must not be empty"
+		}
+		return yaml_emitter_set_emitter_error(emitter, problem)
+	}
+	for i := 0; i < len(anchor); i += width(anchor[i]) {
+		if !is_alpha(anchor, i) {
+			problem := "anchor value must contain alphanumerical characters only"
+			if alias {
+				problem = "alias value must contain alphanumerical characters only"
+			}
+			return yaml_emitter_set_emitter_error(emitter, problem)
+		}
+	}
+	emitter.anchor_data.anchor = anchor
+	emitter.anchor_data.alias = alias
+	return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+	if len(tag) == 0 {
+		return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+	}
+	for i := 0; i < len(emitter.tag_directives); i++ {
+		tag_directive := &emitter.tag_directives[i]
+		if bytes.HasPrefix(tag, tag_directive.prefix) {
+			emitter.tag_data.handle = tag_directive.handle
+			emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+			return true
+		}
+	}
+	emitter.tag_data.suffix = tag
+	return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	var (
+		block_indicators   = false
+		flow_indicators    = false
+		line_breaks        = false
+		special_characters = false
+		tab_characters     = false
+
+		leading_space  = false
+		leading_break  = false
+		trailing_space = false
+		trailing_break = false
+		break_space    = false
+		space_break    = false
+
+		preceded_by_whitespace = false
+		followed_by_whitespace = false
+		previous_space         = false
+		previous_break         = false
+	)
+
+	emitter.scalar_data.value = value
+
+	if len(value) == 0 {
+		emitter.scalar_data.multiline = false
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = true
+		emitter.scalar_data.single_quoted_allowed = true
+		emitter.scalar_data.block_allowed = false
+		return true
+	}
+
+	if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+		block_indicators = true
+		flow_indicators = true
+	}
+
+	preceded_by_whitespace = true
+	for i, w := 0, 0; i < len(value); i += w {
+		w = width(value[i])
+		followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+		if i == 0 {
+			switch value[i] {
+			case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+				flow_indicators = true
+				block_indicators = true
+			case '?', ':':
+				flow_indicators = true
+				if followed_by_whitespace {
+					block_indicators = true
+				}
+			case '-':
+				if followed_by_whitespace {
+					flow_indicators = true
+					block_indicators = true
+				}
+			}
+		} else {
+			switch value[i] {
+			case ',', '?', '[', ']', '{', '}':
+				flow_indicators = true
+			case ':':
+				flow_indicators = true
+				if followed_by_whitespace {
+					block_indicators = true
+				}
+			case '#':
+				if preceded_by_whitespace {
+					flow_indicators = true
+					block_indicators = true
+				}
+			}
+		}
+
+		if value[i] == '\t' {
+			tab_characters = true
+		} else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+			special_characters = true
+		}
+		if is_space(value, i) {
+			if i == 0 {
+				leading_space = true
+			}
+			if i+width(value[i]) == len(value) {
+				trailing_space = true
+			}
+			if previous_break {
+				break_space = true
+			}
+			previous_space = true
+			previous_break = false
+		} else if is_break(value, i) {
+			line_breaks = true
+			if i == 0 {
+				leading_break = true
+			}
+			if i+width(value[i]) == len(value) {
+				trailing_break = true
+			}
+			if previous_space {
+				space_break = true
+			}
+			previous_space = false
+			previous_break = true
+		} else {
+			previous_space = false
+			previous_break = false
+		}
+
+		// [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+		preceded_by_whitespace = is_blankz(value, i)
+	}
+
+	emitter.scalar_data.multiline = line_breaks
+	emitter.scalar_data.flow_plain_allowed = true
+	emitter.scalar_data.block_plain_allowed = true
+	emitter.scalar_data.single_quoted_allowed = true
+	emitter.scalar_data.block_allowed = true
+
+	if leading_space || leading_break || trailing_space || trailing_break {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	if trailing_space {
+		emitter.scalar_data.block_allowed = false
+	}
+	if break_space {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+		emitter.scalar_data.single_quoted_allowed = false
+	}
+	if space_break || tab_characters || special_characters {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+		emitter.scalar_data.single_quoted_allowed = false
+	}
+	if space_break || special_characters {
+		emitter.scalar_data.block_allowed = false
+	}
+	if line_breaks {
+		emitter.scalar_data.flow_plain_allowed = false
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	if flow_indicators {
+		emitter.scalar_data.flow_plain_allowed = false
+	}
+	if block_indicators {
+		emitter.scalar_data.block_plain_allowed = false
+	}
+	return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+	emitter.anchor_data.anchor = nil
+	emitter.tag_data.handle = nil
+	emitter.tag_data.suffix = nil
+	emitter.scalar_data.value = nil
+
+	if len(event.head_comment) > 0 {
+		emitter.head_comment = event.head_comment
+	}
+	if len(event.line_comment) > 0 {
+		emitter.line_comment = event.line_comment
+	}
+	if len(event.foot_comment) > 0 {
+		emitter.foot_comment = event.foot_comment
+	}
+	if len(event.tail_comment) > 0 {
+		emitter.tail_comment = event.tail_comment
+	}
+
+	switch event.typ {
+	case yaml_ALIAS_EVENT:
+		if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+			return false
+		}
+
+	case yaml_SCALAR_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+		if !yaml_emitter_analyze_scalar(emitter, event.value) {
+			return false
+		}
+
+	case yaml_SEQUENCE_START_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+
+	case yaml_MAPPING_START_EVENT:
+		if len(event.anchor) > 0 {
+			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+				return false
+			}
+		}
+		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+			if !yaml_emitter_analyze_tag(emitter, event.tag) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+	if !flush(emitter) {
+		return false
+	}
+	pos := emitter.buffer_pos
+	emitter.buffer[pos+0] = '\xEF'
+	emitter.buffer[pos+1] = '\xBB'
+	emitter.buffer[pos+2] = '\xBF'
+	emitter.buffer_pos += 3
+	return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+	indent := emitter.indent
+	if indent < 0 {
+		indent = 0
+	}
+	if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+		if !put_break(emitter) {
+			return false
+		}
+	}
+	if emitter.foot_indent == indent {
+		if !put_break(emitter) {
+			return false
+		}
+	}
+	for emitter.column < indent {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	emitter.whitespace = true
+	//emitter.indention = true
+	emitter.space_above = false
+	emitter.foot_indent = -1
+	return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+	if need_whitespace && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !write_all(emitter, indicator) {
+		return false
+	}
+	emitter.whitespace = is_whitespace
+	emitter.indention = (emitter.indention && is_indention)
+	emitter.open_ended = false
+	return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+	if !write_all(emitter, value) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+	if !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	if !write_all(emitter, value) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+	if need_whitespace && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+	for i := 0; i < len(value); {
+		var must_write bool
+		switch value[i] {
+		case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+			must_write = true
+		default:
+			must_write = is_alpha(value, i)
+		}
+		if must_write {
+			if !write(emitter, value, &i) {
+				return false
+			}
+		} else {
+			w := width(value[i])
+			for k := 0; k < w; k++ {
+				octet := value[i]
+				i++
+				if !put(emitter, '%') {
+					return false
+				}
+
+				c := octet >> 4
+				if c < 10 {
+					c += '0'
+				} else {
+					c += 'A' - 10
+				}
+				if !put(emitter, c) {
+					return false
+				}
+
+				c = octet & 0x0f
+				if c < 10 {
+					c += '0'
+				} else {
+					c += 'A' - 10
+				}
+				if !put(emitter, c) {
+					return false
+				}
+			}
+		}
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+	if len(value) > 0 && !emitter.whitespace {
+		if !put(emitter, ' ') {
+			return false
+		}
+	}
+
+	spaces := false
+	breaks := false
+	for i := 0; i < len(value); {
+		if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			spaces = true
+		} else if is_break(value, i) {
+			if !breaks && value[i] == '\n' {
+				if !put_break(emitter) {
+					return false
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			spaces = false
+			breaks = false
+		}
+	}
+
+	if len(value) > 0 {
+		emitter.whitespace = false
+	}
+	emitter.indention = false
+	if emitter.root_context {
+		emitter.open_ended = true
+	}
+
+	return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+		return false
+	}
+
+	spaces := false
+	breaks := false
+	for i := 0; i < len(value); {
+		if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			spaces = true
+		} else if is_break(value, i) {
+			if !breaks && value[i] == '\n' {
+				if !put_break(emitter) {
+					return false
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if value[i] == '\'' {
+				if !put(emitter, '\'') {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			spaces = false
+			breaks = false
+		}
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+	spaces := false
+	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+		return false
+	}
+
+	for i := 0; i < len(value); {
+		if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+			is_bom(value, i) || is_break(value, i) ||
+			value[i] == '"' || value[i] == '\\' {
+
+			octet := value[i]
+
+			var w int
+			var v rune
+			switch {
+			case octet&0x80 == 0x00:
+				w, v = 1, rune(octet&0x7F)
+			case octet&0xE0 == 0xC0:
+				w, v = 2, rune(octet&0x1F)
+			case octet&0xF0 == 0xE0:
+				w, v = 3, rune(octet&0x0F)
+			case octet&0xF8 == 0xF0:
+				w, v = 4, rune(octet&0x07)
+			}
+			for k := 1; k < w; k++ {
+				octet = value[i+k]
+				v = (v << 6) + (rune(octet) & 0x3F)
+			}
+			i += w
+
+			if !put(emitter, '\\') {
+				return false
+			}
+
+			var ok bool
+			switch v {
+			case 0x00:
+				ok = put(emitter, '0')
+			case 0x07:
+				ok = put(emitter, 'a')
+			case 0x08:
+				ok = put(emitter, 'b')
+			case 0x09:
+				ok = put(emitter, 't')
+			case 0x0A:
+				ok = put(emitter, 'n')
+			case 0x0b:
+				ok = put(emitter, 'v')
+			case 0x0c:
+				ok = put(emitter, 'f')
+			case 0x0d:
+				ok = put(emitter, 'r')
+			case 0x1b:
+				ok = put(emitter, 'e')
+			case 0x22:
+				ok = put(emitter, '"')
+			case 0x5c:
+				ok = put(emitter, '\\')
+			case 0x85:
+				ok = put(emitter, 'N')
+			case 0xA0:
+				ok = put(emitter, '_')
+			case 0x2028:
+				ok = put(emitter, 'L')
+			case 0x2029:
+				ok = put(emitter, 'P')
+			default:
+				if v <= 0xFF {
+					ok = put(emitter, 'x')
+					w = 2
+				} else if v <= 0xFFFF {
+					ok = put(emitter, 'u')
+					w = 4
+				} else {
+					ok = put(emitter, 'U')
+					w = 8
+				}
+				for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+					digit := byte((v >> uint(k)) & 0x0F)
+					if digit < 10 {
+						ok = put(emitter, digit+'0')
+					} else {
+						ok = put(emitter, digit+'A'-10)
+					}
+				}
+			}
+			if !ok {
+				return false
+			}
+			spaces = false
+		} else if is_space(value, i) {
+			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				if is_space(value, i+1) {
+					if !put(emitter, '\\') {
+						return false
+					}
+				}
+				i += width(value[i])
+			} else if !write(emitter, value, &i) {
+				return false
+			}
+			spaces = true
+		} else {
+			if !write(emitter, value, &i) {
+				return false
+			}
+			spaces = false
+		}
+	}
+	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+		return false
+	}
+	emitter.whitespace = false
+	emitter.indention = false
+	return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+	if is_space(value, 0) || is_break(value, 0) {
+		indent_hint := []byte{'0' + byte(emitter.best_indent)}
+		if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+			return false
+		}
+	}
+
+	emitter.open_ended = false
+
+	var chomp_hint [1]byte
+	if len(value) == 0 {
+		chomp_hint[0] = '-'
+	} else {
+		i := len(value) - 1
+		for value[i]&0xC0 == 0x80 {
+			i--
+		}
+		if !is_break(value, i) {
+			chomp_hint[0] = '-'
+		} else if i == 0 {
+			chomp_hint[0] = '+'
+			emitter.open_ended = true
+		} else {
+			i--
+			for value[i]&0xC0 == 0x80 {
+				i--
+			}
+			if is_break(value, i) {
+				chomp_hint[0] = '+'
+				emitter.open_ended = true
+			}
+		}
+	}
+	if chomp_hint[0] != 0 {
+		if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+			return false
+		}
+	}
+	return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
+		return false
+	}
+	//emitter.indention = true
+	emitter.whitespace = true
+	breaks := true
+	for i := 0; i < len(value); {
+		if is_break(value, i) {
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+			}
+			if !write(emitter, value, &i) {
+				return false
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+
+	return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+	if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+		return false
+	}
+	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+		return false
+	}
+	if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
+		return false
+	}
+
+	//emitter.indention = true
+	emitter.whitespace = true
+
+	breaks := true
+	leading_spaces := true
+	for i := 0; i < len(value); {
+		if is_break(value, i) {
+			if !breaks && !leading_spaces && value[i] == '\n' {
+				k := 0
+				for is_break(value, k) {
+					k += width(value[k])
+				}
+				if !is_blankz(value, k) {
+					if !put_break(emitter) {
+						return false
+					}
+				}
+			}
+			if !write_break(emitter, value, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+		} else {
+			if breaks {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				leading_spaces = is_blank(value, i)
+			}
+			if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+				if !yaml_emitter_write_indent(emitter) {
+					return false
+				}
+				i += width(value[i])
+			} else {
+				if !write(emitter, value, &i) {
+					return false
+				}
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+	return true
+}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+	breaks := false
+	pound := false
+	for i := 0; i < len(comment); {
+		if is_break(comment, i) {
+			if !write_break(emitter, comment, &i) {
+				return false
+			}
+			//emitter.indention = true
+			breaks = true
+			pound = false
+		} else {
+			if breaks && !yaml_emitter_write_indent(emitter) {
+				return false
+			}
+			if !pound {
+				if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+					return false
+				}
+				pound = true
+			}
+			if !write(emitter, comment, &i) {
+				return false
+			}
+			emitter.indention = false
+			breaks = false
+		}
+	}
+	if !breaks && !put_break(emitter) {
+		return false
+	}
+
+	emitter.whitespace = true
+	//emitter.indention = true
+	return true
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/encode.go b/notifier/vendor/go.yaml.in/yaml/v3/encode.go
new file mode 100644
index 00000000..de9e72a3
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding"
+	"fmt"
+	"io"
+	"reflect"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+type encoder struct {
+	emitter  yaml_emitter_t
+	event    yaml_event_t
+	out      []byte
+	flow     bool
+	indent   int
+	doneInit bool
+}
+
+func newEncoder() *encoder {
+	e := &encoder{}
+	yaml_emitter_initialize(&e.emitter)
+	yaml_emitter_set_output_string(&e.emitter, &e.out)
+	yaml_emitter_set_unicode(&e.emitter, true)
+	return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+	e := &encoder{}
+	yaml_emitter_initialize(&e.emitter)
+	yaml_emitter_set_output_writer(&e.emitter, w)
+	yaml_emitter_set_unicode(&e.emitter, true)
+	return e
+}
+
+func (e *encoder) init() {
+	if e.doneInit {
+		return
+	}
+	if e.indent == 0 {
+		e.indent = 4
+	}
+	e.emitter.best_indent = e.indent
+	yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+	e.emit()
+	e.doneInit = true
+}
+
+func (e *encoder) finish() {
+	e.emitter.open_ended = false
+	yaml_stream_end_event_initialize(&e.event)
+	e.emit()
+}
+
+func (e *encoder) destroy() {
+	yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+	// This will internally delete the e.event value.
+	e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+	if !ok {
+		msg := e.emitter.problem
+		if msg == "" {
+			msg = "unknown problem generating YAML content"
+		}
+		failf("%s", msg)
+	}
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+	e.init()
+	var node *Node
+	if in.IsValid() {
+		node, _ = in.Interface().(*Node)
+	}
+	if node != nil && node.Kind == DocumentNode {
+		e.nodev(in)
+	} else {
+		yaml_document_start_event_initialize(&e.event, nil, nil, true)
+		e.emit()
+		e.marshal(tag, in)
+		yaml_document_end_event_initialize(&e.event, true)
+		e.emit()
+	}
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+	tag = shortTag(tag)
+	if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+		e.nilv()
+		return
+	}
+	iface := in.Interface()
+	switch value := iface.(type) {
+	case *Node:
+		e.nodev(in)
+		return
+	case Node:
+		if !in.CanAddr() {
+			var n = reflect.New(in.Type()).Elem()
+			n.Set(in)
+			in = n
+		}
+		e.nodev(in.Addr())
+		return
+	case time.Time:
+		e.timev(tag, in)
+		return
+	case *time.Time:
+		e.timev(tag, in.Elem())
+		return
+	case time.Duration:
+		e.stringv(tag, reflect.ValueOf(value.String()))
+		return
+	case Marshaler:
+		v, err := value.MarshalYAML()
+		if err != nil {
+			fail(err)
+		}
+		if v == nil {
+			e.nilv()
+			return
+		}
+		e.marshal(tag, reflect.ValueOf(v))
+		return
+	case encoding.TextMarshaler:
+		text, err := value.MarshalText()
+		if err != nil {
+			fail(err)
+		}
+		in = reflect.ValueOf(string(text))
+	case nil:
+		e.nilv()
+		return
+	}
+	switch in.Kind() {
+	case reflect.Interface:
+		e.marshal(tag, in.Elem())
+	case reflect.Map:
+		e.mapv(tag, in)
+	case reflect.Ptr:
+		e.marshal(tag, in.Elem())
+	case reflect.Struct:
+		e.structv(tag, in)
+	case reflect.Slice, reflect.Array:
+		e.slicev(tag, in)
+	case reflect.String:
+		e.stringv(tag, in)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		e.intv(tag, in)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		e.uintv(tag, in)
+	case reflect.Float32, reflect.Float64:
+		e.floatv(tag, in)
+	case reflect.Bool:
+		e.boolv(tag, in)
+	default:
+		panic("cannot marshal type: " + in.Type().String())
+	}
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+	e.mappingv(tag, func() {
+		keys := keyList(in.MapKeys())
+		sort.Sort(keys)
+		for _, k := range keys {
+			e.marshal("", k)
+			e.marshal("", in.MapIndex(k))
+		}
+	})
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+	for _, num := range index {
+		for {
+			if v.Kind() == reflect.Ptr {
+				if v.IsNil() {
+					return reflect.Value{}
+				}
+				v = v.Elem()
+				continue
+			}
+			break
+		}
+		v = v.Field(num)
+	}
+	return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+	sinfo, err := getStructInfo(in.Type())
+	if err != nil {
+		panic(err)
+	}
+	e.mappingv(tag, func() {
+		for _, info := range sinfo.FieldsList {
+			var value reflect.Value
+			if info.Inline == nil {
+				value = in.Field(info.Num)
+			} else {
+				value = e.fieldByIndex(in, info.Inline)
+				if !value.IsValid() {
+					continue
+				}
+			}
+			if info.OmitEmpty && isZero(value) {
+				continue
+			}
+			e.marshal("", reflect.ValueOf(info.Key))
+			e.flow = info.Flow
+			e.marshal("", value)
+		}
+		if sinfo.InlineMap >= 0 {
+			m := in.Field(sinfo.InlineMap)
+			if m.Len() > 0 {
+				e.flow = false
+				keys := keyList(m.MapKeys())
+				sort.Sort(keys)
+				for _, k := range keys {
+					if _, found := sinfo.FieldsMap[k.String()]; found {
+						panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+					}
+					e.marshal("", k)
+					e.flow = false
+					e.marshal("", m.MapIndex(k))
+				}
+			}
+		}
+	})
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+	implicit := tag == ""
+	style := yaml_BLOCK_MAPPING_STYLE
+	if e.flow {
+		e.flow = false
+		style = yaml_FLOW_MAPPING_STYLE
+	}
+	yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+	e.emit()
+	f()
+	yaml_mapping_end_event_initialize(&e.event)
+	e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+	implicit := tag == ""
+	style := yaml_BLOCK_SEQUENCE_STYLE
+	if e.flow {
+		e.flow = false
+		style = yaml_FLOW_SEQUENCE_STYLE
+	}
+	e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+	e.emit()
+	n := in.Len()
+	for i := 0; i < n; i++ {
+		e.marshal("", in.Index(i))
+	}
+	e.must(yaml_sequence_end_event_initialize(&e.event))
+	e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+	// Fast path.
+	if s == "" {
+		return false
+	}
+	c := s[0]
+	if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+		return false
+	}
+	// Do the full match.
+	return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+	switch s {
+	case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+		"n", "N", "no", "No", "NO", "off", "Off", "OFF":
+		return true
+	default:
+		return false
+	}
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+	var style yaml_scalar_style_t
+	s := in.String()
+	canUsePlain := true
+	switch {
+	case !utf8.ValidString(s):
+		if tag == binaryTag {
+			failf("explicitly tagged !!binary data must be base64-encoded")
+		}
+		if tag != "" {
+			failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+		}
+		// It can't be encoded directly as YAML so use a binary tag
+		// and encode it as base64.
+		tag = binaryTag
+		s = encodeBase64(s)
+	case tag == "":
+		// Check to see if it would resolve to a specific
+		// tag when encoded unquoted. If it doesn't,
+		// there's no need to quote it.
+		rtag, _ := resolve("", s)
+		canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+	}
+	// Note: it's possible for user code to emit invalid YAML
+	// if they explicitly specify a tag and a string containing
+	// text that's incompatible with that tag.
+	switch {
+	case strings.Contains(s, "\n"):
+		if e.flow {
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		} else {
+			style = yaml_LITERAL_SCALAR_STYLE
+		}
+	case canUsePlain:
+		style = yaml_PLAIN_SCALAR_STYLE
+	default:
+		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+	var s string
+	if in.Bool() {
+		s = "true"
+	} else {
+		s = "false"
+	}
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+	s := strconv.FormatInt(in.Int(), 10)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+	s := strconv.FormatUint(in.Uint(), 10)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+	t := in.Interface().(time.Time)
+	s := t.Format(time.RFC3339Nano)
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+	// Issue #352: When formatting, use the precision of the underlying value
+	precision := 64
+	if in.Kind() == reflect.Float32 {
+		precision = 32
+	}
+
+	s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+	switch s {
+	case "+Inf":
+		s = ".inf"
+	case "-Inf":
+		s = "-.inf"
+	case "NaN":
+		s = ".nan"
+	}
+	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+	e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+	// TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+	implicit := tag == ""
+	if !implicit {
+		tag = longTag(tag)
+	}
+	e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+	e.event.head_comment = head
+	e.event.line_comment = line
+	e.event.foot_comment = foot
+	e.event.tail_comment = tail
+	e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+	e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+	// Zero nodes behave as nil.
+	if node.Kind == 0 && node.IsZero() {
+		e.nilv()
+		return
+	}
+
+	// If the tag was not explicitly requested, and dropping it won't change the
+	// implicit tag of the value, don't include it in the presentation.
+	var tag = node.Tag
+	var stag = shortTag(tag)
+	var forceQuoting bool
+	if tag != "" && node.Style&TaggedStyle == 0 {
+		if node.Kind == ScalarNode {
+			if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+				tag = ""
+			} else {
+				rtag, _ := resolve("", node.Value)
+				if rtag == stag {
+					tag = ""
+				} else if stag == strTag {
+					tag = ""
+					forceQuoting = true
+				}
+			}
+		} else {
+			var rtag string
+			switch node.Kind {
+			case MappingNode:
+				rtag = mapTag
+			case SequenceNode:
+				rtag = seqTag
+			}
+			if rtag == stag {
+				tag = ""
+			}
+		}
+	}
+
+	switch node.Kind {
+	case DocumentNode:
+		yaml_document_start_event_initialize(&e.event, nil, nil, true)
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+		for _, node := range node.Content {
+			e.node(node, "")
+		}
+		yaml_document_end_event_initialize(&e.event, true)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case SequenceNode:
+		style := yaml_BLOCK_SEQUENCE_STYLE
+		if node.Style&FlowStyle != 0 {
+			style = yaml_FLOW_SEQUENCE_STYLE
+		}
+		e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+		for _, node := range node.Content {
+			e.node(node, "")
+		}
+		e.must(yaml_sequence_end_event_initialize(&e.event))
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case MappingNode:
+		style := yaml_BLOCK_MAPPING_STYLE
+		if node.Style&FlowStyle != 0 {
+			style = yaml_FLOW_MAPPING_STYLE
+		}
+		yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+		e.event.tail_comment = []byte(tail)
+		e.event.head_comment = []byte(node.HeadComment)
+		e.emit()
+
+		// The tail logic below moves the foot comment of prior keys to the following key,
+		// since the value for each key may be a nested structure and the foot needs to be
+		// processed only the entirety of the value is streamed. The last tail is processed
+		// with the mapping end event.
+		var tail string
+		for i := 0; i+1 < len(node.Content); i += 2 {
+			k := node.Content[i]
+			foot := k.FootComment
+			if foot != "" {
+				kopy := *k
+				kopy.FootComment = ""
+				k = &kopy
+			}
+			e.node(k, tail)
+			tail = foot
+
+			v := node.Content[i+1]
+			e.node(v, "")
+		}
+
+		yaml_mapping_end_event_initialize(&e.event)
+		e.event.tail_comment = []byte(tail)
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case AliasNode:
+		yaml_alias_event_initialize(&e.event, []byte(node.Value))
+		e.event.head_comment = []byte(node.HeadComment)
+		e.event.line_comment = []byte(node.LineComment)
+		e.event.foot_comment = []byte(node.FootComment)
+		e.emit()
+
+	case ScalarNode:
+		value := node.Value
+		if !utf8.ValidString(value) {
+			if stag == binaryTag {
+				failf("explicitly tagged !!binary data must be base64-encoded")
+			}
+			if stag != "" {
+				failf("cannot marshal invalid UTF-8 data as %s", stag)
+			}
+			// It can't be encoded directly as YAML so use a binary tag
+			// and encode it as base64.
+			tag = binaryTag
+			value = encodeBase64(value)
+		}
+
+		style := yaml_PLAIN_SCALAR_STYLE
+		switch {
+		case node.Style&DoubleQuotedStyle != 0:
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		case node.Style&SingleQuotedStyle != 0:
+			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+		case node.Style&LiteralStyle != 0:
+			style = yaml_LITERAL_SCALAR_STYLE
+		case node.Style&FoldedStyle != 0:
+			style = yaml_FOLDED_SCALAR_STYLE
+		case strings.Contains(value, "\n"):
+			style = yaml_LITERAL_SCALAR_STYLE
+		case forceQuoting:
+			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+		}
+
+		e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+	default:
+		failf("cannot encode node with unknown kind %d", node.Kind)
+	}
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/parserc.go b/notifier/vendor/go.yaml.in/yaml/v3/parserc.go
new file mode 100644
index 00000000..25fe8236
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/parserc.go
@@ -0,0 +1,1274 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream               ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document    ::= block_node DOCUMENT-END*
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence    ::=
+//                          ALIAS
+//                          | properties (block_content | indentless_block_sequence)?
+//                          | block_content
+//                          | indentless_block_sequence
+// block_node           ::= ALIAS
+//                          | properties block_content?
+//                          | block_content
+// flow_node            ::= ALIAS
+//                          | properties flow_content?
+//                          | flow_content
+// properties           ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content        ::= block_collection | flow_collection | SCALAR
+// flow_content         ::= flow_collection | SCALAR
+// block_collection     ::= block_sequence | block_mapping
+// flow_collection      ::= flow_sequence | flow_mapping
+// block_sequence       ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
+// block_mapping        ::= BLOCK-MAPPING_START
+//                          ((KEY block_node_or_indentless_sequence?)?
+//                          (VALUE block_node_or_indentless_sequence?)?)*
+//                          BLOCK-END
+// flow_sequence        ::= FLOW-SEQUENCE-START
+//                          (flow_sequence_entry FLOW-ENTRY)*
+//                          flow_sequence_entry?
+//                          FLOW-SEQUENCE-END
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping         ::= FLOW-MAPPING-START
+//                          (flow_mapping_entry FLOW-ENTRY)*
+//                          flow_mapping_entry?
+//                          FLOW-MAPPING-END
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+	if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+		token := &parser.tokens[parser.tokens_head]
+		yaml_parser_unfold_comments(parser, token)
+		return token
+	}
+	return nil
+}
+
+// yaml_parser_unfold_comments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
+	for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
+		comment := &parser.comments[parser.comments_head]
+		if len(comment.head) > 0 {
+			if token.typ == yaml_BLOCK_END_TOKEN {
+				// No heads on ends, so keep comment.head for a follow up token.
+				break
+			}
+			if len(parser.head_comment) > 0 {
+				parser.head_comment = append(parser.head_comment, '\n')
+			}
+			parser.head_comment = append(parser.head_comment, comment.head...)
+		}
+		if len(comment.foot) > 0 {
+			if len(parser.foot_comment) > 0 {
+				parser.foot_comment = append(parser.foot_comment, '\n')
+			}
+			parser.foot_comment = append(parser.foot_comment, comment.foot...)
+		}
+		if len(comment.line) > 0 {
+			if len(parser.line_comment) > 0 {
+				parser.line_comment = append(parser.line_comment, '\n')
+			}
+			parser.line_comment = append(parser.line_comment, comment.line...)
+		}
+		*comment = yaml_comment_t{}
+		parser.comments_head++
+	}
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+	parser.token_available = false
+	parser.tokens_parsed++
+	parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+	parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+	// Erase the event object.
+	*event = yaml_event_t{}
+
+	// No events after the end of the stream or error.
+	if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+		return true
+	}
+
+	// Generate the next event.
+	return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+	parser.error = yaml_PARSER_ERROR
+	parser.problem = problem
+	parser.problem_mark = problem_mark
+	return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+	parser.error = yaml_PARSER_ERROR
+	parser.context = context
+	parser.context_mark = context_mark
+	parser.problem = problem
+	parser.problem_mark = problem_mark
+	return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+	//trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+	switch parser.state {
+	case yaml_PARSE_STREAM_START_STATE:
+		return yaml_parser_parse_stream_start(parser, event)
+
+	case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+		return yaml_parser_parse_document_start(parser, event, true)
+
+	case yaml_PARSE_DOCUMENT_START_STATE:
+		return yaml_parser_parse_document_start(parser, event, false)
+
+	case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+		return yaml_parser_parse_document_content(parser, event)
+
+	case yaml_PARSE_DOCUMENT_END_STATE:
+		return yaml_parser_parse_document_end(parser, event)
+
+	case yaml_PARSE_BLOCK_NODE_STATE:
+		return yaml_parser_parse_node(parser, event, true, false)
+
+	case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+		return yaml_parser_parse_node(parser, event, true, true)
+
+	case yaml_PARSE_FLOW_NODE_STATE:
+		return yaml_parser_parse_node(parser, event, false, false)
+
+	case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+		return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+	case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+	case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+	case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+	case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+		return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+	case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_block_mapping_value(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+		return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+		return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+		return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+	case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+		return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+	case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+		return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+	case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+		return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+	case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+		return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+	default:
+		panic("invalid parser state")
+	}
+}
+
+// Parse the production:
+// stream   ::= STREAM-START implicit_document? explicit_document* STREAM-END
+//
+//	************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_STREAM_START_TOKEN {
+		return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark)
+	}
+	parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+	*event = yaml_event_t{
+		typ:        yaml_STREAM_START_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+		encoding:   token.encoding,
+	}
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// implicit_document    ::= block_node DOCUMENT-END*
+//
+//	*
+//
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+//	*************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	// Parse extra document end indicators.
+	if !implicit {
+		for token.typ == yaml_DOCUMENT_END_TOKEN {
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	}
+
+	if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+		token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+		token.typ != yaml_DOCUMENT_START_TOKEN &&
+		token.typ != yaml_STREAM_END_TOKEN {
+		// Parse an implicit document.
+		if !yaml_parser_process_directives(parser, nil, nil) {
+			return false
+		}
+		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+		parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+		var head_comment []byte
+		if len(parser.head_comment) > 0 {
+			// [Go] Scan the header comment backwards, and if an empty line is found, break
+			//      the header so the part before the last empty line goes into the
+			//      document header, while the bottom of it goes into a follow up event.
+			for i := len(parser.head_comment) - 1; i > 0; i-- {
+				if parser.head_comment[i] == '\n' {
+					if i == len(parser.head_comment)-1 {
+						head_comment = parser.head_comment[:i]
+						parser.head_comment = parser.head_comment[i+1:]
+						break
+					} else if parser.head_comment[i-1] == '\n' {
+						head_comment = parser.head_comment[:i-1]
+						parser.head_comment = parser.head_comment[i+1:]
+						break
+					}
+				}
+			}
+		}
+
+		*event = yaml_event_t{
+			typ:        yaml_DOCUMENT_START_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+
+			head_comment: head_comment,
+		}
+
+	} else if token.typ != yaml_STREAM_END_TOKEN {
+		// Parse an explicit document.
+		var version_directive *yaml_version_directive_t
+		var tag_directives []yaml_tag_directive_t
+		start_mark := token.start_mark
+		if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+			return false
+		}
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_DOCUMENT_START_TOKEN {
+			yaml_parser_set_parser_error(parser,
+				"did not find expected ", token.start_mark)
+			return false
+		}
+		parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+		parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+		end_mark := token.end_mark
+
+		*event = yaml_event_t{
+			typ:               yaml_DOCUMENT_START_EVENT,
+			start_mark:        start_mark,
+			end_mark:          end_mark,
+			version_directive: version_directive,
+			tag_directives:    tag_directives,
+			implicit:          false,
+		}
+		skip_token(parser)
+
+	} else {
+		// Parse the stream end.
+		parser.state = yaml_PARSE_END_STATE
+		*event = yaml_event_t{
+			typ:        yaml_STREAM_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+		skip_token(parser)
+	}
+
+	return true
+}
+
+// Parse the productions:
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+//	***********
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+		token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+		token.typ == yaml_DOCUMENT_START_TOKEN ||
+		token.typ == yaml_DOCUMENT_END_TOKEN ||
+		token.typ == yaml_STREAM_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		return yaml_parser_process_empty_scalar(parser, event,
+			token.start_mark)
+	}
+	return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document    ::= block_node DOCUMENT-END*
+//
+//	*************
+//
+// explicit_document    ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	start_mark := token.start_mark
+	end_mark := token.start_mark
+
+	implicit := true
+	if token.typ == yaml_DOCUMENT_END_TOKEN {
+		end_mark = token.end_mark
+		skip_token(parser)
+		implicit = false
+	}
+
+	parser.tag_directives = parser.tag_directives[:0]
+
+	parser.state = yaml_PARSE_DOCUMENT_START_STATE
+	*event = yaml_event_t{
+		typ:        yaml_DOCUMENT_END_EVENT,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		implicit:   implicit,
+	}
+	yaml_parser_set_event_comments(parser, event)
+	if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
+		event.foot_comment = event.head_comment
+		event.head_comment = nil
+	}
+	return true
+}
+
+func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
+	event.head_comment = parser.head_comment
+	event.line_comment = parser.line_comment
+	event.foot_comment = parser.foot_comment
+	parser.head_comment = nil
+	parser.line_comment = nil
+	parser.foot_comment = nil
+	parser.tail_comment = nil
+	parser.stem_comment = nil
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence    ::=
+//
+//	ALIAS
+//	*****
+//	| properties (block_content | indentless_block_sequence)?
+//	  **********  *
+//	| block_content | indentless_block_sequence
+//	  *
+//
+// block_node           ::= ALIAS
+//
+//	*****
+//	| properties block_content?
+//	  ********** *
+//	| block_content
+//	  *
+//
+// flow_node            ::= ALIAS
+//
+//	*****
+//	| properties flow_content?
+//	  ********** *
+//	| flow_content
+//	  *
+//
+// properties           ::= TAG ANCHOR? | ANCHOR TAG?
+//
+//	*************************
+//
+// block_content        ::= block_collection | flow_collection | SCALAR
+//
+//	******
+//
+// flow_content         ::= flow_collection | SCALAR
+//
+//	******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+	//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_ALIAS_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		*event = yaml_event_t{
+			typ:        yaml_ALIAS_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+			anchor:     token.value,
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+
+	start_mark := token.start_mark
+	end_mark := token.start_mark
+
+	var tag_token bool
+	var tag_handle, tag_suffix, anchor []byte
+	var tag_mark yaml_mark_t
+	if token.typ == yaml_ANCHOR_TOKEN {
+		anchor = token.value
+		start_mark = token.start_mark
+		end_mark = token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ == yaml_TAG_TOKEN {
+			tag_token = true
+			tag_handle = token.value
+			tag_suffix = token.suffix
+			tag_mark = token.start_mark
+			end_mark = token.end_mark
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	} else if token.typ == yaml_TAG_TOKEN {
+		tag_token = true
+		tag_handle = token.value
+		tag_suffix = token.suffix
+		start_mark = token.start_mark
+		tag_mark = token.start_mark
+		end_mark = token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ == yaml_ANCHOR_TOKEN {
+			anchor = token.value
+			end_mark = token.end_mark
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+		}
+	}
+
+	var tag []byte
+	if tag_token {
+		if len(tag_handle) == 0 {
+			tag = tag_suffix
+			tag_suffix = nil
+		} else {
+			for i := range parser.tag_directives {
+				if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+					tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+					tag = append(tag, tag_suffix...)
+					break
+				}
+			}
+			if len(tag) == 0 {
+				yaml_parser_set_parser_error_context(parser,
+					"while parsing a node", start_mark,
+					"found undefined tag handle", tag_mark)
+				return false
+			}
+		}
+	}
+
+	implicit := len(tag) == 0
+	if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+		}
+		return true
+	}
+	if token.typ == yaml_SCALAR_TOKEN {
+		var plain_implicit, quoted_implicit bool
+		end_mark = token.end_mark
+		if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+			plain_implicit = true
+		} else if len(tag) == 0 {
+			quoted_implicit = true
+		}
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+
+		*event = yaml_event_t{
+			typ:             yaml_SCALAR_EVENT,
+			start_mark:      start_mark,
+			end_mark:        end_mark,
+			anchor:          anchor,
+			tag:             tag,
+			value:           token.value,
+			implicit:        plain_implicit,
+			quoted_implicit: quoted_implicit,
+			style:           yaml_style_t(token.style),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+	if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+		// [Go] Some of the events below can be merged as they differ only on style.
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		return true
+	}
+	if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+		}
+		yaml_parser_set_event_comments(parser, event)
+		return true
+	}
+	if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+		}
+		if parser.stem_comment != nil {
+			event.head_comment = parser.stem_comment
+			parser.stem_comment = nil
+		}
+		return true
+	}
+	if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+		end_mark = token.end_mark
+		parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_START_EVENT,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			anchor:     anchor,
+			tag:        tag,
+			implicit:   implicit,
+			style:      yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+		}
+		if parser.stem_comment != nil {
+			event.head_comment = parser.stem_comment
+			parser.stem_comment = nil
+		}
+		return true
+	}
+	if len(anchor) > 0 || len(tag) > 0 {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+
+		*event = yaml_event_t{
+			typ:             yaml_SCALAR_EVENT,
+			start_mark:      start_mark,
+			end_mark:        end_mark,
+			anchor:          anchor,
+			tag:             tag,
+			implicit:        implicit,
+			quoted_implicit: false,
+			style:           yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+		}
+		return true
+	}
+
+	context := "while parsing a flow node"
+	if block {
+		context = "while parsing a block node"
+	}
+	yaml_parser_set_parser_error_context(parser, context, start_mark,
+		"did not find expected node content", token.start_mark)
+	return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+//
+//	********************  *********** *             *********
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		mark := token.end_mark
+		prior_head_len := len(parser.head_comment)
+		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, true, false)
+		} else {
+			parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+			return yaml_parser_process_empty_scalar(parser, event, mark)
+		}
+	}
+	if token.typ == yaml_BLOCK_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		parser.marks = parser.marks[:len(parser.marks)-1]
+
+		*event = yaml_event_t{
+			typ:        yaml_SEQUENCE_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+
+		skip_token(parser)
+		return true
+	}
+
+	context_mark := parser.marks[len(parser.marks)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	return yaml_parser_set_parser_error_context(parser,
+		"while parsing a block collection", context_mark,
+		"did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence  ::= (BLOCK-ENTRY block_node?)+
+//
+//	*********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+		mark := token.end_mark
+		prior_head_len := len(parser.head_comment)
+		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+			token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, true, false)
+		}
+		parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, mark)
+	}
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+
+	*event = yaml_event_t{
+		typ:        yaml_SEQUENCE_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.start_mark, // [Go] Shouldn't this be token.end_mark?
+	}
+	return true
+}
+
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+	if stem_len == 0 {
+		return
+	}
+
+	token := peek_token(parser)
+	if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+		return
+	}
+
+	parser.stem_comment = parser.head_comment[:stem_len]
+	if len(parser.head_comment) == stem_len {
+		parser.head_comment = nil
+	} else {
+		// Copy suffix to prevent very strange bugs if someone ever appends
+		// further bytes to the prefix in the stem_comment slice above.
+		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+	}
+}
+
+// Parse the productions:
+// block_mapping        ::= BLOCK-MAPPING_START
+//
+//	*******************
+//	((KEY block_node_or_indentless_sequence?)?
+//	  *** *
+//	(VALUE block_node_or_indentless_sequence?)?)*
+//
+//	BLOCK-END
+//	*********
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	// [Go] A tail comment was left from the prior mapping value processed. Emit an event
+	//      as it needs to be processed with that value and not the following key.
+	if len(parser.tail_comment) > 0 {
+		*event = yaml_event_t{
+			typ:          yaml_TAIL_COMMENT_EVENT,
+			start_mark:   token.start_mark,
+			end_mark:     token.end_mark,
+			foot_comment: parser.tail_comment,
+		}
+		parser.tail_comment = nil
+		return true
+	}
+
+	if token.typ == yaml_KEY_TOKEN {
+		mark := token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+			return yaml_parser_parse_node(parser, event, true, true)
+		} else {
+			parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+			return yaml_parser_process_empty_scalar(parser, event, mark)
+		}
+	} else if token.typ == yaml_BLOCK_END_TOKEN {
+		parser.state = parser.states[len(parser.states)-1]
+		parser.states = parser.states[:len(parser.states)-1]
+		parser.marks = parser.marks[:len(parser.marks)-1]
+		*event = yaml_event_t{
+			typ:        yaml_MAPPING_END_EVENT,
+			start_mark: token.start_mark,
+			end_mark:   token.end_mark,
+		}
+		yaml_parser_set_event_comments(parser, event)
+		skip_token(parser)
+		return true
+	}
+
+	context_mark := parser.marks[len(parser.marks)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	return yaml_parser_set_parser_error_context(parser,
+		"while parsing a block mapping", context_mark,
+		"did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping        ::= BLOCK-MAPPING_START
+//
+//	((KEY block_node_or_indentless_sequence?)?
+//
+//	(VALUE block_node_or_indentless_sequence?)?)*
+//	 ***** *
+//	BLOCK-END
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		mark := token.end_mark
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_KEY_TOKEN &&
+			token.typ != yaml_VALUE_TOKEN &&
+			token.typ != yaml_BLOCK_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+			return yaml_parser_parse_node(parser, event, true, true)
+		}
+		parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, mark)
+	}
+	parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence        ::= FLOW-SEQUENCE-START
+//
+//	*******************
+//	(flow_sequence_entry FLOW-ENTRY)*
+//	 *                   **********
+//	flow_sequence_entry?
+//	*
+//	FLOW-SEQUENCE-END
+//	*****************
+//
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+		if !first {
+			if token.typ == yaml_FLOW_ENTRY_TOKEN {
+				skip_token(parser)
+				token = peek_token(parser)
+				if token == nil {
+					return false
+				}
+			} else {
+				context_mark := parser.marks[len(parser.marks)-1]
+				parser.marks = parser.marks[:len(parser.marks)-1]
+				return yaml_parser_set_parser_error_context(parser,
+					"while parsing a flow sequence", context_mark,
+					"did not find expected ',' or ']'", token.start_mark)
+			}
+		}
+
+		if token.typ == yaml_KEY_TOKEN {
+			parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+			*event = yaml_event_t{
+				typ:        yaml_MAPPING_START_EVENT,
+				start_mark: token.start_mark,
+				end_mark:   token.end_mark,
+				implicit:   true,
+				style:      yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+			}
+			skip_token(parser)
+			return true
+		} else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+
+	*event = yaml_event_t{
+		typ:        yaml_SEQUENCE_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+	}
+	yaml_parser_set_event_comments(parser, event)
+
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*** *
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ != yaml_VALUE_TOKEN &&
+		token.typ != yaml_FLOW_ENTRY_TOKEN &&
+		token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+		parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+		return yaml_parser_parse_node(parser, event, false, false)
+	}
+	mark := token.end_mark
+	skip_token(parser)
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+	return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	***** *
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		skip_token(parser)
+		token := peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry  ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//
+//	*
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+	*event = yaml_event_t{
+		typ:        yaml_MAPPING_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.start_mark, // [Go] Shouldn't this be end_mark?
+	}
+	return true
+}
+
+// Parse the productions:
+// flow_mapping         ::= FLOW-MAPPING-START
+//
+//	******************
+//	(flow_mapping_entry FLOW-ENTRY)*
+//	 *                  **********
+//	flow_mapping_entry?
+//	******************
+//	FLOW-MAPPING-END
+//	****************
+//
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//   - *** *
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+	if first {
+		token := peek_token(parser)
+		parser.marks = append(parser.marks, token.start_mark)
+		skip_token(parser)
+	}
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+		if !first {
+			if token.typ == yaml_FLOW_ENTRY_TOKEN {
+				skip_token(parser)
+				token = peek_token(parser)
+				if token == nil {
+					return false
+				}
+			} else {
+				context_mark := parser.marks[len(parser.marks)-1]
+				parser.marks = parser.marks[:len(parser.marks)-1]
+				return yaml_parser_set_parser_error_context(parser,
+					"while parsing a flow mapping", context_mark,
+					"did not find expected ',' or '}'", token.start_mark)
+			}
+		}
+
+		if token.typ == yaml_KEY_TOKEN {
+			skip_token(parser)
+			token = peek_token(parser)
+			if token == nil {
+				return false
+			}
+			if token.typ != yaml_VALUE_TOKEN &&
+				token.typ != yaml_FLOW_ENTRY_TOKEN &&
+				token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+				parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+				return yaml_parser_parse_node(parser, event, false, false)
+			} else {
+				parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+				return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+			}
+		} else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+
+	parser.state = parser.states[len(parser.states)-1]
+	parser.states = parser.states[:len(parser.states)-1]
+	parser.marks = parser.marks[:len(parser.marks)-1]
+	*event = yaml_event_t{
+		typ:        yaml_MAPPING_END_EVENT,
+		start_mark: token.start_mark,
+		end_mark:   token.end_mark,
+	}
+	yaml_parser_set_event_comments(parser, event)
+	skip_token(parser)
+	return true
+}
+
+// Parse the productions:
+// flow_mapping_entry   ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+//   - ***** *
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+	if empty {
+		parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+		return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+	}
+	if token.typ == yaml_VALUE_TOKEN {
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+		if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+			parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+			return yaml_parser_parse_node(parser, event, false, false)
+		}
+	}
+	parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+	return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+	*event = yaml_event_t{
+		typ:        yaml_SCALAR_EVENT,
+		start_mark: mark,
+		end_mark:   mark,
+		value:      nil, // Empty
+		implicit:   true,
+		style:      yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+	}
+	return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+	{[]byte("!"), []byte("!")},
+	{[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+	version_directive_ref **yaml_version_directive_t,
+	tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+	var version_directive *yaml_version_directive_t
+	var tag_directives []yaml_tag_directive_t
+
+	token := peek_token(parser)
+	if token == nil {
+		return false
+	}
+
+	for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+		if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+			if version_directive != nil {
+				yaml_parser_set_parser_error(parser,
+					"found duplicate %YAML directive", token.start_mark)
+				return false
+			}
+			if token.major != 1 || token.minor != 1 {
+				yaml_parser_set_parser_error(parser,
+					"found incompatible YAML document", token.start_mark)
+				return false
+			}
+			version_directive = &yaml_version_directive_t{
+				major: token.major,
+				minor: token.minor,
+			}
+		} else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+			value := yaml_tag_directive_t{
+				handle: token.value,
+				prefix: token.prefix,
+			}
+			if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+				return false
+			}
+			tag_directives = append(tag_directives, value)
+		}
+
+		skip_token(parser)
+		token = peek_token(parser)
+		if token == nil {
+			return false
+		}
+	}
+
+	for i := range default_tag_directives {
+		if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+			return false
+		}
+	}
+
+	if version_directive_ref != nil {
+		*version_directive_ref = version_directive
+	}
+	if tag_directives_ref != nil {
+		*tag_directives_ref = tag_directives
+	}
+	return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+	for i := range parser.tag_directives {
+		if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+			if allow_duplicates {
+				return true
+			}
+			return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+		}
+	}
+
+	// [Go] I suspect the copy is unnecessary. This was likely done
+	// because there was no way to track ownership of the data.
+	value_copy := yaml_tag_directive_t{
+		handle: make([]byte, len(value.handle)),
+		prefix: make([]byte, len(value.prefix)),
+	}
+	copy(value_copy.handle, value.handle)
+	copy(value_copy.prefix, value.prefix)
+	parser.tag_directives = append(parser.tag_directives, value_copy)
+	return true
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/readerc.go b/notifier/vendor/go.yaml.in/yaml/v3/readerc.go
new file mode 100644
index 00000000..56af2453
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/readerc.go
@@ -0,0 +1,434 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+	parser.error = yaml_READER_ERROR
+	parser.problem = problem
+	parser.problem_offset = offset
+	parser.problem_value = value
+	return false
+}
+
+// Byte order marks.
+const (
+	bom_UTF8    = "\xef\xbb\xbf"
+	bom_UTF16LE = "\xff\xfe"
+	bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+	// Ensure that we had enough bytes in the raw buffer.
+	for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+		if !yaml_parser_update_raw_buffer(parser) {
+			return false
+		}
+	}
+
+	// Determine the encoding.
+	buf := parser.raw_buffer
+	pos := parser.raw_buffer_pos
+	avail := len(buf) - pos
+	if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+		parser.encoding = yaml_UTF16LE_ENCODING
+		parser.raw_buffer_pos += 2
+		parser.offset += 2
+	} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+		parser.encoding = yaml_UTF16BE_ENCODING
+		parser.raw_buffer_pos += 2
+		parser.offset += 2
+	} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+		parser.encoding = yaml_UTF8_ENCODING
+		parser.raw_buffer_pos += 3
+		parser.offset += 3
+	} else {
+		parser.encoding = yaml_UTF8_ENCODING
+	}
+	return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+	size_read := 0
+
+	// Return if the raw buffer is full.
+	if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+		return true
+	}
+
+	// Return on EOF.
+	if parser.eof {
+		return true
+	}
+
+	// Move the remaining bytes in the raw buffer to the beginning.
+	if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+		copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+	}
+	parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+	parser.raw_buffer_pos = 0
+
+	// Call the read handler to fill the buffer.
+	size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+	parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+	if err == io.EOF {
+		parser.eof = true
+	} else if err != nil {
+		return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+	}
+	return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+	if parser.read_handler == nil {
+		panic("read handler must be set")
+	}
+
+	// [Go] This function was changed to guarantee the requested length size at EOF.
+	// The fact we need to do this is pretty awful, but the description above implies
+	// for that to be the case, and there are tests
+
+	// If the EOF flag is set and the raw buffer is empty, do nothing.
+	if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+		// [Go] ACTUALLY! Read the documentation of this function above.
+		// This is just broken. To return true, we need to have the
+		// given length in the buffer. Not doing that means every single
+		// check that calls this function to make sure the buffer has a
+		// given length is Go) panicking; or C) accessing invalid memory.
+		//return true
+	}
+
+	// Return if the buffer contains enough characters.
+	if parser.unread >= length {
+		return true
+	}
+
+	// Determine the input encoding if it is not known yet.
+	if parser.encoding == yaml_ANY_ENCODING {
+		if !yaml_parser_determine_encoding(parser) {
+			return false
+		}
+	}
+
+	// Move the unread characters to the beginning of the buffer.
+	buffer_len := len(parser.buffer)
+	if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+		copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+		buffer_len -= parser.buffer_pos
+		parser.buffer_pos = 0
+	} else if parser.buffer_pos == buffer_len {
+		buffer_len = 0
+		parser.buffer_pos = 0
+	}
+
+	// Open the whole buffer for writing, and cut it before returning.
+	parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+	// Fill the buffer until it has enough characters.
+	first := true
+	for parser.unread < length {
+
+		// Fill the raw buffer if necessary.
+		if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+			if !yaml_parser_update_raw_buffer(parser) {
+				parser.buffer = parser.buffer[:buffer_len]
+				return false
+			}
+		}
+		first = false
+
+		// Decode the raw buffer.
+	inner:
+		for parser.raw_buffer_pos != len(parser.raw_buffer) {
+			var value rune
+			var width int
+
+			raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+			// Decode the next character.
+			switch parser.encoding {
+			case yaml_UTF8_ENCODING:
+				// Decode a UTF-8 character.  Check RFC 3629
+				// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+				//
+				// The following table (taken from the RFC) is used for
+				// decoding.
+				//
+				//    Char. number range |        UTF-8 octet sequence
+				//      (hexadecimal)    |              (binary)
+				//   --------------------+------------------------------------
+				//   0000 0000-0000 007F | 0xxxxxxx
+				//   0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+				//   0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+				//   0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+				//
+				// Additionally, the characters in the range 0xD800-0xDFFF
+				// are prohibited as they are reserved for use with UTF-16
+				// surrogate pairs.
+
+				// Determine the length of the UTF-8 sequence.
+				octet := parser.raw_buffer[parser.raw_buffer_pos]
+				switch {
+				case octet&0x80 == 0x00:
+					width = 1
+				case octet&0xE0 == 0xC0:
+					width = 2
+				case octet&0xF0 == 0xE0:
+					width = 3
+				case octet&0xF8 == 0xF0:
+					width = 4
+				default:
+					// The leading octet is invalid.
+					return yaml_parser_set_reader_error(parser,
+						"invalid leading UTF-8 octet",
+						parser.offset, int(octet))
+				}
+
+				// Check if the raw buffer contains an incomplete character.
+				if width > raw_unread {
+					if parser.eof {
+						return yaml_parser_set_reader_error(parser,
+							"incomplete UTF-8 octet sequence",
+							parser.offset, -1)
+					}
+					break inner
+				}
+
+				// Decode the leading octet.
+				switch {
+				case octet&0x80 == 0x00:
+					value = rune(octet & 0x7F)
+				case octet&0xE0 == 0xC0:
+					value = rune(octet & 0x1F)
+				case octet&0xF0 == 0xE0:
+					value = rune(octet & 0x0F)
+				case octet&0xF8 == 0xF0:
+					value = rune(octet & 0x07)
+				default:
+					value = 0
+				}
+
+				// Check and decode the trailing octets.
+				for k := 1; k < width; k++ {
+					octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+					// Check if the octet is valid.
+					if (octet & 0xC0) != 0x80 {
+						return yaml_parser_set_reader_error(parser,
+							"invalid trailing UTF-8 octet",
+							parser.offset+k, int(octet))
+					}
+
+					// Decode the octet.
+					value = (value << 6) + rune(octet&0x3F)
+				}
+
+				// Check the length of the sequence against the value.
+				switch {
+				case width == 1:
+				case width == 2 && value >= 0x80:
+				case width == 3 && value >= 0x800:
+				case width == 4 && value >= 0x10000:
+				default:
+					return yaml_parser_set_reader_error(parser,
+						"invalid length of a UTF-8 sequence",
+						parser.offset, -1)
+				}
+
+				// Check the range of the value.
+				if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+					return yaml_parser_set_reader_error(parser,
+						"invalid Unicode character",
+						parser.offset, int(value))
+				}
+
+			case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+				var low, high int
+				if parser.encoding == yaml_UTF16LE_ENCODING {
+					low, high = 0, 1
+				} else {
+					low, high = 1, 0
+				}
+
+				// The UTF-16 encoding is not as simple as one might
+				// naively think.  Check RFC 2781
+				// (http://www.ietf.org/rfc/rfc2781.txt).
+				//
+				// Normally, two subsequent bytes describe a Unicode
+				// character.  However a special technique (called a
+				// surrogate pair) is used for specifying character
+				// values larger than 0xFFFF.
+				//
+				// A surrogate pair consists of two pseudo-characters:
+				//      high surrogate area (0xD800-0xDBFF)
+				//      low surrogate area (0xDC00-0xDFFF)
+				//
+				// The following formulas are used for decoding
+				// and encoding characters using surrogate pairs:
+				//
+				//  U  = U' + 0x10000   (0x01 00 00 <= U <= 0x10 FF FF)
+				//  U' = yyyyyyyyyyxxxxxxxxxx   (0 <= U' <= 0x0F FF FF)
+				//  W1 = 110110yyyyyyyyyy
+				//  W2 = 110111xxxxxxxxxx
+				//
+				// where U is the character value, W1 is the high surrogate
+				// area, W2 is the low surrogate area.
+
+				// Check for incomplete UTF-16 character.
+				if raw_unread < 2 {
+					if parser.eof {
+						return yaml_parser_set_reader_error(parser,
+							"incomplete UTF-16 character",
+							parser.offset, -1)
+					}
+					break inner
+				}
+
+				// Get the character.
+				value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+					(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+				// Check for unexpected low surrogate area.
+				if value&0xFC00 == 0xDC00 {
+					return yaml_parser_set_reader_error(parser,
+						"unexpected low surrogate area",
+						parser.offset, int(value))
+				}
+
+				// Check for a high surrogate area.
+				if value&0xFC00 == 0xD800 {
+					width = 4
+
+					// Check for incomplete surrogate pair.
+					if raw_unread < 4 {
+						if parser.eof {
+							return yaml_parser_set_reader_error(parser,
+								"incomplete UTF-16 surrogate pair",
+								parser.offset, -1)
+						}
+						break inner
+					}
+
+					// Get the next character.
+					value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+						(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+					// Check for a low surrogate area.
+					if value2&0xFC00 != 0xDC00 {
+						return yaml_parser_set_reader_error(parser,
+							"expected low surrogate area",
+							parser.offset+2, int(value2))
+					}
+
+					// Generate the value of the surrogate pair.
+					value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+				} else {
+					width = 2
+				}
+
+			default:
+				panic("impossible")
+			}
+
+			// Check if the character is in the allowed range:
+			//      #x9 | #xA | #xD | [#x20-#x7E]               (8 bit)
+			//      | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD]    (16 bit)
+			//      | [#x10000-#x10FFFF]                        (32 bit)
+			switch {
+			case value == 0x09:
+			case value == 0x0A:
+			case value == 0x0D:
+			case value >= 0x20 && value <= 0x7E:
+			case value == 0x85:
+			case value >= 0xA0 && value <= 0xD7FF:
+			case value >= 0xE000 && value <= 0xFFFD:
+			case value >= 0x10000 && value <= 0x10FFFF:
+			default:
+				return yaml_parser_set_reader_error(parser,
+					"control characters are not allowed",
+					parser.offset, int(value))
+			}
+
+			// Move the raw pointers.
+			parser.raw_buffer_pos += width
+			parser.offset += width
+
+			// Finally put the character into the buffer.
+			if value <= 0x7F {
+				// 0000 0000-0000 007F . 0xxxxxxx
+				parser.buffer[buffer_len+0] = byte(value)
+				buffer_len += 1
+			} else if value <= 0x7FF {
+				// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+				parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+				buffer_len += 2
+			} else if value <= 0xFFFF {
+				// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+				parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+				parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+				buffer_len += 3
+			} else {
+				// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+				parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+				parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+				parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+				parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+				buffer_len += 4
+			}
+
+			parser.unread++
+		}
+
+		// On EOF, put NUL into the buffer and return.
+		if parser.eof {
+			parser.buffer[buffer_len] = 0
+			buffer_len++
+			parser.unread++
+			break
+		}
+	}
+	// [Go] Read the documentation of this function above. To return true,
+	// we need to have the given length in the buffer. Not doing that means
+	// every single check that calls this function to make sure the buffer
+	// has a given length is Go) panicking; or C) accessing invalid memory.
+	// This happens here due to the EOF above breaking early.
+	for buffer_len < length {
+		parser.buffer[buffer_len] = 0
+		buffer_len++
+	}
+	parser.buffer = parser.buffer[:buffer_len]
+	return true
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/resolve.go b/notifier/vendor/go.yaml.in/yaml/v3/resolve.go
new file mode 100644
index 00000000..64ae8880
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/resolve.go
@@ -0,0 +1,326 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"encoding/base64"
+	"math"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type resolveMapItem struct {
+	value interface{}
+	tag   string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+	t := resolveTable
+	t[int('+')] = 'S' // Sign
+	t[int('-')] = 'S'
+	for _, c := range "0123456789" {
+		t[int(c)] = 'D' // Digit
+	}
+	for _, c := range "yYnNtTfFoO~" {
+		t[int(c)] = 'M' // In map
+	}
+	t[int('.')] = '.' // Float (potentially in map)
+
+	var resolveMapList = []struct {
+		v   interface{}
+		tag string
+		l   []string
+	}{
+		{true, boolTag, []string{"true", "True", "TRUE"}},
+		{false, boolTag, []string{"false", "False", "FALSE"}},
+		{nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+		{math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+		{math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+		{math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+		{math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+		{"<<", mergeTag, []string{"<<"}},
+	}
+
+	m := resolveMap
+	for _, item := range resolveMapList {
+		for _, s := range item.l {
+			m[s] = resolveMapItem{item.v, item.tag}
+		}
+	}
+}
+
+const (
+	nullTag      = "!!null"
+	boolTag      = "!!bool"
+	strTag       = "!!str"
+	intTag       = "!!int"
+	floatTag     = "!!float"
+	timestampTag = "!!timestamp"
+	seqTag       = "!!seq"
+	mapTag       = "!!map"
+	binaryTag    = "!!binary"
+	mergeTag     = "!!merge"
+)
+
+var longTags = make(map[string]string)
+var shortTags = make(map[string]string)
+
+func init() {
+	for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+		ltag := longTag(stag)
+		longTags[stag] = ltag
+		shortTags[ltag] = stag
+	}
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+	if strings.HasPrefix(tag, longTagPrefix) {
+		if stag, ok := shortTags[tag]; ok {
+			return stag
+		}
+		return "!!" + tag[len(longTagPrefix):]
+	}
+	return tag
+}
+
+func longTag(tag string) string {
+	if strings.HasPrefix(tag, "!!") {
+		if ltag, ok := longTags[tag]; ok {
+			return ltag
+		}
+		return longTagPrefix + tag[2:]
+	}
+	return tag
+}
+
+func resolvableTag(tag string) bool {
+	switch tag {
+	case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
+		return true
+	}
+	return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+	tag = shortTag(tag)
+	if !resolvableTag(tag) {
+		return tag, in
+	}
+
+	defer func() {
+		switch tag {
+		case "", rtag, strTag, binaryTag:
+			return
+		case floatTag:
+			if rtag == intTag {
+				switch v := out.(type) {
+				case int64:
+					rtag = floatTag
+					out = float64(v)
+					return
+				case int:
+					rtag = floatTag
+					out = float64(v)
+					return
+				}
+			}
+		}
+		failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+	}()
+
+	// Any data is accepted as a !!str or !!binary.
+	// Otherwise, the prefix is enough of a hint about what it might be.
+	hint := byte('N')
+	if in != "" {
+		hint = resolveTable[in[0]]
+	}
+	if hint != 0 && tag != strTag && tag != binaryTag {
+		// Handle things we can lookup in a map.
+		if item, ok := resolveMap[in]; ok {
+			return item.tag, item.value
+		}
+
+		// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+		// are purposefully unsupported here. They're still quoted on
+		// the way out for compatibility with other parser, though.
+
+		switch hint {
+		case 'M':
+			// We've already checked the map above.
+
+		case '.':
+			// Not in the map, so maybe a normal float.
+			floatv, err := strconv.ParseFloat(in, 64)
+			if err == nil {
+				return floatTag, floatv
+			}
+
+		case 'D', 'S':
+			// Int, float, or timestamp.
+			// Only try values as a timestamp if the value is unquoted or there's an explicit
+			// !!timestamp tag.
+			if tag == "" || tag == timestampTag {
+				t, ok := parseTimestamp(in)
+				if ok {
+					return timestampTag, t
+				}
+			}
+
+			plain := strings.Replace(in, "_", "", -1)
+			intv, err := strconv.ParseInt(plain, 0, 64)
+			if err == nil {
+				if intv == int64(int(intv)) {
+					return intTag, int(intv)
+				} else {
+					return intTag, intv
+				}
+			}
+			uintv, err := strconv.ParseUint(plain, 0, 64)
+			if err == nil {
+				return intTag, uintv
+			}
+			if yamlStyleFloat.MatchString(plain) {
+				floatv, err := strconv.ParseFloat(plain, 64)
+				if err == nil {
+					return floatTag, floatv
+				}
+			}
+			if strings.HasPrefix(plain, "0b") {
+				intv, err := strconv.ParseInt(plain[2:], 2, 64)
+				if err == nil {
+					if intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+				uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+				if err == nil {
+					return intTag, uintv
+				}
+			} else if strings.HasPrefix(plain, "-0b") {
+				intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
+				if err == nil {
+					if true || intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+			}
+			// Octals as introduced in version 1.2 of the spec.
+			// Octals from the 1.1 spec, spelled as 0777, are still
+			// decoded by default in v3 as well for compatibility.
+			// May be dropped in v4 depending on how usage evolves.
+			if strings.HasPrefix(plain, "0o") {
+				intv, err := strconv.ParseInt(plain[2:], 8, 64)
+				if err == nil {
+					if intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+				uintv, err := strconv.ParseUint(plain[2:], 8, 64)
+				if err == nil {
+					return intTag, uintv
+				}
+			} else if strings.HasPrefix(plain, "-0o") {
+				intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
+				if err == nil {
+					if true || intv == int64(int(intv)) {
+						return intTag, int(intv)
+					} else {
+						return intTag, intv
+					}
+				}
+			}
+		default:
+			panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
+		}
+	}
+	return strTag, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+	const lineLen = 70
+	encLen := base64.StdEncoding.EncodedLen(len(s))
+	lines := encLen/lineLen + 1
+	buf := make([]byte, encLen*2+lines)
+	in := buf[0:encLen]
+	out := buf[encLen:]
+	base64.StdEncoding.Encode(in, []byte(s))
+	k := 0
+	for i := 0; i < len(in); i += lineLen {
+		j := i + lineLen
+		if j > len(in) {
+			j = len(in)
+		}
+		k += copy(out[k:], in[i:j])
+		if lines > 1 {
+			out[k] = '\n'
+			k++
+		}
+	}
+	return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+	"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+	"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+	"2006-1-2 15:4:5.999999999",       // space separated with no time zone
+	"2006-1-2",                        // date only
+	// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+	// from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+	// TODO write code to check all the formats supported by
+	// http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+	// Quick check: all date formats start with YYYY-.
+	i := 0
+	for ; i < len(s); i++ {
+		if c := s[i]; c < '0' || c > '9' {
+			break
+		}
+	}
+	if i != 4 || i == len(s) || s[i] != '-' {
+		return time.Time{}, false
+	}
+	for _, format := range allowedTimestampFormats {
+		if t, err := time.Parse(format, s); err == nil {
+			return t, true
+		}
+	}
+	return time.Time{}, false
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/scannerc.go b/notifier/vendor/go.yaml.in/yaml/v3/scannerc.go
new file mode 100644
index 00000000..30b1f089
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/scannerc.go
@@ -0,0 +1,3040 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html).  We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward.  The issues are "block collection start" and
+// "simple keys".  Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented.  We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+//      STREAM-START(encoding)          # The stream start.
+//      STREAM-END                      # The stream end.
+//      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
+//      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
+//      DOCUMENT-START                  # '---'
+//      DOCUMENT-END                    # '...'
+//      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
+//      BLOCK-MAPPING-START             # sequence or a block mapping.
+//      BLOCK-END                       # Indentation decrease.
+//      FLOW-SEQUENCE-START             # '['
+//      FLOW-SEQUENCE-END               # ']'
+//      BLOCK-SEQUENCE-START            # '{'
+//      BLOCK-SEQUENCE-END              # '}'
+//      BLOCK-ENTRY                     # '-'
+//      FLOW-ENTRY                      # ','
+//      KEY                             # '?' or nothing (simple keys).
+//      VALUE                           # ':'
+//      ALIAS(anchor)                   # '*anchor'
+//      ANCHOR(anchor)                  # '&anchor'
+//      TAG(handle,suffix)              # '!handle!suffix'
+//      SCALAR(value,style)             # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+//      STREAM-START(encoding)
+//      STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+//      VERSION-DIRECTIVE(major,minor)
+//      TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+//      %YAML   1.1
+//      %TAG    !   !foo
+//      %TAG    !yaml!  tag:yaml.org,2002:
+//      ---
+//
+// The correspoding sequence of tokens:
+//
+//      STREAM-START(utf-8)
+//      VERSION-DIRECTIVE(1,1)
+//      TAG-DIRECTIVE("!","!foo")
+//      TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+//      DOCUMENT-START
+//      STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+//      DOCUMENT-START
+//      DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+//      1. An implicit document:
+//
+//          'a scalar'
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          SCALAR("a scalar",single-quoted)
+//          STREAM-END
+//
+//      2. An explicit document:
+//
+//          ---
+//          'a scalar'
+//          ...
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          DOCUMENT-START
+//          SCALAR("a scalar",single-quoted)
+//          DOCUMENT-END
+//          STREAM-END
+//
+//      3. Several documents in a stream:
+//
+//          'a scalar'
+//          ---
+//          'another scalar'
+//          ---
+//          'yet another scalar'
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          SCALAR("a scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("another scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("yet another scalar",single-quoted)
+//          STREAM-END
+//
+// We have already introduced the SCALAR token above.  The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+//      ALIAS(anchor)
+//      ANCHOR(anchor)
+//      TAG(handle,suffix)
+//      SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+//      1. A recursive sequence:
+//
+//          &A [ *A ]
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          ANCHOR("A")
+//          FLOW-SEQUENCE-START
+//          ALIAS("A")
+//          FLOW-SEQUENCE-END
+//          STREAM-END
+//
+//      2. A tagged scalar:
+//
+//          !!float "3.14"  # A good approximation.
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          TAG("!!","float")
+//          SCALAR("3.14",double-quoted)
+//          STREAM-END
+//
+//      3. Various scalar styles:
+//
+//          --- # Implicit empty plain scalars do not produce tokens.
+//          --- a plain scalar
+//          --- 'a single-quoted scalar'
+//          --- "a double-quoted scalar"
+//          --- |-
+//            a literal scalar
+//          --- >-
+//            a folded
+//            scalar
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          DOCUMENT-START
+//          DOCUMENT-START
+//          SCALAR("a plain scalar",plain)
+//          DOCUMENT-START
+//          SCALAR("a single-quoted scalar",single-quoted)
+//          DOCUMENT-START
+//          SCALAR("a double-quoted scalar",double-quoted)
+//          DOCUMENT-START
+//          SCALAR("a literal scalar",literal)
+//          DOCUMENT-START
+//          SCALAR("a folded scalar",folded)
+//          STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+//      FLOW-SEQUENCE-START
+//      FLOW-SEQUENCE-END
+//      FLOW-MAPPING-START
+//      FLOW-MAPPING-END
+//      FLOW-ENTRY
+//      KEY
+//      VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly.  FLOW-ENTRY represent the ',' indicator.  Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+//      1. A flow sequence:
+//
+//          [item 1, item 2, item 3]
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          FLOW-SEQUENCE-START
+//          SCALAR("item 1",plain)
+//          FLOW-ENTRY
+//          SCALAR("item 2",plain)
+//          FLOW-ENTRY
+//          SCALAR("item 3",plain)
+//          FLOW-SEQUENCE-END
+//          STREAM-END
+//
+//      2. A flow mapping:
+//
+//          {
+//              a simple key: a value,  # Note that the KEY token is produced.
+//              ? a complex key: another value,
+//          }
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          FLOW-MAPPING-START
+//          KEY
+//          SCALAR("a simple key",plain)
+//          VALUE
+//          SCALAR("a value",plain)
+//          FLOW-ENTRY
+//          KEY
+//          SCALAR("a complex key",plain)
+//          VALUE
+//          SCALAR("another value",plain)
+//          FLOW-ENTRY
+//          FLOW-MAPPING-END
+//          STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator.  Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+//      BLOCK-SEQUENCE-START
+//      BLOCK-MAPPING-START
+//      BLOCK-END
+//      BLOCK-ENTRY
+//      KEY
+//      VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python).  However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+//      1. Block sequences:
+//
+//          - item 1
+//          - item 2
+//          -
+//            - item 3.1
+//            - item 3.2
+//          -
+//            key 1: value 1
+//            key 2: value 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-ENTRY
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 3.1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 3.2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+//      2. Block mappings:
+//
+//          a simple key: a value   # The KEY token is produced here.
+//          ? a complex key
+//          : another value
+//          a mapping:
+//            key 1: value 1
+//            key 2: value 2
+//          a sequence:
+//            - item 1
+//            - item 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("a simple key",plain)
+//          VALUE
+//          SCALAR("a value",plain)
+//          KEY
+//          SCALAR("a complex key",plain)
+//          VALUE
+//          SCALAR("another value",plain)
+//          KEY
+//          SCALAR("a mapping",plain)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          KEY
+//          SCALAR("a sequence",plain)
+//          VALUE
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line.  If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line.  The following examples
+// illustrate this case:
+//
+//      1. Collections in a sequence:
+//
+//          - - item 1
+//            - item 2
+//          - key 1: value 1
+//            key 2: value 2
+//          - ? complex key
+//            : complex value
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-ENTRY
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("complex key")
+//          VALUE
+//          SCALAR("complex value")
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+//      2. Collections in a mapping:
+//
+//          ? a sequence
+//          : - item 1
+//            - item 2
+//          ? a mapping
+//          : key 1: value 1
+//            key 2: value 2
+//
+//      Tokens:
+//
+//          STREAM-START(utf-8)
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("a sequence",plain)
+//          VALUE
+//          BLOCK-SEQUENCE-START
+//          BLOCK-ENTRY
+//          SCALAR("item 1",plain)
+//          BLOCK-ENTRY
+//          SCALAR("item 2",plain)
+//          BLOCK-END
+//          KEY
+//          SCALAR("a mapping",plain)
+//          VALUE
+//          BLOCK-MAPPING-START
+//          KEY
+//          SCALAR("key 1",plain)
+//          VALUE
+//          SCALAR("value 1",plain)
+//          KEY
+//          SCALAR("key 2",plain)
+//          VALUE
+//          SCALAR("value 2",plain)
+//          BLOCK-END
+//          BLOCK-END
+//          STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping.  In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+//      key:
+//      - item 1    # BLOCK-SEQUENCE-START is NOT produced here.
+//      - item 2
+//
+// Tokens:
+//
+//      STREAM-START(utf-8)
+//      BLOCK-MAPPING-START
+//      KEY
+//      SCALAR("key",plain)
+//      VALUE
+//      BLOCK-ENTRY
+//      SCALAR("item 1",plain)
+//      BLOCK-ENTRY
+//      SCALAR("item 2",plain)
+//      BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+	// [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+	return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		parser.newlines = 0
+	}
+	parser.mark.index++
+	parser.mark.column++
+	parser.unread--
+	parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+	if is_crlf(parser.buffer, parser.buffer_pos) {
+		parser.mark.index += 2
+		parser.mark.column = 0
+		parser.mark.line++
+		parser.unread -= 2
+		parser.buffer_pos += 2
+		parser.newlines++
+	} else if is_break(parser.buffer, parser.buffer_pos) {
+		parser.mark.index++
+		parser.mark.column = 0
+		parser.mark.line++
+		parser.unread--
+		parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+		parser.newlines++
+	}
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		parser.newlines = 0
+	}
+	w := width(parser.buffer[parser.buffer_pos])
+	if w == 0 {
+		panic("invalid character sequence")
+	}
+	if len(s) == 0 {
+		s = make([]byte, 0, 32)
+	}
+	if w == 1 && len(s)+w <= cap(s) {
+		s = s[:len(s)+1]
+		s[len(s)-1] = parser.buffer[parser.buffer_pos]
+		parser.buffer_pos++
+	} else {
+		s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+		parser.buffer_pos += w
+	}
+	parser.mark.index++
+	parser.mark.column++
+	parser.unread--
+	return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+	buf := parser.buffer
+	pos := parser.buffer_pos
+	switch {
+	case buf[pos] == '\r' && buf[pos+1] == '\n':
+		// CR LF . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 2
+		parser.mark.index++
+		parser.unread--
+	case buf[pos] == '\r' || buf[pos] == '\n':
+		// CR|LF . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 1
+	case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+		// NEL . LF
+		s = append(s, '\n')
+		parser.buffer_pos += 2
+	case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+		// LS|PS . LS|PS
+		s = append(s, buf[parser.buffer_pos:pos+3]...)
+		parser.buffer_pos += 3
+	default:
+		return s
+	}
+	parser.mark.index++
+	parser.mark.column = 0
+	parser.mark.line++
+	parser.unread--
+	parser.newlines++
+	return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+	// Erase the token object.
+	*token = yaml_token_t{} // [Go] Is this necessary?
+
+	// No tokens after STREAM-END or error.
+	if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+		return true
+	}
+
+	// Ensure that the tokens queue contains enough tokens.
+	if !parser.token_available {
+		if !yaml_parser_fetch_more_tokens(parser) {
+			return false
+		}
+	}
+
+	// Fetch the next token from the queue.
+	*token = parser.tokens[parser.tokens_head]
+	parser.tokens_head++
+	parser.tokens_parsed++
+	parser.token_available = false
+
+	if token.typ == yaml_STREAM_END_TOKEN {
+		parser.stream_end_produced = true
+	}
+	return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+	parser.error = yaml_SCANNER_ERROR
+	parser.context = context
+	parser.context_mark = context_mark
+	parser.problem = problem
+	parser.problem_mark = parser.mark
+	return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+	context := "while parsing a tag"
+	if directive {
+		context = "while parsing a %TAG directive"
+	}
+	return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+	pargs := append([]interface{}{"+++"}, args...)
+	fmt.Println(pargs...)
+	pargs = append([]interface{}{"---"}, args...)
+	return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+	// While we need more tokens to fetch, do it.
+	for {
+		// [Go] The comment parsing logic requires a lookahead of two tokens
+		// so that foot comments may be parsed in time of associating them
+		// with the tokens that are parsed before them, and also for line
+		// comments to be transformed into head comments in some edge cases.
+		if parser.tokens_head < len(parser.tokens)-2 {
+			// If a potential simple key is at the head position, we need to fetch
+			// the next token to disambiguate it.
+			head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
+			if !ok {
+				break
+			} else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
+				return false
+			} else if !valid {
+				break
+			}
+		}
+		// Fetch the next token.
+		if !yaml_parser_fetch_next_token(parser) {
+			return false
+		}
+	}
+
+	parser.token_available = true
+	return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
+	// Ensure that the buffer is initialized.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// Check if we just started scanning.  Fetch STREAM-START then.
+	if !parser.stream_start_produced {
+		return yaml_parser_fetch_stream_start(parser)
+	}
+
+	scan_mark := parser.mark
+
+	// Eat whitespaces and comments until we reach the next token.
+	if !yaml_parser_scan_to_next_token(parser) {
+		return false
+	}
+
+	// [Go] While unrolling indents, transform the head comments of prior
+	// indentation levels observed after scan_start into foot comments at
+	// the respective indexes.
+
+	// Check the indentation level against the current column.
+	if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
+		return false
+	}
+
+	// Ensure that the buffer contains at least 4 characters.  4 is the length
+	// of the longest indicators ('--- ' and '... ').
+	if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+		return false
+	}
+
+	// Is it the end of the stream?
+	if is_z(parser.buffer, parser.buffer_pos) {
+		return yaml_parser_fetch_stream_end(parser)
+	}
+
+	// Is it a directive?
+	if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+		return yaml_parser_fetch_directive(parser)
+	}
+
+	buf := parser.buffer
+	pos := parser.buffer_pos
+
+	// Is it the document start indicator?
+	if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+		return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+	}
+
+	// Is it the document end indicator?
+	if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+		return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+	}
+
+	comment_mark := parser.mark
+	if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+		// Associate any following comments with the prior token.
+		comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
+	}
+	defer func() {
+		if !ok {
+			return
+		}
+		if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+			// Sequence indicators alone have no line comments. It becomes
+			// a head comment for whatever follows.
+			return
+		}
+		if !yaml_parser_scan_line_comment(parser, comment_mark) {
+			ok = false
+			return
+		}
+	}()
+
+	// Is it the flow sequence start indicator?
+	if buf[pos] == '[' {
+		return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+	}
+
+	// Is it the flow mapping start indicator?
+	if parser.buffer[parser.buffer_pos] == '{' {
+		return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+	}
+
+	// Is it the flow sequence end indicator?
+	if parser.buffer[parser.buffer_pos] == ']' {
+		return yaml_parser_fetch_flow_collection_end(parser,
+			yaml_FLOW_SEQUENCE_END_TOKEN)
+	}
+
+	// Is it the flow mapping end indicator?
+	if parser.buffer[parser.buffer_pos] == '}' {
+		return yaml_parser_fetch_flow_collection_end(parser,
+			yaml_FLOW_MAPPING_END_TOKEN)
+	}
+
+	// Is it the flow entry indicator?
+	if parser.buffer[parser.buffer_pos] == ',' {
+		return yaml_parser_fetch_flow_entry(parser)
+	}
+
+	// Is it the block entry indicator?
+	if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+		return yaml_parser_fetch_block_entry(parser)
+	}
+
+	// Is it the key indicator?
+	if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_key(parser)
+	}
+
+	// Is it the value indicator?
+	if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_value(parser)
+	}
+
+	// Is it an alias?
+	if parser.buffer[parser.buffer_pos] == '*' {
+		return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+	}
+
+	// Is it an anchor?
+	if parser.buffer[parser.buffer_pos] == '&' {
+		return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+	}
+
+	// Is it a tag?
+	if parser.buffer[parser.buffer_pos] == '!' {
+		return yaml_parser_fetch_tag(parser)
+	}
+
+	// Is it a literal scalar?
+	if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+		return yaml_parser_fetch_block_scalar(parser, true)
+	}
+
+	// Is it a folded scalar?
+	if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+		return yaml_parser_fetch_block_scalar(parser, false)
+	}
+
+	// Is it a single-quoted scalar?
+	if parser.buffer[parser.buffer_pos] == '\'' {
+		return yaml_parser_fetch_flow_scalar(parser, true)
+	}
+
+	// Is it a double-quoted scalar?
+	if parser.buffer[parser.buffer_pos] == '"' {
+		return yaml_parser_fetch_flow_scalar(parser, false)
+	}
+
+	// Is it a plain scalar?
+	//
+	// A plain scalar may start with any non-blank characters except
+	//
+	//      '-', '?', ':', ',', '[', ']', '{', '}',
+	//      '#', '&', '*', '!', '|', '>', '\'', '\"',
+	//      '%', '@', '`'.
+	//
+	// In the block context (and, for the '-' indicator, in the flow context
+	// too), it may also start with the characters
+	//
+	//      '-', '?', ':'
+	//
+	// if it is followed by a non-space character.
+	//
+	// The last rule is more restrictive than the specification requires.
+	// [Go] TODO Make this logic more reasonable.
+	//switch parser.buffer[parser.buffer_pos] {
+	//case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+	//}
+	if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+		parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+		parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+		parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+		parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+		parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+		parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+		parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+		parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+		parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+		(parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+		(parser.flow_level == 0 &&
+			(parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+			!is_blankz(parser.buffer, parser.buffer_pos+1)) {
+		return yaml_parser_fetch_plain_scalar(parser)
+	}
+
+	// If we don't determine the token type so far, it is an error.
+	return yaml_parser_set_scanner_error(parser,
+		"while scanning for the next token", parser.mark,
+		"found character that cannot start any token")
+}
+
+func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
+	if !simple_key.possible {
+		return false, true
+	}
+
+	// The 1.2 specification says:
+	//
+	//     "If the ? indicator is omitted, parsing needs to see past the
+	//     implicit key to recognize it as such. To limit the amount of
+	//     lookahead required, the “:” indicator must appear at most 1024
+	//     Unicode characters beyond the start of the key. In addition, the key
+	//     is restricted to a single line."
+	//
+	if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
+		// Check if the potential simple key to be removed is required.
+		if simple_key.required {
+			return false, yaml_parser_set_scanner_error(parser,
+				"while scanning a simple key", simple_key.mark,
+				"could not find expected ':'")
+		}
+		simple_key.possible = false
+		return false, true
+	}
+	return true, true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+	// A simple key is required at the current position if the scanner is in
+	// the block context and the current column coincides with the indentation
+	// level.
+
+	required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+	//
+	// If the current position may start a simple key, save it.
+	//
+	if parser.simple_key_allowed {
+		simple_key := yaml_simple_key_t{
+			possible:     true,
+			required:     required,
+			token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+			mark:         parser.mark,
+		}
+
+		if !yaml_parser_remove_simple_key(parser) {
+			return false
+		}
+		parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+		parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
+	}
+	return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+	i := len(parser.simple_keys) - 1
+	if parser.simple_keys[i].possible {
+		// If the key is required, it is an error.
+		if parser.simple_keys[i].required {
+			return yaml_parser_set_scanner_error(parser,
+				"while scanning a simple key", parser.simple_keys[i].mark,
+				"could not find expected ':'")
+		}
+		// Remove the key from the stack.
+		parser.simple_keys[i].possible = false
+		delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
+	}
+	return true
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+	// Reset the simple key on the next level.
+	parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
+		possible:     false,
+		required:     false,
+		token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+		mark:         parser.mark,
+	})
+
+	// Increase the flow level.
+	parser.flow_level++
+	if parser.flow_level > max_flow_level {
+		return yaml_parser_set_scanner_error(parser,
+			"while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+			fmt.Sprintf("exceeded max depth of %d", max_flow_level))
+	}
+	return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+	if parser.flow_level > 0 {
+		parser.flow_level--
+		last := len(parser.simple_keys) - 1
+		delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
+		parser.simple_keys = parser.simple_keys[:last]
+	}
+	return true
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level.  In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+	// In the flow context, do nothing.
+	if parser.flow_level > 0 {
+		return true
+	}
+
+	if parser.indent < column {
+		// Push the current indentation level to the stack and set the new
+		// indentation level.
+		parser.indents = append(parser.indents, parser.indent)
+		parser.indent = column
+		if len(parser.indents) > max_indents {
+			return yaml_parser_set_scanner_error(parser,
+				"while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+				fmt.Sprintf("exceeded max depth of %d", max_indents))
+		}
+
+		// Create a token and insert it into the queue.
+		token := yaml_token_t{
+			typ:        typ,
+			start_mark: mark,
+			end_mark:   mark,
+		}
+		if number > -1 {
+			number -= parser.tokens_parsed
+		}
+		yaml_insert_token(parser, number, &token)
+	}
+	return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column.  For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
+	// In the flow context, do nothing.
+	if parser.flow_level > 0 {
+		return true
+	}
+
+	block_mark := scan_mark
+	block_mark.index--
+
+	// Loop through the indentation levels in the stack.
+	for parser.indent > column {
+
+		// [Go] Reposition the end token before potential following
+		//      foot comments of parent blocks. For that, search
+		//      backwards for recent comments that were at the same
+		//      indent as the block that is ending now.
+		stop_index := block_mark.index
+		for i := len(parser.comments) - 1; i >= 0; i-- {
+			comment := &parser.comments[i]
+
+			if comment.end_mark.index < stop_index {
+				// Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+				// If requested indent column is < 0, then the document is over and everything else
+				// is a foot anyway.
+				break
+			}
+			if comment.start_mark.column == parser.indent+1 {
+				// This is a good match. But maybe there's a former comment
+				// at that same indent level, so keep searching.
+				block_mark = comment.start_mark
+			}
+
+			// While the end of the former comment matches with
+			// the start of the following one, we know there's
+			// nothing in between and scanning is still safe.
+			stop_index = comment.scan_mark.index
+		}
+
+		// Create a token and append it to the queue.
+		token := yaml_token_t{
+			typ:        yaml_BLOCK_END_TOKEN,
+			start_mark: block_mark,
+			end_mark:   block_mark,
+		}
+		yaml_insert_token(parser, -1, &token)
+
+		// Pop the indentation level.
+		parser.indent = parser.indents[len(parser.indents)-1]
+		parser.indents = parser.indents[:len(parser.indents)-1]
+	}
+	return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+	// Set the initial indentation.
+	parser.indent = -1
+
+	// Initialize the simple key stack.
+	parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+	parser.simple_keys_by_tok = make(map[int]int)
+
+	// A simple key is allowed at the beginning of the stream.
+	parser.simple_key_allowed = true
+
+	// We have started.
+	parser.stream_start_produced = true
+
+	// Create the STREAM-START token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_STREAM_START_TOKEN,
+		start_mark: parser.mark,
+		end_mark:   parser.mark,
+		encoding:   parser.encoding,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+	// Force new line.
+	if parser.mark.column != 0 {
+		parser.mark.column = 0
+		parser.mark.line++
+	}
+
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Create the STREAM-END token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_STREAM_END_TOKEN,
+		start_mark: parser.mark,
+		end_mark:   parser.mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+	token := yaml_token_t{}
+	if !yaml_parser_scan_directive(parser, &token) {
+		return false
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// Reset the indentation level.
+	if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+		return false
+	}
+
+	// Reset simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	parser.simple_key_allowed = false
+
+	// Consume the token.
+	start_mark := parser.mark
+
+	skip(parser)
+	skip(parser)
+	skip(parser)
+
+	end_mark := parser.mark
+
+	// Create the DOCUMENT-START or DOCUMENT-END token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+
+	// The indicators '[' and '{' may start a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// Increase the flow level.
+	if !yaml_parser_increase_flow_level(parser) {
+		return false
+	}
+
+	// A simple key may follow the indicators '[' and '{'.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// Reset any potential simple key on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Decrease the flow level.
+	if !yaml_parser_decrease_flow_level(parser) {
+		return false
+	}
+
+	// No simple keys after the indicators ']' and '}'.
+	parser.simple_key_allowed = false
+
+	// Consume the token.
+
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+	token := yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	// Append the token to the queue.
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after ','.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the FLOW-ENTRY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_FLOW_ENTRY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+	// Check if the scanner is in the block context.
+	if parser.flow_level == 0 {
+		// Check if we are allowed to start a new entry.
+		if !parser.simple_key_allowed {
+			return yaml_parser_set_scanner_error(parser, "", parser.mark,
+				"block sequence entries are not allowed in this context")
+		}
+		// Add the BLOCK-SEQUENCE-START token if needed.
+		if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+			return false
+		}
+	} else {
+		// It is an error for the '-' indicator to occur in the flow context,
+		// but we let the Parser detect and report about it because the Parser
+		// is able to point to the context.
+	}
+
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after '-'.
+	parser.simple_key_allowed = true
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the BLOCK-ENTRY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_BLOCK_ENTRY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+	// In the block context, additional checks are required.
+	if parser.flow_level == 0 {
+		// Check if we are allowed to start a new key (not nessesary simple).
+		if !parser.simple_key_allowed {
+			return yaml_parser_set_scanner_error(parser, "", parser.mark,
+				"mapping keys are not allowed in this context")
+		}
+		// Add the BLOCK-MAPPING-START token if needed.
+		if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+			return false
+		}
+	}
+
+	// Reset any potential simple keys on the current flow level.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// Simple keys are allowed after '?' in the block context.
+	parser.simple_key_allowed = parser.flow_level == 0
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the KEY token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_KEY_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+	simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+	// Have we found a simple key?
+	if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
+		return false
+
+	} else if valid {
+
+		// Create the KEY token and insert it into the queue.
+		token := yaml_token_t{
+			typ:        yaml_KEY_TOKEN,
+			start_mark: simple_key.mark,
+			end_mark:   simple_key.mark,
+		}
+		yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+		// In the block context, we may need to add the BLOCK-MAPPING-START token.
+		if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+			simple_key.token_number,
+			yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+			return false
+		}
+
+		// Remove the simple key.
+		simple_key.possible = false
+		delete(parser.simple_keys_by_tok, simple_key.token_number)
+
+		// A simple key cannot follow another simple key.
+		parser.simple_key_allowed = false
+
+	} else {
+		// The ':' indicator follows a complex key.
+
+		// In the block context, extra checks are required.
+		if parser.flow_level == 0 {
+
+			// Check if we are allowed to start a complex value.
+			if !parser.simple_key_allowed {
+				return yaml_parser_set_scanner_error(parser, "", parser.mark,
+					"mapping values are not allowed in this context")
+			}
+
+			// Add the BLOCK-MAPPING-START token if needed.
+			if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+				return false
+			}
+		}
+
+		// Simple keys after ':' are allowed in the block context.
+		parser.simple_key_allowed = parser.flow_level == 0
+	}
+
+	// Consume the token.
+	start_mark := parser.mark
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create the VALUE token and append it to the queue.
+	token := yaml_token_t{
+		typ:        yaml_VALUE_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+	// An anchor or an alias could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow an anchor or an alias.
+	parser.simple_key_allowed = false
+
+	// Create the ALIAS or ANCHOR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_anchor(parser, &token, typ) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+	// A tag could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a tag.
+	parser.simple_key_allowed = false
+
+	// Create the TAG token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_tag(parser, &token) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+	// Remove any potential simple keys.
+	if !yaml_parser_remove_simple_key(parser) {
+		return false
+	}
+
+	// A simple key may follow a block scalar.
+	parser.simple_key_allowed = true
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+	// A plain scalar could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a flow scalar.
+	parser.simple_key_allowed = false
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+	// A plain scalar could be a simple key.
+	if !yaml_parser_save_simple_key(parser) {
+		return false
+	}
+
+	// A simple key cannot follow a flow scalar.
+	parser.simple_key_allowed = false
+
+	// Create the SCALAR token and append it to the queue.
+	var token yaml_token_t
+	if !yaml_parser_scan_plain_scalar(parser, &token) {
+		return false
+	}
+	yaml_insert_token(parser, -1, &token)
+	return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+	scan_mark := parser.mark
+
+	// Until the next token is not found.
+	for {
+		// Allow the BOM mark to start a line.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+		}
+
+		// Eat whitespaces.
+		// Tabs are allowed:
+		//  - in the flow context
+		//  - in the block context, but not at the beginning of the line or
+		//  after '-', '?', or ':' (complex value).
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Check if we just had a line comment under a sequence entry that
+		// looks more like a header to the following content. Similar to this:
+		//
+		// - # The comment
+		//   - Some data
+		//
+		// If so, transform the line comment to a head comment and reposition.
+		if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+			tokenA := parser.tokens[len(parser.tokens)-2]
+			tokenB := parser.tokens[len(parser.tokens)-1]
+			comment := &parser.comments[len(parser.comments)-1]
+			if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
+				// If it was in the prior line, reposition so it becomes a
+				// header of the follow up token. Otherwise, keep it in place
+				// so it becomes a header of the former.
+				comment.head = comment.line
+				comment.line = nil
+				if comment.start_mark.line == parser.mark.line-1 {
+					comment.token_mark = parser.mark
+				}
+			}
+		}
+
+		// Eat a comment until a line break.
+		if parser.buffer[parser.buffer_pos] == '#' {
+			if !yaml_parser_scan_comments(parser, scan_mark) {
+				return false
+			}
+		}
+
+		// If it is a line break, eat it.
+		if is_break(parser.buffer, parser.buffer_pos) {
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+			skip_line(parser)
+
+			// In the block context, a new line may start a simple key.
+			if parser.flow_level == 0 {
+				parser.simple_key_allowed = true
+			}
+		} else {
+			break // We have found a token.
+		}
+	}
+
+	return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+//
+//	%YAML    1.1    # a comment \n
+//	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+	// Eat '%'.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Scan the directive name.
+	var name []byte
+	if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+		return false
+	}
+
+	// Is it a YAML directive?
+	if bytes.Equal(name, []byte("YAML")) {
+		// Scan the VERSION directive value.
+		var major, minor int8
+		if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+			return false
+		}
+		end_mark := parser.mark
+
+		// Create a VERSION-DIRECTIVE token.
+		*token = yaml_token_t{
+			typ:        yaml_VERSION_DIRECTIVE_TOKEN,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			major:      major,
+			minor:      minor,
+		}
+
+		// Is it a TAG directive?
+	} else if bytes.Equal(name, []byte("TAG")) {
+		// Scan the TAG directive value.
+		var handle, prefix []byte
+		if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+			return false
+		}
+		end_mark := parser.mark
+
+		// Create a TAG-DIRECTIVE token.
+		*token = yaml_token_t{
+			typ:        yaml_TAG_DIRECTIVE_TOKEN,
+			start_mark: start_mark,
+			end_mark:   end_mark,
+			value:      handle,
+			prefix:     prefix,
+		}
+
+		// Unknown directive.
+	} else {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "found unknown directive name")
+		return false
+	}
+
+	// Eat the rest of the line including any comments.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	if parser.buffer[parser.buffer_pos] == '#' {
+		// [Go] Discard this inline comment for the time being.
+		//if !yaml_parser_scan_line_comment(parser, start_mark) {
+		//	return false
+		//}
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+	}
+
+	// Check if we are at the end of the line.
+	if !is_breakz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "did not find expected comment or line break")
+		return false
+	}
+
+	// Eat a line break.
+	if is_break(parser.buffer, parser.buffer_pos) {
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		skip_line(parser)
+	}
+
+	return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	 ^^^^
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	 ^^^
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+	// Consume the directive name.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	var s []byte
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the name is empty.
+	if len(s) == 0 {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "could not find expected directive name")
+		return false
+	}
+
+	// Check for an blank character after the name.
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a directive",
+			start_mark, "found unexpected non-alphabetical character")
+		return false
+	}
+	*name = s
+	return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	     ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+	// Eat whitespaces.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Consume the major version number.
+	if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+		return false
+	}
+
+	// Eat '.'.
+	if parser.buffer[parser.buffer_pos] != '.' {
+		return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+			start_mark, "did not find expected digit or '.' character")
+	}
+
+	skip(parser)
+
+	// Consume the minor version number.
+	if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+		return false
+	}
+	return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+//
+//	%YAML   1.1     # a comment \n
+//	        ^
+//	%YAML   1.1     # a comment \n
+//	          ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+	// Repeat while the next character is digit.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	var value, length int8
+	for is_digit(parser.buffer, parser.buffer_pos) {
+		// Check if the number is too long.
+		length++
+		if length > max_number_length {
+			return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+				start_mark, "found extremely long version number")
+		}
+		value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the number was present.
+	if length == 0 {
+		return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+			start_mark, "did not find expected version number")
+	}
+	*number = value
+	return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+//
+//	%TAG    !yaml!  tag:yaml.org,2002:  \n
+//	    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+	var handle_value, prefix_value []byte
+
+	// Eat whitespaces.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Scan a handle.
+	if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+		return false
+	}
+
+	// Expect a whitespace.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blank(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+			start_mark, "did not find expected whitespace")
+		return false
+	}
+
+	// Eat whitespaces.
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Scan a prefix.
+	if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+		return false
+	}
+
+	// Expect a whitespace or line break.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+			start_mark, "did not find expected whitespace or line break")
+		return false
+	}
+
+	*handle = handle_value
+	*prefix = prefix_value
+	return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+	var s []byte
+
+	// Eat the indicator character.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Consume the value.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	end_mark := parser.mark
+
+	/*
+	 * Check if length of the anchor is greater than 0 and it is followed by
+	 * a whitespace character or one of the indicators:
+	 *
+	 *      '?', ':', ',', ']', '}', '%', '@', '`'.
+	 */
+
+	if len(s) == 0 ||
+		!(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+			parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+			parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+			parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+			parser.buffer[parser.buffer_pos] == '`') {
+		context := "while scanning an alias"
+		if typ == yaml_ANCHOR_TOKEN {
+			context = "while scanning an anchor"
+		}
+		yaml_parser_set_scanner_error(parser, context, start_mark,
+			"did not find expected alphabetic or numeric character")
+		return false
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        typ,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+	}
+
+	return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+	var handle, suffix []byte
+
+	start_mark := parser.mark
+
+	// Check if the tag is in the canonical form.
+	if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+		return false
+	}
+
+	if parser.buffer[parser.buffer_pos+1] == '<' {
+		// Keep the handle as ''
+
+		// Eat '!<'
+		skip(parser)
+		skip(parser)
+
+		// Consume the tag value.
+		if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+			return false
+		}
+
+		// Check for '>' and eat it.
+		if parser.buffer[parser.buffer_pos] != '>' {
+			yaml_parser_set_scanner_error(parser, "while scanning a tag",
+				start_mark, "did not find the expected '>'")
+			return false
+		}
+
+		skip(parser)
+	} else {
+		// The tag has either the '!suffix' or the '!handle!suffix' form.
+
+		// First, try to scan a handle.
+		if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+			return false
+		}
+
+		// Check if it is, indeed, handle.
+		if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+			// Scan the suffix now.
+			if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+				return false
+			}
+		} else {
+			// It wasn't a handle after all.  Scan the rest of the tag.
+			if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+				return false
+			}
+
+			// Set the handle to '!'.
+			handle = []byte{'!'}
+
+			// A special case: the '!' tag.  Set the handle to '' and the
+			// suffix to '!'.
+			if len(suffix) == 0 {
+				handle, suffix = suffix, handle
+			}
+		}
+	}
+
+	// Check the character which ends the tag.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if !is_blankz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a tag",
+			start_mark, "did not find expected whitespace or line break")
+		return false
+	}
+
+	end_mark := parser.mark
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_TAG_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      handle,
+		suffix:     suffix,
+	}
+	return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+	// Check the initial '!' character.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	if parser.buffer[parser.buffer_pos] != '!' {
+		yaml_parser_set_scanner_tag_error(parser, directive,
+			start_mark, "did not find expected '!'")
+		return false
+	}
+
+	var s []byte
+
+	// Copy the '!' character.
+	s = read(parser, s)
+
+	// Copy all subsequent alphabetical and numerical characters.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_alpha(parser.buffer, parser.buffer_pos) {
+		s = read(parser, s)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+
+	// Check if the trailing character is '!' and copy it.
+	if parser.buffer[parser.buffer_pos] == '!' {
+		s = read(parser, s)
+	} else {
+		// It's either the '!' tag or not really a tag handle.  If it's a %TAG
+		// directive, it's an error.  If it's a tag token, it must be a part of URI.
+		if directive && string(s) != "!" {
+			yaml_parser_set_scanner_tag_error(parser, directive,
+				start_mark, "did not find expected '!'")
+			return false
+		}
+	}
+
+	*handle = s
+	return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+	//size_t length = head ? strlen((char *)head) : 0
+	var s []byte
+	hasTag := len(head) > 0
+
+	// Copy the head if needed.
+	//
+	// Note that we don't copy the leading '!' character.
+	if len(head) > 1 {
+		s = append(s, head[1:]...)
+	}
+
+	// Scan the tag.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// The set of characters that may appear in URI is as follows:
+	//
+	//      '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+	//      '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+	//      '%'.
+	// [Go] TODO Convert this into more reasonable logic.
+	for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+		parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+		parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+		parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+		parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+		parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+		parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+		parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+		parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+		parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+		parser.buffer[parser.buffer_pos] == '%' {
+		// Check if it is a URI-escape sequence.
+		if parser.buffer[parser.buffer_pos] == '%' {
+			if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+				return false
+			}
+		} else {
+			s = read(parser, s)
+		}
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		hasTag = true
+	}
+
+	if !hasTag {
+		yaml_parser_set_scanner_tag_error(parser, directive,
+			start_mark, "did not find expected tag URI")
+		return false
+	}
+	*uri = s
+	return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+	// Decode the required number of characters.
+	w := 1024
+	for w > 0 {
+		// Check for a URI-escaped octet.
+		if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+			return false
+		}
+
+		if !(parser.buffer[parser.buffer_pos] == '%' &&
+			is_hex(parser.buffer, parser.buffer_pos+1) &&
+			is_hex(parser.buffer, parser.buffer_pos+2)) {
+			return yaml_parser_set_scanner_tag_error(parser, directive,
+				start_mark, "did not find URI escaped octet")
+		}
+
+		// Get the octet.
+		octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+		// If it is the leading octet, determine the length of the UTF-8 sequence.
+		if w == 1024 {
+			w = width(octet)
+			if w == 0 {
+				return yaml_parser_set_scanner_tag_error(parser, directive,
+					start_mark, "found an incorrect leading UTF-8 octet")
+			}
+		} else {
+			// Check if the trailing octet is correct.
+			if octet&0xC0 != 0x80 {
+				return yaml_parser_set_scanner_tag_error(parser, directive,
+					start_mark, "found an incorrect trailing UTF-8 octet")
+			}
+		}
+
+		// Copy the octet and move the pointers.
+		*s = append(*s, octet)
+		skip(parser)
+		skip(parser)
+		skip(parser)
+		w--
+	}
+	return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+	// Eat the indicator '|' or '>'.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Scan the additional block scalar indicators.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+
+	// Check for a chomping indicator.
+	var chomping, increment int
+	if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+		// Set the chomping method and eat the indicator.
+		if parser.buffer[parser.buffer_pos] == '+' {
+			chomping = +1
+		} else {
+			chomping = -1
+		}
+		skip(parser)
+
+		// Check for an indentation indicator.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if is_digit(parser.buffer, parser.buffer_pos) {
+			// Check that the indentation is greater than 0.
+			if parser.buffer[parser.buffer_pos] == '0' {
+				yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+					start_mark, "found an indentation indicator equal to 0")
+				return false
+			}
+
+			// Get the indentation level and eat the indicator.
+			increment = as_digit(parser.buffer, parser.buffer_pos)
+			skip(parser)
+		}
+
+	} else if is_digit(parser.buffer, parser.buffer_pos) {
+		// Do the same as above, but in the opposite order.
+
+		if parser.buffer[parser.buffer_pos] == '0' {
+			yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+				start_mark, "found an indentation indicator equal to 0")
+			return false
+		}
+		increment = as_digit(parser.buffer, parser.buffer_pos)
+		skip(parser)
+
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+			if parser.buffer[parser.buffer_pos] == '+' {
+				chomping = +1
+			} else {
+				chomping = -1
+			}
+			skip(parser)
+		}
+	}
+
+	// Eat whitespaces and comments to the end of the line.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	for is_blank(parser.buffer, parser.buffer_pos) {
+		skip(parser)
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+	}
+	if parser.buffer[parser.buffer_pos] == '#' {
+		if !yaml_parser_scan_line_comment(parser, start_mark) {
+			return false
+		}
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+	}
+
+	// Check if we are at the end of the line.
+	if !is_breakz(parser.buffer, parser.buffer_pos) {
+		yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+			start_mark, "did not find expected comment or line break")
+		return false
+	}
+
+	// Eat a line break.
+	if is_break(parser.buffer, parser.buffer_pos) {
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		skip_line(parser)
+	}
+
+	end_mark := parser.mark
+
+	// Set the indentation level if it was specified.
+	var indent int
+	if increment > 0 {
+		if parser.indent >= 0 {
+			indent = parser.indent + increment
+		} else {
+			indent = increment
+		}
+	}
+
+	// Scan the leading line breaks and determine the indentation level if needed.
+	var s, leading_break, trailing_breaks []byte
+	if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+		return false
+	}
+
+	// Scan the block scalar content.
+	if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+		return false
+	}
+	var leading_blank, trailing_blank bool
+	for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+		// We are at the beginning of a non-empty line.
+
+		// Is it a trailing whitespace?
+		trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+		// Check if we need to fold the leading line break.
+		if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+			// Do we need to join the lines by space?
+			if len(trailing_breaks) == 0 {
+				s = append(s, ' ')
+			}
+		} else {
+			s = append(s, leading_break...)
+		}
+		leading_break = leading_break[:0]
+
+		// Append the remaining line breaks.
+		s = append(s, trailing_breaks...)
+		trailing_breaks = trailing_breaks[:0]
+
+		// Is it a leading whitespace?
+		leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+		// Consume the current line.
+		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			s = read(parser, s)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Consume the line break.
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+
+		leading_break = read_line(parser, leading_break)
+
+		// Eat the following indentation spaces and line breaks.
+		if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+			return false
+		}
+	}
+
+	// Chomp the tail.
+	if chomping != -1 {
+		s = append(s, leading_break...)
+	}
+	if chomping == 1 {
+		s = append(s, trailing_breaks...)
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_LITERAL_SCALAR_STYLE,
+	}
+	if !literal {
+		token.style = yaml_FOLDED_SCALAR_STYLE
+	}
+	return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar.  Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+	*end_mark = parser.mark
+
+	// Eat the indentation spaces and line breaks.
+	max_indent := 0
+	for {
+		// Eat the indentation spaces.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+		for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+			skip(parser)
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+		if parser.mark.column > max_indent {
+			max_indent = parser.mark.column
+		}
+
+		// Check for a tab character messing the indentation.
+		if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+			return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+				start_mark, "found a tab character where an indentation space is expected")
+		}
+
+		// Have we found a non-empty line?
+		if !is_break(parser.buffer, parser.buffer_pos) {
+			break
+		}
+
+		// Consume the line break.
+		if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+			return false
+		}
+		// [Go] Should really be returning breaks instead.
+		*breaks = read_line(parser, *breaks)
+		*end_mark = parser.mark
+	}
+
+	// Determine the indentation level if needed.
+	if *indent == 0 {
+		*indent = max_indent
+		if *indent < parser.indent+1 {
+			*indent = parser.indent + 1
+		}
+		if *indent < 1 {
+			*indent = 1
+		}
+	}
+	return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+	// Eat the left quote.
+	start_mark := parser.mark
+	skip(parser)
+
+	// Consume the content of the quoted scalar.
+	var s, leading_break, trailing_breaks, whitespaces []byte
+	for {
+		// Check that there are no document indicators at the beginning of the line.
+		if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+			return false
+		}
+
+		if parser.mark.column == 0 &&
+			((parser.buffer[parser.buffer_pos+0] == '-' &&
+				parser.buffer[parser.buffer_pos+1] == '-' &&
+				parser.buffer[parser.buffer_pos+2] == '-') ||
+				(parser.buffer[parser.buffer_pos+0] == '.' &&
+					parser.buffer[parser.buffer_pos+1] == '.' &&
+					parser.buffer[parser.buffer_pos+2] == '.')) &&
+			is_blankz(parser.buffer, parser.buffer_pos+3) {
+			yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+				start_mark, "found unexpected document indicator")
+			return false
+		}
+
+		// Check for EOF.
+		if is_z(parser.buffer, parser.buffer_pos) {
+			yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+				start_mark, "found unexpected end of stream")
+			return false
+		}
+
+		// Consume non-blank characters.
+		leading_blanks := false
+		for !is_blankz(parser.buffer, parser.buffer_pos) {
+			if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+				// Is is an escaped single quote.
+				s = append(s, '\'')
+				skip(parser)
+				skip(parser)
+
+			} else if single && parser.buffer[parser.buffer_pos] == '\'' {
+				// It is a right single quote.
+				break
+			} else if !single && parser.buffer[parser.buffer_pos] == '"' {
+				// It is a right double quote.
+				break
+
+			} else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+				// It is an escaped line break.
+				if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+					return false
+				}
+				skip(parser)
+				skip_line(parser)
+				leading_blanks = true
+				break
+
+			} else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+				// It is an escape sequence.
+				code_length := 0
+
+				// Check the escape character.
+				switch parser.buffer[parser.buffer_pos+1] {
+				case '0':
+					s = append(s, 0)
+				case 'a':
+					s = append(s, '\x07')
+				case 'b':
+					s = append(s, '\x08')
+				case 't', '\t':
+					s = append(s, '\x09')
+				case 'n':
+					s = append(s, '\x0A')
+				case 'v':
+					s = append(s, '\x0B')
+				case 'f':
+					s = append(s, '\x0C')
+				case 'r':
+					s = append(s, '\x0D')
+				case 'e':
+					s = append(s, '\x1B')
+				case ' ':
+					s = append(s, '\x20')
+				case '"':
+					s = append(s, '"')
+				case '\'':
+					s = append(s, '\'')
+				case '\\':
+					s = append(s, '\\')
+				case 'N': // NEL (#x85)
+					s = append(s, '\xC2')
+					s = append(s, '\x85')
+				case '_': // #xA0
+					s = append(s, '\xC2')
+					s = append(s, '\xA0')
+				case 'L': // LS (#x2028)
+					s = append(s, '\xE2')
+					s = append(s, '\x80')
+					s = append(s, '\xA8')
+				case 'P': // PS (#x2029)
+					s = append(s, '\xE2')
+					s = append(s, '\x80')
+					s = append(s, '\xA9')
+				case 'x':
+					code_length = 2
+				case 'u':
+					code_length = 4
+				case 'U':
+					code_length = 8
+				default:
+					yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+						start_mark, "found unknown escape character")
+					return false
+				}
+
+				skip(parser)
+				skip(parser)
+
+				// Consume an arbitrary escape code.
+				if code_length > 0 {
+					var value int
+
+					// Scan the character value.
+					if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+						return false
+					}
+					for k := 0; k < code_length; k++ {
+						if !is_hex(parser.buffer, parser.buffer_pos+k) {
+							yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+								start_mark, "did not find expected hexdecimal number")
+							return false
+						}
+						value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+					}
+
+					// Check the value and write the character.
+					if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+						yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+							start_mark, "found invalid Unicode character escape code")
+						return false
+					}
+					if value <= 0x7F {
+						s = append(s, byte(value))
+					} else if value <= 0x7FF {
+						s = append(s, byte(0xC0+(value>>6)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					} else if value <= 0xFFFF {
+						s = append(s, byte(0xE0+(value>>12)))
+						s = append(s, byte(0x80+((value>>6)&0x3F)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					} else {
+						s = append(s, byte(0xF0+(value>>18)))
+						s = append(s, byte(0x80+((value>>12)&0x3F)))
+						s = append(s, byte(0x80+((value>>6)&0x3F)))
+						s = append(s, byte(0x80+(value&0x3F)))
+					}
+
+					// Advance the pointer.
+					for k := 0; k < code_length; k++ {
+						skip(parser)
+					}
+				}
+			} else {
+				// It is a non-escaped non-blank character.
+				s = read(parser, s)
+			}
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+		}
+
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		// Check if we are at the end of the scalar.
+		if single {
+			if parser.buffer[parser.buffer_pos] == '\'' {
+				break
+			}
+		} else {
+			if parser.buffer[parser.buffer_pos] == '"' {
+				break
+			}
+		}
+
+		// Consume blank characters.
+		for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+			if is_blank(parser.buffer, parser.buffer_pos) {
+				// Consume a space or a tab character.
+				if !leading_blanks {
+					whitespaces = read(parser, whitespaces)
+				} else {
+					skip(parser)
+				}
+			} else {
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+
+				// Check if it is a first line break.
+				if !leading_blanks {
+					whitespaces = whitespaces[:0]
+					leading_break = read_line(parser, leading_break)
+					leading_blanks = true
+				} else {
+					trailing_breaks = read_line(parser, trailing_breaks)
+				}
+			}
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Join the whitespaces or fold line breaks.
+		if leading_blanks {
+			// Do we need to fold line breaks?
+			if len(leading_break) > 0 && leading_break[0] == '\n' {
+				if len(trailing_breaks) == 0 {
+					s = append(s, ' ')
+				} else {
+					s = append(s, trailing_breaks...)
+				}
+			} else {
+				s = append(s, leading_break...)
+				s = append(s, trailing_breaks...)
+			}
+			trailing_breaks = trailing_breaks[:0]
+			leading_break = leading_break[:0]
+		} else {
+			s = append(s, whitespaces...)
+			whitespaces = whitespaces[:0]
+		}
+	}
+
+	// Eat the right quote.
+	skip(parser)
+	end_mark := parser.mark
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_SINGLE_QUOTED_SCALAR_STYLE,
+	}
+	if !single {
+		token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+	}
+	return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+	var s, leading_break, trailing_breaks, whitespaces []byte
+	var leading_blanks bool
+	var indent = parser.indent + 1
+
+	start_mark := parser.mark
+	end_mark := parser.mark
+
+	// Consume the content of the plain scalar.
+	for {
+		// Check for a document indicator.
+		if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+			return false
+		}
+		if parser.mark.column == 0 &&
+			((parser.buffer[parser.buffer_pos+0] == '-' &&
+				parser.buffer[parser.buffer_pos+1] == '-' &&
+				parser.buffer[parser.buffer_pos+2] == '-') ||
+				(parser.buffer[parser.buffer_pos+0] == '.' &&
+					parser.buffer[parser.buffer_pos+1] == '.' &&
+					parser.buffer[parser.buffer_pos+2] == '.')) &&
+			is_blankz(parser.buffer, parser.buffer_pos+3) {
+			break
+		}
+
+		// Check for a comment.
+		if parser.buffer[parser.buffer_pos] == '#' {
+			break
+		}
+
+		// Consume non-blank characters.
+		for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+			// Check for indicators that may end a plain scalar.
+			if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+				(parser.flow_level > 0 &&
+					(parser.buffer[parser.buffer_pos] == ',' ||
+						parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+						parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+						parser.buffer[parser.buffer_pos] == '}')) {
+				break
+			}
+
+			// Check if we need to join whitespaces and breaks.
+			if leading_blanks || len(whitespaces) > 0 {
+				if leading_blanks {
+					// Do we need to fold line breaks?
+					if leading_break[0] == '\n' {
+						if len(trailing_breaks) == 0 {
+							s = append(s, ' ')
+						} else {
+							s = append(s, trailing_breaks...)
+						}
+					} else {
+						s = append(s, leading_break...)
+						s = append(s, trailing_breaks...)
+					}
+					trailing_breaks = trailing_breaks[:0]
+					leading_break = leading_break[:0]
+					leading_blanks = false
+				} else {
+					s = append(s, whitespaces...)
+					whitespaces = whitespaces[:0]
+				}
+			}
+
+			// Copy the character.
+			s = read(parser, s)
+
+			end_mark = parser.mark
+			if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+				return false
+			}
+		}
+
+		// Is it the end?
+		if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+			break
+		}
+
+		// Consume blank characters.
+		if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+			return false
+		}
+
+		for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+			if is_blank(parser.buffer, parser.buffer_pos) {
+
+				// Check for tab characters that abuse indentation.
+				if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+					yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+						start_mark, "found a tab character that violates indentation")
+					return false
+				}
+
+				// Consume a space or a tab character.
+				if !leading_blanks {
+					whitespaces = read(parser, whitespaces)
+				} else {
+					skip(parser)
+				}
+			} else {
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+
+				// Check if it is a first line break.
+				if !leading_blanks {
+					whitespaces = whitespaces[:0]
+					leading_break = read_line(parser, leading_break)
+					leading_blanks = true
+				} else {
+					trailing_breaks = read_line(parser, trailing_breaks)
+				}
+			}
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+		}
+
+		// Check indentation level.
+		if parser.flow_level == 0 && parser.mark.column < indent {
+			break
+		}
+	}
+
+	// Create a token.
+	*token = yaml_token_t{
+		typ:        yaml_SCALAR_TOKEN,
+		start_mark: start_mark,
+		end_mark:   end_mark,
+		value:      s,
+		style:      yaml_PLAIN_SCALAR_STYLE,
+	}
+
+	// Note that we change the 'simple_key_allowed' flag.
+	if leading_blanks {
+		parser.simple_key_allowed = true
+	}
+	return true
+}
+
+func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
+	if parser.newlines > 0 {
+		return true
+	}
+
+	var start_mark yaml_mark_t
+	var text []byte
+
+	for peek := 0; peek < 512; peek++ {
+		if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+			break
+		}
+		if is_blank(parser.buffer, parser.buffer_pos+peek) {
+			continue
+		}
+		if parser.buffer[parser.buffer_pos+peek] == '#' {
+			seen := parser.mark.index + peek
+			for {
+				if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+					return false
+				}
+				if is_breakz(parser.buffer, parser.buffer_pos) {
+					if parser.mark.index >= seen {
+						break
+					}
+					if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+						return false
+					}
+					skip_line(parser)
+				} else if parser.mark.index >= seen {
+					if len(text) == 0 {
+						start_mark = parser.mark
+					}
+					text = read(parser, text)
+				} else {
+					skip(parser)
+				}
+			}
+		}
+		break
+	}
+	if len(text) > 0 {
+		parser.comments = append(parser.comments, yaml_comment_t{
+			token_mark: token_mark,
+			start_mark: start_mark,
+			line:       text,
+		})
+	}
+	return true
+}
+
+func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
+	token := parser.tokens[len(parser.tokens)-1]
+
+	if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+		token = parser.tokens[len(parser.tokens)-2]
+	}
+
+	var token_mark = token.start_mark
+	var start_mark yaml_mark_t
+	var next_indent = parser.indent
+	if next_indent < 0 {
+		next_indent = 0
+	}
+
+	var recent_empty = false
+	var first_empty = parser.newlines <= 1
+
+	var line = parser.mark.line
+	var column = parser.mark.column
+
+	var text []byte
+
+	// The foot line is the place where a comment must start to
+	// still be considered as a foot of the prior content.
+	// If there's some content in the currently parsed line, then
+	// the foot is the line below it.
+	var foot_line = -1
+	if scan_mark.line > 0 {
+		foot_line = parser.mark.line - parser.newlines + 1
+		if parser.newlines == 0 && parser.mark.column > 1 {
+			foot_line++
+		}
+	}
+
+	var peek = 0
+	for ; peek < 512; peek++ {
+		if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+			break
+		}
+		column++
+		if is_blank(parser.buffer, parser.buffer_pos+peek) {
+			continue
+		}
+		c := parser.buffer[parser.buffer_pos+peek]
+		var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+		if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
+			// Got line break or terminator.
+			if close_flow || !recent_empty {
+				if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
+					// This is the first empty line and there were no empty lines before,
+					// so this initial part of the comment is a foot of the prior token
+					// instead of being a head for the following one. Split it up.
+					// Alternatively, this might also be the last comment inside a flow
+					// scope, so it must be a footer.
+					if len(text) > 0 {
+						if start_mark.column-1 < next_indent {
+							// If dedented it's unrelated to the prior token.
+							token_mark = start_mark
+						}
+						parser.comments = append(parser.comments, yaml_comment_t{
+							scan_mark:  scan_mark,
+							token_mark: token_mark,
+							start_mark: start_mark,
+							end_mark:   yaml_mark_t{parser.mark.index + peek, line, column},
+							foot:       text,
+						})
+						scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+						token_mark = scan_mark
+						text = nil
+					}
+				} else {
+					if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+						text = append(text, '\n')
+					}
+				}
+			}
+			if !is_break(parser.buffer, parser.buffer_pos+peek) {
+				break
+			}
+			first_empty = false
+			recent_empty = true
+			column = 0
+			line++
+			continue
+		}
+
+		if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
+			// The comment at the different indentation is a foot of the
+			// preceding data rather than a head of the upcoming one.
+			parser.comments = append(parser.comments, yaml_comment_t{
+				scan_mark:  scan_mark,
+				token_mark: token_mark,
+				start_mark: start_mark,
+				end_mark:   yaml_mark_t{parser.mark.index + peek, line, column},
+				foot:       text,
+			})
+			scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+			token_mark = scan_mark
+			text = nil
+		}
+
+		if parser.buffer[parser.buffer_pos+peek] != '#' {
+			break
+		}
+
+		if len(text) == 0 {
+			start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+		} else {
+			text = append(text, '\n')
+		}
+
+		recent_empty = false
+
+		// Consume until after the consumed comment line.
+		seen := parser.mark.index + peek
+		for {
+			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+				return false
+			}
+			if is_breakz(parser.buffer, parser.buffer_pos) {
+				if parser.mark.index >= seen {
+					break
+				}
+				if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+					return false
+				}
+				skip_line(parser)
+			} else if parser.mark.index >= seen {
+				text = read(parser, text)
+			} else {
+				skip(parser)
+			}
+		}
+
+		peek = 0
+		column = 0
+		line = parser.mark.line
+		next_indent = parser.indent
+		if next_indent < 0 {
+			next_indent = 0
+		}
+	}
+
+	if len(text) > 0 {
+		parser.comments = append(parser.comments, yaml_comment_t{
+			scan_mark:  scan_mark,
+			token_mark: start_mark,
+			start_mark: start_mark,
+			end_mark:   yaml_mark_t{parser.mark.index + peek - 1, line, column},
+			head:       text,
+		})
+	}
+	return true
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/sorter.go b/notifier/vendor/go.yaml.in/yaml/v3/sorter.go
new file mode 100644
index 00000000..9210ece7
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/sorter.go
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+	"reflect"
+	"unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int      { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+	a := l[i]
+	b := l[j]
+	ak := a.Kind()
+	bk := b.Kind()
+	for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+		a = a.Elem()
+		ak = a.Kind()
+	}
+	for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+		b = b.Elem()
+		bk = b.Kind()
+	}
+	af, aok := keyFloat(a)
+	bf, bok := keyFloat(b)
+	if aok && bok {
+		if af != bf {
+			return af < bf
+		}
+		if ak != bk {
+			return ak < bk
+		}
+		return numLess(a, b)
+	}
+	if ak != reflect.String || bk != reflect.String {
+		return ak < bk
+	}
+	ar, br := []rune(a.String()), []rune(b.String())
+	digits := false
+	for i := 0; i < len(ar) && i < len(br); i++ {
+		if ar[i] == br[i] {
+			digits = unicode.IsDigit(ar[i])
+			continue
+		}
+		al := unicode.IsLetter(ar[i])
+		bl := unicode.IsLetter(br[i])
+		if al && bl {
+			return ar[i] < br[i]
+		}
+		if al || bl {
+			if digits {
+				return al
+			} else {
+				return bl
+			}
+		}
+		var ai, bi int
+		var an, bn int64
+		if ar[i] == '0' || br[i] == '0' {
+			for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+				if ar[j] != '0' {
+					an = 1
+					bn = 1
+					break
+				}
+			}
+		}
+		for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+			an = an*10 + int64(ar[ai]-'0')
+		}
+		for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+			bn = bn*10 + int64(br[bi]-'0')
+		}
+		if an != bn {
+			return an < bn
+		}
+		if ai != bi {
+			return ai < bi
+		}
+		return ar[i] < br[i]
+	}
+	return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+	switch v.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return float64(v.Int()), true
+	case reflect.Float32, reflect.Float64:
+		return v.Float(), true
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return float64(v.Uint()), true
+	case reflect.Bool:
+		if v.Bool() {
+			return 1, true
+		}
+		return 0, true
+	}
+	return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+	switch a.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return a.Int() < b.Int()
+	case reflect.Float32, reflect.Float64:
+		return a.Float() < b.Float()
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return a.Uint() < b.Uint()
+	case reflect.Bool:
+		return !a.Bool() && b.Bool()
+	}
+	panic("not a number")
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/writerc.go b/notifier/vendor/go.yaml.in/yaml/v3/writerc.go
new file mode 100644
index 00000000..266d0b09
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/writerc.go
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+	emitter.error = yaml_WRITER_ERROR
+	emitter.problem = problem
+	return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+	if emitter.write_handler == nil {
+		panic("write handler not set")
+	}
+
+	// Check if the buffer is empty.
+	if emitter.buffer_pos == 0 {
+		return true
+	}
+
+	if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+		return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+	}
+	emitter.buffer_pos = 0
+	return true
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/yaml.go b/notifier/vendor/go.yaml.in/yaml/v3/yaml.go
new file mode 100644
index 00000000..0b101cd2
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/yaml.go
@@ -0,0 +1,703 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+//	https://github.com/yaml/go-yaml
+package yaml
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"sync"
+	"unicode/utf8"
+)
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document.
+type Unmarshaler interface {
+	UnmarshalYAML(value *Node) error
+}
+
+type obsoleteUnmarshaler interface {
+	UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+	MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+//	type T struct {
+//	    F int `yaml:"a,omitempty"`
+//	    B int
+//	}
+//	var t T
+//	yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+func Unmarshal(in []byte, out interface{}) (err error) {
+	return unmarshal(in, out, false)
+}
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+	parser      *parser
+	knownFields bool
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{
+		parser: newParserFromReader(r),
+	}
+}
+
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+	dec.knownFields = enable
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+	d := newDecoder()
+	d.knownFields = dec.knownFields
+	defer handleErr(&err)
+	node := dec.parser.parse()
+	if node == nil {
+		return io.EOF
+	}
+	out := reflect.ValueOf(v)
+	if out.Kind() == reflect.Ptr && !out.IsNil() {
+		out = out.Elem()
+	}
+	d.unmarshal(node, out)
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v interface{}) (err error) {
+	d := newDecoder()
+	defer handleErr(&err)
+	out := reflect.ValueOf(v)
+	if out.Kind() == reflect.Ptr && !out.IsNil() {
+		out = out.Elem()
+	}
+	d.unmarshal(n, out)
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+	defer handleErr(&err)
+	d := newDecoder()
+	p := newParser(in)
+	defer p.destroy()
+	node := p.parse()
+	if node != nil {
+		v := reflect.ValueOf(out)
+		if v.Kind() == reflect.Ptr && !v.IsNil() {
+			v = v.Elem()
+		}
+		d.unmarshal(node, v)
+	}
+	if len(d.terrors) > 0 {
+		return &TypeError{d.terrors}
+	}
+	return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+//	`(...) yaml:"[][,[,]]" (...)`
+//
+// The following flags are currently supported:
+//
+//	omitempty    Only include the field if it's not set to the zero
+//	             value for the type or to empty slices or maps.
+//	             Zero valued structs will be omitted if all their public
+//	             fields are zero, unless they implement an IsZero
+//	             method (see the IsZeroer interface type), in which
+//	             case the field will be excluded if IsZero returns true.
+//
+//	flow         Marshal using a flow style (useful for structs,
+//	             sequences and maps).
+//
+//	inline       Inline the field, which must be a struct or a map,
+//	             causing all of its fields or keys to be processed as if
+//	             they were part of the outer struct. For maps, keys must
+//	             not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+//	type T struct {
+//	    F int `yaml:"a,omitempty"`
+//	    B int
+//	}
+//	yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+//	yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+func Marshal(in interface{}) (out []byte, err error) {
+	defer handleErr(&err)
+	e := newEncoder()
+	defer e.destroy()
+	e.marshalDoc("", reflect.ValueOf(in))
+	e.finish()
+	out = e.out
+	return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+	encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+	return &Encoder{
+		encoder: newEncoderWithWriter(w),
+	}
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+	defer handleErr(&err)
+	e.encoder.marshalDoc("", reflect.ValueOf(v))
+	return nil
+}
+
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+	defer handleErr(&err)
+	e := newEncoder()
+	defer e.destroy()
+	e.marshalDoc("", reflect.ValueOf(v))
+	e.finish()
+	p := newParser(e.out)
+	p.textless = true
+	defer p.destroy()
+	doc := p.parse()
+	*n = *doc.Content[0]
+	return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+	if spaces < 0 {
+		panic("yaml: cannot indent to a negative number of spaces")
+	}
+	e.encoder.indent = spaces
+}
+
+// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
+func (e *Encoder) CompactSeqIndent() {
+	e.encoder.emitter.compact_sequence_indent = true
+}
+
+// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
+func (e *Encoder) DefaultSeqIndent() {
+	e.encoder.emitter.compact_sequence_indent = false
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+	defer handleErr(&err)
+	e.encoder.finish()
+	return nil
+}
+
+func handleErr(err *error) {
+	if v := recover(); v != nil {
+		if e, ok := v.(yamlError); ok {
+			*err = e.err
+		} else {
+			panic(v)
+		}
+	}
+}
+
+type yamlError struct {
+	err error
+}
+
+func fail(err error) {
+	panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+	panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+	Errors []string
+}
+
+func (e *TypeError) Error() string {
+	return fmt.Sprintf("yaml: unmarshal errors:\n  %s", strings.Join(e.Errors, "\n  "))
+}
+
+type Kind uint32
+
+const (
+	DocumentNode Kind = 1 << iota
+	SequenceNode
+	MappingNode
+	ScalarNode
+	AliasNode
+)
+
+type Style uint32
+
+const (
+	TaggedStyle Style = 1 << iota
+	DoubleQuotedStyle
+	SingleQuotedStyle
+	LiteralStyle
+	FoldedStyle
+	FlowStyle
+)
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+//	var person struct {
+//	        Name    string
+//	        Address yaml.Node
+//	}
+//	err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+//	var person Node
+//	err := yaml.Unmarshal(data, &person)
+type Node struct {
+	// Kind defines whether the node is a document, a mapping, a sequence,
+	// a scalar value, or an alias to another node. The specific data type of
+	// scalar nodes may be obtained via the ShortTag and LongTag methods.
+	Kind Kind
+
+	// Style allows customizing the apperance of the node in the tree.
+	Style Style
+
+	// Tag holds the YAML tag defining the data type for the value.
+	// When decoding, this field will always be set to the resolved tag,
+	// even when it wasn't explicitly provided in the YAML content.
+	// When encoding, if this field is unset the value type will be
+	// implied from the node properties, and if it is set, it will only
+	// be serialized into the representation if TaggedStyle is used or
+	// the implicit tag diverges from the provided one.
+	Tag string
+
+	// Value holds the unescaped and unquoted represenation of the value.
+	Value string
+
+	// Anchor holds the anchor name for this node, which allows aliases to point to it.
+	Anchor string
+
+	// Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+	Alias *Node
+
+	// Content holds contained nodes for documents, mappings, and sequences.
+	Content []*Node
+
+	// HeadComment holds any comments in the lines preceding the node and
+	// not separated by an empty line.
+	HeadComment string
+
+	// LineComment holds any comments at the end of the line where the node is in.
+	LineComment string
+
+	// FootComment holds any comments following the node and before empty lines.
+	FootComment string
+
+	// Line and Column hold the node position in the decoded YAML text.
+	// These fields are not respected when encoding the node.
+	Line   int
+	Column int
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+	return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+		n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+	return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+	if n.indicatedString() {
+		return strTag
+	}
+	if n.Tag == "" || n.Tag == "!" {
+		switch n.Kind {
+		case MappingNode:
+			return mapTag
+		case SequenceNode:
+			return seqTag
+		case AliasNode:
+			if n.Alias != nil {
+				return n.Alias.ShortTag()
+			}
+		case ScalarNode:
+			tag, _ := resolve("", n.Value)
+			return tag
+		case 0:
+			// Special case to make the zero value convenient.
+			if n.IsZero() {
+				return nullTag
+			}
+		}
+		return ""
+	}
+	return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+	return n.Kind == ScalarNode &&
+		(shortTag(n.Tag) == strTag ||
+			(n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+	n.Kind = ScalarNode
+	if utf8.ValidString(s) {
+		n.Value = s
+		n.Tag = strTag
+	} else {
+		n.Value = encodeBase64(s)
+		n.Tag = binaryTag
+	}
+	if strings.Contains(n.Value, "\n") {
+		n.Style = LiteralStyle
+	}
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+	FieldsMap  map[string]fieldInfo
+	FieldsList []fieldInfo
+
+	// InlineMap is the number of the field in the struct that
+	// contains an ,inline map, or -1 if there's none.
+	InlineMap int
+
+	// InlineUnmarshalers holds indexes to inlined fields that
+	// contain unmarshaler values.
+	InlineUnmarshalers [][]int
+}
+
+type fieldInfo struct {
+	Key       string
+	Num       int
+	OmitEmpty bool
+	Flow      bool
+	// Id holds the unique field identifier, so we can cheaply
+	// check for field duplicates without maintaining an extra map.
+	Id int
+
+	// Inline holds the field index if the field is part of an inlined struct.
+	Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+var unmarshalerType reflect.Type
+
+func init() {
+	var v Unmarshaler
+	unmarshalerType = reflect.ValueOf(&v).Elem().Type()
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+	fieldMapMutex.RLock()
+	sinfo, found := structMap[st]
+	fieldMapMutex.RUnlock()
+	if found {
+		return sinfo, nil
+	}
+
+	n := st.NumField()
+	fieldsMap := make(map[string]fieldInfo)
+	fieldsList := make([]fieldInfo, 0, n)
+	inlineMap := -1
+	inlineUnmarshalers := [][]int(nil)
+	for i := 0; i != n; i++ {
+		field := st.Field(i)
+		if field.PkgPath != "" && !field.Anonymous {
+			continue // Private field
+		}
+
+		info := fieldInfo{Num: i}
+
+		tag := field.Tag.Get("yaml")
+		if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+			tag = string(field.Tag)
+		}
+		if tag == "-" {
+			continue
+		}
+
+		inline := false
+		fields := strings.Split(tag, ",")
+		if len(fields) > 1 {
+			for _, flag := range fields[1:] {
+				switch flag {
+				case "omitempty":
+					info.OmitEmpty = true
+				case "flow":
+					info.Flow = true
+				case "inline":
+					inline = true
+				default:
+					return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
+				}
+			}
+			tag = fields[0]
+		}
+
+		if inline {
+			switch field.Type.Kind() {
+			case reflect.Map:
+				if inlineMap >= 0 {
+					return nil, errors.New("multiple ,inline maps in struct " + st.String())
+				}
+				if field.Type.Key() != reflect.TypeOf("") {
+					return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+				}
+				inlineMap = info.Num
+			case reflect.Struct, reflect.Ptr:
+				ftype := field.Type
+				for ftype.Kind() == reflect.Ptr {
+					ftype = ftype.Elem()
+				}
+				if ftype.Kind() != reflect.Struct {
+					return nil, errors.New("option ,inline may only be used on a struct or map field")
+				}
+				if reflect.PtrTo(ftype).Implements(unmarshalerType) {
+					inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+				} else {
+					sinfo, err := getStructInfo(ftype)
+					if err != nil {
+						return nil, err
+					}
+					for _, index := range sinfo.InlineUnmarshalers {
+						inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
+					}
+					for _, finfo := range sinfo.FieldsList {
+						if _, found := fieldsMap[finfo.Key]; found {
+							msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+							return nil, errors.New(msg)
+						}
+						if finfo.Inline == nil {
+							finfo.Inline = []int{i, finfo.Num}
+						} else {
+							finfo.Inline = append([]int{i}, finfo.Inline...)
+						}
+						finfo.Id = len(fieldsList)
+						fieldsMap[finfo.Key] = finfo
+						fieldsList = append(fieldsList, finfo)
+					}
+				}
+			default:
+				return nil, errors.New("option ,inline may only be used on a struct or map field")
+			}
+			continue
+		}
+
+		if tag != "" {
+			info.Key = tag
+		} else {
+			info.Key = strings.ToLower(field.Name)
+		}
+
+		if _, found = fieldsMap[info.Key]; found {
+			msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+			return nil, errors.New(msg)
+		}
+
+		info.Id = len(fieldsList)
+		fieldsList = append(fieldsList, info)
+		fieldsMap[info.Key] = info
+	}
+
+	sinfo = &structInfo{
+		FieldsMap:          fieldsMap,
+		FieldsList:         fieldsList,
+		InlineMap:          inlineMap,
+		InlineUnmarshalers: inlineUnmarshalers,
+	}
+
+	fieldMapMutex.Lock()
+	structMap[st] = sinfo
+	fieldMapMutex.Unlock()
+	return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+	IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+	kind := v.Kind()
+	if z, ok := v.Interface().(IsZeroer); ok {
+		if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+			return true
+		}
+		return z.IsZero()
+	}
+	switch kind {
+	case reflect.String:
+		return len(v.String()) == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	case reflect.Slice:
+		return v.Len() == 0
+	case reflect.Map:
+		return v.Len() == 0
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Struct:
+		vt := v.Type()
+		for i := v.NumField() - 1; i >= 0; i-- {
+			if vt.Field(i).PkgPath != "" {
+				continue // Private field
+			}
+			if !isZero(v.Field(i)) {
+				return false
+			}
+		}
+		return true
+	}
+	return false
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/yamlh.go b/notifier/vendor/go.yaml.in/yaml/v3/yamlh.go
new file mode 100644
index 00000000..f59aa40f
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/yamlh.go
@@ -0,0 +1,811 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+	"fmt"
+	"io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+	major int8 // The major version number.
+	minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+	handle []byte // The tag handle.
+	prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+	// Let the parser choose the encoding.
+	yaml_ANY_ENCODING yaml_encoding_t = iota
+
+	yaml_UTF8_ENCODING    // The default UTF-8 encoding.
+	yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+	yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+	// Let the parser choose the break type.
+	yaml_ANY_BREAK yaml_break_t = iota
+
+	yaml_CR_BREAK   // Use CR for line breaks (Mac style).
+	yaml_LN_BREAK   // Use LN for line breaks (Unix style).
+	yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+	// No error is produced.
+	yaml_NO_ERROR yaml_error_type_t = iota
+
+	yaml_MEMORY_ERROR   // Cannot allocate or reallocate a block of memory.
+	yaml_READER_ERROR   // Cannot read or decode the input stream.
+	yaml_SCANNER_ERROR  // Cannot scan the input stream.
+	yaml_PARSER_ERROR   // Cannot parse the input stream.
+	yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+	yaml_WRITER_ERROR   // Cannot write to the output stream.
+	yaml_EMITTER_ERROR  // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+	index  int // The position index.
+	line   int // The position line.
+	column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
+
+	yaml_PLAIN_SCALAR_STYLE         yaml_scalar_style_t = 1 << iota // The plain scalar style.
+	yaml_SINGLE_QUOTED_SCALAR_STYLE                                 // The single-quoted scalar style.
+	yaml_DOUBLE_QUOTED_SCALAR_STYLE                                 // The double-quoted scalar style.
+	yaml_LITERAL_SCALAR_STYLE                                       // The literal scalar style.
+	yaml_FOLDED_SCALAR_STYLE                                        // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+	yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+	yaml_FLOW_SEQUENCE_STYLE  // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+	// Let the emitter choose the style.
+	yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+	yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+	yaml_FLOW_MAPPING_STYLE  // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+	// An empty token.
+	yaml_NO_TOKEN yaml_token_type_t = iota
+
+	yaml_STREAM_START_TOKEN // A STREAM-START token.
+	yaml_STREAM_END_TOKEN   // A STREAM-END token.
+
+	yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+	yaml_TAG_DIRECTIVE_TOKEN     // A TAG-DIRECTIVE token.
+	yaml_DOCUMENT_START_TOKEN    // A DOCUMENT-START token.
+	yaml_DOCUMENT_END_TOKEN      // A DOCUMENT-END token.
+
+	yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+	yaml_BLOCK_MAPPING_START_TOKEN  // A BLOCK-SEQUENCE-END token.
+	yaml_BLOCK_END_TOKEN            // A BLOCK-END token.
+
+	yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+	yaml_FLOW_SEQUENCE_END_TOKEN   // A FLOW-SEQUENCE-END token.
+	yaml_FLOW_MAPPING_START_TOKEN  // A FLOW-MAPPING-START token.
+	yaml_FLOW_MAPPING_END_TOKEN    // A FLOW-MAPPING-END token.
+
+	yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+	yaml_FLOW_ENTRY_TOKEN  // A FLOW-ENTRY token.
+	yaml_KEY_TOKEN         // A KEY token.
+	yaml_VALUE_TOKEN       // A VALUE token.
+
+	yaml_ALIAS_TOKEN  // An ALIAS token.
+	yaml_ANCHOR_TOKEN // An ANCHOR token.
+	yaml_TAG_TOKEN    // A TAG token.
+	yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+	switch tt {
+	case yaml_NO_TOKEN:
+		return "yaml_NO_TOKEN"
+	case yaml_STREAM_START_TOKEN:
+		return "yaml_STREAM_START_TOKEN"
+	case yaml_STREAM_END_TOKEN:
+		return "yaml_STREAM_END_TOKEN"
+	case yaml_VERSION_DIRECTIVE_TOKEN:
+		return "yaml_VERSION_DIRECTIVE_TOKEN"
+	case yaml_TAG_DIRECTIVE_TOKEN:
+		return "yaml_TAG_DIRECTIVE_TOKEN"
+	case yaml_DOCUMENT_START_TOKEN:
+		return "yaml_DOCUMENT_START_TOKEN"
+	case yaml_DOCUMENT_END_TOKEN:
+		return "yaml_DOCUMENT_END_TOKEN"
+	case yaml_BLOCK_SEQUENCE_START_TOKEN:
+		return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+	case yaml_BLOCK_MAPPING_START_TOKEN:
+		return "yaml_BLOCK_MAPPING_START_TOKEN"
+	case yaml_BLOCK_END_TOKEN:
+		return "yaml_BLOCK_END_TOKEN"
+	case yaml_FLOW_SEQUENCE_START_TOKEN:
+		return "yaml_FLOW_SEQUENCE_START_TOKEN"
+	case yaml_FLOW_SEQUENCE_END_TOKEN:
+		return "yaml_FLOW_SEQUENCE_END_TOKEN"
+	case yaml_FLOW_MAPPING_START_TOKEN:
+		return "yaml_FLOW_MAPPING_START_TOKEN"
+	case yaml_FLOW_MAPPING_END_TOKEN:
+		return "yaml_FLOW_MAPPING_END_TOKEN"
+	case yaml_BLOCK_ENTRY_TOKEN:
+		return "yaml_BLOCK_ENTRY_TOKEN"
+	case yaml_FLOW_ENTRY_TOKEN:
+		return "yaml_FLOW_ENTRY_TOKEN"
+	case yaml_KEY_TOKEN:
+		return "yaml_KEY_TOKEN"
+	case yaml_VALUE_TOKEN:
+		return "yaml_VALUE_TOKEN"
+	case yaml_ALIAS_TOKEN:
+		return "yaml_ALIAS_TOKEN"
+	case yaml_ANCHOR_TOKEN:
+		return "yaml_ANCHOR_TOKEN"
+	case yaml_TAG_TOKEN:
+		return "yaml_TAG_TOKEN"
+	case yaml_SCALAR_TOKEN:
+		return "yaml_SCALAR_TOKEN"
+	}
+	return ""
+}
+
+// The token structure.
+type yaml_token_t struct {
+	// The token type.
+	typ yaml_token_type_t
+
+	// The start/end of the token.
+	start_mark, end_mark yaml_mark_t
+
+	// The stream encoding (for yaml_STREAM_START_TOKEN).
+	encoding yaml_encoding_t
+
+	// The alias/anchor/scalar value or tag/tag directive handle
+	// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+	value []byte
+
+	// The tag suffix (for yaml_TAG_TOKEN).
+	suffix []byte
+
+	// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+	prefix []byte
+
+	// The scalar style (for yaml_SCALAR_TOKEN).
+	style yaml_scalar_style_t
+
+	// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+	major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+	// An empty event.
+	yaml_NO_EVENT yaml_event_type_t = iota
+
+	yaml_STREAM_START_EVENT   // A STREAM-START event.
+	yaml_STREAM_END_EVENT     // A STREAM-END event.
+	yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+	yaml_DOCUMENT_END_EVENT   // A DOCUMENT-END event.
+	yaml_ALIAS_EVENT          // An ALIAS event.
+	yaml_SCALAR_EVENT         // A SCALAR event.
+	yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+	yaml_SEQUENCE_END_EVENT   // A SEQUENCE-END event.
+	yaml_MAPPING_START_EVENT  // A MAPPING-START event.
+	yaml_MAPPING_END_EVENT    // A MAPPING-END event.
+	yaml_TAIL_COMMENT_EVENT
+)
+
+var eventStrings = []string{
+	yaml_NO_EVENT:             "none",
+	yaml_STREAM_START_EVENT:   "stream start",
+	yaml_STREAM_END_EVENT:     "stream end",
+	yaml_DOCUMENT_START_EVENT: "document start",
+	yaml_DOCUMENT_END_EVENT:   "document end",
+	yaml_ALIAS_EVENT:          "alias",
+	yaml_SCALAR_EVENT:         "scalar",
+	yaml_SEQUENCE_START_EVENT: "sequence start",
+	yaml_SEQUENCE_END_EVENT:   "sequence end",
+	yaml_MAPPING_START_EVENT:  "mapping start",
+	yaml_MAPPING_END_EVENT:    "mapping end",
+	yaml_TAIL_COMMENT_EVENT:   "tail comment",
+}
+
+func (e yaml_event_type_t) String() string {
+	if e < 0 || int(e) >= len(eventStrings) {
+		return fmt.Sprintf("unknown event %d", e)
+	}
+	return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+	// The event type.
+	typ yaml_event_type_t
+
+	// The start and end of the event.
+	start_mark, end_mark yaml_mark_t
+
+	// The document encoding (for yaml_STREAM_START_EVENT).
+	encoding yaml_encoding_t
+
+	// The version directive (for yaml_DOCUMENT_START_EVENT).
+	version_directive *yaml_version_directive_t
+
+	// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+	tag_directives []yaml_tag_directive_t
+
+	// The comments
+	head_comment []byte
+	line_comment []byte
+	foot_comment []byte
+	tail_comment []byte
+
+	// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+	anchor []byte
+
+	// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+	tag []byte
+
+	// The scalar value (for yaml_SCALAR_EVENT).
+	value []byte
+
+	// Is the document start/end indicator implicit, or the tag optional?
+	// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+	implicit bool
+
+	// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+	quoted_implicit bool
+
+	// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+	style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t     { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t   { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+	yaml_NULL_TAG      = "tag:yaml.org,2002:null"      // The tag !!null with the only possible value: null.
+	yaml_BOOL_TAG      = "tag:yaml.org,2002:bool"      // The tag !!bool with the values: true and false.
+	yaml_STR_TAG       = "tag:yaml.org,2002:str"       // The tag !!str for string values.
+	yaml_INT_TAG       = "tag:yaml.org,2002:int"       // The tag !!int for integer values.
+	yaml_FLOAT_TAG     = "tag:yaml.org,2002:float"     // The tag !!float for float values.
+	yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+	yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+	yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+	// Not in original libyaml.
+	yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+	yaml_MERGE_TAG  = "tag:yaml.org,2002:merge"
+
+	yaml_DEFAULT_SCALAR_TAG   = yaml_STR_TAG // The default scalar tag is !!str.
+	yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+	yaml_DEFAULT_MAPPING_TAG  = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+	// An empty node.
+	yaml_NO_NODE yaml_node_type_t = iota
+
+	yaml_SCALAR_NODE   // A scalar node.
+	yaml_SEQUENCE_NODE // A sequence node.
+	yaml_MAPPING_NODE  // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+	key   int // The key of the element.
+	value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+	typ yaml_node_type_t // The node type.
+	tag []byte           // The node tag.
+
+	// The node data.
+
+	// The scalar parameters (for yaml_SCALAR_NODE).
+	scalar struct {
+		value  []byte              // The scalar value.
+		length int                 // The length of the scalar value.
+		style  yaml_scalar_style_t // The scalar style.
+	}
+
+	// The sequence parameters (for YAML_SEQUENCE_NODE).
+	sequence struct {
+		items_data []yaml_node_item_t    // The stack of sequence items.
+		style      yaml_sequence_style_t // The sequence style.
+	}
+
+	// The mapping parameters (for yaml_MAPPING_NODE).
+	mapping struct {
+		pairs_data  []yaml_node_pair_t   // The stack of mapping pairs (key, value).
+		pairs_start *yaml_node_pair_t    // The beginning of the stack.
+		pairs_end   *yaml_node_pair_t    // The end of the stack.
+		pairs_top   *yaml_node_pair_t    // The top of the stack.
+		style       yaml_mapping_style_t // The mapping style.
+	}
+
+	start_mark yaml_mark_t // The beginning of the node.
+	end_mark   yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+	// The document nodes.
+	nodes []yaml_node_t
+
+	// The version directive.
+	version_directive *yaml_version_directive_t
+
+	// The list of tag directives.
+	tag_directives_data  []yaml_tag_directive_t
+	tag_directives_start int // The beginning of the tag directives list.
+	tag_directives_end   int // The end of the tag directives list.
+
+	start_implicit int // Is the document start indicator implicit?
+	end_implicit   int // Is the document end indicator implicit?
+
+	// The start/end of the document.
+	start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out]   data        A pointer to an application data specified by
+//
+//	yaml_parser_set_input().
+//
+// [out]      buffer      The buffer to write the data from the source.
+// [in]       size        The size of the buffer.
+// [out]      size_read   The actual number of bytes read from the source.
+//
+// On success, the handler should return 1.  If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+	possible     bool        // Is a simple key possible?
+	required     bool        // Is a simple key required?
+	token_number int         // The number of the token.
+	mark         yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+	yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+	yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE           // Expect the beginning of an implicit document.
+	yaml_PARSE_DOCUMENT_START_STATE                    // Expect DOCUMENT-START.
+	yaml_PARSE_DOCUMENT_CONTENT_STATE                  // Expect the content of a document.
+	yaml_PARSE_DOCUMENT_END_STATE                      // Expect DOCUMENT-END.
+	yaml_PARSE_BLOCK_NODE_STATE                        // Expect a block node.
+	yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+	yaml_PARSE_FLOW_NODE_STATE                         // Expect a flow node.
+	yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE        // Expect the first entry of a block sequence.
+	yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE              // Expect an entry of a block sequence.
+	yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE         // Expect an entry of an indentless sequence.
+	yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE           // Expect the first key of a block mapping.
+	yaml_PARSE_BLOCK_MAPPING_KEY_STATE                 // Expect a block mapping key.
+	yaml_PARSE_BLOCK_MAPPING_VALUE_STATE               // Expect a block mapping value.
+	yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE         // Expect the first entry of a flow sequence.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE               // Expect an entry of a flow sequence.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE   // Expect a key of an ordered mapping.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+	yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE   // Expect the and of an ordered mapping entry.
+	yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE            // Expect the first key of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_KEY_STATE                  // Expect a key of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_VALUE_STATE                // Expect a value of a flow mapping.
+	yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE          // Expect an empty value of a flow mapping.
+	yaml_PARSE_END_STATE                               // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+	switch ps {
+	case yaml_PARSE_STREAM_START_STATE:
+		return "yaml_PARSE_STREAM_START_STATE"
+	case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+		return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+	case yaml_PARSE_DOCUMENT_START_STATE:
+		return "yaml_PARSE_DOCUMENT_START_STATE"
+	case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+		return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+	case yaml_PARSE_DOCUMENT_END_STATE:
+		return "yaml_PARSE_DOCUMENT_END_STATE"
+	case yaml_PARSE_BLOCK_NODE_STATE:
+		return "yaml_PARSE_BLOCK_NODE_STATE"
+	case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+		return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+	case yaml_PARSE_FLOW_NODE_STATE:
+		return "yaml_PARSE_FLOW_NODE_STATE"
+	case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+		return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+	case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+	case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+		return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+	case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+	case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+	case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+	case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+		return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+	case yaml_PARSE_END_STATE:
+		return "yaml_PARSE_END_STATE"
+	}
+	return ""
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+	anchor []byte      // The anchor.
+	index  int         // The node id.
+	mark   yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+	// Error handling
+
+	error yaml_error_type_t // Error type.
+
+	problem string // Error description.
+
+	// The byte about which the problem occurred.
+	problem_offset int
+	problem_value  int
+	problem_mark   yaml_mark_t
+
+	// The error context.
+	context      string
+	context_mark yaml_mark_t
+
+	// Reader stuff
+
+	read_handler yaml_read_handler_t // Read handler.
+
+	input_reader io.Reader // File input data.
+	input        []byte    // String input data.
+	input_pos    int
+
+	eof bool // EOF flag
+
+	buffer     []byte // The working buffer.
+	buffer_pos int    // The current position of the buffer.
+
+	unread int // The number of unread characters in the buffer.
+
+	newlines int // The number of line breaks since last non-break/non-blank character
+
+	raw_buffer     []byte // The raw buffer.
+	raw_buffer_pos int    // The current position of the buffer.
+
+	encoding yaml_encoding_t // The input encoding.
+
+	offset int         // The offset of the current position (in bytes).
+	mark   yaml_mark_t // The mark of the current position.
+
+	// Comments
+
+	head_comment []byte // The current head comments
+	line_comment []byte // The current line comments
+	foot_comment []byte // The current foot comments
+	tail_comment []byte // Foot comment that happens at the end of a block.
+	stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+	comments      []yaml_comment_t // The folded comments for all parsed tokens
+	comments_head int
+
+	// Scanner stuff
+
+	stream_start_produced bool // Have we started to scan the input stream?
+	stream_end_produced   bool // Have we reached the end of the input stream?
+
+	flow_level int // The number of unclosed '[' and '{' indicators.
+
+	tokens          []yaml_token_t // The tokens queue.
+	tokens_head     int            // The head of the tokens queue.
+	tokens_parsed   int            // The number of tokens fetched from the queue.
+	token_available bool           // Does the tokens queue contain a token ready for dequeueing.
+
+	indent  int   // The current indentation level.
+	indents []int // The indentation levels stack.
+
+	simple_key_allowed bool                // May a simple key occur at the current position?
+	simple_keys        []yaml_simple_key_t // The stack of simple keys.
+	simple_keys_by_tok map[int]int         // possible simple_key indexes indexed by token_number
+
+	// Parser stuff
+
+	state          yaml_parser_state_t    // The current parser state.
+	states         []yaml_parser_state_t  // The parser states stack.
+	marks          []yaml_mark_t          // The stack of marks.
+	tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+	// Dumper stuff
+
+	aliases []yaml_alias_data_t // The alias data.
+
+	document *yaml_document_t // The currently parsed document.
+}
+
+type yaml_comment_t struct {
+	scan_mark  yaml_mark_t // Position where scanning for comments started
+	token_mark yaml_mark_t // Position after which tokens will be associated with this comment
+	start_mark yaml_mark_t // Position of '#' comment mark
+	end_mark   yaml_mark_t // Position where comment terminated
+
+	head []byte
+	line []byte
+	foot []byte
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output.  The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out]   data        A pointer to an application data specified by
+//
+//	yaml_emitter_set_output().
+//
+// @param[in]       buffer      The buffer with bytes to be written.
+// @param[in]       size        The size of the buffer.
+//
+// @returns On success, the handler should return @c 1.  If the handler failed,
+// the returned value should be @c 0.
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+	// Expect STREAM-START.
+	yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+	yaml_EMIT_FIRST_DOCUMENT_START_STATE       // Expect the first DOCUMENT-START or STREAM-END.
+	yaml_EMIT_DOCUMENT_START_STATE             // Expect DOCUMENT-START or STREAM-END.
+	yaml_EMIT_DOCUMENT_CONTENT_STATE           // Expect the content of a document.
+	yaml_EMIT_DOCUMENT_END_STATE               // Expect DOCUMENT-END.
+	yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE   // Expect the first item of a flow sequence.
+	yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE   // Expect the next item of a flow sequence, with the comma already written out
+	yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE         // Expect an item of a flow sequence.
+	yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE     // Expect the first key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE     // Expect the next key of a flow mapping, with the comma already written out
+	yaml_EMIT_FLOW_MAPPING_KEY_STATE           // Expect a key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE  // Expect a value for a simple key of a flow mapping.
+	yaml_EMIT_FLOW_MAPPING_VALUE_STATE         // Expect a value of a flow mapping.
+	yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE  // Expect the first item of a block sequence.
+	yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE        // Expect an item of a block sequence.
+	yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE    // Expect the first key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_KEY_STATE          // Expect the key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+	yaml_EMIT_BLOCK_MAPPING_VALUE_STATE        // Expect a value of a block mapping.
+	yaml_EMIT_END_STATE                        // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal.  Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+	// Error handling
+
+	error   yaml_error_type_t // Error type.
+	problem string            // Error description.
+
+	// Writer stuff
+
+	write_handler yaml_write_handler_t // Write handler.
+
+	output_buffer *[]byte   // String output data.
+	output_writer io.Writer // File output data.
+
+	buffer     []byte // The working buffer.
+	buffer_pos int    // The current position of the buffer.
+
+	raw_buffer     []byte // The raw buffer.
+	raw_buffer_pos int    // The current position of the buffer.
+
+	encoding yaml_encoding_t // The stream encoding.
+
+	// Emitter stuff
+
+	canonical   bool         // If the output is in the canonical style?
+	best_indent int          // The number of indentation spaces.
+	best_width  int          // The preferred width of the output lines.
+	unicode     bool         // Allow unescaped non-ASCII characters?
+	line_break  yaml_break_t // The preferred line break.
+
+	state  yaml_emitter_state_t   // The current emitter state.
+	states []yaml_emitter_state_t // The stack of states.
+
+	events      []yaml_event_t // The event queue.
+	events_head int            // The head of the event queue.
+
+	indents []int // The stack of indentation levels.
+
+	tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+	indent int // The current indentation level.
+
+	compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements?
+
+	flow_level int // The current flow level.
+
+	root_context       bool // Is it the document root context?
+	sequence_context   bool // Is it a sequence context?
+	mapping_context    bool // Is it a mapping context?
+	simple_key_context bool // Is it a simple mapping key context?
+
+	line       int  // The current line.
+	column     int  // The current column.
+	whitespace bool // If the last character was a whitespace?
+	indention  bool // If the last character was an indentation character (' ', '-', '?', ':')?
+	open_ended bool // If an explicit document end is required?
+
+	space_above bool // Is there's an empty line above?
+	foot_indent int  // The indent used to write the foot comment above, or -1 if none.
+
+	// Anchor analysis.
+	anchor_data struct {
+		anchor []byte // The anchor value.
+		alias  bool   // Is it an alias?
+	}
+
+	// Tag analysis.
+	tag_data struct {
+		handle []byte // The tag handle.
+		suffix []byte // The tag suffix.
+	}
+
+	// Scalar analysis.
+	scalar_data struct {
+		value                 []byte              // The scalar value.
+		multiline             bool                // Does the scalar contain line breaks?
+		flow_plain_allowed    bool                // Can the scalar be expessed in the flow plain style?
+		block_plain_allowed   bool                // Can the scalar be expressed in the block plain style?
+		single_quoted_allowed bool                // Can the scalar be expressed in the single quoted style?
+		block_allowed         bool                // Can the scalar be expressed in the literal or folded styles?
+		style                 yaml_scalar_style_t // The output style.
+	}
+
+	// Comments
+	head_comment []byte
+	line_comment []byte
+	foot_comment []byte
+	tail_comment []byte
+
+	key_line_comment []byte
+
+	// Dumper stuff
+
+	opened bool // If the stream was already opened?
+	closed bool // If the stream was already closed?
+
+	// The information associated with the document nodes.
+	anchors *struct {
+		references int  // The number of references.
+		anchor     int  // The anchor id.
+		serialized bool // If the node has been emitted?
+	}
+
+	last_anchor_id int // The last assigned anchor id.
+
+	document *yaml_document_t // The currently emitted document.
+}
diff --git a/notifier/vendor/go.yaml.in/yaml/v3/yamlprivateh.go b/notifier/vendor/go.yaml.in/yaml/v3/yamlprivateh.go
new file mode 100644
index 00000000..dea1ba96
--- /dev/null
+++ b/notifier/vendor/go.yaml.in/yaml/v3/yamlprivateh.go
@@ -0,0 +1,198 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+const (
+	// The size of the input raw buffer.
+	input_raw_buffer_size = 512
+
+	// The size of the input buffer.
+	// It should be possible to decode the whole raw buffer.
+	input_buffer_size = input_raw_buffer_size * 3
+
+	// The size of the output buffer.
+	output_buffer_size = 128
+
+	// The size of the output raw buffer.
+	// It should be possible to encode the whole output buffer.
+	output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+	// The size of other stacks and queues.
+	initial_stack_size  = 16
+	initial_queue_size  = 16
+	initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+	return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+	return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+	bi := b[i]
+	if bi >= 'A' && bi <= 'F' {
+		return int(bi) - 'A' + 10
+	}
+	if bi >= 'a' && bi <= 'f' {
+		return int(bi) - 'a' + 10
+	}
+	return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+	return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+	return ((b[i] == 0x0A) || // . == #x0A
+		(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+		(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+		(b[i] > 0xC2 && b[i] < 0xED) ||
+		(b[i] == 0xED && b[i+1] < 0xA0) ||
+		(b[i] == 0xEE) ||
+		(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+			!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+			!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+	return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+	return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+	return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+	return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+	//return is_space(b, i) || is_tab(b, i)
+	return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+	return (b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+	return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+	//return is_break(b, i) || is_z(b, i)
+	return (
+	// is_break:
+	b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		// is_z:
+		b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+	//return is_space(b, i) || is_breakz(b, i)
+	return (
+	// is_space:
+	b[i] == ' ' ||
+		// is_breakz:
+		b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+	//return is_blank(b, i) || is_breakz(b, i)
+	return (
+	// is_blank:
+	b[i] == ' ' || b[i] == '\t' ||
+		// is_breakz:
+		b[i] == '\r' || // CR (#xD)
+		b[i] == '\n' || // LF (#xA)
+		b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+		b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+		b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+	// Don't replace these by a switch without first
+	// confirming that it is being inlined.
+	if b&0x80 == 0x00 {
+		return 1
+	}
+	if b&0xE0 == 0xC0 {
+		return 2
+	}
+	if b&0xF0 == 0xE0 {
+		return 3
+	}
+	if b&0xF8 == 0xF0 {
+		return 4
+	}
+	return 0
+
+}
diff --git a/notifier/vendor/golang.org/x/exp/constraints/constraints.go b/notifier/vendor/golang.org/x/exp/constraints/constraints.go
deleted file mode 100644
index 2c033dff..00000000
--- a/notifier/vendor/golang.org/x/exp/constraints/constraints.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package constraints defines a set of useful constraints to be used
-// with type parameters.
-package constraints
-
-// Signed is a constraint that permits any signed integer type.
-// If future releases of Go add new predeclared signed integer types,
-// this constraint will be modified to include them.
-type Signed interface {
-	~int | ~int8 | ~int16 | ~int32 | ~int64
-}
-
-// Unsigned is a constraint that permits any unsigned integer type.
-// If future releases of Go add new predeclared unsigned integer types,
-// this constraint will be modified to include them.
-type Unsigned interface {
-	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
-// Integer is a constraint that permits any integer type.
-// If future releases of Go add new predeclared integer types,
-// this constraint will be modified to include them.
-type Integer interface {
-	Signed | Unsigned
-}
-
-// Float is a constraint that permits any floating-point type.
-// If future releases of Go add new predeclared floating-point types,
-// this constraint will be modified to include them.
-type Float interface {
-	~float32 | ~float64
-}
-
-// Complex is a constraint that permits any complex numeric type.
-// If future releases of Go add new predeclared complex numeric types,
-// this constraint will be modified to include them.
-type Complex interface {
-	~complex64 | ~complex128
-}
-
-// Ordered is a constraint that permits any ordered type: any type
-// that supports the operators < <= >= >.
-// If future releases of Go add new ordered types,
-// this constraint will be modified to include them.
-type Ordered interface {
-	Integer | Float | ~string
-}
diff --git a/notifier/vendor/golang.org/x/exp/slices/cmp.go b/notifier/vendor/golang.org/x/exp/slices/cmp.go
deleted file mode 100644
index fbf1934a..00000000
--- a/notifier/vendor/golang.org/x/exp/slices/cmp.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-import "golang.org/x/exp/constraints"
-
-// min is a version of the predeclared function from the Go 1.21 release.
-func min[T constraints.Ordered](a, b T) T {
-	if a < b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// max is a version of the predeclared function from the Go 1.21 release.
-func max[T constraints.Ordered](a, b T) T {
-	if a > b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// cmpLess is a copy of cmp.Less from the Go 1.21 release.
-func cmpLess[T constraints.Ordered](x, y T) bool {
-	return (isNaN(x) && !isNaN(y)) || x < y
-}
-
-// cmpCompare is a copy of cmp.Compare from the Go 1.21 release.
-func cmpCompare[T constraints.Ordered](x, y T) int {
-	xNaN := isNaN(x)
-	yNaN := isNaN(y)
-	if xNaN && yNaN {
-		return 0
-	}
-	if xNaN || x < y {
-		return -1
-	}
-	if yNaN || x > y {
-		return +1
-	}
-	return 0
-}
diff --git a/notifier/vendor/golang.org/x/exp/slices/slices.go b/notifier/vendor/golang.org/x/exp/slices/slices.go
deleted file mode 100644
index 46ceac34..00000000
--- a/notifier/vendor/golang.org/x/exp/slices/slices.go
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package slices defines various functions useful with slices of any type.
-package slices
-
-import (
-	"unsafe"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Equal reports whether two slices are equal: the same length and all
-// elements equal. If the lengths are different, Equal returns false.
-// Otherwise, the elements are compared in increasing index order, and the
-// comparison stops at the first unequal pair.
-// Floating point NaNs are not considered equal.
-func Equal[S ~[]E, E comparable](s1, s2 S) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i := range s1 {
-		if s1[i] != s2[i] {
-			return false
-		}
-	}
-	return true
-}
-
-// EqualFunc reports whether two slices are equal using an equality
-// function on each pair of elements. If the lengths are different,
-// EqualFunc returns false. Otherwise, the elements are compared in
-// increasing index order, and the comparison stops at the first index
-// for which eq returns false.
-func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i, v1 := range s1 {
-		v2 := s2[i]
-		if !eq(v1, v2) {
-			return false
-		}
-	}
-	return true
-}
-
-// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
-// of elements. The elements are compared sequentially, starting at index 0,
-// until one element is not equal to the other.
-// The result of comparing the first non-matching elements is returned.
-// If both slices are equal until one of them ends, the shorter slice is
-// considered less than the longer one.
-// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
-func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmpCompare(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// CompareFunc is like [Compare] but uses a custom comparison function on each
-// pair of elements.
-// The result is the first non-zero result of cmp; if cmp always
-// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
-// and +1 if len(s1) > len(s2).
-func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmp(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// Index returns the index of the first occurrence of v in s,
-// or -1 if not present.
-func Index[S ~[]E, E comparable](s S, v E) int {
-	for i := range s {
-		if v == s[i] {
-			return i
-		}
-	}
-	return -1
-}
-
-// IndexFunc returns the first index i satisfying f(s[i]),
-// or -1 if none do.
-func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
-	for i := range s {
-		if f(s[i]) {
-			return i
-		}
-	}
-	return -1
-}
-
-// Contains reports whether v is present in s.
-func Contains[S ~[]E, E comparable](s S, v E) bool {
-	return Index(s, v) >= 0
-}
-
-// ContainsFunc reports whether at least one
-// element e of s satisfies f(e).
-func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
-	return IndexFunc(s, f) >= 0
-}
-
-// Insert inserts the values v... into s at index i,
-// returning the modified slice.
-// The elements at s[i:] are shifted up to make room.
-// In the returned slice r, r[i] == v[0],
-// and r[i+len(v)] == value originally at r[i].
-// Insert panics if i is out of range.
-// This function is O(len(s) + len(v)).
-func Insert[S ~[]E, E any](s S, i int, v ...E) S {
-	m := len(v)
-	if m == 0 {
-		return s
-	}
-	n := len(s)
-	if i == n {
-		return append(s, v...)
-	}
-	if n+m > cap(s) {
-		// Use append rather than make so that we bump the size of
-		// the slice up to the next storage class.
-		// This is what Grow does but we don't call Grow because
-		// that might copy the values twice.
-		s2 := append(s[:i], make(S, n+m-i)...)
-		copy(s2[i:], v)
-		copy(s2[i+m:], s[i:])
-		return s2
-	}
-	s = s[:n+m]
-
-	// before:
-	// s: aaaaaaaabbbbccccccccdddd
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// after:
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	//
-	// a are the values that don't move in s.
-	// v are the values copied in from v.
-	// b and c are the values from s that are shifted up in index.
-	// d are the values that get overwritten, never to be seen again.
-
-	if !overlaps(v, s[i+m:]) {
-		// Easy case - v does not overlap either the c or d regions.
-		// (It might be in some of a or b, or elsewhere entirely.)
-		// The data we copy up doesn't write to v at all, so just do it.
-
-		copy(s[i+m:], s[i:])
-
-		// Now we have
-		// s: aaaaaaaabbbbbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// Note the b values are duplicated.
-
-		copy(s[i:], v)
-
-		// Now we have
-		// s: aaaaaaaavvvvbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// That's the result we want.
-		return s
-	}
-
-	// The hard case - v overlaps c or d. We can't just shift up
-	// the data because we'd move or clobber the values we're trying
-	// to insert.
-	// So instead, write v on top of d, then rotate.
-	copy(s[n:], v)
-
-	// Now we have
-	// s: aaaaaaaabbbbccccccccvvvv
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-
-	rotateRight(s[i:], m)
-
-	// Now we have
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// That's the result we want.
-	return s
-}
-
-// clearSlice sets all elements up to the length of s to the zero value of E.
-// We may use the builtin clear func instead, and remove clearSlice, when upgrading
-// to Go 1.21+.
-func clearSlice[S ~[]E, E any](s S) {
-	var zero E
-	for i := range s {
-		s[i] = zero
-	}
-}
-
-// Delete removes the elements s[i:j] from s, returning the modified slice.
-// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
-// Delete is O(len(s)-i), so if many items must be deleted, it is better to
-// make a single call deleting them all together than to delete one at a time.
-// Delete zeroes the elements s[len(s)-(j-i):len(s)].
-func Delete[S ~[]E, E any](s S, i, j int) S {
-	_ = s[i:j:len(s)] // bounds check
-
-	if i == j {
-		return s
-	}
-
-	oldlen := len(s)
-	s = append(s[:i], s[j:]...)
-	clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
-	return s
-}
-
-// DeleteFunc removes any elements from s for which del returns true,
-// returning the modified slice.
-// DeleteFunc zeroes the elements between the new length and the original length.
-func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
-	i := IndexFunc(s, del)
-	if i == -1 {
-		return s
-	}
-	// Don't start copying elements until we find one to delete.
-	for j := i + 1; j < len(s); j++ {
-		if v := s[j]; !del(v) {
-			s[i] = v
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Replace replaces the elements s[i:j] by the given v, and returns the
-// modified slice. Replace panics if s[i:j] is not a valid slice of s.
-// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
-func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
-	_ = s[i:j] // verify that i:j is a valid subslice
-
-	if i == j {
-		return Insert(s, i, v...)
-	}
-	if j == len(s) {
-		return append(s[:i], v...)
-	}
-
-	tot := len(s[:i]) + len(v) + len(s[j:])
-	if tot > cap(s) {
-		// Too big to fit, allocate and copy over.
-		s2 := append(s[:i], make(S, tot-i)...) // See Insert
-		copy(s2[i:], v)
-		copy(s2[i+len(v):], s[j:])
-		return s2
-	}
-
-	r := s[:tot]
-
-	if i+len(v) <= j {
-		// Easy, as v fits in the deleted portion.
-		copy(r[i:], v)
-		if i+len(v) != j {
-			copy(r[i+len(v):], s[j:])
-		}
-		clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
-		return r
-	}
-
-	// We are expanding (v is bigger than j-i).
-	// The situation is something like this:
-	// (example has i=4,j=8,len(s)=16,len(v)=6)
-	// s: aaaaxxxxbbbbbbbbyy
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	// a: prefix of s
-	// x: deleted range
-	// b: more of s
-	// y: area to expand into
-
-	if !overlaps(r[i+len(v):], v) {
-		// Easy, as v is not clobbered by the first copy.
-		copy(r[i+len(v):], s[j:])
-		copy(r[i:], v)
-		return r
-	}
-
-	// This is a situation where we don't have a single place to which
-	// we can copy v. Parts of it need to go to two different places.
-	// We want to copy the prefix of v into y and the suffix into x, then
-	// rotate |y| spots to the right.
-	//
-	//        v[2:]      v[:2]
-	//         |           |
-	// s: aaaavvvvbbbbbbbbvv
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	//
-	// If either of those two destinations don't alias v, then we're good.
-	y := len(v) - (j - i) // length of y portion
-
-	if !overlaps(r[i:j], v) {
-		copy(r[i:j], v[y:])
-		copy(r[len(s):], v[:y])
-		rotateRight(r[i:], y)
-		return r
-	}
-	if !overlaps(r[len(s):], v) {
-		copy(r[len(s):], v[:y])
-		copy(r[i:j], v[y:])
-		rotateRight(r[i:], y)
-		return r
-	}
-
-	// Now we know that v overlaps both x and y.
-	// That means that the entirety of b is *inside* v.
-	// So we don't need to preserve b at all; instead we
-	// can copy v first, then copy the b part of v out of
-	// v to the right destination.
-	k := startIdx(v, s[j:])
-	copy(r[i:], v)
-	copy(r[i+len(v):], r[i+k:])
-	return r
-}
-
-// Clone returns a copy of the slice.
-// The elements are copied using assignment, so this is a shallow clone.
-func Clone[S ~[]E, E any](s S) S {
-	// Preserve nil in case it matters.
-	if s == nil {
-		return nil
-	}
-	return append(S([]E{}), s...)
-}
-
-// Compact replaces consecutive runs of equal elements with a single copy.
-// This is like the uniq command found on Unix.
-// Compact modifies the contents of the slice s and returns the modified slice,
-// which may have a smaller length.
-// Compact zeroes the elements between the new length and the original length.
-func Compact[S ~[]E, E comparable](s S) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if s[k] != s[k-1] {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// CompactFunc is like [Compact] but uses an equality function to compare elements.
-// For runs of elements that compare equal, CompactFunc keeps the first one.
-// CompactFunc zeroes the elements between the new length and the original length.
-func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if !eq(s[k], s[k-1]) {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Grow increases the slice's capacity, if necessary, to guarantee space for
-// another n elements. After Grow(n), at least n elements can be appended
-// to the slice without another allocation. If n is negative or too large to
-// allocate the memory, Grow panics.
-func Grow[S ~[]E, E any](s S, n int) S {
-	if n < 0 {
-		panic("cannot be negative")
-	}
-	if n -= cap(s) - len(s); n > 0 {
-		// TODO(https://go.dev/issue/53888): Make using []E instead of S
-		// to workaround a compiler bug where the runtime.growslice optimization
-		// does not take effect. Revert when the compiler is fixed.
-		s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)]
-	}
-	return s
-}
-
-// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
-func Clip[S ~[]E, E any](s S) S {
-	return s[:len(s):len(s)]
-}
-
-// Rotation algorithm explanation:
-//
-// rotate left by 2
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join first parts
-//   89234567 01
-// recursively rotate first left part by 2
-//   23456789 01
-// join at the end
-//   2345678901
-//
-// rotate left by 8
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join last parts
-//   89 23456701
-// recursively rotate second part left by 6
-//   89 01234567
-// join at the end
-//   8901234567
-
-// TODO: There are other rotate algorithms.
-// This algorithm has the desirable property that it moves each element exactly twice.
-// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes.
-// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
-
-// rotateLeft rotates b left by n spaces.
-// s_final[i] = s_orig[i+r], wrapping around.
-func rotateLeft[E any](s []E, r int) {
-	for r != 0 && r != len(s) {
-		if r*2 <= len(s) {
-			swap(s[:r], s[len(s)-r:])
-			s = s[:len(s)-r]
-		} else {
-			swap(s[:len(s)-r], s[r:])
-			s, r = s[len(s)-r:], r*2-len(s)
-		}
-	}
-}
-func rotateRight[E any](s []E, r int) {
-	rotateLeft(s, len(s)-r)
-}
-
-// swap swaps the contents of x and y. x and y must be equal length and disjoint.
-func swap[E any](x, y []E) {
-	for i := 0; i < len(x); i++ {
-		x[i], y[i] = y[i], x[i]
-	}
-}
-
-// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
-func overlaps[E any](a, b []E) bool {
-	if len(a) == 0 || len(b) == 0 {
-		return false
-	}
-	elemSize := unsafe.Sizeof(a[0])
-	if elemSize == 0 {
-		return false
-	}
-	// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
-	// Also see crypto/internal/alias/alias.go:AnyOverlap
-	return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
-		uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
-}
-
-// startIdx returns the index in haystack where the needle starts.
-// prerequisite: the needle must be aliased entirely inside the haystack.
-func startIdx[E any](haystack, needle []E) int {
-	p := &needle[0]
-	for i := range haystack {
-		if p == &haystack[i] {
-			return i
-		}
-	}
-	// TODO: what if the overlap is by a non-integral number of Es?
-	panic("needle not found")
-}
-
-// Reverse reverses the elements of the slice in place.
-func Reverse[S ~[]E, E any](s S) {
-	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
-		s[i], s[j] = s[j], s[i]
-	}
-}
diff --git a/notifier/vendor/golang.org/x/exp/slices/sort.go b/notifier/vendor/golang.org/x/exp/slices/sort.go
deleted file mode 100644
index f58bbc7b..00000000
--- a/notifier/vendor/golang.org/x/exp/slices/sort.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp
-
-package slices
-
-import (
-	"math/bits"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Sort sorts a slice of any ordered type in ascending order.
-// When sorting floating-point numbers, NaNs are ordered before other values.
-func Sort[S ~[]E, E constraints.Ordered](x S) {
-	n := len(x)
-	pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
-}
-
-// SortFunc sorts the slice x in ascending order as determined by the cmp
-// function. This sort is not guaranteed to be stable.
-// cmp(a, b) should return a negative number when a < b, a positive number when
-// a > b and zero when a == b or when a is not comparable to b in the sense
-// of the formal definition of Strict Weak Ordering.
-//
-// SortFunc requires that cmp is a strict weak ordering.
-// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
-// To indicate 'uncomparable', return 0 from the function.
-func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	n := len(x)
-	pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
-}
-
-// SortStableFunc sorts the slice x while keeping the original order of equal
-// elements, using cmp to compare elements in the same way as [SortFunc].
-func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	stableCmpFunc(x, len(x), cmp)
-}
-
-// IsSorted reports whether x is sorted in ascending order.
-func IsSorted[S ~[]E, E constraints.Ordered](x S) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmpLess(x[i], x[i-1]) {
-			return false
-		}
-	}
-	return true
-}
-
-// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
-// comparison function as defined by [SortFunc].
-func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmp(x[i], x[i-1]) < 0 {
-			return false
-		}
-	}
-	return true
-}
-
-// Min returns the minimal value in x. It panics if x is empty.
-// For floating-point numbers, Min propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Min[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Min: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = min(m, x[i])
-	}
-	return m
-}
-
-// MinFunc returns the minimal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one minimal element
-// according to the cmp function, MinFunc returns the first one.
-func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MinFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) < 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// Max returns the maximal value in x. It panics if x is empty.
-// For floating-point E, Max propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Max[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Max: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = max(m, x[i])
-	}
-	return m
-}
-
-// MaxFunc returns the maximal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one maximal element
-// according to the cmp function, MaxFunc returns the first one.
-func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MaxFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) > 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// BinarySearch searches for target in a sorted slice and returns the position
-// where target is found, or the position where target would appear in the
-// sort order; it also returns a bool saying whether the target is really found
-// in the slice. The slice must be sorted in increasing order.
-func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) {
-	// Inlining is faster than calling BinarySearchFunc with a lambda.
-	n := len(x)
-	// Define x[-1] < target and x[n] >= target.
-	// Invariant: x[i-1] < target, x[j] >= target.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmpLess(x[h], target) {
-			i = h + 1 // preserves x[i-1] < target
-		} else {
-			j = h // preserves x[j] >= target
-		}
-	}
-	// i == j, x[i-1] < target, and x[j] (= x[i]) >= target  =>  answer is i.
-	return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
-}
-
-// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
-// function. The slice must be sorted in increasing order, where "increasing"
-// is defined by cmp. cmp should return 0 if the slice element matches
-// the target, a negative number if the slice element precedes the target,
-// or a positive number if the slice element follows the target.
-// cmp must implement the same ordering as the slice, such that if
-// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
-func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
-	n := len(x)
-	// Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 .
-	// Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmp(x[h], target) < 0 {
-			i = h + 1 // preserves cmp(x[i - 1], target) < 0
-		} else {
-			j = h // preserves cmp(x[j], target) >= 0
-		}
-	}
-	// i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0  =>  answer is i.
-	return i, i < n && cmp(x[i], target) == 0
-}
-
-type sortedHint int // hint for pdqsort when choosing the pivot
-
-const (
-	unknownHint sortedHint = iota
-	increasingHint
-	decreasingHint
-)
-
-// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
-type xorshift uint64
-
-func (r *xorshift) Next() uint64 {
-	*r ^= *r << 13
-	*r ^= *r >> 17
-	*r ^= *r << 5
-	return uint64(*r)
-}
-
-func nextPowerOfTwo(length int) uint {
-	return 1 << bits.Len(uint(length))
-}
-
-// isNaN reports whether x is a NaN without requiring the math package.
-// This will always return false if T is not floating-point.
-func isNaN[T constraints.Ordered](x T) bool {
-	return x != x
-}
diff --git a/notifier/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/notifier/vendor/golang.org/x/exp/slices/zsortanyfunc.go
deleted file mode 100644
index 06f2c7a2..00000000
--- a/notifier/vendor/golang.org/x/exp/slices/zsortanyfunc.go
+++ /dev/null
@@ -1,479 +0,0 @@
-// Code generated by gen_sort_variants.go; DO NOT EDIT.
-
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-// insertionSortCmpFunc sorts data[a:b] using insertion sort.
-func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	for i := a + 1; i < b; i++ {
-		for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
-			data[j], data[j-1] = data[j-1], data[j]
-		}
-	}
-}
-
-// siftDownCmpFunc implements the heap property on data[lo:hi].
-// first is an offset into the array where the root of the heap lies.
-func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
-	root := lo
-	for {
-		child := 2*root + 1
-		if child >= hi {
-			break
-		}
-		if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
-			child++
-		}
-		if !(cmp(data[first+root], data[first+child]) < 0) {
-			return
-		}
-		data[first+root], data[first+child] = data[first+child], data[first+root]
-		root = child
-	}
-}
-
-func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	first := a
-	lo := 0
-	hi := b - a
-
-	// Build heap with greatest element at top.
-	for i := (hi - 1) / 2; i >= 0; i-- {
-		siftDownCmpFunc(data, i, hi, first, cmp)
-	}
-
-	// Pop elements, largest first, into end of data.
-	for i := hi - 1; i >= 0; i-- {
-		data[first], data[first+i] = data[first+i], data[first]
-		siftDownCmpFunc(data, lo, i, first, cmp)
-	}
-}
-
-// pdqsortCmpFunc sorts data[a:b].
-// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
-// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
-// C++ implementation: https://github.com/orlp/pdqsort
-// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
-// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
-func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
-	const maxInsertion = 12
-
-	var (
-		wasBalanced    = true // whether the last partitioning was reasonably balanced
-		wasPartitioned = true // whether the slice was already partitioned
-	)
-
-	for {
-		length := b - a
-
-		if length <= maxInsertion {
-			insertionSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// Fall back to heapsort if too many bad choices were made.
-		if limit == 0 {
-			heapSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// If the last partitioning was imbalanced, we need to breaking patterns.
-		if !wasBalanced {
-			breakPatternsCmpFunc(data, a, b, cmp)
-			limit--
-		}
-
-		pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
-		if hint == decreasingHint {
-			reverseRangeCmpFunc(data, a, b, cmp)
-			// The chosen pivot was pivot-a elements after the start of the array.
-			// After reversing it is pivot-a elements before the end of the array.
-			// The idea came from Rust's implementation.
-			pivot = (b - 1) - (pivot - a)
-			hint = increasingHint
-		}
-
-		// The slice is likely already sorted.
-		if wasBalanced && wasPartitioned && hint == increasingHint {
-			if partialInsertionSortCmpFunc(data, a, b, cmp) {
-				return
-			}
-		}
-
-		// Probably the slice contains many duplicate elements, partition the slice into
-		// elements equal to and elements greater than the pivot.
-		if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
-			mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
-			a = mid
-			continue
-		}
-
-		mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
-		wasPartitioned = alreadyPartitioned
-
-		leftLen, rightLen := mid-a, b-mid
-		balanceThreshold := length / 8
-		if leftLen < rightLen {
-			wasBalanced = leftLen >= balanceThreshold
-			pdqsortCmpFunc(data, a, mid, limit, cmp)
-			a = mid + 1
-		} else {
-			wasBalanced = rightLen >= balanceThreshold
-			pdqsortCmpFunc(data, mid+1, b, limit, cmp)
-			b = mid
-		}
-	}
-}
-
-// partitionCmpFunc does one quicksort partition.
-// Let p = data[pivot]
-// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/notifier/vendor/golang.org/x/exp/slices/zsortordered.go b/notifier/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c39..00000000 --- a/notifier/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/notifier/vendor/golang.org/x/exp/slog/attr.go b/notifier/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/notifier/vendor/golang.org/x/exp/slog/doc.go b/notifier/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf867..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/notifier/vendor/golang.org/x/exp/slog/handler.go b/notifier/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb8..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/notifier/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/notifier/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/notifier/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/notifier/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/notifier/vendor/golang.org/x/exp/slog/json_handler.go b/notifier/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada86..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/notifier/vendor/golang.org/x/exp/slog/level.go b/notifier/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0a..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/notifier/vendor/golang.org/x/exp/slog/logger.go b/notifier/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec993..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/notifier/vendor/golang.org/x/exp/slog/noplog.bench b/notifier/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/notifier/vendor/golang.org/x/exp/slog/record.go b/notifier/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/notifier/vendor/golang.org/x/exp/slog/text_handler.go b/notifier/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b71..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/notifier/vendor/golang.org/x/exp/slog/value.go b/notifier/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46f..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/notifier/vendor/golang.org/x/exp/slog/value_119.go b/notifier/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d732..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/notifier/vendor/golang.org/x/exp/slog/value_120.go b/notifier/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c093..00000000 --- a/notifier/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/notifier/vendor/golang.org/x/net/http2/frame.go b/notifier/vendor/golang.org/x/net/http2/frame.go index 97bd8b06..db3264da 100644 --- a/notifier/vendor/golang.org/x/net/http2/frame.go +++ b/notifier/vendor/golang.org/x/net/http2/frame.go @@ -39,7 +39,7 @@ const ( FrameContinuation FrameType = 0x9 ) -var frameName = map[FrameType]string{ +var frameNames = [...]string{ FrameData: "DATA", FrameHeaders: "HEADERS", FramePriority: "PRIORITY", @@ -53,10 +53,10 @@ var frameName = map[FrameType]string{ } func (t FrameType) String() string { - if s, ok := frameName[t]; ok { - return s + if int(t) < len(frameNames) { + return frameNames[t] } - return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) + return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t) } // Flags is a bitmask of HTTP/2 flags. @@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{ // might be 0). type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) -var frameParsers = map[FrameType]frameParser{ +var frameParsers = [...]frameParser{ FrameData: parseDataFrame, FrameHeaders: parseHeadersFrame, FramePriority: parsePriorityFrame, @@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{ } func typeFrameParser(t FrameType) frameParser { - if f := frameParsers[t]; f != nil { - return f + if int(t) < len(frameParsers) { + return frameParsers[t] } return parseUnknownFrame } @@ -509,7 +509,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { } if fh.Length > fr.maxReadSize { if fh == invalidHTTP1LookingFrameHeader() { - return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge) } return nil, ErrFrameTooLarge } diff --git a/notifier/vendor/golang.org/x/net/http2/http2.go b/notifier/vendor/golang.org/x/net/http2/http2.go index 6c18ea23..ea5ae629 100644 --- a/notifier/vendor/golang.org/x/net/http2/http2.go +++ b/notifier/vendor/golang.org/x/net/http2/http2.go @@ -11,8 +11,6 @@ // requires Go 1.6 or later) // // See https://http2.github.io/ for more information on HTTP/2. -// -// See https://http2.golang.org/ for a test server running this code. package http2 // import "golang.org/x/net/http2" import ( diff --git a/notifier/vendor/golang.org/x/net/trace/events.go b/notifier/vendor/golang.org/x/net/trace/events.go index c646a695..3aaffdd1 100644 --- a/notifier/vendor/golang.org/x/net/trace/events.go +++ b/notifier/vendor/golang.org/x/net/trace/events.go @@ -508,7 +508,7 @@ const eventsHTML = ` {{$el.When}} {{$el.ElapsedTime}} - {{$el.Title}} + {{$el.Title}} {{if $.Expanded}} diff --git a/notifier/vendor/golang.org/x/sync/errgroup/errgroup.go b/notifier/vendor/golang.org/x/sync/errgroup/errgroup.go index cb6bb9ad..1d8cffae 100644 --- a/notifier/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/notifier/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -12,8 +12,6 @@ package errgroup import ( "context" "fmt" - "runtime" - "runtime/debug" "sync" ) @@ -33,10 +31,6 @@ type Group struct { errOnce sync.Once err error - - mu sync.Mutex - panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked. - abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit). } func (g *Group) done() { @@ -56,22 +50,13 @@ func WithContext(ctx context.Context) (*Group, context.Context) { return &Group{cancel: cancel}, ctx } -// Wait blocks until all function calls from the Go method have returned -// normally, then returns the first non-nil error (if any) from them. -// -// If any of the calls panics, Wait panics with a [PanicValue]; -// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit. +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. func (g *Group) Wait() error { g.wg.Wait() if g.cancel != nil { g.cancel(g.err) } - if g.panicValue != nil { - panic(g.panicValue) - } - if g.abnormal { - runtime.Goexit() - } return g.err } @@ -81,53 +66,31 @@ func (g *Group) Wait() error { // It blocks until the new goroutine can be added without the number of // goroutines in the group exceeding the configured limit. // -// The first goroutine in the group that returns a non-nil error, panics, or -// invokes [runtime.Goexit] will cancel the associated Context, if any. +// The first goroutine in the group that returns a non-nil error will +// cancel the associated Context, if any. The error will be returned +// by Wait. func (g *Group) Go(f func() error) { if g.sem != nil { g.sem <- token{} } - g.add(f) -} - -func (g *Group) add(f func() error) { g.wg.Add(1) go func() { defer g.done() - normalReturn := false - defer func() { - if normalReturn { - return - } - v := recover() - g.mu.Lock() - defer g.mu.Unlock() - if !g.abnormal { - if g.cancel != nil { - g.cancel(g.err) - } - g.abnormal = true - } - if v != nil && g.panicValue == nil { - switch v := v.(type) { - case error: - g.panicValue = PanicError{ - Recovered: v, - Stack: debug.Stack(), - } - default: - g.panicValue = PanicValue{ - Recovered: v, - Stack: debug.Stack(), - } - } - } - }() - err := f() - normalReturn = true - if err != nil { + // It is tempting to propagate panics from f() + // up to the goroutine that calls Wait, but + // it creates more problems than it solves: + // - it delays panics arbitrarily, + // making bugs harder to detect; + // - it turns f's panic stack into a mere value, + // hiding it from crash-monitoring tools; + // - it risks deadlocks that hide the panic entirely, + // if f's panic leaves the program in a state + // that prevents the Wait call from being reached. + // See #53757, #74275, #74304, #74306. + + if err := f(); err != nil { g.errOnce.Do(func() { g.err = err if g.cancel != nil { @@ -152,7 +115,19 @@ func (g *Group) TryGo(f func() error) bool { } } - g.add(f) + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() return true } @@ -174,34 +149,3 @@ func (g *Group) SetLimit(n int) { } g.sem = make(chan token, n) } - -// PanicError wraps an error recovered from an unhandled panic -// when calling a function passed to Go or TryGo. -type PanicError struct { - Recovered error - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicError) Error() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} - -func (p PanicError) Unwrap() error { return p.Recovered } - -// PanicValue wraps a value that does not implement the error interface, -// recovered from an unhandled panic when calling a function passed to Go or -// TryGo. -type PanicValue struct { - Recovered any - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicValue) String() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} diff --git a/notifier/vendor/golang.org/x/sys/unix/mkerrors.sh b/notifier/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c..d1c8b264 100644 --- a/notifier/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/notifier/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/notifier/vendor/golang.org/x/sys/unix/syscall_darwin.go b/notifier/vendor/golang.org/x/sys/unix/syscall_darwin.go index 798f61ad..7838ca5d 100644 --- a/notifier/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/notifier/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,14 +602,9 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) const minIovec = 8 func Readv(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = readv(fd, iovecs) @@ -618,9 +613,6 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { } func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = preadv(fd, iovecs, offset) @@ -629,10 +621,6 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -644,10 +632,6 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -707,45 +691,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } } -func darwinMajorMinPatch() (maj, min, patch int, err error) { - var un Utsname - err = Uname(&un) - if err != nil { - return - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range un.Release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return 0, 0, 0, ENOTSUP - } - case b == 0: - break Loop - default: - return 0, 0, 0, ENOTSUP - } - } - if c != 2 { - return 0, 0, 0, ENOTSUP - } - return mmp[0], mmp[1], mmp[2], nil -} - -func darwinKernelVersionMin(maj, min, patch int) bool { - actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() - if err != nil { - return false - } - return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) -} - +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux.go index 4f432bfe..b6db27d9 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -319,6 +319,7 @@ const ( AUDIT_INTEGRITY_POLICY_RULE = 0x70f AUDIT_INTEGRITY_RULE = 0x70d AUDIT_INTEGRITY_STATUS = 0x70a + AUDIT_INTEGRITY_USERSPACE = 0x710 AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f AUDIT_IPE_ACCESS = 0x58c @@ -327,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -491,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -527,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -554,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -843,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2023-03-01)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x30 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -936,11 +942,10 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 + ETHTOOL_FAMILY_NAME = "ethtool" + ETHTOOL_FAMILY_VERSION = 0x1 ETHTOOL_FEC_AUTO = 0x2 ETHTOOL_FEC_BASER = 0x10 ETHTOOL_FEC_LLRS = 0x20 @@ -1203,13 +1208,18 @@ const ( FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 FAN_EPIDFD = -0x2 + FAN_ERRNO_BITS = 0x8 + FAN_ERRNO_MASK = 0xff + FAN_ERRNO_SHIFT = 0x18 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 + FAN_EVENT_INFO_TYPE_RANGE = 0x6 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_FS_ERROR = 0x8000 @@ -1224,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1240,6 +1253,7 @@ const ( FAN_OPEN_EXEC = 0x1000 FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 + FAN_PRE_ACCESS = 0x100000 FAN_Q_OVERFLOW = 0x4000 FAN_RENAME = 0x10000000 FAN_REPORT_DFID_NAME = 0xc00 @@ -1247,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1266,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1574,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1625,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1687,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1809,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2485,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2644,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2724,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2787,7 +2813,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1e + RTA_MAX = 0x1f RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -2864,10 +2890,12 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELANYCAST = 0x3d RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELLINKPROP = 0x6d RTM_DELMDB = 0x55 + RTM_DELMULTICAST = 0x39 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 @@ -2917,11 +2945,13 @@ const ( RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 + RTM_NEWANYCAST = 0x3c RTM_NEWCACHEREPORT = 0x60 RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWLINKPROP = 0x6c RTM_NEWMDB = 0x54 + RTM_NEWMULTICAST = 0x38 RTM_NEWNDUSEROPT = 0x44 RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 @@ -2970,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -2987,11 +3018,12 @@ const ( RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 RWF_ATOMIC = 0x40 + RWF_DONTCACHE = 0x80 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x7f + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3271,6 +3303,7 @@ const ( STATX_BTIME = 0x800 STATX_CTIME = 0x80 STATX_DIOALIGN = 0x2000 + STATX_DIO_READ_ALIGN = 0x20000 STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 @@ -3322,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xe + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3392,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3503,6 +3534,7 @@ const ( TP_STATUS_WRONG_FORMAT = 0x4 TRACEFS_MAGIC = 0x74726163 TS_COMM_LEN = 0x20 + UBI_IOCECNFO = 0xc01c6f06 UDF_SUPER_MAGIC = 0x15013346 UDP_CORK = 0x1 UDP_ENCAP = 0x64 @@ -3515,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3559,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3673,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 75207613..1c37f9fb 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -372,6 +374,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c68acda5..6f54d34a 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -373,6 +375,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index a8c607ab..783ec5c1 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -378,6 +380,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 18563dd8..ca83d3ba 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 22912cda..607e611c 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -365,6 +367,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 29344eb3..b9cb5bd3 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 20d51fb9..65b078a6 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 321b6090..5298a303 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 9bacdf1e..7bc557c8 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c2242726..152399bb 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -426,6 +428,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 6270c8ee..1a1ce240 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 9966c194..4231a1fb 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 848e5fcc..21c0e952 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -362,6 +364,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 669b2adb..f00d1cd7 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -434,6 +436,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 4834e575..bc8d539e 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 @@ -473,6 +475,7 @@ const ( SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff3..aca56ee4 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb45069..2ea1ef58 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e50297..d22c8af3 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec5..5ee264ae 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a..f9f03ebf 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a33..87c2118e 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b99622..391ad102 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9..56561577 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc..0482b52e 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfb..71806f08 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b4463650..e35a7105 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c1..2aea4767 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 84053916..6c9bb4e5 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790..680bc991 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f..620f2710 100644 --- a/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux.go index a46abe64..cd236443 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,10 @@ type Statx_t struct { Atomic_write_unit_min uint32 Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 _ [1]uint32 - _ [9]uint64 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2226,8 +2229,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -2314,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2594,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -3802,7 +3813,16 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2d + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3842,7 +3862,17 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -3949,7 +3979,12 @@ const ( ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb ETHTOOL_A_RINGS_CQE_SIZE = 0xc ETHTOOL_A_RINGS_TX_PUSH = 0xd - ETHTOOL_A_RINGS_MAX = 0x10 + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 ETHTOOL_A_CHANNELS_UNSPEC = 0x0 ETHTOOL_A_CHANNELS_HEADER = 0x1 ETHTOOL_A_CHANNELS_RX_MAX = 0x2 @@ -4015,7 +4050,9 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x6 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4101,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4613,6 +4663,7 @@ const ( NL80211_ATTR_AKM_SUITES = 0x4c NL80211_ATTR_AP_ISOLATE = 0x60 NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a NL80211_ATTR_AUTH_DATA = 0x9c NL80211_ATTR_AUTH_TYPE = 0x35 NL80211_ATTR_BANDS = 0xef @@ -4623,6 +4674,7 @@ const ( NL80211_ATTR_BSS_BASIC_RATES = 0x24 NL80211_ATTR_BSS = 0x2f NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 NL80211_ATTR_BSS_HT_OPMODE = 0x6d NL80211_ATTR_BSSID = 0xf5 NL80211_ATTR_BSS_SELECT = 0xe3 @@ -4682,6 +4734,7 @@ const ( NL80211_ATTR_DTIM_PERIOD = 0xd NL80211_ATTR_DURATION = 0x57 NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 NL80211_ATTR_EML_CAPABILITY = 0x13d NL80211_ATTR_EXT_CAPA = 0xa9 NL80211_ATTR_EXT_CAPA_MASK = 0xaa @@ -4717,6 +4770,7 @@ const ( NL80211_ATTR_HIDDEN_SSID = 0x7e NL80211_ATTR_HT_CAPABILITY = 0x1f NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 NL80211_ATTR_IE_ASSOC_RESP = 0x80 NL80211_ATTR_IE = 0x2a NL80211_ATTR_IE_PROBE_RESP = 0x7f @@ -4747,9 +4801,10 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14d + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 NL80211_ATTR_MAX_MATCH_SETS = 0x85 NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 @@ -4774,9 +4829,12 @@ const ( NL80211_ATTR_MGMT_SUBTYPE = 0x29 NL80211_ATTR_MLD_ADDR = 0x13a NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 NL80211_ATTR_MLO_LINK_ID = 0x139 NL80211_ATTR_MLO_LINKS = 0x138 NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 NL80211_ATTR_MNTR_FLAGS = 0x17 NL80211_ATTR_MPATH_INFO = 0x1b NL80211_ATTR_MPATH_NEXT_HOP = 0x1a @@ -4809,12 +4867,14 @@ const ( NL80211_ATTR_PORT_AUTHORIZED = 0x103 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 NL80211_ATTR_PREV_BSSID = 0x4f NL80211_ATTR_PRIVACY = 0x46 NL80211_ATTR_PROBE_RESP = 0x91 NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 NL80211_ATTR_PROTOCOL_FEATURES = 0xad NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 NL80211_ATTR_QOS_MAP = 0xc7 NL80211_ATTR_RADAR_BACKGROUND = 0x134 NL80211_ATTR_RADAR_EVENT = 0xa8 @@ -4943,7 +5003,9 @@ const ( NL80211_ATTR_WIPHY_FREQ = 0x26 NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 @@ -4978,6 +5040,8 @@ const ( NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 NL80211_BAND_ATTR_MAX = 0xd NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc NL80211_BAND_ATTR_VHT_CAPA = 0x8 NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 @@ -5001,6 +5065,10 @@ const ( NL80211_BSS_BEACON_INTERVAL = 0x4 NL80211_BSS_BEACON_TSF = 0xd NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 NL80211_BSS_CAPABILITY = 0x5 NL80211_BSS_CHAIN_SIGNAL = 0x13 NL80211_BSS_CHAN_WIDTH_10 = 0x1 @@ -5032,6 +5100,9 @@ const ( NL80211_BSS_STATUS = 0x9 NL80211_BSS_STATUS_IBSS_JOINED = 0x2 NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 NL80211_CHAN_HT20 = 0x1 NL80211_CHAN_HT40MINUS = 0x2 NL80211_CHAN_HT40PLUS = 0x3 @@ -5117,7 +5188,8 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9b + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5161,6 +5233,7 @@ const ( NL80211_CMD_SET_COALESCE = 0x65 NL80211_CMD_SET_CQM = 0x3f NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 NL80211_CMD_SET_INTERFACE = 0x6 NL80211_CMD_SET_KEY = 0xa NL80211_CMD_SET_MAC_ACL = 0x5d @@ -5180,6 +5253,7 @@ const ( NL80211_CMD_SET_SAR_SPECS = 0x8c NL80211_CMD_SET_STATION = 0x12 NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 NL80211_CMD_SET_WDS_PEER = 0x42 NL80211_CMD_SET_WIPHY = 0x2 @@ -5247,6 +5321,7 @@ const ( NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 @@ -5262,6 +5337,7 @@ const ( NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 @@ -5281,9 +5357,12 @@ const ( NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c NL80211_EXT_FEATURE_RRM = 0x1 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 @@ -5295,8 +5374,10 @@ const ( NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f NL80211_EXT_FEATURE_SECURE_RTT = 0x38 NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 NL80211_EXT_FEATURE_TXQS = 0x1c NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 @@ -5343,7 +5424,10 @@ const ( NL80211_FREQUENCY_ATTR_2MHZ = 0x16 NL80211_FREQUENCY_ATTR_4MHZ = 0x17 NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 NL80211_FREQUENCY_ATTR_DISABLED = 0x2 @@ -5351,12 +5435,14 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b NL80211_FREQUENCY_ATTR_NO_HE = 0x13 @@ -5364,8 +5450,11 @@ const ( NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_OFFSET = 0x14 NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c NL80211_FREQUENCY_ATTR_RADAR = 0x5 NL80211_FREQUENCY_ATTR_WMM = 0x12 NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 @@ -5430,6 +5519,7 @@ const ( NL80211_IFTYPE_STATION = 0x2 NL80211_IFTYPE_UNSPECIFIED = 0x0 NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 NL80211_KCK_EXT_LEN = 0x18 NL80211_KCK_LEN = 0x10 NL80211_KEK_EXT_LEN = 0x20 @@ -5458,9 +5548,10 @@ const ( NL80211_MAX_SUPP_HT_RATES = 0x4d NL80211_MAX_SUPP_RATES = 0x20 NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 @@ -5703,11 +5794,16 @@ const ( NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c NL80211_RATE_INFO_BITRATE32 = 0x5 NL80211_RATE_INFO_BITRATE = 0x1 NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 @@ -5753,6 +5849,8 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 NL80211_RATE_INFO_SHORT_GI = 0x4 NL80211_RATE_INFO_VHT_MCS = 0x6 NL80211_RATE_INFO_VHT_NSS = 0x7 @@ -5770,14 +5868,19 @@ const ( NL80211_REKEY_DATA_KEK = 0x1 NL80211_REKEY_DATA_REPLAY_CTR = 0x3 NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 NL80211_RRF_AUTO_BW = 0x800 NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 NL80211_RRF_GO_CONCURRENT = 0x1000 NL80211_RRF_IR_CONCURRENT = 0x1000 NL80211_RRF_NO_160MHZ = 0x10000 NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 NL80211_RRF_NO_80MHZ = 0x8000 NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 NL80211_RRF_NO_HE = 0x20000 NL80211_RRF_NO_HT40 = 0x6000 NL80211_RRF_NO_HT40MINUS = 0x2000 @@ -5788,7 +5891,10 @@ const ( NL80211_RRF_NO_IR = 0x80 NL80211_RRF_NO_OFDM = 0x1 NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 NL80211_RRF_PTMP_ONLY = 0x40 NL80211_RRF_PTP_ONLY = 0x20 NL80211_RXMGMT_FLAG_ANSWERED = 0x1 @@ -5849,6 +5955,7 @@ const ( NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 NL80211_STA_FLAG_TDLS_PEER = 0x6 NL80211_STA_FLAG_WME = 0x3 NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 @@ -6007,6 +6114,13 @@ const ( NL80211_VHT_CAPABILITY_LEN = 0xc NL80211_VHT_NSS_MAX = 0x8 NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 NL80211_WMMR_AIFSN = 0x3 NL80211_WMMR_CW_MAX = 0x2 NL80211_WMMR_CW_MIN = 0x1 @@ -6038,6 +6152,7 @@ const ( NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fd402da4..485f2d3a 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -338,6 +338,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index eb7a5e18..ecbd1ad8 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -351,6 +351,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index d78ac108..02f0463a 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -329,6 +329,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index cd06d47f..6f4d400d 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -330,6 +330,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2f28fe26..cd532cfa 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -331,6 +331,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 71d6cac2..41336208 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8596d453..eaa37eb7 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index cd60ea18..98ae6a1e 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b0ae420c..cae19615 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 83597287..6ce3b4e0 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,7 +285,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -341,6 +341,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 69eb6a5c..c7429c6a 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5f583cb6..4bf4baf4 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index ad05b51a..e9709d70 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -358,6 +358,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cf3ce900..fb44268c 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -353,6 +353,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 590b5673..9c38265c 100644 --- a/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/notifier/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -335,6 +335,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/notifier/vendor/golang.org/x/telemetry/.dockerignore b/notifier/vendor/golang.org/x/telemetry/.dockerignore new file mode 100644 index 00000000..416ae44a --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.dockerignore @@ -0,0 +1,17 @@ +.git +.localstorage +node_modules +devtools +.eslint* +.gitignore +.prettier* +.stylelint* +CONTRIBUTING.md +LICENSE +npm +npx +package-lock.json +package.json +PATENTS +README.md +tsconfig.json \ No newline at end of file diff --git a/notifier/vendor/golang.org/x/telemetry/.eslintrc.json b/notifier/vendor/golang.org/x/telemetry/.eslintrc.json new file mode 100644 index 00000000..ba5e242b --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "root": true, + "ignorePatterns": ["*.min.js"] +} diff --git a/notifier/vendor/golang.org/x/telemetry/.gitattributes b/notifier/vendor/golang.org/x/telemetry/.gitattributes new file mode 100644 index 00000000..f529a114 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.gitattributes @@ -0,0 +1,14 @@ +# Treat all files in the repo as binary, with no git magic updating +# line endings. This produces predictable results in different environments. +# +# Windows users contributing to Go will need to use a modern version +# of git and editors capable of LF line endings. +# +# Windows .bat files are known to have multiple bugs when run with LF +# endings. So if they are checked in with CRLF endings, there should +# be a test like the one in test/winbatch.go in the go repository. +# (See golang.org/issue/37791.) +# +# See golang.org/issue/9281. + +* -text diff --git a/notifier/vendor/golang.org/x/telemetry/.gitignore b/notifier/vendor/golang.org/x/telemetry/.gitignore new file mode 100644 index 00000000..46770c48 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.gitignore @@ -0,0 +1,2 @@ +node_modules +.localstorage \ No newline at end of file diff --git a/notifier/vendor/golang.org/x/telemetry/.prettierrc.json b/notifier/vendor/golang.org/x/telemetry/.prettierrc.json new file mode 100644 index 00000000..91c0b944 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.prettierrc.json @@ -0,0 +1 @@ +{"proseWrap": "always"} diff --git a/notifier/vendor/golang.org/x/telemetry/.stylelintrc.json b/notifier/vendor/golang.org/x/telemetry/.stylelintrc.json new file mode 100644 index 00000000..adccf47b --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/.stylelintrc.json @@ -0,0 +1,11 @@ +{ + "extends": ["stylelint-config-standard"], + "rules": { + "declaration-property-value-allowed-list": { + "/color/": ["/^var\\(--/", "transparent"] + }, + "unit-disallowed-list": ["px"], + "selector-class-pattern": "^[a-zA-Z\\-]+$" + }, + "ignoreFiles": ["**/*.min.css"] +} diff --git a/notifier/vendor/golang.org/x/telemetry/CONTRIBUTING.md b/notifier/vendor/golang.org/x/telemetry/CONTRIBUTING.md new file mode 100644 index 00000000..e913373f --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these +five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the +[golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead +of the issue tracker. The gophers there will answer or ask you to file an issue +if you've tripped over a bug. + +## Contributing code + +Please read the +[Contribution Guidelines](https://golang.org/doc/contribute.html) before sending +patches. + +Unless otherwise noted, the Go source files are distributed under the BSD-style +license found in the LICENSE file. diff --git a/notifier/vendor/golang.org/x/exp/LICENSE b/notifier/vendor/golang.org/x/telemetry/LICENSE similarity index 100% rename from notifier/vendor/golang.org/x/exp/LICENSE rename to notifier/vendor/golang.org/x/telemetry/LICENSE diff --git a/notifier/vendor/golang.org/x/exp/PATENTS b/notifier/vendor/golang.org/x/telemetry/PATENTS similarity index 100% rename from notifier/vendor/golang.org/x/exp/PATENTS rename to notifier/vendor/golang.org/x/telemetry/PATENTS diff --git a/notifier/vendor/golang.org/x/telemetry/README.md b/notifier/vendor/golang.org/x/telemetry/README.md new file mode 100644 index 00000000..81a15749 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/README.md @@ -0,0 +1,62 @@ +# Go Telemetry + +This repository holds the Go Telemetry server code and libraries, used for +hosting [telemetry.go.dev](https://telemetry.go.dev) and instrumenting Go +toolchain programs with opt-in telemetry. + +**Warning**: this repository is intended for use only in tools maintained by +the Go team, including tools in the Go distribution and auxiliary tools like +[gopls](https://pkg.go.dev/golang.org/x/tools/gopls) or +[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck). There are +no compatibility guarantees for any of the packages here: public APIs will +change in breaking ways as the telemetry integration is refined. + +## Notable Packages + +- The [x/telemetry/counter](https://pkg.go.dev/golang.org/x/telemetry/counter) + package provides a library for instrumenting programs with counters and stack + reports. +- The [x/telemetry/upload](https://pkg.go.dev/golang.org/x/telemetry/upload) + package provides a hook for Go toolchain programs to upload telemetry data, + if the user has opted in to telemetry uploading. +- The [x/telemetry/cmd/gotelemetry](https://pkg.go.dev/pkg/golang.org/x/telemetry/cmd/gotelemetry) + command is used for managing telemetry data and configuration. +- The [x/telemetry/config](https://pkg.go.dev/pkg/golang.org/x/telemetry/config) + package defines the subset of telemetry data that has been approved for + uploading by the telemetry proposal process. +- The [x/telemetry/godev](https://pkg.go.dev/pkg/golang.org/x/telemetry/godev) directory defines + the services running at [telemetry.go.dev](https://telemetry.go.dev). + +## Contributing + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/telemetry. + +The main issue tracker for the telemetry repository is located at +https://go.dev/issues. Prefix your issue with "x/telemetry:" in +the subject line, so it is easy to find. + +### Linting & Formatting + +This repository uses [eslint](https://eslint.org/) to format TS files, +[stylelint](https://stylelint.io/) to format CSS files, and +[prettier](https://prettier.io/) to format TS, CSS, Markdown, and YAML files. + +See the style guides: + +- [TypeScript](https://google.github.io/styleguide/tsguide.html) +- [CSS](https://go.dev/wiki/CSSStyleGuide) + +It is encouraged that all TS and CSS code be run through formatters before +submitting a change. However, it is not a strict requirement enforced by CI. + +### Installing npm Dependencies: + +1. Install [docker](https://docs.docker.com/get-docker/) +2. Run `./npm install` + +### Run ESLint, Stylelint, & Prettier + + ./npm run all diff --git a/notifier/vendor/golang.org/x/telemetry/counter/counter.go b/notifier/vendor/golang.org/x/telemetry/counter/counter.go new file mode 100644 index 00000000..fe2d0f69 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/counter/counter.go @@ -0,0 +1,146 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +// The implementation of this package and tests are located in +// internal/counter, which can be shared with the upload package. +// TODO(hyangah): use of type aliases prevents nice documentation +// rendering in go doc or pkgsite. Fix this either by avoiding +// type aliasing or restructuring the internal/counter package. +import ( + "flag" + "path" + "runtime/debug" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// Inc increments the counter with the given name. +func Inc(name string) { + New(name).Inc() +} + +// Add adds n to the counter with the given name. +func Add(name string, n int64) { + New(name).Add(n) +} + +// New returns a counter with the given name. +// New can be called in global initializers and will be compiled down to +// linker-initialized data. That is, calling New to initialize a global +// has no cost at program startup. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func New(name string) *Counter { + // Note: not calling DefaultFile.New in order to keep this + // function something the compiler can inline and convert + // into static data initializations, with no init-time footprint. + // TODO(hyangah): is it trivial enough for the compiler to inline? + return counter.New(name) +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter = counter.Counter + +// A StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter = counter.StackCounter + +// NewStack returns a new stack counter with the given name and depth. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func NewStack(name string, depth int) *StackCounter { + return counter.NewStack(name, depth) +} + +// Open prepares telemetry counters for recording to the file system. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Open should only be called from short-lived processes such as command line +// tools. If your process is long-running, use [OpenAndRotate]. +func Open() { + counter.Open(false) +} + +// OpenAndRotate is like [Open], but also schedules a rotation of the counter +// file when it expires. +// +// See golang/go#68497 for background on why [OpenAndRotate] is a separate API. +// +// TODO(rfindley): refactor Open and OpenAndRotate for Go 1.24. +func OpenAndRotate() { + counter.Open(true) +} + +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open(false) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +// +// For instance, CountFlags("gopls/flag:", *flag.CommandLine) +func CountFlags(prefix string, fs flag.FlagSet) { + fs.Visit(func(f *flag.Flag) { + New(prefix + f.Name).Inc() + }) +} + +// CountCommandLineFlags creates a counter for every flag +// that is set in the default flag.CommandLine FlagSet using +// the counter name binaryName+"/flag:"+flagName where +// binaryName is the base name of the Path embedded in the +// binary's build info. If the binary does not have embedded build +// info, the "flag:"+flagName counter will be incremented. +// +// CountCommandLineFlags must be called after flags are parsed +// with flag.Parse. +// +// For instance, if the -S flag is passed to cmd/compile and +// CountCommandLineFlags is called after flags are parsed, +// the "compile/flag:S" counter will be incremented. +func CountCommandLineFlags() { + prefix := "flag:" + if buildInfo, ok := debug.ReadBuildInfo(); ok && buildInfo.Path != "" { + prefix = path.Base(buildInfo.Path) + "/" + prefix + } + CountFlags(prefix, *flag.CommandLine) +} diff --git a/notifier/vendor/golang.org/x/telemetry/counter/doc.go b/notifier/vendor/golang.org/x/telemetry/counter/doc.go new file mode 100644 index 00000000..639e9ea3 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/counter/doc.go @@ -0,0 +1,58 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package counter implements a simple counter system for collecting +// totally public telemetry data. +// +// There are two kinds of counters, basic counters and stack counters. +// Basic counters are created by [New]. +// Stack counters are created by [NewStack]. +// Both are incremented by calling Inc(). +// +// Basic counters are very cheap. Stack counters are more expensive, as they +// require parsing the stack. (Stack counters are implemented as basic counters +// whose names are the concatenation of the name and the stack trace. There is +// an upper limit on the size of this name, about 4K bytes. If the name is too +// long the stack will be truncated and "truncated" appended.) +// +// When counter files expire they are turned into reports by the upload +// package. The first time any counter file is created for a user, a random day +// of the week is selected on which counter files will expire. For the first +// week, that day is more than 7 days (but not more than two weeks) in the +// future. After that the counter files expire weekly on the same day of the +// week. +// +// # Counter Naming +// +// Counter names passed to [New] and [NewStack] should follow these +// conventions: +// +// - Names cannot contain whitespace or newlines. +// +// - Names must be valid unicode, with no unprintable characters. +// +// - Names may contain at most one ':'. In the counter "foo:bar", we refer to +// "foo" as the "chart name" and "bar" as the "bucket name". +// +// - The '/' character should partition counter names into a hierarchy. The +// root of this hierarchy should identify the logical entity that "owns" +// the counter. This could be an application, such as "gopls" in the case +// of "gopls/client:vscode", or a shared library, such as "crash" in the +// case of the "crash/crash" counter owned by the crashmonitor library. If +// the entity name itself contains a '/', that's ok: "cmd/go/flag" is fine. +// +// - Words should be '-' separated, as in "gopls/completion/errors-latency" +// +// - Histograms should use bucket names identifying upper bounds with '<'. +// For example given two counters "gopls/completion/latency:<50ms" and +// "gopls/completion/latency:<100ms", the "<100ms" bucket counts events +// with latency in the half-open interval [50ms, 100ms). +// +// # Debugging +// +// The GODEBUG environment variable can enable printing of additional debug +// information for counters. Adding GODEBUG=countertrace=1 to the environment +// of a process using counters causes the x/telemetry/counter package to log +// counter information to stderr. +package counter diff --git a/notifier/vendor/golang.org/x/telemetry/dir.go b/notifier/vendor/golang.org/x/telemetry/dir.go new file mode 100644 index 00000000..5931669e --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/dir.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Dir returns the telemetry directory. +func Dir() string { + return telemetry.Default.Dir() +} diff --git a/notifier/vendor/golang.org/x/telemetry/doc.go b/notifier/vendor/golang.org/x/telemetry/doc.go new file mode 100644 index 00000000..073f40d2 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/doc.go @@ -0,0 +1 @@ +package telemetry diff --git a/notifier/vendor/golang.org/x/telemetry/internal/config/config.go b/notifier/vendor/golang.org/x/telemetry/internal/config/config.go new file mode 100644 index 00000000..533a889c --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/config/config.go @@ -0,0 +1,140 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package config provides methods for loading and querying a +// telemetry upload config file. +package config + +import ( + "encoding/json" + "os" + "strings" + + "golang.org/x/telemetry/internal/telemetry" +) + +// Config is a wrapper around telemetry.UploadConfig that provides some +// convenience methods for checking the contents of a report. +type Config struct { + *telemetry.UploadConfig + program map[string]bool + goos map[string]bool + goarch map[string]bool + goversion map[string]bool + pgversion map[pgkey]bool + pgcounter map[pgkey]bool + pgcounterprefix map[pgkey]bool + pgstack map[pgkey]bool + rate map[pgkey]float64 +} + +type pgkey struct { + program, key string +} + +func ReadConfig(file string) (*Config, error) { + data, err := os.ReadFile(file) + if err != nil { + return nil, err + } + var cfg telemetry.UploadConfig + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + return NewConfig(&cfg), nil +} + +func NewConfig(cfg *telemetry.UploadConfig) *Config { + ucfg := Config{UploadConfig: cfg} + ucfg.goos = set(ucfg.GOOS) + ucfg.goarch = set(ucfg.GOARCH) + ucfg.goversion = set(ucfg.GoVersion) + ucfg.program = make(map[string]bool, len(ucfg.Programs)) + ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.rate = make(map[pgkey]float64) + for _, p := range ucfg.Programs { + ucfg.program[p.Name] = true + for _, v := range p.Versions { + ucfg.pgversion[pgkey{p.Name, v}] = true + } + for _, c := range p.Counters { + for _, e := range Expand(c.Name) { + ucfg.pgcounter[pgkey{p.Name, e}] = true + ucfg.rate[pgkey{p.Name, e}] = c.Rate + } + prefix, _, found := strings.Cut(c.Name, ":") + if found { + ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true + } + } + for _, s := range p.Stacks { + ucfg.pgstack[pgkey{p.Name, s.Name}] = true + ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate + } + } + return &ucfg +} + +func (r *Config) HasProgram(s string) bool { + return r.program[s] +} + +func (r *Config) HasGOOS(s string) bool { + return r.goos[s] +} + +func (r *Config) HasGOARCH(s string) bool { + return r.goarch[s] +} + +func (r *Config) HasGoVersion(s string) bool { + return r.goversion[s] +} + +func (r *Config) HasVersion(program, version string) bool { + return r.pgversion[pgkey{program, version}] +} + +func (r *Config) HasCounter(program, counter string) bool { + return r.pgcounter[pgkey{program, counter}] +} + +func (r *Config) HasCounterPrefix(program, prefix string) bool { + return r.pgcounterprefix[pgkey{program, prefix}] +} + +func (r *Config) HasStack(program, stack string) bool { + return r.pgstack[pgkey{program, stack}] +} + +func (r *Config) Rate(program, name string) float64 { + return r.rate[pgkey{program, name}] +} + +func set(slice []string) map[string]bool { + s := make(map[string]bool, len(slice)) + for _, v := range slice { + s[v] = true + } + return s +} + +// Expand takes a counter defined with buckets and expands it into distinct +// strings for each bucket. +func Expand(counter string) []string { + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { + buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",") + for _, b := range buckets { + counters = append(counters, prefix+b) + } + } else { + counters = append(counters, prefix) + } + return counters +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/configstore/download.go b/notifier/vendor/golang.org/x/telemetry/internal/configstore/download.go new file mode 100644 index 00000000..e60ab7e9 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/configstore/download.go @@ -0,0 +1,86 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package configstore abstracts interaction with the telemetry config server. +// Telemetry config (golang.org/x/telemetry/config) is distributed as a go +// module containing go.mod and config.json. Programs that upload collected +// counters download the latest config using `go mod download`. This provides +// verification of downloaded configuration and cacheability. +package configstore + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync/atomic" + + "golang.org/x/telemetry/internal/telemetry" +) + +const ( + ModulePath = "golang.org/x/telemetry/config" + configFileName = "config.json" +) + +// needNoConsole is used on windows to set the windows.CREATE_NO_WINDOW +// creation flag. +var needNoConsole = func(cmd *exec.Cmd) {} + +var downloads int64 + +// Downloads reports, for testing purposes, the number of times [Download] has +// been called. +func Downloads() int64 { + return atomic.LoadInt64(&downloads) +} + +// Download fetches the requested telemetry UploadConfig using "go mod +// download". If envOverlay is provided, it is appended to the environment used +// for invoking the go command. +// +// The second result is the canonical version of the requested configuration. +func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) { + atomic.AddInt64(&downloads, 1) + + if version == "" { + version = "latest" + } + modVer := ModulePath + "@" + version + var stdout, stderr bytes.Buffer + cmd := exec.Command("go", "mod", "download", "-json", modVer) + needNoConsole(cmd) + cmd.Env = append(os.Environ(), envOverlay...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + var info struct { + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err == nil && info.Error != "" { + return nil, "", fmt.Errorf("failed to download config module: %v", info.Error) + } + return nil, "", fmt.Errorf("failed to download config module: %w\n%s", err, &stderr) + } + + var info struct { + Dir string + Version string + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err != nil || info.Dir == "" { + return nil, "", fmt.Errorf("failed to download config module (invalid JSON): %w", err) + } + data, err := os.ReadFile(filepath.Join(info.Dir, configFileName)) + if err != nil { + return nil, "", fmt.Errorf("invalid config module: %w", err) + } + cfg := new(telemetry.UploadConfig) + if err := json.Unmarshal(data, cfg); err != nil { + return nil, "", fmt.Errorf("invalid config: %w", err) + } + return cfg, info.Version, nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go b/notifier/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go new file mode 100644 index 00000000..1368de19 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package configstore + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + needNoConsole = needNoConsoleWindows +} + +func needNoConsoleWindows(cmd *exec.Cmd) { + // The uploader main process is likely a daemonized process with no console. + // (see x/telemetry/start_windows.go) The console creation behavior when + // a parent is a console process without console is not clearly documented + // but empirically we observed the new console is created and attached to the + // subprocess in the default setup. + // + // Ensure no new console is attached to the subprocess by setting CREATE_NO_WINDOW. + // https://learn.microsoft.com/en-us/windows/console/creation-of-a-console + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.CREATE_NO_WINDOW, + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/counter/counter.go b/notifier/vendor/golang.org/x/telemetry/internal/counter/counter.go new file mode 100644 index 00000000..c08115e5 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/counter/counter.go @@ -0,0 +1,401 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal/counter implements the internals of the public counter package. +// In addition to the public API, this package also includes APIs to parse and +// manage the counter files, needed by the upload package. +package counter + +import ( + "fmt" + "os" + "runtime" + "strings" + "sync/atomic" +) + +var ( + // Note: not using internal/godebug, so that internal/godebug can use + // internal/counter. + debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") + CrashOnBugs = false // for testing; if set, exit on fatal log messages +) + +// debugPrintf formats a debug message if GODEBUG=countertrace=1. +func debugPrintf(format string, args ...any) { + if debugCounter { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter: "+format, args...) + } +} + +// debugFatalf logs a fatal error if GODEBUG=countertrace=1. +func debugFatalf(format string, args ...any) { + if debugCounter || CrashOnBugs { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter bug: "+format, args...) + os.Exit(1) + } +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter struct { + name string + file *file + + next atomic.Pointer[Counter] + state counterState + ptr counterPtr +} + +func (c *Counter) Name() string { + return c.name +} + +type counterPtr struct { + m *mappedFile + count *atomic.Uint64 +} + +type counterState struct { + bits atomic.Uint64 +} + +func (s *counterState) load() counterStateBits { + return counterStateBits(s.bits.Load()) +} + +func (s *counterState) update(old *counterStateBits, new counterStateBits) bool { + if s.bits.CompareAndSwap(uint64(*old), uint64(new)) { + *old = new + return true + } + return false +} + +type counterStateBits uint64 + +const ( + stateReaders counterStateBits = 1<<30 - 1 + stateLocked counterStateBits = stateReaders + stateHavePtr counterStateBits = 1 << 30 + stateExtraShift = 31 + stateExtra counterStateBits = 1<<64 - 1<> stateExtraShift } + +func (b counterStateBits) incReader() counterStateBits { return b + 1 } +func (b counterStateBits) decReader() counterStateBits { return b - 1 } +func (b counterStateBits) setLocked() counterStateBits { return b | stateLocked } +func (b counterStateBits) clearLocked() counterStateBits { return b &^ stateLocked } +func (b counterStateBits) setHavePtr() counterStateBits { return b | stateHavePtr } +func (b counterStateBits) clearHavePtr() counterStateBits { return b &^ stateHavePtr } +func (b counterStateBits) clearExtra() counterStateBits { return b &^ stateExtra } +func (b counterStateBits) addExtra(n uint64) counterStateBits { + const maxExtra = uint64(stateExtra) >> stateExtraShift // 0x1ffffffff + x := b.extra() + if x+n < x || x+n > maxExtra { + x = maxExtra + } else { + x += n + } + return b.clearExtra() | counterStateBits(x)< count=%d\n", c.name, extra, sum) + } + + // Took care of refreshing ptr and flushing extra. + // Now we can release the lock, unless of course + // another goroutine cleared havePtr or added to extra, + // in which case we go around again. + if !c.state.update(&state, state.clearLocked()) { + continue + } + debugPrintf("releaseLock %s: unlocked\n", c.name) + return + } +} + +// add wraps the atomic.Uint64.Add operation to handle integer overflow. +func (c *Counter) add(n uint64) uint64 { + count := c.ptr.count + for { + old := count.Load() + sum := old + n + if sum < old { + sum = ^uint64(0) + } + if count.CompareAndSwap(old, sum) { + runtime.KeepAlive(c.ptr.m) + return sum + } + } +} + +func (c *Counter) invalidate() { + for { + state := c.state.load() + if !state.havePtr() { + debugPrintf("invalidate %s: no ptr\n", c.name) + return + } + if c.state.update(&state, state.clearHavePtr()) { + debugPrintf("invalidate %s: cleared havePtr\n", c.name) + return + } + } +} + +func (c *Counter) refresh() { + for { + state := c.state.load() + if state.havePtr() || state.readers() > 0 || state.extra() == 0 { + debugPrintf("refresh %s: havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + return + } + if c.state.update(&state, state.setLocked()) { + debugPrintf("refresh %s: locked havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + c.releaseLock(state) + return + } + } +} + +// Read reads the given counter. +// This is the implementation of x/telemetry/counter/countertest.ReadCounter. +func Read(c *Counter) (uint64, error) { + if c.file.current.Load() == nil { + return c.state.load().extra(), nil + } + pf, err := readFile(c.file) + if err != nil { + return 0, err + } + v, ok := pf.Count[DecodeStack(c.Name())] + if !ok { + return v, fmt.Errorf("not found:%q", DecodeStack(c.Name())) + } + return v, nil +} + +func readFile(f *file) (*File, error) { + if f == nil { + debugPrintf("No file") + return nil, fmt.Errorf("counter is not initialized - was Open called?") + } + + // Note: don't call f.rotate here as this will enqueue a follow-up rotation. + f.rotate1() + + if f.err != nil { + return nil, fmt.Errorf("failed to rotate mapped file - %v", f.err) + } + current := f.current.Load() + if current == nil { + return nil, fmt.Errorf("counter has no mapped file") + } + name := current.f.Name() + data, err := ReadMapped(name) + if err != nil { + return nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, fmt.Errorf("failed to parse: %v", err) + } + return pf, nil +} + +// ReadFile reads the counters and stack counters from the given file. +// This is the implementation of x/telemetry/counter/countertest.ReadFile. +func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) { + // TODO: Document the format of the stackCounters names. + + data, err := ReadMapped(name) + if err != nil { + return nil, nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse: %v", err) + } + counters = make(map[string]uint64) + stackCounters = make(map[string]uint64) + for k, v := range pf.Count { + if IsStackCounter(k) { + stackCounters[DecodeStack(k)] = v + } else { + counters[k] = v + } + } + return counters, stackCounters, nil +} + +// ReadMapped reads the contents of the given file by memory mapping. +// +// This avoids file synchronization issues. +func ReadMapped(name string) ([]byte, error) { + f, err := os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + mapping, err := memmap(f) + if err != nil { + return nil, err + } + data := make([]byte, fi.Size()) + copy(data, mapping.Data) + munmap(mapping) + return data, nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/counter/file.go b/notifier/vendor/golang.org/x/telemetry/internal/counter/file.go new file mode 100644 index 00000000..872a6f6a --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -0,0 +1,814 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "errors" + "fmt" + "math/rand" + "os" + "path" + "path/filepath" + "runtime" + "runtime/debug" + "sync" + "sync/atomic" + "time" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" + "golang.org/x/telemetry/internal/telemetry" +) + +// A file is a counter file. +type file struct { + // Linked list of all known counters. + // (Linked list insertion is easy to make lock-free, + // and we don't want the initial counters incremented + // by a program to cause significant contention.) + counters atomic.Pointer[Counter] // head of list + end Counter // list ends at &end instead of nil + + mu sync.Mutex + buildInfo *debug.BuildInfo + timeBegin, timeEnd time.Time + err error + // current holds the current file mapping, which may change when the file is + // rotated or extended. + // + // current may be read without holding mu, but may be nil. + // + // The cleanup logic for file mappings is complicated, because invalidating + // counter pointers is reentrant: [file.invalidateCounters] may call + // [file.lookup], which acquires mu. Therefore, writing current must be done + // as follows: + // 1. record the previous value of current + // 2. Store a new value in current + // 3. unlock mu + // 4. call invalidateCounters + // 5. close the previous mapped value from (1) + // TODO(rfindley): simplify + current atomic.Pointer[mappedFile] +} + +var defaultFile file + +// register ensures that the counter c is registered with the file. +func (f *file) register(c *Counter) { + debugPrintf("register %s %p\n", c.Name(), c) + + // If counter is not registered with file, register it. + // Doing this lazily avoids init-time work + // as well as any execution cost at all for counters + // that are not used in a given program. + wroteNext := false + for wroteNext || c.next.Load() == nil { + head := f.counters.Load() + next := head + if next == nil { + next = &f.end + } + debugPrintf("register %s next %p\n", c.Name(), next) + if !wroteNext { + if !c.next.CompareAndSwap(nil, next) { + debugPrintf("register %s cas failed %p\n", c.Name(), c.next.Load()) + continue + } + wroteNext = true + } else { + c.next.Store(next) + } + if f.counters.CompareAndSwap(head, c) { + debugPrintf("registered %s %p\n", c.Name(), f.counters.Load()) + return + } + debugPrintf("register %s cas2 failed %p %p\n", c.Name(), f.counters.Load(), head) + } +} + +// invalidateCounters marks as invalid all the pointers +// held by f's counters and then refreshes them. +// +// invalidateCounters cannot be called while holding f.mu, +// because a counter refresh may call f.lookup. +func (f *file) invalidateCounters() { + // Mark every counter as needing to refresh its count pointer. + if head := f.counters.Load(); head != nil { + for c := head; c != &f.end; c = c.next.Load() { + c.invalidate() + } + for c := head; c != &f.end; c = c.next.Load() { + c.refresh() + } + } +} + +// lookup looks up the counter with the given name in the file, +// allocating it if needed, and returns a pointer to the atomic.Uint64 +// containing the counter data. +// If the file has not been opened yet, lookup returns nil. +func (f *file) lookup(name string) counterPtr { + current := f.current.Load() + if current == nil { + debugPrintf("lookup %s - no mapped file\n", name) + return counterPtr{} + } + ptr := f.newCounter(name) + if ptr == nil { + return counterPtr{} + } + return counterPtr{current, ptr} +} + +// ErrDisabled is the error returned when telemetry is disabled. +var ErrDisabled = errors.New("counter: disabled as Go telemetry is off") + +var ( + errNoBuildInfo = errors.New("counter: missing build info") + errCorrupt = errors.New("counter: corrupt counter file") +) + +// weekEnd returns the day of the week on which uploads occur (and therefore +// counters expire). +// +// Reads the weekends file, creating one if none exists. +func weekEnd() (time.Weekday, error) { + // If there is no 'weekends' file create it and initialize it + // to a random day of the week. There is a short interval for + // a race. + weekends := filepath.Join(telemetry.Default.LocalDir(), "weekends") + day := fmt.Sprintf("%d\n", rand.Intn(7)) + if _, err := os.ReadFile(weekends); err != nil { + if err := os.MkdirAll(telemetry.Default.LocalDir(), 0777); err != nil { + debugPrintf("%v: could not create telemetry.LocalDir %s", err, telemetry.Default.LocalDir()) + return 0, err + } + if err = os.WriteFile(weekends, []byte(day), 0666); err != nil { + return 0, err + } + } + + // race is over, read the file + buf, err := os.ReadFile(weekends) + // There is no reasonable way of recovering from errors + // so we just fail + if err != nil { + return 0, err + } + buf = bytes.TrimSpace(buf) + if len(buf) == 0 { + return 0, fmt.Errorf("empty weekends file") + } + weekend := time.Weekday(buf[0] - '0') // 0 is Sunday + // paranoia to make sure the value is legal + weekend %= 7 + if weekend < 0 { + weekend += 7 + } + return weekend, nil +} + +// rotate checks to see whether the file f needs to be rotated, +// meaning to start a new counter file with a different date in the name. +// rotate is also used to open the file initially, meaning f.current can be nil. +// In general rotate should be called just once for each file. +// rotate will arrange a timer to call itself again when necessary. +func (f *file) rotate() { + expiry := f.rotate1() + if !expiry.IsZero() { + delay := time.Until(expiry) + // Some tests set CounterTime to a time in the past, causing delay to be + // negative. Avoid infinite loops by delaying at least a short interval. + // + // TODO(rfindley): instead, just also mock AfterFunc. + const minDelay = 1 * time.Minute + if delay < minDelay { + delay = minDelay + } + // TODO(rsc): Does this do the right thing for laptops closing? + time.AfterFunc(delay, f.rotate) + } +} + +func nop() {} + +// CounterTime returns the current UTC time. +// Mutable for testing. +var CounterTime = func() time.Time { + return time.Now().UTC() +} + +// counterSpan returns the current time span for a counter file, as determined +// by [CounterTime] and the [weekEnd]. +func counterSpan() (begin, end time.Time, _ error) { + year, month, day := CounterTime().Date() + begin = time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + // files always begin today, but expire on the next day of the week + // from the 'weekends' file. + weekend, err := weekEnd() + if err != nil { + return time.Time{}, time.Time{}, err + } + incr := int(weekend - begin.Weekday()) + if incr <= 0 { + incr += 7 // ensure that end is later than begin + } + end = time.Date(year, month, day+incr, 0, 0, 0, 0, time.UTC) + return begin, end, nil +} + +// rotate1 rotates the current counter file, returning its expiry, or the zero +// time if rotation failed. +func (f *file) rotate1() time.Time { + // Cleanup must be performed while unlocked, since invalidateCounters may + // involve calls to f.lookup. + var previous *mappedFile // read below while holding the f.mu. + defer func() { + // Counters must be invalidated whenever the mapped file changes. + if next := f.current.Load(); next != previous { + f.invalidateCounters() + // Ensure that the previous counter mapped file is closed. + if previous != nil { + previous.close() // safe to call multiple times + } + } + }() + + f.mu.Lock() + defer f.mu.Unlock() + + previous = f.current.Load() + + if f.err != nil { + return time.Time{} // already in failed state; nothing to do + } + + fail := func(err error) { + debugPrintf("rotate: %v", err) + f.err = err + f.current.Store(nil) + } + + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // TODO(rfindley): do we ever want to make ErrDisabled recoverable? + // Specifically, if f.err is ErrDisabled, should we check again during when + // rotating? + fail(ErrDisabled) + return time.Time{} + } + + if f.buildInfo == nil { + bi, ok := debug.ReadBuildInfo() + if !ok { + fail(errNoBuildInfo) + return time.Time{} + } + f.buildInfo = bi + } + + begin, end, err := counterSpan() + if err != nil { + fail(err) + return time.Time{} + } + if f.timeBegin.Equal(begin) && f.timeEnd.Equal(end) { + return f.timeEnd // nothing to do + } + f.timeBegin, f.timeEnd = begin, end + + goVers, progPath, progVers := telemetry.ProgramInfo(f.buildInfo) + meta := fmt.Sprintf("TimeBegin: %s\nTimeEnd: %s\nProgram: %s\nVersion: %s\nGoVersion: %s\nGOOS: %s\nGOARCH: %s\n\n", + f.timeBegin.Format(time.RFC3339), f.timeEnd.Format(time.RFC3339), + progPath, progVers, goVers, runtime.GOOS, runtime.GOARCH) + if len(meta) > maxMetaLen { // should be impossible for our use + fail(fmt.Errorf("metadata too long")) + return time.Time{} + } + + if progVers != "" { + progVers = "@" + progVers + } + baseName := fmt.Sprintf("%s%s-%s-%s-%s-%s.%s.count", + path.Base(progPath), + progVers, + goVers, + runtime.GOOS, + runtime.GOARCH, + f.timeBegin.Format(telemetry.DateOnly), + FileVersion, + ) + dir := telemetry.Default.LocalDir() + if err := os.MkdirAll(dir, 0777); err != nil { + fail(fmt.Errorf("making local dir: %v", err)) + return time.Time{} + } + name := filepath.Join(dir, baseName) + + m, err := openMapped(name, meta) + if err != nil { + // Mapping failed: + // If there used to be a mapped file, after cleanup + // incrementing counters will only change their internal state. + // (before cleanup the existing mapped file would be updated) + fail(fmt.Errorf("openMapped: %v", err)) + return time.Time{} + } + + debugPrintf("using %v", m.f.Name()) + f.current.Store(m) + return f.timeEnd +} + +func (f *file) newCounter(name string) *atomic.Uint64 { + v, cleanup := f.newCounter1(name) + cleanup() + return v +} + +func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { + f.mu.Lock() + defer f.mu.Unlock() + + current := f.current.Load() + if current == nil { + return nil, nop + } + debugPrintf("newCounter %s in %s\n", name, current.f.Name()) + if v, _, _, _ := current.lookup(name); v != nil { + return v, nop + } + v, newM, err := current.newCounter(name) + if err != nil { + debugPrintf("newCounter %s: %v\n", name, err) + return nil, nop + } + + cleanup = nop + if newM != nil { + f.current.Store(newM) + cleanup = func() { + f.invalidateCounters() + current.close() + } + } + return v, cleanup +} + +var ( + openOnce sync.Once + // rotating reports whether the call to Open had rotate = true. + // + // In golang/go#68497, we observed that file rotation can break runtime + // deadlock detection. To minimize the fix for 1.23, we are splitting the + // Open API into one version that rotates the counter file, and another that + // does not. The rotating variable guards against use of both APIs from the + // same process. + rotating bool +) + +// Open associates counting with the defaultFile. +// The returned function is for testing only, and should +// be called after all Inc()s are finished, but before +// any reports are generated. +// (Otherwise expired count files will not be deleted on Windows.) +func Open(rotate bool) func() { + if telemetry.DisabledOnPlatform { + return func() {} + } + close := func() {} + openOnce.Do(func() { + rotating = rotate + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. + return + } + debugPrintf("Open(%v)", rotate) + if rotate { + defaultFile.rotate() // calls rotate1 and schedules a rotation + } else { + defaultFile.rotate1() + } + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + if rotating != rotate { + panic("BUG: Open called with inconsistent values for 'rotate'") + } + return close +} + +const ( + FileVersion = "v1" + hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" + recordUnit = 32 + maxMetaLen = 512 + numHash = 512 // 2kB for hash table + maxNameLen = 4 * 1024 + limitOff = 0 + hashOff = 4 + pageSize = 16 * 1024 + minFileLen = 16 * 1024 +) + +// A mappedFile is a counter file mmapped into memory. +// +// The file layout for a mappedFile m is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, hdrLen: header, containing metadata; see [mappedHeader] +// hdrLen+limitOff, 4: uint32 allocation limit (byte offset of the end of counter records) +// hdrLen+hashOff, 4*numHash: hash table, stores uint32 heads of a linked list of records, keyed by name hash +// hdrLen+hashOff+4*numHash to limit: counter records: see record syntax below +// +// The record layout is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, 8: uint64 counter value +// 8, 12: uint32 name length +// 12, 16: uint32 offset of next record in linked list +// 16, name length: counter name +type mappedFile struct { + meta string + hdrLen uint32 + zero [4]byte + closeOnce sync.Once + f *os.File + mapping *mmap.Data +} + +// openMapped opens and memory maps a file. +// +// name is the path to the file. +// +// meta is the file metadata, which must match the metadata of the file on disk +// exactly. +// +// existing should be nil the first time this is called for a file, +// and when remapping, should be the previous mappedFile. +func openMapped(name, meta string) (_ *mappedFile, err error) { + hdr, err := mappedHeader(meta) + if err != nil { + return nil, err + } + + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + // Note: using local variable m here, not return value, + // so that return nil, err does not set m = nil and break the code in the defer. + m := &mappedFile{ + f: f, + meta: meta, + } + + defer func() { + if err != nil { + m.close() + } + }() + + info, err := f.Stat() + if err != nil { + return nil, err + } + + // Establish file header and initial data area if not already present. + if info.Size() < minFileLen { + if _, err := f.WriteAt(hdr, 0); err != nil { + return nil, err + } + // Write zeros at the end of the file to extend it to minFileLen. + if _, err := f.WriteAt(m.zero[:], int64(minFileLen-len(m.zero))); err != nil { + return nil, err + } + info, err = f.Stat() + if err != nil { + return nil, err + } + if info.Size() < minFileLen { + return nil, fmt.Errorf("counter: writing file did not extend it") + } + } + + // Map into memory. + mapping, err := memmap(f) + if err != nil { + return nil, err + } + m.mapping = mapping + if !bytes.HasPrefix(m.mapping.Data, hdr) { + // TODO(rfindley): we can and should do better here, reading the mapped + // header length and comparing headers exactly. + return nil, fmt.Errorf("counter: header mismatch") + } + m.hdrLen = uint32(len(hdr)) + + return m, nil +} + +func mappedHeader(meta string) ([]byte, error) { + if len(meta) > maxMetaLen { + return nil, fmt.Errorf("counter: metadata too large") + } + np := round(len(hdrPrefix), 4) + n := round(np+4+len(meta), 32) + hdr := make([]byte, n) + copy(hdr, hdrPrefix) + *(*uint32)(unsafe.Pointer(&hdr[np])) = uint32(n) + copy(hdr[np+4:], meta) + return hdr, nil +} + +func (m *mappedFile) place(limit uint32, name string) (start, end uint32) { + if limit == 0 { + // first record in file + limit = m.hdrLen + hashOff + 4*numHash + } + n := round(uint32(16+len(name)), recordUnit) + start = round(limit, recordUnit) // should already be rounded but just in case + // Note: Checking for crossing a page boundary would be + // start/pageSize != (start+n-1)/pageSize, + // but we are checking for reaching the page end, so no -1. + // The page end is reserved for use by extend. + // See the comment in m.extend. + if start/pageSize != (start+n)/pageSize { + // bump start to next page + start = round(limit, pageSize) + } + return start, start + n +} + +var memmap = mmap.Mmap +var munmap = mmap.Munmap + +func (m *mappedFile) close() { + m.closeOnce.Do(func() { + if m.mapping != nil { + munmap(m.mapping) + m.mapping = nil + } + if m.f != nil { + m.f.Close() // best effort + m.f = nil + } + }) +} + +// hash returns the hash code for name. +// The implementation is FNV-1a. +// This hash function is a fixed detail of the file format. +// It cannot be changed without also changing the file format version. +func hash(name string) uint32 { + const ( + offset32 = 2166136261 + prime32 = 16777619 + ) + h := uint32(offset32) + for i := 0; i < len(name); i++ { + c := name[i] + h = (h ^ uint32(c)) * prime32 + } + return (h ^ (h >> 16)) % numHash +} + +func (m *mappedFile) load32(off uint32) uint32 { + if int64(off) >= int64(len(m.mapping.Data)) { + return 0 + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).Load() +} + +func (m *mappedFile) cas32(off, old, new uint32) bool { + if int64(off) >= int64(len(m.mapping.Data)) { + panic("bad cas32") // return false would probably loop + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).CompareAndSwap(old, new) +} + +// entryAt reads a counter record at the given byte offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Uint64, ok bool) { + if off < m.hdrLen+hashOff || int64(off)+16 > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + nameLen := m.load32(off+8) & 0x00ffffff + if nameLen == 0 || int64(off)+16+int64(nameLen) > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + name = m.mapping.Data[off+16 : off+16+nameLen] + next = m.load32(off + 12) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return name, next, v, true +} + +// writeEntryAt writes a new counter record at the given offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +// +// writeEntryAt only returns false in the presence of some form of corruption: +// an offset outside the bounds of the record region in the mapped file. +func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, v *atomic.Uint64, ok bool) { + // TODO(rfindley): shouldn't this first condition be off < m.hdrLen+hashOff+4*numHash? + if off < m.hdrLen+hashOff || int64(off)+16+int64(len(name)) > int64(len(m.mapping.Data)) { + return nil, nil, false + } + copy(m.mapping.Data[off+16:], name) + atomic.StoreUint32((*uint32)(unsafe.Pointer(&m.mapping.Data[off+8])), uint32(len(name))|0xff000000) + next = (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off+12])) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return next, v, true +} + +// lookup searches the mapped file for a counter record with the given name, returning: +// - v: the mapped counter value +// - headOff: the offset of the head pointer (see [mappedFile]) +// - head: the value of the head pointer +// - ok: whether lookup succeeded +func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32, ok bool) { + h := hash(name) + headOff = m.hdrLen + hashOff + h*4 + head = m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return nil, 0, 0, false + } + if string(ename) == name { + return v, headOff, head, true + } + off = next + } + return nil, headOff, head, true +} + +// newCounter allocates and writes a new counter record with the given name. +// +// If name is already recorded in the file, newCounter returns the existing counter. +func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, err error) { + if len(name) > maxNameLen { + return nil, nil, fmt.Errorf("counter name too long") + } + orig := m + defer func() { + if m != orig { + if err != nil { + m.close() + } else { + m1 = m + } + } + }() + + v, headOff, head, ok := m.lookup(name) + for tries := 0; !ok; tries++ { + if tries >= 10 { + debugFatalf("corrupt: failed to remap after 10 tries") + return nil, nil, errCorrupt + } + // Lookup found an invalid pointer, + // perhaps because the file has grown larger than the mapping. + limit := m.load32(m.hdrLen + limitOff) + if limit, datalen := int64(limit), int64(len(m.mapping.Data)); limit <= datalen { + // Mapping doesn't need to grow, so lookup found actual corruption, + // in the form of an entry pointer that exceeds the recorded allocation + // limit. This should never happen, unless the actual file contents are + // corrupt. + debugFatalf("corrupt: limit %d is within mapping length %d", limit, datalen) + return nil, nil, errCorrupt + } + // That the recorded limit is greater than the mapped data indicates that + // an external process has extended the file. Re-map to pick up this extension. + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, nil, err + } + if limit, datalen := int64(limit), int64(len(newM.mapping.Data)); limit > datalen { + // We've re-mapped, yet limit still exceeds the data length. This + // indicates that the underlying file was somehow truncated, or the + // recorded limit is corrupt. + debugFatalf("corrupt: limit %d exceeds file size %d", limit, datalen) + return nil, nil, errCorrupt + } + // If m != orig, this is at least the second time around the loop + // trying to open the mapping. Close the previous attempt. + if m != orig { + m.close() + } + m = newM + v, headOff, head, ok = m.lookup(name) + } + if v != nil { + return v, nil, nil + } + + // Reserve space for new record. + // We are competing against other programs using the same file, + // so we use a compare-and-swap on the allocation limit in the header. + var start, end uint32 + for { + // Determine where record should end, and grow file if needed. + limit := m.load32(m.hdrLen + limitOff) + start, end = m.place(limit, name) + debugPrintf("place %s at %#x-%#x\n", name, start, end) + if int64(end) > int64(len(m.mapping.Data)) { + newM, err := m.extend(end) + if err != nil { + return nil, nil, err + } + if m != orig { + m.close() + } + m = newM + continue + } + + // Attempt to reserve that space for our record. + if m.cas32(m.hdrLen+limitOff, limit, end) { + break + } + } + + // Write record. + next, v, ok := m.writeEntryAt(start, name) + if !ok { + debugFatalf("corrupt: failed to write entry: %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) + return nil, nil, errCorrupt // more likely our math is wrong + } + + // Link record into hash chain, making sure not to introduce a duplicate. + // We know name does not appear in the chain starting at head. + for { + next.Store(head) + if m.cas32(headOff, head, start) { + return v, nil, nil + } + + // Check new elements in chain for duplicates. + old := head + head = m.load32(headOff) + for off := head; off != old; { + ename, enext, v, ok := m.entryAt(off) + if !ok { + return nil, nil, errCorrupt + } + if string(ename) == name { + next.Store(^uint32(0)) // mark ours as dead + return v, nil, nil + } + off = enext + } + } +} + +func (m *mappedFile) extend(end uint32) (*mappedFile, error) { + end = round(end, pageSize) + info, err := m.f.Stat() + if err != nil { + return nil, err + } + if info.Size() < int64(end) { + // Note: multiple processes could be calling extend at the same time, + // but this write only writes the last 4 bytes of the page. + // The last 4 bytes of the page are reserved for this purpose and hold no data. + // (In m.place, if a new record would extend to the very end of the page, + // it is placed in the next page instead.) + // So it is fine if multiple processes extend at the same time. + if _, err := m.f.WriteAt(m.zero[:], int64(end)-int64(len(m.zero))); err != nil { + return nil, err + } + } + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, err + } + if int64(len(newM.mapping.Data)) < int64(end) { + // File system or logic bug: new file is somehow not extended. + // See go.dev/issue/68311, where this appears to have been happening. + newM.close() + return nil, errCorrupt + } + return newM, err +} + +// round returns x rounded up to the next multiple of unit, +// which must be a power of two. +func round[T int | uint32](x T, unit T) T { + return (x + unit - 1) &^ (unit - 1) +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/counter/parse.go b/notifier/vendor/golang.org/x/telemetry/internal/counter/parse.go new file mode 100644 index 00000000..a42a3513 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/counter/parse.go @@ -0,0 +1,82 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "fmt" + "strings" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" +) + +type File struct { + Meta map[string]string + Count map[string]uint64 +} + +func Parse(filename string, data []byte) (*File, error) { + if !bytes.HasPrefix(data, []byte(hdrPrefix)) || len(data) < pageSize { + if len(data) < pageSize { + return nil, fmt.Errorf("%s: file too short (%d<%d)", filename, len(data), pageSize) + } + return nil, fmt.Errorf("%s: wrong hdr (not %q)", filename, hdrPrefix) + } + corrupt := func() (*File, error) { + // TODO(rfindley): return a useful error message. + return nil, fmt.Errorf("%s: corrupt counter file", filename) + } + + f := &File{ + Meta: make(map[string]string), + Count: make(map[string]uint64), + } + np := round(len(hdrPrefix), 4) + hdrLen := *(*uint32)(unsafe.Pointer(&data[np])) + if hdrLen > pageSize { + return corrupt() + } + meta := data[np+4 : hdrLen] + if i := bytes.IndexByte(meta, 0); i >= 0 { + meta = meta[:i] + } + m := &mappedFile{ + meta: string(meta), + hdrLen: hdrLen, + mapping: &mmap.Data{Data: data}, + } + + lines := strings.Split(m.meta, "\n") + for _, line := range lines { + if line == "" { + continue + } + k, v, ok := strings.Cut(line, ": ") + if !ok { + return corrupt() + } + f.Meta[k] = v + } + + for i := uint32(0); i < numHash; i++ { + headOff := hdrLen + hashOff + i*4 + head := m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return corrupt() + } + if _, ok := f.Count[string(ename)]; ok { + return corrupt() + } + ctrName := DecodeStack(string(ename)) + f.Count[ctrName] = v.Load() + off = next + } + } + return f, nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go b/notifier/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go new file mode 100644 index 00000000..3e7ffdeb --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go @@ -0,0 +1,212 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "fmt" + "runtime" + "strings" + "sync" +) + +// On the disk, and upstream, stack counters look like sets of +// regular counters with names that include newlines. + +// a StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter struct { + name string + depth int + file *file + + mu sync.Mutex + // as this is a detail of the implementation, it could be replaced + // by a more efficient mechanism + stacks []stack +} + +type stack struct { + pcs []uintptr + counter *Counter +} + +func NewStack(name string, depth int) *StackCounter { + return &StackCounter{name: name, depth: depth, file: &defaultFile} +} + +// Inc increments a stack counter. It computes the caller's stack and +// looks up the corresponding counter. It then increments that counter, +// creating it if necessary. +func (c *StackCounter) Inc() { + pcs := make([]uintptr, c.depth) + n := runtime.Callers(2, pcs) // caller of Inc + pcs = pcs[:n] + + c.mu.Lock() + defer c.mu.Unlock() + + // Existing counter? + var ctr *Counter + for _, s := range c.stacks { + if eq(s.pcs, pcs) { + if s.counter != nil { + ctr = s.counter + break + } + } + } + + if ctr == nil { + // Create new counter. + ctr = &Counter{ + name: EncodeStack(pcs, c.name), + file: c.file, + } + c.stacks = append(c.stacks, stack{pcs: pcs, counter: ctr}) + } + + ctr.Inc() +} + +// EncodeStack returns the name of the counter to +// use for the given stack of program counters. +// The name encodes the stack. +func EncodeStack(pcs []uintptr, prefix string) string { + var locs []string + lastImport := "" + frs := runtime.CallersFrames(pcs) + for { + fr, more := frs.Next() + // TODO(adonovan): this CutLast(".") operation isn't + // appropriate for generic function symbols. + path, fname := cutLastDot(fr.Function) + if path == lastImport { + path = `"` // (a ditto mark) + } else { + lastImport = path + } + var loc string + if fr.Func != nil { + // Use function-relative line numbering. + // f:+2 means two lines into function f. + // f:-1 should never happen, but be conservative. + // + // An inlined call is replaced by a NOP instruction + // with the correct pclntab information. + _, entryLine := fr.Func.FileLine(fr.Entry) + loc = fmt.Sprintf("%s.%s:%+d,+0x%x", path, fname, fr.Line-entryLine, fr.PC-fr.Entry) + } else { + // The function is non-Go code or is fully inlined: + // use absolute line number within enclosing file. + // + // For inlined calls, the PC and Entry values + // both refer to the enclosing combined function. + // For example, both these PCs are relative to "caller": + // + // callee:=1,+0x12 ('=' means inlined) + // caller:+2,+0x34 + loc = fmt.Sprintf("%s.%s:=%d,+0x%x", path, fname, fr.Line, fr.PC-fr.Entry) + } + locs = append(locs, loc) + if !more { + break + } + } + + name := prefix + "\n" + strings.Join(locs, "\n") + if len(name) > maxNameLen { + const bad = "\ntruncated\n" + name = name[:maxNameLen-len(bad)] + bad + } + return name +} + +// DecodeStack expands the (compressed) stack encoded in the counter name. +func DecodeStack(ename string) string { + if !strings.Contains(ename, "\n") { + return ename // not a stack counter + } + lines := strings.Split(ename, "\n") + var lastPath string // empty or ends with . + for i, line := range lines { + path, rest := cutLastDot(line) + if len(path) == 0 { + continue // unchanged + } + if len(path) == 1 && path[0] == '"' { + lines[i] = lastPath + rest + } else { + lastPath = path + "." + // line unchanged + } + } + return strings.Join(lines, "\n") // trailing \n? +} + +// input is . +// output is (import path, function name) +func cutLastDot(x string) (before, after string) { + i := strings.LastIndex(x, ".") + if i < 0 { + return "", x + } + return x[:i], x[i+1:] +} + +// Names reports all the counter names associated with a StackCounter. +func (c *StackCounter) Names() []string { + c.mu.Lock() + defer c.mu.Unlock() + names := make([]string, len(c.stacks)) + for i, s := range c.stacks { + names[i] = s.counter.Name() + } + return names +} + +// Counters returns the known Counters for a StackCounter. +// There may be more in the count file. +func (c *StackCounter) Counters() []*Counter { + c.mu.Lock() + defer c.mu.Unlock() + counters := make([]*Counter, len(c.stacks)) + for i, s := range c.stacks { + counters[i] = s.counter + } + return counters +} + +func eq(a, b []uintptr) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// ReadStack reads the given stack counter. +// This is the implementation of +// golang.org/x/telemetry/counter/countertest.ReadStackCounter. +func ReadStack(c *StackCounter) (map[string]uint64, error) { + ret := map[string]uint64{} + for _, ctr := range c.Counters() { + v, err := Read(ctr) + if err != nil { + return nil, err + } + ret[DecodeStack(ctr.Name())] = v + } + return ret, nil +} + +// IsStackCounter reports whether the counter name is for a stack counter. +func IsStackCounter(name string) bool { + return strings.Contains(name, "\n") +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go b/notifier/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go new file mode 100644 index 00000000..53966ad2 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go @@ -0,0 +1,336 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crashmonitor + +// This file defines a monitor that reports arbitrary Go runtime +// crashes to telemetry. + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "reflect" + "runtime/debug" + "strconv" + "strings" + + "golang.org/x/telemetry/internal/counter" +) + +// Parent sets up the parent side of the crashmonitor. It requires +// exclusive use of a writable pipe connected to the child process's stdin. +func Parent(pipe *os.File) { + writeSentinel(pipe) + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + debug.SetCrashOutput(pipe, debug.CrashOptions{}) // ignore error +} + +// Child runs the part of the crashmonitor that runs in the child process. +// It expects its stdin to be connected via a pipe to the parent which has +// run Parent. +func Child() { + // Wait for parent process's dying gasp. + // If the parent dies for any reason this read will return. + data, err := io.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("failed to read from input pipe: %v", err) + } + + // If the only line is the sentinel, it wasn't a crash. + if bytes.Count(data, []byte("\n")) < 2 { + childExitHook() + os.Exit(0) // parent exited without crash report + } + + log.Printf("parent reported crash:\n%s", data) + + // Parse the stack out of the crash report + // and record a telemetry count for it. + name, err := telemetryCounterName(data) + if err != nil { + // Keep count of how often this happens + // so that we can investigate if necessary. + incrementCounter("crash/malformed") + + // Something went wrong. + // Save the crash securely in the file system. + f, err := os.CreateTemp(os.TempDir(), "*.crash") + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(data); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + log.Printf("failed to report crash to telemetry: %v", err) + log.Fatalf("crash report saved at %s", f.Name()) + } + + incrementCounter(name) + + childExitHook() + log.Fatalf("telemetry crash recorded") +} + +// (stubbed by test) +var ( + incrementCounter = func(name string) { counter.New(name).Inc() } + childExitHook = func() {} +) + +// The sentinel function returns its address. The difference between +// this value as observed by calls in two different processes of the +// same executable tells us the relative offset of their text segments. +// +// It would be nice if SetCrashOutput took care of this as it's fiddly +// and likely to confuse every user at first. +func sentinel() uint64 { + return uint64(reflect.ValueOf(sentinel).Pointer()) +} + +func writeSentinel(out io.Writer) { + fmt.Fprintf(out, "sentinel %x\n", sentinel()) +} + +// telemetryCounterName parses a crash report produced by the Go +// runtime, extracts the stack of the first runnable goroutine, +// converts each line into telemetry form ("symbol:relative-line"), +// and returns this as the name of a counter. +func telemetryCounterName(crash []byte) (string, error) { + pcs, err := parseStackPCs(string(crash)) + if err != nil { + return "", err + } + + // Limit the number of frames we request. + pcs = pcs[:min(len(pcs), 16)] + + if len(pcs) == 0 { + // This can occur if all goroutines are idle, as when + // caught in a deadlock, or killed by an async signal + // while blocked. + // + // TODO(adonovan): consider how to report such + // situations. Reporting a goroutine in [sleep] or + // [select] state could be quite confusing without + // further information about the nature of the crash, + // as the problem is not local to the code location. + // + // For now, we keep count of this situation so that we + // can access whether it needs a more involved solution. + return "crash/no-running-goroutine", nil + } + + // This string appears at the start of all + // crashmonitor-generated counter names. + // + // It is tempting to expose this as a parameter of Start, but + // it is not without risk. What value should most programs + // provide? There's no point giving the name of the executable + // as this is already recorded by telemetry. What if the + // application runs in multiple modes? Then it might be useful + // to record the mode. The problem is that an application with + // multiple modes probably doesn't know its mode by line 1 of + // main.main: it might require flag or argument parsing, or + // even validation of an environment variable, and we really + // want to steer users aware from any logic before Start. The + // flags and arguments will be wrong in the child process, and + // every extra conditional branch creates a risk that the + // recursively executed child program will behave not like the + // monitor but like the application. If the child process + // exits before calling Start, then the parent application + // will not have a monitor, and its crash reports will be + // discarded (written in to a pipe that is never read). + // + // So for now, we use this constant string. + const prefix = "crash/crash" + return counter.EncodeStack(pcs, prefix), nil +} + +// parseStackPCs parses the parent process's program counters for the +// first running goroutine out of a GOTRACEBACK=system traceback, +// adjusting them so that they are valid for the child process's text +// segment. +// +// This function returns only program counter values, ensuring that +// there is no possibility of strings from the crash report (which may +// contain PII) leaking into the telemetry system. +func parseStackPCs(crash string) ([]uintptr, error) { + // getSymbol parses the symbol name out of a line of the form: + // SYMBOL(ARGS) + // + // Note: SYMBOL may contain parens "pkg.(*T).method". However, type + // parameters are always replaced with ..., so they cannot introduce + // more parens. e.g., "pkg.(*T[...]).method". + // + // ARGS can contain parens. We want the first paren that is not + // immediately preceded by a ".". + // + // TODO(prattmic): This is mildly complicated and is only used to find + // runtime.sigpanic, so perhaps simplify this by checking explicitly + // for sigpanic. + getSymbol := func(line string) (string, error) { + var prev rune + for i, c := range line { + if line[i] != '(' { + prev = c + continue + } + if prev == '.' { + prev = c + continue + } + return line[:i], nil + } + return "", fmt.Errorf("no symbol for stack frame: %s", line) + } + + // getPC parses the PC out of a line of the form: + // \tFILE:LINE +0xRELPC sp=... fp=... pc=... + getPC := func(line string) (uint64, error) { + _, pcstr, ok := strings.Cut(line, " pc=") // e.g. pc=0x%x + if !ok { + return 0, fmt.Errorf("no pc= for stack frame: %s", line) + } + return strconv.ParseUint(pcstr, 0, 64) // 0 => allow 0x prefix + } + + var ( + pcs []uintptr + parentSentinel uint64 + childSentinel = sentinel() + on = false // are we in the first running goroutine? + lines = strings.Split(crash, "\n") + symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. + currSymbol string + prevSymbol string // symbol of the most recent previous frame with a PC. + ) + for i := 0; i < len(lines); i++ { + line := lines[i] + + // Read sentinel value. + if parentSentinel == 0 && strings.HasPrefix(line, "sentinel ") { + _, err := fmt.Sscanf(line, "sentinel %x", &parentSentinel) + if err != nil { + return nil, fmt.Errorf("can't read sentinel line") + } + continue + } + + // Search for "goroutine GID [STATUS]" + if !on { + if strings.HasPrefix(line, "goroutine ") && + strings.Contains(line, " [running]:") { + on = true + + if parentSentinel == 0 { + return nil, fmt.Errorf("no sentinel value in crash report") + } + } + continue + } + + // A blank line marks end of a goroutine stack. + if line == "" { + break + } + + // Skip the final "created by SYMBOL in goroutine GID" part. + if strings.HasPrefix(line, "created by ") { + break + } + + // Expect a pair of lines: + // SYMBOL(ARGS) + // \tFILE:LINE +0xRELPC sp=0x%x fp=0x%x pc=0x%x + // Note: SYMBOL may contain parens "pkg.(*T).method" + // The RELPC is sometimes missing. + + if symLine { + var err error + currSymbol, err = getSymbol(line) + if err != nil { + return nil, fmt.Errorf("error extracting symbol: %v", err) + } + + symLine = false // Next line is FILE:LINE. + } else { + // Parse the PC, and correct for the parent and child's + // different mappings of the text section. + pc, err := getPC(line) + if err != nil { + // Inlined frame, perhaps; skip it. + + // Done with this frame. Next line is a new frame. + // + // Don't update prevSymbol; we only want to + // track frames with a PC. + currSymbol = "" + symLine = true + continue + } + + pc = pc - parentSentinel + childSentinel + + // If the previous frame was sigpanic, then this frame + // was a trap (e.g., SIGSEGV). + // + // Typically all middle frames are calls, and report + // the "return PC". That is, the instruction following + // the CALL where the callee will eventually return to. + // + // runtime.CallersFrames is aware of this property and + // will decrement each PC by 1 to "back up" to the + // location of the CALL, which is the actual line + // number the user expects. + // + // This does not work for traps, as a trap is not a + // call, so the reported PC is not the return PC, but + // the actual PC of the trap. + // + // runtime.Callers is aware of this and will + // intentionally increment trap PCs in order to correct + // for the decrement performed by + // runtime.CallersFrames. See runtime.tracebackPCs and + // runtume.(*unwinder).symPC. + // + // We must emulate the same behavior, otherwise we will + // report the location of the instruction immediately + // prior to the trap, which may be on a different line, + // or even a different inlined functions. + // + // TODO(prattmic): The runtime applies the same trap + // behavior for other "injected calls", see injectCall + // in runtime.(*unwinder).next. Do we want to handle + // those as well? I don't believe we'd ever see + // runtime.asyncPreempt or runtime.debugCallV2 in a + // typical crash. + if prevSymbol == "runtime.sigpanic" { + pc++ + } + + pcs = append(pcs, uintptr(pc)) + + // Done with this frame. Next line is a new frame. + prevSymbol = currSymbol + currSymbol = "" + symLine = true + } + } + return pcs, nil +} + +func min(x, y int) int { + if x < y { + return x + } else { + return y + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap.go b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap.go new file mode 100644 index 00000000..2febe3ec --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package is a lightly modified version of the mmap code +// in github.com/google/codesearch/index. + +// The mmap package provides an abstraction for memory mapping files +// on different platforms. +package mmap + +import ( + "os" +) + +// The backing file is never closed, so Data +// remains valid for the lifetime of the process. +type Data struct { + // TODO(pjw): might be better to define versions of Data + // for the 3 specializations + f *os.File + Data []byte + // Some windows magic + Windows interface{} +} + +// Mmap maps the given file into memory. +// When remapping a file, pass the most recently returned Data. +func Mmap(f *os.File) (*Data, error) { + return mmapFile(f) +} + +// Munmap unmaps the given file from memory. +func Munmap(d *Data) error { + return munmapFile(d) +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go new file mode 100644 index 00000000..610ab1a1 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go @@ -0,0 +1,25 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || wasip1 || plan9 + +package mmap + +import ( + "io" + "os" +) + +// mmapFile on other systems doesn't mmap the file. It just reads everything. +func mmapFile(f *os.File) (*Data, error) { + b, err := io.ReadAll(f) + if err != nil { + return nil, err + } + return &Data{f, b, nil}, nil +} + +func munmapFile(_ *Data) error { + return nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go new file mode 100644 index 00000000..72ad91d5 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go @@ -0,0 +1,47 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix + +package mmap + +import ( + "fmt" + "io/fs" + "os" + "syscall" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + pagesize := int64(os.Getpagesize()) + if int64(int(size+(pagesize-1))) != size+(pagesize-1) { + return nil, fmt.Errorf("%s: too large for mmap", f.Name()) + } + n := int(size) + if n == 0 { + return &Data{f, nil, nil}, nil + } + mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size + data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} + } + return &Data{f, data[:n], nil}, nil +} + +func munmapFile(d *Data) error { + if len(d.Data) == 0 { + return nil + } + err := syscall.Munmap(d.Data) + if err != nil { + return &fs.PathError{Op: "munmap", Path: d.f.Name(), Err: err} + } + return nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go new file mode 100644 index 00000000..2e8dfbea --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go @@ -0,0 +1,52 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mmap + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + if size == 0 { + return &Data{f, nil, nil}, nil + } + // set the min and max sizes to zero to map the whole file, as described in + // https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object#file-mapping-size + h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, syscall.PAGE_READWRITE, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) + } + // the mapping extends from zero to the end of the file mapping + // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile + addr, err := windows.MapViewOfFile(h, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, 0) + if err != nil { + return nil, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) + } + // Note: previously, we called windows.VirtualQuery here to get the exact + // size of the memory mapped region, but VirtualQuery reported sizes smaller + // than the actual file size (hypothesis: VirtualQuery only reports pages in + // a certain state, and newly written pages may not be counted). + return &Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil +} + +func munmapFile(d *Data) error { + err := windows.UnmapViewOfFile(uintptr(unsafe.Pointer(&d.Data[0]))) + x, ok := d.Windows.(windows.Handle) + if ok { + windows.CloseHandle(x) + } + d.f.Close() + return err +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go new file mode 100644 index 00000000..71953018 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// TODO(rfindley): replace uses of DateOnly with time.DateOnly once we no +// longer support building gopls with go 1.19. +const DateOnly = "2006-01-02" diff --git a/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dir.go b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dir.go new file mode 100644 index 00000000..0673be56 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/dir.go @@ -0,0 +1,163 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package telemetry manages the telemetry mode file. +package telemetry + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +// Default is the default directory containing Go telemetry configuration and +// data. +// +// If Default is uninitialized, Default.Mode will be "off". As a consequence, +// no data should be written to the directory, and so the path values of +// LocalDir, UploadDir, etc. must not matter. +// +// Default is a global for convenience and testing, but should not be mutated +// outside of tests. +// +// TODO(rfindley): it would be nice to completely eliminate this global state, +// or at least push it in the golang.org/x/telemetry package +var Default Dir + +// A Dir holds paths to telemetry data inside a directory. +type Dir struct { + dir, local, upload, debug, modefile string +} + +// NewDir creates a new Dir encapsulating paths in the given dir. +// +// NewDir does not create any new directories or files--it merely encapsulates +// the telemetry directory layout. +func NewDir(dir string) Dir { + return Dir{ + dir: dir, + local: filepath.Join(dir, "local"), + upload: filepath.Join(dir, "upload"), + debug: filepath.Join(dir, "debug"), + modefile: filepath.Join(dir, "mode"), + } +} + +func init() { + cfgDir, err := os.UserConfigDir() + if err != nil { + return + } + Default = NewDir(filepath.Join(cfgDir, "go", "telemetry")) +} + +func (d Dir) Dir() string { + return d.dir +} + +func (d Dir) LocalDir() string { + return d.local +} + +func (d Dir) UploadDir() string { + return d.upload +} + +func (d Dir) DebugDir() string { + return d.debug +} + +func (d Dir) ModeFile() string { + return d.modefile +} + +// SetMode updates the telemetry mode with the given mode. +// Acceptable values for mode are "on", "off", or "local". +// +// SetMode always writes the mode file, and explicitly records the date at +// which the modefile was updated. This means that calling SetMode with "on" +// effectively resets the timeout before the next telemetry report is uploaded. +func (d Dir) SetMode(mode string) error { + return d.SetModeAsOf(mode, time.Now()) +} + +// SetModeAsOf is like SetMode, but accepts an explicit time to use to +// back-date the mode state. This exists only for testing purposes. +func (d Dir) SetModeAsOf(mode string, asofTime time.Time) error { + mode = strings.TrimSpace(mode) + switch mode { + case "on", "off", "local": + default: + return fmt.Errorf("invalid telemetry mode: %q", mode) + } + if d.modefile == "" { + return fmt.Errorf("cannot determine telemetry mode file name") + } + // TODO(rfindley): why is this not 777, consistent with the use of 666 below? + if err := os.MkdirAll(filepath.Dir(d.modefile), 0755); err != nil { + return fmt.Errorf("cannot create a telemetry mode file: %w", err) + } + + asof := asofTime.UTC().Format(DateOnly) + // Defensively guarantee that we can parse the asof time. + if _, err := time.Parse(DateOnly, asof); err != nil { + return fmt.Errorf("internal error: invalid mode date %q: %v", asof, err) + } + + data := []byte(mode + " " + asof) + return os.WriteFile(d.modefile, data, 0666) +} + +// Mode returns the current telemetry mode, as well as the time that the mode +// was effective. +// +// If there is no effective time, the second result is the zero time. +// +// If Mode is "off", no data should be written to the telemetry directory, and +// the other paths values referenced by Dir should be considered undefined. +// This accounts for the case where initializing [Default] fails, and therefore +// local telemetry paths are unknown. +func (d Dir) Mode() (string, time.Time) { + if d.modefile == "" { + return "off", time.Time{} // it's likely LocalDir/UploadDir are empty too. Turn off telemetry. + } + data, err := os.ReadFile(d.modefile) + if err != nil { + return "local", time.Time{} // default + } + mode := string(data) + mode = strings.TrimSpace(mode) + + // Forward compatibility for https://go.dev/issue/63142#issuecomment-1734025130 + // + // If the modefile contains a date, return it. + if idx := strings.Index(mode, " "); idx >= 0 { + d, err := time.Parse(DateOnly, mode[idx+1:]) + if err != nil { + d = time.Time{} + } + return mode[:idx], d + } + + return mode, time.Time{} +} + +// DisabledOnPlatform indicates whether telemetry is disabled +// due to bugs in the current platform. +// +// TODO(rfindley): move to a more appropriate file. +const DisabledOnPlatform = false || + // The following platforms could potentially be supported in the future: + runtime.GOOS == "openbsd" || // #60614 + runtime.GOOS == "solaris" || // #60968 #60970 + runtime.GOOS == "android" || // #60967 + runtime.GOOS == "illumos" || // #65544 + // These platforms fundamentally can't be supported: + runtime.GOOS == "js" || // #60971 + runtime.GOOS == "wasip1" || // #60971 + runtime.GOOS == "plan9" || // https://github.com/golang/go/issues/57540#issuecomment-1470766639 + runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" // mips lacks cross-process 64-bit atomics diff --git a/notifier/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go new file mode 100644 index 00000000..5ff7d34f --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -0,0 +1,57 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "go/version" + "os" + "path/filepath" + "runtime/debug" + "strings" +) + +// IsToolchainProgram reports whether a program with the given path is a Go +// toolchain program. +func IsToolchainProgram(progPath string) bool { + return strings.HasPrefix(progPath, "cmd/") +} + +// ProgramInfo extracts the go version, program package path, and program +// version to use for counter files. +// +// For programs in the Go toolchain, the program version will be the same as +// the Go version, and will typically be of the form "go1.2.3", not a semantic +// version of the form "v1.2.3". Go versions may also include spaces and +// special characters. +func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { + goVers = info.GoVersion + if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") || !version.IsValid(goVers) { + goVers = "devel" + } + + progPath = info.Path + if progPath == "" { + progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + + // Main module version information is not populated for the cmd module, but + // we can re-use the Go version here. + if IsToolchainProgram(progPath) { + progVers = goVers + } else { + progVers = info.Main.Version + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). + progVers = "devel" + } + } + + return goVers, progPath, progVers +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/telemetry/types.go b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/types.go new file mode 100644 index 00000000..0fd61f8d --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/telemetry/types.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig struct { + GOOS []string + GOARCH []string + GoVersion []string + SampleRate float64 + Programs []*ProgramConfig +} + +type ProgramConfig struct { + // the counter names may have to be + // repeated for each program. (e.g., if the counters are in a package + // that is used in more than one program.) + Name string + Versions []string // versions present in a counterconfig + Counters []CounterConfig `json:",omitempty"` + Stacks []CounterConfig `json:",omitempty"` +} + +type CounterConfig struct { + Name string // The "collapsed" counter: :{,,...} + Rate float64 // If X <= Rate, report this counter + Depth int `json:",omitempty"` // for stack counters +} + +// A Report is the weekly aggregate of counters. +type Report struct { + Week string // End day this report covers (YYYY-MM-DD) + LastWeek string // Week field from latest previous report uploaded + X float64 // A random probability used to determine which counters are uploaded + Programs []*ProgramReport + Config string // version of UploadConfig used +} + +type ProgramReport struct { + Program string // Package path of the program. + Version string // Program version. Go version if the program is part of the go distribution. Module version, otherwise. + GoVersion string // Go version used to build the program. + GOOS string + GOARCH string + Counters map[string]int64 + Stacks map[string]int64 +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/Doc.txt b/notifier/vendor/golang.org/x/telemetry/internal/upload/Doc.txt new file mode 100644 index 00000000..45601e65 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/Doc.txt @@ -0,0 +1,45 @@ +The upload process converts count files into reports, and +uploads reports. There will be only one report, named YYYY-MM-DD.json, +for a given day. + +First phase. Look at the localdir (os.UserConfigdir()/go/telemetry/local) +and find all .count and .json files. Find the count files that are no +longer active by looking at their metadata. + +Second phase. Group the inactive count files by their expiry date, and +for each date generate the local report and the upload report. (The upload +report only contains the counters in the upload configuration.) The upload +report is saved in the local directory with a name like YYYY-MM-DD.json, if +there is no file already existing with that name. +If the local report is different, it is saved in the local directory +with a name like local.YYYY-MM-DD.json. The new upload report is +added to the list of .json files from the first phase. At this point +the count files are no longer needed and can be deleted. + +Third phase. Look at the .json files in the list from the first phase. +If the name starts with local, skip it. If there is a file with the +identical name in the upload directory, remove the one in the local directory. +Otherwise try to upload the one in the local directory, +If the upload succeeds, move the file to the uploaded directory. + + +There are various error conditions. +1. Several processes could look at localdir and see work to do. +1A. They could see different sets of expired count files for some day. + This could happen if another process is removing count files. In this + case there is already a YYYY-MM-DD.json file either in localdir + or updatedir, so the process seeing fewer count files will not generate + a report. +1B. They could see the same count files, and no report in either directory. + They will both generate (in memory) reports and check to see if there + is a YYYY-MM-DD.json file in either directory. They could both then + write two files with the same name, but different X values, but + otherwise the same contents. The X values are very close to the front + of the file. Assuming reasonable file system semantics one version of + the file will be written. To minimize this, just before writing reports + the code checks again to see if they exist. +1C. Once there is an existing well-formed file YYYY-MM-DD.json in localdir + eventually the upload will succeed, and the file will be moved to updatedir. + It is possible that other processes will not see the file in updatedir and + upload it again and also move it to uploaddir. This is harmless as all + the uploaded files are identical. diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/date.go b/notifier/vendor/golang.org/x/telemetry/internal/upload/date.go new file mode 100644 index 00000000..d6d67a16 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/date.go @@ -0,0 +1,85 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "os" + "sync" + "time" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// time and date handling + +var distantPast = 21 * 24 * time.Hour + +// reports that are too old (21 days) are not uploaded +func (u *uploader) tooOld(date string, uploadStartTime time.Time) bool { + t, err := time.Parse(telemetry.DateOnly, date) + if err != nil { + u.logger.Printf("tooOld: %v", err) + return false + } + age := uploadStartTime.Sub(t) + return age > distantPast +} + +// counterDateSpan parses the counter file named fname and returns the (begin, +// end) span recorded in its metadata, or an error if this data could not be +// extracted. +func (u *uploader) counterDateSpan(fname string) (begin, end time.Time, _ error) { + parsed, err := u.parseCountFile(fname) + if err != nil { + return time.Time{}, time.Time{}, err + } + timeBegin, ok := parsed.Meta["TimeBegin"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeBegin") + } + begin, err = time.Parse(time.RFC3339, timeBegin) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeBegin: %v", err) + } + timeEnd, ok := parsed.Meta["TimeEnd"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeEnd") + } + end, err = time.Parse(time.RFC3339, timeEnd) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeEnd: %v", err) + } + return begin, end, nil +} + +// avoid parsing count files multiple times +type parsedCache struct { + mu sync.Mutex + m map[string]*counter.File +} + +func (u *uploader) parseCountFile(fname string) (*counter.File, error) { + u.cache.mu.Lock() + defer u.cache.mu.Unlock() + if u.cache.m == nil { + u.cache.m = make(map[string]*counter.File) + } + if f, ok := u.cache.m[fname]; ok { + return f, nil + } + buf, err := os.ReadFile(fname) + if err != nil { + return nil, fmt.Errorf("parse ReadFile: %v for %s", err, fname) + } + f, err := counter.Parse(fname, buf) + if err != nil { + + return nil, fmt.Errorf("parse Parse: %v for %s", err, fname) + } + u.cache.m[fname] = f + return f, nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/findwork.go b/notifier/vendor/golang.org/x/telemetry/internal/upload/findwork.go new file mode 100644 index 00000000..2b165be3 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/findwork.go @@ -0,0 +1,102 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "os" + "path/filepath" + "strings" +) + +// files to handle +type work struct { + // absolute file names + countfiles []string // count files to process + readyfiles []string // old reports to upload + // relative names + uploaded map[string]bool // reports that have been uploaded +} + +// find all the files that look like counter files or reports +// that need to be uploaded. (There may be unexpected leftover files +// and uploading is supposed to be idempotent.) +func (u *uploader) findWork() work { + localdir, uploaddir := u.dir.LocalDir(), u.dir.UploadDir() + var ans work + fis, err := os.ReadDir(localdir) + if err != nil { + u.logger.Printf("Could not find work: failed to read local dir %s: %v", localdir, err) + return ans + } + + mode, asof := u.dir.Mode() + u.logger.Printf("Finding work: mode %s asof %s", mode, asof) + + // count files end in .v1.count + // reports end in .json. If they are not to be uploaded they + // start with local. + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".v1.count") { + fname := filepath.Join(localdir, fi.Name()) + _, expiry, err := u.counterDateSpan(fname) + switch { + case err != nil: + u.logger.Printf("Error reading expiry for count file %s: %v", fi.Name(), err) + case expiry.After(u.startTime): + u.logger.Printf("Skipping count file %s: still active", fi.Name()) + default: + u.logger.Printf("Collecting count file %s", fi.Name()) + ans.countfiles = append(ans.countfiles, fname) + } + } else if strings.HasPrefix(fi.Name(), "local.") { + // skip + } else if strings.HasSuffix(fi.Name(), ".json") && mode == "on" { + // Collect reports that are ready for upload. + reportDate := u.uploadReportDate(fi.Name()) + if !asof.IsZero() && !reportDate.IsZero() { + // If both the mode asof date and the report date are present, do the + // right thing... + // + // (see https://github.com/golang/go/issues/63142#issuecomment-1734025130) + if asof.Before(reportDate) { + // Note: since this report was created after telemetry was enabled, + // we can only assume that the process that created it checked that + // the counter data contained therein was all from after the asof + // date. + // + // TODO(rfindley): store the begin date in reports, so that we can + // verify this assumption. + u.logger.Printf("Uploadable: %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } else { + // ...otherwise fall back on the old behavior of uploading all + // unuploaded files. + // + // TODO(rfindley): invert this logic following more testing. We + // should only upload if we know both the asof date and the report + // date, and they are acceptable. + u.logger.Printf("Uploadable (missing date): %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } + } + + fis, err = os.ReadDir(uploaddir) + if err != nil { + os.MkdirAll(uploaddir, 0777) + return ans + } + // There should be only one of these per day; maybe sometime + // we'll want to clean the directory. + ans.uploaded = make(map[string]bool) + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".json") { + u.logger.Printf("Already uploaded: %s", fi.Name()) + ans.uploaded[fi.Name()] = true + } + } + return ans +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/reports.go b/notifier/vendor/golang.org/x/telemetry/internal/upload/reports.go new file mode 100644 index 00000000..34bb29d8 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/reports.go @@ -0,0 +1,344 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "crypto/rand" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/telemetry/internal/config" + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// reports generates reports from inactive count files +func (u *uploader) reports(todo *work) ([]string, error) { + if mode, _ := u.dir.Mode(); mode == "off" { + return nil, nil // no reports + } + thisInstant := u.startTime + today := thisInstant.Format(telemetry.DateOnly) + lastWeek := latestReport(todo.uploaded) + if lastWeek >= today { //should never happen + lastWeek = "" + } + u.logger.Printf("Last week: %s, today: %s", lastWeek, today) + countFiles := make(map[string][]string) // expiry date string->filenames + earliest := make(map[string]time.Time) // earliest begin time for any counter + for _, f := range todo.countfiles { + begin, end, err := u.counterDateSpan(f) + if err != nil { + // This shouldn't happen: we should have already skipped count files that + // don't contain valid start or end times. + u.logger.Printf("BUG: failed to parse expiry for collected count file: %v", err) + continue + } + + if end.Before(thisInstant) { + expiry := end.Format(dateFormat) + countFiles[expiry] = append(countFiles[expiry], f) + if earliest[expiry].IsZero() || earliest[expiry].After(begin) { + earliest[expiry] = begin + } + } + } + for expiry, files := range countFiles { + if notNeeded(expiry, *todo) { + u.logger.Printf("Files for %s not needed, deleting %v", expiry, files) + // The report already exists. + // There's another check in createReport. + u.deleteFiles(files) + continue + } + fname, err := u.createReport(earliest[expiry], expiry, files, lastWeek) + if err != nil { + u.logger.Printf("Failed to create report for %s: %v", expiry, err) + continue + } + if fname != "" { + u.logger.Printf("Ready to upload: %s", filepath.Base(fname)) + todo.readyfiles = append(todo.readyfiles, fname) + } + } + return todo.readyfiles, nil +} + +// latestReport returns the YYYY-MM-DD of the last report uploaded +// or the empty string if there are no reports. +func latestReport(uploaded map[string]bool) string { + var latest string + for name := range uploaded { + if strings.HasSuffix(name, ".json") { + if name > latest { + latest = name + } + } + } + if latest == "" { + return "" + } + // strip off the .json + return latest[:len(latest)-len(".json")] +} + +// notNeeded returns true if the report for date has already been created +func notNeeded(date string, todo work) bool { + if todo.uploaded != nil && todo.uploaded[date+".json"] { + return true + } + // maybe the report is already in todo.readyfiles + for _, f := range todo.readyfiles { + if strings.Contains(f, date) { + return true + } + } + return false +} + +func (u *uploader) deleteFiles(files []string) { + for _, f := range files { + if err := os.Remove(f); err != nil { + // this could be a race condition. + // conversely, on Windows, err may be nil and + // the file not deleted if anyone has it open. + u.logger.Printf("%v failed to remove %s", err, f) + } + } +} + +// createReport creates local and upload report files by +// combining all the count files for the expiryDate, and +// returns the upload report file's path. +// It may delete the count files once local and upload report +// files are successfully created. +func (u *uploader) createReport(start time.Time, expiryDate string, countFiles []string, lastWeek string) (string, error) { + uploadOK := true + mode, asof := u.dir.Mode() + if mode != "on" { + u.logger.Printf("No upload config or mode %q is not 'on'", mode) + uploadOK = false // no config, nothing to upload + } + if u.tooOld(expiryDate, u.startTime) { + u.logger.Printf("Expiry date %s is too old", expiryDate) + uploadOK = false + } + // If the mode is recorded with an asof date, don't upload if the report + // includes any data on or before the asof date. + if !asof.IsZero() && !asof.Before(start) { + u.logger.Printf("As-of date %s is not before start %s", asof, start) + uploadOK = false + } + // TODO(rfindley): check that all the x.Meta are consistent for GOOS, GOARCH, etc. + report := &telemetry.Report{ + Config: u.configVersion, + X: computeRandom(), // json encodes all the bits + Week: expiryDate, + LastWeek: lastWeek, + } + if report.X > u.config.SampleRate && u.config.SampleRate > 0 { + u.logger.Printf("X: %f > SampleRate:%f, not uploadable", report.X, u.config.SampleRate) + uploadOK = false + } + var succeeded bool + for _, f := range countFiles { + fok := false + x, err := u.parseCountFile(f) + if err != nil { + u.logger.Printf("Unparseable count file %s: %v", filepath.Base(f), err) + continue + } + prog := findProgReport(x.Meta, report) + for k, v := range x.Count { + if counter.IsStackCounter(k) { + // stack + prog.Stacks[k] += int64(v) + } else { + // counter + prog.Counters[k] += int64(v) + } + succeeded = true + fok = true + } + if !fok { + u.logger.Printf("no counters found in %s", f) + } + } + if !succeeded { + return "", fmt.Errorf("none of the %d count files for %s contained counters", len(countFiles), expiryDate) + } + // 1. generate the local report + localContents, err := json.MarshalIndent(report, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal report for %s: %v", expiryDate, err) + } + // check that the report can be read back + // TODO(pjw): remove for production? + var report2 telemetry.Report + if err := json.Unmarshal(localContents, &report2); err != nil { + return "", fmt.Errorf("failed to unmarshal local report for %s: %v", expiryDate, err) + } + + var uploadContents []byte + if uploadOK { + // 2. create the uploadable version + cfg := config.NewConfig(u.config) + upload := &telemetry.Report{ + Week: report.Week, + LastWeek: report.LastWeek, + X: report.X, + Config: report.Config, + } + for _, p := range report.Programs { + // does the uploadConfig want this program? + // if so, copy over the Stacks and Counters + // that the uploadConfig mentions. + if !cfg.HasGoVersion(p.GoVersion) || !cfg.HasProgram(p.Program) || !cfg.HasVersion(p.Program, p.Version) { + continue + } + x := &telemetry.ProgramReport{ + Program: p.Program, + Version: p.Version, + GOOS: p.GOOS, + GOARCH: p.GOARCH, + GoVersion: p.GoVersion, + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + upload.Programs = append(upload.Programs, x) + for k, v := range p.Counters { + if cfg.HasCounter(p.Program, k) && report.X <= cfg.Rate(p.Program, k) { + x.Counters[k] = v + } + } + // and the same for Stacks + // this can be made more efficient, when it matters + for k, v := range p.Stacks { + before, _, _ := strings.Cut(k, "\n") + if cfg.HasStack(p.Program, before) && report.X <= cfg.Rate(p.Program, before) { + x.Stacks[k] = v + } + } + } + + uploadContents, err = json.MarshalIndent(upload, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal upload report for %s: %v", expiryDate, err) + } + } + localFileName := filepath.Join(u.dir.LocalDir(), "local."+expiryDate+".json") + uploadFileName := filepath.Join(u.dir.LocalDir(), expiryDate+".json") + + /* Prepare to write files */ + // if either file exists, someone has been here ahead of us + // (there is still a race, but this check shortens the open window) + if _, err := os.Stat(localFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("local report %s already exists", localFileName) + } + if _, err := os.Stat(uploadFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("report %s already exists", uploadFileName) + } + // write the uploadable file + var errUpload, errLocal error + if uploadOK { + _, errUpload = exclusiveWrite(uploadFileName, uploadContents) + } + // write the local file + _, errLocal = exclusiveWrite(localFileName, localContents) + /* Wrote the files */ + + // even though these errors won't occur, what should happen + // if errUpload == nil and it is ok to upload, and errLocal != nil? + if errLocal != nil { + return "", fmt.Errorf("failed to write local file %s (%v)", localFileName, errLocal) + } + if errUpload != nil { + return "", fmt.Errorf("failed to write upload file %s (%v)", uploadFileName, errUpload) + } + u.logger.Printf("Created %s, deleting %d count files", filepath.Base(uploadFileName), len(countFiles)) + u.deleteFiles(countFiles) + if uploadOK { + return uploadFileName, nil + } + return "", nil +} + +// exclusiveWrite attempts to create filename exclusively, and if successful, +// writes content to the resulting file handle. +// +// It returns a boolean indicating whether the exclusive handle was acquired, +// and an error indicating whether the operation succeeded. +// If the file already exists, exclusiveWrite returns (false, nil). +func exclusiveWrite(filename string, content []byte) (_ bool, rerr error) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + if os.IsExist(err) { + return false, nil + } + return false, err + } + defer func() { + if err := f.Close(); err != nil && rerr == nil { + rerr = err + } + }() + if _, err := f.Write(content); err != nil { + return false, err + } + return true, nil +} + +// return an existing ProgremReport, or create anew +func findProgReport(meta map[string]string, report *telemetry.Report) *telemetry.ProgramReport { + for _, prog := range report.Programs { + if prog.Program == meta["Program"] && prog.Version == meta["Version"] && + prog.GoVersion == meta["GoVersion"] && prog.GOOS == meta["GOOS"] && + prog.GOARCH == meta["GOARCH"] { + return prog + } + } + prog := telemetry.ProgramReport{ + Program: meta["Program"], + Version: meta["Version"], + GoVersion: meta["GoVersion"], + GOOS: meta["GOOS"], + GOARCH: meta["GOARCH"], + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + report.Programs = append(report.Programs, &prog) + return &prog +} + +// computeRandom returns a cryptographic random float64 in the range [0, 1], +// with 52 bits of precision. +func computeRandom() float64 { + for { + b := make([]byte, 8) + _, err := rand.Read(b) + if err != nil { + panic(fmt.Sprintf("rand.Read failed: %v", err)) + } + // and turn it into a float64 + x := math.Float64frombits(binary.LittleEndian.Uint64(b)) + if math.IsNaN(x) || math.IsInf(x, 0) { + continue + } + x = math.Abs(x) + if x < 0x1p-1000 { // avoid underflow patterns + continue + } + frac, _ := math.Frexp(x) // 52 bits of randomness + return frac*2 - 1 + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/run.go b/notifier/vendor/golang.org/x/telemetry/internal/upload/run.go new file mode 100644 index 00000000..e9c8dc20 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/run.go @@ -0,0 +1,226 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "io" + "log" + "os" + "path" + "path/filepath" + "runtime/debug" + "strings" + "time" + + "golang.org/x/telemetry/internal/configstore" + "golang.org/x/telemetry/internal/telemetry" +) + +// RunConfig configures non-default behavior of a call to Run. +// +// All fields are optional, for testing or observability. +type RunConfig struct { + TelemetryDir string // if set, overrides the telemetry data directory + UploadURL string // if set, overrides the telemetry upload endpoint + LogWriter io.Writer // if set, used for detailed logging of the upload process + Env []string // if set, appended to the config download environment + StartTime time.Time // if set, overrides the upload start time +} + +// Run generates and uploads reports, as allowed by the mode file. +func Run(config RunConfig) error { + defer func() { + if err := recover(); err != nil { + log.Printf("upload recover: %v", err) + } + }() + uploader, err := newUploader(config) + if err != nil { + return err + } + defer uploader.Close() + return uploader.Run() +} + +// uploader encapsulates a single upload operation, carrying parameters and +// shared state. +type uploader struct { + // config is used to select counters to upload. + config *telemetry.UploadConfig // + configVersion string // version of the config + dir telemetry.Dir // the telemetry dir to process + + uploadServerURL string + startTime time.Time + + cache parsedCache + + logFile *os.File + logger *log.Logger +} + +// newUploader creates a new uploader to use for running the upload for the +// given config. +// +// Uploaders should only be used for one call to [uploader.Run]. +func newUploader(rcfg RunConfig) (*uploader, error) { + // Determine the upload directory. + var dir telemetry.Dir + if rcfg.TelemetryDir != "" { + dir = telemetry.NewDir(rcfg.TelemetryDir) + } else { + dir = telemetry.Default + } + + // Determine the upload URL. + uploadURL := rcfg.UploadURL + if uploadURL == "" { + uploadURL = "https://telemetry.go.dev/upload" + } + + // Determine the upload logger. + // + // This depends on the provided rcfg.LogWriter and the presence of + // dir.DebugDir, as follows: + // 1. If LogWriter is present, log to it. + // 2. If DebugDir is present, log to a file within it. + // 3. If both LogWriter and DebugDir are present, log to a multi writer. + // 4. If neither LogWriter nor DebugDir are present, log to a noop logger. + var logWriters []io.Writer + logFile, err := debugLogFile(dir.DebugDir()) + if err != nil { + logFile = nil + } + if logFile != nil { + logWriters = append(logWriters, logFile) + } + if rcfg.LogWriter != nil { + logWriters = append(logWriters, rcfg.LogWriter) + } + var logWriter io.Writer + switch len(logWriters) { + case 0: + logWriter = io.Discard + case 1: + logWriter = logWriters[0] + default: + logWriter = io.MultiWriter(logWriters...) + } + logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile) + + // Fetch the upload config, if it is not provided. + var ( + config *telemetry.UploadConfig + configVersion string + ) + + if mode, _ := dir.Mode(); mode == "on" { + // golang/go#68946: only download the upload config if it will be used. + // + // TODO(rfindley): This is a narrow change aimed at minimally fixing the + // associated bug. In the future, we should read the mode only once during + // the upload process. + config, configVersion, err = configstore.Download("latest", rcfg.Env) + if err != nil { + return nil, err + } + } else { + config = &telemetry.UploadConfig{} + configVersion = "v0.0.0-0" + } + + // Set the start time, if it is not provided. + startTime := time.Now().UTC() + if !rcfg.StartTime.IsZero() { + startTime = rcfg.StartTime + } + + return &uploader{ + config: config, + configVersion: configVersion, + dir: dir, + uploadServerURL: uploadURL, + startTime: startTime, + + logFile: logFile, + logger: logger, + }, nil +} + +// Close cleans up any resources associated with the uploader. +func (u *uploader) Close() error { + if u.logFile == nil { + return nil + } + return u.logFile.Close() +} + +// Run generates and uploads reports +func (u *uploader) Run() error { + if telemetry.DisabledOnPlatform { + return nil + } + todo := u.findWork() + ready, err := u.reports(&todo) + if err != nil { + u.logger.Printf("Error building reports: %v", err) + return fmt.Errorf("reports failed: %v", err) + } + u.logger.Printf("Uploading %d reports", len(ready)) + for _, f := range ready { + u.uploadReport(f) + } + return nil +} + +// debugLogFile arranges to write a log file in the given debug directory, if +// it exists. +func debugLogFile(debugDir string) (*os.File, error) { + fd, err := os.Stat(debugDir) + if os.IsNotExist(err) { + return nil, nil + } + if err != nil { + return nil, err + } + if !fd.IsDir() { + return nil, fmt.Errorf("debug path %q is not a directory", debugDir) + } + info, ok := debug.ReadBuildInfo() + if !ok { + return nil, fmt.Errorf("no build info") + } + year, month, day := time.Now().UTC().Date() + goVers := info.GoVersion + // E.g., goVers:"go1.22-20240109-RC01 cl/597041403 +dcbe772469 X:loopvar" + words := strings.Fields(goVers) + goVers = words[0] + progPkgPath := info.Path + if progPkgPath == "" { + progPkgPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + prog := path.Base(progPkgPath) + progVers := info.Main.Version + if progVers == "(devel)" { // avoid special characters in created file names + progVers = "devel" + } + logBase := strings.ReplaceAll( + fmt.Sprintf("%s-%s-%s-%4d%02d%02d-%d.log", prog, progVers, goVers, year, month, day, os.Getpid()), + " ", "") + fname := filepath.Join(debugDir, logBase) + if _, err := os.Stat(fname); err == nil { + // This process previously called upload.Run + return nil, nil + } + f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return nil, nil // this process previously called upload.Run + } + return nil, err + } + return f, nil +} diff --git a/notifier/vendor/golang.org/x/telemetry/internal/upload/upload.go b/notifier/vendor/golang.org/x/telemetry/internal/upload/upload.go new file mode 100644 index 00000000..419745f6 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/internal/upload/upload.go @@ -0,0 +1,117 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "bytes" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "golang.org/x/telemetry/internal/telemetry" +) + +var ( + dateRE = regexp.MustCompile(`(\d\d\d\d-\d\d-\d\d)[.]json$`) + dateFormat = telemetry.DateOnly + // TODO(rfindley): use dateFormat throughout. +) + +// uploadReportDate returns the date component of the upload file name, or "" if the +// date was unmatched. +func (u *uploader) uploadReportDate(fname string) time.Time { + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("malformed report name: missing date: %q", filepath.Base(fname)) + return time.Time{} + } + d, err := time.Parse(dateFormat, match[1]) + if err != nil { + u.logger.Printf("malformed report name: bad date: %q", filepath.Base(fname)) + return time.Time{} + } + return d +} + +func (u *uploader) uploadReport(fname string) { + thisInstant := u.startTime + // TODO(rfindley): use uploadReportDate here, once we've done a gopls release. + + // first make sure it is not in the future + today := thisInstant.Format(telemetry.DateOnly) + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("Report name %q missing date", filepath.Base(fname)) + } else if match[1] > today { + u.logger.Printf("Report date for %q is later than today (%s)", filepath.Base(fname), today) + return // report is in the future, which shouldn't happen + } + buf, err := os.ReadFile(fname) + if err != nil { + u.logger.Printf("%v reading %s", err, fname) + return + } + if u.uploadReportContents(fname, buf) { + // anything left to do? + } +} + +// try to upload the report, 'true' if successful +func (u *uploader) uploadReportContents(fname string, buf []byte) bool { + fdate := strings.TrimSuffix(filepath.Base(fname), ".json") + fdate = fdate[len(fdate)-len(telemetry.DateOnly):] + + newname := filepath.Join(u.dir.UploadDir(), fdate+".json") + + // Lock the upload, to prevent duplicate uploads. + { + lockname := newname + ".lock" + lockfile, err := os.OpenFile(lockname, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + u.logger.Printf("Failed to acquire lock %s: %v", lockname, err) + return false + } + _ = lockfile.Close() + defer os.Remove(lockname) + } + + if _, err := os.Stat(newname); err == nil { + // Another process uploaded but failed to clean up (or hasn't yet cleaned + // up). Ensure that cleanup occurs. + u.logger.Printf("After acquire: report already uploaded") + _ = os.Remove(fname) + return false + } + + endpoint := u.uploadServerURL + "/" + fdate + b := bytes.NewReader(buf) + resp, err := http.Post(endpoint, "application/json", b) + if err != nil { + u.logger.Printf("Error upload %s to %s: %v", filepath.Base(fname), endpoint, err) + return false + } + // hope for a 200, remove file on a 4xx, otherwise it will be retried by another process + if resp.StatusCode != 200 { + u.logger.Printf("Failed to upload %s to %s: %s", filepath.Base(fname), endpoint, resp.Status) + if resp.StatusCode >= 400 && resp.StatusCode < 500 { + err := os.Remove(fname) + if err == nil { + u.logger.Printf("Removed local/%s", filepath.Base(fname)) + } else { + u.logger.Printf("Error removing local/%s: %v", filepath.Base(fname), err) + } + } + return false + } + // Store a copy of the uploaded report in the uploaded directory. + if err := os.WriteFile(newname, buf, 0644); err == nil { + os.Remove(fname) // if it exists + } + u.logger.Printf("Uploaded %s to %q", fdate+".json", endpoint) + return true +} diff --git a/notifier/vendor/golang.org/x/telemetry/mode.go b/notifier/vendor/golang.org/x/telemetry/mode.go new file mode 100644 index 00000000..8cdcd134 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/mode.go @@ -0,0 +1,38 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Mode returns the current telemetry mode. +// +// The telemetry mode is a global value that controls both the local collection +// and uploading of telemetry data. Possible mode values are: +// - "on": both collection and uploading is enabled +// - "local": collection is enabled, but uploading is disabled +// - "off": both collection and uploading are disabled +// +// When mode is "on", or "local", telemetry data is written to the local file +// system and may be inspected with the [gotelemetry] command. +// +// If an error occurs while reading the telemetry mode from the file system, +// Mode returns the default value "local". +// +// [gotelemetry]: https://pkg.go.dev/golang.org/x/telemetry/cmd/gotelemetry +func Mode() string { + mode, _ := telemetry.Default.Mode() + return mode +} + +// SetMode sets the global telemetry mode to the given value. +// +// See the documentation of [Mode] for a description of the supported mode +// values. +// +// An error is returned if the provided mode value is invalid, or if an error +// occurs while persisting the mode value to the file system. +func SetMode(mode string) error { + return telemetry.Default.SetMode(mode) +} diff --git a/notifier/vendor/golang.org/x/telemetry/npm b/notifier/vendor/golang.org/x/telemetry/npm new file mode 100644 index 00000000..a5455cfb --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/npm @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npm \ + node:18.16.0-slim \ + $@ diff --git a/notifier/vendor/golang.org/x/telemetry/npx b/notifier/vendor/golang.org/x/telemetry/npx new file mode 100644 index 00000000..47bb38bb --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/npx @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npx \ + node:18.16.0-slim \ + $@ diff --git a/notifier/vendor/golang.org/x/telemetry/package-lock.json b/notifier/vendor/golang.org/x/telemetry/package-lock.json new file mode 100644 index 00000000..9c86033e --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/package-lock.json @@ -0,0 +1,4363 @@ +{ + "name": "workspace", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.1.1.tgz", + "integrity": "sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz", + "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.4.tgz", + "integrity": "sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@observablehq/plot": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.9.tgz", + "integrity": "sha512-vwV6bzQsGjv2XrPEpc3Voixcz2e5EVvCSzzcs/uW9KXO5ZM8GdMVXtNTaRwYXUOk98nbiYFCFwzMaIyRjrt9IA==", + "dependencies": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz", + "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "dependencies": { + "binary-search-bounds": "^2.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", + "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1", + "@csstools/media-query-list-parser": "^2.0.4", + "@csstools/selector-specificity": "^2.2.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.1.3", + "css-functions-list": "^3.1.0", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.27.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.12", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^12.0.0" + }, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/package.json b/notifier/vendor/golang.org/x/telemetry/package.json new file mode 100644 index 00000000..3680ce22 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/package.json @@ -0,0 +1,23 @@ +{ + "scripts": { + "eslint": "eslint . --fix", + "stylelint": "stylelint '**/*.css' --fix", + "prettier": "prettier --write **/*.{css,ts,md,yaml} !**/*.min.css", + "all": "run-s --continue-on-error eslint stylelint prettier" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + }, + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/start.go b/notifier/vendor/golang.org/x/telemetry/start.go new file mode 100644 index 00000000..9c0519a6 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/start.go @@ -0,0 +1,354 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "sync" + "time" + + "golang.org/x/sync/errgroup" + "golang.org/x/telemetry/counter" + "golang.org/x/telemetry/internal/crashmonitor" + "golang.org/x/telemetry/internal/telemetry" + "golang.org/x/telemetry/internal/upload" +) + +// Config controls the behavior of [Start]. +type Config struct { + // ReportCrashes, if set, will enable crash reporting. + // ReportCrashes uses the [debug.SetCrashOutput] mechanism, which is a + // process-wide resource. + // Do not make other calls to that function within your application. + // ReportCrashes is a non-functional unless the program is built with go1.23+. + ReportCrashes bool + + // Upload causes this program to periodically upload approved counters + // from the local telemetry database to telemetry.go.dev. + // + // This option has no effect unless the user has given consent + // to enable data collection, for example by running + // cmd/gotelemetry or affirming the gopls dialog. + // + // (This feature is expected to be used only by gopls. + // Longer term, the go command may become the sole program + // responsible for uploading.) + Upload bool + + // TelemetryDir, if set, will specify an alternate telemetry + // directory to write data to. If not set, it uses the default + // directory. + // This field is intended to be used for isolating testing environments. + TelemetryDir string + + // UploadStartTime, if set, overrides the time used as the upload start time, + // which is the time used by the upload logic to determine whether counter + // file data should be uploaded. Only counter files that have expired before + // the start time are considered for upload. + // + // This field can be used to simulate a future upload that collects recently + // modified counters. + UploadStartTime time.Time + + // UploadURL, if set, overrides the URL used to receive uploaded reports. If + // unset, this URL defaults to https://telemetry.go.dev/upload. + UploadURL string +} + +// Start initializes telemetry using the specified configuration. +// +// Start opens the local telemetry database so that counter increment +// operations are durably recorded in the local file system. +// +// If [Config.Upload] is set, and the user has opted in to telemetry +// uploading, this process may attempt to upload approved counters +// to telemetry.go.dev. +// +// If [Config.ReportCrashes] is set, any fatal crash will be +// recorded by incrementing a counter named for the stack of the +// first running goroutine in the traceback. +// +// If either of these flags is set, Start re-executes the current +// executable as a child process, in a special mode in which it +// acts as a telemetry sidecar for the parent process (the application). +// In that mode, the call to Start will never return, so Start must +// be called immediately within main, even before such things as +// inspecting the command line. The application should avoid expensive +// steps or external side effects in init functions, as they will +// be executed twice (parent and child). +// +// Start returns a StartResult, which may be awaited via [StartResult.Wait] to +// wait for all work done by Start to complete. +func Start(config Config) *StartResult { + switch v := os.Getenv(telemetryChildVar); v { + case "": + // The subprocess started by parent has GO_TELEMETRY_CHILD=1. + return parent(config) + case "1": + child(config) // child will exit the process when it's done. + case "2": + // Do nothing: this was executed directly or indirectly by a child. + default: + log.Fatalf("unexpected value for %q: %q", telemetryChildVar, v) + } + + return &StartResult{} +} + +// MaybeChild executes the telemetry child logic if the calling program is +// the telemetry child process, and does nothing otherwise. It is meant to be +// called as the first thing in a program that uses telemetry.Start but cannot +// call telemetry.Start immediately when it starts. +func MaybeChild(config Config) { + if v := os.Getenv(telemetryChildVar); v == "1" { + child(config) // child will exit the process when it's done. + } + // other values of the telemetryChildVar environment variable + // will be handled by telemetry.Start. +} + +// A StartResult is a handle to the result of a call to [Start]. Call +// [StartResult.Wait] to wait for the completion of all work done on behalf of +// Start. +type StartResult struct { + wg sync.WaitGroup +} + +// Wait waits for the completion of all work initiated by [Start]. +func (res *StartResult) Wait() { + if res == nil { + return + } + res.wg.Wait() +} + +var daemonize = func(cmd *exec.Cmd) {} + +// If telemetryChildVar is set to "1" in the environment, this is the telemetry +// child. +// +// If telemetryChildVar is set to "2", this is a child of the child, and no +// further forking should occur. +const telemetryChildVar = "GO_TELEMETRY_CHILD" + +// If telemetryUploadVar is set to "1" in the environment, the upload token has been +// acquired by the parent, and the child should attempt an upload. +const telemetryUploadVar = "GO_TELEMETRY_CHILD_UPLOAD" + +func parent(config Config) *StartResult { + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + result := new(StartResult) + + mode, _ := telemetry.Default.Mode() + if mode == "off" { + // Telemetry is turned off. Crash reporting doesn't work without telemetry + // at least set to "local". The upload process runs in both "on" and "local" modes. + // In local mode the upload process builds local reports but does not do the upload. + return result + } + + counter.Open() + + if _, err := os.Stat(telemetry.Default.LocalDir()); err != nil { + // There was a problem statting LocalDir, which is needed for both + // crash monitoring and counter uploading. Most likely, there was an + // error creating telemetry.LocalDir in the counter.Open call above. + // Don't start the child. + return result + } + + childShouldUpload := config.Upload && acquireUploadToken() + reportCrashes := config.ReportCrashes + + if reportCrashes || childShouldUpload { + startChild(reportCrashes, childShouldUpload, result) + } + + return result +} + +func startChild(reportCrashes, upload bool, result *StartResult) { + // This process is the application (parent). + // Fork+exec the telemetry child. + exe, err := os.Executable() + if err != nil { + // There was an error getting os.Executable. It's possible + // for this to happen on AIX if os.Args[0] is not an absolute + // path and we can't find os.Args[0] in PATH. + log.Printf("failed to start telemetry sidecar: os.Executable: %v", err) + return + } + cmd := exec.Command(exe, "** telemetry **") // this unused arg is just for ps(1) + daemonize(cmd) + cmd.Env = append(os.Environ(), telemetryChildVar+"=1") + if upload { + cmd.Env = append(cmd.Env, telemetryUploadVar+"=1") + } + cmd.Dir = telemetry.Default.LocalDir() + + // The child process must write to a log file, not + // the stderr file it inherited from the parent, as + // the child may outlive the parent but should not prolong + // the life of any pipes created (by the grandparent) + // to gather the output of the parent. + // + // By default, we discard the child process's stderr, + // but in line with the uploader, log to a file in debug + // only if that directory was created by the user. + fd, err := os.Stat(telemetry.Default.DebugDir()) + if err != nil { + if !os.IsNotExist(err) { + log.Printf("failed to stat debug directory: %v", err) + return + } + } else if fd.IsDir() { + // local/debug exists and is a directory. Set stderr to a log file path + // in local/debug. + childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log") + childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) + if err != nil { + log.Printf("opening sidecar log file for child: %v", err) + return + } + defer childLog.Close() + cmd.Stderr = childLog + } + + var crashOutputFile *os.File + if reportCrashes { + pipe, err := cmd.StdinPipe() + if err != nil { + log.Printf("StdinPipe: %v", err) + return + } + + crashOutputFile = pipe.(*os.File) // (this conversion is safe) + } + + if err := cmd.Start(); err != nil { + // The child couldn't be started. Log the failure. + log.Printf("can't start telemetry child process: %v", err) + return + } + if reportCrashes { + crashmonitor.Parent(crashOutputFile) + } + result.wg.Add(1) + go func() { + cmd.Wait() // Release resources if cmd happens not to outlive this process. + result.wg.Done() + }() +} + +func child(config Config) { + log.SetPrefix(fmt.Sprintf("telemetry-sidecar (pid %v): ", os.Getpid())) + + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + + // golang/go#67211: be sure to set telemetryChildVar before running the + // child, because the child itself invokes the go command to download the + // upload config. If the telemetryChildVar variable is still set to "1", + // that delegated go command may think that it is itself a telemetry + // child. + // + // On the other hand, if telemetryChildVar were simply unset, then the + // delegated go commands would fork themselves recursively. Short-circuit + // this recursion. + os.Setenv(telemetryChildVar, "2") + upload := os.Getenv(telemetryUploadVar) == "1" + + // The crashmonitor and/or upload process may themselves record counters. + counter.Open() + + // Start crashmonitoring and uploading depending on what's requested + // and wait for the longer running child to complete before exiting: + // if we collected a crash before the upload finished, wait for the + // upload to finish before exiting + var g errgroup.Group + + if config.ReportCrashes { + g.Go(func() error { + crashmonitor.Child() + return nil + }) + } + if upload { + g.Go(func() error { + uploaderChild(config.UploadStartTime, config.UploadURL) + return nil + }) + } + g.Wait() + + os.Exit(0) +} + +func uploaderChild(asof time.Time, uploadURL string) { + if err := upload.Run(upload.RunConfig{ + UploadURL: uploadURL, + LogWriter: os.Stderr, + StartTime: asof, + }); err != nil { + log.Printf("upload failed: %v", err) + } +} + +// acquireUploadToken acquires a token permitting the caller to upload. +// To limit the frequency of uploads, only one token is issue per +// machine per time period. +// The boolean indicates whether the token was acquired. +func acquireUploadToken() bool { + if telemetry.Default.LocalDir() == "" { + // The telemetry dir wasn't initialized properly, probably because + // os.UserConfigDir did not complete successfully. In that case + // there are no counters to upload, so we should just do nothing. + return false + } + tokenfile := filepath.Join(telemetry.Default.LocalDir(), "upload.token") + const period = 24 * time.Hour + + // A process acquires a token by successfully creating a + // well-known file. If the file already exists and has an + // mtime age less then than the period, the process does + // not acquire the token. If the file is older than the + // period, the process is allowed to remove the file and + // try to re-create it. + fi, err := os.Stat(tokenfile) + if err == nil { + if time.Since(fi.ModTime()) < period { + return false + } + // There's a possible race here where two processes check the + // token file and see that it's older than the period, then the + // first one removes it and creates another, and then a second one + // removes the newly created file and creates yet another + // file. Then both processes would act as though they had the token. + // This is very rare, but it's also okay because we're only grabbing + // the token to do rate limiting, not for correctness. + _ = os.Remove(tokenfile) + } else if !os.IsNotExist(err) { + log.Printf("error acquiring upload taken: statting token file: %v", err) + return false + } + + f, err := os.OpenFile(tokenfile, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return false + } + log.Printf("error acquiring upload token: creating token file: %v", err) + return false + } + _ = f.Close() + return true +} diff --git a/notifier/vendor/golang.org/x/telemetry/start_posix.go b/notifier/vendor/golang.org/x/telemetry/start_posix.go new file mode 100644 index 00000000..078b2353 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/start_posix.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package telemetry + +import ( + "os/exec" + "syscall" +) + +func init() { + daemonize = daemonizePosix +} + +func daemonizePosix(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/start_windows.go b/notifier/vendor/golang.org/x/telemetry/start_windows.go new file mode 100644 index 00000000..ceb2c029 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/start_windows.go @@ -0,0 +1,29 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package telemetry + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + daemonize = daemonizeWindows +} + +func daemonizeWindows(cmd *exec.Cmd) { + // Set DETACHED_PROCESS creation flag so that closing + // the console window the parent process was run in + // does not kill the child. + // See documentation of creation flags in the Microsoft documentation: + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.DETACHED_PROCESS, + } +} diff --git a/notifier/vendor/golang.org/x/telemetry/tsconfig.json b/notifier/vendor/golang.org/x/telemetry/tsconfig.json new file mode 100644 index 00000000..7833e310 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/tsconfig.json @@ -0,0 +1,26 @@ +{ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "node", + + "strict": true, + "allowUnusedLabels": false, + "allowUnreachableCode": false, + "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "checkJs": true, + + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, +} \ No newline at end of file diff --git a/notifier/vendor/golang.org/x/telemetry/types_alias.go b/notifier/vendor/golang.org/x/telemetry/types_alias.go new file mode 100644 index 00000000..83ba7e05 --- /dev/null +++ b/notifier/vendor/golang.org/x/telemetry/types_alias.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig = telemetry.UploadConfig + +type ProgramConfig = telemetry.ProgramConfig + +type CounterConfig = telemetry.CounterConfig + +// A Report is what's uploaded (or saved locally) +type Report = telemetry.Report + +type ProgramReport = telemetry.ProgramReport diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index 436b03cb..1aa7afb9 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -57,7 +57,7 @@ type asmArch struct { // include the first integer register and first floating-point register. Accessing // any of them counts as writing to result. retRegs []string - // writeResult is a list of instructions that will change result register implicity. + // writeResult is a list of instructions that will change result register implicitly. writeResult []string // calculated during initialization sizes types.Sizes diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go index 1413ee13..1914bb47 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go @@ -9,11 +9,11 @@ package assign import ( _ "embed" - "fmt" "go/ast" "go/token" "go/types" "reflect" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -48,31 +48,84 @@ func run(pass *analysis.Pass) (any, error) { // If LHS and RHS have different cardinality, they can't be the same. return } + + // Delete redundant LHS, RHS pairs, taking care + // to include intervening commas. + var ( + exprs []string // expressions appearing on both sides (x = x) + edits []analysis.TextEdit + runStartLHS, runStartRHS token.Pos // non-zero => within a run + ) for i, lhs := range stmt.Lhs { rhs := stmt.Rhs[i] - if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || - analysisutil.HasSideEffects(pass.TypesInfo, rhs) || - isMapIndex(pass.TypesInfo, lhs) { - continue // expressions may not be equal - } - if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { - continue // short-circuit the heavy-weight gofmt check + isSelfAssign := false + var le string + + if !analysisutil.HasSideEffects(pass.TypesInfo, lhs) && + !analysisutil.HasSideEffects(pass.TypesInfo, rhs) && + !isMapIndex(pass.TypesInfo, lhs) && + reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check + + le = analysisinternal.Format(pass.Fset, lhs) + re := analysisinternal.Format(pass.Fset, rhs) + if le == re { + isSelfAssign = true + } } - le := analysisinternal.Format(pass.Fset, lhs) - re := analysisinternal.Format(pass.Fset, rhs) - if le == re { - pass.Report(analysis.Diagnostic{ - Pos: stmt.Pos(), Message: fmt.Sprintf("self-assignment of %s to %s", re, le), - SuggestedFixes: []analysis.SuggestedFix{{ - Message: "Remove self-assignment", - TextEdits: []analysis.TextEdit{{ - Pos: stmt.Pos(), - End: stmt.End(), - }}}, - }, - }) + + if isSelfAssign { + exprs = append(exprs, le) + if !runStartLHS.IsValid() { + // Start of a new run of self-assignments. + if i > 0 { + runStartLHS = stmt.Lhs[i-1].End() + runStartRHS = stmt.Rhs[i-1].End() + } else { + runStartLHS = lhs.Pos() + runStartRHS = rhs.Pos() + } + } + } else if runStartLHS.IsValid() { + // End of a run of self-assignments. + endLHS, endRHS := stmt.Lhs[i-1].End(), stmt.Rhs[i-1].End() + if runStartLHS == stmt.Lhs[0].Pos() { + endLHS, endRHS = lhs.Pos(), rhs.Pos() + } + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: endLHS}, + analysis.TextEdit{Pos: runStartRHS, End: endRHS}, + ) + runStartLHS, runStartRHS = 0, 0 } } + + // If a run of self-assignments continues to the end of the statement, close it. + if runStartLHS.IsValid() { + last := len(stmt.Lhs) - 1 + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: stmt.Lhs[last].End()}, + analysis.TextEdit{Pos: runStartRHS, End: stmt.Rhs[last].End()}, + ) + } + + if len(exprs) == 0 { + return + } + + if len(exprs) == len(stmt.Lhs) { + // If every part of the statement is a self-assignment, + // remove the whole statement. + edits = []analysis.TextEdit{{Pos: stmt.Pos(), End: stmt.End()}} + } + + pass.Report(analysis.Diagnostic{ + Pos: stmt.Pos(), + Message: "self-assignment of " + strings.Join(exprs, ", "), + SuggestedFixes: []analysis.SuggestedFix{{ + Message: "Remove self-assignment", + TextEdits: edits, + }}, + }) }) return nil, nil diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 25c98a97..ed2284e6 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -153,7 +153,8 @@ func isLocalType(pass *analysis.Pass, typ types.Type) bool { return isLocalType(pass, x.Elem()) case interface{ Obj() *types.TypeName }: // *Named or *TypeParam (aliases were removed already) // names in package foo are local to foo_test too - return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") + return x.Obj().Pkg() != nil && + strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") } return false } diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go index ba94fd68..ff9c8b4f 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go @@ -28,9 +28,9 @@ var Analyzer = &analysis.Analyzer{ // Per-architecture checks for instructions. // Assume comments, leading and trailing spaces are removed. type arch struct { - isFPWrite func(string) bool - isFPRead func(string) bool - isBranch func(string) bool + isFPWrite func(string) bool + isFPRead func(string) bool + isUnconditionalBranch func(string) bool } var re = regexp.MustCompile @@ -48,8 +48,8 @@ var arches = map[string]arch{ "amd64": { isFPWrite: re(`,\s*BP$`).MatchString, // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely. isFPRead: re(`\bBP\b`).MatchString, - isBranch: func(s string) bool { - return hasAnyPrefix(s, "J", "RET") + isUnconditionalBranch: func(s string) bool { + return hasAnyPrefix(s, "JMP", "RET") }, }, "arm64": { @@ -70,49 +70,16 @@ var arches = map[string]arch{ return false }, isFPRead: re(`\bR29\b`).MatchString, - isBranch: func(s string) bool { + isUnconditionalBranch: func(s string) bool { // Get just the instruction if i := strings.IndexFunc(s, unicode.IsSpace); i > 0 { s = s[:i] } - return arm64Branch[s] + return s == "B" || s == "JMP" || s == "RET" }, }, } -// arm64 has many control flow instructions. -// ^(B|RET) isn't sufficient or correct (e.g. BIC, BFI aren't control flow.) -// It's easier to explicitly enumerate them in a map than to write a regex. -// Borrowed from Go tree, cmd/asm/internal/arch/arm64.go -var arm64Branch = map[string]bool{ - "B": true, - "BL": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CBZ": true, - "CBZW": true, - "CBNZ": true, - "CBNZW": true, - "JMP": true, - "TBNZ": true, - "TBZ": true, - "RET": true, -} - func run(pass *analysis.Pass) (any, error) { arch, ok := arches[build.Default.GOARCH] if !ok { @@ -164,7 +131,7 @@ func run(pass *analysis.Pass) (any, error) { active = false continue } - if arch.isFPRead(line) || arch.isBranch(line) { + if arch.isFPRead(line) || arch.isUnconditionalBranch(line) { active = false continue } diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go index 64df1b10..2580a0ac 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go @@ -88,7 +88,7 @@ func run(pass *analysis.Pass) (any, error) { // // TODO: consider allowing the "last" go/defer/Go statement to be followed by // N "trivial" statements, possibly under a recursive definition of "trivial" - // so that that checker could, for example, conclude that a go statement is + // so that checker could, for example, conclude that a go statement is // followed by an if statement made of only trivial statements and trivial expressions, // and hence the go statement could still be checked. forEachLastStmt(body.List, func(last ast.Stmt) { diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index a28ed365..159a95ae 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/internal/analysisinternal" + "golang.org/x/tools/internal/astutil" "golang.org/x/tools/internal/fmtstr" "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/versions" @@ -540,7 +541,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", name) + pass.ReportRangef(call.Args[firstArg], "%s call has arguments but no formatting directives", name) } return } @@ -552,7 +553,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C if err != nil { // All error messages are in predicate form ("call has a problem") // so that they may be affixed into a subject ("log.Printf "). - pass.ReportRangef(call.Args[idx], "%s %s", name, err) + pass.ReportRangef(formatArg, "%s %s", name, err) return } @@ -560,20 +561,21 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C maxArgIndex := firstArg - 1 anyIndex := false // Check formats against args. - for _, operation := range operations { - if operation.Prec.Index != -1 || - operation.Width.Index != -1 || - operation.Verb.Index != -1 { + for _, op := range operations { + if op.Prec.Index != -1 || + op.Width.Index != -1 || + op.Verb.Index != -1 { anyIndex = true } - if !okPrintfArg(pass, call, &maxArgIndex, firstArg, name, operation) { + rng := opRange(formatArg, op) + if !okPrintfArg(pass, call, rng, &maxArgIndex, firstArg, name, op) { // One error per format is enough. return } - if operation.Verb.Verb == 'w' { + if op.Verb.Verb == 'w' { switch kind { case KindNone, KindPrint, KindPrintf: - pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", name) + pass.ReportRangef(rng, "%s does not support error-wrapping directive %%w", name) return } } @@ -594,6 +596,18 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C } } +// opRange returns the source range for the specified printf operation, +// such as the position of the %v substring of "...%v...". +func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range { + if lit, ok := formatArg.(*ast.BasicLit); ok { + start, end, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End) + if err == nil { + return analysisinternal.Range(start, end) // position of "%v" + } + } + return formatArg // entire format string +} + // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask. type printfArgType int @@ -657,7 +671,7 @@ var printVerbs = []printVerb{ // okPrintfArg compares the operation to the arguments actually present, // reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index. // If the final argument is ellipsissed, there's little it can do for that. -func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { +func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { verb := operation.Verb.Verb var v printVerb found := false @@ -680,7 +694,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if !formatter { if !found { - pass.ReportRangef(call, "%s format %s has unknown verb %c", name, operation.Text, verb) + pass.ReportRangef(rng, "%s format %s has unknown verb %c", name, operation.Text, verb) return false } for _, flag := range operation.Flags { @@ -690,7 +704,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs continue } if !strings.ContainsRune(v.flags, rune(flag)) { - pass.ReportRangef(call, "%s format %s has unrecognized flag %c", name, operation.Text, flag) + pass.ReportRangef(rng, "%s format %s has unrecognized flag %c", name, operation.Text, flag) return false } } @@ -707,7 +721,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // If len(argIndexes)>0, we have something like %.*s and all // indexes in argIndexes must be an integer. for _, argIndex := range argIndexes { - if !argCanBeChecked(pass, call, argIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, argIndex, firstArg, operation, name) { return } arg := call.Args[argIndex] @@ -716,7 +730,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) + pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) return false } } @@ -738,12 +752,12 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // Now check verb's type. verbArgIndex := operation.Verb.ArgIndex - if !argCanBeChecked(pass, call, verbArgIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, verbArgIndex, firstArg, operation, name) { return false } arg := call.Args[verbArgIndex] if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' { - pass.ReportRangef(call, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) + pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) return false } if reason, ok := matchArgType(pass, v.typ, arg); !ok { @@ -755,12 +769,14 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) + pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) return false } - if v.typ&argString != 0 && v.verb != 'T' && !strings.Contains(operation.Flags, "#") { + // Detect recursive formatting via value's String/Error methods. + // The '#' flag suppresses the methods, except with %x, %X, and %q. + if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) { if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) + pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) return false } } @@ -844,7 +860,7 @@ func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { // argCanBeChecked reports whether the specified argument is statically present; // it may be beyond the list of arguments or in a terminal slice... argument, which // means we can't see it. -func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { +func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { if argIndex <= 0 { // Shouldn't happen, so catch it with prejudice. panic("negative argIndex") @@ -861,7 +877,7 @@ func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg // There are bad indexes in the format or there are fewer arguments than the format needs. // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". arg := argIndex - firstArg + 1 // People think of arguments as 1-indexed. - pass.ReportRangef(call, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) + pass.ReportRangef(rng, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) return false } diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index a23721cd..7dbff1e4 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/typesinternal" ) //go:embed doc.go @@ -60,12 +61,11 @@ func describe(typ, inType types.Type, inName string) string { } func typeName(t types.Type) string { - type hasTypeName interface{ Obj() *types.TypeName } // Alias, Named, TypeParam - switch t := t.(type) { - case *types.Basic: - return t.Name() - case hasTypeName: - return t.Obj().Name() + if basic, ok := t.(*types.Basic); ok { + return basic.Name() // may be (e.g.) "untyped int", which has no TypeName + } + if tname := typesinternal.TypeNameFor(t); tname != nil { + return tname.Name() } return "" } diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go index 13a99973..cc90f733 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go @@ -107,7 +107,7 @@ func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, s // Embedded struct. Nothing to do for now, but that // may change, depending on what happens with issue 7363. - // TODO(adonovan): investigate, now that that issue is fixed. + // TODO(adonovan): investigate, now that issue is fixed. if field.Anonymous() { return } diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 9f59006e..d4e9b025 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -447,18 +447,6 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { } } -type tokenRange struct { - p, e token.Pos -} - -func (r tokenRange) Pos() token.Pos { - return r.p -} - -func (r tokenRange) End() token.Pos { - return r.e -} - func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { // Want functions with 0 results and 1 parameter. if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || @@ -476,8 +464,9 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 { // Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters. // We have currently decided to also warn before compilation/package loading. This can help users in IDEs. - at := tokenRange{tparams.Opening, tparams.Closing} - pass.ReportRangef(at, "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix) + pass.ReportRangef(analysisinternal.Range(tparams.Opening, tparams.Closing), + "%s has type parameters: it will not be run by go test as a %sXXX function", + fn.Name.Name, prefix) } if !isTestSuffix(fn.Name.Name[len(prefix):]) { diff --git a/notifier/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/notifier/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index 932f1347..556ffed7 100644 --- a/notifier/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/notifier/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -26,6 +26,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/analysisinternal" ) //go:embed doc.go @@ -59,23 +60,62 @@ func init() { // The context.With{Cancel,Deadline,Timeout} entries are // effectively redundant wrt the lostcancel analyzer. funcs = stringSetFlag{ - "context.WithCancel": true, - "context.WithDeadline": true, - "context.WithTimeout": true, - "context.WithValue": true, - "errors.New": true, - "fmt.Errorf": true, - "fmt.Sprint": true, - "fmt.Sprintf": true, - "slices.Clip": true, - "slices.Compact": true, - "slices.CompactFunc": true, - "slices.Delete": true, - "slices.DeleteFunc": true, - "slices.Grow": true, - "slices.Insert": true, - "slices.Replace": true, - "sort.Reverse": true, + "context.WithCancel": true, + "context.WithDeadline": true, + "context.WithTimeout": true, + "context.WithValue": true, + "errors.New": true, + "fmt.Append": true, + "fmt.Appendf": true, + "fmt.Appendln": true, + "fmt.Errorf": true, + "fmt.Sprint": true, + "fmt.Sprintf": true, + "fmt.Sprintln": true, + "maps.All": true, + "maps.Clone": true, + "maps.Collect": true, + "maps.Equal": true, + "maps.EqualFunc": true, + "maps.Keys": true, + "maps.Values": true, + "slices.All": true, + "slices.AppendSeq": true, + "slices.Backward": true, + "slices.BinarySearch": true, + "slices.BinarySearchFunc": true, + "slices.Chunk": true, + "slices.Clip": true, + "slices.Clone": true, + "slices.Collect": true, + "slices.Compact": true, + "slices.CompactFunc": true, + "slices.Compare": true, + "slices.CompareFunc": true, + "slices.Concat": true, + "slices.Contains": true, + "slices.ContainsFunc": true, + "slices.Delete": true, + "slices.DeleteFunc": true, + "slices.Equal": true, + "slices.EqualFunc": true, + "slices.Grow": true, + "slices.Index": true, + "slices.IndexFunc": true, + "slices.Insert": true, + "slices.IsSorted": true, + "slices.IsSortedFunc": true, + "slices.Max": true, + "slices.MaxFunc": true, + "slices.Min": true, + "slices.MinFunc": true, + "slices.Repeat": true, + "slices.Replace": true, + "slices.Sorted": true, + "slices.SortedFunc": true, + "slices.SortedStableFunc": true, + "slices.Values": true, + "sort.Reverse": true, } Analyzer.Flags.Var(&funcs, "funcs", "comma-separated list of functions whose results must be used") @@ -114,14 +154,16 @@ func run(pass *analysis.Pass) (any, error) { // method (e.g. foo.String()) if types.Identical(sig, sigNoArgsStringResult) { if stringMethods[fn.Name()] { - pass.Reportf(call.Lparen, "result of (%s).%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of (%s).%s call not used", sig.Recv().Type(), fn.Name()) } } } else { // package-level function (e.g. fmt.Errorf) if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] { - pass.Reportf(call.Lparen, "result of %s.%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of %s.%s call not used", fn.Pkg().Path(), fn.Name()) } } diff --git a/notifier/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/notifier/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6e34df46..0fb4e7ee 100644 --- a/notifier/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/notifier/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -113,7 +113,7 @@ func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Nod // childrenOf elides the FuncType node beneath FuncDecl. // Add it back here for TypeParams, Params, Results, // all FieldLists). But we don't add it back for the "func" token - // even though it is is the tree at FuncDecl.Type.Func. + // even though it is the tree at FuncDecl.Type.Func. if decl, ok := node.(*ast.FuncDecl); ok { if fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv { path = append(path, decl.Type) @@ -207,6 +207,9 @@ func childrenOf(n ast.Node) []ast.Node { return false // no recursion }) + // TODO(adonovan): be more careful about missing (!Pos.Valid) + // tokens in trees produced from invalid input. + // Then add fake Nodes for bare tokens. switch n := n.(type) { case *ast.ArrayType: @@ -226,9 +229,12 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) + if n.Lbrace.IsValid() { + children = append(children, tok(n.Lbrace, len("{"))) + } + if n.Rbrace.IsValid() { + children = append(children, tok(n.Rbrace, len("}"))) + } case *ast.BranchStmt: children = append(children, @@ -304,9 +310,12 @@ func childrenOf(n ast.Node) []ast.Node { // TODO(adonovan): Field.{Doc,Comment,Tag}? case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), // or len("[") - tok(n.Closing, len(")"))) // or len("]") + if n.Opening.IsValid() { + children = append(children, tok(n.Opening, len("("))) + } + if n.Closing.IsValid() { + children = append(children, tok(n.Closing, len(")"))) + } case *ast.File: // TODO test: Doc diff --git a/notifier/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/notifier/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index 5c8dbbb7..4ad05493 100644 --- a/notifier/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/notifier/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -67,6 +67,10 @@ var abort = new(int) // singleton, to signal termination of Apply // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. +// +// This type is not to be confused with [inspector.Cursor] from +// package [golang.org/x/tools/go/ast/inspector], which provides +// stateless navigation of immutable syntax trees. type Cursor struct { parent ast.Node name string diff --git a/notifier/vendor/golang.org/x/tools/internal/astutil/edge/edge.go b/notifier/vendor/golang.org/x/tools/go/ast/edge/edge.go similarity index 100% rename from notifier/vendor/golang.org/x/tools/internal/astutil/edge/edge.go rename to notifier/vendor/golang.org/x/tools/go/ast/edge/edge.go diff --git a/notifier/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/notifier/vendor/golang.org/x/tools/go/ast/inspector/cursor.go new file mode 100644 index 00000000..31c8d2f2 --- /dev/null +++ b/notifier/vendor/golang.org/x/tools/go/ast/inspector/cursor.go @@ -0,0 +1,502 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package inspector + +import ( + "fmt" + "go/ast" + "go/token" + "iter" + "reflect" + + "golang.org/x/tools/go/ast/edge" +) + +// A Cursor represents an [ast.Node]. It is immutable. +// +// Two Cursors compare equal if they represent the same node. +// +// Call [Inspector.Root] to obtain a valid cursor for the virtual root +// node of the traversal. +// +// Use the following methods to navigate efficiently around the tree: +// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing]; +// - for children, use [Cursor.Child], [Cursor.Children], +// [Cursor.FirstChild], and [Cursor.LastChild]; +// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling]; +// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode], +// [Cursor.Inspect], and [Cursor.Preorder]. +// +// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for +// information about the edges in a tree: which field (and slice +// element) of the parent node holds the child. +type Cursor struct { + in *Inspector + index int32 // index of push node; -1 for virtual root node +} + +// Root returns a cursor for the virtual root node, +// whose children are the files provided to [New]. +// +// Its [Cursor.Node] and [Cursor.Stack] methods return nil. +func (in *Inspector) Root() Cursor { + return Cursor{in, -1} +} + +// At returns the cursor at the specified index in the traversal, +// which must have been obtained from [Cursor.Index] on a Cursor +// belonging to the same Inspector (see [Cursor.Inspector]). +func (in *Inspector) At(index int32) Cursor { + if index < 0 { + panic("negative index") + } + if int(index) >= len(in.events) { + panic("index out of range for this inspector") + } + if in.events[index].index < index { + panic("invalid index") // (a push, not a pop) + } + return Cursor{in, index} +} + +// Inspector returns the cursor's Inspector. +func (c Cursor) Inspector() *Inspector { return c.in } + +// Index returns the index of this cursor position within the package. +// +// Clients should not assume anything about the numeric Index value +// except that it increases monotonically throughout the traversal. +// It is provided for use with [At]. +// +// Index must not be called on the Root node. +func (c Cursor) Index() int32 { + if c.index < 0 { + panic("Index called on Root node") + } + return c.index +} + +// Node returns the node at the current cursor position, +// or nil for the cursor returned by [Inspector.Root]. +func (c Cursor) Node() ast.Node { + if c.index < 0 { + return nil + } + return c.in.events[c.index].node +} + +// String returns information about the cursor's node, if any. +func (c Cursor) String() string { + if c.in == nil { + return "(invalid)" + } + if c.index < 0 { + return "(root)" + } + return reflect.TypeOf(c.Node()).String() +} + +// indices return the [start, end) half-open interval of event indices. +func (c Cursor) indices() (int32, int32) { + if c.index < 0 { + return 0, int32(len(c.in.events)) // root: all events + } else { + return c.index, c.in.events[c.index].index + 1 // just one subtree + } +} + +// Preorder returns an iterator over the nodes of the subtree +// represented by c in depth-first order. Each node in the sequence is +// represented by a Cursor that allows access to the Node, but may +// also be used to start a new traversal, or to obtain the stack of +// nodes enclosing the cursor. +// +// The traversal sequence is determined by [ast.Inspect]. The types +// argument, if non-empty, enables type-based filtering of events. The +// function f if is called only for nodes whose type matches an +// element of the types slice. +// +// If you need control over descent into subtrees, +// or need both pre- and post-order notifications, use [Cursor.Inspect] +func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain types: skip. + i = pop + 1 + continue + } + } + i++ + } + } +} + +// Inspect visits the nodes of the subtree represented by c in +// depth-first order. It calls f(n) for each node n before it +// visits n's children. If f returns true, Inspect invokes f +// recursively for each of the non-nil children of the node. +// +// Each node is represented by a Cursor that allows access to the +// Node, but may also be used to start a new traversal, or to obtain +// the stack of nodes enclosing the cursor. +// +// The complete traversal sequence is determined by [ast.Inspect]. +// The types argument, if non-empty, enables type-based filtering of +// events. The function f if is called only for nodes whose type +// matches an element of the types slice. +func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { + mask := maskOf(types) + events := c.in.events + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { + // push + pop := ev.index + if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || + events[pop].typ&mask == 0 { + // The user opted not to descend, or the + // subtree does not contain types: + // skip past the pop. + i = pop + 1 + continue + } + } + i++ + } +} + +// Enclosing returns an iterator over the nodes enclosing the current +// current node, starting with the Cursor itself. +// +// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// The types argument, if non-empty, enables type-based filtering of +// events: the sequence includes only enclosing nodes whose type +// matches an element of the types slice. +func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { + if c.index < 0 { + panic("Cursor.Enclosing called on Root node") + } + + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + for i := c.index; i >= 0; i = events[i].parent { + if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + } + } +} + +// Parent returns the parent of the current node. +// +// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Parent() Cursor { + if c.index < 0 { + panic("Cursor.Parent called on Root node") + } + + return Cursor{c.in, c.in.events[c.index].parent} +} + +// ParentEdge returns the identity of the field in the parent node +// that holds this cursor's node, and if it is a list, the index within it. +// +// For example, f(x, y) is a CallExpr whose three children are Idents. +// f has edge kind [edge.CallExpr_Fun] and index -1. +// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. +// +// If called on a child of the Root node, it returns ([edge.Invalid], -1). +// +// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) ParentEdge() (edge.Kind, int) { + if c.index < 0 { + panic("Cursor.ParentEdge called on Root node") + } + events := c.in.events + pop := events[c.index].index + return unpackEdgeKindAndIndex(events[pop].parent) +} + +// ChildAt returns the cursor for the child of the +// current node identified by its edge and index. +// The index must be -1 if the edge.Kind is not a slice. +// The indicated child node must exist. +// +// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. +func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { + target := packEdgeKindAndIndex(k, idx) + + // Unfortunately there's no shortcut to looping. + events := c.in.events + i := c.index + 1 + for { + pop := events[i].index + if pop < i { + break + } + if events[pop].parent == target { + return Cursor{c.in, i} + } + i = pop + 1 + } + panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) +} + +// Child returns the cursor for n, which must be a direct child of c's Node. +// +// Child must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Child(n ast.Node) Cursor { + if c.index < 0 { + panic("Cursor.Child called on Root node") + } + + if false { + // reference implementation + for child := range c.Children() { + if child.Node() == n { + return child + } + } + + } else { + // optimized implementation + events := c.in.events + for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { + if events[i].node == n { + return Cursor{c.in, i} + } + } + } + panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) +} + +// NextSibling returns the cursor for the next sibling node in the same list +// (for example, of files, decls, specs, statements, fields, or expressions) as +// the current node. It returns (zero, false) if the node is the last node in +// the list, or is not part of a list. +// +// NextSibling must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) NextSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.NextSibling called on Root node") + } + + events := c.in.events + i := events[c.index].index + 1 // after corresponding pop + if i < int32(len(events)) { + if events[i].index > i { // push? + return Cursor{c.in, i}, true + } + } + return Cursor{}, false +} + +// PrevSibling returns the cursor for the previous sibling node in the +// same list (for example, of files, decls, specs, statements, fields, +// or expressions) as the current node. It returns zero if the node is +// the first node in the list, or is not part of a list. +// +// It must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) PrevSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.PrevSibling called on Root node") + } + + events := c.in.events + i := c.index - 1 + if i >= 0 { + if j := events[i].index; j < i { // pop? + return Cursor{c.in, j}, true + } + } + return Cursor{}, false +} + +// FirstChild returns the first direct child of the current node, +// or zero if it has no children. +func (c Cursor) FirstChild() (Cursor, bool) { + events := c.in.events + i := c.index + 1 // i=0 if c is root + if i < int32(len(events)) && events[i].index > i { // push? + return Cursor{c.in, i}, true + } + return Cursor{}, false +} + +// LastChild returns the last direct child of the current node, +// or zero if it has no children. +func (c Cursor) LastChild() (Cursor, bool) { + events := c.in.events + if c.index < 0 { // root? + if len(events) > 0 { + // return push of final event (a pop) + return Cursor{c.in, events[len(events)-1].index}, true + } + } else { + j := events[c.index].index - 1 // before corresponding pop + // Inv: j == c.index if c has no children + // or j is last child's pop. + if j > c.index { // c has children + return Cursor{c.in, events[j].index}, true + } + } + return Cursor{}, false +} + +// Children returns an iterator over the direct children of the +// current node, if any. +// +// When using Children, NextChild, and PrevChild, bear in mind that a +// Node's children may come from different fields, some of which may +// be lists of nodes without a distinguished intervening container +// such as [ast.BlockStmt]. +// +// For example, [ast.CaseClause] has a field List of expressions and a +// field Body of statements, so the children of a CaseClause are a mix +// of expressions and statements. Other nodes that have "uncontained" +// list fields include: +// +// - [ast.ValueSpec] (Names, Values) +// - [ast.CompositeLit] (Type, Elts) +// - [ast.IndexListExpr] (X, Indices) +// - [ast.CallExpr] (Fun, Args) +// - [ast.AssignStmt] (Lhs, Rhs) +// +// So, do not assume that the previous sibling of an ast.Stmt is also +// an ast.Stmt, or if it is, that they are executed sequentially, +// unless you have established that, say, its parent is a BlockStmt +// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. +// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, +// even though they are not executed in sequence. +func (c Cursor) Children() iter.Seq[Cursor] { + return func(yield func(Cursor) bool) { + c, ok := c.FirstChild() + for ok && yield(c) { + c, ok = c.NextSibling() + } + } +} + +// Contains reports whether c contains or is equal to c2. +// +// Both Cursors must belong to the same [Inspector]; +// neither may be its Root node. +func (c Cursor) Contains(c2 Cursor) bool { + if c.in != c2.in { + panic("different inspectors") + } + events := c.in.events + return c.index <= c2.index && events[c2.index].index <= events[c.index].index +} + +// FindNode returns the cursor for node n if it belongs to the subtree +// rooted at c. It returns zero if n is not found. +func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { + + // FindNode is equivalent to this code, + // but more convenient and 15-20% faster: + if false { + for candidate := range c.Preorder(n) { + if candidate.Node() == n { + return candidate, true + } + } + return Cursor{}, false + } + + // TODO(adonovan): opt: should we assume Node.Pos is accurate + // and combine type-based filtering with position filtering + // like FindByPos? + + mask := maskOf([]ast.Node{n}) + events := c.in.events + + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && ev.node == n { + return Cursor{c.in, i}, true + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain type of n: skip. + i = pop + } + } + } + return Cursor{}, false +} + +// FindByPos returns the cursor for the innermost node n in the tree +// rooted at c such that n.Pos() <= start && end <= n.End(). +// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) +// +// It returns zero if none is found. +// Precondition: start <= end. +// +// See also [astutil.PathEnclosingInterval], which +// tolerates adjoining whitespace. +func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { + if end < start { + panic("end < start") + } + events := c.in.events + + // This algorithm could be implemented using c.Inspect, + // but it is about 2.5x slower. + + best := int32(-1) // push index of latest (=innermost) node containing range + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + n := ev.node + var nodeEnd token.Pos + if file, ok := n.(*ast.File); ok { + nodeEnd = file.FileEnd + // Note: files may be out of Pos order. + if file.FileStart > start { + i = ev.index // disjoint, after; skip to next file + continue + } + } else { + nodeEnd = n.End() + if n.Pos() > start { + break // disjoint, after; stop + } + } + // Inv: node.{Pos,FileStart} <= start + if end <= nodeEnd { + // node fully contains target range + best = i + } else if nodeEnd < start { + i = ev.index // disjoint, before; skip forward + } + } + } + if best >= 0 { + return Cursor{c.in, best}, true + } + return Cursor{}, false +} diff --git a/notifier/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/notifier/vendor/golang.org/x/tools/go/ast/inspector/inspector.go index 674490a6..a703cdfc 100644 --- a/notifier/vendor/golang.org/x/tools/go/ast/inspector/inspector.go +++ b/notifier/vendor/golang.org/x/tools/go/ast/inspector/inspector.go @@ -13,10 +13,19 @@ // This representation is sometimes called a "balanced parenthesis tree." // // Experiments suggest the inspector's traversals are about 2.5x faster -// than ast.Inspect, but it may take around 5 traversals for this +// than [ast.Inspect], but it may take around 5 traversals for this // benefit to amortize the inspector's construction cost. // If efficiency is the primary concern, do not use Inspector for // one-off traversals. +// +// The [Cursor] type provides a more flexible API for efficient +// navigation of syntax trees in all four "cardinal directions". For +// example, traversals may be nested, so you can find each node of +// type A and then search within it for nodes of type B. Or you can +// traverse from a node to its immediate neighbors: its parent, its +// previous and next sibling, or its first and last child. We +// recommend using methods of Cursor in preference to Inspector where +// possible. package inspector // There are four orthogonal features in a traversal: @@ -37,9 +46,8 @@ package inspector import ( "go/ast" - _ "unsafe" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) // An Inspector provides methods for inspecting @@ -48,18 +56,12 @@ type Inspector struct { events []event } -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *Inspector) []event { return in.events } - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex func packEdgeKindAndIndex(ek edge.Kind, index int) int32 { return int32(uint32(index+1)<<7 | uint32(ek)) } // unpackEdgeKindAndIndex unpacks the edge kind and edge index (within // an []ast.Node slice) from the parent field of a pop event. -// -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) { // The "parent" field of a pop node holds the // edge Kind in the lower 7 bits and the index+1 @@ -83,15 +85,21 @@ type event struct { // TODO: Experiment with storing only the second word of event.node (unsafe.Pointer). // Type can be recovered from the sole bit in typ. +// [Tried this, wasn't faster. --adonovan] // Preorder visits all the nodes of the files supplied to New in // depth-first order. It calls f(n) for each node n before it visits // n's children. // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Preorder] method provides a richer alternative interface. +// Example: +// +// for c := range in.Root().Preorder(types) { ... } func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // Because it avoids postorder calls to f, and the pruning // check, Preorder is almost twice as fast as Nodes. The two @@ -131,10 +139,18 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // of the non-nil children of the node, followed by a call of // f(n, false). // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f if is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// ... +// return true +// } func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) { mask := maskOf(types) for i := int32(0); i < int32(len(in.events)); { @@ -168,6 +184,15 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proc // supplies each call to f an additional argument, the current // traversal stack. The stack's first element is the outermost node, // an *ast.File; its last is the innermost, n. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// stack := slices.Collect(c.Enclosing()) +// ... +// return true +// }) func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) { mask := maskOf(types) var stack []ast.Node @@ -233,7 +258,7 @@ type visitor struct { type item struct { index int32 // index of current node's push event parentIndex int32 // index of parent node's push event - typAccum uint64 // accumulated type bits of current node's descendents + typAccum uint64 // accumulated type bits of current node's descendants edgeKindAndIndex int32 // edge.Kind and index, bit packed } diff --git a/notifier/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/notifier/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index e936c67c..9852331a 100644 --- a/notifier/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/notifier/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - _ "unsafe" ) const ( @@ -217,7 +215,6 @@ func typeOf(n ast.Node) uint64 { return 0 } -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf func maskOf(nodes []ast.Node) uint64 { if len(nodes) == 0 { return math.MaxUint64 // match all node types diff --git a/notifier/vendor/golang.org/x/tools/go/ast/inspector/walk.go b/notifier/vendor/golang.org/x/tools/go/ast/inspector/walk.go index 5a42174a..5f1c93c8 100644 --- a/notifier/vendor/golang.org/x/tools/go/ast/inspector/walk.go +++ b/notifier/vendor/golang.org/x/tools/go/ast/inspector/walk.go @@ -13,7 +13,7 @@ import ( "fmt" "go/ast" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) { diff --git a/notifier/vendor/golang.org/x/tools/go/callgraph/vta/graph.go b/notifier/vendor/golang.org/x/tools/go/callgraph/vta/graph.go index 26225e7d..f66f4c73 100644 --- a/notifier/vendor/golang.org/x/tools/go/callgraph/vta/graph.go +++ b/notifier/vendor/golang.org/x/tools/go/callgraph/vta/graph.go @@ -658,7 +658,7 @@ func (b *builder) call(c ssa.CallInstruction) { } func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) { - // When f has no paremeters (including receiver), there is no type + // When f has no parameters (including receiver), there is no type // flow here. Also, f's body and parameters might be missing, such // as when vta is used within the golang.org/x/tools/go/analysis // framework (see github.com/golang/go/issues/50670). @@ -803,7 +803,7 @@ func (b *builder) nodeFromVal(val ssa.Value) node { return function{f: v} case *ssa.Parameter, *ssa.FreeVar, ssa.Instruction: // ssa.Param, ssa.FreeVar, and a specific set of "register" instructions, - // satisifying the ssa.Value interface, can serve as local variables. + // satisfying the ssa.Value interface, can serve as local variables. return local{val: v} default: panic(fmt.Errorf("unsupported value %v in node creation", val)) diff --git a/notifier/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go b/notifier/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go index bdd39397..adef1282 100644 --- a/notifier/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go +++ b/notifier/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go @@ -245,7 +245,7 @@ func (b *Builder) create(leaves []*leaf) node { } else if n == 1 { return leaves[0] } - // Note: we can do a more sophisicated algorithm by: + // Note: we can do a more sophisticated algorithm by: // - sorting the leaves ahead of time, // - taking the prefix and branching bit of the min and max key, // - binary searching for the branching bit, diff --git a/notifier/vendor/golang.org/x/tools/go/loader/doc.go b/notifier/vendor/golang.org/x/tools/go/loader/doc.go index e35b1fd7..769a1fcf 100644 --- a/notifier/vendor/golang.org/x/tools/go/loader/doc.go +++ b/notifier/vendor/golang.org/x/tools/go/loader/doc.go @@ -164,7 +164,7 @@ package loader // entry is created in this cache by startLoad the first time the // package is imported. The first goroutine to request an entry becomes // responsible for completing the task and broadcasting completion to -// subsequent requestors, which block until then. +// subsequent requesters, which block until then. // // Type checking occurs in (parallel) postorder: we cannot type-check a // set of files until we have loaded and type-checked all of their diff --git a/notifier/vendor/golang.org/x/tools/go/packages/doc.go b/notifier/vendor/golang.org/x/tools/go/packages/doc.go index f1931d10..366aab6b 100644 --- a/notifier/vendor/golang.org/x/tools/go/packages/doc.go +++ b/notifier/vendor/golang.org/x/tools/go/packages/doc.go @@ -76,6 +76,8 @@ uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. +See also [golang.org/x/tools/go/packages/internal/linecount] +for an example application. # The driver protocol diff --git a/notifier/vendor/golang.org/x/tools/go/packages/golist.go b/notifier/vendor/golang.org/x/tools/go/packages/golist.go index 96e43cd8..89f89dd2 100644 --- a/notifier/vendor/golang.org/x/tools/go/packages/golist.go +++ b/notifier/vendor/golang.org/x/tools/go/packages/golist.go @@ -224,13 +224,22 @@ extractQueries: return response.dr, nil } +// abs returns an absolute representation of path, based on cfg.Dir. +func (cfg *Config) abs(path string) (string, error) { + if filepath.IsAbs(path) { + return path, nil + } + // In case cfg.Dir is relative, pass it to filepath.Abs. + return filepath.Abs(filepath.Join(cfg.Dir, path)) +} + func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { for _, query := range queries { // TODO(matloob): Do only one query per directory. fdir := filepath.Dir(query) // Pass absolute path of directory to go list so that it knows to treat it as a directory, // not a package path. - pattern, err := filepath.Abs(fdir) + pattern, err := state.cfg.abs(fdir) if err != nil { return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err) } @@ -703,9 +712,8 @@ func (state *golistState) getGoVersion() (int, error) { // getPkgPath finds the package path of a directory if it's relative to a root // directory. func (state *golistState) getPkgPath(dir string) (string, bool, error) { - absDir, err := filepath.Abs(dir) - if err != nil { - return "", false, err + if !filepath.IsAbs(dir) { + panic("non-absolute dir passed to getPkgPath") } roots, err := state.determineRootDirs() if err != nil { @@ -715,7 +723,7 @@ func (state *golistState) getPkgPath(dir string) (string, bool, error) { for rdir, rpath := range roots { // Make sure that the directory is in the module, // to avoid creating a path relative to another module. - if !strings.HasPrefix(absDir, rdir) { + if !strings.HasPrefix(dir, rdir) { continue } // TODO(matloob): This doesn't properly handle symlinks. diff --git a/notifier/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/notifier/vendor/golang.org/x/tools/go/packages/golist_overlay.go index d823c474..d9d5a45c 100644 --- a/notifier/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/notifier/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -55,7 +55,7 @@ func (state *golistState) determineRootDirsModules() (map[string]string, error) } if mod.Dir != "" && mod.Path != "" { // This is a valid module; add it to the map. - absDir, err := filepath.Abs(mod.Dir) + absDir, err := state.cfg.abs(mod.Dir) if err != nil { return nil, err } diff --git a/notifier/vendor/golang.org/x/tools/go/ssa/builder.go b/notifier/vendor/golang.org/x/tools/go/ssa/builder.go index 84ccbc09..a5ef8fb4 100644 --- a/notifier/vendor/golang.org/x/tools/go/ssa/builder.go +++ b/notifier/vendor/golang.org/x/tools/go/ssa/builder.go @@ -25,7 +25,7 @@ package ssa // populating fields such as Function.Body, .Params, and others. // // Building may create additional methods, including: -// - wrapper methods (e.g. for embeddding, or implicit &recv) +// - wrapper methods (e.g. for embedding, or implicit &recv) // - bound method closures (e.g. for use(recv.f)) // - thunks (e.g. for use(I.f) or use(T.f)) // - generic instances (e.g. to produce f[int] from f[any]). @@ -138,7 +138,7 @@ type builder struct { finished int // finished is the length of the prefix of fns containing built functions. // The task of building shared functions within the builder. - // Shared functions are ones the the builder may either create or lookup. + // Shared functions are ones the builder may either create or lookup. // These may be built by other builders in parallel. // The task is done when the builder has finished iterating, and it // waits for all shared functions to finish building. @@ -2920,6 +2920,9 @@ func (b *builder) buildParamsOnly(fn *Function) { for i, n := 0, params.Len(); i < n; i++ { fn.addParamVar(params.At(i)) } + + // clear out other function state (keep consistent with finishBody) + fn.subst = nil } // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. diff --git a/notifier/vendor/golang.org/x/tools/go/ssa/func.go b/notifier/vendor/golang.org/x/tools/go/ssa/func.go index 2d52309b..f48bd718 100644 --- a/notifier/vendor/golang.org/x/tools/go/ssa/func.go +++ b/notifier/vendor/golang.org/x/tools/go/ssa/func.go @@ -386,6 +386,8 @@ func (f *Function) finishBody() { f.results = nil // (used by lifting) f.deferstack = nil // (used by lifting) f.vars = nil // (used by lifting) + + // clear out other function state (keep consistent with buildParamsOnly) f.subst = nil numberRegisters(f) // uses f.namedRegisters diff --git a/notifier/vendor/golang.org/x/tools/go/ssa/sanity.go b/notifier/vendor/golang.org/x/tools/go/ssa/sanity.go index b11680a1..c47a137c 100644 --- a/notifier/vendor/golang.org/x/tools/go/ssa/sanity.go +++ b/notifier/vendor/golang.org/x/tools/go/ssa/sanity.go @@ -27,9 +27,10 @@ type sanity struct { } // sanityCheck performs integrity checking of the SSA representation -// of the function fn and returns true if it was valid. Diagnostics -// are written to reporter if non-nil, os.Stderr otherwise. Some -// diagnostics are only warnings and do not imply a negative result. +// of the function fn (which must have been "built") and returns true +// if it was valid. Diagnostics are written to reporter if non-nil, +// os.Stderr otherwise. Some diagnostics are only warnings and do not +// imply a negative result. // // Sanity-checking is intended to facilitate the debugging of code // transformation passes. diff --git a/notifier/vendor/golang.org/x/tools/go/ssa/subst.go b/notifier/vendor/golang.org/x/tools/go/ssa/subst.go index b4ea1685..362dce12 100644 --- a/notifier/vendor/golang.org/x/tools/go/ssa/subst.go +++ b/notifier/vendor/golang.org/x/tools/go/ssa/subst.go @@ -543,7 +543,7 @@ func (subst *subster) signature(t *types.Signature) types.Type { // We are choosing not to support tparams.Len() > 0 until a need has been observed in practice. // // There are some known usages for types.Types coming from types.{Eval,CheckExpr}. - // To support tparams.Len() > 0, we just need to do the following [psuedocode]: + // To support tparams.Len() > 0, we just need to do the following [pseudocode]: // targs := {subst.replacements[tparams[i]]]}; Instantiate(ctxt, t, targs, false) assert(tparams.Len() == 0, "Substituting types.Signatures with generic functions are currently unsupported.") diff --git a/notifier/vendor/golang.org/x/tools/go/ssa/util.go b/notifier/vendor/golang.org/x/tools/go/ssa/util.go index e53b31ff..932eb6cb 100644 --- a/notifier/vendor/golang.org/x/tools/go/ssa/util.go +++ b/notifier/vendor/golang.org/x/tools/go/ssa/util.go @@ -25,7 +25,7 @@ type unit struct{} //// Sanity checking utilities -// assert panics with the mesage msg if p is false. +// assert panics with the message msg if p is false. // Avoid combining with expensive string formatting. func assert(p bool, msg string) { if !p { diff --git a/notifier/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/notifier/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 16ed3c17..d3c2913b 100644 --- a/notifier/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/notifier/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -603,7 +603,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { type hasTypeParams interface { TypeParams() *types.TypeParamList } - // abstraction of *types.{Named,TypeParam} + // abstraction of *types.{Alias,Named,TypeParam} type hasObj interface { Obj() *types.TypeName } diff --git a/notifier/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/notifier/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index c4d10de3..e46aab02 100644 --- a/notifier/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/notifier/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -22,7 +22,6 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/cursor" "golang.org/x/tools/internal/typesinternal" ) @@ -526,7 +525,7 @@ func CanImport(from, to string) bool { func DeleteStmt(fset *token.FileSet, astFile *ast.File, stmt ast.Stmt, report func(string, ...any)) []analysis.TextEdit { // TODO: pass in the cursor to a ast.Stmt. callers should provide the Cursor insp := inspector.New([]*ast.File{astFile}) - root := cursor.Root(insp) + root := insp.Root() cstmt, ok := root.FindNode(stmt) if !ok { report("%s not found in file", stmt.Pos()) @@ -620,8 +619,8 @@ Outer: // otherwise remove the line edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()} if from.IsValid() || to.IsValid() { - // remove just the statment. - // we can't tell if there is a ; or whitespace right after the statment + // remove just the statement. + // we can't tell if there is a ; or whitespace right after the statement // ideally we'd like to remove the former and leave the latter // (if gofmt has run, there likely won't be a ;) // In type switches we know there's a semicolon somewhere after the statement, @@ -671,3 +670,14 @@ func IsStdPackage(path string) bool { } return !strings.Contains(path[:slash], ".") && path != "testdata" } + +// Range returns an [analysis.Range] for the specified start and end positions. +func Range(pos, end token.Pos) analysis.Range { + return tokenRange{pos, end} +} + +// tokenRange is an implementation of the [analysis.Range] interface. +type tokenRange struct{ StartPos, EndPos token.Pos } + +func (r tokenRange) Pos() token.Pos { return r.StartPos } +func (r tokenRange) End() token.Pos { return r.EndPos } diff --git a/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go b/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go deleted file mode 100644 index 78d874a8..00000000 --- a/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -// Package cursor augments [inspector.Inspector] with [Cursor] -// functionality allowing more flexibility and control during -// inspection. -// -// This package is a temporary private extension of inspector until -// proposal #70859 is accepted, and which point it will be moved into -// the inspector package, and [Root] will become a method of -// Inspector. -package cursor - -import ( - "fmt" - "go/ast" - "go/token" - "iter" - "reflect" - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// A Cursor represents an [ast.Node]. It is immutable. -// -// Two Cursors compare equal if they represent the same node. -// -// Call [Root] to obtain a valid cursor. -type Cursor struct { - in *inspector.Inspector - index int32 // index of push node; -1 for virtual root node -} - -// Root returns a cursor for the virtual root node, -// whose children are the files provided to [New]. -// -// Its [Cursor.Node] and [Cursor.Stack] methods return nil. -func Root(in *inspector.Inspector) Cursor { - return Cursor{in, -1} -} - -// At returns the cursor at the specified index in the traversal, -// which must have been obtained from [Cursor.Index] on a Cursor -// belonging to the same Inspector (see [Cursor.Inspector]). -func At(in *inspector.Inspector, index int32) Cursor { - if index < 0 { - panic("negative index") - } - events := events(in) - if int(index) >= len(events) { - panic("index out of range for this inspector") - } - if events[index].index < index { - panic("invalid index") // (a push, not a pop) - } - return Cursor{in, index} -} - -// Inspector returns the cursor's Inspector. -func (c Cursor) Inspector() *inspector.Inspector { return c.in } - -// Index returns the index of this cursor position within the package. -// -// Clients should not assume anything about the numeric Index value -// except that it increases monotonically throughout the traversal. -// It is provided for use with [At]. -// -// Index must not be called on the Root node. -func (c Cursor) Index() int32 { - if c.index < 0 { - panic("Index called on Root node") - } - return c.index -} - -// Node returns the node at the current cursor position, -// or nil for the cursor returned by [Inspector.Root]. -func (c Cursor) Node() ast.Node { - if c.index < 0 { - return nil - } - return c.events()[c.index].node -} - -// String returns information about the cursor's node, if any. -func (c Cursor) String() string { - if c.in == nil { - return "(invalid)" - } - if c.index < 0 { - return "(root)" - } - return reflect.TypeOf(c.Node()).String() -} - -// indices return the [start, end) half-open interval of event indices. -func (c Cursor) indices() (int32, int32) { - if c.index < 0 { - return 0, int32(len(c.events())) // root: all events - } else { - return c.index, c.events()[c.index].index + 1 // just one subtree - } -} - -// Preorder returns an iterator over the nodes of the subtree -// represented by c in depth-first order. Each node in the sequence is -// represented by a Cursor that allows access to the Node, but may -// also be used to start a new traversal, or to obtain the stack of -// nodes enclosing the cursor. -// -// The traversal sequence is determined by [ast.Inspect]. The types -// argument, if non-empty, enables type-based filtering of events. The -// function f if is called only for nodes whose type matches an -// element of the types slice. -// -// If you need control over descent into subtrees, -// or need both pre- and post-order notifications, use [Cursor.Inspect] -func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain types: skip. - i = pop + 1 - continue - } - } - i++ - } - } -} - -// Inspect visits the nodes of the subtree represented by c in -// depth-first order. It calls f(n) for each node n before it -// visits n's children. If f returns true, Inspect invokes f -// recursively for each of the non-nil children of the node. -// -// Each node is represented by a Cursor that allows access to the -// Node, but may also be used to start a new traversal, or to obtain -// the stack of nodes enclosing the cursor. -// -// The complete traversal sequence is determined by [ast.Inspect]. -// The types argument, if non-empty, enables type-based filtering of -// events. The function f if is called only for nodes whose type -// matches an element of the types slice. -func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { - mask := maskOf(types) - events := c.events() - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { - // push - pop := ev.index - if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || - events[pop].typ&mask == 0 { - // The user opted not to descend, or the - // subtree does not contain types: - // skip past the pop. - i = pop + 1 - continue - } - } - i++ - } -} - -// Enclosing returns an iterator over the nodes enclosing the current -// current node, starting with the Cursor itself. -// -// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// The types argument, if non-empty, enables type-based filtering of -// events: the sequence includes only enclosing nodes whose type -// matches an element of the types slice. -func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { - if c.index < 0 { - panic("Cursor.Enclosing called on Root node") - } - - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - for i := c.index; i >= 0; i = events[i].parent { - if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - } - } -} - -// Parent returns the parent of the current node. -// -// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Parent() Cursor { - if c.index < 0 { - panic("Cursor.Parent called on Root node") - } - - return Cursor{c.in, c.events()[c.index].parent} -} - -// ParentEdge returns the identity of the field in the parent node -// that holds this cursor's node, and if it is a list, the index within it. -// -// For example, f(x, y) is a CallExpr whose three children are Idents. -// f has edge kind [edge.CallExpr_Fun] and index -1. -// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. -// -// If called on a child of the Root node, it returns ([edge.Invalid], -1). -// -// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) ParentEdge() (edge.Kind, int) { - if c.index < 0 { - panic("Cursor.ParentEdge called on Root node") - } - events := c.events() - pop := events[c.index].index - return unpackEdgeKindAndIndex(events[pop].parent) -} - -// ChildAt returns the cursor for the child of the -// current node identified by its edge and index. -// The index must be -1 if the edge.Kind is not a slice. -// The indicated child node must exist. -// -// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. -func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { - target := packEdgeKindAndIndex(k, idx) - - // Unfortunately there's no shortcut to looping. - events := c.events() - i := c.index + 1 - for { - pop := events[i].index - if pop < i { - break - } - if events[pop].parent == target { - return Cursor{c.in, i} - } - i = pop + 1 - } - panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) -} - -// Child returns the cursor for n, which must be a direct child of c's Node. -// -// Child must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Child(n ast.Node) Cursor { - if c.index < 0 { - panic("Cursor.Child called on Root node") - } - - if false { - // reference implementation - for child := range c.Children() { - if child.Node() == n { - return child - } - } - - } else { - // optimized implementation - events := c.events() - for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { - if events[i].node == n { - return Cursor{c.in, i} - } - } - } - panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) -} - -// NextSibling returns the cursor for the next sibling node in the same list -// (for example, of files, decls, specs, statements, fields, or expressions) as -// the current node. It returns (zero, false) if the node is the last node in -// the list, or is not part of a list. -// -// NextSibling must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) NextSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.NextSibling called on Root node") - } - - events := c.events() - i := events[c.index].index + 1 // after corresponding pop - if i < int32(len(events)) { - if events[i].index > i { // push? - return Cursor{c.in, i}, true - } - } - return Cursor{}, false -} - -// PrevSibling returns the cursor for the previous sibling node in the -// same list (for example, of files, decls, specs, statements, fields, -// or expressions) as the current node. It returns zero if the node is -// the first node in the list, or is not part of a list. -// -// It must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) PrevSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.PrevSibling called on Root node") - } - - events := c.events() - i := c.index - 1 - if i >= 0 { - if j := events[i].index; j < i { // pop? - return Cursor{c.in, j}, true - } - } - return Cursor{}, false -} - -// FirstChild returns the first direct child of the current node, -// or zero if it has no children. -func (c Cursor) FirstChild() (Cursor, bool) { - events := c.events() - i := c.index + 1 // i=0 if c is root - if i < int32(len(events)) && events[i].index > i { // push? - return Cursor{c.in, i}, true - } - return Cursor{}, false -} - -// LastChild returns the last direct child of the current node, -// or zero if it has no children. -func (c Cursor) LastChild() (Cursor, bool) { - events := c.events() - if c.index < 0 { // root? - if len(events) > 0 { - // return push of final event (a pop) - return Cursor{c.in, events[len(events)-1].index}, true - } - } else { - j := events[c.index].index - 1 // before corresponding pop - // Inv: j == c.index if c has no children - // or j is last child's pop. - if j > c.index { // c has children - return Cursor{c.in, events[j].index}, true - } - } - return Cursor{}, false -} - -// Children returns an iterator over the direct children of the -// current node, if any. -// -// When using Children, NextChild, and PrevChild, bear in mind that a -// Node's children may come from different fields, some of which may -// be lists of nodes without a distinguished intervening container -// such as [ast.BlockStmt]. -// -// For example, [ast.CaseClause] has a field List of expressions and a -// field Body of statements, so the children of a CaseClause are a mix -// of expressions and statements. Other nodes that have "uncontained" -// list fields include: -// -// - [ast.ValueSpec] (Names, Values) -// - [ast.CompositeLit] (Type, Elts) -// - [ast.IndexListExpr] (X, Indices) -// - [ast.CallExpr] (Fun, Args) -// - [ast.AssignStmt] (Lhs, Rhs) -// -// So, do not assume that the previous sibling of an ast.Stmt is also -// an ast.Stmt, or if it is, that they are executed sequentially, -// unless you have established that, say, its parent is a BlockStmt -// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. -// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, -// even though they are not executed in sequence. -func (c Cursor) Children() iter.Seq[Cursor] { - return func(yield func(Cursor) bool) { - c, ok := c.FirstChild() - for ok && yield(c) { - c, ok = c.NextSibling() - } - } -} - -// Contains reports whether c contains or is equal to c2. -// -// Both Cursors must belong to the same [Inspector]; -// neither may be its Root node. -func (c Cursor) Contains(c2 Cursor) bool { - if c.in != c2.in { - panic("different inspectors") - } - events := c.events() - return c.index <= c2.index && events[c2.index].index <= events[c.index].index -} - -// FindNode returns the cursor for node n if it belongs to the subtree -// rooted at c. It returns zero if n is not found. -func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { - - // FindNode is equivalent to this code, - // but more convenient and 15-20% faster: - if false { - for candidate := range c.Preorder(n) { - if candidate.Node() == n { - return candidate, true - } - } - return Cursor{}, false - } - - // TODO(adonovan): opt: should we assume Node.Pos is accurate - // and combine type-based filtering with position filtering - // like FindByPos? - - mask := maskOf([]ast.Node{n}) - events := c.events() - - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && ev.node == n { - return Cursor{c.in, i}, true - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain type of n: skip. - i = pop - } - } - } - return Cursor{}, false -} - -// FindByPos returns the cursor for the innermost node n in the tree -// rooted at c such that n.Pos() <= start && end <= n.End(). -// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) -// -// It returns zero if none is found. -// Precondition: start <= end. -// -// See also [astutil.PathEnclosingInterval], which -// tolerates adjoining whitespace. -func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { - if end < start { - panic("end < start") - } - events := c.events() - - // This algorithm could be implemented using c.Inspect, - // but it is about 2.5x slower. - - best := int32(-1) // push index of latest (=innermost) node containing range - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - n := ev.node - var nodeEnd token.Pos - if file, ok := n.(*ast.File); ok { - nodeEnd = file.FileEnd - // Note: files may be out of Pos order. - if file.FileStart > start { - i = ev.index // disjoint, after; skip to next file - continue - } - } else { - nodeEnd = n.End() - if n.Pos() > start { - break // disjoint, after; stop - } - } - // Inv: node.{Pos,FileStart} <= start - if end <= nodeEnd { - // node fully contains target range - best = i - } else if nodeEnd < start { - i = ev.index // disjoint, before; skip forward - } - } - } - if best >= 0 { - return Cursor{c.in, best}, true - } - return Cursor{}, false -} diff --git a/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go b/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go deleted file mode 100644 index 0257d61d..00000000 --- a/notifier/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -package cursor - -import ( - "go/ast" - _ "unsafe" // for go:linkname - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// This file defines backdoor access to inspector. - -// Copied from inspector.event; must remain in sync. -// (Note that the linkname effects a type coercion too.) -type event struct { - node ast.Node - typ uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events - index int32 // index of corresponding push or pop event (relative to this event's index, +ve=push, -ve=pop) - parent int32 // index of parent's push node (push nodes only); or edge and index, bit packed (pop nodes only) -} - -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf -func maskOf(nodes []ast.Node) uint64 - -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *inspector.Inspector) []event - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex -func packEdgeKindAndIndex(edge.Kind, int) int32 - -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex -func unpackEdgeKindAndIndex(int32) (edge.Kind, int) - -func (c Cursor) events() []event { return events(c.in) } diff --git a/notifier/vendor/golang.org/x/tools/internal/astutil/util.go b/notifier/vendor/golang.org/x/tools/internal/astutil/util.go index 1862668a..f06dbda3 100644 --- a/notifier/vendor/golang.org/x/tools/internal/astutil/util.go +++ b/notifier/vendor/golang.org/x/tools/internal/astutil/util.go @@ -71,6 +71,8 @@ func PosInStringLiteral(lit *ast.BasicLit, offset int) (token.Pos, error) { // In practice, the second call is nearly always used only to pop the // stack, and it is surprisingly tricky to do this correctly; see // https://go.dev/issue/73319. +// +// TODO(adonovan): replace with [ast.PreorderStack] when go1.25 is assured. func PreorderStack(root ast.Node, stack []ast.Node, f func(n ast.Node, stack []ast.Node) bool) { before := len(stack) ast.Inspect(root, func(n ast.Node) bool { diff --git a/notifier/vendor/golang.org/x/tools/internal/imports/fix.go b/notifier/vendor/golang.org/x/tools/internal/imports/fix.go index 89b96381..50b6ca51 100644 --- a/notifier/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/notifier/vendor/golang.org/x/tools/internal/imports/fix.go @@ -27,12 +27,13 @@ import ( "unicode" "unicode/utf8" + "maps" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/stdlib" - "maps" ) // importToGroup is a list of functions which map from an import path to @@ -290,8 +291,8 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro return nil } -// if there is a trailing major version, remove it -func withoutVersion(nm string) string { +// WithoutVersion removes a trailing major version, if there is one. +func WithoutVersion(nm string) string { if v := path.Base(nm); len(v) > 0 && v[0] == 'v' { if _, err := strconv.Atoi(v[1:]); err == nil { // this is, for instance, called with rand/v2 and returns rand @@ -313,7 +314,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { } known := p.knownPackages[imp.ImportPath] if known != nil && known.Name != "" { - return withoutVersion(known.Name) + return WithoutVersion(known.Name) } return ImportPathToAssumedName(imp.ImportPath) } diff --git a/notifier/vendor/golang.org/x/tools/internal/imports/imports.go b/notifier/vendor/golang.org/x/tools/internal/imports/imports.go index 2215a128..b5f5218b 100644 --- a/notifier/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/notifier/vendor/golang.org/x/tools/internal/imports/imports.go @@ -93,7 +93,7 @@ func FixImports(ctx context.Context, filename string, src []byte, goroot string, // env is needed. func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) { // Don't use parse() -- we don't care about fragments or statement lists - // here, and we need to work with unparseable files. + // here, and we need to work with unparsable files. fileSet := token.NewFileSet() parserMode := parser.SkipObjectResolution if opt.Comments { diff --git a/notifier/vendor/golang.org/x/tools/internal/imports/source_modindex.go b/notifier/vendor/golang.org/x/tools/internal/imports/source_modindex.go index 05229f06..ca745d4a 100644 --- a/notifier/vendor/golang.org/x/tools/internal/imports/source_modindex.go +++ b/notifier/vendor/golang.org/x/tools/internal/imports/source_modindex.go @@ -15,6 +15,10 @@ import ( // This code is here rather than in the modindex package // to avoid import loops +// TODO(adonovan): this code is only used by a test in this package. +// Can we delete it? Or is there a plan to call NewIndexSource from +// cmd/goimports? + // implements Source using modindex, so only for module cache. // // this is perhaps over-engineered. A new Index is read at first use. @@ -22,8 +26,8 @@ import ( // is read if the index changed. It is not clear the Mutex is needed. type IndexSource struct { modcachedir string - mutex sync.Mutex - ix *modindex.Index + mu sync.Mutex + index *modindex.Index // (access via getIndex) expires time.Time } @@ -39,13 +43,14 @@ func (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths } func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) { - if err := s.maybeReadIndex(); err != nil { + index, err := s.getIndex() + if err != nil { return nil, err } var cs []modindex.Candidate for pkg, nms := range missing { for nm := range nms { - x := s.ix.Lookup(pkg, nm, false) + x := index.Lookup(pkg, nm, false) cs = append(cs, x...) } } @@ -74,30 +79,22 @@ func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, mi return ans, nil } -func (s *IndexSource) maybeReadIndex() error { - s.mutex.Lock() - defer s.mutex.Unlock() - - var readIndex bool - if time.Now().After(s.expires) { - ok, err := modindex.Update(s.modcachedir) - if err != nil { - return err - } - if ok { - readIndex = true - } - } +func (s *IndexSource) getIndex() (*modindex.Index, error) { + s.mu.Lock() + defer s.mu.Unlock() - if readIndex || s.ix == nil { - ix, err := modindex.ReadIndex(s.modcachedir) + // (s.index = nil => s.expires is zero, + // so the first condition is strictly redundant. + // But it makes the postcondition very clear.) + if s.index == nil || time.Now().After(s.expires) { + index, err := modindex.Update(s.modcachedir) if err != nil { - return err + return nil, err } - s.ix = ix - // for now refresh every 15 minutes - s.expires = time.Now().Add(time.Minute * 15) + s.index = index + s.expires = index.ValidAt.Add(15 * time.Minute) // (refresh period) } + // Inv: s.index != nil - return nil + return s.index, nil } diff --git a/notifier/vendor/golang.org/x/tools/internal/modindex/directories.go b/notifier/vendor/golang.org/x/tools/internal/modindex/directories.go index 1e1a02f2..9a963744 100644 --- a/notifier/vendor/golang.org/x/tools/internal/modindex/directories.go +++ b/notifier/vendor/golang.org/x/tools/internal/modindex/directories.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "regexp" - "slices" "strings" "sync" "time" @@ -20,50 +19,48 @@ import ( ) type directory struct { - path Relpath + path string // relative to GOMODCACHE importPath string version string // semantic version - syms []symbol } -// filterDirs groups the directories by import path, -// sorting the ones with the same import path by semantic version, -// most recent first. -func byImportPath(dirs []Relpath) (map[string][]*directory, error) { - ans := make(map[string][]*directory) // key is import path - for _, d := range dirs { - ip, sv, err := DirToImportPathVersion(d) +// bestDirByImportPath returns the best directory for each import +// path, where "best" means most recent semantic version. These import +// paths are inferred from the GOMODCACHE-relative dir names in dirs. +func bestDirByImportPath(dirs []string) (map[string]directory, error) { + dirsByPath := make(map[string]directory) + for _, dir := range dirs { + importPath, version, err := dirToImportPathVersion(dir) if err != nil { return nil, err } - ans[ip] = append(ans[ip], &directory{ - path: d, - importPath: ip, - version: sv, - }) - } - for k, v := range ans { - semanticSort(v) - ans[k] = v + new := directory{ + path: dir, + importPath: importPath, + version: version, + } + if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 { + dirsByPath[importPath] = new + } } - return ans, nil + return dirsByPath, nil } -// sort the directories by semantic version, latest first -func semanticSort(v []*directory) { - slices.SortFunc(v, func(l, r *directory) int { - if n := semver.Compare(l.version, r.version); n != 0 { - return -n // latest first - } - return strings.Compare(string(l.path), string(r.path)) - }) +// compareDirectory defines an ordering of path@version directories, +// by descending version, then by ascending path. +func compareDirectory(x, y directory) int { + if sign := -semver.Compare(x.version, y.version); sign != 0 { + return sign // latest first + } + return strings.Compare(string(x.path), string(y.path)) } // modCacheRegexp splits a relpathpath into module, module version, and package. var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`) -// DirToImportPathVersion computes import path and semantic version -func DirToImportPathVersion(dir Relpath) (string, string, error) { +// dirToImportPathVersion computes import path and semantic version +// from a GOMODCACHE-relative directory name. +func dirToImportPathVersion(dir string) (string, string, error) { m := modCacheRegexp.FindStringSubmatch(string(dir)) // m[1] is the module path // m[2] is the version major.minor.patch(-

 that contains the name
+// Package modindex contains code for building and searching an
+// [Index] of the Go module cache.
+package modindex
+
+// The directory containing the index, returned by
+// [IndexDir], contains a file index-name- that contains the name
 // of the current index. We believe writing that short file is atomic.
-// ReadIndex reads that file to get the file name of the index.
+// [Read] reads that file to get the file name of the index.
 // WriteIndex writes an index with a unique name and then
 // writes that name into a new version of index-name-.
 // ( stands for the CurrentVersion of the index format.)
-package modindex
 
 import (
+	"maps"
+	"os"
 	"path/filepath"
 	"slices"
 	"strings"
@@ -21,144 +25,95 @@ import (
 	"golang.org/x/mod/semver"
 )
 
-// Create always creates a new index for the go module cache that is in cachedir.
-func Create(cachedir string) error {
-	_, err := indexModCache(cachedir, true)
-	return err
-}
-
-// Update the index for the go module cache that is in cachedir,
-// If there is no existing index it will build one.
-// If there are changed directories since the last index, it will
-// write a new one and return true. Otherwise it returns false.
-func Update(cachedir string) (bool, error) {
-	return indexModCache(cachedir, false)
+// Update updates the index for the specified Go
+// module cache directory, creating it as needed.
+// On success it returns the current index.
+func Update(gomodcache string) (*Index, error) {
+	prev, err := Read(gomodcache)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return nil, err
+		}
+		prev = nil
+	}
+	return update(gomodcache, prev)
 }
 
-// indexModCache writes an index current as of when it is called.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and the updates to the cache. It returns true if it wrote an index,
-// false otherwise.
-func indexModCache(cachedir string, clear bool) (bool, error) {
-	cachedir, err := filepath.Abs(cachedir)
+// update builds, writes, and returns the current index.
+//
+// If old is nil, the new index is built from all of GOMODCACHE;
+// otherwise it is built from the old index plus cache updates
+// since the previous index's time.
+func update(gomodcache string, old *Index) (*Index, error) {
+	gomodcache, err := filepath.Abs(gomodcache)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	cd := Abspath(cachedir)
-	future := time.Now().Add(24 * time.Hour) // safely in the future
-	ok, err := modindexTimed(future, cd, clear)
+	new, changed, err := build(gomodcache, old)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	return ok, nil
-}
-
-// modindexTimed writes an index current as of onlyBefore.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and all the updates to the cache before onlyBefore.
-// It returns true if it wrote a new index, false if it wrote nothing.
-func modindexTimed(onlyBefore time.Time, cachedir Abspath, clear bool) (bool, error) {
-	var curIndex *Index
-	if !clear {
-		var err error
-		curIndex, err = ReadIndex(string(cachedir))
-		if clear && err != nil {
-			return false, err
+	if old == nil || changed {
+		if err := write(gomodcache, new); err != nil {
+			return nil, err
 		}
-		// TODO(pjw): check that most of those directories still exist
-	}
-	cfg := &work{
-		onlyBefore: onlyBefore,
-		oldIndex:   curIndex,
-		cacheDir:   cachedir,
-	}
-	if curIndex != nil {
-		cfg.onlyAfter = curIndex.Changed
-	}
-	if err := cfg.buildIndex(); err != nil {
-		return false, err
 	}
-	if len(cfg.newIndex.Entries) == 0 && curIndex != nil {
-		// no changes from existing curIndex, don't write a new index
-		return false, nil
-	}
-	if err := cfg.writeIndex(); err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-type work struct {
-	onlyBefore time.Time // do not use directories later than this
-	onlyAfter  time.Time // only interested in directories after this
-	// directories from before onlyAfter come from oldIndex
-	oldIndex *Index
-	newIndex *Index
-	cacheDir Abspath
+	return new, nil
 }
 
-func (w *work) buildIndex() error {
-	// The effective date of the new index should be at least
-	// slightly earlier than when the directories are scanned
-	// so set it now.
-	w.newIndex = &Index{Changed: time.Now(), Cachedir: w.cacheDir}
-	dirs := findDirs(string(w.cacheDir), w.onlyAfter, w.onlyBefore)
-	if len(dirs) == 0 {
-		return nil
+// build returns a new index for the specified Go module cache (an
+// absolute path).
+//
+// If an old index is provided, only directories more recent than it
+// that it are scanned; older directories are provided by the old
+// Index.
+//
+// The boolean result indicates whether new entries were found.
+func build(gomodcache string, old *Index) (*Index, bool, error) {
+	// Set the time window.
+	var start time.Time // = dawn of time
+	if old != nil {
+		start = old.ValidAt
 	}
-	newdirs, err := byImportPath(dirs)
+	now := time.Now()
+	end := now.Add(24 * time.Hour) // safely in the future
+
+	// Enumerate GOMODCACHE package directories.
+	// Choose the best (latest) package for each import path.
+	pkgDirs := findDirs(gomodcache, start, end)
+	dirByPath, err := bestDirByImportPath(pkgDirs)
 	if err != nil {
-		return err
+		return nil, false, err
 	}
-	// for each import path it might occur only in newdirs,
-	// only in w.oldIndex, or in both.
-	// If it occurs in both, use the semantically later one
-	if w.oldIndex != nil {
-		for _, e := range w.oldIndex.Entries {
-			found, ok := newdirs[e.ImportPath]
-			if !ok {
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				continue // use this one, there is no new one
-			}
-			if semver.Compare(found[0].version, e.Version) > 0 {
-				// use the new one
-			} else {
-				// use the old one, forget the new one
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				delete(newdirs, e.ImportPath)
+
+	// For each import path it might occur only in
+	// dirByPath, only in old, or in both.
+	// If both, use the semantically later one.
+	var entries []Entry
+	if old != nil {
+		for _, entry := range old.Entries {
+			dir, ok := dirByPath[entry.ImportPath]
+			if !ok || semver.Compare(dir.version, entry.Version) <= 0 {
+				// New dir is missing or not more recent; use old entry.
+				entries = append(entries, entry)
+				delete(dirByPath, entry.ImportPath)
 			}
 		}
 	}
-	// get symbol information for all the new diredtories
-	getSymbols(w.cacheDir, newdirs)
-	// assemble the new index entries
-	for k, v := range newdirs {
-		d := v[0]
-		pkg, names := processSyms(d.syms)
-		if pkg == "" {
-			continue // PJW: does this ever happen?
-		}
-		entry := Entry{
-			PkgName:    pkg,
-			Dir:        d.path,
-			ImportPath: k,
-			Version:    d.version,
-			Names:      names,
-		}
-		w.newIndex.Entries = append(w.newIndex.Entries, entry)
-	}
-	// sort the entries in the new index
-	slices.SortFunc(w.newIndex.Entries, func(l, r Entry) int {
-		if n := strings.Compare(l.PkgName, r.PkgName); n != 0 {
+
+	// Extract symbol information for all the new directories.
+	newEntries := extractSymbols(gomodcache, maps.Values(dirByPath))
+	entries = append(entries, newEntries...)
+	slices.SortFunc(entries, func(x, y Entry) int {
+		if n := strings.Compare(x.PkgName, y.PkgName); n != 0 {
 			return n
 		}
-		return strings.Compare(l.ImportPath, r.ImportPath)
+		return strings.Compare(x.ImportPath, y.ImportPath)
 	})
-	return nil
-}
 
-func (w *work) writeIndex() error {
-	return writeIndex(w.cacheDir, w.newIndex)
+	return &Index{
+		GOMODCACHE: gomodcache,
+		ValidAt:    now, // time before the directories were scanned
+		Entries:    entries,
+	}, len(newEntries) > 0, nil
 }
diff --git a/notifier/vendor/golang.org/x/tools/internal/modindex/symbols.go b/notifier/vendor/golang.org/x/tools/internal/modindex/symbols.go
index b918529d..fe24db9b 100644
--- a/notifier/vendor/golang.org/x/tools/internal/modindex/symbols.go
+++ b/notifier/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -10,11 +10,13 @@ import (
 	"go/parser"
 	"go/token"
 	"go/types"
+	"iter"
 	"os"
 	"path/filepath"
 	"runtime"
 	"slices"
 	"strings"
+	"sync"
 
 	"golang.org/x/sync/errgroup"
 )
@@ -30,45 +32,69 @@ import (
 type symbol struct {
 	pkg  string // name of the symbols's package
 	name string // declared name
-	kind string // T, C, V, or F, follwed by D if deprecated
+	kind string // T, C, V, or F, followed by D if deprecated
 	sig  string // signature information, for F
 }
 
-// find the symbols for the best directories
-func getSymbols(cd Abspath, dirs map[string][]*directory) {
+// extractSymbols returns a (new, unordered) array of Entries, one for
+// each provided package directory, describing its exported symbols.
+func extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {
+	var (
+		mu      sync.Mutex
+		entries []Entry
+	)
+
 	var g errgroup.Group
 	g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
-	for _, vv := range dirs {
-		// throttling some day?
-		d := vv[0]
+	for dir := range dirs {
 		g.Go(func() error {
-			thedir := filepath.Join(string(cd), string(d.path))
+			thedir := filepath.Join(cwd, string(dir.path))
 			mode := parser.SkipObjectResolution | parser.ParseComments
 
-			fi, err := os.ReadDir(thedir)
+			// Parse all Go files in dir and extract symbols.
+			dirents, err := os.ReadDir(thedir)
 			if err != nil {
 				return nil // log this someday?
 			}
-			for _, fx := range fi {
-				if !strings.HasSuffix(fx.Name(), ".go") || strings.HasSuffix(fx.Name(), "_test.go") {
+			var syms []symbol
+			for _, dirent := range dirents {
+				if !strings.HasSuffix(dirent.Name(), ".go") ||
+					strings.HasSuffix(dirent.Name(), "_test.go") {
 					continue
 				}
-				fname := filepath.Join(thedir, fx.Name())
+				fname := filepath.Join(thedir, dirent.Name())
 				tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
 				if err != nil {
 					continue // ignore errors, someday log them?
 				}
-				d.syms = append(d.syms, getFileExports(tr)...)
+				syms = append(syms, getFileExports(tr)...)
+			}
+
+			// Create an entry for the package.
+			pkg, names := processSyms(syms)
+			if pkg != "" {
+				mu.Lock()
+				defer mu.Unlock()
+				entries = append(entries, Entry{
+					PkgName:    pkg,
+					Dir:        dir.path,
+					ImportPath: dir.importPath,
+					Version:    dir.version,
+					Names:      names,
+				})
 			}
+
 			return nil
 		})
 	}
-	g.Wait()
+	g.Wait() // ignore error
+
+	return entries
 }
 
 func getFileExports(f *ast.File) []symbol {
 	pkg := f.Name.Name
-	if pkg == "main" {
+	if pkg == "main" || pkg == "" {
 		return nil
 	}
 	var ans []symbol
@@ -110,7 +136,7 @@ func getFileExports(f *ast.File) []symbol {
 				// The only place a $ can occur seems to be in a struct tag, which
 				// can be an arbitrary string literal, and ExprString does not presently
 				// print struct tags. So for this to happen the type of a formal parameter
-				// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
+				// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
 				// would have to show the struct tag. Even testing for this case seems
 				// a waste of effort, but let's remember the possibility
 				if strings.Contains(tp, "$") {
@@ -202,17 +228,18 @@ func processSyms(syms []symbol) (string, []string) {
 	pkg := syms[0].pkg
 	var names []string
 	for _, s := range syms {
+		if s.pkg != pkg {
+			// Symbols came from two files in same dir
+			// with different package declarations.
+			continue
+		}
 		var nx string
-		if s.pkg == pkg {
-			if s.sig != "" {
-				nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
-			} else {
-				nx = fmt.Sprintf("%s %s", s.name, s.kind)
-			}
-			names = append(names, nx)
+		if s.sig != "" {
+			nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
 		} else {
-			continue // PJW: do we want to keep track of these?
+			nx = fmt.Sprintf("%s %s", s.name, s.kind)
 		}
+		names = append(names, nx)
 	}
 	return pkg, names
 }
diff --git a/notifier/vendor/golang.org/x/tools/internal/modindex/types.go b/notifier/vendor/golang.org/x/tools/internal/modindex/types.go
deleted file mode 100644
index ece44886..00000000
--- a/notifier/vendor/golang.org/x/tools/internal/modindex/types.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modindex
-
-import (
-	"strings"
-)
-
-// some special types to avoid confusions
-
-// distinguish various types of directory names. It's easy to get confused.
-type Abspath string // absolute paths
-type Relpath string // paths with GOMODCACHE prefix removed
-
-func toRelpath(cachedir Abspath, s string) Relpath {
-	if strings.HasPrefix(s, string(cachedir)) {
-		if s == string(cachedir) {
-			return Relpath("")
-		}
-		return Relpath(s[len(cachedir)+1:])
-	}
-	return Relpath(s)
-}
diff --git a/notifier/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/notifier/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 73eefa2a..929b470b 100644
--- a/notifier/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/notifier/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -5,6 +5,8 @@
 // Package packagesinternal exposes internal-only fields from go/packages.
 package packagesinternal
 
+import "fmt"
+
 var GetDepsErrors = func(p any) []*PackageError { return nil }
 
 type PackageError struct {
@@ -13,5 +15,9 @@ type PackageError struct {
 	Err         string   // the error itself
 }
 
+func (err PackageError) String() string {
+	return fmt.Sprintf("%s: %s (import stack: %s)", err.Pos, err.Err, err.ImportStack)
+}
+
 var TypecheckCgo int
 var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
diff --git a/notifier/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go b/notifier/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
index 649c82b6..3db2a135 100644
--- a/notifier/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
+++ b/notifier/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
@@ -65,14 +65,16 @@ func ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {
 	if info.Types == nil {
 		panic("ClassifyCall: info.Types is nil")
 	}
-	if info.Types[call.Fun].IsType() {
+	tv := info.Types[call.Fun]
+	if tv.IsType() {
 		return CallConversion
 	}
+	if tv.IsBuiltin() {
+		return CallBuiltin
+	}
 	obj := info.Uses[UsedIdent(info, call.Fun)]
 	// Classify the call by the type of the object, if any.
 	switch obj := obj.(type) {
-	case *types.Builtin:
-		return CallBuiltin
 	case *types.Func:
 		if interfaceMethod(obj) {
 			return CallInterface
diff --git a/notifier/vendor/golang.org/x/tools/internal/typesinternal/types.go b/notifier/vendor/golang.org/x/tools/internal/typesinternal/types.go
index cc244689..a5cd7e8d 100644
--- a/notifier/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/notifier/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -69,6 +69,34 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 	}
 }
 
+// TypeNameFor returns the type name symbol for the specified type, if
+// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a
+// [*types.Basic] representing a type.
+//
+// For all other types, and for Basic types representing a builtin,
+// constant, or nil, it returns nil. Be careful not to convert the
+// resulting nil pointer to a [types.Object]!
+//
+// If t is the type of a constant, it may be an "untyped" type, which
+// has no TypeName. To access the name of such types (e.g. "untyped
+// int"), use [types.Basic.Name].
+func TypeNameFor(t types.Type) *types.TypeName {
+	switch t := t.(type) {
+	case *types.Alias:
+		return t.Obj()
+	case *types.Named:
+		return t.Obj()
+	case *types.TypeParam:
+		return t.Obj()
+	case *types.Basic:
+		// See issues #71886 and #66890 for some history.
+		if tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {
+			return tname
+		}
+	}
+	return nil
+}
+
 // A NamedOrAlias is a [types.Type] that is named (as
 // defined by the spec) and capable of bearing type parameters: it
 // abstracts aliases ([types.Alias]) and defined types
@@ -77,7 +105,7 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 // Every type declared by an explicit "type" declaration is a
 // NamedOrAlias. (Built-in type symbols may additionally
 // have type [types.Basic], which is not a NamedOrAlias,
-// though the spec regards them as "named".)
+// though the spec regards them as "named"; see [TypeNameFor].)
 //
 // NamedOrAlias cannot expose the Origin method, because
 // [types.Alias.Origin] and [types.Named.Origin] have different
@@ -85,32 +113,15 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 type NamedOrAlias interface {
 	types.Type
 	Obj() *types.TypeName
-	// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
-}
-
-// TypeParams is a light shim around t.TypeParams().
-// (go/types.Alias).TypeParams requires >= 1.23.
-func TypeParams(t NamedOrAlias) *types.TypeParamList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeParams(t)
-	case *types.Named:
-		return t.TypeParams()
-	}
-	return nil
+	TypeArgs() *types.TypeList
+	TypeParams() *types.TypeParamList
+	SetTypeParams(tparams []*types.TypeParam)
 }
 
-// TypeArgs is a light shim around t.TypeArgs().
-// (go/types.Alias).TypeArgs requires >= 1.23.
-func TypeArgs(t NamedOrAlias) *types.TypeList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeArgs(t)
-	case *types.Named:
-		return t.TypeArgs()
-	}
-	return nil
-}
+var (
+	_ NamedOrAlias = (*types.Alias)(nil)
+	_ NamedOrAlias = (*types.Named)(nil)
+)
 
 // Origin returns the generic type of the Named or Alias type t if it
 // is instantiated, otherwise it returns t.
diff --git a/notifier/vendor/golang.org/x/vuln/LICENSE b/notifier/vendor/golang.org/x/vuln/LICENSE
index 6a66aea5..2a7cf70d 100644
--- a/notifier/vendor/golang.org/x/vuln/LICENSE
+++ b/notifier/vendor/golang.org/x/vuln/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
+Copyright 2009 The Go Authors.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
-   * Neither the name of Google Inc. nor the names of its
+   * Neither the name of Google LLC nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.
 
diff --git a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
index b7b16d9f..8de6904a 100644
--- a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
+++ b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
@@ -9,10 +9,10 @@ only those that could affect the application.
 
 By default, govulncheck makes requests to the Go vulnerability database at
 https://vuln.go.dev. Requests to the vulnerability database contain only module
-paths, not code or other properties of your program. See
-https://vuln.go.dev/privacy.html for more. Use the -db flag to specify a
-different database, which must implement the specification at
-https://go.dev/security/vuln/database.
+paths with vulnerabilities already known to the database, not code or other
+properties of your program. See https://vuln.go.dev/privacy.html for more.
+Use the -db flag to specify a different database, which must implement the
+specification at https://go.dev/security/vuln/database.
 
 Govulncheck looks for vulnerabilities in Go programs using a specific build
 configuration. For analyzing source code, that configuration is the Go version
@@ -20,8 +20,6 @@ specified by the “go” command found on the PATH. For binaries, the build
 configuration is the one used to build the binary. Note that different build
 configurations may have different known vulnerabilities.
 
-Govulncheck must be built with Go version 1.18 or later.
-
 # Usage
 
 To analyze source code, run govulncheck from the module directory, using the
@@ -41,44 +39,45 @@ To control which files are processed, use the -tags flag to provide a
 comma-separated list of build tags, and the -test flag to indicate that test
 files should be included.
 
-To run govulncheck on a compiled binary, pass it the path to the binary file
-with the -mode=binary flag:
-
-	$ govulncheck -mode=binary $HOME/go/bin/my-go-program
+To include more detailed stack traces, pass '-show traces', this will cause it to
+print the full call stack for each entry.
 
-Govulncheck uses the binary's symbol information to find mentions of vulnerable
-functions. Its output omits call stacks, which require source code analysis.
+To include progress messages and more details on findings, pass '-show verbose'.
 
-Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
-and exits unsuccessfully if there are. It also exits successfully if -json flag
-is provided, regardless of the number of detected vulnerabilities.
+To run govulncheck on a compiled binary, pass it the path to the binary file
+with the '-mode binary' flag:
 
-# Flags
+	$ govulncheck -mode binary $HOME/go/bin/my-go-program
 
-A few flags control govulncheck's behavior.
+Govulncheck uses the binary's symbol information to find mentions of vulnerable
+functions. These functions can belong to binary's transitive dependencies and
+also the main module of the binary. The latter functions are checked for only
+when the precise version of the binary module is known. Govulncheck output on
+binaries omits call stacks, which require source code analysis.
 
-The -C flag causes govulncheck to change its working directory to the provided
-directory before running. Any patterns or files named on the command line are
-interpreted after changing directories.
+Govulncheck also supports '-mode extract' on a Go binary for extraction of minimal
+information needed to analyze the binary. This will produce a blob, typically much
+smaller than the binary, that can also be passed to govulncheck as an argument with
+'-mode binary'. The users should not rely on the contents or representation of the blob.
 
-The -db flag causes govulncheck to read from the specified database, which must
-implement the specification at https://go.dev/security/vuln/database. By
-default, govulncheck fetches vulnerability data from https://vuln.go.dev.
+# Integrations
 
-The -json flag causes govulncheck to print its output as a JSON object
-corresponding to the type [golang.org/x/vuln/internal/govulncheck.Result]. The
-exit code of govulncheck is 0 when this flag is provided.
+Govulncheck supports streaming JSON. For more details, please see [golang.org/x/vuln/internal/govulncheck].
 
-The -mode flag causes govulncheck to run source or binary analysis. By default,
-govulnchecks runs source analysis.
+Govulncheck also supports Static Analysis Results Interchange Format (SARIF) output
+format, following the specification at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+For more details, please see [golang.org/x/vuln/internal/sarif].
 
-The -tags flag accepts a comma-separated list of build tags to control which
-files should be included in loaded packages for source analysis.
+Govulncheck supports the Vulnerability EXchange (VEX) output format, following
+the specification at https://github.com/openvex/spec.
+For more details, please see [golang.org/x/vuln/internal/openvex].
 
-The -test flag causes govulncheck to include test files in the source analysis.
+# Exit codes
 
-The -v flag causes govulncheck to output more information when run on source.
-It has no effect when run on a binary.
+Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
+and exits unsuccessfully if there are. It also exits successfully if the
+'format -json' ('-json'), '-format sarif', or '-format openvex' is provided,
+regardless of the number of detected vulnerabilities.
 
 # Limitations
 
@@ -88,22 +87,20 @@ Govulncheck has these limitations:
     which may result in false positives or inaccurate call stacks in some cases.
   - Calls to functions made using package reflect are not visible to static
     analysis. Vulnerable code reachable only through those calls will not be
-    reported.
+    reported in source scan mode. Similarly, use of the unsafe package may
+    result in false negatives.
   - Because Go binaries do not contain detailed call information, govulncheck
     cannot show the call graphs for detected vulnerabilities. It may also
     report false positives for code that is in the binary but unreachable.
-  - There is no support for silencing vulnerability findings.
-  - Govulncheck only reads binaries compiled with Go 1.18 and later.
-  - Govulncheck only reports vulnerabilities that apply to the current Go
-    version. For example, a standard library vulnerability that only applies for
-    Go 1.18 will not be reported if the current Go version is 1.19. See
-    https://go.dev/issue/54841 for updates to this limitation.
+  - There is no support for silencing vulnerability findings. See https://go.dev/issue/61211 for
+    updates.
+  - Govulncheck reports only standard library vulnerabilities for binaries
+    built with Go versions prior to Go 1.18.
   - For binaries where the symbol information cannot be extracted, govulncheck
     reports vulnerabilities for all modules on which the binary depends.
 
 # Feedback
 
-Govulncheck is an experimental tool under active development. To share
-feedback, see https://go.dev/security/vuln#feedback.
+To share feedback, see https://go.dev/security/vuln#feedback.
 */
 package main
diff --git a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
new file mode 100644
index 00000000..288c10c2
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
@@ -0,0 +1,12 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.23
+
+//go:debug gotypesalias=1
+
+package main
+
+// Materialize aliases whenever the go toolchain version is after 1.23 (#69772).
+// Remove this file after go.mod >= 1.23 (which implies gotypesalias=1).
diff --git a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/main.go b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
index f6ca253f..73e3370a 100644
--- a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
+++ b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
@@ -9,10 +9,13 @@ import (
 	"fmt"
 	"os"
 
+	"golang.org/x/telemetry"
 	"golang.org/x/vuln/scan"
 )
 
 func main() {
+	telemetry.Start(telemetry.Config{ReportCrashes: true})
+
 	ctx := context.Background()
 
 	cmd := scan.Command(ctx, os.Args[1:]...)
diff --git a/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
new file mode 100644
index 00000000..826d6caf
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
@@ -0,0 +1,128 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"testing"
+)
+
+// copyTestCase copies the test case at dir into a
+// temporary directory. The created files have 0644
+// permission and directories 0755. It does not create
+// symlinks.
+func copyTestCase(dir string, t *testing.T) string {
+	newDir, err := filepath.Abs(t.TempDir())
+	if err != nil {
+		t.Fatalf("failed to copy test case %s: cannot create root %v", dir, err)
+	}
+
+	if err := copyDir(dir, newDir); err != nil {
+		t.Fatalf("failed to copy test case %s: copy failure %v", dir, err)
+	}
+	return newDir
+}
+
+func copyDir(srcDir, destDir string) error {
+	entries, err := os.ReadDir(srcDir)
+	if err != nil {
+		return err
+	}
+	for _, entry := range entries {
+		src := filepath.Join(srcDir, entry.Name())
+		dest := filepath.Join(destDir, entry.Name())
+
+		fileInfo, err := os.Stat(src)
+		if err != nil {
+			return err
+		}
+
+		switch fileInfo.Mode() & os.ModeType {
+		case os.ModeDir:
+			if err := os.MkdirAll(dest, 0755); err != nil {
+				return err
+			}
+			if err := copyDir(src, dest); err != nil {
+				return err
+			}
+		default:
+			if err := copyFile(src, dest); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func copyFile(src, dest string) error {
+	b, err := os.ReadFile(src)
+	if err != nil {
+		return err
+	}
+	return os.WriteFile(dest, b, 0644)
+}
+
+type config struct {
+	// SkipGOOS is a list of GOOS to skip
+	SkipGOOS []string `json:"skipGOOS,omitempty"`
+	// Copy the folder to isolate it
+	Copy bool `json:"copy,omitempty"`
+	// SkipBuild the test case
+	SkipBuild bool `json:"skipBuild,omitempty"`
+	// Strip indicates if binaries should be stripped
+	Strip bool `json:"strip,omitempty"`
+	// EnableSBOM indicates if sbom should be
+	// printed in JSON.
+	EnableSBOM bool `json:"sbom,omitempty"`
+
+	Fixups []fixup `json:"fixups,omitempty"`
+}
+
+func (c *config) skip() bool {
+	for _, sg := range c.SkipGOOS {
+		if runtime.GOOS == sg {
+			return true
+		}
+	}
+	return false
+}
+
+type fixup struct {
+	Pattern     string `json:"pattern,omitempty"`
+	Replace     string `json:"replace,omitempty"`
+	compiled    *regexp.Regexp
+	replaceFunc func(b []byte) []byte
+}
+
+func (f *fixup) init() {
+	f.compiled = regexp.MustCompile(f.Pattern)
+}
+
+func (f *fixup) apply(data []byte) []byte {
+	if f.replaceFunc != nil {
+		return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
+	}
+	return f.compiled.ReplaceAll(data, []byte(f.Replace))
+}
+
+// loadConfig loads and initializes the config from path.
+func loadConfig(path string) (*config, error) {
+	b, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	var cfg config
+	if err := json.Unmarshal(b, &cfg); err != nil {
+		return nil, err
+	}
+	for i := range cfg.Fixups {
+		cfg.Fixups[i].init()
+	}
+	return &cfg, nil
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/README.md
similarity index 100%
rename from notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md
rename to notifier/vendor/golang.org/x/vuln/internal/buildinfo/README.md
diff --git a/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
new file mode 100644
index 00000000..49869ce3
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
@@ -0,0 +1,257 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// This file adds to buildinfo the functionality for extracting the PCLN table.
+
+import (
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// ErrNoSymbols represents non-existence of symbol
+// table in binaries supported by buildinfo.
+var ErrNoSymbols = errors.New("no symbol section")
+
+// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
+func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil || sym == nil {
+		if errors.Is(err, elf.ErrNoSymbols) {
+			return 0, 0, nil, ErrNoSymbols
+		}
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	prog := x.progContaining(sym.Value)
+	if prog == nil {
+		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
+}
+
+func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		syms, err := x.f.Symbols()
+		if err != nil {
+			x.symbolsErr = err
+			return
+		}
+		x.symbols = make(map[string]*elf.Symbol, len(syms))
+		for _, s := range syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *elfExe) progContaining(addr uint64) *elf.Prog {
+	for _, p := range x.f.Progs {
+		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
+			return p
+		}
+	}
+	return nil
+}
+
+const go12magic = 0xfffffffb
+const go116magic = 0xfffffffa
+
+// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
+func (x *elfExe) PCLNTab() ([]byte, uint64) {
+	var offset uint64
+	text := x.f.Section(".text")
+	if text != nil {
+		offset = text.Offset
+	}
+	pclntab := x.f.Section(".gopclntab")
+	if pclntab == nil {
+		// Addition: this code is added to support some form of stripping.
+		pclntab = x.f.Section(".data.rel.ro.gopclntab")
+		if pclntab == nil {
+			pclntab = x.f.Section(".data.rel.ro")
+			if pclntab == nil {
+				return nil, 0
+			}
+			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
+			// its own section header. We can search for for the start by looking for the four
+			// byte magic and the go magic.
+			b, err := pclntab.Data()
+			if err != nil {
+				return nil, 0
+			}
+			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
+			// actually correct. During testing it worked, but that may be because I got lucky
+			// with the binary I was using, and we need to do four byte jumps to exhaustively
+			// search the section?
+			for i := 0; i < len(b); i += 16 {
+				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
+					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
+					(b[i+7] == 4 || b[i+7] == 8) {
+					// Also check for the go magic
+					leMagic := binary.LittleEndian.Uint32(b[i:])
+					beMagic := binary.BigEndian.Uint32(b[i:])
+					switch {
+					case leMagic == go12magic:
+						fallthrough
+					case beMagic == go12magic:
+						fallthrough
+					case leMagic == go116magic:
+						fallthrough
+					case beMagic == go116magic:
+						return b[i:], offset
+					}
+				}
+			}
+		}
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, offset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
+func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	sect := x.f.Sections[sym.SectionNumber-1]
+	// In PE, the symbol's value is the offset from the section start.
+	return uint64(sym.Value), 0, sect.ReaderAt, nil
+}
+
+func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
+		if len(x.f.Symbols) == 0 {
+			x.symbolsErr = ErrNoSymbols
+			return
+		}
+		for _, s := range x.f.Symbols {
+			x.symbols[s.Name] = s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
+// Assumes that the underlying symbol table exists, otherwise
+// it might panic.
+func (x *peExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	for _, section := range x.f.Sections {
+		if section.Name == ".text" {
+			textOffset = uint64(section.Offset)
+			break
+		}
+	}
+
+	var start, end int64
+	var section int
+	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
+		start = int64(s.Value)
+		section = int(s.SectionNumber - 1)
+	}
+	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
+		end = int64(s.Value)
+	}
+	if start == 0 || end == 0 {
+		return nil, 0
+	}
+	offset := int64(x.f.Sections[section].Offset) + start
+	size := end - start
+
+	pclntab := make([]byte, size)
+	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
+		return nil, 0
+	}
+	return pclntab, textOffset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
+func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	seg := x.segmentContaining(sym.Value)
+	if seg == nil {
+		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, seg.Addr, seg.ReaderAt, nil
+}
+
+func (x *machoExe) lookupSymbol(name string) (*macho.Symbol, error) {
+	const mustExistSymbol = "runtime.main"
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
+		for _, s := range x.f.Symtab.Syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+		// In the presence of stripping, the symbol table for darwin
+		// binaries will not be empty, but the program symbols will
+		// be missing.
+		if _, ok := x.symbols[mustExistSymbol]; !ok {
+			x.symbolsErr = ErrNoSymbols
+		}
+	})
+
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
+			return seg
+		}
+	}
+	return nil
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
+func (x *machoExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	text := x.f.Section("__text")
+	if text != nil {
+		textOffset = uint64(text.Offset)
+	}
+	pclntab := x.f.Section("__gopclntab")
+	if pclntab == nil {
+		return nil, 0
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, textOffset
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
new file mode 100644
index 00000000..ddbdea08
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
@@ -0,0 +1,160 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Code in this package is dervied from src/cmd/go/internal/version/version.go
+// and cmd/go/internal/version/exe.go.
+
+import (
+	"debug/buildinfo"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"runtime/debug"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/gosym"
+	"golang.org/x/vuln/internal/goversion"
+)
+
+func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
+	packagesModules := make([]*packages.Module, len(debugModules))
+	for i, mod := range debugModules {
+		packagesModules[i] = &packages.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+		if mod.Replace != nil {
+			packagesModules[i].Replace = &packages.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+	}
+	return packagesModules
+}
+
+type Symbol struct {
+	Pkg  string `json:"pkg,omitempty"`
+	Name string `json:"name,omitempty"`
+}
+
+// ExtractPackagesAndSymbols extracts symbols, packages, modules from
+// Go binary file as well as bin's metadata.
+//
+// If the symbol table is not available, such as in the case of stripped
+// binaries, returns module and binary info but without the symbol info.
+func ExtractPackagesAndSymbols(file string) ([]*packages.Module, []Symbol, *debug.BuildInfo, error) {
+	bin, err := os.Open(file)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+	defer bin.Close()
+
+	bi, err := buildinfo.Read(bin)
+	if err != nil {
+		// It could be that bin is an ancient Go binary.
+		v, err := goversion.ReadExe(file)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		bi := &debug.BuildInfo{
+			GoVersion: v.Release,
+			Main:      debug.Module{Path: v.ModuleInfo},
+		}
+		// We cannot analyze symbol tables of ancient binaries.
+		return nil, nil, bi, nil
+	}
+
+	funcSymName := gosym.FuncSymName(bi.GoVersion)
+	if funcSymName == "" {
+		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
+	}
+
+	x, err := openExe(bin)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	value, base, r, err := x.SymbolInfo(funcSymName)
+	if err != nil {
+		if errors.Is(err, ErrNoSymbols) {
+			// bin is stripped, so return just module info and metadata.
+			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+		}
+		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
+	}
+
+	pclntab, textOffset := x.PCLNTab()
+	if pclntab == nil {
+		// If we have build information, but not PCLN table, fall
+		// back to much higher granularity vulnerability checking.
+		return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+	}
+	lineTab := gosym.NewLineTable(pclntab, textOffset)
+	if lineTab == nil {
+		return nil, nil, nil, errors.New("invalid line table")
+	}
+	tab, err := gosym.NewTable(nil, lineTab)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	pkgSyms := make(map[Symbol]bool)
+	for _, f := range tab.Funcs {
+		if f.Func == nil {
+			continue
+		}
+		pkgName, symName, err := parseName(f.Func.Sym)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		pkgSyms[Symbol{pkgName, symName}] = true
+
+		// Collect symbols that were inlined in f.
+		it, err := lineTab.InlineTree(&f, value, base, r)
+		if err != nil {
+			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
+		}
+		for _, ic := range it {
+			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
+			if err != nil {
+				return nil, nil, nil, err
+			}
+			pkgSyms[Symbol{pkgName, symName}] = true
+		}
+	}
+
+	var syms []Symbol
+	for ps := range pkgSyms {
+		syms = append(syms, ps)
+	}
+
+	return debugModulesToPackagesModules(bi.Deps), syms, bi, nil
+}
+
+func parseName(s *gosym.Sym) (pkg, sym string, err error) {
+	symName := s.BaseName()
+	if r := s.ReceiverName(); r != "" {
+		if strings.HasPrefix(r, "(*") {
+			r = strings.Trim(r, "(*)")
+		}
+		symName = fmt.Sprintf("%s.%s", r, symName)
+	}
+
+	pkgName := s.PackageName()
+	if pkgName != "" {
+		pkgName, err = url.PathUnescape(pkgName)
+		if err != nil {
+			return "", "", err
+		}
+	}
+	return pkgName, symName, nil
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
new file mode 100644
index 00000000..f29dffa2
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
@@ -0,0 +1,221 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"fmt"
+	"sync"
+
+	// "internal/xcoff"
+	"io"
+)
+
+// Addition: modification of rawBuildInfo in the original file.
+// openExe returns reader r as an exe.
+func openExe(r io.ReaderAt) (exe, error) {
+	data := make([]byte, 16)
+	if _, err := r.ReadAt(data, 0); err != nil {
+		return nil, err
+	}
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &elfExe{f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &peExe{r: r, f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &machoExe{f: e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type exe interface {
+	// ReadData reads and returns up to size byte starting at virtual address addr.
+	ReadData(addr, size uint64) ([]byte, error)
+
+	// DataStart returns the virtual address of the segment or section that
+	// should contain build information. This is either a specially named section
+	// or the first writable non-zero data segment.
+	DataStart() uint64
+
+	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
+
+	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
+}
+
+// elfExe is the ELF implementation of the exe interface.
+type elfExe struct {
+	f *elf.File
+
+	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once              // Addition: for computing symbols
+	symbolsErr  error                  // Addition: error for computing symbols
+}
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *elfExe) DataStart() uint64 {
+	for _, s := range x.f.Sections {
+		if s.Name == ".go.buildinfo" {
+			return s.Addr
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
+			return p.Vaddr
+		}
+	}
+	return 0
+}
+
+// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
+type peExe struct {
+	r io.ReaderAt
+	f *pe.File
+
+	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once             // Addition: for computing symbols
+	symbolsErr  error                 // Addition: error for computing symbols
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
+			n := uint64(sect.VirtualAddress+sect.Size) - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *peExe) DataStart() uint64 {
+	// Assume data is first writable section.
+	const (
+		IMAGE_SCN_CNT_CODE               = 0x00000020
+		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
+		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
+		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
+		IMAGE_SCN_MEM_READ               = 0x40000000
+		IMAGE_SCN_MEM_WRITE              = 0x80000000
+		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
+		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
+		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
+	)
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 &&
+			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
+			return uint64(sect.VirtualAddress) + x.imageBase()
+		}
+	}
+	return 0
+}
+
+// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
+type machoExe struct {
+	f *macho.File
+
+	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once                // Addition: for computing symbols
+	symbolsErr  error                    // Addition: error for computing symbols
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			n := seg.Addr + seg.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *machoExe) DataStart() uint64 {
+	// Look for section named "__go_buildinfo".
+	for _, sec := range x.f.Sections {
+		if sec.Name == "__go_buildinfo" {
+			return sec.Addr
+		}
+	}
+	// Try the first non-empty writable segment.
+	const RW = 3
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
+			return seg.Addr
+		}
+	}
+	return 0
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/client/index.go b/notifier/vendor/golang.org/x/vuln/internal/client/index.go
index 5f2d0c00..435980c4 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/client/index.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/client/index.go
@@ -96,7 +96,7 @@ func (i *index) add(entry *osv.Entry) {
 		module.Vulns = append(module.Vulns, moduleVuln{
 			ID:       entry.ID,
 			Modified: entry.Modified,
-			Fixed:    isem.LatestFixedVersion(affected.Ranges),
+			Fixed:    isem.NonSupersededFix(affected.Ranges),
 		})
 	}
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/client/source.go b/notifier/vendor/golang.org/x/vuln/internal/client/source.go
index 3e47b09f..2e848c32 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/client/source.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/client/source.go
@@ -45,8 +45,9 @@ type httpSource struct {
 func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err error) {
 	derrors.Wrap(&err, "get(%s)", endpoint)
 
+	method := http.MethodGet
 	reqURL := fmt.Sprintf("%s/%s", hs.url, endpoint+".json.gz")
-	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
+	req, err := http.NewRequestWithContext(ctx, method, reqURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -56,7 +57,7 @@ func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err e
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
+		return nil, fmt.Errorf("HTTP %s %s returned unexpected status: %s", method, reqURL, resp.Status)
 	}
 
 	// Uncompress the result.
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md b/notifier/vendor/golang.org/x/vuln/internal/gosym/README.md
similarity index 100%
rename from notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md
rename to notifier/vendor/golang.org/x/vuln/internal/gosym/README.md
diff --git a/notifier/vendor/golang.org/x/vuln/internal/gosym/additions.go b/notifier/vendor/golang.org/x/vuln/internal/gosym/additions.go
new file mode 100644
index 00000000..022cf92e
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/gosym/additions.go
@@ -0,0 +1,184 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gosym
+
+import (
+	"encoding/binary"
+	"io"
+	"strings"
+
+	sv "golang.org/x/mod/semver"
+	"golang.org/x/vuln/internal/semver"
+)
+
+const (
+	funcSymNameGo119Lower string = "go.func.*"
+	funcSymNameGo120      string = "go:func.*"
+)
+
+// FuncSymName returns symbol name for Go functions used in binaries
+// based on Go version. Supported Go versions are 1.18 and greater.
+// If the go version is unreadable it assumes that it is a newer version
+// and returns the symbol name for go version 1.20 or greater.
+func FuncSymName(goVersion string) string {
+	// Support devel goX.Y...
+	v := strings.TrimPrefix(goVersion, "devel ")
+	v = semver.GoTagToSemver(v)
+	mm := sv.MajorMinor(v)
+	if sv.Compare(mm, "v1.20") >= 0 || mm == "" {
+		return funcSymNameGo120
+	} else if sv.Compare(mm, "v1.18") >= 0 {
+		return funcSymNameGo119Lower
+	}
+	return ""
+}
+
+// Additions to the original package from cmd/internal/objabi/funcdata.go
+const (
+	pcdata_InlTreeIndex = 2
+	funcdata_InlTree    = 3
+)
+
+// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
+// goFuncValue is the value of the gosym.FuncSymName symbol.
+// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
+// progReader is a ReaderAt positioned at the start of that region.
+func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
+	if f.inlineTreeCount == 0 {
+		return nil, nil
+	}
+	if f.inlineTreeOffset == ^uint32(0) {
+		return nil, nil
+	}
+	var offset int64
+	if t.version >= ver118 {
+		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
+	} else {
+		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
+	}
+
+	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
+	ics := make([]InlinedCall, 0, f.inlineTreeCount)
+	for i := 0; i < f.inlineTreeCount; i++ {
+		if t.version >= ver120 {
+			var ric rawInlinedCall120
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.NameOff)),
+				ParentPC: ric.ParentPC,
+			})
+		} else {
+			var ric rawInlinedCall112
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.Func_)),
+				ParentPC: ric.ParentPC,
+			})
+		}
+	}
+	return ics, nil
+}
+
+// InlinedCall describes a call to an inlined function.
+type InlinedCall struct {
+	FuncID   uint8  // type of the called function
+	Name     string // name of called function
+	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall112 struct {
+	Parent   int16 // index of parent in the inltree, or < 0
+	FuncID   uint8 // type of the called function
+	_        byte
+	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
+	Line     int32 // line number of the call site
+	Func_    int32 // offset into pclntab for name of called function
+	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.20. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall120 struct {
+	FuncID    uint8 // type of the called function
+	_         [3]byte
+	NameOff   int32 // offset into pclntab for name of called function
+	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
+	StartLine int32 // line number of start of function (func keyword/TEXT directive)
+}
+
+func (f funcData) npcdata() uint32 { return f.field(7) }
+func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
+	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
+}
+
+func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.nfuncdata(numFuncFields) {
+		return ^uint32(0)
+	}
+	var off uint32
+	if f.t.version >= ver118 {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4 + // skip pcdata
+			uint32(i)*4 // index of i'th FUNCDATA
+	} else {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4
+		off += uint32(i) * f.t.ptrsize
+	}
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+func (f funcData) fieldOffset(n uint32) uint32 {
+	// In Go 1.18, the first field of _func changed
+	// from a uintptr entry PC to a uint32 entry offset.
+	sz0 := f.t.ptrsize
+	if f.t.version >= ver118 {
+		sz0 = 4
+	}
+	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
+}
+
+func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.npcdata() {
+		return ^uint32(0)
+	}
+	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
+		uint32(i)*4 // index of i'th PCDATA
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+// maxInlineTreeIndexValue returns the maximum value of the inline tree index
+// pc-value table in info. This is the only way to determine how many
+// IndexedCalls are in an inline tree, since the data of the tree itself is not
+// delimited in any way.
+func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
+	if info.npcdata() <= pcdata_InlTreeIndex {
+		return -1
+	}
+	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
+	p := t.pctab[off:]
+	val := int32(-1)
+	max := int32(-1)
+	var pc uint64
+	for t.step(&p, &pc, &val, pc == 0) {
+		if val > max {
+			max = val
+		}
+	}
+	return int(max)
+}
+
+type inlTree struct {
+	inlineTreeOffset uint32 // offset from go.func.* symbol
+	inlineTreeCount  int    // number of entries in inline tree
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go b/notifier/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
similarity index 100%
rename from notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go
rename to notifier/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go b/notifier/vendor/golang.org/x/vuln/internal/gosym/symtab.go
similarity index 100%
rename from notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go
rename to notifier/vendor/golang.org/x/vuln/internal/gosym/symtab.go
diff --git a/notifier/vendor/golang.org/x/vuln/internal/goversion/asm.go b/notifier/vendor/golang.org/x/vuln/internal/goversion/asm.go
new file mode 100644
index 00000000..1c165e60
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/goversion/asm.go
@@ -0,0 +1,349 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"encoding/binary"
+	"fmt"
+	"os"
+)
+
+type matcher [][]uint32
+
+const (
+	pWild    uint32 = 0xff00
+	pAddr    uint32 = 0x10000
+	pEnd     uint32 = 0x20000
+	pRelAddr uint32 = 0x30000
+
+	opMaybe = 1 + iota
+	opMust
+	opDone
+	opAnchor = 0x100
+	opSub8   = 0x200
+	opFlags  = opAnchor | opSub8
+)
+
+var amd64Matcher = matcher{
+	{opMaybe | opAnchor,
+		// __rt0_amd64_darwin:
+		//	JMP __rt0_amd64
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	lea ADDR(%rip), %rax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24, 0x48,
+		0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	mov $ADDR, %eax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24,
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// __rt0_amd64:
+		//	mov (%rsp), %rdi
+		//	lea 8(%rsp), %rsi
+		//	jmp runtime.rt0_g0
+		0x48, 0x8b, 0x3c, 0x24,
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	lea __libc_csu_fini(%rip), %r8
+		//	lea __libc_csu_init(%rip), %rcx
+		//	lea ADDR(%rip), %rdi # main
+		//	callq *xxx(%rip)
+		0x4c, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x3d, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0x15,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	push %rsp (1)
+		//	mov $__libc_csu_fini, %r8 (7)
+		//	mov $__libc_csu_init, %rcx (7)
+		//	mov $ADDR, %rdi # main (7)
+		//	callq *xxx(%rip)
+		0x54,
+		0x49, 0xc7, 0xc0, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc1, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc7, pAddr | pWild, pWild, pWild, pWild,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	lea ADDR(%rip), %rax # rt0_go
+		//	jmpq *%rax
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	mov $ADDR, %eax
+		//	jmpq *%rax
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	JMP runtime.rt0_go(SB)
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMust | opAnchor,
+		// rt0_go:
+		//	mov %rdi, %rax
+		//	mov %rsi, %rbx
+		//	sub %0x27, %rsp
+		//	and $0xfffffffffffffff0,%rsp
+		//	mov %rax,0x10(%rsp)
+		//	mov %rbx,0x18(%rsp)
+		0x48, 0x89, 0xf8,
+		0x48, 0x89, 0xf3,
+		0x48, 0x83, 0xec, 0x27,
+		0x48, 0x83, 0xe4, 0xf0,
+		0x48, 0x89, 0x44, 0x24, 0x10,
+		0x48, 0x89, 0x5c, 0x24, 0x18,
+	},
+	{opMust,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		//	lea other(%rip), %rdi
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0x8d, 0x05,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.hashinit
+		//	callq runtime.schedinit (ADDR)
+		//	pushq $main.main
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x68,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rax
+		//	test %rax, %rax
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc0,
+		0x75, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rbx
+		//	cmp $0x0, %rbx
+		//	jne 
+		//	lea "unknown"(%rip), %rbx
+		//	mov %rbx, ADDR(%rip)
+		//	movq $7, (ADDR+8)(%rip)
+		0x48, 0x8b, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x83, 0xfb, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	lea "unknown"(%rip), %rax
+		//	mov %rax, ADDR(%rip)
+		//	lea ADDR(%rip), %rax
+		//	movq $7, 8(%rax)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		//	test %eax, %eax
+		//	jne 
+		//	lea "unknown"(RIP), %rax
+		//	mov %rax, ADDR(%rip)
+		0x48, 0x85, 0xc0, 0x75, pWild, 0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild, 0x48, 0x89, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rcx
+		//	test %rcx, %rcx
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc9,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+}
+
+var DebugMatch bool
+
+func (m matcher) match(f exe, addr uint64) (uint64, bool) {
+	data, err := f.ReadData(addr, 512)
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
+	}
+	if err != nil {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "match: %v\n", err)
+		}
+		return 0, false
+	}
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
+	}
+Matchers:
+	for pc, p := range m {
+		op := p[0]
+		p = p[1:]
+	Search:
+		for i := 0; i <= len(data)-len(p); i++ {
+			a := -1
+			e := -1
+			if i > 0 && op&opAnchor != 0 {
+				break
+			}
+			for j := 0; j < len(p); j++ {
+				b := byte(p[j])
+				m := byte(p[j] >> 8)
+				if data[i+j]&^m != b {
+					continue Search
+				}
+				if p[j]&pAddr != 0 {
+					a = j
+				}
+				if p[j]&pEnd != 0 {
+					e = j + 1
+				}
+			}
+			// matched
+			if DebugMatch {
+				fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
+			}
+			if a != -1 {
+				val := uint64(int32(binary.LittleEndian.Uint32(data[i+a:])))
+				if e == -1 {
+					addr = val
+				} else {
+					addr += uint64(i+e) + val
+				}
+				if op&opSub8 != 0 {
+					addr -= 8
+				}
+			}
+			if op&^opFlags == opDone {
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "done %x\n", addr)
+				}
+				return addr, true
+			}
+			if a != -1 {
+				// changed addr, so reload
+				data, err = f.ReadData(addr, 512)
+				if err != nil {
+					return 0, false
+				}
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
+				}
+			}
+			continue Matchers
+		}
+		// not matched
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
+		}
+		if op&^opFlags == opMust {
+			return 0, false
+		}
+	}
+	// ran off end of matcher
+	return 0, false
+}
+
+func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
+	entry := f.Entry()
+	if entry == 0 {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "missing entry!\n")
+		}
+		return
+	}
+	addr, ok := amd64Matcher.match(f, entry)
+	if !ok {
+		return
+	}
+	v, err := readBuildVersion(f, addr, 16)
+	if err != nil {
+		return
+	}
+	return true, v
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/goversion/exe.go b/notifier/vendor/golang.org/x/vuln/internal/goversion/exe.go
new file mode 100644
index 00000000..d833bfe6
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/goversion/exe.go
@@ -0,0 +1,324 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+type sym struct {
+	Name string
+	Addr uint64
+	Size uint64
+}
+
+type exe interface {
+	AddrSize() int // bytes
+	ReadData(addr, size uint64) ([]byte, error)
+	Symbols() ([]sym, error)
+	SectionNames() []string
+	Close() error
+	ByteOrder() binary.ByteOrder
+	Entry() uint64
+	TextRange() (uint64, uint64)
+	RODataRange() (uint64, uint64)
+}
+
+func openExe(file string) (exe, error) {
+	f, err := os.Open(file)
+	if err != nil {
+		return nil, err
+	}
+	data := make([]byte, 16)
+	if _, err := io.ReadFull(f, data); err != nil {
+		return nil, err
+	}
+	f.Seek(0, 0)
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &elfExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &peExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &machoExe{f, e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type elfExe struct {
+	os *os.File
+	f  *elf.File
+}
+
+func (x *elfExe) AddrSize() int { return 0 }
+
+func (x *elfExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *elfExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *elfExe) Entry() uint64 { return x.f.Entry }
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		// The following line was commented from the original code.
+		//fmt.Printf("%#x %#x %#x\n", addr, prog.Vaddr, prog.Vaddr+prog.Filesz)
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *elfExe) Symbols() ([]sym, error) {
+	syms, err := x.f.Symbols()
+	if err != nil {
+		return nil, err
+	}
+	var out []sym
+	for _, s := range syms {
+		out = append(out, sym{s.Name, s.Value, s.Size})
+	}
+	return out, nil
+}
+
+func (x *elfExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *elfExe) TextRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *elfExe) RODataRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == elf.PF_R {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == (elf.PF_R|elf.PF_X) {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+type peExe struct {
+	os *os.File
+	f  *pe.File
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) AddrSize() int {
+	if x.f.Machine == pe.IMAGE_FILE_MACHINE_AMD64 {
+		return 8
+	}
+	return 4
+}
+
+func (x *peExe) ByteOrder() binary.ByteOrder { return binary.LittleEndian }
+
+func (x *peExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *peExe) Entry() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase + oh.AddressOfEntryPoint)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase + uint64(oh.AddressOfEntryPoint)
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	data := make([]byte, size)
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr+size-1 <= uint64(sect.VirtualAddress+sect.Size-1) {
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *peExe) Symbols() ([]sym, error) {
+	base := x.imageBase()
+	var out []sym
+	for _, s := range x.f.Symbols {
+		if s.SectionNumber <= 0 || int(s.SectionNumber) > len(x.f.Sections) {
+			continue
+		}
+		sect := x.f.Sections[s.SectionNumber-1]
+		out = append(out, sym{s.Name, uint64(s.Value) + base + uint64(sect.VirtualAddress), 0})
+	}
+	return out, nil
+}
+
+func (x *peExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *peExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty section.
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 {
+			return uint64(sect.VirtualAddress) + x.imageBase(), uint64(sect.VirtualAddress+sect.Size) + x.imageBase()
+		}
+	}
+	return 0, 0
+}
+
+func (x *peExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
+
+type machoExe struct {
+	os *os.File
+	f  *macho.File
+}
+
+func (x *machoExe) AddrSize() int {
+	if x.f.Cpu&0x01000000 != 0 {
+		return 8
+	}
+	return 4
+}
+
+func (x *machoExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *machoExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *machoExe) Entry() uint64 {
+	for _, load := range x.f.Loads {
+		b, ok := load.(macho.LoadBytes)
+		if !ok {
+			continue
+		}
+		// TODO: Other thread states.
+		bo := x.f.ByteOrder
+		const x86_THREAD_STATE64 = 4
+		cmd, siz := macho.LoadCmd(bo.Uint32(b[0:4])), bo.Uint32(b[4:8])
+		if cmd == macho.LoadCmdUnixThread && siz == 184 && bo.Uint32(b[8:12]) == x86_THREAD_STATE64 {
+			return bo.Uint64(b[144:])
+		}
+	}
+	return 0
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	data := make([]byte, size)
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr+size-1 <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *machoExe) Symbols() ([]sym, error) {
+	var out []sym
+	for _, s := range x.f.Symtab.Syms {
+		out = append(out, sym{s.Name, s.Value, 0})
+	}
+	return out, nil
+}
+
+func (x *machoExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *machoExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty segment.
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Name != "__PAGEZERO" && seg.Addr != 0 && seg.Filesz != 0 {
+			return seg.Addr, seg.Addr + seg.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *machoExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/goversion/read.go b/notifier/vendor/golang.org/x/vuln/internal/goversion/read.go
new file mode 100644
index 00000000..f298ef07
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/goversion/read.go
@@ -0,0 +1,246 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package goversion reports the Go version used to build program executables.
+//
+// This is a copy of rsc.io/goversion/version. We renamed the package to goversion
+// to differentiate between version package in standard library that we also use.
+package goversion
+
+import (
+	"bytes"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// Version is the information reported by ReadExe.
+type Version struct {
+	Release        string // Go version (runtime.Version in the program)
+	ModuleInfo     string // program's module information
+	BoringCrypto   bool   // program uses BoringCrypto
+	StandardCrypto bool   // program uses standard crypto (replaced by BoringCrypto)
+	FIPSOnly       bool   // program imports "crypto/tls/fipsonly"
+}
+
+// ReadExe reports information about the Go version used to build
+// the program executable named by file.
+func ReadExe(file string) (Version, error) {
+	var v Version
+	f, err := openExe(file)
+	if err != nil {
+		return v, err
+	}
+	defer f.Close()
+	isGo := false
+	for _, name := range f.SectionNames() {
+		if name == ".note.go.buildid" {
+			isGo = true
+		}
+	}
+	syms, symsErr := f.Symbols()
+	isGccgo := false
+	for _, sym := range syms {
+		name := sym.Name
+		if name == "runtime.main" || name == "main.main" {
+			isGo = true
+		}
+		if strings.HasPrefix(name, "runtime.") && strings.HasSuffix(name, "$descriptor") {
+			isGccgo = true
+		}
+		if name == "runtime.buildVersion" {
+			isGo = true
+			release, err := readBuildVersion(f, sym.Addr, sym.Size)
+			if err != nil {
+				return v, err
+			}
+			v.Release = release
+		}
+		// Note: Using strings.HasPrefix because Go 1.17+ adds ".abi0" to many of these symbols.
+		if strings.Contains(name, "_Cfunc__goboringcrypto_") || strings.HasPrefix(name, "crypto/internal/boring/sig.BoringCrypto") {
+			v.BoringCrypto = true
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.FIPSOnly") {
+			v.FIPSOnly = true
+		}
+		for _, re := range standardCryptoNames {
+			if re.MatchString(name) {
+				v.StandardCrypto = true
+			}
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.StandardCrypto") {
+			v.StandardCrypto = true
+		}
+	}
+
+	if DebugMatch {
+		v.Release = ""
+	}
+	if err := findModuleInfo(&v, f); err != nil {
+		return v, err
+	}
+	if v.Release == "" {
+		g, release := readBuildVersionX86Asm(f)
+		if g {
+			isGo = true
+			v.Release = release
+			if err := findCryptoSigs(&v, f); err != nil {
+				return v, err
+			}
+		}
+	}
+	if isGccgo && v.Release == "" {
+		isGo = true
+		v.Release = "gccgo (version unknown)"
+	}
+	if !isGo && symsErr != nil {
+		return v, symsErr
+	}
+
+	if !isGo {
+		return v, errors.New("not a Go executable")
+	}
+	if v.Release == "" {
+		v.Release = "unknown Go version"
+	}
+	return v, nil
+}
+
+var re = regexp.MustCompile
+
+var standardCryptoNames = []*regexp.Regexp{
+	re(`^crypto/sha1\.\(\*digest\)`),
+	re(`^crypto/sha256\.\(\*digest\)`),
+	re(`^crypto/rand\.\(\*devReader\)`),
+	re(`^crypto/rsa\.encrypt(\.abi.)?$`),
+	re(`^crypto/rsa\.decrypt(\.abi.)?$`),
+}
+
+func readBuildVersion(f exe, addr, size uint64) (string, error) {
+	if size == 0 {
+		size = uint64(f.AddrSize() * 2)
+	}
+	if size != 8 && size != 16 {
+		return "", fmt.Errorf("invalid size for runtime.buildVersion")
+	}
+	data, err := f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion: %v", err)
+	}
+
+	if size == 8 {
+		addr = uint64(f.ByteOrder().Uint32(data))
+		size = uint64(f.ByteOrder().Uint32(data[4:]))
+	} else {
+		addr = f.ByteOrder().Uint64(data)
+		size = f.ByteOrder().Uint64(data[8:])
+	}
+	if size > 1000 {
+		return "", fmt.Errorf("implausible string size %d for runtime.buildVersion", size)
+	}
+
+	data, err = f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion string data: %v", err)
+	}
+	return string(data), nil
+}
+
+// Code signatures that indicate BoringCrypto or crypto/internal/fipsonly.
+// These are not byte literals in order to avoid the actual
+// byte signatures appearing in the goversion binary,
+// because on some systems you can't tell rodata from text.
+var (
+	sigBoringCrypto, _   = hex.DecodeString("EB1DF448F44BF4B332F52813A3B450D441CC2485F001454E92101B1D2F1950C3")
+	sigStandardCrypto, _ = hex.DecodeString("EB1DF448F44BF4BAEE4DFA9851CA56A91145E83E99C59CF911CB8E80DAF12FC3")
+	sigFIPSOnly, _       = hex.DecodeString("EB1DF448F44BF4363CB9CE9D68047D31F28D325D5CA5873F5D80CAF6D6151BC3")
+)
+
+func findCryptoSigs(v *Version, f exe) error {
+	const maxSigLen = 1 << 10
+	start, end := f.TextRange()
+	for addr := start; addr < end; {
+		size := uint64(1 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveSig(data, sigBoringCrypto) {
+			v.BoringCrypto = true
+		}
+		if haveSig(data, sigFIPSOnly) {
+			v.FIPSOnly = true
+		}
+		if haveSig(data, sigStandardCrypto) {
+			v.StandardCrypto = true
+		}
+		if addr+size < end {
+			size -= maxSigLen
+		}
+		addr += size
+	}
+	return nil
+}
+
+func haveSig(data, sig []byte) bool {
+	const align = 16
+	for {
+		i := bytes.Index(data, sig)
+		if i < 0 {
+			return false
+		}
+		if i&(align-1) == 0 {
+			return true
+		}
+		// Found unaligned match; unexpected but
+		// skip to next aligned boundary and keep searching.
+		data = data[(i+align-1)&^(align-1):]
+	}
+}
+
+func findModuleInfo(v *Version, f exe) error {
+	const maxModInfo = 128 << 10
+	start, end := f.RODataRange()
+	for addr := start; addr < end; {
+		size := uint64(4 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveModuleInfo(data, v) {
+			return nil
+		}
+		if addr+size < end {
+			size -= maxModInfo
+		}
+		addr += size
+	}
+	return nil
+}
+
+var (
+	infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+	infoEnd, _   = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func haveModuleInfo(data []byte, v *Version) bool {
+	i := bytes.Index(data, infoStart)
+	if i < 0 {
+		return false
+	}
+	j := bytes.Index(data[i:], infoEnd)
+	if j < 0 {
+		return false
+	}
+	v.ModuleInfo = string(data[i+len(infoStart) : i+j])
+	return true
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
new file mode 100644
index 00000000..377a3787
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
@@ -0,0 +1,241 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package govulncheck contains the JSON output structs for govulncheck.
+//
+// govulncheck supports streaming JSON by emitting a series of Message
+// objects as it analyzes user code and discovers vulnerabilities.
+// Streaming JSON is useful for displaying progress in real-time for
+// large projects where govulncheck execution might take some time.
+//
+// govulncheck JSON emits configuration used to perform the analysis,
+// a user-friendly message about what is being analyzed, and the
+// vulnerability findings. Findings for the same vulnerability can
+// can be emitted several times. For instance, govulncheck JSON will
+// emit a finding when it sees that a vulnerable module is required
+// before proceeding to check if the vulnerability is imported or called.
+// Please see documentation on Message and related types for precise
+// details on the stream encoding.
+//
+// There are no guarantees on the order of messages. The pattern of emitted
+// messages can change in the future. Clients can follow code in handler.go
+// for consuming the streaming JSON programmatically.
+package govulncheck
+
+import (
+	"time"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+const (
+	// ProtocolVersion is the current protocol version this file implements
+	ProtocolVersion = "v1.0.0"
+)
+
+// Message is an entry in the output stream. It will always have exactly one
+// field filled in.
+type Message struct {
+	Config   *Config   `json:"config,omitempty"`
+	Progress *Progress `json:"progress,omitempty"`
+	SBOM     *SBOM     `json:"SBOM,omitempty"`
+	// OSV is emitted for every vulnerability in the current database
+	// that applies to user modules regardless of their version. If a
+	// module is being used at a vulnerable version, the corresponding
+	// OSV will be referenced in Findings depending on the type of usage
+	// and the desired scan level.
+	OSV     *osv.Entry `json:"osv,omitempty"`
+	Finding *Finding   `json:"finding,omitempty"`
+}
+
+// Config must occur as the first message of a stream and informs the client
+// about the information used to generate the findings.
+// The only required field is the protocol version.
+type Config struct {
+	// ProtocolVersion specifies the version of the JSON protocol.
+	ProtocolVersion string `json:"protocol_version"`
+
+	// ScannerName is the name of the tool, for example, govulncheck.
+	//
+	// We expect this JSON format to be used by other tools that wrap
+	// govulncheck, which will have a different name.
+	ScannerName string `json:"scanner_name,omitempty"`
+
+	// ScannerVersion is the version of the tool.
+	ScannerVersion string `json:"scanner_version,omitempty"`
+
+	// DB is the database used by the tool, for example,
+	// vuln.go.dev.
+	DB string `json:"db,omitempty"`
+
+	// LastModified is the last modified time of the data source.
+	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
+
+	// GoVersion is the version of Go used for analyzing standard library
+	// vulnerabilities.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// ScanLevel instructs govulncheck to analyze at a specific level of detail.
+	// Valid values include module, package and symbol.
+	ScanLevel ScanLevel `json:"scan_level,omitempty"`
+
+	// ScanMode instructs govulncheck how to interpret the input and
+	// what to do with it. Valid values are source, binary, query,
+	// and extract.
+	ScanMode ScanMode `json:"scan_mode,omitempty"`
+}
+
+// SBOM contains minimal information about the artifacts govulncheck is scanning.
+type SBOM struct {
+	// The go version used by govulncheck when scanning, which also defines
+	// the version of the standard library used for detecting vulns.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// The set of modules included in the scan.
+	Modules []*Module `json:"modules,omitempty"`
+
+	// The roots of the scan, as package paths.
+	// For binaries, this will be the main package.
+	// For source code, this will be the packages matching the provided package patterns.
+	Roots []string `json:"roots,omitempty"`
+}
+
+type Module struct {
+	// The full module path.
+	Path string `json:"path,omitempty"`
+
+	// The version of the module.
+	Version string `json:"version,omitempty"`
+}
+
+// Progress messages are informational only, intended to allow users to monitor
+// the progress of a long running scan.
+// A stream must remain fully valid and able to be interpreted with all progress
+// messages removed.
+type Progress struct {
+	// A time stamp for the message.
+	Timestamp *time.Time `json:"time,omitempty"`
+
+	// Message is the progress message.
+	Message string `json:"message,omitempty"`
+}
+
+// Finding contains information on a discovered vulnerability. Each vulnerability
+// will likely have multiple findings in JSON mode. This is because govulncheck
+// emits findings as it does work, and therefore could emit one module level,
+// one package level, and potentially multiple symbol level findings depending
+// on scan level.
+// Multiple symbol level findings can be emitted when multiple symbols of the
+// same vuln are called or govulncheck decides to show multiple traces for the
+// same symbol.
+type Finding struct {
+	// OSV is the id of the detected vulnerability.
+	OSV string `json:"osv,omitempty"`
+
+	// FixedVersion is the module version where the vulnerability was
+	// fixed. This is empty if a fix is not available.
+	//
+	// If there are multiple fixed versions in the OSV report, this will
+	// be the fixed version in the latest range event for the OSV report.
+	//
+	// For example, if the range events are
+	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
+	// will be empty.
+	//
+	// For the stdlib, we will show the fixed version closest to the
+	// Go version that is used. For example, if a fix is available in 1.17.5 and
+	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
+	// fixed version.
+	FixedVersion string `json:"fixed_version,omitempty"`
+
+	// Trace contains an entry for each frame in the trace.
+	//
+	// Frames are sorted starting from the imported vulnerable symbol
+	// until the entry point. The first frame in Frames should match
+	// Symbol.
+	//
+	// In binary mode, trace will contain a single-frame with no position
+	// information.
+	//
+	// For module level source findings, the trace will contain a single-frame
+	// with no symbol, position, or package information. For package level source
+	// findings, the trace will contain a single-frame with no symbol or position
+	// information.
+	Trace []*Frame `json:"trace,omitempty"`
+}
+
+// Frame represents an entry in a finding trace.
+type Frame struct {
+	// Module is the module path of the module containing this symbol.
+	//
+	// Importable packages in the standard library will have the path "stdlib".
+	Module string `json:"module"`
+
+	// Version is the module version from the build graph.
+	Version string `json:"version,omitempty"`
+
+	// Package is the import path.
+	Package string `json:"package,omitempty"`
+
+	// Function is the function name.
+	Function string `json:"function,omitempty"`
+
+	// Receiver is the receiver type if the called symbol is a method.
+	//
+	// The client can create the final symbol name by
+	// prepending Receiver to FuncName.
+	Receiver string `json:"receiver,omitempty"`
+
+	// Position describes an arbitrary source position
+	// including the file, line, and column location.
+	// A Position is valid if the line number is > 0.
+	//
+	// The filenames are relative to the directory of
+	// the enclosing module and always use "/" for
+	// portability.
+	Position *Position `json:"position,omitempty"`
+}
+
+// Position represents arbitrary source position.
+type Position struct {
+	Filename string `json:"filename,omitempty"` // filename, if any
+	Offset   int    `json:"offset"`             // byte offset, starting at 0
+	Line     int    `json:"line"`               // line number, starting at 1
+	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
+}
+
+// ScanLevel represents the detail level at which a scan occurred.
+// This can be necessary to correctly interpret the findings, for instance if
+// a scan is at symbol level and a finding does not have a symbol it means the
+// vulnerability was imported but not called. If the scan however was at
+// "package" level, that determination cannot be made.
+type ScanLevel string
+
+const (
+	ScanLevelModule  = "module"
+	ScanLevelPackage = "package"
+	ScanLevelSymbol  = "symbol"
+)
+
+// WantSymbols can be used to check whether the scan level is one that is able
+// to generate symbol-level findings.
+func (l ScanLevel) WantSymbols() bool { return l == ScanLevelSymbol }
+
+// WantPackages can be used to check whether the scan level is one that is able
+// to generate package-level findings.
+func (l ScanLevel) WantPackages() bool { return l == ScanLevelPackage || l == ScanLevelSymbol }
+
+// ScanMode represents the mode in which a scan occurred. This can
+// be necessary to correctly to interpret findings. For instance,
+// a binary can be checked for vulnerabilities or the user just wants
+// to extract minimal data necessary for the vulnerability check.
+type ScanMode string
+
+const (
+	ScanModeSource  = "source"
+	ScanModeBinary  = "binary"
+	ScanModeConvert = "convert"
+	ScanModeQuery   = "query"
+	ScanModeExtract = "extract" // currently, only binary extraction is supported
+)
diff --git a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/handler.go b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
index 5676ea94..5ce7d532 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
@@ -17,6 +17,9 @@ type Handler interface {
 	// Config communicates introductory message to the user.
 	Config(config *Config) error
 
+	// SBOM shows information about what govulncheck is scanning.
+	SBOM(sbom *SBOM) error
+
 	// Progress is called to display a progress message.
 	Progress(progress *Progress) error
 
@@ -45,6 +48,9 @@ func HandleJSON(from io.Reader, to Handler) error {
 		if msg.Progress != nil {
 			err = to.Progress(msg.Progress)
 		}
+		if msg.SBOM != nil {
+			err = to.SBOM(msg.SBOM)
+		}
 		if msg.OSV != nil {
 			err = to.OSV(msg.OSV)
 		}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/json.go b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/json.go
deleted file mode 100644
index d1ea78af..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/json.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package govulncheck
-
-import (
-	"encoding/json"
-
-	"io"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-type jsonHandler struct {
-	enc *json.Encoder
-}
-
-// NewJSONHandler returns a handler that writes govulncheck output as json.
-func NewJSONHandler(w io.Writer) Handler {
-	enc := json.NewEncoder(w)
-	enc.SetIndent("", "  ")
-	return &jsonHandler{enc: enc}
-}
-
-// Config writes config block in JSON to the underlying writer.
-func (h *jsonHandler) Config(config *Config) error {
-	return h.enc.Encode(Message{Config: config})
-}
-
-// Progress writes a progress message in JSON to the underlying writer.
-func (h *jsonHandler) Progress(progress *Progress) error {
-	return h.enc.Encode(Message{Progress: progress})
-}
-
-// OSV writes an osv entry in JSON to the underlying writer.
-func (h *jsonHandler) OSV(entry *osv.Entry) error {
-	return h.enc.Encode(Message{OSV: entry})
-}
-
-// Finding writes a finding in JSON to the underlying writer.
-func (h *jsonHandler) Finding(finding *Finding) error {
-	return h.enc.Encode(Message{Finding: finding})
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
new file mode 100644
index 00000000..b1586e09
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
@@ -0,0 +1,49 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package govulncheck
+
+import (
+	"encoding/json"
+
+	"io"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+type jsonHandler struct {
+	enc *json.Encoder
+}
+
+// NewJSONHandler returns a handler that writes govulncheck output as json.
+func NewJSONHandler(w io.Writer) Handler {
+	enc := json.NewEncoder(w)
+	enc.SetIndent("", "  ")
+	return &jsonHandler{enc: enc}
+}
+
+// Config writes config block in JSON to the underlying writer.
+func (h *jsonHandler) Config(config *Config) error {
+	return h.enc.Encode(Message{Config: config})
+}
+
+// Progress writes a progress message in JSON to the underlying writer.
+func (h *jsonHandler) Progress(progress *Progress) error {
+	return h.enc.Encode(Message{Progress: progress})
+}
+
+// SBOM writes the SBOM block in JSON to the underlying writer.
+func (h *jsonHandler) SBOM(sbom *SBOM) error {
+	return h.enc.Encode(Message{SBOM: sbom})
+}
+
+// OSV writes an osv entry in JSON to the underlying writer.
+func (h *jsonHandler) OSV(entry *osv.Entry) error {
+	return h.enc.Encode(Message{OSV: entry})
+}
+
+// Finding writes a finding in JSON to the underlying writer.
+func (h *jsonHandler) Finding(finding *Finding) error {
+	return h.enc.Encode(Message{Finding: finding})
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/result.go b/notifier/vendor/golang.org/x/vuln/internal/govulncheck/result.go
deleted file mode 100644
index 3c1f2bdd..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/govulncheck/result.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package result contains the JSON output structs for govulncheck.
-package govulncheck
-
-import (
-	"time"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-const (
-	// ProtocolVersion is the current protocol version this file implements
-	ProtocolVersion = "v0.1.0"
-)
-
-// Message is an entry in the output stream. It will always have exactly one
-// field filled in.
-type Message struct {
-	Config   *Config    `json:"config,omitempty"`
-	Progress *Progress  `json:"progress,omitempty"`
-	OSV      *osv.Entry `json:"osv,omitempty"`
-	Finding  *Finding   `json:"finding,omitempty"`
-}
-
-type Config struct {
-	// ProtocolVersion specifies the version of the JSON protocol.
-	ProtocolVersion string `json:"protocol_version,omitempty"`
-
-	// ScannerName is the name of the tool, for example, govulncheck.
-	//
-	// We expect this JSON format to be used by other tools that wrap
-	// govulncheck, which will have a different name.
-	ScannerName string `json:"scanner_name,omitempty"`
-
-	// ScannerVersion is the version of the tool.
-	ScannerVersion string `json:"scanner_version,omitempty"`
-
-	// DB is the database used by the tool, for example,
-	// vuln.go.dev.
-	DB string `json:"db,omitempty"`
-
-	// LastModified is the last modified time of the data source.
-	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
-
-	// GoVersion is the version of Go used for analyzing standard library
-	// vulnerabilities.
-	GoVersion string `json:"go_version,omitempty"`
-
-	// ScanLevel instructs vulncheck to analyze at a specific level of detail.
-	// Valid values include module, package and symbol.
-	ScanLevel ScanLevel `json:"scan_level,omitempty"`
-}
-
-type Progress struct {
-	// A time stamp for the message.
-	Timestamp *time.Time `json:"time,omitempty"`
-
-	// Message is the progress message.
-	Message string `json:"message,omitempty"`
-}
-
-// Vuln represents a single OSV entry.
-type Finding struct {
-	// OSV is the id of the detected vulnerability.
-	OSV string `json:"osv,omitempty"`
-
-	// FixedVersion is the module version where the vulnerability was
-	// fixed. This is empty if a fix is not available.
-	//
-	// If there are multiple fixed versions in the OSV report, this will
-	// be the fixed version in the latest range event for the OSV report.
-	//
-	// For example, if the range events are
-	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
-	// will be empty.
-	//
-	// For the stdlib, we will show the fixed version closest to the
-	// Go version that is used. For example, if a fix is available in 1.17.5 and
-	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
-	// fixed version.
-	FixedVersion string `json:"fixed_version,omitempty"`
-
-	// Trace contains an entry for each frame in the trace.
-	//
-	// Frames are sorted starting from the imported vulnerable symbol
-	// until the entry point. The first frame in Frames should match
-	// Symbol.
-	//
-	// In binary mode, trace will contain a single-frame with no position
-	// information.
-	//
-	// When a package is imported but no vulnerable symbol is called, the trace
-	// will contain a single-frame with no symbol or position information.
-	Trace []*Frame `json:"trace,omitempty"`
-}
-
-// Frame represents an entry in a finding trace.
-type Frame struct {
-	// Module is the module path of the module containing this symbol.
-	//
-	// Importable packages in the standard library will have the path "stdlib".
-	Module string `json:"module"`
-
-	// Version is the module version from the build graph.
-	Version string `json:"version,omitempty"`
-
-	// Package is the import path.
-	Package string `json:"package,omitempty"`
-
-	// Function is the function name.
-	Function string `json:"function,omitempty"`
-
-	// Receiver is the receiver type if the called symbol is a method.
-	//
-	// The client can create the final symbol name by
-	// prepending Receiver to FuncName.
-	Receiver string `json:"receiver,omitempty"`
-
-	// Position describes an arbitrary source position
-	// including the file, line, and column location.
-	// A Position is valid if the line number is > 0.
-	Position *Position `json:"position,omitempty"`
-}
-
-// Position is a copy of token.Position used to marshal/unmarshal
-// JSON correctly.
-type Position struct {
-	Filename string `json:"filename,omitempty"` // filename, if any
-	Offset   int    `json:"offset"`             // offset, starting at 0
-	Line     int    `json:"line"`               // line number, starting at 1
-	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
-}
-
-type ScanLevel string
-
-const (
-	scanLevelModule  = "module"
-	scanLevelPackage = "package"
-	scanLevelSymbol  = "symbol"
-)
-
-func (l ScanLevel) WantSymbols() bool { return l == scanLevelSymbol }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/internal.go b/notifier/vendor/golang.org/x/vuln/internal/internal.go
index 64c5e8d5..8e6b7f5c 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/internal.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/internal.go
@@ -24,5 +24,9 @@ const (
 
 	// UnknownModulePath is a special module path for when we cannot work out
 	// the module for a package.
-	UnknownModulePath = "unknown"
+	UnknownModulePath = "unknown-module"
+
+	// UnknownPackagePath is a special package path for when we cannot work out
+	// the packagUnknownModulePath = "unknown"
+	UnknownPackagePath = "unknown-package"
 )
diff --git a/notifier/vendor/golang.org/x/vuln/internal/openvex/handler.go b/notifier/vendor/golang.org/x/vuln/internal/openvex/handler.go
new file mode 100644
index 00000000..a2d32829
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/openvex/handler.go
@@ -0,0 +1,261 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"io"
+	"slices"
+	"time"
+
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+)
+
+type findingLevel int
+
+const (
+	invalid findingLevel = iota
+	required
+	imported
+	called
+)
+
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	sbom *govulncheck.SBOM
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(cfg *govulncheck.Config) error {
+	h.cfg = cfg
+	return nil
+}
+
+func (h *handler) Progress(progress *govulncheck.Progress) error {
+	return nil
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	h.sbom = s
+	return nil
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// foundAtLevel returns the level at which a specific finding is present in the
+// scanned product.
+func foundAtLevel(f *govulncheck.Finding) findingLevel {
+	frame := f.Trace[0]
+	if frame.Function != "" {
+		return called
+	}
+	if frame.Package != "" {
+		return imported
+	}
+	return required
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is at the same level of precision.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print the vex json to w.
+// This is needed as vex is not streamed.
+func (h *handler) Flush() error {
+	doc := toVex(h)
+	out, err := json.MarshalIndent(doc, "", "  ")
+	if err != nil {
+		return err
+	}
+	_, err = h.w.Write(out)
+	return err
+}
+
+func toVex(h *handler) Document {
+	doc := Document{
+		Context:    ContextURI,
+		Author:     DefaultAuthor,
+		Timestamp:  time.Now().UTC(),
+		Version:    1,
+		Tooling:    Tooling,
+		Statements: statements(h),
+	}
+
+	id := hashVex(doc)
+	doc.ID = "govulncheck/vex:" + id
+	return doc
+}
+
+// Given a slice of findings, returns those findings as a set of subcomponents
+// that are unique per the vulnerable artifact's PURL.
+func subcomponentSet(findings []*govulncheck.Finding) []Component {
+	var scs []Component
+	seen := make(map[string]bool)
+	for _, f := range findings {
+		purl := purlFromFinding(f)
+		if !seen[purl] {
+			scs = append(scs, Component{
+				ID: purlFromFinding(f),
+			})
+			seen[purl] = true
+		}
+	}
+	return scs
+}
+
+// statements combines all OSVs found by govulncheck and generates the list of
+// vex statements with the proper affected level and justification to match the
+// openVex specification.
+func statements(h *handler) []Statement {
+	var scanLevel findingLevel
+	switch h.cfg.ScanLevel {
+	case govulncheck.ScanLevelModule:
+		scanLevel = required
+	case govulncheck.ScanLevelPackage:
+		scanLevel = imported
+	case govulncheck.ScanLevelSymbol:
+		scanLevel = called
+	}
+
+	var statements []Statement
+	for id, osv := range h.osvs {
+		// if there are no findings emitted for a given OSV that means that
+		// the vulnerable module is not required at a vulnerable version.
+		if len(h.findings[id]) == 0 {
+			continue
+		}
+		description := osv.Summary
+		if description == "" {
+			description = osv.Details
+		}
+
+		s := Statement{
+			Vulnerability: Vulnerability{
+				ID:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", id),
+				Name:        id,
+				Description: description,
+				Aliases:     osv.Aliases,
+			},
+			Products: []Product{
+				{
+					Component:     Component{ID: DefaultPID},
+					Subcomponents: subcomponentSet(h.findings[id]),
+				},
+			},
+		}
+
+		// Findings are guaranteed to be at the same level, so we can just check the first element
+		fLevel := foundAtLevel(h.findings[id][0])
+		if fLevel >= scanLevel {
+			s.Status = StatusAffected
+		} else {
+			s.Status = StatusNotAffected
+			s.ImpactStatement = Impact
+			s.Justification = JustificationNotPresent
+			// We only reach this case if running in symbol mode
+			if fLevel == imported {
+				s.Justification = JustificationNotExecuted
+			}
+		}
+		statements = append(statements, s)
+	}
+
+	slices.SortFunc(statements, func(a, b Statement) int {
+		if a.Vulnerability.ID > b.Vulnerability.ID {
+			return 1
+		}
+		if a.Vulnerability.ID < b.Vulnerability.ID {
+			return -1
+		}
+		// this should never happen in practice, since statements are being
+		// populated from a map with the vulnerability IDs as keys
+		return 0
+	})
+	return statements
+}
+
+func hashVex(doc Document) string {
+	// json.Marshal should never error here (because of the structure of Document).
+	// If an error does occur, it won't be a jsonerror, but instead a panic
+	d := Document{
+		Context:    doc.Context,
+		ID:         doc.ID,
+		Author:     doc.Author,
+		Version:    doc.Version,
+		Tooling:    doc.Tooling,
+		Statements: doc.Statements,
+	}
+	out, err := json.Marshal(d)
+	if err != nil {
+		panic(err)
+	}
+	return fmt.Sprintf("%x", sha256.Sum256(out))
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/openvex/purl.go b/notifier/vendor/golang.org/x/vuln/internal/openvex/purl.go
new file mode 100644
index 00000000..fc1cea9c
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/openvex/purl.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"net/url"
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// The PURL is printed as: pkg:golang/MODULE_PATH@VERSION
+// Conceptually there is no namespace and the name is entirely defined by
+// the module path. See https://github.com/package-url/purl-spec/issues/63
+// for further disucssion.
+
+const suffix = "pkg:golang/"
+
+type purl struct {
+	name    string
+	version string
+}
+
+func (p *purl) String() string {
+	var b strings.Builder
+	b.WriteString(suffix)
+	b.WriteString(url.PathEscape(p.name))
+	if p.version != "" {
+		b.WriteString("@")
+		b.WriteString(p.version)
+	}
+	return b.String()
+}
+
+// purlFromFinding takes a govulncheck finding and generates a purl to the
+// vulnerable dependency.
+func purlFromFinding(f *govulncheck.Finding) string {
+	purl := purl{
+		name:    f.Trace[0].Module,
+		version: f.Trace[0].Version,
+	}
+
+	return purl.String()
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/openvex/vex.go b/notifier/vendor/golang.org/x/vuln/internal/openvex/vex.go
new file mode 100644
index 00000000..18779f70
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/openvex/vex.go
@@ -0,0 +1,113 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vex defines the Vulnerability EXchange Format (VEX) types
+// supported by govulncheck.
+//
+// These types match the OpenVEX standard. See https://github.com/openvex for
+// more information on VEX and OpenVEX.
+//
+// This is intended to be the minimimal amount of information required to output
+// a complete VEX document according to the specification.
+package openvex
+
+import "time"
+
+const (
+	ContextURI = "https://openvex.dev/ns/v0.2.0"
+	Tooling    = "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Impact     = "Govulncheck determined that the vulnerable code isn't called"
+
+	DefaultAuthor = "Unknown Author"
+	DefaultPID    = "Unknown Product"
+
+	// The following are defined by the VEX standard.
+	StatusAffected    = "affected"
+	StatusNotAffected = "not_affected"
+
+	// The following are defined by the VEX standard.
+	JustificationNotExecuted = "vulnerable_code_not_in_execute_path"
+	JustificationNotPresent  = "vulnerable_code_not_present"
+)
+
+// Document is the top-level struct for a VEX document.
+type Document struct {
+	// Context is an IRI pointing to the version of openVEX being used by the doc
+	// For govulncheck, it will always be https://openvex.dev/ns/v0.2.0
+	Context string `json:"@context,omitempty"`
+
+	// ID is the identifying string for the VEX document.
+	// govulncheck/vex-[content-based-hash]
+	ID string `json:"@id,omitempty"`
+
+	// Author is the identifier for the author of the VEX statement.
+	// Govulncheck will leave this field default (Unknown author) to be filled in by the user.
+	Author string `json:"author,omitempty"`
+
+	// Timestamp defines the time at which the document was issued.
+	Timestamp time.Time `json:"timestamp,omitempty"`
+
+	// Version is the document version. For govulncheck's output, this will always be 1.
+	Version int `json:"version,omitempty"`
+
+	// Tooling expresses how the VEX document and contained VEX statements were
+	// generated. In this case, it will always be:
+	// "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Tooling string `json:"tooling,omitempty"`
+
+	// Statements are all statements for a given govulncheck output.
+	// Each OSV emitted by govulncheck will have a corresponding statement.
+	Statements []Statement `json:"statements,omitempty"`
+}
+
+// Statement conveys a single status for a single vulnerability for one or more products.
+type Statement struct {
+	// Vulnerability is the vuln being referenced by the statement.
+	Vulnerability Vulnerability `json:"vulnerability,omitempty"`
+
+	// Products are the products associated with the given vulnerability in the statement.
+	Products []Product `json:"products,omitempty"`
+
+	// The status of the vulnerability. Will be either not_affected or affected for govulncheck.
+	Status string `json:"status,omitempty"`
+
+	// If the status is not_affected, this must be filled. The official VEX justification that
+	// best matches govulncheck's vuln filtering is "vulnerable_code_not_in_execute_path"
+	Justification string `json:"justification,omitempty"`
+
+	// If the status is not_affected, this must be filled. For govulncheck, this will always be:
+	// "Govulncheck determined that the vulnerable code isn't called"
+	ImpactStatement string `json:"impact_statement,omitempty"`
+}
+
+// Vulnerability captures a vulnerability and its identifiers/aliases.
+type Vulnerability struct {
+	// ID is a URI that in govulncheck's case points to the govulndb link for the vulnerability.
+	// I.E. https://pkg.go.dev/vuln/GO-2024-2497
+	ID string `json:"@id,omitempty"`
+
+	// Name is the main identifier for the vulnerability (GO-YYYY-XXXX)
+	Name string `json:"name,omitempty"`
+
+	// Description is a short text description of the vulnerability.
+	// It will be populated from the 'summary' field of the vuln's OSV if it exists,
+	// and the 'description' field of the osv if a summary isn't present.
+	Description string `json:"description,omitempty"`
+
+	// Aliases a list of identifiers that other systems are using to track the vulnerability.
+	// I.E. GHSA or CVE ids.
+	Aliases []string `json:"aliases,omitempty"`
+}
+
+// Product identifies the products associated with the given vuln.
+type Product struct {
+	// The main product ID will remian default for now.
+	Component
+	// The subcomponent ID will be a PURL to the vulnerable dependency.
+	Subcomponents []Component `json:"subcomponents,omitempty"`
+}
+
+type Component struct {
+	ID string `json:"@id,omitempty"`
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/osv/osv.go b/notifier/vendor/golang.org/x/vuln/internal/osv/osv.go
index 3fa3a086..0bb44b27 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/osv/osv.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/osv/osv.go
@@ -97,7 +97,7 @@ type Range struct {
 	Events []RangeEvent `json:"events"`
 }
 
-// Reference type is a reference (link) type.
+// ReferenceType is a reference (link) type.
 type ReferenceType string
 
 const (
@@ -235,4 +235,6 @@ type DatabaseSpecific struct {
 	// The URL of the Go advisory for this vulnerability, of the form
 	// "https://pkg.go.dev/GO-YYYY-XXXX".
 	URL string `json:"url,omitempty"`
+	// The review status of this report (UNREVIEWED or REVIEWED).
+	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/osv/review_status.go b/notifier/vendor/golang.org/x/vuln/internal/osv/review_status.go
new file mode 100644
index 00000000..7185e184
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/osv/review_status.go
@@ -0,0 +1,67 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package osv
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type ReviewStatus int
+
+const (
+	ReviewStatusUnknown ReviewStatus = iota
+	ReviewStatusUnreviewed
+	ReviewStatusReviewed
+)
+
+var statusStrs = []string{
+	ReviewStatusUnknown:    "",
+	ReviewStatusUnreviewed: "UNREVIEWED",
+	ReviewStatusReviewed:   "REVIEWED",
+}
+
+func (r ReviewStatus) String() string {
+	if !r.IsValid() {
+		return fmt.Sprintf("INVALID(%d)", r)
+	}
+	return statusStrs[r]
+}
+
+func ReviewStatusValues() []string {
+	return statusStrs[1:]
+}
+
+func (r ReviewStatus) IsValid() bool {
+	return int(r) >= 0 && int(r) < len(statusStrs)
+}
+
+func ToReviewStatus(s string) (ReviewStatus, bool) {
+	for stat, str := range statusStrs {
+		if s == str {
+			return ReviewStatus(stat), true
+		}
+	}
+	return 0, false
+}
+
+func (r ReviewStatus) MarshalJSON() ([]byte, error) {
+	if !r.IsValid() {
+		return nil, fmt.Errorf("MarshalJSON: unrecognized review status: %d", r)
+	}
+	return json.Marshal(r.String())
+}
+
+func (r *ReviewStatus) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if rs, ok := ToReviewStatus(s); ok {
+		*r = rs
+		return nil
+	}
+	return fmt.Errorf("UnmarshalJSON: unrecognized review status: %s", s)
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/sarif/handler.go b/notifier/vendor/golang.org/x/vuln/internal/sarif/handler.go
new file mode 100644
index 00000000..d9e585b7
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/sarif/handler.go
@@ -0,0 +1,409 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"path/filepath"
+	"sort"
+
+	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
+)
+
+// handler for sarif output.
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(c *govulncheck.Config) error {
+	h.cfg = c
+	return nil
+}
+
+func (h *handler) Progress(p *govulncheck.Progress) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is equal to an existing one and
+			// because of the invariant on h.findings, it is
+			// also equal to all existing ones.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print out to w the sarif json output.
+// This is needed as sarif is not streamed.
+func (h *handler) Flush() error {
+	sLog := toSarif(h)
+	s, err := json.MarshalIndent(sLog, "", "  ")
+	if err != nil {
+		return err
+	}
+	h.w.Write(s)
+	return nil
+}
+
+func toSarif(h *handler) Log {
+	cfg := h.cfg
+	r := Run{
+		Tool: Tool{
+			Driver: Driver{
+				Name:           cfg.ScannerName,
+				Version:        cfg.ScannerVersion,
+				InformationURI: "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
+				Properties:     *cfg,
+				Rules:          rules(h),
+			},
+		},
+		Results: results(h),
+	}
+
+	return Log{
+		Version: "2.1.0",
+		Schema:  "https://json.schemastore.org/sarif-2.1.0.json",
+		Runs:    []Run{r},
+	}
+}
+
+func rules(h *handler) []Rule {
+	rs := make([]Rule, 0, len(h.findings)) // must not be nil
+	for id := range h.findings {
+		osv := h.osvs[id]
+		// s is either summary if it exists, or details
+		// otherwise. Govulncheck text does the same.
+		s := osv.Summary
+		if s == "" {
+			s = osv.Details
+		}
+		rs = append(rs, Rule{
+			ID:               osv.ID,
+			ShortDescription: Description{Text: fmt.Sprintf("[%s] %s", osv.ID, s)},
+			FullDescription:  Description{Text: s},
+			HelpURI:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", osv.ID),
+			Help:             Description{Text: osv.Details},
+			Properties:       RuleTags{Tags: tags(osv)},
+		})
+	}
+	sort.SliceStable(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
+	return rs
+}
+
+// tags returns an slice of zero or
+// more aliases of o.
+func tags(o *osv.Entry) []string {
+	if len(o.Aliases) > 0 {
+		return o.Aliases
+	}
+	return []string{} // must not be nil
+}
+
+func results(h *handler) []Result {
+	results := make([]Result, 0, len(h.findings)) // must not be nil
+	for osv, fs := range h.findings {
+		var locs []Location
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			// Attach result to the go.mod file for source analysis.
+			// But there is no such place for binaries.
+			locs = []Location{{PhysicalLocation: PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       "go.mod",
+					URIBaseID: SrcRootID,
+				},
+				Region: Region{StartLine: 1}, // for now, point to the first line
+			},
+				Message: Description{Text: fmt.Sprintf("Findings for vulnerability %s", osv)}, // not having a message here results in an invalid sarif
+			}}
+		}
+
+		res := Result{
+			RuleID:    osv,
+			Level:     level(fs[0], h.cfg),
+			Message:   Description{Text: resultMessage(fs, h.cfg)},
+			Stacks:    stacks(h, fs),
+			CodeFlows: codeFlows(h, fs),
+			Locations: locs,
+		}
+		results = append(results, res)
+	}
+	sort.SliceStable(results, func(i, j int) bool { return results[i].RuleID < results[j].RuleID }) // for deterministic output
+	return results
+}
+
+func resultMessage(findings []*govulncheck.Finding, cfg *govulncheck.Config) string {
+	// We can infer the findings' level by just looking at the
+	// top trace frame of any finding.
+	frame := findings[0].Trace[0]
+	uniqueElems := make(map[string]bool)
+	if frame.Function == "" && frame.Package == "" { // module level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Module] = true
+		}
+	} else { // symbol and package level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Package] = true
+		}
+	}
+	var elems []string
+	for e := range uniqueElems {
+		elems = append(elems, e)
+	}
+	sort.Strings(elems)
+
+	l := len(elems)
+	elemList := list(elems)
+	main, addition := "", ""
+	const runCallAnalysis = "Run the call-level analysis to understand whether your code actually calls the vulnerabilities."
+	switch {
+	case frame.Function != "":
+		main = fmt.Sprintf("calls vulnerable functions in %d package%s (%s).", l, choose("", "s", l == 1), elemList)
+	case frame.Package != "":
+		main = fmt.Sprintf("imports %d vulnerable package%s (%s)", l, choose("", "s", l == 1), elemList)
+		addition = choose(", but doesn’t appear to call any of the vulnerable symbols.", ". "+runCallAnalysis, cfg.ScanLevel.WantSymbols())
+	default:
+		main = fmt.Sprintf("depends on %d vulnerable module%s (%s)", l, choose("", "s", l == 1), elemList)
+		informational := ", but doesn't appear to " + choose("call", "import", cfg.ScanLevel.WantSymbols()) + " any of the vulnerable symbols."
+		addition = choose(informational, ". "+runCallAnalysis, cfg.ScanLevel.WantPackages())
+	}
+
+	return fmt.Sprintf("Your code %s%s", main, addition)
+}
+
+const (
+	errorLevel         = "error"
+	warningLevel       = "warning"
+	informationalLevel = "note"
+)
+
+func level(f *govulncheck.Finding, cfg *govulncheck.Config) string {
+	fr := f.Trace[0]
+	switch {
+	case cfg.ScanLevel.WantSymbols():
+		if fr.Function != "" {
+			return errorLevel
+		}
+		if fr.Package != "" {
+			return warningLevel
+		}
+		return informationalLevel
+	case cfg.ScanLevel.WantPackages():
+		if fr.Package != "" {
+			return errorLevel
+		}
+		return warningLevel
+	default:
+		return errorLevel
+	}
+}
+
+func stacks(h *handler, fs []*govulncheck.Finding) []Stack {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	var stacks []Stack
+	for _, f := range fs {
+		stacks = append(stacks, stack(h, f))
+	}
+	// Sort stacks for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(stacks, func(i, j int) bool { return stacks[i].Message.Text < stacks[j].Message.Text })
+	return stacks
+}
+
+// stack transforms call stack in f to a sarif stack.
+func stack(h *handler, f *govulncheck.Finding) Stack {
+	trace := f.Trace
+	top := trace[len(trace)-1] // belongs to top level module
+
+	frames := make([]Frame, 0, len(trace)) // must not be nil
+	for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+		frame := trace[i]
+		pos := govulncheck.Position{Line: 1, Column: 1}
+		if frame.Position != nil {
+			pos = *frame.Position
+		}
+
+		sf := Frame{
+			Module:   frame.Module + "@" + frame.Version,
+			Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+		}
+		file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			sf.Location.PhysicalLocation = PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       file,
+					URIBaseID: base,
+				},
+				Region: Region{
+					StartLine:   pos.Line,
+					StartColumn: pos.Column,
+				},
+			}
+		}
+		frames = append(frames, sf)
+	}
+
+	return Stack{
+		Frames:  frames,
+		Message: Description{Text: fmt.Sprintf("A call stack for vulnerable function %s", symbol(trace[0]))},
+	}
+}
+
+func codeFlows(h *handler, fs []*govulncheck.Finding) []CodeFlow {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	// group call stacks per symbol. There should
+	// be one call stack currently per symbol, but
+	// this might change in the future.
+	m := make(map[govulncheck.Frame][]*govulncheck.Finding)
+	for _, f := range fs {
+		// fr.Position is currently the position
+		// of the definition of the vuln symbol
+		fr := *f.Trace[0]
+		m[fr] = append(m[fr], f)
+	}
+
+	var codeFlows []CodeFlow
+	for fr, fs := range m {
+		tfs := threadFlows(h, fs)
+		codeFlows = append(codeFlows, CodeFlow{
+			ThreadFlows: tfs,
+			// TODO: should we instead show the message from govulncheck text output?
+			Message: Description{Text: fmt.Sprintf("A summarized code flow for vulnerable function %s", symbol(&fr))},
+		})
+	}
+	// Sort flows for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(codeFlows, func(i, j int) bool { return codeFlows[i].Message.Text < codeFlows[j].Message.Text })
+	return codeFlows
+}
+
+func threadFlows(h *handler, fs []*govulncheck.Finding) []ThreadFlow {
+	tfs := make([]ThreadFlow, 0, len(fs)) // must not be nil
+	for _, f := range fs {
+		trace := traces.Compact(f)
+		top := trace[len(trace)-1] // belongs to top level module
+
+		var tf []ThreadFlowLocation
+		for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+			// TODO: should we, similar to govulncheck text output, only
+			// mention three elements of the compact trace?
+			frame := trace[i]
+			pos := govulncheck.Position{Line: 1, Column: 1}
+			if frame.Position != nil {
+				pos = *frame.Position
+			}
+
+			tfl := ThreadFlowLocation{
+				Module:   frame.Module + "@" + frame.Version,
+				Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+			}
+			file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+			if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+				tfl.Location.PhysicalLocation = PhysicalLocation{
+					ArtifactLocation: ArtifactLocation{
+						URI:       file,
+						URIBaseID: base,
+					},
+					Region: Region{
+						StartLine:   pos.Line,
+						StartColumn: pos.Column,
+					},
+				}
+			}
+			tf = append(tf, tfl)
+		}
+		tfs = append(tfs, ThreadFlow{Locations: tf})
+	}
+	return tfs
+}
+
+func fileURIInfo(filename, top, module, version string) (string, string) {
+	if top == module {
+		return filename, SrcRootID
+	}
+	if module == internal.GoStdModulePath {
+		return filename, GoRootID
+	}
+	return filepath.ToSlash(filepath.Join(module+"@"+version, filename)), GoModCacheID
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/sarif/sarif.go b/notifier/vendor/golang.org/x/vuln/internal/sarif/sarif.go
new file mode 100644
index 00000000..934ade8b
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/sarif/sarif.go
@@ -0,0 +1,213 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sarif defines Static Analysis Results Interchange Format
+// (SARIF) types supported by govulncheck.
+//
+// The implementation covers the subset of the specification available
+// at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+//
+// The sarif encoding models govulncheck findings as Results. Each
+// Result encodes findings for a unique OSV entry at the most precise
+// detected level only. CodeFlows summarize call stacks, similar to govulncheck
+// textual output, while Stacks contain call stack information verbatim.
+//
+// The result Levels are defined by the govulncheck.ScanLevel and the most
+// precise level at which the finding was detected. Result error is produced
+// when the finding level matches the user desired level of scan precision;
+// all other finding levels are then classified as progressively weaker.
+// For instance, if the user specified symbol scan level and govulncheck
+// detected a use of a vulnerable symbol, then the Result will have error
+// Level. If the symbol was not used but its package was imported, then the
+// Result Level is warning, and so on.
+//
+// Each Result is attached to the first line of the go.mod file. Other
+// ArtifactLocations are paths relative to their enclosing modules.
+// Similar to JSON output format, this makes govulncheck sarif locations
+// portable.
+//
+// The relative paths in PhysicalLocations also come with a URIBaseID offset.
+// Paths for the source module analyzed, the Go standard library, and third-party
+// dependencies are relative to %SRCROOT%, %GOROOT%, and %GOMODCACHE% offsets,
+// resp. We note that the URIBaseID offsets are not explicitly defined in
+// the sarif output. It is the clients responsibility to set them to resolve
+// paths at their local machines.
+//
+// All paths use "/" delimiter for portability.
+//
+// Properties field of a Tool.Driver is a govulncheck.Config used for the
+// invocation of govulncheck producing the Results. Properties field of
+// a Rule contains information on CVE and GHSA aliases for the corresponding
+// rule OSV. Clients can use this information to, say, suppress and filter
+// vulnerabilities.
+//
+// Please see the definition of types below for more information.
+package sarif
+
+import "golang.org/x/vuln/internal/govulncheck"
+
+// Log is the top-level SARIF object encoded in UTF-8.
+type Log struct {
+	// Version should always be "2.1.0"
+	Version string `json:"version,omitempty"`
+
+	// Schema should always be "https://json.schemastore.org/sarif-2.1.0.json"
+	Schema string `json:"$schema,omitempty"`
+
+	// Runs describes executions of static analysis tools. For govulncheck,
+	// there will be only one run object.
+	Runs []Run `json:"runs,omitempty"`
+}
+
+// Run summarizes results of a single invocation of a static analysis tool,
+// in this case govulncheck.
+type Run struct {
+	Tool Tool `json:"tool,omitempty"`
+	// Results contain govulncheck findings. There should be exactly one
+	// Result per a detected use of an OSV.
+	Results []Result `json:"results"`
+}
+
+// Tool captures information about govulncheck analysis that was run.
+type Tool struct {
+	Driver Driver `json:"driver,omitempty"`
+}
+
+// Driver provides details about the govulncheck binary being executed.
+type Driver struct {
+	// Name is "govulncheck"
+	Name string `json:"name,omitempty"`
+	// Version is the govulncheck version
+	Version string `json:"semanticVersion,omitempty"`
+	// InformationURI points to the description of govulncheck tool
+	InformationURI string `json:"informationUri,omitempty"`
+	// Properties are govulncheck run metadata, such as vuln db, Go version, etc.
+	Properties govulncheck.Config `json:"properties,omitempty"`
+
+	Rules []Rule `json:"rules"`
+}
+
+// Rule corresponds to the static analysis rule/analyzer that
+// produces findings. For govulncheck, rules are OSVs.
+type Rule struct {
+	// ID is OSV.ID
+	ID               string      `json:"id,omitempty"`
+	ShortDescription Description `json:"shortDescription,omitempty"`
+	FullDescription  Description `json:"fullDescription,omitempty"`
+	Help             Description `json:"help,omitempty"`
+	HelpURI          string      `json:"helpUri,omitempty"`
+	// Properties contain OSV.Aliases (CVEs and GHSAs) as tags.
+	// Consumers of govulncheck SARIF can use these tags to filter
+	// results.
+	Properties RuleTags `json:"properties,omitempty"`
+}
+
+// RuleTags defines properties.tags.
+type RuleTags struct {
+	Tags []string `json:"tags"`
+}
+
+// Description is a text in its raw or markdown form.
+type Description struct {
+	Text     string `json:"text,omitempty"`
+	Markdown string `json:"markdown,omitempty"`
+}
+
+// Result is a set of govulncheck findings for an OSV. For call stack
+// mode, it will contain call stacks for the OSV. There is exactly
+// one Result per detected OSV. Only findings at the most precise
+// detected level appear in the Result. For instance, if there are
+// symbol findings for an OSV, those findings will be in the Result,
+// but not the package and module level findings for the same OSV.
+type Result struct {
+	// RuleID is the Rule.ID/OSV producing the finding.
+	RuleID string `json:"ruleId,omitempty"`
+	// Level is one of "error", "warning", and "note".
+	Level string `json:"level,omitempty"`
+	// Message explains the overall findings.
+	Message Description `json:"message,omitempty"`
+	// Locations to which the findings are associated. Always
+	// a single location pointing to the first line of the go.mod
+	// file. The path to the file is "go.mod".
+	Locations []Location `json:"locations,omitempty"`
+	// CodeFlows summarize call stacks produced by govulncheck.
+	CodeFlows []CodeFlow `json:"codeFlows,omitempty"`
+	// Stacks encode call stacks produced by govulncheck.
+	Stacks []Stack `json:"stacks,omitempty"`
+}
+
+// CodeFlow summarizes a detected offending flow of information in terms of
+// code locations. More precisely, it can contain several related information
+// flows, keeping them together. In govulncheck, those can be all call stacks
+// for, say, a particular symbol or package.
+type CodeFlow struct {
+	// ThreadFlows is effectively a set of related information flows.
+	ThreadFlows []ThreadFlow `json:"threadFlows"`
+	Message     Description  `json:"message,omitempty"`
+}
+
+// ThreadFlow encodes an information flow as a sequence of locations.
+// For govulncheck, it can encode a call stack.
+type ThreadFlow struct {
+	Locations []ThreadFlowLocation `json:"locations,omitempty"`
+}
+
+type ThreadFlowLocation struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module string `json:"module,omitempty"`
+	// Location also contains a Message field.
+	Location Location `json:"location,omitempty"`
+}
+
+// Stack is a sequence of frames and can encode a govulncheck call stack.
+type Stack struct {
+	Message Description `json:"message,omitempty"`
+	Frames  []Frame     `json:"frames"`
+}
+
+// Frame is effectively a module location. It can also contain thread and
+// parameter info, but those are not needed for govulncheck.
+type Frame struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module   string   `json:"module,omitempty"`
+	Location Location `json:"location,omitempty"`
+}
+
+// Location is currently a physical location annotated with a message.
+type Location struct {
+	PhysicalLocation PhysicalLocation `json:"physicalLocation,omitempty"`
+	Message          Description      `json:"message,omitempty"`
+}
+
+type PhysicalLocation struct {
+	ArtifactLocation ArtifactLocation `json:"artifactLocation,omitempty"`
+	Region           Region           `json:"region,omitempty"`
+}
+
+const (
+	SrcRootID    = "%SRCROOT%"
+	GoRootID     = "%GOROOT%"
+	GoModCacheID = "%GOMODCACHE%"
+)
+
+// ArtifactLocation is a path to an offending file.
+type ArtifactLocation struct {
+	// URI is a path relative to URIBaseID.
+	URI string `json:"uri,omitempty"`
+	// URIBaseID is offset for URI, one of %SRCROOT%, %GOROOT%,
+	// and %GOMODCACHE%.
+	URIBaseID string `json:"uriBaseId,omitempty"`
+}
+
+// Region is a target region within a file.
+type Region struct {
+	StartLine   int `json:"startLine,omitempty"`
+	StartColumn int `json:"startColumn,omitempty"`
+	EndLine     int `json:"endLine,omitempty"`
+	EndColumn   int `json:"endColumn,omitempty"`
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/sarif/utils.go b/notifier/vendor/golang.org/x/vuln/internal/sarif/utils.go
new file mode 100644
index 00000000..045cac76
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/sarif/utils.go
@@ -0,0 +1,46 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+func choose(s1, s2 string, cond bool) string {
+	if cond {
+		return s1
+	}
+	return s2
+}
+
+func list(elems []string) string {
+	l := len(elems)
+	if l == 0 {
+		return ""
+	}
+	if l == 1 {
+		return elems[0]
+	}
+
+	cList := strings.Join(elems[:l-1], ", ")
+	return cList + choose("", ",", l == 2) + " and " + elems[l-1]
+}
+
+// symbol is simplified adaptation of internal/scan/symbol.
+func symbol(fr *govulncheck.Frame) string {
+	if fr.Function == "" {
+		return ""
+	}
+	sym := strings.Split(fr.Function, "$")[0]
+	if fr.Receiver != "" {
+		sym = fr.Receiver + "." + sym
+	}
+	if fr.Package != "" {
+		sym = fr.Package + "." + sym
+	}
+	return sym
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/binary.go b/notifier/vendor/golang.org/x/vuln/internal/scan/binary.go
index 76b17f75..5cc8f6ba 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/binary.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/binary.go
@@ -2,93 +2,109 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package scan
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
+	"errors"
 	"os"
-	"strings"
-	"unicode"
+	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
-// runBinary detects presence of vulnerable symbols in an executable.
-func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) error {
-	var exe *os.File
-	exe, err := os.Open(cfg.patterns[0])
+// runBinary detects presence of vulnerable symbols in an executable or its minimal blob representation.
+func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
 	if err != nil {
 		return err
 	}
-	defer exe.Close()
 
 	p := &govulncheck.Progress{Message: binaryProgressMessage}
 	if err := handler.Progress(p); err != nil {
 		return err
 	}
-	vr, err := binary(ctx, exe, &cfg.Config, client)
-	if err != nil {
-		return fmt.Errorf("govulncheck: %v", err)
-	}
-	callstacks := binaryCallstacks(vr)
-	return emitResult(handler, vr, callstacks)
+	return vulncheck.Binary(ctx, handler, bin, &cfg.Config, client)
 }
 
-func binaryCallstacks(vr *vulncheck.Result) map[*vulncheck.Vuln]vulncheck.CallStack {
-	callstacks := map[*vulncheck.Vuln]vulncheck.CallStack{}
-	for _, vv := range uniqueVulns(vr.Vulns) {
-		f := &vulncheck.FuncNode{Package: vv.ImportSink, Name: vv.Symbol}
-		parts := strings.Split(vv.Symbol, ".")
-		if len(parts) != 1 {
-			f.RecvType = parts[0]
-			f.Name = parts[1]
+func createBin(path string) (*vulncheck.Bin, error) {
+	// First check if the path points to a Go binary. Otherwise, blob
+	// parsing might json decode a Go binary which takes time.
+	//
+	// TODO(#64716): use fingerprinting to make this precise, clean, and fast.
+	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(path)
+	if err == nil {
+		var main *packages.Module
+		if bi.Main.Path != "" {
+			main = &packages.Module{
+				Path:    bi.Main.Path,
+				Version: bi.Main.Version,
+			}
 		}
-		callstacks[vv] = vulncheck.CallStack{vulncheck.StackEntry{Function: f}}
+
+		return &vulncheck.Bin{
+			Path:       bi.Path,
+			Main:       main,
+			Modules:    mods,
+			PkgSymbols: packageSymbols,
+			GoVersion:  bi.GoVersion,
+			GOOS:       findSetting("GOOS", bi),
+			GOARCH:     findSetting("GOARCH", bi),
+		}, nil
+	}
+
+	// Otherwise, see if the path points to a valid blob.
+	bin := parseBlob(path)
+	if bin != nil {
+		return bin, nil
 	}
-	return callstacks
+
+	return nil, errors.New("unrecognized binary format")
 }
 
-// uniqueVulns does for binary mode what uniqueCallStack does for source mode.
-// It tries not to report redundant symbols. Since there are no call stacks in
-// binary mode, the following approximate approach is used. Do not report unexported
-// symbols for a  triple if there are some exported symbols.
-// Otherwise, report all unexported symbols to avoid not reporting anything.
-func uniqueVulns(vulns []*vulncheck.Vuln) []*vulncheck.Vuln {
-	type key struct {
-		id  string
-		pkg string
-		mod string
+// parseBlob extracts vulncheck.Bin from a valid blob at path.
+// If it cannot recognize a valid blob, returns nil.
+func parseBlob(path string) *vulncheck.Bin {
+	from, err := os.Open(path)
+	if err != nil {
+		return nil
 	}
-	hasExported := make(map[key]bool)
-	for _, v := range vulns {
-		if isExported(v.Symbol) {
-			k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-			hasExported[k] = true
-		}
+	defer from.Close()
+
+	dec := json.NewDecoder(from)
+
+	var h header
+	if err := dec.Decode(&h); err != nil {
+		return nil // no header
+	} else if h.Name != extractModeID || h.Version != extractModeVersion {
+		return nil // invalid header
 	}
 
-	var uniques []*vulncheck.Vuln
-	for _, v := range vulns {
-		k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-		if isExported(v.Symbol) || !hasExported[k] {
-			uniques = append(uniques, v)
-		}
+	var b vulncheck.Bin
+	if err := dec.Decode(&b); err != nil {
+		return nil // no body
+	}
+	if dec.More() {
+		return nil // we want just header and body, nothing else
 	}
-	return uniques
+	return &b
 }
 
-// isExported checks if the symbol is exported. Assumes that the
-// symbol is of the form "identifier" or "identifier1.identifier2".
-func isExported(symbol string) bool {
-	parts := strings.Split(symbol, ".")
-	if len(parts) == 1 {
-		return unicode.IsUpper(rune(symbol[0]))
+// findSetting returns value of setting from bi if present.
+// Otherwise, returns "".
+func findSetting(setting string, bi *debug.BuildInfo) string {
+	for _, s := range bi.Settings {
+		if s.Key == setting {
+			return s.Value
+		}
 	}
-	return unicode.IsUpper(rune(parts[1][0]))
+	return ""
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/binary_118.go b/notifier/vendor/golang.org/x/vuln/internal/scan/binary_118.go
deleted file mode 100644
index d4345f3b..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/binary_118.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package scan
-
-import (
-	"context"
-	"io"
-
-	"golang.org/x/vuln/internal/client"
-	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *vulncheck.Result, err error) {
-	return vulncheck.Binary(ctx, exe, cfg, client)
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/binary_not118.go b/notifier/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
deleted file mode 100644
index 0f66a02c..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package scan
-
-import (
-	"context"
-	"errors"
-	"io"
-
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *vulncheck.Config) (_ *vulncheck.Result, err error) {
-	return nil, errors.New("compile with Go 1.18 or higher to analyze binary files")
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/errors.go b/notifier/vendor/golang.org/x/vuln/internal/scan/errors.go
index 920edd4c..c28e3c5a 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/errors.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/errors.go
@@ -22,7 +22,7 @@ var (
 	// errUsage indicates that there was a usage error on the command line.
 	//
 	// In this case, we assume that the user does not know how to run
-	// govulncheck, and print the usage message with exit status 2.
+	// govulncheck and exit with status 2.
 	errUsage = &exitCodeError{message: "invalid usage", code: 2}
 
 	// errGoVersionMismatch is used to indicate that there is a mismatch between
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/extract.go b/notifier/vendor/golang.org/x/vuln/internal/scan/extract.go
new file mode 100644
index 00000000..58a3f673
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/extract.go
@@ -0,0 +1,60 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scan
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"sort"
+
+	"golang.org/x/vuln/internal/derrors"
+	"golang.org/x/vuln/internal/vulncheck"
+)
+
+const (
+	// extractModeID is the unique name of the extract mode protocol
+	extractModeID      = "govulncheck-extract"
+	extractModeVersion = "0.1.0"
+)
+
+// header information for the blob output.
+type header struct {
+	Name    string `json:"name"`
+	Version string `json:"version"`
+}
+
+// runExtract dumps the extracted abstraction of binary at cfg.patterns to out.
+// It prints out exactly two blob messages, one with the header and one with
+// the vulncheck.Bin as the body.
+func runExtract(cfg *config, out io.Writer) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
+	if err != nil {
+		return err
+	}
+	sortBin(bin) // sort for easier testing and validation
+	header := header{
+		Name:    extractModeID,
+		Version: extractModeVersion,
+	}
+
+	enc := json.NewEncoder(out)
+
+	if err := enc.Encode(header); err != nil {
+		return fmt.Errorf("marshaling blob header: %v", err)
+	}
+	if err := enc.Encode(bin); err != nil {
+		return fmt.Errorf("marshaling blob body: %v", err)
+	}
+	return nil
+}
+
+func sortBin(bin *vulncheck.Bin) {
+	sort.SliceStable(bin.PkgSymbols, func(i, j int) bool {
+		return bin.PkgSymbols[i].Pkg+"."+bin.PkgSymbols[i].Name < bin.PkgSymbols[j].Pkg+"."+bin.PkgSymbols[j].Name
+	})
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/flags.go b/notifier/vendor/golang.org/x/vuln/internal/scan/flags.go
index 1e581102..5512540f 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/flags.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/flags.go
@@ -19,37 +19,37 @@ import (
 type config struct {
 	govulncheck.Config
 	patterns []string
-	mode     string
 	db       string
-	json     bool
 	dir      string
-	tags     []string
+	tags     buildutil.TagsFlag
 	test     bool
-	show     []string
+	show     ShowFlag
+	format   FormatFlag
 	env      []string
 }
 
-const (
-	modeBinary  = "binary"
-	modeSource  = "source"
-	modeConvert = "convert" // only intended for use by gopls
-	modeQuery   = "query"   // only intended for use by gopls
-)
-
 func parseFlags(cfg *config, stderr io.Writer, args []string) error {
-	var tagsFlag buildutil.TagsFlag
-	var showFlag showFlag
+	var version bool
+	var json bool
+	var scanFlag ScanFlag
+	var modeFlag ModeFlag
 	flags := flag.NewFlagSet("", flag.ContinueOnError)
 	flags.SetOutput(stderr)
-	flags.BoolVar(&cfg.json, "json", false, "output JSON")
-	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode)")
+	flags.BoolVar(&json, "json", false, "output JSON (Go compatible legacy flag, see format flag)")
+	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode, default false)")
 	flags.StringVar(&cfg.dir, "C", "", "change to `dir` before running govulncheck")
 	flags.StringVar(&cfg.db, "db", "https://vuln.go.dev", "vulnerability database `url`")
-	flags.StringVar(&cfg.mode, "mode", modeSource, "supports source or binary")
-	flags.Var(&tagsFlag, "tags", "comma-separated `list` of build tags")
-	flags.Var(&showFlag, "show", "enable display of additional information specified by `list`")
-	scanLevel := flags.String("scan-level", "symbol", "set the scanning level desired, one of module, package or symbol")
-	flags.Usage = func() {
+	flags.Var(&modeFlag, "mode", "supports 'source', 'binary', and 'extract' (default 'source')")
+	flags.Var(&cfg.tags, "tags", "comma-separated `list` of build tags")
+	flags.Var(&cfg.show, "show", "enable display of additional information specified by the comma separated `list`\nThe supported values are 'traces','color', 'version', and 'verbose'")
+	flags.Var(&cfg.format, "format", "specify format output\nThe supported values are 'text', 'json', 'sarif', and 'openvex' (default 'text')")
+	flags.BoolVar(&version, "version", false, "print the version information")
+	flags.Var(&scanFlag, "scan", "set the scanning level desired, one of 'module', 'package', or 'symbol' (default 'symbol')")
+
+	// We don't want to print the whole usage message on each flags
+	// error, so we set to a no-op and do the printing ourselves.
+	flags.Usage = func() {}
+	usage := func() {
 		fmt.Fprint(flags.Output(), `Govulncheck reports known vulnerabilities in dependencies.
 
 Usage:
@@ -61,44 +61,60 @@ Usage:
 		flags.PrintDefaults()
 		fmt.Fprintf(flags.Output(), "\n%s\n", detailsMessage)
 	}
+
 	if err := flags.Parse(args); err != nil {
 		if err == flag.ErrHelp {
+			usage() // print usage only on help
 			return errHelp
 		}
-		return err
+		return errUsage
 	}
 	cfg.patterns = flags.Args()
-	if cfg.mode != modeConvert && len(cfg.patterns) == 0 {
-		flags.Usage()
-		return errUsage
+	if version {
+		cfg.show = append(cfg.show, "version")
 	}
-	cfg.tags = tagsFlag
-	cfg.show = showFlag
-	cfg.ScanLevel = govulncheck.ScanLevel(*scanLevel)
-	if err := validateConfig(cfg); err != nil {
+	cfg.ScanLevel = govulncheck.ScanLevel(scanFlag)
+	cfg.ScanMode = govulncheck.ScanMode(modeFlag)
+	if err := validateConfig(cfg, json); err != nil {
 		fmt.Fprintln(flags.Output(), err)
 		return errUsage
 	}
 	return nil
 }
 
-var supportedModes = map[string]bool{
-	modeSource:  true,
-	modeBinary:  true,
-	modeConvert: true,
-	modeQuery:   true,
-}
+func validateConfig(cfg *config, json bool) error {
+	// take care of default values
+	if cfg.ScanMode == "" {
+		cfg.ScanMode = govulncheck.ScanModeSource
+	}
+	if cfg.ScanLevel == "" {
+		cfg.ScanLevel = govulncheck.ScanLevelSymbol
+	}
+	if json {
+		if cfg.format != formatUnset {
+			return fmt.Errorf("the -json flag cannot be used with -format flag")
+		}
+		cfg.format = formatJSON
+	} else {
+		if cfg.format == formatUnset {
+			cfg.format = formatText
+		}
+	}
 
-func validateConfig(cfg *config) error {
-	if _, ok := supportedModes[cfg.mode]; !ok {
-		return fmt.Errorf("%q is not a valid mode", cfg.mode)
+	// show flag is only supported with text output
+	if cfg.format != formatText && len(cfg.show) > 0 {
+		return fmt.Errorf("the -show flag is not supported for %s output", cfg.format)
 	}
-	switch cfg.mode {
-	case modeSource:
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		if len(cfg.patterns) == 1 && isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is a file.\n\n%v", cfg.patterns[0], errNoBinaryFlag)
 		}
-	case modeBinary:
+		if cfg.ScanLevel == govulncheck.ScanLevelModule && len(cfg.patterns) != 0 {
+			return fmt.Errorf("patterns are not accepted for module only scanning")
+		}
+	case govulncheck.ScanModeBinary:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in binary mode")
 		}
@@ -111,7 +127,23 @@ func validateConfig(cfg *config) error {
 		if !isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is not a file", cfg.patterns[0])
 		}
-	case modeConvert:
+	case govulncheck.ScanModeExtract:
+		if cfg.test {
+			return fmt.Errorf("the -test flag is not supported in extract mode")
+		}
+		if len(cfg.tags) > 0 {
+			return fmt.Errorf("the -tags flag is not supported in extract mode")
+		}
+		if len(cfg.patterns) != 1 {
+			return fmt.Errorf("only 1 binary can be extracted at a time")
+		}
+		if cfg.format == formatJSON {
+			return fmt.Errorf("the json format must be off in extract mode")
+		}
+		if !isFile(cfg.patterns[0]) {
+			return fmt.Errorf("%q is not a file (source extraction is not supported)", cfg.patterns[0])
+		}
+	case govulncheck.ScanModeConvert:
 		if len(cfg.patterns) != 0 {
 			return fmt.Errorf("patterns are not accepted in convert mode")
 		}
@@ -124,15 +156,15 @@ func validateConfig(cfg *config) error {
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in convert mode")
 		}
-	case modeQuery:
+	case govulncheck.ScanModeQuery:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in query mode")
 		}
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in query mode")
 		}
-		if !cfg.json {
-			return fmt.Errorf("the -json flag must be set in query mode")
+		if cfg.format != formatJSON {
+			return fmt.Errorf("the json format must be set in query mode")
 		}
 		for _, pattern := range cfg.patterns {
 			// Parse the input here so that we can catch errors before
@@ -142,9 +174,6 @@ func validateConfig(cfg *config) error {
 			}
 		}
 	}
-	if cfg.json && len(cfg.show) > 0 {
-		return fmt.Errorf("the -show flag is not supported for JSON output")
-	}
 	return nil
 }
 
@@ -156,26 +185,119 @@ func isFile(path string) bool {
 	return !s.IsDir()
 }
 
-// fileExists checks if file path exists. Returns true
-// if the file exists or it cannot prove that it does
-// not exist. Otherwise, returns false.
-func fileExists(path string) bool {
-	if _, err := os.Stat(path); err == nil {
-		return true
-	} else if errors.Is(err, os.ErrNotExist) {
-		return false
+var errFlagParse = errors.New("see -help for details")
+
+// ShowFlag is used for parsing and validation of
+// govulncheck -show flag.
+type ShowFlag []string
+
+var supportedShows = map[string]bool{
+	"traces":  true,
+	"color":   true,
+	"verbose": true,
+	"version": true,
+}
+
+func (v *ShowFlag) Set(s string) error {
+	if s == "" {
+		return nil
+	}
+	for _, show := range strings.Split(s, ",") {
+		sh := strings.TrimSpace(show)
+		if _, ok := supportedShows[sh]; !ok {
+			return errFlagParse
+		}
+		*v = append(*v, sh)
 	}
-	// Conservatively return true if os.Stat fails
-	// for some other reason.
-	return true
+	return nil
 }
 
-type showFlag []string
+func (v *ShowFlag) Get() interface{} { return *v }
+func (v *ShowFlag) String() string   { return "" }
+
+// Update the text handler h with values of the flag.
+func (v ShowFlag) Update(h *TextHandler) {
+	for _, show := range v {
+		switch show {
+		case "traces":
+			h.showTraces = true
+		case "color":
+			h.showColor = true
+		case "version":
+			h.showVersion = true
+		case "verbose":
+			h.showVerbose = true
+		}
+	}
+}
 
-func (v *showFlag) Set(s string) error {
-	*v = append(*v, strings.Split(s, ",")...)
+// FormatFlag is used for parsing and validation of
+// govulncheck -format flag.
+type FormatFlag string
+
+const (
+	formatUnset   = ""
+	formatJSON    = "json"
+	formatText    = "text"
+	formatSarif   = "sarif"
+	formatOpenVEX = "openvex"
+)
+
+var supportedFormats = map[string]bool{
+	formatJSON:    true,
+	formatText:    true,
+	formatSarif:   true,
+	formatOpenVEX: true,
+}
+
+func (f *FormatFlag) Get() interface{} { return *f }
+func (f *FormatFlag) Set(s string) error {
+	if _, ok := supportedFormats[s]; !ok {
+		return errFlagParse
+	}
+	*f = FormatFlag(s)
 	return nil
 }
+func (f *FormatFlag) String() string { return "" }
 
-func (f *showFlag) Get() interface{} { return *f }
-func (f *showFlag) String() string   { return "" }
+// ModeFlag is used for parsing and validation of
+// govulncheck -mode flag.
+type ModeFlag string
+
+var supportedModes = map[string]bool{
+	govulncheck.ScanModeSource:  true,
+	govulncheck.ScanModeBinary:  true,
+	govulncheck.ScanModeConvert: true,
+	govulncheck.ScanModeQuery:   true,
+	govulncheck.ScanModeExtract: true,
+}
+
+func (f *ModeFlag) Get() interface{} { return *f }
+func (f *ModeFlag) Set(s string) error {
+	if _, ok := supportedModes[s]; !ok {
+		return errFlagParse
+	}
+	*f = ModeFlag(s)
+	return nil
+}
+func (f *ModeFlag) String() string { return "" }
+
+// ScanFlag is used for parsing and validation of
+// govulncheck -scan flag.
+type ScanFlag string
+
+var supportedLevels = map[string]bool{
+	govulncheck.ScanLevelModule:  true,
+	govulncheck.ScanLevelPackage: true,
+	govulncheck.ScanLevelSymbol:  true,
+}
+
+func (f *ScanFlag) Get() interface{} { return *f }
+func (f *ScanFlag) Set(s string) error {
+	if _, ok := supportedLevels[s]; !ok {
+		return errFlagParse
+	}
+	*f = ScanFlag(s)
+	return nil
+}
+func (f *ScanFlag) String() string { return "" }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/run.go b/notifier/vendor/golang.org/x/vuln/internal/scan/run.go
index fe452cfa..f29b9d31 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/run.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/run.go
@@ -15,8 +15,11 @@ import (
 	"strings"
 	"time"
 
+	"golang.org/x/telemetry/counter"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/openvex"
+	"golang.org/x/vuln/internal/sarif"
 )
 
 // RunGovulncheck performs main govulncheck functionality and exits the
@@ -27,9 +30,6 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 	if err := parseFlags(cfg, stderr, args); err != nil {
 		return err
 	}
-	if cfg.mode == modeConvert {
-		return convertJSONToText(r, stdout)
-	}
 
 	client, err := client.NewClient(cfg.db, nil)
 	if err != nil {
@@ -38,42 +38,48 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 
 	prepareConfig(ctx, cfg, client)
 	var handler govulncheck.Handler
-	switch {
-	case cfg.json:
+	switch cfg.format {
+	case formatJSON:
 		handler = govulncheck.NewJSONHandler(stdout)
+	case formatSarif:
+		handler = sarif.NewHandler(stdout)
+	case formatOpenVEX:
+		handler = openvex.NewHandler(stdout)
 	default:
 		th := NewTextHandler(stdout)
-		th.Show(cfg.show)
+		cfg.show.Update(th)
 		handler = th
 	}
 
-	// Write the introductory message to the user.
 	if err := handler.Config(&cfg.Config); err != nil {
 		return err
 	}
 
-	switch cfg.mode {
-	case modeSource:
+	incTelemetryFlagCounters(cfg)
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		dir := filepath.FromSlash(cfg.dir)
 		err = runSource(ctx, handler, cfg, client, dir)
-	case modeBinary:
+	case govulncheck.ScanModeBinary:
 		err = runBinary(ctx, handler, cfg, client)
-	case modeQuery:
+	case govulncheck.ScanModeExtract:
+		return runExtract(cfg, stdout)
+	case govulncheck.ScanModeQuery:
 		err = runQuery(ctx, handler, cfg, client)
+	case govulncheck.ScanModeConvert:
+		err = govulncheck.HandleJSON(r, handler)
 	}
 	if err != nil {
 		return err
 	}
-	if err := Flush(handler); err != nil {
-		return err
-	}
-	return nil
+	return Flush(handler)
 }
 
 func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 	cfg.ProtocolVersion = govulncheck.ProtocolVersion
 	cfg.DB = cfg.db
-	if cfg.mode == modeSource && cfg.GoVersion == "" {
+	if cfg.ScanMode == govulncheck.ScanModeSource && cfg.GoVersion == "" {
 		const goverPrefix = "GOVERSION="
 		for _, env := range cfg.env {
 			if val := strings.TrimPrefix(env, goverPrefix); val != env {
@@ -82,7 +88,7 @@ func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 		}
 		if cfg.GoVersion == "" {
 			if out, err := exec.Command("go", "env", "GOVERSION").Output(); err == nil {
-				cfg.GoVersion = string(out)
+				cfg.GoVersion = strings.TrimSpace(string(out))
 			}
 		}
 	}
@@ -133,13 +139,22 @@ func scannerVersion(cfg *config, bi *debug.BuildInfo) {
 	cfg.ScannerVersion = buf.String()
 }
 
-// convertJSONToText converts r, which is expected to be the JSON output of govulncheck,
-// into the text output, and writes the output to w.
-func convertJSONToText(r io.Reader, w io.Writer) error {
-	h := NewTextHandler(w)
-	if err := govulncheck.HandleJSON(r, h); err != nil {
-		return err
+func incTelemetryFlagCounters(cfg *config) {
+	counter.Inc(fmt.Sprintf("govulncheck/mode:%s", cfg.ScanMode))
+	counter.Inc(fmt.Sprintf("govulncheck/scan:%s", cfg.ScanLevel))
+	counter.Inc(fmt.Sprintf("govulncheck/format:%s", cfg.format))
+
+	if len(cfg.show) == 0 {
+		counter.Inc("govulncheck/show:none")
+	}
+	for _, s := range cfg.show {
+		counter.Inc(fmt.Sprintf("govulncheck/show:%s", s))
+	}
+}
+
+func Flush(h govulncheck.Handler) error {
+	if th, ok := h.(interface{ Flush() error }); ok {
+		return th.Flush()
 	}
-	Flush(h)
 	return nil
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/source.go b/notifier/vendor/golang.org/x/vuln/internal/scan/source.go
index cfdc1227..e9232112 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/source.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/source.go
@@ -7,13 +7,11 @@ package scan
 import (
 	"context"
 	"fmt"
-	"path/filepath"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
@@ -22,189 +20,30 @@ import (
 // Vulnerabilities can be called (affecting the package, because a vulnerable
 // symbol is actually exercised) or just imported by the package
 // (likely having a non-affecting outcome).
-func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) error {
-	var pkgs []*packages.Package
+func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	if cfg.ScanLevel.WantPackages() && len(cfg.patterns) == 0 {
+		return nil // don't throw an error here
+	}
+	if !gomodExists(dir) {
+		return errNoGoMod
+	}
 	graph := vulncheck.NewPackageGraph(cfg.GoVersion)
 	pkgConfig := &packages.Config{
 		Dir:   dir,
 		Tests: cfg.test,
 		Env:   cfg.env,
 	}
-	pkgs, err := graph.LoadPackages(pkgConfig, cfg.tags, cfg.patterns)
-	if err != nil {
-		// Try to provide a meaningful and actionable error message.
-		if !fileExists(filepath.Join(dir, "go.mod")) {
-			return fmt.Errorf("govulncheck: %v", errNoGoMod)
-		}
+	if err := graph.LoadPackagesAndMods(pkgConfig, cfg.tags, cfg.patterns, cfg.ScanLevel == govulncheck.ScanLevelSymbol); err != nil {
 		if isGoVersionMismatchError(err) {
-			return fmt.Errorf("govulncheck: %v\n\n%v", errGoVersionMismatch, err)
-		}
-		return fmt.Errorf("govulncheck: loading packages: %w", err)
-	}
-	if err := handler.Progress(sourceProgressMessage(pkgs)); err != nil {
-		return err
-	}
-	vr, err := vulncheck.Source(ctx, pkgs, &cfg.Config, client, graph)
-	if err != nil {
-		return err
-	}
-	callStacks := vulncheck.CallStacks(vr)
-	return emitResult(handler, vr, callStacks)
-}
-
-func emitResult(handler govulncheck.Handler, vr *vulncheck.Result, callstacks map[*vulncheck.Vuln]vulncheck.CallStack) error {
-	osvs := map[string]*osv.Entry{}
-	// first deal with all the affected vulnerabilities
-	emitted := map[string]bool{}
-	seen := map[string]bool{}
-	for _, vv := range vr.Vulns {
-		osvs[vv.OSV.ID] = vv.OSV
-		fixed := fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected)
-		stack := callstacks[vv]
-		if stack == nil {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixed,
-			Trace:        tracefromEntries(stack),
-		})
-	}
-	for _, vv := range vr.Vulns {
-		if emitted[vv.OSV.ID] {
-			continue
+			return fmt.Errorf("%v\n\n%v", errGoVersionMismatch, err)
 		}
-		stacks := callstacks[vv]
-		if len(stacks) != 0 {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected),
-			Trace:        []*govulncheck.Frame{frameFromPackage(vv.ImportSink)},
-		})
-	}
-	return nil
-}
-
-func emitFinding(handler govulncheck.Handler, osvs map[string]*osv.Entry, seen map[string]bool, finding *govulncheck.Finding) error {
-	if !seen[finding.OSV] {
-		seen[finding.OSV] = true
-		if err := handler.OSV(osvs[finding.OSV]); err != nil {
-			return err
-		}
-	}
-	return handler.Finding(finding)
-}
-
-// tracefromEntries creates a sequence of
-// frames from vcs. Position of a Frame is the
-// call position of the corresponding stack entry.
-func tracefromEntries(vcs vulncheck.CallStack) []*govulncheck.Frame {
-	var frames []*govulncheck.Frame
-	for i := len(vcs) - 1; i >= 0; i-- {
-		e := vcs[i]
-		fr := frameFromPackage(e.Function.Package)
-		fr.Function = e.Function.Name
-		fr.Receiver = e.Function.Receiver()
-		if e.Call == nil || e.Call.Pos == nil {
-			fr.Position = nil
-		} else {
-			fr.Position = &govulncheck.Position{
-				Filename: e.Call.Pos.Filename,
-				Offset:   e.Call.Pos.Offset,
-				Line:     e.Call.Pos.Line,
-				Column:   e.Call.Pos.Column,
-			}
-		}
-		frames = append(frames, fr)
+		return fmt.Errorf("loading packages: %w", err)
 	}
-	return frames
-}
 
-func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
-	fr := &govulncheck.Frame{}
-	if pkg != nil {
-		fr.Module = pkg.Module.Path
-		fr.Version = pkg.Module.Version
-		fr.Package = pkg.PkgPath
-	}
-	if pkg.Module.Replace != nil {
-		fr.Module = pkg.Module.Replace.Path
-		fr.Version = pkg.Module.Replace.Version
+	if cfg.ScanLevel.WantPackages() && len(graph.TopPkgs()) == 0 {
+		return nil // early exit
 	}
-	return fr
-}
-
-// sourceProgressMessage returns a string of the form
-//
-//	"Scanning your code and P packages across M dependent modules for known vulnerabilities..."
-//
-// P is the number of strictly dependent packages of
-// topPkgs and Y is the number of their modules.
-func sourceProgressMessage(topPkgs []*packages.Package) *govulncheck.Progress {
-	pkgs, mods := depPkgsAndMods(topPkgs)
-
-	pkgsPhrase := fmt.Sprintf("%d package", pkgs)
-	if pkgs != 1 {
-		pkgsPhrase += "s"
-	}
-
-	modsPhrase := fmt.Sprintf("%d dependent module", mods)
-	if mods != 1 {
-		modsPhrase += "s"
-	}
-
-	msg := fmt.Sprintf("Scanning your code and %s across %s for known vulnerabilities...", pkgsPhrase, modsPhrase)
-	return &govulncheck.Progress{Message: msg}
-}
-
-// depPkgsAndMods returns the number of packages that
-// topPkgs depend on and the number of their modules.
-func depPkgsAndMods(topPkgs []*packages.Package) (int, int) {
-	tops := make(map[string]bool)
-	depPkgs := make(map[string]bool)
-	depMods := make(map[string]bool)
-
-	for _, t := range topPkgs {
-		tops[t.PkgPath] = true
-	}
-
-	var visit func(*packages.Package, bool)
-	visit = func(p *packages.Package, top bool) {
-		path := p.PkgPath
-		if depPkgs[path] {
-			return
-		}
-		if tops[path] && !top {
-			// A top package that is a dependency
-			// will not be in depPkgs, so we skip
-			// reiterating on it here.
-			return
-		}
-
-		// We don't count a top-level package as
-		// a dependency even when they are used
-		// as a dependent package.
-		if !tops[path] {
-			depPkgs[path] = true
-			if p.Module != nil &&
-				p.Module.Path != internal.GoStdModulePath && // no module for stdlib
-				p.Module.Path != internal.UnknownModulePath { // no module for unknown
-				depMods[p.Module.Path] = true
-			}
-		}
-
-		for _, d := range p.Imports {
-			visit(d, false)
-		}
-	}
-
-	for _, t := range topPkgs {
-		visit(t, true)
-	}
-
-	return len(depPkgs), len(depMods)
+	return vulncheck.Source(ctx, handler, &cfg.Config, client, graph)
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/template.go b/notifier/vendor/golang.org/x/vuln/internal/scan/template.go
index 953fbaeb..5c1a4a75 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/template.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/template.go
@@ -14,9 +14,9 @@ import (
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
 )
 
 type findingSummary struct {
@@ -26,9 +26,11 @@ type findingSummary struct {
 }
 
 type summaryCounters struct {
-	VulnerabilitiesCalled int
-	ModulesCalled         int
-	StdlibCalled          bool
+	VulnerabilitiesCalled   int
+	ModulesCalled           int
+	VulnerabilitiesImported int
+	VulnerabilitiesRequired int
+	StdlibCalled            bool
 }
 
 func fixupFindings(osvs []*osv.Entry, findings []*findingSummary) {
@@ -74,27 +76,22 @@ func groupBy(findings []*findingSummary, compare func(left, right *findingSummar
 	return result
 }
 
-func counters(findings []*findingSummary) summaryCounters {
-	vulns := map[string]struct{}{}
-	modules := map[string]struct{}{}
+func isRequired(findings []*findingSummary) bool {
 	for _, f := range findings {
-		if f.Trace[0].Function == "" {
-			continue
+		if f.Trace[0].Module != "" {
+			return true
 		}
-		id := f.OSV.ID
-		vulns[id] = struct{}{}
-		mod := f.Trace[0].Module
-		modules[mod] = struct{}{}
-	}
-	result := summaryCounters{
-		VulnerabilitiesCalled: len(vulns),
-		ModulesCalled:         len(modules),
 	}
-	if _, found := modules[internal.GoStdModulePath]; found {
-		result.StdlibCalled = true
-		result.ModulesCalled--
+	return false
+}
+
+func isImported(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if f.Trace[0].Package != "" {
+			return true
+		}
 	}
-	return result
+	return false
 }
 
 func isCalled(findings []*findingSummary) bool {
@@ -105,6 +102,7 @@ func isCalled(findings []*findingSummary) bool {
 	}
 	return false
 }
+
 func getOSV(osvs []*osv.Entry, id string) *osv.Entry {
 	for _, entry := range osvs {
 		if entry.ID == id {
@@ -184,7 +182,13 @@ func posToString(p *govulncheck.Position) string {
 
 func symbol(frame *govulncheck.Frame, short bool) string {
 	buf := &strings.Builder{}
-	addSymbolName(buf, frame, short)
+	addSymbol(buf, frame, short)
+	return buf.String()
+}
+
+func symbolName(frame *govulncheck.Frame) string {
+	buf := &strings.Builder{}
+	addSymbolName(buf, frame)
 	return buf.String()
 }
 
@@ -196,44 +200,36 @@ func symbol(frame *govulncheck.Frame, short bool) string {
 // If the vulnerable symbol is in the users code, it will show the entry point
 // and the vulnerable symbol.
 func compactTrace(finding *govulncheck.Finding) string {
-	if len(finding.Trace) < 1 {
+	compact := traces.Compact(finding)
+	if len(compact) == 0 {
 		return ""
 	}
-	iTop := len(finding.Trace) - 1
-	topModule := finding.Trace[iTop].Module
-	// search for the exit point of the top module
-	for i, frame := range finding.Trace {
-		if frame.Module == topModule {
-			iTop = i
-			break
-		}
-	}
-
-	if iTop == 0 {
-		// all in one module, reset to the end
-		iTop = len(finding.Trace) - 1
-	}
 
+	l := len(compact)
+	iTop := l - 1
 	buf := &strings.Builder{}
-	topPos := posToString(finding.Trace[iTop].Position)
+	topPos := posToString(compact[iTop].Position)
 	if topPos != "" {
 		buf.WriteString(topPos)
 		buf.WriteString(": ")
 	}
 
-	if iTop > 0 {
-		addSymbolName(buf, finding.Trace[iTop], true)
+	if l > 1 {
+		// print the root of the compact trace
+		addSymbol(buf, compact[iTop], true)
 		buf.WriteString(" calls ")
 	}
-	if iTop > 1 {
-		addSymbolName(buf, finding.Trace[iTop-1], true)
+	if l > 2 {
+		// print next element of the trace, if any
+		addSymbol(buf, compact[iTop-1], true)
 		buf.WriteString(", which")
-		if iTop > 2 {
+		if l > 3 {
+			// don't print the third element, just acknowledge it
 			buf.WriteString(" eventually")
 		}
 		buf.WriteString(" calls ")
 	}
-	addSymbolName(buf, finding.Trace[0], true)
+	addSymbol(buf, compact[0], true) // print the vulnerable symbol
 	return buf.String()
 }
 
@@ -265,7 +261,7 @@ func importPathToAssumedName(importPath string) string {
 	return base
 }
 
-func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
+func addSymbol(w io.Writer, frame *govulncheck.Frame, short bool) {
 	if frame.Function == "" {
 		return
 	}
@@ -277,6 +273,10 @@ func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
 		io.WriteString(w, pkg)
 		io.WriteString(w, ".")
 	}
+	addSymbolName(w, frame)
+}
+
+func addSymbolName(w io.Writer, frame *govulncheck.Frame) {
 	if frame.Receiver != "" {
 		if frame.Receiver[0] == '*' {
 			io.WriteString(w, frame.Receiver[1:])
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/text.go b/notifier/vendor/golang.org/x/vuln/internal/scan/text.go
index 845054b9..ab49bdd1 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/text.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/text.go
@@ -7,19 +7,19 @@ package scan
 import (
 	"fmt"
 	"io"
+	"sort"
 	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/vulncheck"
 )
 
 type style int
 
 const (
 	defaultStyle = style(iota)
-	goStyle
-	scannerStyle
 	osvCalledStyle
 	osvImportedStyle
 	detailsStyle
@@ -34,81 +34,143 @@ func NewTextHandler(w io.Writer) *TextHandler {
 }
 
 type TextHandler struct {
-	w        io.Writer
-	osvs     []*osv.Entry
-	findings []*findingSummary
+	w         io.Writer
+	sbom      *govulncheck.SBOM
+	osvs      []*osv.Entry
+	findings  []*findingSummary
+	scanLevel govulncheck.ScanLevel
+	scanMode  govulncheck.ScanMode
 
 	err error
 
-	showColor  bool
-	showTraces bool
+	showColor   bool
+	showTraces  bool
+	showVersion bool
+	showVerbose bool
 }
 
 const (
 	detailsMessage = `For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.`
 
 	binaryProgressMessage = `Scanning your binary for known vulnerabilities...`
-)
 
-func (h *TextHandler) Show(show []string) {
-	for _, show := range show {
-		switch show {
-		case "traces":
-			h.showTraces = true
-		case "color":
-			h.showColor = true
-		}
-	}
-}
+	noVulnsMessage = `No vulnerabilities found.`
 
-func Flush(h govulncheck.Handler) error {
-	if th, ok := h.(interface{ Flush() error }); ok {
-		return th.Flush()
-	}
-	return nil
-}
+	noOtherVulnsMessage = `No other vulnerabilities found.`
+
+	verboseMessage = `'-show verbose' for more details`
+
+	symbolMessage = `'-scan symbol' for more fine grained vulnerability detection`
+)
 
 func (h *TextHandler) Flush() error {
+	if h.showVerbose {
+		h.printSBOM()
+	}
 	if len(h.findings) == 0 {
-		return nil
+		h.print(noVulnsMessage + "\n")
+	} else {
+		fixupFindings(h.osvs, h.findings)
+		counters := h.allVulns(h.findings)
+		h.summary(counters)
 	}
-	fixupFindings(h.osvs, h.findings)
-	h.byVulnerability(h.findings)
-	h.summary(h.findings)
 	if h.err != nil {
 		return h.err
 	}
-	if isCalled(h.findings) {
+	// We found vulnerabilities when the findings' level matches the scan level.
+	if (isCalled(h.findings) && h.scanLevel == govulncheck.ScanLevelSymbol) ||
+		(isImported(h.findings) && h.scanLevel == govulncheck.ScanLevelPackage) ||
+		(isRequired(h.findings) && h.scanLevel == govulncheck.ScanLevelModule) {
 		return errVulnerabilitiesFound
 	}
+
 	return nil
 }
 
-// Config writes text output formatted according to govulncheck-intro.tmpl.
+// Config writes version information only if --version was set.
 func (h *TextHandler) Config(config *govulncheck.Config) error {
-	h.print("govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.\n\nUsing ")
+	h.scanLevel = config.ScanLevel
+	h.scanMode = config.ScanMode
+
+	if !h.showVersion {
+		return nil
+	}
 	if config.GoVersion != "" {
-		h.style(goStyle, config.GoVersion)
-		h.print(` and `)
+		h.style(keyStyle, "Go: ")
+		h.print(config.GoVersion, "\n")
 	}
 	if config.ScannerName != "" {
-		h.style(scannerStyle, config.ScannerName)
+		h.style(keyStyle, "Scanner: ")
+		h.print(config.ScannerName)
 		if config.ScannerVersion != "" {
 			h.print(`@`, config.ScannerVersion)
 		}
-		h.print(` with `)
+		h.print("\n")
 	}
-	h.print(`vulnerability data from `, config.DB)
-	if config.DBLastModified != nil {
-		h.print(` (last modified `, *config.DBLastModified, `)`)
+	if config.DB != "" {
+		h.style(keyStyle, "DB: ")
+		h.print(config.DB, "\n")
+		if config.DBLastModified != nil {
+			h.style(keyStyle, "DB updated: ")
+			h.print(*config.DBLastModified, "\n")
+		}
 	}
-	h.print(".\n\n")
+	h.print("\n")
 	return h.err
 }
 
-// Progress writes progress updates during govulncheck execution..
+func (h *TextHandler) SBOM(sbom *govulncheck.SBOM) error {
+	h.sbom = sbom
+	return nil
+}
+
+func (h *TextHandler) printSBOM() error {
+	if h.sbom == nil {
+		h.print("No packages matched the provided pattern.\n")
+		return nil
+	}
+
+	printed := false
+
+	for i, root := range h.sbom.Roots {
+		if i == 0 {
+			if len(h.sbom.Roots) > 1 {
+				h.print("The package pattern matched the following ", len(h.sbom.Roots), " root packages:\n")
+			} else {
+				h.print("The package pattern matched the following root package:\n")
+			}
+		}
+
+		h.print("  ", root, "\n")
+		printed = true
+	}
+	for i, mod := range h.sbom.Modules {
+		if i == 0 && mod.Path != "stdlib" {
+			h.print("Govulncheck scanned the following ", len(h.sbom.Modules)-1, " modules and the ", h.sbom.GoVersion, " standard library:\n")
+		}
+
+		if mod.Path == "stdlib" {
+			continue
+		}
+
+		h.print("  ", mod.Path)
+		if mod.Version != "" {
+			h.print("@", mod.Version)
+		}
+		h.print("\n")
+		printed = true
+	}
+	if printed {
+		h.print("\n")
+	}
+	return nil
+}
+
+// Progress writes progress updates during govulncheck execution.
 func (h *TextHandler) Progress(progress *govulncheck.Progress) error {
-	h.print(progress.Message, "\n\n")
+	if h.showVerbose {
+		h.print(progress.Message, "\n\n")
+	}
 	return h.err
 }
 
@@ -127,39 +189,64 @@ func (h *TextHandler) Finding(finding *govulncheck.Finding) error {
 	return nil
 }
 
-func (h *TextHandler) byVulnerability(findings []*findingSummary) {
+func (h *TextHandler) allVulns(findings []*findingSummary) summaryCounters {
 	byVuln := groupByVuln(findings)
-	called := 0
+	var called, imported, required [][]*findingSummary
+	mods := map[string]struct{}{}
+	stdlibCalled := false
 	for _, findings := range byVuln {
-		if isCalled(findings) {
-			if called > 0 {
-				h.print("\n")
+		switch {
+		case isCalled(findings):
+			called = append(called, findings)
+			if isStdFindings(findings) {
+				stdlibCalled = true
+			} else {
+				mods[findings[0].Trace[0].Module] = struct{}{}
 			}
-			h.vulnerability(called, findings)
-			called++
+		case isImported(findings):
+			imported = append(imported, findings)
+		default:
+			required = append(required, findings)
 		}
 	}
-	unCalled := len(byVuln) - called
-	if unCalled == 0 {
-		return
+
+	if h.scanLevel.WantSymbols() {
+		h.style(sectionStyle, "=== Symbol Results ===\n\n")
+		if len(called) == 0 {
+			h.print(noVulnsMessage, "\n\n")
+		}
+		for index, findings := range called {
+			h.vulnerability(index, findings)
+		}
 	}
-	h.print("\n")
-	h.style(sectionStyle, "=== Informational ===\n")
-	h.print("\nFound ", unCalled)
-	h.print(choose(unCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(" in packages that you import, but there are no call\nstacks leading to the use of ")
-	h.print(choose(unCalled == 1, `this vulnerability`, `these vulnerabilities`))
-	h.print(". You may not need to\ntake any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck\nfor details.\n\n")
-	index := 0
-	for _, findings := range byVuln {
-		if !isCalled(findings) {
-			if index > 0 {
-				h.print("\n")
-			}
+
+	if h.scanLevel == govulncheck.ScanLevelPackage || (h.scanLevel.WantPackages() && h.showVerbose) {
+		h.style(sectionStyle, "=== Package Results ===\n\n")
+		if len(imported) == 0 {
+			h.print(choose(!h.scanLevel.WantSymbols(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range imported {
 			h.vulnerability(index, findings)
-			index++
 		}
 	}
+
+	if h.showVerbose || h.scanLevel == govulncheck.ScanLevelModule {
+		h.style(sectionStyle, "=== Module Results ===\n\n")
+		if len(required) == 0 {
+			h.print(choose(!h.scanLevel.WantPackages(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range required {
+			h.vulnerability(index, findings)
+		}
+	}
+
+	return summaryCounters{
+		VulnerabilitiesCalled:   len(called),
+		VulnerabilitiesImported: len(imported),
+		VulnerabilitiesRequired: len(required),
+		ModulesCalled:           len(mods),
+		StdlibCalled:            stdlibCalled,
+	}
 }
 
 func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
@@ -185,13 +272,20 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 	byModule := groupByModule(findings)
 	first := true
 	for _, module := range byModule {
-		//TODO: this assumes all traces on a module are found and fixed at the same versions
+		// Note: there can be several findingSummaries for the same vulnerability
+		// emitted during streaming for different scan levels.
+
+		// The module is same for all finding summaries.
 		lastFrame := module[0].Trace[0]
 		mod := lastFrame.Module
+		// For stdlib, try to show package path as module name where
+		// the scan level allows it.
+		// TODO: should this be done in byModule as well?
 		path := lastFrame.Module
-		if path == internal.GoStdModulePath {
-			path = lastFrame.Package
+		if stdPkg := h.pkg(module); path == internal.GoStdModulePath && stdPkg != "" {
+			path = stdPkg
 		}
+		// All findings on a module are found and fixed at the same version
 		foundVersion := moduleVersionString(lastFrame.Module, lastFrame.Version)
 		fixedVersion := moduleVersionString(lastFrame.Module, module[0].FixedVersion)
 		if !first {
@@ -228,59 +322,180 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 		}
 		h.traces(module)
 	}
+	h.print("\n")
+}
+
+// pkg gives the package information for findings summaries
+// if one exists. This is only used to print package path
+// instead of a module for stdlib vulnerabilities at symbol
+// and package scan level.
+func (h *TextHandler) pkg(summaries []*findingSummary) string {
+	for _, f := range summaries {
+		if pkg := f.Trace[0].Package; pkg != "" {
+			return pkg
+		}
+	}
+	return ""
 }
 
+// traces prints out the most precise trace information
+// found in the given summaries.
 func (h *TextHandler) traces(traces []*findingSummary) {
-	first := true
-	for i, entry := range traces {
-		if entry.Compact == "" {
-			continue
+	// Sort the traces by the vulnerable symbol. This
+	// guarantees determinism since we are currently
+	// showing only one trace per symbol.
+	sort.SliceStable(traces, func(i, j int) bool {
+		return symbol(traces[i].Trace[0], true) < symbol(traces[j].Trace[0], true)
+	})
+
+	// compacts are finding summaries with compact traces
+	// suitable for non-verbose textual output. Currently,
+	// only traces produced by symbol analysis.
+	var compacts []*findingSummary
+	for _, t := range traces {
+		if t.Compact != "" {
+			compacts = append(compacts, t)
 		}
-		if first {
-			h.style(keyStyle, "    Example traces found:\n")
+	}
+
+	// binLimit is a limit on the number of binary traces
+	// to show. Traces for binaries are less interesting
+	// as users cannot act on them and they can hence
+	// spam users.
+	const binLimit = 5
+	binary := h.scanMode == govulncheck.ScanModeBinary
+	for i, entry := range compacts {
+		if i == 0 {
+			if binary {
+				h.style(keyStyle, "    Vulnerable symbols found:\n")
+			} else {
+				h.style(keyStyle, "    Example traces found:\n")
+			}
+		}
+
+		// skip showing all symbols in binary mode unless '-show traces' is on.
+		if binary && (i+1) > binLimit && !h.showTraces {
+			h.print("      Use '-show traces' to see the other ", len(compacts)-binLimit, " found symbols\n")
+			break
 		}
-		first = false
 
 		h.print("      #", i+1, ": ")
-		if !h.showTraces {
+
+		if !h.showTraces { // show summarized traces
 			h.print(entry.Compact, "\n")
+			continue
+		}
+
+		if binary {
+			// There are no call stacks in binary mode
+			// so just show the full symbol name.
+			h.print(symbol(entry.Trace[0], false), "\n")
 		} else {
 			h.print("for function ", symbol(entry.Trace[0], false), "\n")
 			for i := len(entry.Trace) - 1; i >= 0; i-- {
 				t := entry.Trace[i]
 				h.print("        ")
+				h.print(symbolName(t))
 				if t.Position != nil {
-					h.print(posToString(t.Position), ": ")
+					h.print(" @ ", symbolPath(t))
 				}
-				h.print(symbol(t, false), "\n")
+				h.print("\n")
 			}
 		}
 	}
 }
 
-func (h *TextHandler) summary(findings []*findingSummary) {
-	counters := counters(findings)
-	h.print("\n")
-	if counters.VulnerabilitiesCalled == 0 {
-		h.print("No vulnerabilities found.\n")
-		return
-	}
-	h.print(`Your code is affected by `)
-	h.style(valueStyle, counters.VulnerabilitiesCalled)
-	h.print(choose(counters.VulnerabilitiesCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(` from`)
-	if counters.ModulesCalled > 0 {
-		h.print(` `)
-		h.style(valueStyle, counters.ModulesCalled)
-		h.print(choose(counters.ModulesCalled == 1, ` module`, ` modules`))
+// symbolPath returns a user-friendly path to a symbol.
+func symbolPath(t *govulncheck.Frame) string {
+	// Add module path prefix to symbol paths to be more
+	// explicit to which module the symbols belong to.
+	return t.Module + "/" + posToString(t.Position)
+}
+
+func (h *TextHandler) summary(c summaryCounters) {
+	// print short summary of findings identified at the desired level of scan precision
+	var vulnCount int
+	h.print("Your code ", choose(h.scanLevel.WantSymbols(), "is", "may be"), " affected by ")
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		vulnCount = c.VulnerabilitiesCalled
+	case govulncheck.ScanLevelPackage:
+		vulnCount = c.VulnerabilitiesImported
+	case govulncheck.ScanLevelModule:
+		vulnCount = c.VulnerabilitiesRequired
 	}
-	if counters.StdlibCalled {
-		if counters.ModulesCalled != 0 {
-			h.print(` and`)
+	h.style(valueStyle, vulnCount)
+	h.print(choose(vulnCount == 1, ` vulnerability`, ` vulnerabilities`))
+	if h.scanLevel.WantSymbols() {
+		h.print(choose(c.ModulesCalled > 0 || c.StdlibCalled, ` from `, ``))
+		if c.ModulesCalled > 0 {
+			h.style(valueStyle, c.ModulesCalled)
+			h.print(choose(c.ModulesCalled == 1, ` module`, ` modules`))
+		}
+		if c.StdlibCalled {
+			if c.ModulesCalled != 0 {
+				h.print(` and `)
+			}
+			h.print(`the Go standard library`)
 		}
-		h.print(` the Go standard library`)
 	}
 	h.print(".\n")
+
+	// print summary for vulnerabilities found at other levels of scan precision
+	if other := h.summaryOtherVulns(c); other != "" {
+		h.wrap("", other, 80)
+		h.print("\n")
+	}
+
+	// print suggested flags for more/better info depending on scan level and if in verbose mode
+	if sugg := h.summarySuggestion(); sugg != "" {
+		h.wrap("", sugg, 80)
+		h.print("\n")
+	}
+}
+
+func (h *TextHandler) summaryOtherVulns(c summaryCounters) string {
+	var summary strings.Builder
+	if c.VulnerabilitiesRequired+c.VulnerabilitiesImported == 0 {
+		summary.WriteString("This scan found no other vulnerabilities in ")
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString("packages you import or ")
+		}
+		summary.WriteString("modules you require.")
+	} else {
+		summary.WriteString(choose(h.scanLevel.WantPackages(), "This scan also found ", ""))
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesImported))
+			summary.WriteString(choose(c.VulnerabilitiesImported == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in packages you import and ")
+		}
+		if h.scanLevel.WantPackages() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesRequired))
+			summary.WriteString(choose(c.VulnerabilitiesRequired == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in modules you require")
+			summary.WriteString(choose(h.scanLevel.WantSymbols(), ", but your code doesn't appear to call these vulnerabilities.", "."))
+		}
+	}
+	return summary.String()
+}
+
+func (h *TextHandler) summarySuggestion() string {
+	var sugg strings.Builder
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		if !h.showVerbose {
+			sugg.WriteString("Use " + verboseMessage + ".")
+		}
+	case govulncheck.ScanLevelPackage:
+		sugg.WriteString("Use " + symbolMessage)
+		if !h.showVerbose {
+			sugg.WriteString(" and " + verboseMessage)
+		}
+		sugg.WriteString(".")
+	case govulncheck.ScanLevelModule:
+		sugg.WriteString("Use " + symbolMessage + ".")
+	}
+	return sugg.String()
 }
 
 func (h *TextHandler) style(style style, values ...any) {
@@ -288,10 +503,6 @@ func (h *TextHandler) style(style style, values ...any) {
 		switch style {
 		default:
 			h.print(colorReset)
-		case goStyle:
-			h.print(colorBold)
-		case scannerStyle:
-			h.print(colorBold)
 		case osvCalledStyle:
 			h.print(colorBold, fgRed)
 		case osvImportedStyle:
@@ -347,9 +558,18 @@ func (h *TextHandler) wrap(indent string, s string, maxWidth int) {
 	}
 }
 
-func choose(b bool, yes, no any) any {
+func choose[t any](b bool, yes, no t) t {
 	if b {
 		return yes
 	}
 	return no
 }
+
+func isStdFindings(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if vulncheck.IsStdPackage(f.Trace[0].Package) || f.Trace[0].Module == internal.GoStdModulePath {
+			return true
+		}
+	}
+	return false
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/scan/util.go b/notifier/vendor/golang.org/x/vuln/internal/scan/util.go
index ce5500bb..0d82ca82 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/scan/util.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/scan/util.go
@@ -6,11 +6,12 @@ package scan
 
 import (
 	"fmt"
+	"os"
+	"os/exec"
+	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	isem "golang.org/x/vuln/internal/semver"
 )
 
 // validateFindings checks that the supplied findings all obey the protocol
@@ -25,48 +26,19 @@ func validateFindings(findings ...*govulncheck.Finding) error {
 		}
 		for _, frame := range f.Trace {
 			if frame.Version != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Version is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Version (%s) is set, Frame.Module must also be", frame.Version)
 			}
 			if frame.Package != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Package is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Package (%s) is set, Frame.Module must also be", frame.Package)
 			}
 			if frame.Function != "" && frame.Package == "" {
-				return fmt.Errorf("invalid finding: if Frame.Function is set, Frame.Package must also be")
+				return fmt.Errorf("invalid finding: if Frame.Function (%s) is set, Frame.Package must also be", frame.Function)
 			}
 		}
 	}
 	return nil
 }
 
-// latestFixed returns the latest fixed version in the list of affected ranges,
-// or the empty string if there are no fixed versions.
-func latestFixed(modulePath string, as []osv.Affected) string {
-	v := ""
-	for _, a := range as {
-		if modulePath != a.Module.Path {
-			continue
-		}
-		fixed := isem.LatestFixedVersion(a.Ranges)
-		// Special case: if there is any affected block for this module
-		// with no fix, the module is considered unfixed.
-		if fixed == "" {
-			return ""
-		}
-		if isem.Less(v, fixed) {
-			v = fixed
-		}
-	}
-	return v
-}
-
-func fixedVersion(modulePath string, affected []osv.Affected) string {
-	fixed := latestFixed(modulePath, affected)
-	if fixed != "" {
-		fixed = "v" + fixed
-	}
-	return fixed
-}
-
 func moduleVersionString(modulePath, version string) string {
 	if version == "" {
 		return ""
@@ -76,3 +48,13 @@ func moduleVersionString(modulePath, version string) string {
 	}
 	return version
 }
+
+func gomodExists(dir string) bool {
+	cmd := exec.Command("go", "env", "GOMOD")
+	cmd.Dir = dir
+	out, err := cmd.Output()
+	output := strings.TrimSpace(string(out))
+	// If module-aware mode is enabled, but there is no go.mod, GOMOD will be os.DevNull
+	// If module-aware mode is disabled, GOMOD will be the empty string.
+	return err == nil && !(output == os.DevNull || output == "")
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/semver/affects.go b/notifier/vendor/golang.org/x/vuln/internal/semver/affects.go
index 603d8277..03ea6fd7 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/semver/affects.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/semver/affects.go
@@ -21,7 +21,7 @@ func Affects(a []osv.Range, v string) bool {
 			continue
 		}
 		semverRangePresent = true
-		if containsSemver(r, v) {
+		if ContainsSemver(r, v) {
 			return true
 		}
 	}
@@ -32,9 +32,10 @@ func Affects(a []osv.Range, v string) bool {
 	return !semverRangePresent
 }
 
-// containsSemver checks if semver version v is in the
+// ContainsSemver checks if semver version v is in the
 // range encoded by ar. If ar is not a semver range,
-// returns false.
+// returns false. A range is interpreted as a left-closed
+// and right-open interval.
 //
 // Assumes that
 //   - exactly one of Introduced or Fixed fields is set
@@ -42,7 +43,7 @@ func Affects(a []osv.Range, v string) bool {
 //   - beginning of time is encoded with .Introduced="0"
 //   - no-fix is not an event, as opposed to being an
 //     event where Introduced="" and Fixed=""
-func containsSemver(ar osv.Range, v string) bool {
+func ContainsSemver(ar osv.Range, v string) bool {
 	if ar.Type != osv.RangeTypeSemver {
 		return false
 	}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/semver/fixed.go b/notifier/vendor/golang.org/x/vuln/internal/semver/fixed.go
index 152fc1de..bd29c407 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/semver/fixed.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/semver/fixed.go
@@ -6,7 +6,11 @@ package semver
 
 import "golang.org/x/vuln/internal/osv"
 
-func LatestFixedVersion(ranges []osv.Range) string {
+// NonSupersededFix returns a fixed version from ranges
+// that is not superseded by any other fix or any other
+// introduction of a vulnerability. Returns "" in case
+// there is no such fixed version.
+func NonSupersededFix(ranges []osv.Range) string {
 	var latestFixed string
 	for _, r := range ranges {
 		if r.Type == "SEMVER" {
@@ -16,6 +20,7 @@ func LatestFixedVersion(ranges []osv.Range) string {
 					latestFixed = fixed
 				}
 			}
+
 			// If the vulnerability was re-introduced after the latest fix
 			// we found, there is no latest fix for this range.
 			for _, e := range r.Events {
diff --git a/notifier/vendor/golang.org/x/vuln/internal/semver/semver.go b/notifier/vendor/golang.org/x/vuln/internal/semver/semver.go
index fe0f701b..efe1e006 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/semver/semver.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/semver/semver.go
@@ -7,6 +7,7 @@
 package semver
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -93,3 +94,47 @@ func GoTagToSemver(tag string) string {
 	}
 	return version
 }
+
+// This is a modified copy of pkgsite/internal/stlib:TagForVersion
+func SemverToGoTag(v string) string {
+	// Special case: v1.0.0 => go1.
+	if v == "v1.0.0" {
+		return "go1"
+	}
+
+	goVersion := semver.Canonical(v)
+	prerelease := semver.Prerelease(goVersion)
+	versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)
+	patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".")
+	if patch == "0" && (semver.Compare(v, "v1.21.0") < 0 || prerelease != "") {
+		// Starting with go1.21.0, the first patch version includes .0.
+		// Prereleases do not include .0 (we don't do prereleases for other patch releases).
+		versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0")
+	}
+	goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v"))
+	if prerelease != "" {
+		i := finalDigitsIndex(prerelease)
+		if i >= 1 {
+			// Remove the dot.
+			prerelease = prerelease[:i-1] + prerelease[i:]
+		}
+		goVersion += prerelease
+	}
+	return goVersion
+}
+
+// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.
+// If s doesn't end in digits, it returns -1.
+func finalDigitsIndex(s string) int {
+	// Assume ASCII (since the semver package does anyway).
+	var i int
+	for i = len(s) - 1; i >= 0; i-- {
+		if s[i] < '0' || s[i] > '9' {
+			break
+		}
+	}
+	if i == len(s)-1 {
+		return -1
+	}
+	return i + 1
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/traces/traces.go b/notifier/vendor/golang.org/x/vuln/internal/traces/traces.go
new file mode 100644
index 00000000..e413ae7d
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/traces/traces.go
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package traces
+
+import (
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// Compact returns a summarization of finding.Trace. The first
+// returned element is the vulnerable symbol and the last element
+// is the exit point of the user module. There can also be two
+// elements in between, if applicable, which are the two elements
+// preceding the user module exit point.
+func Compact(finding *govulncheck.Finding) []*govulncheck.Frame {
+	if len(finding.Trace) < 1 {
+		return nil
+	}
+	iTop := len(finding.Trace) - 1
+	topModule := finding.Trace[iTop].Module
+	// search for the exit point of the top module
+	for i, frame := range finding.Trace {
+		if frame.Module == topModule {
+			iTop = i
+			break
+		}
+	}
+
+	if iTop == 0 {
+		// all in one module, reset to the end
+		iTop = len(finding.Trace) - 1
+	}
+
+	compact := []*govulncheck.Frame{finding.Trace[0]}
+	if iTop > 1 {
+		if iTop > 2 {
+			compact = append(compact, finding.Trace[iTop-2])
+		}
+		compact = append(compact, finding.Trace[iTop-1])
+	}
+	if iTop > 0 {
+		compact = append(compact, finding.Trace[iTop])
+	}
+	return compact
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/binary.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
index a35a3a0a..d78af3ff 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
@@ -2,120 +2,184 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package vulncheck
 
 import (
 	"context"
 	"fmt"
-	"io"
-	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	"golang.org/x/vuln/internal/vulncheck/internal/buildinfo"
+	"golang.org/x/vuln/internal/semver"
 )
 
-// Binary detects presence of vulnerable symbols in exe.
-// The Calls, Imports, and Requires fields on Result will be empty.
-func Binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *Result, err error) {
-	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(exe)
+// Bin is an abstraction of Go binary containing
+// minimal information needed by govulncheck.
+type Bin struct {
+	// Path of the main package.
+	Path string `json:"path,omitempty"`
+	// Main module. When present, it never has empty information.
+	Main       *packages.Module   `json:"main,omitempty"`
+	Modules    []*packages.Module `json:"modules,omitempty"`
+	PkgSymbols []buildinfo.Symbol `json:"pkgSymbols,omitempty"`
+	GoVersion  string             `json:"goVersion,omitempty"`
+	GOOS       string             `json:"goos,omitempty"`
+	GOARCH     string             `json:"goarch,omitempty"`
+}
+
+// Binary detects presence of vulnerable symbols in bin and
+// emits findings to handler.
+func Binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) error {
+	vr, err := binary(ctx, handler, bin, cfg, client)
 	if err != nil {
-		return nil, fmt.Errorf("could not parse provided binary: %v", err)
+		return err
+	}
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, binaryCallstacks(vr))
+	}
+	return nil
+}
+
+// binary detects presence of vulnerable symbols in bin.
+// It does not compute call graphs so the corresponding
+// info in Result will be empty.
+func binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) (*Result, error) {
+	graph := NewPackageGraph(bin.GoVersion)
+	mods := append(bin.Modules, graph.GetModule(internal.GoStdModulePath))
+
+	if bin.Main != nil {
+		mods = append(mods, bin.Main)
 	}
 
-	graph := NewPackageGraph(bi.GoVersion)
 	graph.AddModules(mods...)
-	mods = append(mods, graph.GetModule(internal.GoStdModulePath))
+
+	if err := handler.SBOM(bin.SBOM()); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
+	}
 
 	mv, err := FetchVulnerabilities(ctx, client, mods)
 	if err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
 
-	goos := findSetting("GOOS", bi)
-	goarch := findSetting("GOARCH", bi)
-	if goos == "" || goarch == "" {
-		fmt.Printf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", goos, goarch)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingBinVulnsMessage}); err != nil {
+		return nil, err
+	}
+
+	// Emit warning message for ancient Go binaries, defined as binaries
+	// built with Go version without support for debug.BuildInfo (< go1.18).
+	if semver.Valid(bin.GoVersion) && semver.Less(bin.GoVersion, "go1.18") {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: binary built with Go version %s, only standard library vulnerabilities will be checked", bin.GoVersion)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+
+	if bin.GOOS == "" || bin.GOARCH == "" {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", bin.GOOS, bin.GOARCH)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+	affVulns := affectingVulnerabilities(mv, bin.GOOS, bin.GOARCH)
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
 
-	modVulns = modVulns.filter(goos, goarch)
-	result := &Result{}
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
+	}
 
-	if packageSymbols == nil {
+	// Group symbols per package to avoid querying affVulns all over again.
+	var pkgSymbols map[string][]string
+	if len(bin.PkgSymbols) == 0 {
 		// The binary exe is stripped. We currently cannot detect inlined
 		// symbols for stripped binaries (see #57764), so we report
 		// vulnerabilities at the go.mod-level precision.
-		addRequiresOnlyVulns(result, graph, modVulns)
+		pkgSymbols = allKnownVulnerableSymbols(affVulns)
 	} else {
-		for pkg, symbols := range packageSymbols {
-			if !cfg.ScanLevel.WantSymbols() {
-				addImportsOnlyVulns(result, graph, pkg, symbols, modVulns)
-			} else {
-				addSymbolVulns(result, graph, pkg, symbols, modVulns)
-			}
-		}
+		pkgSymbols = packagesAndSymbols(bin)
 	}
-	return result, nil
-}
 
-// addImportsOnlyVulns adds Vuln entries to result in imports only mode, i.e., for each vulnerable symbol
-// of pkg.
-func addImportsOnlyVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, osv := range modVulns.vulnsForPackage(pkg) {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg {
-					continue
-				}
-				syms := p.Symbols
-				if len(syms) == 0 {
-					// If every symbol of pkg is vulnerable, we would ideally
-					// compute every symbol mentioned in the pkg and then add
-					// Vuln entry for it, just as we do in Source. However,
-					// we don't have code of pkg here so we have to do best
-					// we can, which is the symbols of pkg actually appearing
-					// in the binary.
-					syms = symbols
-				}
+	impVulns := binImportedVulnPackages(graph, pkgSymbols, affVulns)
+	// Emit information on imported vulnerable packages now to
+	// mimic behavior of source.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
+	}
 
-				for _, symbol := range syms {
-					addVuln(result, graph, osv, symbol, pkg)
-				}
-			}
+	// Return result immediately if not in symbol mode to mimic the
+	// behavior of source.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
+
+	symVulns := binVulnSymbols(graph, pkgSymbols, affVulns)
+	return &Result{Vulns: symVulns}, nil
+}
+
+func packagesAndSymbols(bin *Bin) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, sym := range bin.PkgSymbols {
+		// If the name of the package is main, we need to expand
+		// it to its full path as that is what vuln db uses.
+		if sym.Pkg == "main" && bin.Path != "" {
+			pkgSymbols[bin.Path] = append(pkgSymbols[bin.Path], sym.Name)
+		} else {
+			pkgSymbols[sym.Pkg] = append(pkgSymbols[sym.Pkg], sym.Name)
 		}
 	}
+	return pkgSymbols
 }
 
-// addSymbolVulns adds Vuln entries to result for every symbol of pkg in the binary that is vulnerable.
-func addSymbolVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, symbol := range symbols {
-		for _, osv := range modVulns.vulnsForSymbol(pkg, symbol) {
-			addVuln(result, graph, osv, symbol, pkg)
+func binImportedVulnPackages(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg := range pkgSymbols {
+		for _, osv := range affVulns.ForPackage(internal.UnknownModulePath, pkg) {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg),
+			}
+			vulns = append(vulns, vuln)
 		}
 	}
+	return vulns
 }
 
-// findSetting returns value of setting from bi if present.
-// Otherwise, returns "".
-func findSetting(setting string, bi *debug.BuildInfo) string {
-	for _, s := range bi.Settings {
-		if s.Key == setting {
-			return s.Value
+func binVulnSymbols(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg, symbols := range pkgSymbols {
+		for _, symbol := range symbols {
+			for _, osv := range affVulns.ForSymbol(internal.UnknownModulePath, pkg, symbol) {
+				vuln := &Vuln{
+					OSV:     osv,
+					Symbol:  symbol,
+					Package: graph.GetPackage(pkg),
+				}
+				vulns = append(vulns, vuln)
+			}
 		}
 	}
-	return ""
+	return vulns
 }
 
-// addRequiresOnlyVulns adds to result all vulnerabilities in modVulns.
-// Used when the binary under analysis is stripped.
-func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVulnerabilities) {
-	for _, mv := range modVulns {
+// allKnownVulnerableSymbols returns all known vulnerable symbols for packages in graph.
+// If all symbols of a package are vulnerable, that is modeled as a wild car symbol "/*".
+func allKnownVulnerableSymbols(affVulns affectingVulns) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, mv := range affVulns {
 		for _, osv := range mv.Vulns {
 			for _, affected := range osv.Affected {
 				for _, p := range affected.EcosystemSpecific.Packages {
@@ -134,19 +198,40 @@ func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVu
 						syms = []string{fmt.Sprintf("%s/*", p.Path)}
 					}
 
-					for _, symbol := range syms {
-						addVuln(result, graph, osv, symbol, p.Path)
-					}
+					pkgSymbols[p.Path] = append(pkgSymbols[p.Path], syms...)
 				}
 			}
 		}
 	}
+	return pkgSymbols
 }
 
-func addVuln(result *Result, graph *PackageGraph, osv *osv.Entry, symbol string, pkgPath string) {
-	result.Vulns = append(result.Vulns, &Vuln{
-		OSV:        osv,
-		Symbol:     symbol,
-		ImportSink: graph.GetPackage(pkgPath),
+func (bin *Bin) SBOM() (sbom *govulncheck.SBOM) {
+	sbom = &govulncheck.SBOM{}
+	if bin.Main != nil {
+		sbom.Roots = []string{bin.Main.Path}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    bin.Main.Path,
+			Version: bin.Main.Version,
+		})
+	}
+
+	sbom.GoVersion = bin.GoVersion
+	for _, mod := range bin.Modules {
+		if mod.Replace != nil {
+			mod = mod.Replace
+		}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		})
+	}
+
+	// add stdlib to mirror source mode output
+	sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+		Path:    internal.GoStdModulePath,
+		Version: bin.GoVersion,
 	})
+
+	return sbom
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/doc.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
index 3f19e299..e56cdfbc 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
@@ -24,8 +24,7 @@ detection in Go source code and binaries, respectively.
 
 [Source] accepts a list of [Package] objects, which
 are a trimmed version of [golang.org/x/tools/go/packages.Package] objects to
-reduce memory consumption. [Binary] accepts a path to a Go binary file that
-must have been compiled with Go 1.18 or greater.
+reduce memory consumption. [Binary] accepts a path to a Go binary file.
 
 Both [Source] and [Binary] require information about known
 vulnerabilities in the form of a vulnerability database,
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/emit.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
new file mode 100644
index 00000000..fc9b2d7a
--- /dev/null
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
@@ -0,0 +1,198 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vulncheck
+
+import (
+	"go/token"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// emitOSVs emits all OSV vuln entries in modVulns to handler.
+func emitOSVs(handler govulncheck.Handler, modVulns []*ModVulns) error {
+	for _, mv := range modVulns {
+		for _, v := range mv.Vulns {
+			if err := handler.OSV(v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitModuleFindings emits module-level findings for vulnerabilities in modVulns.
+func emitModuleFindings(handler govulncheck.Handler, affVulns affectingVulns) error {
+	for _, vuln := range affVulns {
+		for _, osv := range vuln.Vulns {
+			if err := handler.Finding(&govulncheck.Finding{
+				OSV:          osv.ID,
+				FixedVersion: FixedVersion(modPath(vuln.Module), modVersion(vuln.Module), osv.Affected),
+				Trace:        []*govulncheck.Frame{frameFromModule(vuln.Module)},
+			}); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitPackageFinding emits package-level findings fod vulnerabilities in vulns.
+func emitPackageFindings(handler govulncheck.Handler, vulns []*Vuln) error {
+	for _, v := range vulns {
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          v.OSV.ID,
+			FixedVersion: FixedVersion(modPath(v.Package.Module), modVersion(v.Package.Module), v.OSV.Affected),
+			Trace:        []*govulncheck.Frame{frameFromPackage(v.Package)},
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// emitCallFindings emits call-level findings for vulnerabilities
+// that have a call stack in callstacks.
+func emitCallFindings(handler govulncheck.Handler, callstacks map[*Vuln]CallStack) error {
+	var vulns []*Vuln
+	for v := range callstacks {
+		vulns = append(vulns, v)
+	}
+
+	for _, vuln := range vulns {
+		stack := callstacks[vuln]
+		if stack == nil {
+			continue
+		}
+		fixed := FixedVersion(modPath(vuln.Package.Module), modVersion(vuln.Package.Module), vuln.OSV.Affected)
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          vuln.OSV.ID,
+			FixedVersion: fixed,
+			Trace:        traceFromEntries(stack),
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// traceFromEntries creates a sequence of
+// frames from vcs. Position of a Frame is the
+// call position of the corresponding stack entry.
+func traceFromEntries(vcs CallStack) []*govulncheck.Frame {
+	var frames []*govulncheck.Frame
+	for i := len(vcs) - 1; i >= 0; i-- {
+		e := vcs[i]
+		fr := frameFromPackage(e.Function.Package)
+		fr.Function = e.Function.Name
+		fr.Receiver = e.Function.Receiver()
+		isSink := i == (len(vcs) - 1)
+		fr.Position = posFromStackEntry(e, isSink)
+		frames = append(frames, fr)
+	}
+	return frames
+}
+
+func posFromStackEntry(e StackEntry, sink bool) *govulncheck.Position {
+	var p *token.Position
+	var f *FuncNode
+	if sink && e.Function != nil && e.Function.Pos != nil {
+		// For sinks, i.e., vulns we take the position
+		// of the symbol.
+		p = e.Function.Pos
+		f = e.Function
+	} else if e.Call != nil && e.Call.Pos != nil {
+		// Otherwise, we take the position of
+		// the call statement.
+		p = e.Call.Pos
+		f = e.Call.Parent
+	}
+
+	if p == nil {
+		return nil
+	}
+	return &govulncheck.Position{
+		Filename: pathRelativeToMod(p.Filename, f),
+		Offset:   p.Offset,
+		Line:     p.Line,
+		Column:   p.Column,
+	}
+}
+
+// pathRelativeToMod computes a version of path
+// relative to the module of f. If it does not
+// have all the necessary information, returns
+// an empty string.
+//
+// The returned paths always use slash as separator
+// so they can work across different platforms.
+func pathRelativeToMod(path string, f *FuncNode) string {
+	if path == "" || f == nil || f.Package == nil { // sanity
+		return ""
+	}
+
+	mod := f.Package.Module
+	if mod.Replace != nil {
+		mod = mod.Replace // for replace directive
+	}
+
+	modDir := modDirWithVendor(mod.Dir, path, mod.Path)
+	p, err := filepath.Rel(modDir, path)
+	if err != nil {
+		return ""
+	}
+	// make sure paths are portable.
+	return filepath.ToSlash(p)
+}
+
+// modDirWithVendor returns modDir if modDir is not empty.
+// Otherwise, the module might be located in the vendor
+// directory. This function attempts to reconstruct the
+// vendored module directory from path and module. It
+// returns an empty string if reconstruction fails.
+func modDirWithVendor(modDir, path, module string) string {
+	if modDir != "" {
+		return modDir
+	}
+
+	sep := string(os.PathSeparator)
+	vendor := sep + "vendor" + sep
+	vendorIndex := strings.Index(path, vendor)
+	if vendorIndex == -1 {
+		return ""
+	}
+	return filepath.Join(path[:vendorIndex], "vendor", filepath.FromSlash(module))
+}
+
+func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
+	fr := &govulncheck.Frame{}
+	if pkg != nil {
+		fr.Module = pkg.Module.Path
+		fr.Version = pkg.Module.Version
+		fr.Package = pkg.PkgPath
+	}
+	if pkg.Module.Replace != nil {
+		fr.Module = pkg.Module.Replace.Path
+		fr.Version = pkg.Module.Replace.Version
+	}
+	return fr
+}
+
+func frameFromModule(mod *packages.Module) *govulncheck.Frame {
+	fr := &govulncheck.Frame{
+		Module:  mod.Path,
+		Version: mod.Version,
+	}
+
+	if mod.Replace != nil {
+		fr.Module = mod.Replace.Path
+		fr.Version = mod.Replace.Version
+	}
+
+	return fr
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/entries.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
index 834d5901..3d46f6ca 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
@@ -10,6 +10,12 @@ import (
 	"golang.org/x/tools/go/ssa"
 )
 
+// entryPoints returns functions of topPackages considered entry
+// points of govulncheck analysis: main, inits, and exported methods
+// and functions.
+//
+// TODO(https://go.dev/issue/57221): currently, entry functions
+// that are generics are not considered an entry point.
 func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
 	var entries []*ssa.Function
 	for _, pkg := range topPackages {
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
index ef0c7ca9..700a7f99 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
@@ -6,6 +6,7 @@ package vulncheck
 
 import (
 	"context"
+	"fmt"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal/client"
@@ -25,7 +26,7 @@ func FetchVulnerabilities(ctx context.Context, c *client.Client, modules []*pack
 	}
 	resps, err := c.ByModules(ctx, mreqs)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("fetching vulnerabilities: %v", err)
 	}
 	var mv []*ModVulns
 	for i, resp := range resps {
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
deleted file mode 100644
index 1bdd38c7..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// This file adds to buildinfo the functionality for extracting the PCLN table.
-
-import (
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-)
-
-// ErrNoSymbols represents non-existence of symbol
-// table in binaries supported by buildinfo.
-var ErrNoSymbols = errors.New("no symbol section")
-
-// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
-func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		if errors.Is(err, elf.ErrNoSymbols) {
-			return 0, 0, nil, ErrNoSymbols
-		}
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	prog := x.progContaining(sym.Value)
-	if prog == nil {
-		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
-}
-
-func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		syms, err := x.f.Symbols()
-		if err != nil {
-			x.symbolsErr = err
-			return
-		}
-		x.symbols = make(map[string]*elf.Symbol, len(syms))
-		for _, s := range syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-func (x *elfExe) progContaining(addr uint64) *elf.Prog {
-	for _, p := range x.f.Progs {
-		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
-			return p
-		}
-	}
-	return nil
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
-	var offset uint64
-	text := x.f.Section(".text")
-	if text != nil {
-		offset = text.Offset
-	}
-	pclntab := x.f.Section(".gopclntab")
-	if pclntab == nil {
-		// Addition: this code is added to support some form of stripping.
-		pclntab = x.f.Section(".data.rel.ro.gopclntab")
-		if pclntab == nil {
-			pclntab = x.f.Section(".data.rel.ro")
-			if pclntab == nil {
-				return nil, 0
-			}
-			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
-			// its own section header. We can search for for the start by looking for the four
-			// byte magic and the go magic.
-			b, err := pclntab.Data()
-			if err != nil {
-				return nil, 0
-			}
-			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
-			// actually correct. During testing it worked, but that may be because I got lucky
-			// with the binary I was using, and we need to do four byte jumps to exhaustively
-			// search the section?
-			for i := 0; i < len(b); i += 16 {
-				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
-					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
-					(b[i+7] == 4 || b[i+7] == 8) {
-					// Also check for the go magic
-					leMagic := binary.LittleEndian.Uint32(b[i:])
-					beMagic := binary.BigEndian.Uint32(b[i:])
-					switch {
-					case leMagic == go12magic:
-						fallthrough
-					case beMagic == go12magic:
-						fallthrough
-					case leMagic == go116magic:
-						fallthrough
-					case beMagic == go116magic:
-						return b[i:], offset
-					}
-				}
-			}
-		}
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, offset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
-func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		return 0, 0, nil, err
-	}
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	sect := x.f.Sections[sym.SectionNumber-1]
-	// In PE, the symbol's value is the offset from the section start.
-	return uint64(sym.Value), 0, sect.ReaderAt, nil
-}
-
-func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
-		if len(x.f.Symbols) == 0 {
-			x.symbolsErr = ErrNoSymbols
-			return
-		}
-		for _, s := range x.f.Symbols {
-			x.symbols[s.Name] = s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
-// Assumes that the underlying symbol table exists, otherwise
-// it might panic.
-func (x *peExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	for _, section := range x.f.Sections {
-		if section.Name == ".text" {
-			textOffset = uint64(section.Offset)
-			break
-		}
-	}
-
-	var start, end int64
-	var section int
-	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
-		start = int64(s.Value)
-		section = int(s.SectionNumber - 1)
-	}
-	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
-		end = int64(s.Value)
-	}
-	if start == 0 || end == 0 {
-		return nil, 0
-	}
-	offset := int64(x.f.Sections[section].Offset) + start
-	size := end - start
-
-	pclntab := make([]byte, size)
-	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
-		return nil, 0
-	}
-	return pclntab, textOffset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
-func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym := x.lookupSymbol(name)
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	seg := x.segmentContaining(sym.Value)
-	if seg == nil {
-		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, seg.Addr, seg.ReaderAt, nil
-}
-
-func (x *machoExe) lookupSymbol(name string) *macho.Symbol {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
-		for _, s := range x.f.Symtab.Syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	return x.symbols[name]
-}
-
-func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
-			return seg
-		}
-	}
-	return nil
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	text := x.f.Section("__text")
-	if text != nil {
-		textOffset = uint64(text.Offset)
-	}
-	pclntab := x.f.Section("__gopclntab")
-	if pclntab == nil {
-		return nil, 0
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, textOffset
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
deleted file mode 100644
index 9790cfa9..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
-	"debug/buildinfo"
-	"errors"
-	"fmt"
-	"io"
-	"net/url"
-	"runtime/debug"
-	"sort"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal/vulncheck/internal/gosym"
-)
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
-	packagesModules := make([]*packages.Module, len(debugModules))
-	for i, mod := range debugModules {
-		packagesModules[i] = &packages.Module{
-			Path:    mod.Path,
-			Version: mod.Version,
-		}
-		if mod.Replace != nil {
-			packagesModules[i].Replace = &packages.Module{
-				Path:    mod.Replace.Path,
-				Version: mod.Replace.Version,
-			}
-		}
-	}
-	return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts symbols, packages, modules from
-// bin as well as bin's metadata.
-//
-// If the symbol table is not available, such as in the case of stripped
-// binaries, returns module and binary info but without the symbol info.
-func ExtractPackagesAndSymbols(bin io.ReaderAt) ([]*packages.Module, map[string][]string, *debug.BuildInfo, error) {
-	bi, err := buildinfo.Read(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	funcSymName := gosym.FuncSymName(bi.GoVersion)
-	if funcSymName == "" {
-		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
-	}
-
-	x, err := openExe(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	value, base, r, err := x.SymbolInfo(funcSymName)
-	if err != nil {
-		if errors.Is(err, ErrNoSymbols) {
-			// bin is stripped, so return just module info and metadata.
-			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
-		}
-		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
-	}
-
-	pclntab, textOffset := x.PCLNTab()
-	if pclntab == nil {
-		// TODO(https://go.dev/issue/59731): if we have build information, but
-		// not PCLN table, we should be able to fall back to much higher
-		// granularity vulnerability checking.
-		return nil, nil, nil, errors.New("unable to load the PCLN table")
-	}
-	lineTab := gosym.NewLineTable(pclntab, textOffset)
-	if lineTab == nil {
-		return nil, nil, nil, errors.New("invalid line table")
-	}
-	tab, err := gosym.NewTable(nil, lineTab)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	type pkgSymbol struct {
-		pkg string
-		sym string
-	}
-	pkgSyms := make(map[pkgSymbol]bool)
-	for _, f := range tab.Funcs {
-		if f.Func == nil {
-			continue
-		}
-		pkgName, symName, err := parseName(f.Func.Sym)
-		if err != nil {
-			return nil, nil, nil, err
-		}
-		pkgSyms[pkgSymbol{pkgName, symName}] = true
-
-		// Collect symbols that were inlined in f.
-		it, err := lineTab.InlineTree(&f, value, base, r)
-		if err != nil {
-			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
-		}
-		for _, ic := range it {
-			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
-			if err != nil {
-				return nil, nil, nil, err
-			}
-			pkgSyms[pkgSymbol{pkgName, symName}] = true
-		}
-	}
-
-	packageSymbols := make(map[string][]string)
-	for p := range pkgSyms {
-		packageSymbols[p.pkg] = append(packageSymbols[p.pkg], p.sym)
-	}
-	// Sort symbols per pkg for deterministic results.
-	for _, syms := range packageSymbols {
-		sort.Strings(syms)
-	}
-
-	return debugModulesToPackagesModules(bi.Deps), packageSymbols, bi, nil
-}
-
-func parseName(s *gosym.Sym) (pkg, sym string, err error) {
-	symName := s.BaseName()
-	if r := s.ReceiverName(); r != "" {
-		if strings.HasPrefix(r, "(*") {
-			r = strings.Trim(r, "(*)")
-		}
-		symName = fmt.Sprintf("%s.%s", r, symName)
-	}
-
-	pkgName := s.PackageName()
-	if pkgName != "" {
-		pkgName, err = url.PathUnescape(pkgName)
-		if err != nil {
-			return "", "", err
-		}
-	}
-	return pkgName, symName, nil
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
deleted file mode 100644
index 1be795ee..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
-
-import (
-	"bytes"
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"fmt"
-	"sync"
-
-	// "internal/xcoff"
-	"io"
-)
-
-// Addition: modification of rawBuildInfo in the original file.
-// openExe returns reader r as an exe.
-func openExe(r io.ReaderAt) (exe, error) {
-	data := make([]byte, 16)
-	if _, err := r.ReadAt(data, 0); err != nil {
-		return nil, err
-	}
-	if bytes.HasPrefix(data, []byte("\x7FELF")) {
-		e, err := elf.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &elfExe{f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("MZ")) {
-		e, err := pe.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &peExe{r: r, f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
-		e, err := macho.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &machoExe{f: e}, nil
-	}
-	return nil, fmt.Errorf("unrecognized executable format")
-}
-
-type exe interface {
-	// ReadData reads and returns up to size byte starting at virtual address addr.
-	ReadData(addr, size uint64) ([]byte, error)
-
-	// DataStart returns the virtual address of the segment or section that
-	// should contain build information. This is either a specially named section
-	// or the first writable non-zero data segment.
-	DataStart() uint64
-
-	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
-
-	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
-	f *elf.File
-
-	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once              // Addition: for computing symbols
-	symbolsErr  error                  // Addition: error for computing symbols
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, prog := range x.f.Progs {
-		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
-			n := prog.Vaddr + prog.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *elfExe) DataStart() uint64 {
-	for _, s := range x.f.Sections {
-		if s.Name == ".go.buildinfo" {
-			return s.Addr
-		}
-	}
-	for _, p := range x.f.Progs {
-		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
-			return p.Vaddr
-		}
-	}
-	return 0
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
-	r io.ReaderAt
-	f *pe.File
-
-	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once             // Addition: for computing symbols
-	symbolsErr  error                 // Addition: error for computing symbols
-}
-
-func (x *peExe) imageBase() uint64 {
-	switch oh := x.f.OptionalHeader.(type) {
-	case *pe.OptionalHeader32:
-		return uint64(oh.ImageBase)
-	case *pe.OptionalHeader64:
-		return oh.ImageBase
-	}
-	return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
-	addr -= x.imageBase()
-	for _, sect := range x.f.Sections {
-		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-			n := uint64(sect.VirtualAddress+sect.Size) - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *peExe) DataStart() uint64 {
-	// Assume data is first writable section.
-	const (
-		IMAGE_SCN_CNT_CODE               = 0x00000020
-		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-		IMAGE_SCN_MEM_READ               = 0x40000000
-		IMAGE_SCN_MEM_WRITE              = 0x80000000
-		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-	)
-	for _, sect := range x.f.Sections {
-		if sect.VirtualAddress != 0 && sect.Size != 0 &&
-			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
-			return uint64(sect.VirtualAddress) + x.imageBase()
-		}
-	}
-	return 0
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
-	f *macho.File
-
-	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once                // Addition: for computing symbols
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if !ok {
-			continue
-		}
-		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
-			if seg.Name == "__PAGEZERO" {
-				continue
-			}
-			n := seg.Addr + seg.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *machoExe) DataStart() uint64 {
-	// Look for section named "__go_buildinfo".
-	for _, sec := range x.f.Sections {
-		if sec.Name == "__go_buildinfo" {
-			return sec.Addr
-		}
-	}
-	// Try the first non-empty writable segment.
-	const RW = 3
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
-			return seg.Addr
-		}
-	}
-	return 0
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
deleted file mode 100644
index f608c151..00000000
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gosym
-
-import (
-	"encoding/binary"
-	"io"
-	"strings"
-
-	sv "golang.org/x/mod/semver"
-	"golang.org/x/vuln/internal/semver"
-)
-
-const (
-	funcSymNameGo119Lower string = "go.func.*"
-	funcSymNameGo120      string = "go:func.*"
-)
-
-// FuncSymName returns symbol name for Go functions
-// used in binaries based on Go version. Supported
-// Go versions are 1.18, 1.19, and 1.20. Otherwise,
-// returns an empty string.
-func FuncSymName(goVersion string) string {
-	// Support devel goX.Y...
-	v := strings.TrimPrefix(goVersion, "devel ")
-	v = semver.GoTagToSemver(v)
-	mm := sv.MajorMinor(v)
-	if mm == "v1.18" || mm == "v1.19" {
-		return funcSymNameGo119Lower
-	} else if mm == "v1.20" {
-		return funcSymNameGo120
-	} else if v == "" && strings.HasPrefix(goVersion, "devel") {
-		// We currently don't have a direct way of mapping
-		// Go versions of the form devel  to semver,
-		// so we map it to the most recent supported major
-		// Go version, which is currently go1.20.
-		return funcSymNameGo120
-	}
-	return ""
-}
-
-// Additions to the original package from cmd/internal/objabi/funcdata.go
-const (
-	pcdata_InlTreeIndex = 2
-	funcdata_InlTree    = 3
-)
-
-// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
-// goFuncValue is the value of the gosym.FuncSymName symbol.
-// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
-// progReader is a ReaderAt positioned at the start of that region.
-func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
-	if f.inlineTreeCount == 0 {
-		return nil, nil
-	}
-	if f.inlineTreeOffset == ^uint32(0) {
-		return nil, nil
-	}
-	var offset int64
-	if t.version >= ver118 {
-		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
-	} else {
-		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
-	}
-
-	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
-	var ics []InlinedCall
-	for i := 0; i < f.inlineTreeCount; i++ {
-		if t.version >= ver120 {
-			var ric rawInlinedCall120
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.NameOff)),
-				ParentPC: ric.ParentPC,
-			})
-		} else {
-			var ric rawInlinedCall112
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.Func_)),
-				ParentPC: ric.ParentPC,
-			})
-		}
-	}
-	return ics, nil
-}
-
-// InlinedCall describes a call to an inlined function.
-type InlinedCall struct {
-	FuncID   uint8  // type of the called function
-	Name     string // name of called function
-	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall112 struct {
-	Parent   int16 // index of parent in the inltree, or < 0
-	FuncID   uint8 // type of the called function
-	_        byte
-	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
-	Line     int32 // line number of the call site
-	Func_    int32 // offset into pclntab for name of called function
-	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.20. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall120 struct {
-	FuncID    uint8 // type of the called function
-	_         [3]byte
-	NameOff   int32 // offset into pclntab for name of called function
-	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
-	StartLine int32 // line number of start of function (func keyword/TEXT directive)
-}
-
-func (f funcData) npcdata() uint32 { return f.field(7) }
-func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
-	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
-}
-
-func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.nfuncdata(numFuncFields) {
-		return ^uint32(0)
-	}
-	var off uint32
-	if f.t.version >= ver118 {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4 + // skip pcdata
-			uint32(i)*4 // index of i'th FUNCDATA
-	} else {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4
-		off += uint32(i) * f.t.ptrsize
-	}
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-func (f funcData) fieldOffset(n uint32) uint32 {
-	// In Go 1.18, the first field of _func changed
-	// from a uintptr entry PC to a uint32 entry offset.
-	sz0 := f.t.ptrsize
-	if f.t.version >= ver118 {
-		sz0 = 4
-	}
-	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
-}
-
-func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.npcdata() {
-		return ^uint32(0)
-	}
-	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
-		uint32(i)*4 // index of i'th PCDATA
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-// maxInlineTreeIndexValue returns the maximum value of the inline tree index
-// pc-value table in info. This is the only way to determine how many
-// IndexedCalls are in an inline tree, since the data of the tree itself is not
-// delimited in any way.
-func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
-	if info.npcdata() <= pcdata_InlTreeIndex {
-		return -1
-	}
-	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
-	p := t.pctab[off:]
-	val := int32(-1)
-	max := int32(-1)
-	var pc uint64
-	for t.step(&p, &pc, &val, pc == 0) {
-		if val > max {
-			max = val
-		}
-	}
-	return int(max)
-}
-
-type inlTree struct {
-	inlineTreeOffset uint32 // offset from go.func.* symbol
-	inlineTreeCount  int    // number of entries in inline tree
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/packages.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
index 124a9a50..484e5494 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
@@ -6,18 +6,25 @@ package vulncheck
 
 import (
 	"fmt"
+	"os/exec"
+	"slices"
 	"strings"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/semver"
 )
 
 // PackageGraph holds a complete module and package graph.
-// Its primary purpose is to allow fast access to the nodes by path.
+// Its primary purpose is to allow fast access to the nodes
+// by path and make sure all(stdlib)  packages have a module.
 type PackageGraph struct {
-	modules  map[string]*packages.Module
-	packages map[string]*packages.Package
+	// topPkgs are top-level packages specified by the user.
+	// Empty in binary mode.
+	topPkgs  []*packages.Package
+	modules  map[string]*packages.Module  // all modules (even replacing ones)
+	packages map[string]*packages.Package // all packages (even dependencies)
 }
 
 func NewPackageGraph(goVersion string) *PackageGraph {
@@ -25,15 +32,83 @@ func NewPackageGraph(goVersion string) *PackageGraph {
 		modules:  map[string]*packages.Module{},
 		packages: map[string]*packages.Package{},
 	}
-	graph.AddModules(&packages.Module{
+
+	goRoot := ""
+	if out, err := exec.Command("go", "env", "GOROOT").Output(); err == nil {
+		goRoot = strings.TrimSpace(string(out))
+	}
+	stdlibModule := &packages.Module{
 		Path:    internal.GoStdModulePath,
 		Version: semver.GoTagToSemver(goVersion),
-	})
+		Dir:     goRoot,
+	}
+	graph.AddModules(stdlibModule)
 	return graph
 }
 
+func (g *PackageGraph) TopPkgs() []*packages.Package {
+	return g.topPkgs
+}
+
+// DepPkgs returns the number of packages that graph.TopPkgs()
+// strictly depend on. This does not include topPkgs even if
+// they are dependency of each other.
+func (g *PackageGraph) DepPkgs() []*packages.Package {
+	topPkgs := g.TopPkgs()
+	tops := make(map[string]bool)
+	depPkgs := make(map[string]*packages.Package)
+
+	for _, t := range topPkgs {
+		tops[t.PkgPath] = true
+	}
+
+	var visit func(*packages.Package, bool)
+	visit = func(p *packages.Package, top bool) {
+		path := p.PkgPath
+		if _, ok := depPkgs[path]; ok {
+			return
+		}
+		if tops[path] && !top {
+			// A top package that is a dependency
+			// will not be in depPkgs, so we skip
+			// reiterating on it here.
+			return
+		}
+
+		// We don't count a top-level package as
+		// a dependency even when they are used
+		// as a dependent package.
+		if !tops[path] {
+			depPkgs[path] = p
+		}
+
+		for _, d := range p.Imports {
+			visit(d, false)
+		}
+	}
+
+	for _, t := range topPkgs {
+		visit(t, true)
+	}
+
+	var deps []*packages.Package
+	for _, d := range depPkgs {
+		deps = append(deps, g.GetPackage(d.PkgPath))
+	}
+	return deps
+}
+
+func (g *PackageGraph) Modules() []*packages.Module {
+	var mods []*packages.Module
+	for _, m := range g.modules {
+		mods = append(mods, m)
+	}
+	return mods
+}
+
 // AddModules adds the modules and any replace modules provided.
-// It will ignore modules that have duplicate paths to ones the graph already holds.
+// It will ignore modules that have duplicate paths to ones the
+// graph already holds.
 func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	for _, mod := range mods {
 		if _, found := g.modules[mod.Path]; found {
@@ -47,7 +122,8 @@ func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	}
 }
 
-// .
+// GetModule gets module at path if one exists. Otherwise,
+// it creates a module and returns it.
 func (g *PackageGraph) GetModule(path string) *packages.Module {
 	if mod, ok := g.modules[path]; ok {
 		return mod
@@ -60,8 +136,9 @@ func (g *PackageGraph) GetModule(path string) *packages.Module {
 	return mod
 }
 
-// AddPackages adds the packages and the full graph of imported packages.
-// It will ignore packages that have duplicate paths to ones the graph already holds.
+// AddPackages adds the packages and their full graph of imported packages.
+// It also adds the modules of the added packages. It will ignore packages
+// that have duplicate paths to ones the graph already holds.
 func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	for _, pkg := range pkgs {
 		if _, found := g.packages[pkg.PkgPath]; found {
@@ -76,6 +153,9 @@ func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	}
 }
 
+// fixupPackage adds the module of pkg, if any, to the set
+// of all modules in g. If packages is not assigned a module
+// (likely stdlib package), a module set for pkg.
 func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 	if pkg.Module != nil {
 		g.AddModules(pkg.Module)
@@ -89,7 +169,7 @@ func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 // not find anything, it returns the "unknown" module.
 func (g *PackageGraph) findModule(pkgPath string) *packages.Module {
 	//TODO: better stdlib test
-	if !strings.Contains(pkgPath, ".") {
+	if IsStdPackage(pkgPath) {
 		return g.GetModule(internal.GoStdModulePath)
 	}
 	for _, m := range g.modules {
@@ -116,22 +196,16 @@ func (g *PackageGraph) GetPackage(path string) *packages.Package {
 
 // LoadPackages loads the packages specified by the patterns into the graph.
 // See golang.org/x/tools/go/packages.Load for details of how it works.
-func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, patterns []string) ([]*packages.Package, error) {
+func (g *PackageGraph) LoadPackagesAndMods(cfg *packages.Config, tags []string, patterns []string, wantSymbols bool) error {
 	if len(tags) > 0 {
 		cfg.BuildFlags = []string{fmt.Sprintf("-tags=%s", strings.Join(tags, ","))}
 	}
-	cfg.Mode |=
-		packages.NeedDeps |
-			packages.NeedImports |
-			packages.NeedModule |
-			packages.NeedSyntax |
-			packages.NeedTypes |
-			packages.NeedTypesInfo |
-			packages.NeedName
+
+	addLoadMode(cfg, wantSymbols)
 
 	pkgs, err := packages.Load(cfg, patterns...)
 	if err != nil {
-		return nil, err
+		return err
 	}
 	var perrs []packages.Error
 	packages.Visit(pkgs, nil, func(p *packages.Package) {
@@ -140,8 +214,27 @@ func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, pattern
 	if len(perrs) > 0 {
 		err = &packageError{perrs}
 	}
+
+	// Add all packages, top-level ones and their imports.
+	// This will also add their respective modules.
 	g.AddPackages(pkgs...)
-	return pkgs, err
+
+	// save top-level packages
+	for _, p := range pkgs {
+		g.topPkgs = append(g.topPkgs, g.GetPackage(p.PkgPath))
+	}
+	return err
+}
+
+func addLoadMode(cfg *packages.Config, wantSymbols bool) {
+	cfg.Mode |=
+		packages.NeedModule |
+			packages.NeedName |
+			packages.NeedDeps |
+			packages.NeedImports
+	if wantSymbols {
+		cfg.Mode |= packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo
+	}
 }
 
 // packageError contains errors from loading a set of packages.
@@ -159,3 +252,67 @@ func (e *packageError) Error() string {
 	fmt.Fprintln(&b, "\nFor details on package patterns, see https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.")
 	return b.String()
 }
+
+func (g *PackageGraph) SBOM() *govulncheck.SBOM {
+	getMod := func(mod *packages.Module) *govulncheck.Module {
+		if mod.Replace != nil {
+			return &govulncheck.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+
+		return &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+	}
+
+	var roots []string
+	rootMods := make(map[string]*govulncheck.Module)
+	for _, pkg := range g.TopPkgs() {
+		roots = append(roots, pkg.PkgPath)
+		mod := getMod(pkg.Module)
+		rootMods[mod.Path] = mod
+	}
+
+	// Govulncheck attempts to put the modules that correspond to the matched package patterns (i.e. the root modules)
+	// at the beginning of the SBOM.Modules message.
+	// Note: This does not guarantee that the first element is the root module.
+	var topMods, depMods []*govulncheck.Module
+	var goVersion string
+	for _, mod := range g.Modules() {
+		mod := getMod(mod)
+
+		if mod.Path == internal.GoStdModulePath {
+			goVersion = semver.SemverToGoTag(mod.Version)
+		}
+
+		// if the mod is not associated with a root package, add it to depMods
+		if rootMods[mod.Path] == nil {
+			depMods = append(depMods, mod)
+		}
+	}
+
+	for _, mod := range rootMods {
+		topMods = append(topMods, mod)
+	}
+	// Sort for deterministic output
+	sortMods(topMods)
+	sortMods(depMods)
+
+	mods := append(topMods, depMods...)
+
+	return &govulncheck.SBOM{
+		GoVersion: goVersion,
+		Modules:   mods,
+		Roots:     roots,
+	}
+}
+
+// Sorts modules alphabetically by path.
+func sortMods(mods []*govulncheck.Module) {
+	slices.SortFunc(mods, func(a, b *govulncheck.Module) int {
+		return strings.Compare(a.Path, b.Path)
+	})
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
index 71fffc41..0bfa1603 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
@@ -44,12 +44,3 @@ func forwardSlice(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.
 	}
 	return seen
 }
-
-// pruneSet removes functions in `set` that are in `toPrune`.
-func pruneSet(set, toPrune map[*ssa.Function]bool) {
-	for f := range set {
-		if !toPrune[f] {
-			delete(set, f)
-		}
-	}
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/source.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/source.go
index 2119c70d..348c3b96 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/source.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/source.go
@@ -6,8 +6,6 @@ package vulncheck
 
 import (
 	"context"
-	"fmt"
-	"go/token"
 	"sync"
 
 	"golang.org/x/tools/go/callgraph"
@@ -18,32 +16,24 @@ import (
 	"golang.org/x/vuln/internal/osv"
 )
 
-// Source detects vulnerabilities in packages. The result will contain:
-//
-// 1) An ImportGraph related to an import of a package with some known
-// vulnerabilities.
-//
-// 2) A RequireGraph related to a require of a module with a package that has
-// some known vulnerabilities.
-//
-// 3) A CallGraph leading to the use of a known vulnerable function or method.
-func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (_ *Result, err error) {
-	// buildSSA builds a whole program that assumes all packages use the same FileSet.
-	// Check all packages in pkgs are using the same FileSet.
-	// TODO(https://go.dev/issue/59729): take FileSet out of Package and
-	// let Source take a single FileSet. That will make the enforcement
-	// clearer from the API level.
-	var fset *token.FileSet
-	for _, p := range pkgs {
-		if fset == nil {
-			fset = p.Fset
-		} else {
-			if fset != p.Fset {
-				return nil, fmt.Errorf("[]*Package must have created with the same FileSet")
-			}
-		}
+// Source detects vulnerabilities in pkgs and emits the findings to handler.
+func Source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) error {
+	vr, err := source(ctx, handler, cfg, client, graph)
+	if err != nil {
+		return err
+	}
+
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, sourceCallstacks(vr))
 	}
+	return nil
+}
 
+// source detects vulnerabilities in packages. It emits findings to handler
+// and produces a Result that contains info on detected vulnerabilities.
+//
+// Assumes that pkgs are non-empty and belong to the same program.
+func source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (*Result, error) {
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
@@ -57,118 +47,109 @@ func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Conf
 		buildErr error
 	)
 	if cfg.ScanLevel.WantSymbols() {
+		fset := graph.TopPkgs()[0].Fset
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			prog, ssaPkgs := buildSSA(pkgs, fset)
+			prog, ssaPkgs := buildSSA(graph.TopPkgs(), fset)
 			entries = entryPoints(ssaPkgs)
 			cg, buildErr = callGraph(ctx, prog, entries)
 		}()
 	}
 
-	mods := extractModules(pkgs)
-	mv, err := FetchVulnerabilities(ctx, client, mods)
-	if err != nil {
+	if err := handler.SBOM(graph.SBOM()); err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
-	modVulns = modVulns.filter("", "")
-	result := &Result{}
 
-	vulnPkgModSlice(pkgs, modVulns, result)
-	// Return result immediately if not in symbol mode or
-	// if there are no vulnerable packages.
-	if !cfg.ScanLevel.WantSymbols() || len(result.EntryPackages) == 0 {
-		return result, nil
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
 	}
 
-	wg.Wait() // wait for build to finish
-	if buildErr != nil {
+	mv, err := FetchVulnerabilities(ctx, client, graph.Modules())
+	if err != nil {
 		return nil, err
 	}
 
-	vulnCallGraphSlice(entries, modVulns, cg, result, graph)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
 
-	return result, nil
-}
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingSrcVulnsMessage}); err != nil {
+		return nil, err
+	}
 
-// vulnPkgModSlice computes the slice of pkgs imports and requires graph
-// leading to imports/requires of vulnerable packages/modules in modVulns
-// and stores the computed slices to result.
-func vulnPkgModSlice(pkgs []*packages.Package, modVulns moduleVulnerabilities, result *Result) {
-	// analyzedPkgs contains information on packages analyzed thus far.
-	// If a package is mapped to false, this means it has been visited
-	// but it does not lead to a vulnerable imports. Otherwise, a
-	// visited package is mapped to true.
-	analyzedPkgs := make(map[*packages.Package]bool)
-	for _, pkg := range pkgs {
-		// Top level packages that lead to vulnerable imports are
-		// stored as result.EntryPackages graph entry points.
-		if vulnerable := vulnImportSlice(pkg, modVulns, result, analyzedPkgs); vulnerable {
-			result.EntryPackages = append(result.EntryPackages, pkg)
-		}
+	affVulns := affectingVulnerabilities(mv, "", "")
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
-}
 
-// vulnImportSlice checks if pkg has some vulnerabilities or transitively imports
-// a package with known vulnerabilities. If that is the case, populates result.Imports
-// graph with this reachability information and returns the result.Imports package
-// node for pkg. Otherwise, returns nil.
-func vulnImportSlice(pkg *packages.Package, modVulns moduleVulnerabilities, result *Result, analyzed map[*packages.Package]bool) bool {
-	if vulnerable, ok := analyzed[pkg]; ok {
-		return vulnerable
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
 	}
-	analyzed[pkg] = false
-	// Recursively compute which direct dependencies lead to an import of
-	// a vulnerable package and remember the nodes of such dependencies.
-	transitiveVulnerable := false
-	for _, imp := range pkg.Imports {
-		if impVulnerable := vulnImportSlice(imp, modVulns, result, analyzed); impVulnerable {
-			transitiveVulnerable = true
-		}
+
+	impVulns := importedVulnPackages(affVulns, graph)
+	// Emit information on imported vulnerable packages now as
+	// call graph computation might take a while.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
 	}
 
-	// Check if pkg has known vulnerabilities.
-	vulns := modVulns.vulnsForPackage(pkg.PkgPath)
+	// Return result immediately if not in symbol mode or
+	// if there are no vulnerabilities imported.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
 
-	// If pkg is not vulnerable nor it transitively leads
-	// to vulnerabilities, jump out.
-	if !transitiveVulnerable && len(vulns) == 0 {
-		return false
+	wg.Wait() // wait for build to finish
+	if buildErr != nil {
+		return nil, err
 	}
 
-	// Create Vuln entry for each symbol of known OSV entries for pkg.
-	for _, osv := range vulns {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg.PkgPath {
-					continue
-				}
-
-				symbols := p.Symbols
-				if len(symbols) == 0 {
-					symbols = allSymbols(pkg.Types)
-				}
-
-				for _, symbol := range symbols {
-					vuln := &Vuln{
-						OSV:        osv,
-						Symbol:     symbol,
-						ImportSink: pkg,
-					}
-					result.Vulns = append(result.Vulns, vuln)
-				}
+	entryFuncs, callVulns := calledVulnSymbols(entries, affVulns, cg, graph)
+	return &Result{EntryFunctions: entryFuncs, Vulns: callVulns}, nil
+}
+
+// importedVulnPackages detects imported vulnerable packages.
+func importedVulnPackages(affVulns affectingVulns, graph *PackageGraph) []*Vuln {
+	var vulns []*Vuln
+	analyzed := make(map[*packages.Package]bool) // skip analyzing the same package multiple times
+	var vulnImports func(pkg *packages.Package)
+	vulnImports = func(pkg *packages.Package) {
+		if analyzed[pkg] {
+			return
+		}
+
+		osvs := affVulns.ForPackage(pkgModPath(pkg), pkg.PkgPath)
+		// Create Vuln entry for each OSV entry for pkg.
+		for _, osv := range osvs {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg.PkgPath),
 			}
+			vulns = append(vulns, vuln)
+		}
+
+		analyzed[pkg] = true
+		for _, imp := range pkg.Imports {
+			vulnImports(imp)
 		}
 	}
-	analyzed[pkg] = true
-	return true
+
+	for _, pkg := range graph.TopPkgs() {
+		vulnImports(pkg)
+	}
+	return vulns
 }
 
-// vulnCallGraphSlice checks if known vulnerabilities are transitively reachable from sources
-// via call graph cg. If so, populates result.Calls graph with this reachability information.
-func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result, graph *PackageGraph) {
-	sinksWithVulns := vulnFuncs(cg, modVulns)
+// calledVulnSymbols detects vuln symbols transitively reachable from sources
+// via call graph cg.
+//
+// A slice of call graph is computed related to the reachable vulnerabilities. Each
+// reachable Vuln has attached FuncNode that can be upward traversed to the entry points.
+// Entry points that reach the vulnerable symbols are also returned.
+func calledVulnSymbols(sources []*ssa.Function, affVulns affectingVulns, cg *callgraph.Graph, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	sinksWithVulns := vulnFuncs(cg, affVulns, graph)
 
 	// Compute call graph backwards reachable
 	// from vulnerable functions and methods.
@@ -197,8 +178,8 @@ func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities,
 	}
 
 	// Transform the resulting call graph slice into
-	// vulncheck representation and store it to result.
-	vulnCallGraph(filteredSources, filteredSinks, result, graph)
+	// vulncheck representation.
+	return vulnCallGraph(filteredSources, filteredSinks, graph)
 }
 
 // callGraphSlice computes a slice of callgraph beginning at starts
@@ -240,25 +221,25 @@ func callGraphSlice(starts []*callgraph.Node, forward bool) *callgraph.Graph {
 	return g
 }
 
-// vulnCallGraph creates vulnerability call graph from sources -> sinks reachability info.
-func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, result *Result, graph *PackageGraph) {
+// vulnCallGraph creates vulnerability call graph in terms of sources and sinks.
+func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	var entries []*FuncNode
+	var vulns []*Vuln
 	nodes := make(map[*ssa.Function]*FuncNode)
 
 	// First create entries and sinks and store relevant information.
 	for _, s := range sources {
 		fn := createNode(nodes, s.Func, graph)
-		result.EntryFunctions = append(result.EntryFunctions, fn)
+		entries = append(entries, fn)
 	}
 
-	for s, vulns := range sinks {
+	for s, osvs := range sinks {
 		f := s.Func
 		funNode := createNode(nodes, s.Func, graph)
 
 		// Populate CallSink field for each detected vuln symbol.
-		for _, osv := range vulns {
-			if vulnMatchesPackage(osv, funNode.Package.PkgPath) {
-				addCallSinkForVuln(funNode, osv, dbFuncName(f), funNode.Package.PkgPath, result)
-			}
+		for _, osv := range osvs {
+			vulns = append(vulns, calledVuln(funNode, osv, dbFuncName(f), funNode.Package))
 		}
 	}
 
@@ -291,13 +272,15 @@ func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.E
 	for s := range sinks {
 		visit(s)
 	}
+	return entries, vulns
 }
 
 // vulnFuncs returns vulnerability information for vulnerable functions in cg.
-func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgraph.Node][]*osv.Entry {
+func vulnFuncs(cg *callgraph.Graph, affVulns affectingVulns, graph *PackageGraph) map[*callgraph.Node][]*osv.Entry {
 	m := make(map[*callgraph.Node][]*osv.Entry)
 	for f, n := range cg.Nodes {
-		vulns := modVulns.vulnsForSymbol(pkgPath(f), dbFuncName(f))
+		p := pkgPath(f)
+		vulns := affVulns.ForSymbol(pkgModPath(graph.GetPackage(p)), p, dbFuncName(f))
 		if len(vulns) > 0 {
 			m[n] = vulns
 		}
@@ -305,15 +288,6 @@ func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgra
 	return m
 }
 
-// pkgPath returns the path of the f's enclosing package, if any.
-// Otherwise, returns "".
-func pkgPath(f *ssa.Function) string {
-	if f.Package() != nil && f.Package().Pkg != nil {
-		return f.Package().Pkg.Path()
-	}
-	return ""
-}
-
 func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *PackageGraph) *FuncNode {
 	if fn, ok := nodes[f]; ok {
 		return fn
@@ -328,46 +302,11 @@ func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *Packa
 	return fn
 }
 
-// addCallSinkForVuln adds callID as call sink to vuln of result.Vulns
-// identified with .
-func addCallSinkForVuln(call *FuncNode, osv *osv.Entry, symbol, pkg string, result *Result) {
-	for _, vuln := range result.Vulns {
-		if vuln.OSV == osv && vuln.Symbol == symbol && vuln.ImportSink.PkgPath == pkg {
-			vuln.CallSink = call
-			return
-		}
-	}
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*packages.Package) []*packages.Module {
-	modMap := map[string]*packages.Module{}
-	seen := map[*packages.Package]bool{}
-	var extract func(*packages.Package, map[string]*packages.Module)
-	extract = func(pkg *packages.Package, modMap map[string]*packages.Module) {
-		if pkg == nil || seen[pkg] {
-			return
-		}
-		if pkg.Module != nil {
-			if pkg.Module.Replace != nil {
-				modMap[pkg.Module.Replace.Path] = pkg.Module
-			} else {
-				modMap[pkg.Module.Path] = pkg.Module
-			}
-		}
-		seen[pkg] = true
-		for _, imp := range pkg.Imports {
-			extract(imp, modMap)
-		}
-	}
-	for _, pkg := range pkgs {
-		extract(pkg, modMap)
-	}
-
-	modules := []*packages.Module{}
-	for _, mod := range modMap {
-		modules = append(modules, mod)
+func calledVuln(call *FuncNode, osv *osv.Entry, symbol string, pkg *packages.Package) *Vuln {
+	return &Vuln{
+		Symbol:   symbol,
+		Package:  pkg,
+		OSV:      osv,
+		CallSink: call,
 	}
-	return modules
 }
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/utils.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
index 4fa9c69a..e752f4a0 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
@@ -9,15 +9,17 @@ import (
 	"context"
 	"go/token"
 	"go/types"
+	"sort"
 	"strings"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/callgraph/cha"
 	"golang.org/x/tools/go/callgraph/vta"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa/ssautil"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/semver"
 
 	"golang.org/x/tools/go/ssa"
 )
@@ -26,7 +28,6 @@ import (
 // the ssa program encapsulating the packages and top level
 // ssa packages corresponding to pkgs.
 func buildSSA(pkgs []*packages.Package, fset *token.FileSet) (*ssa.Program, []*ssa.Package) {
-	// TODO(https://go.dev/issue/57221): what about entry functions that are generics?
 	prog := ssa.NewProgram(fset, ssa.InstantiateGenerics)
 
 	imports := make(map[*packages.Package]*ssa.Package)
@@ -69,12 +70,8 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 		return nil, err
 	}
 	initial := cha.CallGraph(prog)
-	allFuncs := ssautil.AllFunctions(prog)
 
 	fslice := forwardSlice(entrySlice, initial)
-	// Keep only actually linked functions.
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -83,8 +80,6 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 	// Repeat the process once more, this time using
 	// the produced VTA call graph as the base graph.
 	fslice = forwardSlice(entrySlice, vtaCg)
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -110,15 +105,17 @@ func dbTypeFormat(t types.Type) string {
 
 // dbFuncName computes a function name consistent with the namings used in vulnerability
 // databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
+// If a receiver is a pointer, this information is not encoded in the resulting name. If
+// a function has type argument/parameter, this information is omitted. The name of
+// anonymous functions is simply "". The function names are unique subject to the enclosing
+// package, but not globally.
 //
 // Examples:
 //
 //	func (a A) foo (...) {...}  -> A.foo
 //	func foo(...) {...}         -> foo
 //	func (b *B) bar (...) {...} -> B.bar
+//	func (c C[T]) do(...) {...} -> C.do
 func dbFuncName(f *ssa.Function) string {
 	selectBound := func(f *ssa.Function) types.Type {
 		// If f is a "bound" function introduced by ssa for a given type, return the type.
@@ -151,18 +148,17 @@ func dbFuncName(f *ssa.Function) string {
 	}
 
 	if qprefix == "" {
-		return f.Name()
+		return funcName(f)
 	}
-	return qprefix + "." + f.Name()
+	return qprefix + "." + funcName(f)
 }
 
-// dbTypesFuncName is dbFuncName defined over *types.Func.
-func dbTypesFuncName(f *types.Func) string {
-	sig := f.Type().(*types.Signature)
-	if sig.Recv() == nil {
-		return f.Name()
-	}
-	return dbTypeFormat(sig.Recv().Type()) + "." + f.Name()
+// funcName returns the name of the ssa function f.
+// It is f.Name() without additional type argument
+// information in case of generics.
+func funcName(f *ssa.Function) string {
+	n, _, _ := strings.Cut(f.Name(), "[")
+	return n
 }
 
 // memberFuncs returns functions associated with the `member`:
@@ -227,35 +223,124 @@ func funcRecvType(f *ssa.Function) string {
 	return buf.String()
 }
 
-// allSymbols returns all top-level functions and methods defined in pkg.
-func allSymbols(pkg *types.Package) []string {
-	var names []string
-	scope := pkg.Scope()
-	for _, name := range scope.Names() {
-		o := scope.Lookup(name)
-		switch o := o.(type) {
-		case *types.Func:
-			names = append(names, dbTypesFuncName(o))
-		case *types.TypeName:
-			ms := types.NewMethodSet(types.NewPointer(o.Type()))
-			for i := 0; i < ms.Len(); i++ {
-				if f, ok := ms.At(i).Obj().(*types.Func); ok {
-					names = append(names, dbTypesFuncName(f))
+func FixedVersion(modulePath, version string, affected []osv.Affected) string {
+	fixed := earliestValidFix(modulePath, version, affected)
+	// Add "v" prefix if one does not exist. moduleVersionString
+	// will later on replace it with "go" if needed.
+	if fixed != "" && !strings.HasPrefix(fixed, "v") {
+		fixed = "v" + fixed
+	}
+	return fixed
+}
+
+// earliestValidFix returns the earliest fix for version of modulePath that
+// itself is not vulnerable in affected.
+//
+// Suppose we have a version "v1.0.0" and we use {...} to denote different
+// affected regions. Assume for simplicity that all affected apply to the
+// same input modulePath.
+//
+//	{[v0.1.0, v0.1.9), [v1.0.0, v2.0.0)} -> v2.0.0
+//	{[v1.0.0, v1.5.0), [v2.0.0, v2.1.0}, {[v1.4.0, v1.6.0)} -> v2.1.0
+func earliestValidFix(modulePath, version string, affected []osv.Affected) string {
+	var moduleAffected []osv.Affected
+	for _, a := range affected {
+		if a.Module.Path == modulePath {
+			moduleAffected = append(moduleAffected, a)
+		}
+	}
+
+	vFixes := validFixes(version, moduleAffected)
+	for _, fix := range vFixes {
+		if !fixNegated(fix, moduleAffected) {
+			return fix
+		}
+	}
+	return ""
+
+}
+
+// validFixes computes all fixes for version in affected and
+// returns them sorted increasingly. Assumes that all affected
+// apply to the same module.
+func validFixes(version string, affected []osv.Affected) []string {
+	var fixes []string
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if r.Type != osv.RangeTypeSemver {
+				continue
+			}
+			for _, e := range r.Events {
+				fix := e.Fixed
+				if fix != "" && semver.Less(version, fix) {
+					fixes = append(fixes, fix)
 				}
 			}
 		}
 	}
-	return names
+	sort.SliceStable(fixes, func(i, j int) bool { return semver.Less(fixes[i], fixes[j]) })
+	return fixes
 }
 
-// vulnMatchesPackage reports whether an entry applies to pkg (an import path).
-func vulnMatchesPackage(v *osv.Entry, pkg string) bool {
-	for _, a := range v.Affected {
-		for _, p := range a.EcosystemSpecific.Packages {
-			if p.Path == pkg {
+// fixNegated checks if fix is negated to by a re-introduction
+// of a vulnerability in affected. Assumes that all affected apply
+// to the same module.
+func fixNegated(fix string, affected []osv.Affected) bool {
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if semver.ContainsSemver(r, fix) {
 				return true
 			}
 		}
 	}
 	return false
 }
+
+func modPath(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Path
+	}
+	return mod.Path
+}
+
+func modVersion(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Version
+	}
+	return mod.Version
+}
+
+// pkgPath returns the path of the f's enclosing package, if any.
+// Otherwise, returns internal.UnknownPackagePath.
+func pkgPath(f *ssa.Function) string {
+	g := f
+	if f.Origin() != nil {
+		// Instantiations of generics do not have
+		// an associated package. We hence look up
+		// the original function for the package.
+		g = f.Origin()
+	}
+	if g.Package() != nil && g.Package().Pkg != nil {
+		return g.Package().Pkg.Path()
+	}
+	return internal.UnknownPackagePath
+}
+
+func pkgModPath(pkg *packages.Package) string {
+	if pkg != nil && pkg.Module != nil {
+		return pkg.Module.Path
+	}
+	return internal.UnknownModulePath
+}
+
+func IsStdPackage(pkg string) bool {
+	if pkg == "" || pkg == internal.UnknownPackagePath {
+		return false
+	}
+	// std packages do not have a "." in their path. For instance, see
+	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
+	if i := strings.IndexByte(pkg, '/'); i != -1 {
+		pkg = pkg[:i]
+	}
+	return !strings.Contains(pkg, ".")
+}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
index 7786695c..198fffe0 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
@@ -16,31 +16,31 @@ import (
 	"golang.org/x/vuln/internal/semver"
 )
 
-// Result contains information on how known vulnerabilities are reachable
-// in the call graph, package imports graph, and module requires graph of
-// the user code.
+const (
+	fetchingVulnsMessage    = "Fetching vulnerabilities from the database..."
+	checkingSrcVulnsMessage = "Checking the code against the vulnerabilities..."
+	checkingBinVulnsMessage = "Checking the binary against the vulnerabilities..."
+)
+
+// Result contains information on detected vulnerabilities.
+// For call graph analysis, it provides information on reachability
+// of vulnerable symbols through entry points of the program.
 type Result struct {
 	// EntryFunctions are a subset of Functions representing vulncheck entry points.
 	EntryFunctions []*FuncNode
 
-	// EntryPackages are a subset of Packages representing packages of vulncheck entry points.
-	EntryPackages []*packages.Package
-
-	// Vulns contains information on detected vulnerabilities and their place in
-	// the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
-	// or whose packages are imported in Imports, or whose modules are required in
-	// Requires, have an entry in Vulns.
+	// Vulns contains information on detected vulnerabilities.
 	Vulns []*Vuln
 }
 
-// Vuln provides information on how a vulnerability is affecting user code by
-// connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities
-// detected in Go binaries do not appear in the Result graphs.
+// Vuln provides information on a detected vulnerability. For call
+// graph mode, Vuln will also contain the information on how the
+// vulnerability is reachable in the user call graph.
 type Vuln struct {
 	// OSV contains information on the detected vulnerability in the shared
 	// vulnerability format.
 	//
-	// OSV, Symbol, PkgPath, and ModPath identify a vulnerability.
+	// OSV, Symbol, and Package identify a vulnerability.
 	//
 	// Note that *osv.Entry may describe multiple symbols from multiple
 	// packages.
@@ -49,17 +49,17 @@ type Vuln struct {
 	// Symbol is the name of the detected vulnerable function or method.
 	Symbol string
 
-	// CallSink is the FuncNode in Result.Calls corresponding to Symbol.
+	// CallSink is the FuncNode corresponding to Symbol.
 	//
 	// When analyzing binaries, Symbol is not reachable, or cfg.ScanLevel
-	// is symbol, CallSink will be unavailable and set to 0.
+	// is symbol, CallSink will be unavailable and set to nil.
 	CallSink *FuncNode
 
-	// ImportSink is the PkgNode in Result.Imports corresponding to PkgPath.
+	// Package of Symbol.
 	//
-	// When analyzing binaries or PkgPath is not imported, ImportSink will be
-	// unavailable and set to 0.
-	ImportSink *packages.Package
+	// When the package of symbol is not imported, Package will be
+	// unavailable and set to nil.
+	Package *packages.Package
 }
 
 // A FuncNode describes a function in the call graph.
@@ -111,10 +111,10 @@ type CallSite struct {
 	Resolved bool
 }
 
-// moduleVulnerabilities is an internal structure for
-// holding and querying vulnerabilities provided by a
-// vulnerability database client.
-type moduleVulnerabilities []*ModVulns
+// affectingVulns is an internal structure for querying
+// vulnerabilities that apply to the current program
+// and platform under consideration.
+type affectingVulns []*ModVulns
 
 // ModVulns groups vulnerabilities per module.
 type ModVulns struct {
@@ -122,10 +122,10 @@ type ModVulns struct {
 	Vulns  []*osv.Entry
 }
 
-func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
+func affectingVulnerabilities(vulns []*ModVulns, os, arch string) affectingVulns {
 	now := time.Now()
-	var filteredMod moduleVulnerabilities
-	for _, mod := range mv {
+	var filtered affectingVulns
+	for _, mod := range vulns {
 		module := mod.Module
 		modVersion := module.Version
 		if module.Replace != nil {
@@ -150,24 +150,20 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 				if a.Module.Path != module.Path {
 					continue
 				}
-
-				// A module version is affected if
-				//  - it is included in one of the affected version ranges
-				//  - and module version is not ""
-				if modVersion == "" {
-					// Module version of "" means the module version is not available,
-					// and so we don't want to spam users with potential false alarms.
-					continue
-				}
-				if !semver.Affects(a.Ranges, modVersion) {
+				if !affected(modVersion, a) {
 					continue
 				}
+
 				var filteredImports []osv.Package
 				for _, p := range a.EcosystemSpecific.Packages {
 					if matchesPlatform(os, arch, p) {
 						filteredImports = append(filteredImports, p)
 					}
 				}
+				// If we pruned all existing Packages, then the affected is
+				// empty and we can filter it out. Note that Packages can
+				// be empty for vulnerabilities that have no package or
+				// symbol information available.
 				if len(a.EcosystemSpecific.Packages) != 0 && len(filteredImports) == 0 {
 					continue
 				}
@@ -183,12 +179,28 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 			newV.Affected = filteredAffected
 			filteredVulns = append(filteredVulns, &newV)
 		}
-		filteredMod = append(filteredMod, &ModVulns{
+
+		filtered = append(filtered, &ModVulns{
 			Module: module,
 			Vulns:  filteredVulns,
 		})
 	}
-	return filteredMod
+	return filtered
+}
+
+// affected checks if modVersion is affected by a:
+//   - it is included in one of the affected version ranges
+//   - and module version is not "" and "(devel)"
+func affected(modVersion string, a osv.Affected) bool {
+	const devel = "(devel)"
+	if modVersion == "" || modVersion == devel {
+		// Module version of "" means the module version is not available
+		// and devel means it is in development stage. Either way, we don't
+		// know the exact version so we don't want to spam users with
+		// potential false alarms.
+		return false
+	}
+	return semver.Affects(a.Ranges, modVersion)
 }
 
 func matchesPlatform(os, arch string, e osv.Package) bool {
@@ -211,37 +223,66 @@ func matchesPlatformComponent(s string, ps []string) bool {
 	return false
 }
 
-// vulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv moduleVulnerabilities) vulnsForPackage(importPath string) []*osv.Entry {
-	isStd := isStdPackage(importPath)
-	var mostSpecificMod *ModVulns
-	for _, mod := range mv {
+// moduleVulns return vulnerabilities for module. If module is unknown,
+// it figures the module from package importPath. It returns the module
+// whose path is the longest prefix of importPath.
+func (aff affectingVulns) moduleVulns(module, importPath string) *ModVulns {
+	moduleKnown := module != "" && module != internal.UnknownModulePath
+
+	isStd := IsStdPackage(importPath)
+	var mostSpecificMod *ModVulns // for the case where !moduleKnown
+	for _, mod := range aff {
 		md := mod
 		if isStd && mod.Module.Path == internal.GoStdModulePath {
-			// standard library packages do not have an associated module,
+			// Standard library packages do not have an associated module,
 			// so we relate them to the artificial stdlib module.
-			mostSpecificMod = md
+			return md
+		}
+
+		if moduleKnown {
+			if mod.Module.Path == module {
+				// If we know exactly which module we need,
+				// return its vulnerabilities.
+				return md
+			}
 		} else if strings.HasPrefix(importPath, md.Module.Path) {
+			// If module is unknown, we try to figure it out from importPath.
+			// We take the module whose path has the longest match to importPath.
+			// TODO: do matching based on path components.
 			if mostSpecificMod == nil || len(mostSpecificMod.Module.Path) < len(md.Module.Path) {
 				mostSpecificMod = md
 			}
 		}
 	}
-	if mostSpecificMod == nil {
+	return mostSpecificMod
+}
+
+// ForPackage returns the vulnerabilities for the importPath belonging to
+// module.
+//
+// If module is unknown, ForPackage will resolve it as the most specific
+// prefix of importPath.
+func (aff affectingVulns) ForPackage(module, importPath string) []*osv.Entry {
+	mod := aff.moduleVulns(module, importPath)
+	if mod == nil {
 		return nil
 	}
 
-	if mostSpecificMod.Module.Replace != nil {
+	if mod.Module.Replace != nil {
 		// standard libraries do not have a module nor replace module
-		importPath = fmt.Sprintf("%s%s", mostSpecificMod.Module.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.Module.Path))
+		importPath = fmt.Sprintf("%s%s", mod.Module.Replace.Path, strings.TrimPrefix(importPath, mod.Module.Path))
 	}
-	vulns := mostSpecificMod.Vulns
+	vulns := mod.Vulns
 	packageVulns := []*osv.Entry{}
 Vuln:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all packages are vulnerable
+				packageVulns = append(packageVulns, v)
+				continue Vuln
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path == importPath {
 					packageVulns = append(packageVulns, v)
@@ -253,9 +294,9 @@ Vuln:
 	return packageVulns
 }
 
-// vulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv.Entry {
-	vulns := mv.vulnsForPackage(importPath)
+// ForSymbol returns vulnerabilities for symbol in aff.ForPackage(module, importPath).
+func (aff affectingVulns) ForSymbol(module, importPath, symbol string) []*osv.Entry {
+	vulns := aff.ForPackage(module, importPath)
 	if vulns == nil {
 		return nil
 	}
@@ -264,6 +305,12 @@ func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv
 vulnLoop:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all symbols of all packages are vulnerable
+				symbolVulns = append(symbolVulns, v)
+				continue vulnLoop
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path != importPath {
 					continue
@@ -287,15 +334,3 @@ func contains(symbols []string, target string) bool {
 	}
 	return false
 }
-
-func isStdPackage(pkg string) bool {
-	if pkg == "" {
-		return false
-	}
-	// std packages do not have a "." in their path. For instance, see
-	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
-	if i := strings.IndexByte(pkg, '/'); i != -1 {
-		pkg = pkg[:i]
-	}
-	return !strings.Contains(pkg, ".")
-}
diff --git a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/witness.go b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
index 7de37587..7bc18581 100644
--- a/notifier/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
+++ b/notifier/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
@@ -13,6 +13,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"unicode"
 
 	"golang.org/x/tools/go/packages"
 )
@@ -32,18 +33,18 @@ type StackEntry struct {
 	Call *CallSite
 }
 
-// CallStacks returns representative call stacks for each
+// sourceCallstacks returns representative call stacks for each
 // vulnerability in res. The returned call stacks are heuristically
 // ordered by how seemingly easy is to understand them: shorter
 // call stacks with less dynamic call sites appear earlier in the
 // returned slices.
 //
-// CallStacks performs a breadth-first search of res.CallGraph starting
-// at the vulnerable symbol and going up until reaching an entry
+// sourceCallstacks performs a breadth-first search of res.CallGraph
+// starting at the vulnerable symbol and going up until reaching an entry
 // function or method in res.CallGraph.Entries. During this search,
 // each function is visited at most once to avoid potential
 // exponential explosion. Hence, not all call stacks are analyzed.
-func CallStacks(res *Result) map[*Vuln]CallStack {
+func sourceCallstacks(res *Result) map[*Vuln]CallStack {
 	var (
 		wg sync.WaitGroup
 		mu sync.Mutex
@@ -53,7 +54,7 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 		vuln := vuln
 		wg.Add(1)
 		go func() {
-			cs := callStack(vuln, res)
+			cs := sourceCallstack(vuln, res)
 			mu.Lock()
 			stackPerVuln[vuln] = cs
 			mu.Unlock()
@@ -66,10 +67,10 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 	return stackPerVuln
 }
 
-// callStack finds a representative call stack for vuln.
+// sourceCallstack finds a representative call stack for vuln.
 // This is a shortest unique call stack with the least
 // number of dynamic call sites.
-func callStack(vuln *Vuln, res *Result) CallStack {
+func sourceCallstack(vuln *Vuln, res *Result) CallStack {
 	vulnSink := vuln.CallSink
 	if vulnSink == nil {
 		return nil
@@ -100,7 +101,7 @@ func callStack(vuln *Vuln, res *Result) CallStack {
 	skipSymbols := make(map[*FuncNode]bool)
 	for _, v := range res.Vulns {
 		if v.CallSink != nil && v != vuln &&
-			v.OSV == vuln.OSV && v.ImportSink == vuln.ImportSink {
+			v.OSV == vuln.OSV && v.Package == vuln.Package {
 			skipSymbols[v.CallSink] = true
 		}
 	}
@@ -390,3 +391,59 @@ func isInit(f *FuncNode) bool {
 	// positive integer. Implicit inits are named simply "init".
 	return f.Name == "init" || strings.HasPrefix(f.Name, "init#")
 }
+
+// binaryCallstacks computes representative call stacks for binary results.
+func binaryCallstacks(vr *Result) map[*Vuln]CallStack {
+	callstacks := map[*Vuln]CallStack{}
+	for _, vv := range uniqueVulns(vr.Vulns) {
+		f := &FuncNode{Package: vv.Package, Name: vv.Symbol}
+		parts := strings.Split(vv.Symbol, ".")
+		if len(parts) != 1 {
+			f.RecvType = parts[0]
+			f.Name = parts[1]
+		}
+		callstacks[vv] = CallStack{StackEntry{Function: f}}
+	}
+	return callstacks
+}
+
+// uniqueVulns does for binary mode what sourceCallstacks does for source mode.
+// It tries not to report redundant symbols. Since there are no call stacks in
+// binary mode, the following approximate approach is used. Do not report unexported
+// symbols for a  triple if there are some exported symbols.
+// Otherwise, report all unexported symbols to avoid not reporting anything.
+func uniqueVulns(vulns []*Vuln) []*Vuln {
+	type key struct {
+		id  string
+		pkg string
+		mod string
+	}
+	hasExported := make(map[key]bool)
+	for _, v := range vulns {
+		if isExported(v.Symbol) {
+			k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+			hasExported[k] = true
+		}
+	}
+
+	var uniques []*Vuln
+	for _, v := range vulns {
+		k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+		if isExported(v.Symbol) || !hasExported[k] {
+			uniques = append(uniques, v)
+		}
+	}
+	return uniques
+}
+
+// isExported checks if the symbol is exported. Assumes that the
+// symbol is of the form "identifier", "identifier1.identifier2",
+// or "identifier.".
+func isExported(symbol string) bool {
+	parts := strings.Split(symbol, ".")
+	last := parts[len(parts)-1]
+	if last == "" { // case for "identifier."
+		return false
+	}
+	return unicode.IsUpper(rune(last[0]))
+}
diff --git a/notifier/vendor/golang.org/x/vuln/scan/scan.go b/notifier/vendor/golang.org/x/vuln/scan/scan.go
index 83ed75a9..0aa9975e 100644
--- a/notifier/vendor/golang.org/x/vuln/scan/scan.go
+++ b/notifier/vendor/golang.org/x/vuln/scan/scan.go
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+/*
+Package scan provides functionality for running govulncheck.
+
+See [cmd/govulncheck/main.go] as a usage example.
+
+[cmd/govulncheck/main.go]: https://go.googlesource.com/vuln/+/master/cmd/govulncheck/main.go
+*/
 package scan
 
 import (
diff --git a/notifier/vendor/google.golang.org/grpc/MAINTAINERS.md b/notifier/vendor/google.golang.org/grpc/MAINTAINERS.md
index 5d4096d4..df35bb9a 100644
--- a/notifier/vendor/google.golang.org/grpc/MAINTAINERS.md
+++ b/notifier/vendor/google.golang.org/grpc/MAINTAINERS.md
@@ -9,21 +9,19 @@ for general contribution guidelines.
 
 ## Maintainers (in alphabetical order)
 
-- [aranjans](https://github.com/aranjans), Google LLC
 - [arjan-bal](https://github.com/arjan-bal), Google LLC
 - [arvindbr8](https://github.com/arvindbr8), Google LLC
 - [atollena](https://github.com/atollena), Datadog, Inc.
 - [dfawley](https://github.com/dfawley), Google LLC
 - [easwars](https://github.com/easwars), Google LLC
-- [erm-g](https://github.com/erm-g), Google LLC
 - [gtcooke94](https://github.com/gtcooke94), Google LLC
-- [purnesh42h](https://github.com/purnesh42h), Google LLC
-- [zasweq](https://github.com/zasweq), Google LLC
 
 ## Emeritus Maintainers (in alphabetical order)
 - [adelez](https://github.com/adelez)
+- [aranjans](https://github.com/aranjans)
 - [canguler](https://github.com/canguler)
 - [cesarghali](https://github.com/cesarghali)
+- [erm-g](https://github.com/erm-g)
 - [iamqizhao](https://github.com/iamqizhao)
 - [jeanbza](https://github.com/jeanbza)
 - [jtattermusch](https://github.com/jtattermusch)
@@ -32,5 +30,7 @@ for general contribution guidelines.
 - [matt-kwong](https://github.com/matt-kwong)
 - [menghanl](https://github.com/menghanl)
 - [nicolasnoble](https://github.com/nicolasnoble)
+- [purnesh42h](https://github.com/purnesh42h)
 - [srini100](https://github.com/srini100)
 - [yongni](https://github.com/yongni)
+- [zasweq](https://github.com/zasweq)
diff --git a/notifier/vendor/google.golang.org/grpc/balancer/balancer.go b/notifier/vendor/google.golang.org/grpc/balancer/balancer.go
index c9b343c7..b1264017 100644
--- a/notifier/vendor/google.golang.org/grpc/balancer/balancer.go
+++ b/notifier/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -360,6 +360,10 @@ type Balancer interface {
 	// call SubConn.Shutdown for its existing SubConns; however, this will be
 	// required in a future release, so it is recommended.
 	Close()
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // ExitIdler is an optional interface for balancers to implement.  If
@@ -367,8 +371,8 @@ type Balancer interface {
 // the ClientConn is idle.  If unimplemented, ClientConn.Connect will cause
 // all SubConns to connect.
 //
-// Notice: it will be required for all balancers to implement this in a future
-// release.
+// Deprecated: All balancers must implement this interface. This interface will
+// be removed in a future release.
 type ExitIdler interface {
 	// ExitIdle instructs the LB policy to reconnect to backends / exit the
 	// IDLE state, if appropriate and possible.  Note that SubConns that enter
diff --git a/notifier/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/notifier/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
index cc606f4d..360db08e 100644
--- a/notifier/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
+++ b/notifier/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
@@ -37,6 +37,8 @@ import (
 	"google.golang.org/grpc/resolver"
 )
 
+var randIntN = rand.IntN
+
 // ChildState is the balancer state of a child along with the endpoint which
 // identifies the child balancer.
 type ChildState struct {
@@ -45,7 +47,15 @@ type ChildState struct {
 
 	// Balancer exposes only the ExitIdler interface of the child LB policy.
 	// Other methods of the child policy are called only by endpointsharding.
-	Balancer balancer.ExitIdler
+	Balancer ExitIdler
+}
+
+// ExitIdler provides access to only the ExitIdle method of the child balancer.
+type ExitIdler interface {
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // Options are the options to configure the behaviour of the
@@ -104,6 +114,21 @@ type endpointSharding struct {
 	mu sync.Mutex
 }
 
+// rotateEndpoints returns a slice of all the input endpoints rotated a random
+// amount.
+func rotateEndpoints(es []resolver.Endpoint) []resolver.Endpoint {
+	les := len(es)
+	if les == 0 {
+		return es
+	}
+	r := randIntN(les)
+	// Make a copy to avoid mutating data beyond the end of es.
+	ret := make([]resolver.Endpoint, les)
+	copy(ret, es[r:])
+	copy(ret[les-r:], es[:r])
+	return ret
+}
+
 // UpdateClientConnState creates a child for new endpoints and deletes children
 // for endpoints that are no longer present. It also updates all the children,
 // and sends a single synchronous update of the childrens' aggregated state at
@@ -125,7 +150,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
 	newChildren := resolver.NewEndpointMap[*balancerWrapper]()
 
 	// Update/Create new children.
-	for _, endpoint := range state.ResolverState.Endpoints {
+	for _, endpoint := range rotateEndpoints(state.ResolverState.Endpoints) {
 		if _, ok := newChildren.Get(endpoint); ok {
 			// Endpoint child was already created, continue to avoid duplicate
 			// update.
@@ -205,6 +230,16 @@ func (es *endpointSharding) Close() {
 	}
 }
 
+func (es *endpointSharding) ExitIdle() {
+	es.childMu.Lock()
+	defer es.childMu.Unlock()
+	for _, bw := range es.children.Load().Values() {
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+	}
+}
+
 // updateState updates this component's state. It sends the aggregated state,
 // and a picker with round robin behavior with all the child states present if
 // needed.
@@ -261,7 +296,7 @@ func (es *endpointSharding) updateState() {
 	p := &pickerWithChildStates{
 		pickers:     pickers,
 		childStates: childStates,
-		next:        uint32(rand.IntN(len(pickers))),
+		next:        uint32(randIntN(len(pickers))),
 	}
 	es.cc.UpdateState(balancer.State{
 		ConnectivityState: aggState,
@@ -326,15 +361,13 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) {
 // ExitIdle pings an IDLE child balancer to exit idle in a new goroutine to
 // avoid deadlocks due to synchronous balancer state updates.
 func (bw *balancerWrapper) ExitIdle() {
-	if ei, ok := bw.child.(balancer.ExitIdler); ok {
-		go func() {
-			bw.es.childMu.Lock()
-			if !bw.isClosed {
-				ei.ExitIdle()
-			}
-			bw.es.childMu.Unlock()
-		}()
-	}
+	go func() {
+		bw.es.childMu.Lock()
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+		bw.es.childMu.Unlock()
+	}()
 }
 
 // updateClientConnStateLocked delivers the ClientConnState to the child
diff --git a/notifier/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/notifier/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
index 494314f2..67f315a0 100644
--- a/notifier/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
+++ b/notifier/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
@@ -54,18 +54,9 @@ func init() {
 	balancer.Register(pickfirstBuilder{})
 }
 
-type (
-	// enableHealthListenerKeyType is a unique key type used in resolver
-	// attributes to indicate whether the health listener usage is enabled.
-	enableHealthListenerKeyType struct{}
-	// managedByPickfirstKeyType is an attribute key type to inform Outlier
-	// Detection that the generic health listener is being used.
-	// TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when
-	// implementing the dualstack design. This is a hack. Once Dualstack is
-	// completed, outlier detection will stop sending ejection updates through
-	// the connectivity listener.
-	managedByPickfirstKeyType struct{}
-)
+// enableHealthListenerKeyType is a unique key type used in resolver
+// attributes to indicate whether the health listener usage is enabled.
+type enableHealthListenerKeyType struct{}
 
 var (
 	logger = grpclog.Component("pick-first-leaf-lb")
@@ -76,21 +67,21 @@ var (
 	disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.disconnections",
 		Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
-		Unit:        "disconnection",
+		Unit:        "{disconnection}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_succeeded",
 		Description: "EXPERIMENTAL. Number of successful connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_failed",
 		Description: "EXPERIMENTAL. Number of failed connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
@@ -149,17 +140,6 @@ func EnableHealthListener(state resolver.State) resolver.State {
 	return state
 }
 
-// IsManagedByPickfirst returns whether an address belongs to a SubConn
-// managed by the pickfirst LB policy.
-// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable
-// outlier_detection via the with connectivity listener when using pick_first.
-// Once Dualstack changes are complete, all SubConns will be created by
-// pick_first and outlier detection will only use the health listener for
-// ejection. This hack can then be removed.
-func IsManagedByPickfirst(addr resolver.Address) bool {
-	return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil
-}
-
 type pfConfig struct {
 	serviceconfig.LoadBalancingConfig `json:"-"`
 
@@ -186,7 +166,6 @@ type scData struct {
 }
 
 func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) {
-	addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true)
 	sd := &scData{
 		rawConnectivityState: connectivity.Idle,
 		effectiveState:       connectivity.Idle,
diff --git a/notifier/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/notifier/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
index 35da5d1e..22045bf3 100644
--- a/notifier/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
+++ b/notifier/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -70,10 +70,3 @@ func (b *rrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
 		ResolverState: pickfirstleaf.EnableHealthListener(ccs.ResolverState),
 	})
 }
-
-func (b *rrBalancer) ExitIdle() {
-	// Should always be ok, as child is endpoint sharding.
-	if ei, ok := b.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-	}
-}
diff --git a/notifier/vendor/google.golang.org/grpc/clientconn.go b/notifier/vendor/google.golang.org/grpc/clientconn.go
index cd3eaf8d..3f762285 100644
--- a/notifier/vendor/google.golang.org/grpc/clientconn.go
+++ b/notifier/vendor/google.golang.org/grpc/clientconn.go
@@ -208,7 +208,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error)
 	channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority)
 
 	cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz)
-	cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers)
+	cc.pickerWrapper = newPickerWrapper()
 
 	cc.metricsRecorderList = stats.NewMetricsRecorderList(cc.dopts.copts.StatsHandlers)
 
@@ -1076,13 +1076,6 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
 	return cc.sc.healthCheckConfig
 }
 
-func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
-	return cc.pickerWrapper.pick(ctx, failfast, balancer.PickInfo{
-		Ctx:            ctx,
-		FullMethodName: method,
-	})
-}
-
 func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSelector iresolver.ConfigSelector) {
 	if sc == nil {
 		// should never reach here.
@@ -1831,7 +1824,7 @@ func (cc *ClientConn) initAuthority() error {
 	} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
 		cc.authority = auth.OverrideAuthority(cc.parsedTarget)
 	} else if strings.HasPrefix(endpoint, ":") {
-		cc.authority = "localhost" + endpoint
+		cc.authority = "localhost" + encodeAuthority(endpoint)
 	} else {
 		cc.authority = encodeAuthority(endpoint)
 	}
diff --git a/notifier/vendor/google.golang.org/grpc/credentials/credentials.go b/notifier/vendor/google.golang.org/grpc/credentials/credentials.go
index a63ab606..c8e337cd 100644
--- a/notifier/vendor/google.golang.org/grpc/credentials/credentials.go
+++ b/notifier/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -96,10 +96,11 @@ func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
 	return c
 }
 
-// ProtocolInfo provides information regarding the gRPC wire protocol version,
-// security protocol, security protocol version in use, server name, etc.
+// ProtocolInfo provides static information regarding transport credentials.
 type ProtocolInfo struct {
 	// ProtocolVersion is the gRPC wire protocol version.
+	//
+	// Deprecated: this is unused by gRPC.
 	ProtocolVersion string
 	// SecurityProtocol is the security protocol in use.
 	SecurityProtocol string
@@ -109,7 +110,16 @@ type ProtocolInfo struct {
 	//
 	// Deprecated: please use Peer.AuthInfo.
 	SecurityVersion string
-	// ServerName is the user-configured server name.
+	// ServerName is the user-configured server name.  If set, this overrides
+	// the default :authority header used for all RPCs on the channel using the
+	// containing credentials, unless grpc.WithAuthority is set on the channel,
+	// in which case that setting will take precedence.
+	//
+	// This must be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: Users should use grpc.WithAuthority to override the authority
+	// on a channel instead of configuring the credentials.
 	ServerName string
 }
 
@@ -173,12 +183,17 @@ type TransportCredentials interface {
 	// Clone makes a copy of this TransportCredentials.
 	Clone() TransportCredentials
 	// OverrideServerName specifies the value used for the following:
+	//
 	// - verifying the hostname on the returned certificates
 	// - as SNI in the client's handshake to support virtual hosting
 	// - as the value for `:authority` header at stream creation time
 	//
-	// Deprecated: use grpc.WithAuthority instead. Will be supported
-	// throughout 1.x.
+	// The provided string should be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: this method is unused by gRPC.  Users should use
+	// grpc.WithAuthority to override the authority on a channel instead of
+	// configuring the credentials.
 	OverrideServerName(string) error
 }
 
diff --git a/notifier/vendor/google.golang.org/grpc/credentials/tls.go b/notifier/vendor/google.golang.org/grpc/credentials/tls.go
index 20f65f7b..8277be7d 100644
--- a/notifier/vendor/google.golang.org/grpc/credentials/tls.go
+++ b/notifier/vendor/google.golang.org/grpc/credentials/tls.go
@@ -110,14 +110,14 @@ func (c tlsCreds) Info() ProtocolInfo {
 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
 	// use local cfg to avoid clobbering ServerName if using multiple endpoints
 	cfg := credinternal.CloneTLSConfig(c.config)
-	if cfg.ServerName == "" {
-		serverName, _, err := net.SplitHostPort(authority)
-		if err != nil {
-			// If the authority had no host port or if the authority cannot be parsed, use it as-is.
-			serverName = authority
-		}
-		cfg.ServerName = serverName
+
+	serverName, _, err := net.SplitHostPort(authority)
+	if err != nil {
+		// If the authority had no host port or if the authority cannot be parsed, use it as-is.
+		serverName = authority
 	}
+	cfg.ServerName = serverName
+
 	conn := tls.Client(rawConn, cfg)
 	errChannel := make(chan error, 1)
 	go func() {
@@ -259,9 +259,11 @@ func applyDefaults(c *tls.Config) *tls.Config {
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
 }
@@ -271,9 +273,11 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
 	b, err := os.ReadFile(certFile)
 	if err != nil {
diff --git a/notifier/vendor/google.golang.org/grpc/dialoptions.go b/notifier/vendor/google.golang.org/grpc/dialoptions.go
index 050ba0f1..7a5ac2e7 100644
--- a/notifier/vendor/google.golang.org/grpc/dialoptions.go
+++ b/notifier/vendor/google.golang.org/grpc/dialoptions.go
@@ -213,6 +213,7 @@ func WithReadBufferSize(s int) DialOption {
 func WithInitialWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -222,6 +223,26 @@ func WithInitialWindowSize(s int32) DialOption {
 func WithInitialConnWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticStreamWindowSize returns a DialOption which sets the initial
+// stream window size to the value provided and disables dynamic flow control.
+func WithStaticStreamWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticConnWindowSize returns a DialOption which sets the initial
+// connection window size to the value provided and disables dynamic flow
+// control.
+func WithStaticConnWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -587,6 +608,8 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
 
 // WithAuthority returns a DialOption that specifies the value to be used as the
 // :authority pseudo-header and as the server name in authentication handshake.
+// This overrides all other ways of setting authority on the channel, but can be
+// overridden per-call by using grpc.CallAuthority.
 func WithAuthority(a string) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.authority = a
diff --git a/notifier/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go b/notifier/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
index 93136610..f2c01f29 100644
--- a/notifier/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
+++ b/notifier/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
@@ -188,13 +188,13 @@ type HealthServer interface {
 type UnimplementedHealthServer struct{}
 
 func (UnimplementedHealthServer) Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
+	return nil, status.Error(codes.Unimplemented, "method Check not implemented")
 }
 func (UnimplementedHealthServer) List(context.Context, *HealthListRequest) (*HealthListResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+	return nil, status.Error(codes.Unimplemented, "method List not implemented")
 }
 func (UnimplementedHealthServer) Watch(*HealthCheckRequest, grpc.ServerStreamingServer[HealthCheckResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method Watch not implemented")
+	return status.Error(codes.Unimplemented, "method Watch not implemented")
 }
 func (UnimplementedHealthServer) testEmbeddedByValue() {}
 
diff --git a/notifier/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/notifier/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
index fbc1ca35..ba25b898 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
@@ -223,15 +223,7 @@ func (gsb *Balancer) ExitIdle() {
 	// There is no need to protect this read with a mutex, as the write to the
 	// Balancer field happens in SwitchTo, which completes before this can be
 	// called.
-	if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-		return
-	}
-	gsb.mu.Lock()
-	defer gsb.mu.Unlock()
-	for sc := range balToUpdate.subconns {
-		sc.Connect()
-	}
+	balToUpdate.ExitIdle()
 }
 
 // updateSubConnState forwards the update to the appropriate child.
diff --git a/notifier/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/notifier/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
index f5f2bdeb..7e060f5e 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -26,30 +26,32 @@ import (
 )
 
 var (
-	// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
+	// EnableTXTServiceConfig is set if the DNS resolver should perform TXT
+	// lookups for service config ("GRPC_ENABLE_TXT_SERVICE_CONFIG" is not
+	// "false").
+	EnableTXTServiceConfig = boolFromEnv("GRPC_ENABLE_TXT_SERVICE_CONFIG", true)
+
+	// TXTErrIgnore is set if TXT errors should be ignored
+	// ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
 	TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
+
 	// RingHashCap indicates the maximum ring size which defaults to 4096
 	// entries but may be overridden by setting the environment variable
 	// "GRPC_RING_HASH_CAP".  This does not override the default bounds
 	// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
 	RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
-	// LeastRequestLB is set if we should support the least_request_experimental
-	// LB policy, which can be enabled by setting the environment variable
-	// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
-	LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", true)
+
 	// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
 	// handshakes that can be performed.
 	ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
+
 	// EnforceALPNEnabled is set if TLS connections to servers with ALPN disabled
 	// should be rejected. The HTTP/2 protocol requires ALPN to be enabled, this
 	// option is present for backward compatibility. This option may be overridden
 	// by setting the environment variable "GRPC_ENFORCE_ALPN_ENABLED" to "true"
 	// or "false".
 	EnforceALPNEnabled = boolFromEnv("GRPC_ENFORCE_ALPN_ENABLED", true)
-	// XDSFallbackSupport is the env variable that controls whether support for
-	// xDS fallback is turned on. If this is unset or is false, only the first
-	// xDS server in the list of server configs will be used.
-	XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true)
+
 	// NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used
 	// instead of the exiting pickfirst implementation. This can be disabled by
 	// setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST"
diff --git a/notifier/vendor/google.golang.org/grpc/internal/internal.go b/notifier/vendor/google.golang.org/grpc/internal/internal.go
index 3ac798e8..2699223a 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/internal.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/internal.go
@@ -182,35 +182,6 @@ var (
 	// other features, including the CSDS service.
 	NewXDSResolverWithClientForTesting any // func(xdsclient.XDSClient) (resolver.Builder, error)
 
-	// RegisterRLSClusterSpecifierPluginForTesting registers the RLS Cluster
-	// Specifier Plugin for testing purposes, regardless of the XDSRLS environment
-	// variable.
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	RegisterRLSClusterSpecifierPluginForTesting func()
-
-	// UnregisterRLSClusterSpecifierPluginForTesting unregisters the RLS Cluster
-	// Specifier Plugin for testing purposes. This is needed because there is no way
-	// to unregister the RLS Cluster Specifier Plugin after registering it solely
-	// for testing purposes using RegisterRLSClusterSpecifierPluginForTesting().
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	UnregisterRLSClusterSpecifierPluginForTesting func()
-
-	// RegisterRBACHTTPFilterForTesting registers the RBAC HTTP Filter for testing
-	// purposes, regardless of the RBAC environment variable.
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	RegisterRBACHTTPFilterForTesting func()
-
-	// UnregisterRBACHTTPFilterForTesting unregisters the RBAC HTTP Filter for
-	// testing purposes. This is needed because there is no way to unregister the
-	// HTTP Filter after registering it solely for testing purposes using
-	// RegisterRBACHTTPFilterForTesting().
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	UnregisterRBACHTTPFilterForTesting func()
-
 	// ORCAAllowAnyMinReportingInterval is for examples/orca use ONLY.
 	ORCAAllowAnyMinReportingInterval any // func(so *orca.ServiceOptions)
 
diff --git a/notifier/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/notifier/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
index ba5c5a95..ada5251c 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
@@ -132,13 +132,13 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
 	// DNS address (non-IP).
 	ctx, cancel := context.WithCancel(context.Background())
 	d := &dnsResolver{
-		host:                 host,
-		port:                 port,
-		ctx:                  ctx,
-		cancel:               cancel,
-		cc:                   cc,
-		rn:                   make(chan struct{}, 1),
-		disableServiceConfig: opts.DisableServiceConfig,
+		host:                host,
+		port:                port,
+		ctx:                 ctx,
+		cancel:              cancel,
+		cc:                  cc,
+		rn:                  make(chan struct{}, 1),
+		enableServiceConfig: envconfig.EnableTXTServiceConfig && !opts.DisableServiceConfig,
 	}
 
 	d.resolver, err = internal.NewNetResolver(target.URL.Host)
@@ -181,8 +181,8 @@ type dnsResolver struct {
 	// finishes, race detector sometimes will warn lookup (READ the lookup
 	// function pointers) inside watcher() goroutine has data race with
 	// replaceNetFunc (WRITE the lookup function pointers).
-	wg                   sync.WaitGroup
-	disableServiceConfig bool
+	wg                  sync.WaitGroup
+	enableServiceConfig bool
 }
 
 // ResolveNow invoke an immediate resolution of the target that this
@@ -346,7 +346,7 @@ func (d *dnsResolver) lookup() (*resolver.State, error) {
 	if len(srv) > 0 {
 		state = grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: srv})
 	}
-	if !d.disableServiceConfig {
+	if d.enableServiceConfig {
 		state.ServiceConfig = d.lookupTXT(ctx)
 	}
 	return &state, nil
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/notifier/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
index ef72fbb3..a2831e5d 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -40,6 +40,13 @@ var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
 	e.SetMaxDynamicTableSizeLimit(v)
 }
 
+// itemNodePool is used to reduce heap allocations.
+var itemNodePool = sync.Pool{
+	New: func() any {
+		return &itemNode{}
+	},
+}
+
 type itemNode struct {
 	it   any
 	next *itemNode
@@ -51,7 +58,9 @@ type itemList struct {
 }
 
 func (il *itemList) enqueue(i any) {
-	n := &itemNode{it: i}
+	n := itemNodePool.Get().(*itemNode)
+	n.next = nil
+	n.it = i
 	if il.tail == nil {
 		il.head, il.tail = n, n
 		return
@@ -71,7 +80,9 @@ func (il *itemList) dequeue() any {
 		return nil
 	}
 	i := il.head.it
+	temp := il.head
 	il.head = il.head.next
+	itemNodePool.Put(temp)
 	if il.head == nil {
 		il.tail = nil
 	}
@@ -146,10 +157,11 @@ type earlyAbortStream struct {
 func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
 
 type dataFrame struct {
-	streamID  uint32
-	endStream bool
-	h         []byte
-	reader    mem.Reader
+	streamID   uint32
+	endStream  bool
+	h          []byte
+	data       mem.BufferSlice
+	processing bool
 	// onEachWrite is called every time
 	// a part of data is written out.
 	onEachWrite func()
@@ -234,6 +246,7 @@ type outStream struct {
 	itl              *itemList
 	bytesOutStanding int
 	wq               *writeQuota
+	reader           mem.Reader
 
 	next *outStream
 	prev *outStream
@@ -461,7 +474,9 @@ func (c *controlBuffer) finish() {
 				v.onOrphaned(ErrConnClosing)
 			}
 		case *dataFrame:
-			_ = v.reader.Close()
+			if !v.processing {
+				v.data.Free()
+			}
 		}
 	}
 
@@ -650,10 +665,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
 
 func (l *loopyWriter) registerStreamHandler(h *registerStream) {
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	l.estdStreams[h.streamID] = str
 }
@@ -685,10 +701,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
 	}
 	// Case 2: Client wants to originate stream.
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	return l.originateStream(str, h)
 }
@@ -790,10 +807,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
 		// a RST_STREAM before stream initialization thus the stream might
 		// not be established yet.
 		delete(l.estdStreams, c.streamID)
+		str.reader.Close()
 		str.deleteSelf()
 		for head := str.itl.dequeueAll(); head != nil; head = head.next {
 			if df, ok := head.it.(*dataFrame); ok {
-				_ = df.reader.Close()
+				if !df.processing {
+					df.data.Free()
+				}
 			}
 		}
 	}
@@ -928,7 +948,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	if str == nil {
 		return true, nil
 	}
+	reader := str.reader
 	dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
+	if !dataItem.processing {
+		dataItem.processing = true
+		str.reader.Reset(dataItem.data)
+		dataItem.data.Free()
+	}
 	// A data item is represented by a dataFrame, since it later translates into
 	// multiple HTTP2 data frames.
 	// Every dataFrame has two buffers; h that keeps grpc-message header and data
@@ -936,13 +962,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	// from data is copied to h to make as big as the maximum possible HTTP2 frame
 	// size.
 
-	if len(dataItem.h) == 0 && dataItem.reader.Remaining() == 0 { // Empty data frame
+	if len(dataItem.h) == 0 && reader.Remaining() == 0 { // Empty data frame
 		// Client sends out empty data frame with endStream = true
 		if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
 			return false, err
 		}
 		str.itl.dequeue() // remove the empty data item from stream
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		if str.itl.isEmpty() {
 			str.state = empty
 		} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
@@ -971,8 +997,8 @@ func (l *loopyWriter) processData() (bool, error) {
 	}
 	// Compute how much of the header and data we can send within quota and max frame length
 	hSize := min(maxSize, len(dataItem.h))
-	dSize := min(maxSize-hSize, dataItem.reader.Remaining())
-	remainingBytes := len(dataItem.h) + dataItem.reader.Remaining() - hSize - dSize
+	dSize := min(maxSize-hSize, reader.Remaining())
+	remainingBytes := len(dataItem.h) + reader.Remaining() - hSize - dSize
 	size := hSize + dSize
 
 	var buf *[]byte
@@ -993,7 +1019,7 @@ func (l *loopyWriter) processData() (bool, error) {
 		defer pool.Put(buf)
 
 		copy((*buf)[:hSize], dataItem.h)
-		_, _ = dataItem.reader.Read((*buf)[hSize:])
+		_, _ = reader.Read((*buf)[hSize:])
 	}
 
 	// Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1014,7 +1040,7 @@ func (l *loopyWriter) processData() (bool, error) {
 	dataItem.h = dataItem.h[hSize:]
 
 	if remainingBytes == 0 { // All the data from that message was written out.
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		str.itl.dequeue()
 	}
 	if str.itl.isEmpty() {
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/notifier/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 3dea2357..d954a64c 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -277,11 +277,13 @@ func (ht *serverHandlerTransport) writeStatus(s *ServerStream, st *status.Status
 	if err == nil { // transport has not been closed
 		// Note: The trailer fields are compressed with hpack after this call returns.
 		// No WireLength field is set here.
+		s.hdrMu.Lock()
 		for _, sh := range ht.stats {
 			sh.HandleRPC(s.Context(), &stats.OutTrailer{
 				Trailer: s.trailer.Copy(),
 			})
 		}
+		s.hdrMu.Unlock()
 	}
 	ht.Close(errors.New("finished writing status"))
 	return err
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/notifier/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index ef56592b..5467fe97 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -309,11 +309,9 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 			scheme = "https"
 		}
 	}
-	dynamicWindow := true
 	icwz := int32(initialWindowSize)
 	if opts.InitialConnWindowSize >= defaultWindowSize {
 		icwz = opts.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	writeBufSize := opts.WriteBufferSize
 	readBufSize := opts.ReadBufferSize
@@ -381,9 +379,8 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 	t.controlBuf = newControlBuffer(t.ctxDone)
 	if opts.InitialWindowSize >= defaultWindowSize {
 		t.initialWindowSize = opts.InitialWindowSize
-		dynamicWindow = false
 	}
-	if dynamicWindow {
+	if !opts.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -1091,32 +1088,29 @@ func (t *http2Client) GracefulClose() {
 // Write formats the data into HTTP2 data frame(s) and sends it out. The caller
 // should proceed only if Write returns nil.
 func (t *http2Client) write(s *ClientStream, hdr []byte, data mem.BufferSlice, opts *WriteOptions) error {
-	reader := data.Reader()
-
 	if opts.Last {
 		// If it's the last message, update stream state.
 		if !s.compareAndSwapState(streamActive, streamWriteDone) {
-			_ = reader.Close()
 			return errStreamDone
 		}
 	} else if s.getState() != streamActive {
-		_ = reader.Close()
 		return errStreamDone
 	}
 	df := &dataFrame{
 		streamID:  s.id,
 		endStream: opts.Last,
 		h:         hdr,
-		reader:    reader,
+		data:      data,
 	}
-	if hdr != nil || df.reader.Remaining() != 0 { // If it's not an empty data frame, check quota.
-		if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-			_ = reader.Close()
+	dataLen := data.Len()
+	if hdr != nil || dataLen != 0 { // If it's not an empty data frame, check quota.
+		if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 			return err
 		}
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/notifier/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index e4c3731b..83cee314 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -132,6 +132,10 @@ type http2Server struct {
 	maxStreamID uint32 // max stream ID ever seen
 
 	logger *grpclog.PrefixLogger
+	// setResetPingStrikes is stored as a closure instead of making this a
+	// method on http2Server to avoid a heap allocation when converting a method
+	// to a closure for passing to frames objects.
+	setResetPingStrikes func()
 }
 
 // NewServerTransport creates a http2 transport with conn and configuration
@@ -176,16 +180,13 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 			Val: config.MaxStreams,
 		})
 	}
-	dynamicWindow := true
 	iwz := int32(initialWindowSize)
 	if config.InitialWindowSize >= defaultWindowSize {
 		iwz = config.InitialWindowSize
-		dynamicWindow = false
 	}
 	icwz := int32(initialWindowSize)
 	if config.InitialConnWindowSize >= defaultWindowSize {
 		icwz = config.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	if iwz != defaultWindowSize {
 		isettings = append(isettings, http2.Setting{
@@ -266,6 +267,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		initialWindowSize: iwz,
 		bufferPool:        config.BufferPool,
 	}
+	t.setResetPingStrikes = func() {
+		atomic.StoreUint32(&t.resetPingStrikes, 1)
+	}
 	var czSecurity credentials.ChannelzSecurityValue
 	if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok {
 		czSecurity = au.GetSecurityValue()
@@ -285,7 +289,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 	t.logger = prefixLoggerForServerTransport(t)
 
 	t.controlBuf = newControlBuffer(t.done)
-	if dynamicWindow {
+	if !config.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -596,10 +600,25 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
 			return nil
 		}
 	}
+
+	if s.ctx.Err() != nil {
+		t.mu.Unlock()
+		// Early abort in case the timeout was zero or so low it already fired.
+		t.controlBuf.put(&earlyAbortStream{
+			httpStatus:     http.StatusOK,
+			streamID:       s.id,
+			contentSubtype: s.contentSubtype,
+			status:         status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()),
+			rst:            !frame.StreamEnded(),
+		})
+		return nil
+	}
+
 	t.activeStreams[streamID] = s
 	if len(t.activeStreams) == 1 {
 		t.idle = time.Time{}
 	}
+
 	// Start a timer to close the stream on reaching the deadline.
 	if timeoutSet {
 		// We need to wait for s.cancel to be updated before calling
@@ -1016,10 +1035,6 @@ func (t *http2Server) writeHeader(s *ServerStream, md metadata.MD) error {
 	return nil
 }
 
-func (t *http2Server) setResetPingStrikes() {
-	atomic.StoreUint32(&t.resetPingStrikes, 1)
-}
-
 func (t *http2Server) writeHeaderLocked(s *ServerStream) error {
 	// TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
 	// first and create a slice of that exact size.
@@ -1132,17 +1147,13 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error {
 // Write converts the data into HTTP2 data frame and sends it out. Non-nil error
 // is returns if it fails (e.g., framing error, transport error).
 func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _ *WriteOptions) error {
-	reader := data.Reader()
-
 	if !s.isHeaderSent() { // Headers haven't been written yet.
 		if err := t.writeHeader(s, nil); err != nil {
-			_ = reader.Close()
 			return err
 		}
 	} else {
 		// Writing headers checks for this condition.
 		if s.getState() == streamDone {
-			_ = reader.Close()
 			return t.streamContextErr(s)
 		}
 	}
@@ -1150,15 +1161,16 @@ func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _
 	df := &dataFrame{
 		streamID:    s.id,
 		h:           hdr,
-		reader:      reader,
+		data:        data,
 		onEachWrite: t.setResetPingStrikes,
 	}
-	if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-		_ = reader.Close()
+	dataLen := data.Len()
+	if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 		return t.streamContextErr(s)
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
@@ -1341,10 +1353,10 @@ func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCo
 	// called to interrupt the potential blocking on other goroutines.
 	s.cancel()
 
-	oldState := s.swapState(streamDone)
-	if oldState == streamDone {
-		return
-	}
+	// We can't return early even if the stream's state is "done" as the state
+	// might have been set by the `finishStream` method. Deleting the stream via
+	// `finishStream` can get blocked on flow control.
+	s.swapState(streamDone)
 	t.deleteStream(s, eosReceived)
 
 	t.controlBuf.put(&cleanupStream{
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/http_util.go b/notifier/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 607d2c4c..e3663f87 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/http_util.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -200,9 +200,6 @@ func decodeTimeout(s string) (time.Duration, error) {
 	if err != nil {
 		return 0, err
 	}
-	if t == 0 {
-		return 0, fmt.Errorf("transport: timeout must be positive: %q", s)
-	}
 	const maxHours = math.MaxInt64 / uint64(time.Hour)
 	if d == time.Hour && t > maxHours {
 		// This timeout would overflow math.MaxInt64; clamp it.
diff --git a/notifier/vendor/google.golang.org/grpc/internal/transport/transport.go b/notifier/vendor/google.golang.org/grpc/internal/transport/transport.go
index 1730a639..7dd53e80 100644
--- a/notifier/vendor/google.golang.org/grpc/internal/transport/transport.go
+++ b/notifier/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -466,6 +466,7 @@ type ServerConfig struct {
 	MaxHeaderListSize     *uint32
 	HeaderTableSize       *uint32
 	BufferPool            mem.BufferPool
+	StaticWindowSize      bool
 }
 
 // ConnectOptions covers all relevant options for communicating with the server.
@@ -504,6 +505,8 @@ type ConnectOptions struct {
 	MaxHeaderListSize *uint32
 	// The mem.BufferPool to use when reading/writing to the wire.
 	BufferPool mem.BufferPool
+	// StaticWindowSize controls whether dynamic window sizing is enabled.
+	StaticWindowSize bool
 }
 
 // WriteOptions provides additional hints and information for message
diff --git a/notifier/vendor/google.golang.org/grpc/mem/buffer_slice.go b/notifier/vendor/google.golang.org/grpc/mem/buffer_slice.go
index 65002e2c..af510d20 100644
--- a/notifier/vendor/google.golang.org/grpc/mem/buffer_slice.go
+++ b/notifier/vendor/google.golang.org/grpc/mem/buffer_slice.go
@@ -137,6 +137,9 @@ type Reader interface {
 	Close() error
 	// Remaining returns the number of unread bytes remaining in the slice.
 	Remaining() int
+	// Reset frees the currently held buffer slice and starts reading from the
+	// provided slice. This allows reusing the reader object.
+	Reset(s BufferSlice)
 }
 
 type sliceReader struct {
@@ -150,6 +153,14 @@ func (r *sliceReader) Remaining() int {
 	return r.len
 }
 
+func (r *sliceReader) Reset(s BufferSlice) {
+	r.data.Free()
+	s.Ref()
+	r.data = s
+	r.len = s.Len()
+	r.bufferIdx = 0
+}
+
 func (r *sliceReader) Close() error {
 	r.data.Free()
 	r.data = nil
diff --git a/notifier/vendor/google.golang.org/grpc/picker_wrapper.go b/notifier/vendor/google.golang.org/grpc/picker_wrapper.go
index a2d2a798..aa52bfe9 100644
--- a/notifier/vendor/google.golang.org/grpc/picker_wrapper.go
+++ b/notifier/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -29,7 +29,6 @@ import (
 	"google.golang.org/grpc/internal/channelz"
 	istatus "google.golang.org/grpc/internal/status"
 	"google.golang.org/grpc/internal/transport"
-	"google.golang.org/grpc/stats"
 	"google.golang.org/grpc/status"
 )
 
@@ -48,14 +47,11 @@ type pickerGeneration struct {
 // actions and unblock when there's a picker update.
 type pickerWrapper struct {
 	// If pickerGen holds a nil pointer, the pickerWrapper is closed.
-	pickerGen     atomic.Pointer[pickerGeneration]
-	statsHandlers []stats.Handler // to record blocking picker calls
+	pickerGen atomic.Pointer[pickerGeneration]
 }
 
-func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
-	pw := &pickerWrapper{
-		statsHandlers: statsHandlers,
-	}
+func newPickerWrapper() *pickerWrapper {
+	pw := &pickerWrapper{}
 	pw.pickerGen.Store(&pickerGeneration{
 		blockingCh: make(chan struct{}),
 	})
@@ -93,6 +89,12 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 	}
 }
 
+type pick struct {
+	transport transport.ClientTransport // the selected transport
+	result    balancer.PickResult       // the contents of the pick from the LB policy
+	blocked   bool                      // set if a picker call queued for a new picker
+}
+
 // pick returns the transport that will be used for the RPC.
 // It may block in the following cases:
 // - there's no picker
@@ -100,15 +102,16 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 // - the current picker returns other errors and failfast is false.
 // - the subConn returned by the current picker is not READY
 // When one of these situations happens, pick blocks until the picker gets updated.
-func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
+func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (pick, error) {
 	var ch chan struct{}
 
 	var lastPickErr error
+	pickBlocked := false
 
 	for {
 		pg := pw.pickerGen.Load()
 		if pg == nil {
-			return nil, balancer.PickResult{}, ErrClientConnClosing
+			return pick{}, ErrClientConnClosing
 		}
 		if pg.picker == nil {
 			ch = pg.blockingCh
@@ -127,9 +130,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				}
 				switch ctx.Err() {
 				case context.DeadlineExceeded:
-					return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
+					return pick{}, status.Error(codes.DeadlineExceeded, errStr)
 				case context.Canceled:
-					return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
+					return pick{}, status.Error(codes.Canceled, errStr)
 				}
 			case <-ch:
 			}
@@ -145,9 +148,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		// In the second case, the only way it will get to this conditional is
 		// if there is a new picker.
 		if ch != nil {
-			for _, sh := range pw.statsHandlers {
-				sh.HandleRPC(ctx, &stats.PickerUpdated{})
-			}
+			pickBlocked = true
 		}
 
 		ch = pg.blockingCh
@@ -164,7 +165,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				if istatus.IsRestrictedControlPlaneCode(st) {
 					err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
 				}
-				return nil, balancer.PickResult{}, dropError{error: err}
+				return pick{}, dropError{error: err}
 			}
 			// For all other errors, wait for ready RPCs should block and other
 			// RPCs should fail with unavailable.
@@ -172,7 +173,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				lastPickErr = err
 				continue
 			}
-			return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
+			return pick{}, status.Error(codes.Unavailable, err.Error())
 		}
 
 		acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
@@ -183,9 +184,8 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		if t := acbw.ac.getReadyTransport(); t != nil {
 			if channelz.IsOn() {
 				doneChannelzWrapper(acbw, &pickResult)
-				return t, pickResult, nil
 			}
-			return t, pickResult, nil
+			return pick{transport: t, result: pickResult, blocked: pickBlocked}, nil
 		}
 		if pickResult.Done != nil {
 			// Calling done with nil error, no bytes sent and no bytes received.
diff --git a/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
index 03108280..f4a361c6 100644
--- a/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
+++ b/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go
@@ -90,7 +90,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
index 80755d74..0a43b521 100644
--- a/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
+++ b/notifier/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go
@@ -87,7 +87,7 @@ type ServerReflectionServer interface {
 type UnimplementedServerReflectionServer struct{}
 
 func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented")
+	return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented")
 }
 func (UnimplementedServerReflectionServer) testEmbeddedByValue() {}
 
diff --git a/notifier/vendor/google.golang.org/grpc/resolver/resolver.go b/notifier/vendor/google.golang.org/grpc/resolver/resolver.go
index b84ef26d..8e6af951 100644
--- a/notifier/vendor/google.golang.org/grpc/resolver/resolver.go
+++ b/notifier/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -332,6 +332,11 @@ type AuthorityOverrider interface {
 	// OverrideAuthority returns the authority to use for a ClientConn with the
 	// given target. The implementation must generate it without blocking,
 	// typically in line, and must keep it unchanged.
+	//
+	// The returned string must be a valid ":authority" header value, i.e. be
+	// encoded according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
+	// necessary.
 	OverrideAuthority(Target) string
 }
 
diff --git a/notifier/vendor/google.golang.org/grpc/server.go b/notifier/vendor/google.golang.org/grpc/server.go
index 976e70ae..1da2a542 100644
--- a/notifier/vendor/google.golang.org/grpc/server.go
+++ b/notifier/vendor/google.golang.org/grpc/server.go
@@ -179,6 +179,7 @@ type serverOptions struct {
 	numServerWorkers      uint32
 	bufferPool            mem.BufferPool
 	waitForHandlers       bool
+	staticWindowSize      bool
 }
 
 var defaultServerOptions = serverOptions{
@@ -279,6 +280,7 @@ func ReadBufferSize(s int) ServerOption {
 func InitialWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -287,6 +289,29 @@ func InitialWindowSize(s int32) ServerOption {
 func InitialConnWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialConnWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticStreamWindowSize returns a ServerOption to set the initial stream
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticStreamWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticConnWindowSize returns a ServerOption to set the initial connection
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticConnWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialConnWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -986,6 +1011,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
 		MaxHeaderListSize:     s.opts.maxHeaderListSize,
 		HeaderTableSize:       s.opts.headerTableSize,
 		BufferPool:            s.opts.bufferPool,
+		StaticWindowSize:      s.opts.staticWindowSize,
 	}
 	st, err := transport.NewServerTransport(c, config)
 	if err != nil {
@@ -1572,6 +1598,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv
 		s:                     stream,
 		p:                     &parser{r: stream, bufferPool: s.opts.bufferPool},
 		codec:                 s.getCodec(stream.ContentSubtype()),
+		desc:                  sd,
 		maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
 		maxSendMessageSize:    s.opts.maxSendMessageSize,
 		trInfo:                trInfo,
diff --git a/notifier/vendor/google.golang.org/grpc/stats/stats.go b/notifier/vendor/google.golang.org/grpc/stats/stats.go
index baf7740e..10bf998a 100644
--- a/notifier/vendor/google.golang.org/grpc/stats/stats.go
+++ b/notifier/vendor/google.golang.org/grpc/stats/stats.go
@@ -64,15 +64,21 @@ func (s *Begin) IsClient() bool { return s.Client }
 
 func (s *Begin) isRPCStats() {}
 
-// PickerUpdated indicates that the LB policy provided a new picker while the
-// RPC was waiting for one.
-type PickerUpdated struct{}
+// DelayedPickComplete indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+type DelayedPickComplete struct{}
 
-// IsClient indicates if the stats information is from client side. Only Client
-// Side interfaces with a Picker, thus always returns true.
-func (*PickerUpdated) IsClient() bool { return true }
+// IsClient indicates DelayedPickComplete is available on the client.
+func (*DelayedPickComplete) IsClient() bool { return true }
 
-func (*PickerUpdated) isRPCStats() {}
+func (*DelayedPickComplete) isRPCStats() {}
+
+// PickerUpdated indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+//
+// Deprecated: will be removed in a future release; use DelayedPickComplete
+// instead.
+type PickerUpdated = DelayedPickComplete
 
 // InPayload contains stats about an incoming payload.
 type InPayload struct {
diff --git a/notifier/vendor/google.golang.org/grpc/stream.go b/notifier/vendor/google.golang.org/grpc/stream.go
index d58bb647..d9bbd4c5 100644
--- a/notifier/vendor/google.golang.org/grpc/stream.go
+++ b/notifier/vendor/google.golang.org/grpc/stream.go
@@ -469,8 +469,9 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error)
 func (a *csAttempt) getTransport() error {
 	cs := a.cs
 
-	var err error
-	a.transport, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method)
+	pickInfo := balancer.PickInfo{Ctx: a.ctx, FullMethodName: cs.callHdr.Method}
+	pick, err := cs.cc.pickerWrapper.pick(a.ctx, cs.callInfo.failFast, pickInfo)
+	a.transport, a.pickResult = pick.transport, pick.result
 	if err != nil {
 		if de, ok := err.(dropError); ok {
 			err = de.error
@@ -481,6 +482,11 @@ func (a *csAttempt) getTransport() error {
 	if a.trInfo != nil {
 		a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr())
 	}
+	if pick.blocked {
+		for _, sh := range a.statsHandlers {
+			sh.HandleRPC(a.ctx, &stats.DelayedPickComplete{})
+		}
+	}
 	return nil
 }
 
@@ -1171,7 +1177,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (a *csAttempt) finish(err error) {
@@ -1495,7 +1501,7 @@ func (as *addrConnStream) RecvMsg(m any) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (as *addrConnStream) finish(err error) {
@@ -1580,6 +1586,7 @@ type serverStream struct {
 	s     *transport.ServerStream
 	p     *parser
 	codec baseCodec
+	desc  *StreamDesc
 
 	compressorV0   Compressor
 	compressorV1   encoding.Compressor
@@ -1588,6 +1595,8 @@ type serverStream struct {
 
 	sendCompressorName string
 
+	recvFirstMsg bool // set after the first message is received
+
 	maxReceiveMessageSize int
 	maxSendMessageSize    int
 	trInfo                *traceInfo
@@ -1774,6 +1783,10 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 					binlog.Log(ss.ctx, chc)
 				}
 			}
+			// Received no request msg for non-client streaming rpcs.
+			if !ss.desc.ClientStreams && !ss.recvFirstMsg {
+				return status.Error(codes.Internal, "cardinality violation: received no request message from non-client-streaming RPC")
+			}
 			return err
 		}
 		if err == io.ErrUnexpectedEOF {
@@ -1781,6 +1794,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 		}
 		return toRPCErr(err)
 	}
+	ss.recvFirstMsg = true
 	if len(ss.statsHandler) != 0 {
 		for _, sh := range ss.statsHandler {
 			sh.HandleRPC(ss.s.Context(), &stats.InPayload{
@@ -1800,7 +1814,19 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 			binlog.Log(ss.ctx, cm)
 		}
 	}
-	return nil
+
+	if ss.desc.ClientStreams {
+		// Subsequent messages should be received by subsequent RecvMsg calls.
+		return nil
+	}
+	// Special handling for non-client-stream rpcs.
+	// This recv expects EOF or errors, so we don't collect inPayload.
+	if err := recv(ss.p, ss.codec, ss.s, ss.decompressorV0, m, ss.maxReceiveMessageSize, nil, ss.decompressorV1, true); err == io.EOF {
+		return nil
+	} else if err != nil {
+		return err
+	}
+	return status.Error(codes.Internal, "cardinality violation: received multiple request messages for non-client-streaming RPC")
 }
 
 // MethodFromServerStream returns the method string for the input stream.
diff --git a/notifier/vendor/google.golang.org/grpc/version.go b/notifier/vendor/google.golang.org/grpc/version.go
index bd82673d..468f1106 100644
--- a/notifier/vendor/google.golang.org/grpc/version.go
+++ b/notifier/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.73.0"
+const Version = "1.75.1"
diff --git a/notifier/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go b/notifier/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
index 999a2515..45749edd 100644
--- a/notifier/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
+++ b/notifier/vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/opaque.go
@@ -11,6 +11,7 @@ import (
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/reflect/protoreflect"
 
@@ -279,8 +280,7 @@ func isLazy(field *protogen.Field) bool {
 	}
 
 	// Was the field marked as [lazy = true] in the .proto file?
-	fopts := field.Desc.Options().(*descriptorpb.FieldOptions)
-	return fopts.GetLazy()
+	return field.Desc.(interface{ IsLazy() bool }).IsLazy()
 }
 
 // opaqueGenGet generates a Get method for a field.
@@ -573,16 +573,8 @@ func usePresence(message *messageInfo, field *protogen.Field) bool {
 	if !message.isOpaque() {
 		return false
 	}
-	return opaqueFieldNeedsPresenceArray(message, field)
-}
-
-func opaqueFieldNeedsPresenceArray(message *messageInfo, field *protogen.Field) bool {
-	// Non optional fields need presence if truly lazy field, i.e. are message fields.
-	if isLazy(field) {
-		return true
-	}
-	isNotOneof := field.Desc.ContainingOneof() == nil || field.Desc.ContainingOneof().IsSynthetic()
-	return field.Desc.HasPresence() && field.Message == nil && isNotOneof
+	usePresence, _ := filedesc.UsePresenceForField(field.Desc)
+	return usePresence
 }
 
 // opaqueGenHas generates a Has method for a field.
@@ -832,7 +824,7 @@ func opaqueNeedsPresenceArray(message *messageInfo) bool {
 		return false
 	}
 	for _, field := range message.Fields {
-		if opaqueFieldNeedsPresenceArray(message, field) {
+		if usePresence, _ := filedesc.UsePresenceForField(field.Desc); usePresence {
 			return true
 		}
 	}
diff --git a/notifier/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/notifier/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
index e942bc98..743bfb81 100644
--- a/notifier/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
+++ b/notifier/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
@@ -371,7 +371,31 @@ func ConsumeVarint(b []byte) (v uint64, n int) {
 func SizeVarint(v uint64) int {
 	// This computes 1 + (bits.Len64(v)-1)/7.
 	// 9/64 is a good enough approximation of 1/7
-	return int(9*uint32(bits.Len64(v))+64) / 64
+	//
+	// The Go compiler can translate the bits.LeadingZeros64 call into the LZCNT
+	// instruction, which is very fast on CPUs from the last few years. The
+	// specific way of expressing the calculation matches C++ Protobuf, see
+	// https://godbolt.org/z/4P3h53oM4 for the C++ code and how gcc/clang
+	// optimize that function for GOAMD64=v1 and GOAMD64=v3 (-march=haswell).
+
+	// By OR'ing v with 1, we guarantee that v is never 0, without changing the
+	// result of SizeVarint. LZCNT is not defined for 0, meaning the compiler
+	// needs to add extra instructions to handle that case.
+	//
+	// The Go compiler currently (go1.24.4) does not make use of this knowledge.
+	// This opportunity (removing the XOR instruction, which handles the 0 case)
+	// results in a small (1%) performance win across CPU architectures.
+	//
+	// Independently of avoiding the 0 case, we need the v |= 1 line because
+	// it allows the Go compiler to eliminate an extra XCHGL barrier.
+	v |= 1
+
+	// It would be clearer to write log2value := 63 - uint32(...), but
+	// writing uint32(...) ^ 63 is much more efficient (-14% ARM, -20% Intel).
+	// Proof of identity for our value range [0..63]:
+	// https://go.dev/play/p/Pdn9hEWYakX
+	log2value := uint32(bits.LeadingZeros64(v)) ^ 63
+	return int((log2value*9 + (64 + 9)) / 64)
 }
 
 // AppendFixed32 appends v to b as a little-endian uint32.
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/notifier/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb
index 323829da..04696351 100644
Binary files a/notifier/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb and b/notifier/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb differ
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/notifier/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
index bf1aba0e..7b9f01af 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
@@ -9,7 +9,7 @@ import "google.golang.org/protobuf/types/descriptorpb"
 
 const (
 	Minimum = descriptorpb.Edition_EDITION_PROTO2
-	Maximum = descriptorpb.Edition_EDITION_2023
+	Maximum = descriptorpb.Edition_EDITION_2024
 
 	// MaximumKnown is the maximum edition that is known to Go Protobuf, but not
 	// declared as supported. In other words: end users cannot use it, but
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 688aabe4..dbcf90b8 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -72,9 +72,10 @@ type (
 		EditionFeatures EditionFeatures
 	}
 	FileL2 struct {
-		Options   func() protoreflect.ProtoMessage
-		Imports   FileImports
-		Locations SourceLocations
+		Options       func() protoreflect.ProtoMessage
+		Imports       FileImports
+		OptionImports func() protoreflect.FileImports
+		Locations     SourceLocations
 	}
 
 	// EditionFeatures is a frequently-instantiated struct, so please take care
@@ -126,12 +127,9 @@ func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
 func (fd *File) Parent() protoreflect.Descriptor         { return nil }
 func (fd *File) Index() int                              { return 0 }
 func (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }
-
-// Not exported and just used to reconstruct the original FileDescriptor proto
-func (fd *File) Edition() int32                  { return int32(fd.L1.Edition) }
-func (fd *File) Name() protoreflect.Name         { return fd.L1.Package.Name() }
-func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
-func (fd *File) IsPlaceholder() bool             { return false }
+func (fd *File) Name() protoreflect.Name                 { return fd.L1.Package.Name() }
+func (fd *File) FullName() protoreflect.FullName         { return fd.L1.Package }
+func (fd *File) IsPlaceholder() bool                     { return false }
 func (fd *File) Options() protoreflect.ProtoMessage {
 	if f := fd.lazyInit().Options; f != nil {
 		return f()
@@ -150,6 +148,16 @@ func (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatD
 func (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
 func (fd *File) ProtoInternal(pragma.DoNotImplement)           {}
 
+// The next two are not part of the FileDescriptor interface. They are just used to reconstruct
+// the original FileDescriptor proto.
+func (fd *File) Edition() int32 { return int32(fd.L1.Edition) }
+func (fd *File) OptionImports() protoreflect.FileImports {
+	if f := fd.lazyInit().OptionImports; f != nil {
+		return f()
+	}
+	return emptyFiles
+}
+
 func (fd *File) lazyInit() *FileL2 {
 	if atomic.LoadUint32(&fd.once) == 0 {
 		fd.lazyInitOnce()
@@ -182,9 +190,9 @@ type (
 		L2 *EnumL2 // protected by fileDesc.once
 	}
 	EnumL1 struct {
-		eagerValues bool // controls whether EnumL2.Values is already populated
-
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		eagerValues     bool // controls whether EnumL2.Values is already populated
 	}
 	EnumL2 struct {
 		Options        func() protoreflect.ProtoMessage
@@ -219,6 +227,11 @@ func (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit()
 func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
 func (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
 func (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
+
+// This is not part of the EnumDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (ed *Enum) Visibility() int32 { return ed.L1.Visibility }
+
 func (ed *Enum) lazyInit() *EnumL2 {
 	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return ed.L2
@@ -244,13 +257,13 @@ type (
 		L2 *MessageL2 // protected by fileDesc.once
 	}
 	MessageL1 struct {
-		Enums        Enums
-		Messages     Messages
-		Extensions   Extensions
-		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
-		IsMessageSet bool // promoted from google.protobuf.MessageOptions
-
+		Enums           Enums
+		Messages        Messages
+		Extensions      Extensions
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		IsMapEntry      bool // promoted from google.protobuf.MessageOptions
+		IsMessageSet    bool // promoted from google.protobuf.MessageOptions
 	}
 	MessageL2 struct {
 		Options               func() protoreflect.ProtoMessage
@@ -319,6 +332,11 @@ func (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L
 func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
 func (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
 func (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
+
+// This is not part of the MessageDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (md *Message) Visibility() int32 { return md.L1.Visibility }
+
 func (md *Message) lazyInit() *MessageL2 {
 	md.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return md.L2
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
index d2f54949..e91860f5 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
@@ -284,6 +284,13 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protorefl
 			case genid.EnumDescriptorProto_Value_field_number:
 				numValues++
 			}
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.EnumDescriptorProto_Visibility_field_number:
+				ed.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
@@ -365,6 +372,13 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
 				md.unmarshalSeedOptions(v)
 			}
 			prevField = num
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.DescriptorProto_Visibility_field_number:
+				md.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index d4c94458..dd31faae 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -134,6 +134,7 @@ func (fd *File) unmarshalFull(b []byte) {
 
 	var enumIdx, messageIdx, extensionIdx, serviceIdx int
 	var rawOptions []byte
+	var optionImports []string
 	fd.L2 = new(FileL2)
 	for len(b) > 0 {
 		num, typ, n := protowire.ConsumeTag(b)
@@ -157,6 +158,8 @@ func (fd *File) unmarshalFull(b []byte) {
 					imp = PlaceholderFile(path)
 				}
 				fd.L2.Imports = append(fd.L2.Imports, protoreflect.FileImport{FileDescriptor: imp})
+			case genid.FileDescriptorProto_OptionDependency_field_number:
+				optionImports = append(optionImports, sb.MakeString(v))
 			case genid.FileDescriptorProto_EnumType_field_number:
 				fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
 				enumIdx++
@@ -178,6 +181,23 @@ func (fd *File) unmarshalFull(b []byte) {
 		}
 	}
 	fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
+	if len(optionImports) > 0 {
+		var imps FileImports
+		var once sync.Once
+		fd.L2.OptionImports = func() protoreflect.FileImports {
+			once.Do(func() {
+				imps = make(FileImports, len(optionImports))
+				for i, path := range optionImports {
+					imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
+					if imp == nil {
+						imp = PlaceholderFile(path)
+					}
+					imps[i] = protoreflect.FileImport{FileDescriptor: imp}
+				}
+			})
+			return &imps
+		}
+	}
 }
 
 func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
index b08b7183..66ba9068 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
@@ -13,8 +13,10 @@ import (
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
-var defaultsCache = make(map[Edition]EditionFeatures)
-var defaultsKeys = []Edition{}
+var (
+	defaultsCache = make(map[Edition]EditionFeatures)
+	defaultsKeys  = []Edition{}
+)
 
 func init() {
 	unmarshalEditionDefaults(editiondefaults.Defaults)
@@ -41,7 +43,7 @@ func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
 			b = b[m:]
 			parent.StripEnumPrefix = int(v)
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling GoFeatures", num))
 		}
 	}
 	return parent
@@ -72,8 +74,11 @@ func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
 			case genid.FeatureSet_EnforceNamingStyle_field_number:
 				// EnforceNamingStyle is enforced in protoc, languages other than C++
 				// are not supposed to do anything with this feature.
+			case genid.FeatureSet_DefaultSymbolVisibility_field_number:
+				// DefaultSymbolVisibility is enforced in protoc, runtimes should not
+				// inspect this value.
 			default:
-				panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
+				panic(fmt.Sprintf("unknown field number %d while unmarshalling FeatureSet", num))
 			}
 		case protowire.BytesType:
 			v, m := protowire.ConsumeBytes(b)
@@ -147,7 +152,7 @@ func unmarshalEditionDefaults(b []byte) {
 			_, m := protowire.ConsumeVarint(b)
 			b = b[m:]
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling EditionDefault", num))
 		}
 	}
 }
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/filedesc/presence.go b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
new file mode 100644
index 00000000..a12ec979
--- /dev/null
+++ b/notifier/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
@@ -0,0 +1,33 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package filedesc
+
+import "google.golang.org/protobuf/reflect/protoreflect"
+
+// UsePresenceForField reports whether the presence bitmap should be used for
+// the specified field.
+func UsePresenceForField(fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
+	switch {
+	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
+		// Oneof fields never use the presence bitmap.
+		//
+		// Synthetic oneofs are an exception: Those are used to implement proto3
+		// optional fields and hence should follow non-oneof field semantics.
+		return false, false
+
+	case fd.IsMap():
+		// Map-typed fields never use the presence bitmap.
+		return false, false
+
+	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
+		// Lazy fields always use the presence bitmap (only messages can be lazy).
+		isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
+		return isLazy, isLazy
+
+	default:
+		// If the field has presence, use the presence bitmap.
+		return fd.HasPresence(), false
+	}
+}
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/genid/api_gen.go b/notifier/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
index df8f9185..3ceb6fa7 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
@@ -27,6 +27,7 @@ const (
 	Api_SourceContext_field_name protoreflect.Name = "source_context"
 	Api_Mixins_field_name        protoreflect.Name = "mixins"
 	Api_Syntax_field_name        protoreflect.Name = "syntax"
+	Api_Edition_field_name       protoreflect.Name = "edition"
 
 	Api_Name_field_fullname          protoreflect.FullName = "google.protobuf.Api.name"
 	Api_Methods_field_fullname       protoreflect.FullName = "google.protobuf.Api.methods"
@@ -35,6 +36,7 @@ const (
 	Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context"
 	Api_Mixins_field_fullname        protoreflect.FullName = "google.protobuf.Api.mixins"
 	Api_Syntax_field_fullname        protoreflect.FullName = "google.protobuf.Api.syntax"
+	Api_Edition_field_fullname       protoreflect.FullName = "google.protobuf.Api.edition"
 )
 
 // Field numbers for google.protobuf.Api.
@@ -46,6 +48,7 @@ const (
 	Api_SourceContext_field_number protoreflect.FieldNumber = 5
 	Api_Mixins_field_number        protoreflect.FieldNumber = 6
 	Api_Syntax_field_number        protoreflect.FieldNumber = 7
+	Api_Edition_field_number       protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Method.
@@ -63,6 +66,7 @@ const (
 	Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming"
 	Method_Options_field_name           protoreflect.Name = "options"
 	Method_Syntax_field_name            protoreflect.Name = "syntax"
+	Method_Edition_field_name           protoreflect.Name = "edition"
 
 	Method_Name_field_fullname              protoreflect.FullName = "google.protobuf.Method.name"
 	Method_RequestTypeUrl_field_fullname    protoreflect.FullName = "google.protobuf.Method.request_type_url"
@@ -71,6 +75,7 @@ const (
 	Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming"
 	Method_Options_field_fullname           protoreflect.FullName = "google.protobuf.Method.options"
 	Method_Syntax_field_fullname            protoreflect.FullName = "google.protobuf.Method.syntax"
+	Method_Edition_field_fullname           protoreflect.FullName = "google.protobuf.Method.edition"
 )
 
 // Field numbers for google.protobuf.Method.
@@ -82,6 +87,7 @@ const (
 	Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5
 	Method_Options_field_number           protoreflect.FieldNumber = 6
 	Method_Syntax_field_number            protoreflect.FieldNumber = 7
+	Method_Edition_field_number           protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Mixin.
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/notifier/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
index 39524782..950a6a32 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
@@ -34,6 +34,19 @@ const (
 	Edition_EDITION_MAX_enum_value             = 2147483647
 )
 
+// Full and short names for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_enum_fullname = "google.protobuf.SymbolVisibility"
+	SymbolVisibility_enum_name     = "SymbolVisibility"
+)
+
+// Enum values for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_VISIBILITY_UNSET_enum_value  = 0
+	SymbolVisibility_VISIBILITY_LOCAL_enum_value  = 1
+	SymbolVisibility_VISIBILITY_EXPORT_enum_value = 2
+)
+
 // Names for google.protobuf.FileDescriptorSet.
 const (
 	FileDescriptorSet_message_name     protoreflect.Name     = "FileDescriptorSet"
@@ -65,6 +78,7 @@ const (
 	FileDescriptorProto_Dependency_field_name       protoreflect.Name = "dependency"
 	FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency"
 	FileDescriptorProto_WeakDependency_field_name   protoreflect.Name = "weak_dependency"
+	FileDescriptorProto_OptionDependency_field_name protoreflect.Name = "option_dependency"
 	FileDescriptorProto_MessageType_field_name      protoreflect.Name = "message_type"
 	FileDescriptorProto_EnumType_field_name         protoreflect.Name = "enum_type"
 	FileDescriptorProto_Service_field_name          protoreflect.Name = "service"
@@ -79,6 +93,7 @@ const (
 	FileDescriptorProto_Dependency_field_fullname       protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency"
 	FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency"
 	FileDescriptorProto_WeakDependency_field_fullname   protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency"
+	FileDescriptorProto_OptionDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.option_dependency"
 	FileDescriptorProto_MessageType_field_fullname      protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type"
 	FileDescriptorProto_EnumType_field_fullname         protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type"
 	FileDescriptorProto_Service_field_fullname          protoreflect.FullName = "google.protobuf.FileDescriptorProto.service"
@@ -96,6 +111,7 @@ const (
 	FileDescriptorProto_Dependency_field_number       protoreflect.FieldNumber = 3
 	FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10
 	FileDescriptorProto_WeakDependency_field_number   protoreflect.FieldNumber = 11
+	FileDescriptorProto_OptionDependency_field_number protoreflect.FieldNumber = 15
 	FileDescriptorProto_MessageType_field_number      protoreflect.FieldNumber = 4
 	FileDescriptorProto_EnumType_field_number         protoreflect.FieldNumber = 5
 	FileDescriptorProto_Service_field_number          protoreflect.FieldNumber = 6
@@ -124,6 +140,7 @@ const (
 	DescriptorProto_Options_field_name        protoreflect.Name = "options"
 	DescriptorProto_ReservedRange_field_name  protoreflect.Name = "reserved_range"
 	DescriptorProto_ReservedName_field_name   protoreflect.Name = "reserved_name"
+	DescriptorProto_Visibility_field_name     protoreflect.Name = "visibility"
 
 	DescriptorProto_Name_field_fullname           protoreflect.FullName = "google.protobuf.DescriptorProto.name"
 	DescriptorProto_Field_field_fullname          protoreflect.FullName = "google.protobuf.DescriptorProto.field"
@@ -135,6 +152,7 @@ const (
 	DescriptorProto_Options_field_fullname        protoreflect.FullName = "google.protobuf.DescriptorProto.options"
 	DescriptorProto_ReservedRange_field_fullname  protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range"
 	DescriptorProto_ReservedName_field_fullname   protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name"
+	DescriptorProto_Visibility_field_fullname     protoreflect.FullName = "google.protobuf.DescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.DescriptorProto.
@@ -149,6 +167,7 @@ const (
 	DescriptorProto_Options_field_number        protoreflect.FieldNumber = 7
 	DescriptorProto_ReservedRange_field_number  protoreflect.FieldNumber = 9
 	DescriptorProto_ReservedName_field_number   protoreflect.FieldNumber = 10
+	DescriptorProto_Visibility_field_number     protoreflect.FieldNumber = 11
 )
 
 // Names for google.protobuf.DescriptorProto.ExtensionRange.
@@ -388,12 +407,14 @@ const (
 	EnumDescriptorProto_Options_field_name       protoreflect.Name = "options"
 	EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
 	EnumDescriptorProto_ReservedName_field_name  protoreflect.Name = "reserved_name"
+	EnumDescriptorProto_Visibility_field_name    protoreflect.Name = "visibility"
 
 	EnumDescriptorProto_Name_field_fullname          protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name"
 	EnumDescriptorProto_Value_field_fullname         protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value"
 	EnumDescriptorProto_Options_field_fullname       protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options"
 	EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range"
 	EnumDescriptorProto_ReservedName_field_fullname  protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name"
+	EnumDescriptorProto_Visibility_field_fullname    protoreflect.FullName = "google.protobuf.EnumDescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.EnumDescriptorProto.
@@ -403,6 +424,7 @@ const (
 	EnumDescriptorProto_Options_field_number       protoreflect.FieldNumber = 3
 	EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4
 	EnumDescriptorProto_ReservedName_field_number  protoreflect.FieldNumber = 5
+	EnumDescriptorProto_Visibility_field_number    protoreflect.FieldNumber = 6
 )
 
 // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
@@ -1008,32 +1030,35 @@ const (
 
 // Field names for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_name         protoreflect.Name = "field_presence"
-	FeatureSet_EnumType_field_name              protoreflect.Name = "enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_name        protoreflect.Name = "utf8_validation"
-	FeatureSet_MessageEncoding_field_name       protoreflect.Name = "message_encoding"
-	FeatureSet_JsonFormat_field_name            protoreflect.Name = "json_format"
-	FeatureSet_EnforceNamingStyle_field_name    protoreflect.Name = "enforce_naming_style"
-
-	FeatureSet_FieldPresence_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
-	FeatureSet_EnumType_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_fullname        protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
-	FeatureSet_MessageEncoding_field_fullname       protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
-	FeatureSet_JsonFormat_field_fullname            protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
-	FeatureSet_EnforceNamingStyle_field_fullname    protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_FieldPresence_field_name           protoreflect.Name = "field_presence"
+	FeatureSet_EnumType_field_name                protoreflect.Name = "enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_name   protoreflect.Name = "repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_name          protoreflect.Name = "utf8_validation"
+	FeatureSet_MessageEncoding_field_name         protoreflect.Name = "message_encoding"
+	FeatureSet_JsonFormat_field_name              protoreflect.Name = "json_format"
+	FeatureSet_EnforceNamingStyle_field_name      protoreflect.Name = "enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_name protoreflect.Name = "default_symbol_visibility"
+
+	FeatureSet_FieldPresence_field_fullname           protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
+	FeatureSet_EnumType_field_fullname                protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_fullname   protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_fullname          protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
+	FeatureSet_MessageEncoding_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
+	FeatureSet_JsonFormat_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
+	FeatureSet_EnforceNamingStyle_field_fullname      protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.default_symbol_visibility"
 )
 
 // Field numbers for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_number         protoreflect.FieldNumber = 1
-	FeatureSet_EnumType_field_number              protoreflect.FieldNumber = 2
-	FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
-	FeatureSet_Utf8Validation_field_number        protoreflect.FieldNumber = 4
-	FeatureSet_MessageEncoding_field_number       protoreflect.FieldNumber = 5
-	FeatureSet_JsonFormat_field_number            protoreflect.FieldNumber = 6
-	FeatureSet_EnforceNamingStyle_field_number    protoreflect.FieldNumber = 7
+	FeatureSet_FieldPresence_field_number           protoreflect.FieldNumber = 1
+	FeatureSet_EnumType_field_number                protoreflect.FieldNumber = 2
+	FeatureSet_RepeatedFieldEncoding_field_number   protoreflect.FieldNumber = 3
+	FeatureSet_Utf8Validation_field_number          protoreflect.FieldNumber = 4
+	FeatureSet_MessageEncoding_field_number         protoreflect.FieldNumber = 5
+	FeatureSet_JsonFormat_field_number              protoreflect.FieldNumber = 6
+	FeatureSet_EnforceNamingStyle_field_number      protoreflect.FieldNumber = 7
+	FeatureSet_DefaultSymbolVisibility_field_number protoreflect.FieldNumber = 8
 )
 
 // Full and short names for google.protobuf.FeatureSet.FieldPresence.
@@ -1128,6 +1153,27 @@ const (
 	FeatureSet_STYLE_LEGACY_enum_value                 = 2
 )
 
+// Names for google.protobuf.FeatureSet.VisibilityFeature.
+const (
+	FeatureSet_VisibilityFeature_message_name     protoreflect.Name     = "VisibilityFeature"
+	FeatureSet_VisibilityFeature_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet.VisibilityFeature"
+)
+
+// Full and short names for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_fullname = "google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility"
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_name     = "DefaultSymbolVisibility"
+)
+
+// Enum values for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN_enum_value = 0
+	FeatureSet_VisibilityFeature_EXPORT_ALL_enum_value                        = 1
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL_enum_value                  = 2
+	FeatureSet_VisibilityFeature_LOCAL_ALL_enum_value                         = 3
+	FeatureSet_VisibilityFeature_STRICT_enum_value                            = 4
+)
+
 // Names for google.protobuf.FeatureSetDefaults.
 const (
 	FeatureSetDefaults_message_name     protoreflect.Name     = "FeatureSetDefaults"
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/notifier/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
index 41c1f74e..bdad12a9 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
@@ -11,6 +11,7 @@ import (
 
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/encoding/messageset"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/order"
 	"google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -80,7 +81,7 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
 		// permit us to skip over definitely-unset fields at marshal time.
 
 		var hasPresence bool
-		hasPresence, cf.isLazy = usePresenceForField(si, fd)
+		hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
 
 		if hasPresence {
 			cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/notifier/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
index dd55e8e0..5a439daa 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"sync/atomic"
 
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
@@ -53,7 +54,7 @@ func opaqueInitHook(mi *MessageInfo) bool {
 		fd := fds.Get(i)
 		fs := si.fieldsByNumber[fd.Number()]
 		var fi fieldInfo
-		usePresence, _ := usePresenceForField(si, fd)
+		usePresence, _ := filedesc.UsePresenceForField(fd)
 
 		switch {
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
@@ -343,17 +344,15 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return false
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return false
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			return rv.Elem().Len() > 0
 		},
 		clear: func(p pointer) {
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if !sp.IsNil() {
-				rv := sp.AsValueOf(fs.Type.Elem())
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if !rv.IsNil() {
 				rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
 			}
 		},
@@ -361,11 +360,10 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return conv.Zero()
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return conv.Zero()
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			if rv.Elem().Len() == 0 {
 				return conv.Zero()
 			}
@@ -598,30 +596,3 @@ func (mi *MessageInfo) clearPresent(p pointer, index uint32) {
 func (mi *MessageInfo) present(p pointer, index uint32) bool {
 	return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
 }
-
-// usePresenceForField implements the somewhat intricate logic of when
-// the presence bitmap is used for a field.  The main logic is that a
-// field that is optional or that can be lazy will use the presence
-// bit, but for proto2, also maps have a presence bit. It also records
-// if the field can ever be lazy, which is true if we have a
-// lazyOffset and the field is a message or a slice of messages. A
-// field that is lazy will always need a presence bit.  Oneofs are not
-// lazy and do not use presence, unless they are a synthetic oneof,
-// which is a proto3 optional field. For proto3 optionals, we use the
-// presence and they can also be lazy when applicable (a message).
-func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
-	hasLazyField := fd.(interface{ IsLazy() bool }).IsLazy()
-
-	// Non-oneof scalar fields with explicit field presence use the presence array.
-	usesPresenceArray := fd.HasPresence() && fd.Message() == nil && (fd.ContainingOneof() == nil || fd.ContainingOneof().IsSynthetic())
-	switch {
-	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
-		return false, false
-	case fd.IsMap():
-		return false, false
-	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
-		return hasLazyField, hasLazyField
-	default:
-		return usesPresenceArray || (hasLazyField && fd.HasPresence()), false
-	}
-}
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/impl/presence.go b/notifier/vendor/google.golang.org/protobuf/internal/impl/presence.go
index 914cb1de..443afe81 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/impl/presence.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/impl/presence.go
@@ -32,9 +32,6 @@ func (p presence) toElem(num uint32) (ret *uint32) {
 
 // Present checks for the presence of a specific field number in a presence set.
 func (p presence) Present(num uint32) bool {
-	if p.P == nil {
-		return false
-	}
 	return Export{}.Present(p.toElem(num), num)
 }
 
diff --git a/notifier/vendor/google.golang.org/protobuf/internal/version/version.go b/notifier/vendor/google.golang.org/protobuf/internal/version/version.go
index aac1cb18..77de0f23 100644
--- a/notifier/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/notifier/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -52,7 +52,7 @@ import (
 const (
 	Major      = 1
 	Minor      = 36
-	Patch      = 6
+	Patch      = 10
 	PreRelease = ""
 )
 
diff --git a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
index 823dbf3b..9196288e 100644
--- a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
+++ b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
@@ -152,6 +152,28 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
 		imp := &f.L2.Imports[i]
 		imps.importPublic(imp.Imports())
 	}
+	if len(fd.GetOptionDependency()) > 0 {
+		optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency()))
+		for i, path := range fd.GetOptionDependency() {
+			imp := &optionImports[i]
+			f, err := r.FindFileByPath(path)
+			if err == protoregistry.NotFound {
+				// We always allow option imports to be unresolvable.
+				f = filedesc.PlaceholderFile(path)
+			} else if err != nil {
+				return nil, errors.New("could not resolve import %q: %v", path, err)
+			}
+			imp.FileDescriptor = f
+
+			if imps[imp.Path()] {
+				return nil, errors.New("already imported %q", path)
+			}
+			imps[imp.Path()] = true
+		}
+		f.L2.OptionImports = func() protoreflect.FileImports {
+			return &optionImports
+		}
+	}
 
 	// Handle source locations.
 	f.L2.Locations.File = f
diff --git a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
index 9da34998..c826ad04 100644
--- a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
+++ b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
@@ -29,6 +29,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
 			e.L2.Options = func() protoreflect.ProtoMessage { return opts }
 		}
 		e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
+		e.L1.Visibility = int32(ed.GetVisibility())
 		for _, s := range ed.GetReservedName() {
 			e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
 		}
@@ -70,6 +71,7 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
 			return nil, err
 		}
 		m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
+		m.L1.Visibility = int32(md.GetVisibility())
 		if opts := md.GetOptions(); opts != nil {
 			opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
 			m.L2.Options = func() protoreflect.ProtoMessage { return opts }
diff --git a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
index 9b880aa8..6f91074e 100644
--- a/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
+++ b/notifier/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
@@ -70,16 +70,27 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
 	if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
 		p.Syntax = proto.String(file.Syntax().String())
 	}
+	desc := file
+	if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
+		desc = fileImportDesc.FileDescriptor
+	}
 	if file.Syntax() == protoreflect.Editions {
-		desc := file
-		if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
-			desc = fileImportDesc.FileDescriptor
-		}
-
 		if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok {
 			p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum()
 		}
 	}
+	type hasOptionImports interface {
+		OptionImports() protoreflect.FileImports
+	}
+	if opts, ok := desc.(hasOptionImports); ok {
+		if optionImports := opts.OptionImports(); optionImports.Len() > 0 {
+			optionDeps := make([]string, optionImports.Len())
+			for i := range optionImports.Len() {
+				optionDeps[i] = optionImports.Get(i).Path()
+			}
+			p.OptionDependency = optionDeps
+		}
+	}
 	return p
 }
 
@@ -123,6 +134,14 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
 	for i, names := 0, message.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := message.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
@@ -216,6 +235,14 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
 	for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ {
 		p.ReservedName = append(p.ReservedName, string(names.Get(i)))
 	}
+	type hasVisibility interface {
+		Visibility() int32
+	}
+	if vis, ok := enum.(hasVisibility); ok {
+		if visibility := vis.Visibility(); visibility > 0 {
+			p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum()
+		}
+	}
 	return p
 }
 
diff --git a/notifier/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/notifier/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
index a4a0a297..730331e6 100644
--- a/notifier/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
+++ b/notifier/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
@@ -21,6 +21,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "public_dependency", nil)
 	case 11:
 		b = p.appendRepeatedField(b, "weak_dependency", nil)
+	case 15:
+		b = p.appendRepeatedField(b, "option_dependency", nil)
 	case 4:
 		b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto)
 	case 5:
@@ -66,6 +68,8 @@ func (p *SourcePath) appendDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange)
 	case 10:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 11:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -85,6 +89,8 @@ func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange)
 	case 5:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 6:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -400,6 +406,8 @@ func (p *SourcePath) appendFeatureSet(b []byte) []byte {
 		b = p.appendSingularField(b, "json_format", nil)
 	case 7:
 		b = p.appendSingularField(b, "enforce_naming_style", nil)
+	case 8:
+		b = p.appendSingularField(b, "default_symbol_visibility", nil)
 	}
 	return b
 }
diff --git a/notifier/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/notifier/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
index 7fe280f1..4eacb523 100644
--- a/notifier/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
+++ b/notifier/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
@@ -151,6 +151,70 @@ func (Edition) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0}
 }
 
+// Describes the 'visibility' of a symbol with respect to the proto import
+// system. Symbols can only be imported when the visibility rules do not prevent
+// it (ex: local symbols cannot be imported).  Visibility modifiers can only set
+// on `message` and `enum` as they are the only types available to be referenced
+// from other files.
+type SymbolVisibility int32
+
+const (
+	SymbolVisibility_VISIBILITY_UNSET  SymbolVisibility = 0
+	SymbolVisibility_VISIBILITY_LOCAL  SymbolVisibility = 1
+	SymbolVisibility_VISIBILITY_EXPORT SymbolVisibility = 2
+)
+
+// Enum value maps for SymbolVisibility.
+var (
+	SymbolVisibility_name = map[int32]string{
+		0: "VISIBILITY_UNSET",
+		1: "VISIBILITY_LOCAL",
+		2: "VISIBILITY_EXPORT",
+	}
+	SymbolVisibility_value = map[string]int32{
+		"VISIBILITY_UNSET":  0,
+		"VISIBILITY_LOCAL":  1,
+		"VISIBILITY_EXPORT": 2,
+	}
+)
+
+func (x SymbolVisibility) Enum() *SymbolVisibility {
+	p := new(SymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x SymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+}
+
+func (SymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+}
+
+func (x SymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *SymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = SymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use SymbolVisibility.Descriptor instead.
+func (SymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1}
+}
+
 // The verification state of the extension range.
 type ExtensionRangeOptions_VerificationState int32
 
@@ -183,11 +247,11 @@ func (x ExtensionRangeOptions_VerificationState) String() string {
 }
 
 func (ExtensionRangeOptions_VerificationState) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
 }
 
 func (ExtensionRangeOptions_VerificationState) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+	return &file_google_protobuf_descriptor_proto_enumTypes[2]
 }
 
 func (x ExtensionRangeOptions_VerificationState) Number() protoreflect.EnumNumber {
@@ -299,11 +363,11 @@ func (x FieldDescriptorProto_Type) String() string {
 }
 
 func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
 }
 
 func (FieldDescriptorProto_Type) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[2]
+	return &file_google_protobuf_descriptor_proto_enumTypes[3]
 }
 
 func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber {
@@ -362,11 +426,11 @@ func (x FieldDescriptorProto_Label) String() string {
 }
 
 func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
 }
 
 func (FieldDescriptorProto_Label) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[3]
+	return &file_google_protobuf_descriptor_proto_enumTypes[4]
 }
 
 func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber {
@@ -423,11 +487,11 @@ func (x FileOptions_OptimizeMode) String() string {
 }
 
 func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
 }
 
 func (FileOptions_OptimizeMode) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[4]
+	return &file_google_protobuf_descriptor_proto_enumTypes[5]
 }
 
 func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber {
@@ -489,11 +553,11 @@ func (x FieldOptions_CType) String() string {
 }
 
 func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
 }
 
 func (FieldOptions_CType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[5]
+	return &file_google_protobuf_descriptor_proto_enumTypes[6]
 }
 
 func (x FieldOptions_CType) Number() protoreflect.EnumNumber {
@@ -551,11 +615,11 @@ func (x FieldOptions_JSType) String() string {
 }
 
 func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
 }
 
 func (FieldOptions_JSType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[6]
+	return &file_google_protobuf_descriptor_proto_enumTypes[7]
 }
 
 func (x FieldOptions_JSType) Number() protoreflect.EnumNumber {
@@ -611,11 +675,11 @@ func (x FieldOptions_OptionRetention) String() string {
 }
 
 func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
 }
 
 func (FieldOptions_OptionRetention) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[7]
+	return &file_google_protobuf_descriptor_proto_enumTypes[8]
 }
 
 func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber {
@@ -694,11 +758,11 @@ func (x FieldOptions_OptionTargetType) String() string {
 }
 
 func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
 }
 
 func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[8]
+	return &file_google_protobuf_descriptor_proto_enumTypes[9]
 }
 
 func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber {
@@ -756,11 +820,11 @@ func (x MethodOptions_IdempotencyLevel) String() string {
 }
 
 func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
 }
 
 func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[9]
+	return &file_google_protobuf_descriptor_proto_enumTypes[10]
 }
 
 func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber {
@@ -818,11 +882,11 @@ func (x FeatureSet_FieldPresence) String() string {
 }
 
 func (FeatureSet_FieldPresence) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
 }
 
 func (FeatureSet_FieldPresence) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[10]
+	return &file_google_protobuf_descriptor_proto_enumTypes[11]
 }
 
 func (x FeatureSet_FieldPresence) Number() protoreflect.EnumNumber {
@@ -877,11 +941,11 @@ func (x FeatureSet_EnumType) String() string {
 }
 
 func (FeatureSet_EnumType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
 }
 
 func (FeatureSet_EnumType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[11]
+	return &file_google_protobuf_descriptor_proto_enumTypes[12]
 }
 
 func (x FeatureSet_EnumType) Number() protoreflect.EnumNumber {
@@ -936,11 +1000,11 @@ func (x FeatureSet_RepeatedFieldEncoding) String() string {
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[12]
+	return &file_google_protobuf_descriptor_proto_enumTypes[13]
 }
 
 func (x FeatureSet_RepeatedFieldEncoding) Number() protoreflect.EnumNumber {
@@ -995,11 +1059,11 @@ func (x FeatureSet_Utf8Validation) String() string {
 }
 
 func (FeatureSet_Utf8Validation) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
 }
 
 func (FeatureSet_Utf8Validation) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[13]
+	return &file_google_protobuf_descriptor_proto_enumTypes[14]
 }
 
 func (x FeatureSet_Utf8Validation) Number() protoreflect.EnumNumber {
@@ -1054,11 +1118,11 @@ func (x FeatureSet_MessageEncoding) String() string {
 }
 
 func (FeatureSet_MessageEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
 }
 
 func (FeatureSet_MessageEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[14]
+	return &file_google_protobuf_descriptor_proto_enumTypes[15]
 }
 
 func (x FeatureSet_MessageEncoding) Number() protoreflect.EnumNumber {
@@ -1113,11 +1177,11 @@ func (x FeatureSet_JsonFormat) String() string {
 }
 
 func (FeatureSet_JsonFormat) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
 }
 
 func (FeatureSet_JsonFormat) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[15]
+	return &file_google_protobuf_descriptor_proto_enumTypes[16]
 }
 
 func (x FeatureSet_JsonFormat) Number() protoreflect.EnumNumber {
@@ -1172,11 +1236,11 @@ func (x FeatureSet_EnforceNamingStyle) String() string {
 }
 
 func (FeatureSet_EnforceNamingStyle) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
 }
 
 func (FeatureSet_EnforceNamingStyle) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[16]
+	return &file_google_protobuf_descriptor_proto_enumTypes[17]
 }
 
 func (x FeatureSet_EnforceNamingStyle) Number() protoreflect.EnumNumber {
@@ -1198,6 +1262,77 @@ func (FeatureSet_EnforceNamingStyle) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 6}
 }
 
+type FeatureSet_VisibilityFeature_DefaultSymbolVisibility int32
+
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 0
+	// Default pre-EDITION_2024, all UNSET visibility are export.
+	FeatureSet_VisibilityFeature_EXPORT_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 1
+	// All top-level symbols default to export, nested default to local.
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 2
+	// All symbols default to local.
+	FeatureSet_VisibilityFeature_LOCAL_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 3
+	// All symbols local by default. Nested types cannot be exported.
+	// With special case caveat for message { enum {} reserved 1 to max; }
+	// This is the recommended setting for new protos.
+	FeatureSet_VisibilityFeature_STRICT FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 4
+)
+
+// Enum value maps for FeatureSet_VisibilityFeature_DefaultSymbolVisibility.
+var (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_name = map[int32]string{
+		0: "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN",
+		1: "EXPORT_ALL",
+		2: "EXPORT_TOP_LEVEL",
+		3: "LOCAL_ALL",
+		4: "STRICT",
+	}
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_value = map[string]int32{
+		"DEFAULT_SYMBOL_VISIBILITY_UNKNOWN": 0,
+		"EXPORT_ALL":                        1,
+		"EXPORT_TOP_LEVEL":                  2,
+		"LOCAL_ALL":                         3,
+		"STRICT":                            4,
+	}
+)
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Enum() *FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	p := new(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[18].Descriptor()
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[18]
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_VisibilityFeature_DefaultSymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = FeatureSet_VisibilityFeature_DefaultSymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature_DefaultSymbolVisibility.Descriptor instead.
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0, 0}
+}
+
 // Represents the identified object's effect on the element in the original
 // .proto file.
 type GeneratedCodeInfo_Annotation_Semantic int32
@@ -1236,11 +1371,11 @@ func (x GeneratedCodeInfo_Annotation_Semantic) String() string {
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[19].Descriptor()
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[17]
+	return &file_google_protobuf_descriptor_proto_enumTypes[19]
 }
 
 func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber {
@@ -1321,6 +1456,9 @@ type FileDescriptorProto struct {
 	// Indexes of the weak imported files in the dependency list.
 	// For Google-internal migration only. Do not use.
 	WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+	// Names of files imported by this file purely for the purpose of providing
+	// option extensions. These are excluded from the dependency list above.
+	OptionDependency []string `protobuf:"bytes,15,rep,name=option_dependency,json=optionDependency" json:"option_dependency,omitempty"`
 	// All top-level definitions in this file.
 	MessageType []*DescriptorProto        `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
 	EnumType    []*EnumDescriptorProto    `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
@@ -1414,6 +1552,13 @@ func (x *FileDescriptorProto) GetWeakDependency() []int32 {
 	return nil
 }
 
+func (x *FileDescriptorProto) GetOptionDependency() []string {
+	if x != nil {
+		return x.OptionDependency
+	}
+	return nil
+}
+
 func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto {
 	if x != nil {
 		return x.MessageType
@@ -1484,7 +1629,9 @@ type DescriptorProto struct {
 	ReservedRange  []*DescriptorProto_ReservedRange  `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved field names, which may not be used by fields in the same message.
 	// A given name may only be reserved once.
-	ReservedName  []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,11,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1589,6 +1736,13 @@ func (x *DescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *DescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 type ExtensionRangeOptions struct {
 	state protoimpl.MessageState `protogen:"open.v1"`
 	// The parser stores options it doesn't recognize here. See above.
@@ -1901,7 +2055,9 @@ type EnumDescriptorProto struct {
 	ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved enum value names, which may not be reused. A given name may only
 	// be reserved once.
-	ReservedName  []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,6,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1971,6 +2127,13 @@ func (x *EnumDescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *EnumDescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 // Describes a value within an enum.
 type EnumValueDescriptorProto struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
@@ -2710,7 +2873,10 @@ type FieldOptions struct {
 	// for accessors, or it will be completely ignored; in the very least, this
 	// is a formalization for deprecating fields.
 	Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+	// DEPRECATED. DO NOT USE!
 	// For Google-internal migration only. Do not use.
+	//
+	// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 	Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
 	// Indicate that the field value should not be printed out when using debug
 	// formats, e.g. when the field contains sensitive credentials.
@@ -2814,6 +2980,7 @@ func (x *FieldOptions) GetDeprecated() bool {
 	return Default_FieldOptions_Deprecated
 }
 
+// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 func (x *FieldOptions) GetWeak() bool {
 	if x != nil && x.Weak != nil {
 		return *x.Weak
@@ -3392,17 +3559,18 @@ func (x *UninterpretedOption) GetAggregateValue() string {
 // be designed and implemented to handle this, hopefully before we ever hit a
 // conflict here.
 type FeatureSet struct {
-	state                 protoimpl.MessageState            `protogen:"open.v1"`
-	FieldPresence         *FeatureSet_FieldPresence         `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
-	EnumType              *FeatureSet_EnumType              `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
-	RepeatedFieldEncoding *FeatureSet_RepeatedFieldEncoding `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
-	Utf8Validation        *FeatureSet_Utf8Validation        `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
-	MessageEncoding       *FeatureSet_MessageEncoding       `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
-	JsonFormat            *FeatureSet_JsonFormat            `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
-	EnforceNamingStyle    *FeatureSet_EnforceNamingStyle    `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
-	extensionFields       protoimpl.ExtensionFields
-	unknownFields         protoimpl.UnknownFields
-	sizeCache             protoimpl.SizeCache
+	state                   protoimpl.MessageState                                `protogen:"open.v1"`
+	FieldPresence           *FeatureSet_FieldPresence                             `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
+	EnumType                *FeatureSet_EnumType                                  `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
+	RepeatedFieldEncoding   *FeatureSet_RepeatedFieldEncoding                     `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
+	Utf8Validation          *FeatureSet_Utf8Validation                            `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
+	MessageEncoding         *FeatureSet_MessageEncoding                           `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
+	JsonFormat              *FeatureSet_JsonFormat                                `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
+	EnforceNamingStyle      *FeatureSet_EnforceNamingStyle                        `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
+	DefaultSymbolVisibility *FeatureSet_VisibilityFeature_DefaultSymbolVisibility `protobuf:"varint,8,opt,name=default_symbol_visibility,json=defaultSymbolVisibility,enum=google.protobuf.FeatureSet_VisibilityFeature_DefaultSymbolVisibility" json:"default_symbol_visibility,omitempty"`
+	extensionFields         protoimpl.ExtensionFields
+	unknownFields           protoimpl.UnknownFields
+	sizeCache               protoimpl.SizeCache
 }
 
 func (x *FeatureSet) Reset() {
@@ -3484,6 +3652,13 @@ func (x *FeatureSet) GetEnforceNamingStyle() FeatureSet_EnforceNamingStyle {
 	return FeatureSet_ENFORCE_NAMING_STYLE_UNKNOWN
 }
 
+func (x *FeatureSet) GetDefaultSymbolVisibility() FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	if x != nil && x.DefaultSymbolVisibility != nil {
+		return *x.DefaultSymbolVisibility
+	}
+	return FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN
+}
+
 // A compiled specification for the defaults of a set of features.  These
 // messages are generated from FeatureSet extensions and can be used to seed
 // feature resolution. The resolution with this object becomes a simple search
@@ -4144,6 +4319,42 @@ func (x *UninterpretedOption_NamePart) GetIsExtension() bool {
 	return false
 }
 
+type FeatureSet_VisibilityFeature struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *FeatureSet_VisibilityFeature) Reset() {
+	*x = FeatureSet_VisibilityFeature{}
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *FeatureSet_VisibilityFeature) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSet_VisibilityFeature) ProtoMessage() {}
+
+func (x *FeatureSet_VisibilityFeature) ProtoReflect() protoreflect.Message {
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature.ProtoReflect.Descriptor instead.
+func (*FeatureSet_VisibilityFeature) Descriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+}
+
 // A map from every known edition with a unique set of defaults to its
 // defaults. Not all editions may be contained here.  For a given edition,
 // the defaults at the closest matching edition ordered at or before it should
@@ -4161,7 +4372,7 @@ type FeatureSetDefaults_FeatureSetEditionDefault struct {
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() {
 	*x = FeatureSetDefaults_FeatureSetEditionDefault{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4173,7 +4384,7 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string {
 func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {}
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4309,7 +4520,7 @@ type SourceCodeInfo_Location struct {
 
 func (x *SourceCodeInfo_Location) Reset() {
 	*x = SourceCodeInfo_Location{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4321,7 +4532,7 @@ func (x *SourceCodeInfo_Location) String() string {
 func (*SourceCodeInfo_Location) ProtoMessage() {}
 
 func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4393,7 +4604,7 @@ type GeneratedCodeInfo_Annotation struct {
 
 func (x *GeneratedCodeInfo_Annotation) Reset() {
 	*x = GeneratedCodeInfo_Annotation{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4405,7 +4616,7 @@ func (x *GeneratedCodeInfo_Annotation) String() string {
 func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
 
 func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4462,7 +4673,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\n" +
 	" google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"[\n" +
 	"\x11FileDescriptorSet\x128\n" +
-	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\x98\x05\n" +
+	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\xc5\x05\n" +
 	"\x13FileDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
 	"\apackage\x18\x02 \x01(\tR\apackage\x12\x1e\n" +
@@ -4471,7 +4682,8 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"dependency\x12+\n" +
 	"\x11public_dependency\x18\n" +
 	" \x03(\x05R\x10publicDependency\x12'\n" +
-	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12C\n" +
+	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12+\n" +
+	"\x11option_dependency\x18\x0f \x03(\tR\x10optionDependency\x12C\n" +
 	"\fmessage_type\x18\x04 \x03(\v2 .google.protobuf.DescriptorProtoR\vmessageType\x12A\n" +
 	"\tenum_type\x18\x05 \x03(\v2$.google.protobuf.EnumDescriptorProtoR\benumType\x12A\n" +
 	"\aservice\x18\x06 \x03(\v2'.google.protobuf.ServiceDescriptorProtoR\aservice\x12C\n" +
@@ -4479,7 +4691,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\b \x01(\v2\x1c.google.protobuf.FileOptionsR\aoptions\x12I\n" +
 	"\x10source_code_info\x18\t \x01(\v2\x1f.google.protobuf.SourceCodeInfoR\x0esourceCodeInfo\x12\x16\n" +
 	"\x06syntax\x18\f \x01(\tR\x06syntax\x122\n" +
-	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xb9\x06\n" +
+	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xfc\x06\n" +
 	"\x0fDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12;\n" +
 	"\x05field\x18\x02 \x03(\v2%.google.protobuf.FieldDescriptorProtoR\x05field\x12C\n" +
@@ -4493,7 +4705,10 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\a \x01(\v2\x1f.google.protobuf.MessageOptionsR\aoptions\x12U\n" +
 	"\x0ereserved_range\x18\t \x03(\v2..google.protobuf.DescriptorProto.ReservedRangeR\rreservedRange\x12#\n" +
 	"\rreserved_name\x18\n" +
-	" \x03(\tR\freservedName\x1az\n" +
+	" \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\v \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1az\n" +
 	"\x0eExtensionRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\x12@\n" +
@@ -4562,13 +4777,16 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0eLABEL_REQUIRED\x10\x02\"c\n" +
 	"\x14OneofDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x127\n" +
-	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xe3\x02\n" +
+	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xa6\x03\n" +
 	"\x13EnumDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12?\n" +
 	"\x05value\x18\x02 \x03(\v2).google.protobuf.EnumValueDescriptorProtoR\x05value\x126\n" +
 	"\aoptions\x18\x03 \x01(\v2\x1c.google.protobuf.EnumOptionsR\aoptions\x12]\n" +
 	"\x0ereserved_range\x18\x04 \x03(\v26.google.protobuf.EnumDescriptorProto.EnumReservedRangeR\rreservedRange\x12#\n" +
-	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x1a;\n" +
+	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\x06 \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1a;\n" +
 	"\x11EnumReservedRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\"\x83\x01\n" +
@@ -4629,7 +4847,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"&deprecated_legacy_json_field_conflicts\x18\v \x01(\bB\x02\x18\x01R\"deprecatedLegacyJsonFieldConflicts\x127\n" +
 	"\bfeatures\x18\f \x01(\v2\x1b.google.protobuf.FeatureSetR\bfeatures\x12X\n" +
 	"\x14uninterpreted_option\x18\xe7\a \x03(\v2$.google.protobuf.UninterpretedOptionR\x13uninterpretedOption*\t\b\xe8\a\x10\x80\x80\x80\x80\x02J\x04\b\x04\x10\x05J\x04\b\x05\x10\x06J\x04\b\x06\x10\aJ\x04\b\b\x10\tJ\x04\b\t\x10\n" +
-	"\"\x9d\r\n" +
+	"\"\xa1\r\n" +
 	"\fFieldOptions\x12A\n" +
 	"\x05ctype\x18\x01 \x01(\x0e2#.google.protobuf.FieldOptions.CType:\x06STRINGR\x05ctype\x12\x16\n" +
 	"\x06packed\x18\x02 \x01(\bR\x06packed\x12G\n" +
@@ -4638,9 +4856,9 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0funverified_lazy\x18\x0f \x01(\b:\x05falseR\x0eunverifiedLazy\x12%\n" +
 	"\n" +
 	"deprecated\x18\x03 \x01(\b:\x05falseR\n" +
-	"deprecated\x12\x19\n" +
+	"deprecated\x12\x1d\n" +
 	"\x04weak\x18\n" +
-	" \x01(\b:\x05falseR\x04weak\x12(\n" +
+	" \x01(\b:\x05falseB\x02\x18\x01R\x04weak\x12(\n" +
 	"\fdebug_redact\x18\x10 \x01(\b:\x05falseR\vdebugRedact\x12K\n" +
 	"\tretention\x18\x11 \x01(\x0e2-.google.protobuf.FieldOptions.OptionRetentionR\tretention\x12H\n" +
 	"\atargets\x18\x13 \x03(\x0e2..google.protobuf.FieldOptions.OptionTargetTypeR\atargets\x12W\n" +
@@ -4728,7 +4946,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0faggregate_value\x18\b \x01(\tR\x0eaggregateValue\x1aJ\n" +
 	"\bNamePart\x12\x1b\n" +
 	"\tname_part\x18\x01 \x02(\tR\bnamePart\x12!\n" +
-	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\xae\f\n" +
+	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\x8e\x0f\n" +
 	"\n" +
 	"FeatureSet\x12\x91\x01\n" +
 	"\x0efield_presence\x18\x01 \x01(\x0e2).google.protobuf.FeatureSet.FieldPresenceB?\x88\x01\x01\x98\x01\x04\x98\x01\x01\xa2\x01\r\x12\bEXPLICIT\x18\x84\a\xa2\x01\r\x12\bIMPLICIT\x18\xe7\a\xa2\x01\r\x12\bEXPLICIT\x18\xe8\a\xb2\x01\x03\b\xe8\aR\rfieldPresence\x12l\n" +
@@ -4739,7 +4957,18 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\vjson_format\x18\x06 \x01(\x0e2&.google.protobuf.FeatureSet.JsonFormatB9\x88\x01\x01\x98\x01\x03\x98\x01\x06\x98\x01\x01\xa2\x01\x17\x12\x12LEGACY_BEST_EFFORT\x18\x84\a\xa2\x01\n" +
 	"\x12\x05ALLOW\x18\xe7\a\xb2\x01\x03\b\xe8\aR\n" +
 	"jsonFormat\x12\xab\x01\n" +
-	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\"\\\n" +
+	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\x12\xb9\x01\n" +
+	"\x19default_symbol_visibility\x18\b \x01(\x0e2E.google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibilityB6\x88\x01\x02\x98\x01\x01\xa2\x01\x0f\x12\n" +
+	"EXPORT_ALL\x18\x84\a\xa2\x01\x15\x12\x10EXPORT_TOP_LEVEL\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x17defaultSymbolVisibility\x1a\xa1\x01\n" +
+	"\x11VisibilityFeature\"\x81\x01\n" +
+	"\x17DefaultSymbolVisibility\x12%\n" +
+	"!DEFAULT_SYMBOL_VISIBILITY_UNKNOWN\x10\x00\x12\x0e\n" +
+	"\n" +
+	"EXPORT_ALL\x10\x01\x12\x14\n" +
+	"\x10EXPORT_TOP_LEVEL\x10\x02\x12\r\n" +
+	"\tLOCAL_ALL\x10\x03\x12\n" +
+	"\n" +
+	"\x06STRICT\x10\x04J\b\b\x01\x10\x80\x80\x80\x80\x02\"\\\n" +
 	"\rFieldPresence\x12\x1a\n" +
 	"\x16FIELD_PRESENCE_UNKNOWN\x10\x00\x12\f\n" +
 	"\bEXPLICIT\x10\x01\x12\f\n" +
@@ -4817,7 +5046,11 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99998_TEST_ONLY\x10\x9e\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99999_TEST_ONLY\x10\x9f\x8d\x06\x12\x13\n" +
-	"\vEDITION_MAX\x10\xff\xff\xff\xff\aB~\n" +
+	"\vEDITION_MAX\x10\xff\xff\xff\xff\a*U\n" +
+	"\x10SymbolVisibility\x12\x14\n" +
+	"\x10VISIBILITY_UNSET\x10\x00\x12\x14\n" +
+	"\x10VISIBILITY_LOCAL\x10\x01\x12\x15\n" +
+	"\x11VISIBILITY_EXPORT\x10\x02B~\n" +
 	"\x13com.google.protobufB\x10DescriptorProtosH\x01Z-google.golang.org/protobuf/types/descriptorpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection"
 
 var (
@@ -4832,145 +5065,151 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte {
 	return file_google_protobuf_descriptor_proto_rawDescData
 }
 
-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 18)
-var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 20)
+var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
 var file_google_protobuf_descriptor_proto_goTypes = []any{
-	(Edition)(0), // 0: google.protobuf.Edition
-	(ExtensionRangeOptions_VerificationState)(0),        // 1: google.protobuf.ExtensionRangeOptions.VerificationState
-	(FieldDescriptorProto_Type)(0),                      // 2: google.protobuf.FieldDescriptorProto.Type
-	(FieldDescriptorProto_Label)(0),                     // 3: google.protobuf.FieldDescriptorProto.Label
-	(FileOptions_OptimizeMode)(0),                       // 4: google.protobuf.FileOptions.OptimizeMode
-	(FieldOptions_CType)(0),                             // 5: google.protobuf.FieldOptions.CType
-	(FieldOptions_JSType)(0),                            // 6: google.protobuf.FieldOptions.JSType
-	(FieldOptions_OptionRetention)(0),                   // 7: google.protobuf.FieldOptions.OptionRetention
-	(FieldOptions_OptionTargetType)(0),                  // 8: google.protobuf.FieldOptions.OptionTargetType
-	(MethodOptions_IdempotencyLevel)(0),                 // 9: google.protobuf.MethodOptions.IdempotencyLevel
-	(FeatureSet_FieldPresence)(0),                       // 10: google.protobuf.FeatureSet.FieldPresence
-	(FeatureSet_EnumType)(0),                            // 11: google.protobuf.FeatureSet.EnumType
-	(FeatureSet_RepeatedFieldEncoding)(0),               // 12: google.protobuf.FeatureSet.RepeatedFieldEncoding
-	(FeatureSet_Utf8Validation)(0),                      // 13: google.protobuf.FeatureSet.Utf8Validation
-	(FeatureSet_MessageEncoding)(0),                     // 14: google.protobuf.FeatureSet.MessageEncoding
-	(FeatureSet_JsonFormat)(0),                          // 15: google.protobuf.FeatureSet.JsonFormat
-	(FeatureSet_EnforceNamingStyle)(0),                  // 16: google.protobuf.FeatureSet.EnforceNamingStyle
-	(GeneratedCodeInfo_Annotation_Semantic)(0),          // 17: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	(*FileDescriptorSet)(nil),                           // 18: google.protobuf.FileDescriptorSet
-	(*FileDescriptorProto)(nil),                         // 19: google.protobuf.FileDescriptorProto
-	(*DescriptorProto)(nil),                             // 20: google.protobuf.DescriptorProto
-	(*ExtensionRangeOptions)(nil),                       // 21: google.protobuf.ExtensionRangeOptions
-	(*FieldDescriptorProto)(nil),                        // 22: google.protobuf.FieldDescriptorProto
-	(*OneofDescriptorProto)(nil),                        // 23: google.protobuf.OneofDescriptorProto
-	(*EnumDescriptorProto)(nil),                         // 24: google.protobuf.EnumDescriptorProto
-	(*EnumValueDescriptorProto)(nil),                    // 25: google.protobuf.EnumValueDescriptorProto
-	(*ServiceDescriptorProto)(nil),                      // 26: google.protobuf.ServiceDescriptorProto
-	(*MethodDescriptorProto)(nil),                       // 27: google.protobuf.MethodDescriptorProto
-	(*FileOptions)(nil),                                 // 28: google.protobuf.FileOptions
-	(*MessageOptions)(nil),                              // 29: google.protobuf.MessageOptions
-	(*FieldOptions)(nil),                                // 30: google.protobuf.FieldOptions
-	(*OneofOptions)(nil),                                // 31: google.protobuf.OneofOptions
-	(*EnumOptions)(nil),                                 // 32: google.protobuf.EnumOptions
-	(*EnumValueOptions)(nil),                            // 33: google.protobuf.EnumValueOptions
-	(*ServiceOptions)(nil),                              // 34: google.protobuf.ServiceOptions
-	(*MethodOptions)(nil),                               // 35: google.protobuf.MethodOptions
-	(*UninterpretedOption)(nil),                         // 36: google.protobuf.UninterpretedOption
-	(*FeatureSet)(nil),                                  // 37: google.protobuf.FeatureSet
-	(*FeatureSetDefaults)(nil),                          // 38: google.protobuf.FeatureSetDefaults
-	(*SourceCodeInfo)(nil),                              // 39: google.protobuf.SourceCodeInfo
-	(*GeneratedCodeInfo)(nil),                           // 40: google.protobuf.GeneratedCodeInfo
-	(*DescriptorProto_ExtensionRange)(nil),              // 41: google.protobuf.DescriptorProto.ExtensionRange
-	(*DescriptorProto_ReservedRange)(nil),               // 42: google.protobuf.DescriptorProto.ReservedRange
-	(*ExtensionRangeOptions_Declaration)(nil),           // 43: google.protobuf.ExtensionRangeOptions.Declaration
-	(*EnumDescriptorProto_EnumReservedRange)(nil),       // 44: google.protobuf.EnumDescriptorProto.EnumReservedRange
-	(*FieldOptions_EditionDefault)(nil),                 // 45: google.protobuf.FieldOptions.EditionDefault
-	(*FieldOptions_FeatureSupport)(nil),                 // 46: google.protobuf.FieldOptions.FeatureSupport
-	(*UninterpretedOption_NamePart)(nil),                // 47: google.protobuf.UninterpretedOption.NamePart
-	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 48: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	(*SourceCodeInfo_Location)(nil),                     // 49: google.protobuf.SourceCodeInfo.Location
-	(*GeneratedCodeInfo_Annotation)(nil),                // 50: google.protobuf.GeneratedCodeInfo.Annotation
+	(Edition)(0),          // 0: google.protobuf.Edition
+	(SymbolVisibility)(0), // 1: google.protobuf.SymbolVisibility
+	(ExtensionRangeOptions_VerificationState)(0),              // 2: google.protobuf.ExtensionRangeOptions.VerificationState
+	(FieldDescriptorProto_Type)(0),                            // 3: google.protobuf.FieldDescriptorProto.Type
+	(FieldDescriptorProto_Label)(0),                           // 4: google.protobuf.FieldDescriptorProto.Label
+	(FileOptions_OptimizeMode)(0),                             // 5: google.protobuf.FileOptions.OptimizeMode
+	(FieldOptions_CType)(0),                                   // 6: google.protobuf.FieldOptions.CType
+	(FieldOptions_JSType)(0),                                  // 7: google.protobuf.FieldOptions.JSType
+	(FieldOptions_OptionRetention)(0),                         // 8: google.protobuf.FieldOptions.OptionRetention
+	(FieldOptions_OptionTargetType)(0),                        // 9: google.protobuf.FieldOptions.OptionTargetType
+	(MethodOptions_IdempotencyLevel)(0),                       // 10: google.protobuf.MethodOptions.IdempotencyLevel
+	(FeatureSet_FieldPresence)(0),                             // 11: google.protobuf.FeatureSet.FieldPresence
+	(FeatureSet_EnumType)(0),                                  // 12: google.protobuf.FeatureSet.EnumType
+	(FeatureSet_RepeatedFieldEncoding)(0),                     // 13: google.protobuf.FeatureSet.RepeatedFieldEncoding
+	(FeatureSet_Utf8Validation)(0),                            // 14: google.protobuf.FeatureSet.Utf8Validation
+	(FeatureSet_MessageEncoding)(0),                           // 15: google.protobuf.FeatureSet.MessageEncoding
+	(FeatureSet_JsonFormat)(0),                                // 16: google.protobuf.FeatureSet.JsonFormat
+	(FeatureSet_EnforceNamingStyle)(0),                        // 17: google.protobuf.FeatureSet.EnforceNamingStyle
+	(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)(0), // 18: google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	(GeneratedCodeInfo_Annotation_Semantic)(0),                // 19: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	(*FileDescriptorSet)(nil),                                 // 20: google.protobuf.FileDescriptorSet
+	(*FileDescriptorProto)(nil),                               // 21: google.protobuf.FileDescriptorProto
+	(*DescriptorProto)(nil),                                   // 22: google.protobuf.DescriptorProto
+	(*ExtensionRangeOptions)(nil),                             // 23: google.protobuf.ExtensionRangeOptions
+	(*FieldDescriptorProto)(nil),                              // 24: google.protobuf.FieldDescriptorProto
+	(*OneofDescriptorProto)(nil),                              // 25: google.protobuf.OneofDescriptorProto
+	(*EnumDescriptorProto)(nil),                               // 26: google.protobuf.EnumDescriptorProto
+	(*EnumValueDescriptorProto)(nil),                          // 27: google.protobuf.EnumValueDescriptorProto
+	(*ServiceDescriptorProto)(nil),                            // 28: google.protobuf.ServiceDescriptorProto
+	(*MethodDescriptorProto)(nil),                             // 29: google.protobuf.MethodDescriptorProto
+	(*FileOptions)(nil),                                       // 30: google.protobuf.FileOptions
+	(*MessageOptions)(nil),                                    // 31: google.protobuf.MessageOptions
+	(*FieldOptions)(nil),                                      // 32: google.protobuf.FieldOptions
+	(*OneofOptions)(nil),                                      // 33: google.protobuf.OneofOptions
+	(*EnumOptions)(nil),                                       // 34: google.protobuf.EnumOptions
+	(*EnumValueOptions)(nil),                                  // 35: google.protobuf.EnumValueOptions
+	(*ServiceOptions)(nil),                                    // 36: google.protobuf.ServiceOptions
+	(*MethodOptions)(nil),                                     // 37: google.protobuf.MethodOptions
+	(*UninterpretedOption)(nil),                               // 38: google.protobuf.UninterpretedOption
+	(*FeatureSet)(nil),                                        // 39: google.protobuf.FeatureSet
+	(*FeatureSetDefaults)(nil),                                // 40: google.protobuf.FeatureSetDefaults
+	(*SourceCodeInfo)(nil),                                    // 41: google.protobuf.SourceCodeInfo
+	(*GeneratedCodeInfo)(nil),                                 // 42: google.protobuf.GeneratedCodeInfo
+	(*DescriptorProto_ExtensionRange)(nil),                    // 43: google.protobuf.DescriptorProto.ExtensionRange
+	(*DescriptorProto_ReservedRange)(nil),                     // 44: google.protobuf.DescriptorProto.ReservedRange
+	(*ExtensionRangeOptions_Declaration)(nil),                 // 45: google.protobuf.ExtensionRangeOptions.Declaration
+	(*EnumDescriptorProto_EnumReservedRange)(nil),             // 46: google.protobuf.EnumDescriptorProto.EnumReservedRange
+	(*FieldOptions_EditionDefault)(nil),                       // 47: google.protobuf.FieldOptions.EditionDefault
+	(*FieldOptions_FeatureSupport)(nil),                       // 48: google.protobuf.FieldOptions.FeatureSupport
+	(*UninterpretedOption_NamePart)(nil),                      // 49: google.protobuf.UninterpretedOption.NamePart
+	(*FeatureSet_VisibilityFeature)(nil),                      // 50: google.protobuf.FeatureSet.VisibilityFeature
+	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil),       // 51: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	(*SourceCodeInfo_Location)(nil),                           // 52: google.protobuf.SourceCodeInfo.Location
+	(*GeneratedCodeInfo_Annotation)(nil),                      // 53: google.protobuf.GeneratedCodeInfo.Annotation
 }
 var file_google_protobuf_descriptor_proto_depIdxs = []int32{
-	19, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
-	20, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
-	24, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	26, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
-	22, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	28, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
-	39, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
+	21, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
+	22, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
+	26, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	28, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
+	24, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	30, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
+	41, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
 	0,  // 7: google.protobuf.FileDescriptorProto.edition:type_name -> google.protobuf.Edition
-	22, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
-	22, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	20, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
-	24, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	41, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
-	23, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
-	29, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
-	42, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
-	36, // 16: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	43, // 17: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
-	37, // 18: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
-	1,  // 19: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
-	3,  // 20: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
-	2,  // 21: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
-	30, // 22: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
-	31, // 23: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
-	25, // 24: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
-	32, // 25: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
-	44, // 26: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
-	33, // 27: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
-	27, // 28: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
-	34, // 29: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
-	35, // 30: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
-	4,  // 31: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
-	37, // 32: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 33: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 34: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 35: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	5,  // 36: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
-	6,  // 37: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
-	7,  // 38: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
-	8,  // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
-	45, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
-	37, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	9,  // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
-	37, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	47, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
-	10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
-	11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
-	12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
-	13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
-	14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
-	15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
-	16, // 63: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
-	48, // 64: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	0,  // 65: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
-	0,  // 66: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
-	49, // 67: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
-	50, // 68: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
-	21, // 69: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
-	0,  // 70: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
-	0,  // 71: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
-	0,  // 72: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
-	0,  // 73: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
-	0,  // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
-	37, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
-	37, // 76: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
-	17, // 77: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	78, // [78:78] is the sub-list for method output_type
-	78, // [78:78] is the sub-list for method input_type
-	78, // [78:78] is the sub-list for extension type_name
-	78, // [78:78] is the sub-list for extension extendee
-	0,  // [0:78] is the sub-list for field type_name
+	24, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
+	24, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	22, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
+	26, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	43, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
+	25, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
+	31, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
+	44, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
+	1,  // 16: google.protobuf.DescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	38, // 17: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	45, // 18: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
+	39, // 19: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
+	2,  // 20: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
+	4,  // 21: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
+	3,  // 22: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
+	32, // 23: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
+	33, // 24: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
+	27, // 25: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
+	34, // 26: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
+	46, // 27: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
+	1,  // 28: google.protobuf.EnumDescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	35, // 29: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
+	29, // 30: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
+	36, // 31: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
+	37, // 32: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
+	5,  // 33: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
+	39, // 34: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 35: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 36: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 37: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	6,  // 38: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
+	7,  // 39: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
+	8,  // 40: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
+	9,  // 41: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
+	47, // 42: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
+	39, // 43: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 44: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 45: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 46: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 47: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 48: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 49: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 50: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 51: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 52: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 53: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 54: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	10, // 55: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
+	39, // 56: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 57: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	49, // 58: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
+	11, // 59: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
+	12, // 60: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
+	13, // 61: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
+	14, // 62: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
+	15, // 63: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
+	16, // 64: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
+	17, // 65: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
+	18, // 66: google.protobuf.FeatureSet.default_symbol_visibility:type_name -> google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	51, // 67: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	0,  // 68: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
+	0,  // 69: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
+	52, // 70: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
+	53, // 71: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
+	23, // 72: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
+	0,  // 73: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
+	0,  // 74: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
+	0,  // 75: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
+	0,  // 76: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
+	0,  // 77: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
+	39, // 78: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
+	39, // 79: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
+	19, // 80: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	81, // [81:81] is the sub-list for method output_type
+	81, // [81:81] is the sub-list for method input_type
+	81, // [81:81] is the sub-list for extension type_name
+	81, // [81:81] is the sub-list for extension extendee
+	0,  // [0:81] is the sub-list for field type_name
 }
 
 func init() { file_google_protobuf_descriptor_proto_init() }
@@ -4983,8 +5222,8 @@ func file_google_protobuf_descriptor_proto_init() {
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_protobuf_descriptor_proto_rawDesc), len(file_google_protobuf_descriptor_proto_rawDesc)),
-			NumEnums:      18,
-			NumMessages:   33,
+			NumEnums:      20,
+			NumMessages:   34,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/notifier/vendor/gopkg.in/ini.v1/.editorconfig b/notifier/vendor/gopkg.in/ini.v1/.editorconfig
deleted file mode 100644
index 4a2d9180..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# http://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*_test.go]
-trim_trailing_whitespace = false
diff --git a/notifier/vendor/gopkg.in/ini.v1/.gitignore b/notifier/vendor/gopkg.in/ini.v1/.gitignore
deleted file mode 100644
index 588388bd..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-testdata/conf_out.ini
-ini.sublime-project
-ini.sublime-workspace
-testdata/conf_reflect.ini
-.idea
-/.vscode
-.DS_Store
diff --git a/notifier/vendor/gopkg.in/ini.v1/.golangci.yml b/notifier/vendor/gopkg.in/ini.v1/.golangci.yml
deleted file mode 100644
index 631e3692..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/.golangci.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-linters-settings:
-  staticcheck:
-    checks: [
-      "all",
-      "-SA1019" # There are valid use cases of strings.Title
-    ]
-  nakedret:
-    max-func-lines: 0 # Disallow any unnamed return statement
-
-linters:
-  enable:
-    - deadcode
-    - errcheck
-    - gosimple
-    - govet
-    - ineffassign
-    - staticcheck
-    - structcheck
-    - typecheck
-    - unused
-    - varcheck
-    - nakedret
-    - gofmt
-    - rowserrcheck
-    - unconvert
-    - goimports
-    - unparam
diff --git a/notifier/vendor/gopkg.in/ini.v1/LICENSE b/notifier/vendor/gopkg.in/ini.v1/LICENSE
deleted file mode 100644
index d361bbcd..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the Work and such
-Derivative Works in Source or Object form.
-
-3. Grant of Patent License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable (except as stated in this section) patent license to make, have
-made, use, offer to sell, sell, import, and otherwise transfer the Work, where
-such license applies only to those patent claims licensable by such Contributor
-that are necessarily infringed by their Contribution(s) alone or by combination
-of their Contribution(s) with the Work to which such Contribution(s) was
-submitted. If You institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work or a
-Contribution incorporated within the Work constitutes direct or contributory
-patent infringement, then any patent licenses granted to You under this License
-for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.
-
-You may reproduce and distribute copies of the Work or Derivative Works thereof
-in any medium, with or without modifications, and in Source or Object form,
-provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of
-this License; and
-You must cause any modified files to carry prominent notices stating that You
-changed the files; and
-You must retain, in the Source form of any Derivative Works that You distribute,
-all copyright, patent, trademark, and attribution notices from the Source form
-of the Work, excluding those notices that do not pertain to any part of the
-Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any
-Derivative Works that You distribute must include a readable copy of the
-attribution notices contained within such NOTICE file, excluding those notices
-that do not pertain to any part of the Derivative Works, in at least one of the
-following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions.
-
-Unless You explicitly state otherwise, any Contribution intentionally submitted
-for inclusion in the Work by You to the Licensor shall be under the terms and
-conditions of this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify the terms of
-any separate license agreement you may have executed with Licensor regarding
-such Contributions.
-
-6. Trademarks.
-
-This License does not grant permission to use the trade names, trademarks,
-service marks, or product names of the Licensor, except as required for
-reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty.
-
-Unless required by applicable law or agreed to in writing, Licensor provides the
-Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
-including, without limitation, any warranties or conditions of TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
-solely responsible for determining the appropriateness of using or
-redistributing the Work and assume any risks associated with Your exercise of
-permissions under this License.
-
-8. Limitation of Liability.
-
-In no event and under no legal theory, whether in tort (including negligence),
-contract, or otherwise, unless required by applicable law (such as deliberate
-and grossly negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special, incidental,
-or consequential damages of any character arising as a result of this License or
-out of the use or inability to use the Work (including but not limited to
-damages for loss of goodwill, work stoppage, computer failure or malfunction, or
-any and all other commercial damages or losses), even if such Contributor has
-been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability.
-
-While redistributing the Work or Derivative Works thereof, You may choose to
-offer, and charge a fee for, acceptance of support, warranty, indemnity, or
-other liability obligations and/or rights consistent with this License. However,
-in accepting such obligations, You may act only on Your own behalf and on Your
-sole responsibility, not on behalf of any other Contributor, and only if You
-agree to indemnify, defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason of your
-accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work
-
-To apply the Apache License to your work, attach the following boilerplate
-notice, with the fields enclosed by brackets "[]" replaced with your own
-identifying information. (Don't include the brackets!) The text should be
-enclosed in the appropriate comment syntax for the file format. We also
-recommend that a file or class name and description of purpose be included on
-the same "printed page" as the copyright notice for easier identification within
-third-party archives.
-
-   Copyright 2014 Unknwon
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/notifier/vendor/gopkg.in/ini.v1/Makefile b/notifier/vendor/gopkg.in/ini.v1/Makefile
deleted file mode 100644
index f3b0dae2..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-.PHONY: build test bench vet coverage
-
-build: vet bench
-
-test:
-	go test -v -cover -race
-
-bench:
-	go test -v -cover -test.bench=. -test.benchmem
-
-vet:
-	go vet
-
-coverage:
-	go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
diff --git a/notifier/vendor/gopkg.in/ini.v1/README.md b/notifier/vendor/gopkg.in/ini.v1/README.md
deleted file mode 100644
index 30606d97..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# INI
-
-[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain)
-[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini)
-[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc)
-[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini)
-
-![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
-
-Package ini provides INI file read and write functionality in Go.
-
-## Features
-
-- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites.
-- Read with recursion values.
-- Read with parent-child sections.
-- Read with auto-increment key names.
-- Read with multiple-line values.
-- Read with tons of helper methods.
-- Read and convert values to Go types.
-- Read and **WRITE** comments of sections and keys.
-- Manipulate sections, keys and comments with ease.
-- Keep sections and keys in order as you parse and save.
-
-## Installation
-
-The minimum requirement of Go is **1.13**.
-
-```sh
-$ go get gopkg.in/ini.v1
-```
-
-Please add `-u` flag to update in the future.
-
-## Getting Help
-
-- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started)
-- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
-- 中国大陆镜像:https://ini.unknwon.cn
-
-## License
-
-This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
diff --git a/notifier/vendor/gopkg.in/ini.v1/codecov.yml b/notifier/vendor/gopkg.in/ini.v1/codecov.yml
deleted file mode 100644
index e02ec84b..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/codecov.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-coverage:
-  range: "60...95"
-  status:
-    project:
-      default:
-        threshold: 1%
-        informational: true
-    patch:
-      defualt:
-        only_pulls: true
-        informational: true
-
-comment:
-  layout: 'diff'
-
-github_checks: false
diff --git a/notifier/vendor/gopkg.in/ini.v1/data_source.go b/notifier/vendor/gopkg.in/ini.v1/data_source.go
deleted file mode 100644
index c3a541f1..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/data_source.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-)
-
-var (
-	_ dataSource = (*sourceFile)(nil)
-	_ dataSource = (*sourceData)(nil)
-	_ dataSource = (*sourceReadCloser)(nil)
-)
-
-// dataSource is an interface that returns object which can be read and closed.
-type dataSource interface {
-	ReadCloser() (io.ReadCloser, error)
-}
-
-// sourceFile represents an object that contains content on the local file system.
-type sourceFile struct {
-	name string
-}
-
-func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
-	return os.Open(s.name)
-}
-
-// sourceData represents an object that contains content in memory.
-type sourceData struct {
-	data []byte
-}
-
-func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewReader(s.data)), nil
-}
-
-// sourceReadCloser represents an input stream with Close method.
-type sourceReadCloser struct {
-	reader io.ReadCloser
-}
-
-func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
-	return s.reader, nil
-}
-
-func parseDataSource(source interface{}) (dataSource, error) {
-	switch s := source.(type) {
-	case string:
-		return sourceFile{s}, nil
-	case []byte:
-		return &sourceData{s}, nil
-	case io.ReadCloser:
-		return &sourceReadCloser{s}, nil
-	case io.Reader:
-		return &sourceReadCloser{ioutil.NopCloser(s)}, nil
-	default:
-		return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
-	}
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/deprecated.go b/notifier/vendor/gopkg.in/ini.v1/deprecated.go
deleted file mode 100644
index 48b8e66d..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/deprecated.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-var (
-	// Deprecated: Use "DefaultSection" instead.
-	DEFAULT_SECTION = DefaultSection
-	// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
-	AllCapsUnderscore = SnackCase
-)
diff --git a/notifier/vendor/gopkg.in/ini.v1/error.go b/notifier/vendor/gopkg.in/ini.v1/error.go
deleted file mode 100644
index f66bc94b..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/error.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"fmt"
-)
-
-// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
-type ErrDelimiterNotFound struct {
-	Line string
-}
-
-// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
-func IsErrDelimiterNotFound(err error) bool {
-	_, ok := err.(ErrDelimiterNotFound)
-	return ok
-}
-
-func (err ErrDelimiterNotFound) Error() string {
-	return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
-}
-
-// ErrEmptyKeyName indicates the error type of no key name is found which there should be one.
-type ErrEmptyKeyName struct {
-	Line string
-}
-
-// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName.
-func IsErrEmptyKeyName(err error) bool {
-	_, ok := err.(ErrEmptyKeyName)
-	return ok
-}
-
-func (err ErrEmptyKeyName) Error() string {
-	return fmt.Sprintf("empty key name: %s", err.Line)
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/file.go b/notifier/vendor/gopkg.in/ini.v1/file.go
deleted file mode 100644
index f8b22408..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/file.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2017 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"sync"
-)
-
-// File represents a combination of one or more INI files in memory.
-type File struct {
-	options     LoadOptions
-	dataSources []dataSource
-
-	// Should make things safe, but sometimes doesn't matter.
-	BlockMode bool
-	lock      sync.RWMutex
-
-	// To keep data in order.
-	sectionList []string
-	// To keep track of the index of a section with same name.
-	// This meta list is only used with non-unique section names are allowed.
-	sectionIndexes []int
-
-	// Actual data is stored here.
-	sections map[string][]*Section
-
-	NameMapper
-	ValueMapper
-}
-
-// newFile initializes File object with given data sources.
-func newFile(dataSources []dataSource, opts LoadOptions) *File {
-	if len(opts.KeyValueDelimiters) == 0 {
-		opts.KeyValueDelimiters = "=:"
-	}
-	if len(opts.KeyValueDelimiterOnWrite) == 0 {
-		opts.KeyValueDelimiterOnWrite = "="
-	}
-	if len(opts.ChildSectionDelimiter) == 0 {
-		opts.ChildSectionDelimiter = "."
-	}
-
-	return &File{
-		BlockMode:   true,
-		dataSources: dataSources,
-		sections:    make(map[string][]*Section),
-		options:     opts,
-	}
-}
-
-// Empty returns an empty file object.
-func Empty(opts ...LoadOptions) *File {
-	var opt LoadOptions
-	if len(opts) > 0 {
-		opt = opts[0]
-	}
-
-	// Ignore error here, we are sure our data is good.
-	f, _ := LoadSources(opt, []byte(""))
-	return f
-}
-
-// NewSection creates a new section.
-func (f *File) NewSection(name string) (*Section, error) {
-	if len(name) == 0 {
-		return nil, errors.New("empty section name")
-	}
-
-	if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) {
-		return f.sections[name][0], nil
-	}
-
-	f.sectionList = append(f.sectionList, name)
-
-	// NOTE: Append to indexes must happen before appending to sections,
-	// otherwise index will have off-by-one problem.
-	f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name]))
-
-	sec := newSection(f, name)
-	f.sections[name] = append(f.sections[name], sec)
-
-	return sec, nil
-}
-
-// NewRawSection creates a new section with an unparseable body.
-func (f *File) NewRawSection(name, body string) (*Section, error) {
-	section, err := f.NewSection(name)
-	if err != nil {
-		return nil, err
-	}
-
-	section.isRawSection = true
-	section.rawBody = body
-	return section, nil
-}
-
-// NewSections creates a list of sections.
-func (f *File) NewSections(names ...string) (err error) {
-	for _, name := range names {
-		if _, err = f.NewSection(name); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// GetSection returns section by given name.
-func (f *File) GetSection(name string) (*Section, error) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return nil, err
-	}
-
-	return secs[0], err
-}
-
-// HasSection returns true if the file contains a section with given name.
-func (f *File) HasSection(name string) bool {
-	section, _ := f.GetSection(name)
-	return section != nil
-}
-
-// SectionsByName returns all sections with given name.
-func (f *File) SectionsByName(name string) ([]*Section, error) {
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	secs := f.sections[name]
-	if len(secs) == 0 {
-		return nil, fmt.Errorf("section %q does not exist", name)
-	}
-
-	return secs, nil
-}
-
-// Section assumes named section exists and returns a zero-value when not.
-func (f *File) Section(name string) *Section {
-	sec, err := f.GetSection(name)
-	if err != nil {
-		if name == "" {
-			name = DefaultSection
-		}
-		sec, _ = f.NewSection(name)
-		return sec
-	}
-	return sec
-}
-
-// SectionWithIndex assumes named section exists and returns a new section when not.
-func (f *File) SectionWithIndex(name string, index int) *Section {
-	secs, err := f.SectionsByName(name)
-	if err != nil || len(secs) <= index {
-		// NOTE: It's OK here because the only possible error is empty section name,
-		// but if it's empty, this piece of code won't be executed.
-		newSec, _ := f.NewSection(name)
-		return newSec
-	}
-
-	return secs[index]
-}
-
-// Sections returns a list of Section stored in the current instance.
-func (f *File) Sections() []*Section {
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	sections := make([]*Section, len(f.sectionList))
-	for i, name := range f.sectionList {
-		sections[i] = f.sections[name][f.sectionIndexes[i]]
-	}
-	return sections
-}
-
-// ChildSections returns a list of child sections of given section name.
-func (f *File) ChildSections(name string) []*Section {
-	return f.Section(name).ChildSections()
-}
-
-// SectionStrings returns list of section names.
-func (f *File) SectionStrings() []string {
-	list := make([]string, len(f.sectionList))
-	copy(list, f.sectionList)
-	return list
-}
-
-// DeleteSection deletes a section or all sections with given name.
-func (f *File) DeleteSection(name string) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(secs); i++ {
-		// For non-unique sections, it is always needed to remove the first one so
-		// in the next iteration, the subsequent section continue having index 0.
-		// Ignoring the error as index 0 never returns an error.
-		_ = f.DeleteSectionWithIndex(name, 0)
-	}
-}
-
-// DeleteSectionWithIndex deletes a section with given name and index.
-func (f *File) DeleteSectionWithIndex(name string, index int) error {
-	if !f.options.AllowNonUniqueSections && index != 0 {
-		return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled")
-	}
-
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	// Count occurrences of the sections
-	occurrences := 0
-
-	sectionListCopy := make([]string, len(f.sectionList))
-	copy(sectionListCopy, f.sectionList)
-
-	for i, s := range sectionListCopy {
-		if s != name {
-			continue
-		}
-
-		if occurrences == index {
-			if len(f.sections[name]) <= 1 {
-				delete(f.sections, name) // The last one in the map
-			} else {
-				f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...)
-			}
-
-			// Fix section lists
-			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
-			f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...)
-
-		} else if occurrences > index {
-			// Fix the indices of all following sections with this name.
-			f.sectionIndexes[i-1]--
-		}
-
-		occurrences++
-	}
-
-	return nil
-}
-
-func (f *File) reload(s dataSource) error {
-	r, err := s.ReadCloser()
-	if err != nil {
-		return err
-	}
-	defer r.Close()
-
-	return f.parse(r)
-}
-
-// Reload reloads and parses all data sources.
-func (f *File) Reload() (err error) {
-	for _, s := range f.dataSources {
-		if err = f.reload(s); err != nil {
-			// In loose mode, we create an empty default section for nonexistent files.
-			if os.IsNotExist(err) && f.options.Loose {
-				_ = f.parse(bytes.NewBuffer(nil))
-				continue
-			}
-			return err
-		}
-		if f.options.ShortCircuit {
-			return nil
-		}
-	}
-	return nil
-}
-
-// Append appends one or more data sources and reloads automatically.
-func (f *File) Append(source interface{}, others ...interface{}) error {
-	ds, err := parseDataSource(source)
-	if err != nil {
-		return err
-	}
-	f.dataSources = append(f.dataSources, ds)
-	for _, s := range others {
-		ds, err = parseDataSource(s)
-		if err != nil {
-			return err
-		}
-		f.dataSources = append(f.dataSources, ds)
-	}
-	return f.Reload()
-}
-
-func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
-	equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight
-
-	if PrettyFormat || PrettyEqual {
-		equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite)
-	}
-
-	// Use buffer to make sure target is safe until finish encoding.
-	buf := bytes.NewBuffer(nil)
-	lastSectionIdx := len(f.sectionList) - 1
-	for i, sname := range f.sectionList {
-		sec := f.SectionWithIndex(sname, f.sectionIndexes[i])
-		if len(sec.Comment) > 0 {
-			// Support multiline comments
-			lines := strings.Split(sec.Comment, LineBreak)
-			for i := range lines {
-				if lines[i][0] != '#' && lines[i][0] != ';' {
-					lines[i] = "; " + lines[i]
-				} else {
-					lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-				}
-
-				if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) {
-			if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
-				return nil, err
-			}
-		} else {
-			// Write nothing if default section is empty
-			if len(sec.keyList) == 0 {
-				continue
-			}
-		}
-
-		isLastSection := i == lastSectionIdx
-		if sec.isRawSection {
-			if _, err := buf.WriteString(sec.rawBody); err != nil {
-				return nil, err
-			}
-
-			if PrettySection && !isLastSection {
-				// Put a line between sections
-				if _, err := buf.WriteString(LineBreak); err != nil {
-					return nil, err
-				}
-			}
-			continue
-		}
-
-		// Count and generate alignment length and buffer spaces using the
-		// longest key. Keys may be modified if they contain certain characters so
-		// we need to take that into account in our calculation.
-		alignLength := 0
-		if PrettyFormat {
-			for _, kname := range sec.keyList {
-				keyLength := len(kname)
-				// First case will surround key by ` and second by """
-				if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) {
-					keyLength += 2
-				} else if strings.Contains(kname, "`") {
-					keyLength += 6
-				}
-
-				if keyLength > alignLength {
-					alignLength = keyLength
-				}
-			}
-		}
-		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
-
-	KeyList:
-		for _, kname := range sec.keyList {
-			key := sec.Key(kname)
-			if len(key.Comment) > 0 {
-				if len(indent) > 0 && sname != DefaultSection {
-					buf.WriteString(indent)
-				}
-
-				// Support multiline comments
-				lines := strings.Split(key.Comment, LineBreak)
-				for i := range lines {
-					if lines[i][0] != '#' && lines[i][0] != ';' {
-						lines[i] = "; " + strings.TrimSpace(lines[i])
-					} else {
-						lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-					}
-
-					if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-						return nil, err
-					}
-				}
-			}
-
-			if len(indent) > 0 && sname != DefaultSection {
-				buf.WriteString(indent)
-			}
-
-			switch {
-			case key.isAutoIncrement:
-				kname = "-"
-			case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters):
-				kname = "`" + kname + "`"
-			case strings.Contains(kname, "`"):
-				kname = `"""` + kname + `"""`
-			}
-
-			writeKeyValue := func(val string) (bool, error) {
-				if _, err := buf.WriteString(kname); err != nil {
-					return false, err
-				}
-
-				if key.isBooleanType {
-					buf.WriteString(LineBreak)
-					return true, nil
-				}
-
-				// Write out alignment spaces before "=" sign
-				if PrettyFormat {
-					buf.Write(alignSpaces[:alignLength-len(kname)])
-				}
-
-				// In case key value contains "\n", "`", "\"", "#" or ";"
-				if strings.ContainsAny(val, "\n`") {
-					val = `"""` + val + `"""`
-				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
-					val = "`" + val + "`"
-				} else if len(strings.TrimSpace(val)) != len(val) {
-					val = `"` + val + `"`
-				}
-				if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
-					return false, err
-				}
-				return false, nil
-			}
-
-			shadows := key.ValueWithShadows()
-			if len(shadows) == 0 {
-				if _, err := writeKeyValue(""); err != nil {
-					return nil, err
-				}
-			}
-
-			for _, val := range shadows {
-				exitLoop, err := writeKeyValue(val)
-				if err != nil {
-					return nil, err
-				} else if exitLoop {
-					continue KeyList
-				}
-			}
-
-			for _, val := range key.nestedValues {
-				if _, err := buf.WriteString(indent + "  " + val + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if PrettySection && !isLastSection {
-			// Put a line between sections
-			if _, err := buf.WriteString(LineBreak); err != nil {
-				return nil, err
-			}
-		}
-	}
-
-	return buf, nil
-}
-
-// WriteToIndent writes content into io.Writer with given indention.
-// If PrettyFormat has been set to be true,
-// it will align "=" sign with spaces under each section.
-func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return 0, err
-	}
-	return buf.WriteTo(w)
-}
-
-// WriteTo writes file content into io.Writer.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
-	return f.WriteToIndent(w, "")
-}
-
-// SaveToIndent writes content to file system with given value indention.
-func (f *File) SaveToIndent(filename, indent string) error {
-	// Note: Because we are truncating with os.Create,
-	// 	so it's safer to save to a temporary file location and rename after done.
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return err
-	}
-
-	return ioutil.WriteFile(filename, buf.Bytes(), 0666)
-}
-
-// SaveTo writes content to file system.
-func (f *File) SaveTo(filename string) error {
-	return f.SaveToIndent(filename, "")
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/helper.go b/notifier/vendor/gopkg.in/ini.v1/helper.go
deleted file mode 100644
index f9d80a68..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/helper.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-func inSlice(str string, s []string) bool {
-	for _, v := range s {
-		if str == v {
-			return true
-		}
-	}
-	return false
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/ini.go b/notifier/vendor/gopkg.in/ini.v1/ini.go
deleted file mode 100644
index 99e7f865..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/ini.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-// Package ini provides INI file read and write functionality in Go.
-package ini
-
-import (
-	"os"
-	"regexp"
-	"runtime"
-	"strings"
-)
-
-const (
-	// Maximum allowed depth when recursively substituing variable names.
-	depthValues = 99
-)
-
-var (
-	// DefaultSection is the name of default section. You can use this var or the string literal.
-	// In most of cases, an empty string is all you need to access the section.
-	DefaultSection = "DEFAULT"
-
-	// LineBreak is the delimiter to determine or compose a new line.
-	// This variable will be changed to "\r\n" automatically on Windows at package init time.
-	LineBreak = "\n"
-
-	// Variable regexp pattern: %(variable)s
-	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)
-
-	// DefaultHeader explicitly writes default section header.
-	DefaultHeader = false
-
-	// PrettySection indicates whether to put a line between sections.
-	PrettySection = true
-	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
-	// or reduce all possible spaces for compact format.
-	PrettyFormat = true
-	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
-	PrettyEqual = false
-	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatLeft = ""
-	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatRight = ""
-)
-
-var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
-
-func init() {
-	if runtime.GOOS == "windows" && !inTest {
-		LineBreak = "\r\n"
-	}
-}
-
-// LoadOptions contains all customized options used for load data source(s).
-type LoadOptions struct {
-	// Loose indicates whether the parser should ignore nonexistent files or return error.
-	Loose bool
-	// Insensitive indicates whether the parser forces all section and key names to lowercase.
-	Insensitive bool
-	// InsensitiveSections indicates whether the parser forces all section to lowercase.
-	InsensitiveSections bool
-	// InsensitiveKeys indicates whether the parser forces all key names to lowercase.
-	InsensitiveKeys bool
-	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
-	IgnoreContinuation bool
-	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
-	IgnoreInlineComment bool
-	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs.
-	SkipUnrecognizableLines bool
-	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source.
-	ShortCircuit bool
-	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
-	// This type of keys are mostly used in my.cnf.
-	AllowBooleanKeys bool
-	// AllowShadows indicates whether to keep track of keys with same name under same section.
-	AllowShadows bool
-	// AllowNestedValues indicates whether to allow AWS-like nested values.
-	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
-	AllowNestedValues bool
-	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values.
-	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
-	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper
-	// than the first line of the value.
-	AllowPythonMultilineValues bool
-	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
-	// Docs: https://docs.python.org/2/library/configparser.html
-	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
-	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
-	SpaceBeforeInlineComment bool
-	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
-	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
-	UnescapeValueDoubleQuotes bool
-	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
-	// when value is NOT surrounded by any quotes.
-	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
-	UnescapeValueCommentSymbols bool
-	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
-	// conform to key/value pairs. Specify the names of those blocks here.
-	UnparseableSections []string
-	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
-	KeyValueDelimiters string
-	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=".
-	KeyValueDelimiterOnWrite string
-	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
-	ChildSectionDelimiter string
-	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
-	PreserveSurroundedQuote bool
-	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
-	DebugFunc DebugFunc
-	// ReaderBufferSize is the buffer size of the reader in bytes.
-	ReaderBufferSize int
-	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
-	AllowNonUniqueSections bool
-	// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated.
-	AllowDuplicateShadowValues bool
-}
-
-// DebugFunc is the type of function called to log parse events.
-type DebugFunc func(message string)
-
-// LoadSources allows caller to apply customized options for loading from data source(s).
-func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
-	sources := make([]dataSource, len(others)+1)
-	sources[0], err = parseDataSource(source)
-	if err != nil {
-		return nil, err
-	}
-	for i := range others {
-		sources[i+1], err = parseDataSource(others[i])
-		if err != nil {
-			return nil, err
-		}
-	}
-	f := newFile(sources, opts)
-	if err = f.Reload(); err != nil {
-		return nil, err
-	}
-	return f, nil
-}
-
-// Load loads and parses from INI data sources.
-// Arguments can be mixed of file name with string type, or raw data in []byte.
-// It will return error if list contains nonexistent files.
-func Load(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{}, source, others...)
-}
-
-// LooseLoad has exactly same functionality as Load function
-// except it ignores nonexistent files instead of returning error.
-func LooseLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Loose: true}, source, others...)
-}
-
-// InsensitiveLoad has exactly same functionality as Load function
-// except it forces all section and key names to be lowercased.
-func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
-}
-
-// ShadowLoad has exactly same functionality as Load function
-// except it allows have shadow keys.
-func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/key.go b/notifier/vendor/gopkg.in/ini.v1/key.go
deleted file mode 100644
index a19d9f38..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/key.go
+++ /dev/null
@@ -1,837 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Key represents a key under a section.
-type Key struct {
-	s               *Section
-	Comment         string
-	name            string
-	value           string
-	isAutoIncrement bool
-	isBooleanType   bool
-
-	isShadow bool
-	shadows  []*Key
-
-	nestedValues []string
-}
-
-// newKey simply return a key object with given values.
-func newKey(s *Section, name, val string) *Key {
-	return &Key{
-		s:     s,
-		name:  name,
-		value: val,
-	}
-}
-
-func (k *Key) addShadow(val string) error {
-	if k.isShadow {
-		return errors.New("cannot add shadow to another shadow key")
-	} else if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add shadow to auto-increment or boolean key")
-	}
-
-	if !k.s.f.options.AllowDuplicateShadowValues {
-		// Deduplicate shadows based on their values.
-		if k.value == val {
-			return nil
-		}
-		for i := range k.shadows {
-			if k.shadows[i].value == val {
-				return nil
-			}
-		}
-	}
-
-	shadow := newKey(k.s, k.name, val)
-	shadow.isShadow = true
-	k.shadows = append(k.shadows, shadow)
-	return nil
-}
-
-// AddShadow adds a new shadow key to itself.
-func (k *Key) AddShadow(val string) error {
-	if !k.s.f.options.AllowShadows {
-		return errors.New("shadow key is not allowed")
-	}
-	return k.addShadow(val)
-}
-
-func (k *Key) addNestedValue(val string) error {
-	if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add nested value to auto-increment or boolean key")
-	}
-
-	k.nestedValues = append(k.nestedValues, val)
-	return nil
-}
-
-// AddNestedValue adds a nested value to the key.
-func (k *Key) AddNestedValue(val string) error {
-	if !k.s.f.options.AllowNestedValues {
-		return errors.New("nested value is not allowed")
-	}
-	return k.addNestedValue(val)
-}
-
-// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
-type ValueMapper func(string) string
-
-// Name returns name of key.
-func (k *Key) Name() string {
-	return k.name
-}
-
-// Value returns raw value of key for performance purpose.
-func (k *Key) Value() string {
-	return k.value
-}
-
-// ValueWithShadows returns raw values of key and its shadows if any. Shadow
-// keys with empty values are ignored from the returned list.
-func (k *Key) ValueWithShadows() []string {
-	if len(k.shadows) == 0 {
-		if k.value == "" {
-			return []string{}
-		}
-		return []string{k.value}
-	}
-
-	vals := make([]string, 0, len(k.shadows)+1)
-	if k.value != "" {
-		vals = append(vals, k.value)
-	}
-	for _, s := range k.shadows {
-		if s.value != "" {
-			vals = append(vals, s.value)
-		}
-	}
-	return vals
-}
-
-// NestedValues returns nested values stored in the key.
-// It is possible returned value is nil if no nested values stored in the key.
-func (k *Key) NestedValues() []string {
-	return k.nestedValues
-}
-
-// transformValue takes a raw value and transforms to its final string.
-func (k *Key) transformValue(val string) string {
-	if k.s.f.ValueMapper != nil {
-		val = k.s.f.ValueMapper(val)
-	}
-
-	// Fail-fast if no indicate char found for recursive value
-	if !strings.Contains(val, "%") {
-		return val
-	}
-	for i := 0; i < depthValues; i++ {
-		vr := varPattern.FindString(val)
-		if len(vr) == 0 {
-			break
-		}
-
-		// Take off leading '%(' and trailing ')s'.
-		noption := vr[2 : len(vr)-2]
-
-		// Search in the same section.
-		// If not found or found the key itself, then search again in default section.
-		nk, err := k.s.GetKey(noption)
-		if err != nil || k == nk {
-			nk, _ = k.s.f.Section("").GetKey(noption)
-			if nk == nil {
-				// Stop when no results found in the default section,
-				// and returns the value as-is.
-				break
-			}
-		}
-
-		// Substitute by new value and take off leading '%(' and trailing ')s'.
-		val = strings.Replace(val, vr, nk.value, -1)
-	}
-	return val
-}
-
-// String returns string representation of value.
-func (k *Key) String() string {
-	return k.transformValue(k.value)
-}
-
-// Validate accepts a validate function which can
-// return modifed result as key value.
-func (k *Key) Validate(fn func(string) string) string {
-	return fn(k.String())
-}
-
-// parseBool returns the boolean value represented by the string.
-//
-// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
-// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
-// Any other value returns an error.
-func parseBool(str string) (value bool, err error) {
-	switch str {
-	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
-		return true, nil
-	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
-		return false, nil
-	}
-	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
-}
-
-// Bool returns bool type value.
-func (k *Key) Bool() (bool, error) {
-	return parseBool(k.String())
-}
-
-// Float64 returns float64 type value.
-func (k *Key) Float64() (float64, error) {
-	return strconv.ParseFloat(k.String(), 64)
-}
-
-// Int returns int type value.
-func (k *Key) Int() (int, error) {
-	v, err := strconv.ParseInt(k.String(), 0, 64)
-	return int(v), err
-}
-
-// Int64 returns int64 type value.
-func (k *Key) Int64() (int64, error) {
-	return strconv.ParseInt(k.String(), 0, 64)
-}
-
-// Uint returns uint type valued.
-func (k *Key) Uint() (uint, error) {
-	u, e := strconv.ParseUint(k.String(), 0, 64)
-	return uint(u), e
-}
-
-// Uint64 returns uint64 type value.
-func (k *Key) Uint64() (uint64, error) {
-	return strconv.ParseUint(k.String(), 0, 64)
-}
-
-// Duration returns time.Duration type value.
-func (k *Key) Duration() (time.Duration, error) {
-	return time.ParseDuration(k.String())
-}
-
-// TimeFormat parses with given format and returns time.Time type value.
-func (k *Key) TimeFormat(format string) (time.Time, error) {
-	return time.Parse(format, k.String())
-}
-
-// Time parses with RFC3339 format and returns time.Time type value.
-func (k *Key) Time() (time.Time, error) {
-	return k.TimeFormat(time.RFC3339)
-}
-
-// MustString returns default value if key value is empty.
-func (k *Key) MustString(defaultVal string) string {
-	val := k.String()
-	if len(val) == 0 {
-		k.value = defaultVal
-		return defaultVal
-	}
-	return val
-}
-
-// MustBool always returns value without error,
-// it returns false if error occurs.
-func (k *Key) MustBool(defaultVal ...bool) bool {
-	val, err := k.Bool()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatBool(defaultVal[0])
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustFloat64 always returns value without error,
-// it returns 0.0 if error occurs.
-func (k *Key) MustFloat64(defaultVal ...float64) float64 {
-	val, err := k.Float64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt(defaultVal ...int) int {
-	val, err := k.Int()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt64(defaultVal ...int64) int64 {
-	val, err := k.Int64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint(defaultVal ...uint) uint {
-	val, err := k.Uint()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
-	val, err := k.Uint64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustDuration always returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
-	val, err := k.Duration()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].String()
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTimeFormat always parses with given format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
-	val, err := k.TimeFormat(format)
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].Format(format)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTime always parses with RFC3339 format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
-	return k.MustTimeFormat(time.RFC3339, defaultVal...)
-}
-
-// In always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) In(defaultVal string, candidates []string) string {
-	val := k.String()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InFloat64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
-	val := k.MustFloat64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt(defaultVal int, candidates []int) int {
-	val := k.MustInt()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
-	val := k.MustInt64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
-	val := k.MustUint()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
-	val := k.MustUint64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTimeFormat always parses with given format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTime always parses with RFC3339 format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
-	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
-}
-
-// RangeFloat64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
-	val := k.MustFloat64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt(defaultVal, min, max int) int {
-	val := k.MustInt()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
-	val := k.MustInt64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTimeFormat checks if value with given format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTime checks if value with RFC3339 format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
-	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
-}
-
-// Strings returns list of string divided by given delimiter.
-func (k *Key) Strings(delim string) []string {
-	str := k.String()
-	if len(str) == 0 {
-		return []string{}
-	}
-
-	runes := []rune(str)
-	vals := make([]string, 0, 2)
-	var buf bytes.Buffer
-	escape := false
-	idx := 0
-	for {
-		if escape {
-			escape = false
-			if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
-				buf.WriteRune('\\')
-			}
-			buf.WriteRune(runes[idx])
-		} else {
-			if runes[idx] == '\\' {
-				escape = true
-			} else if strings.HasPrefix(string(runes[idx:]), delim) {
-				idx += len(delim) - 1
-				vals = append(vals, strings.TrimSpace(buf.String()))
-				buf.Reset()
-			} else {
-				buf.WriteRune(runes[idx])
-			}
-		}
-		idx++
-		if idx == len(runes) {
-			break
-		}
-	}
-
-	if buf.Len() > 0 {
-		vals = append(vals, strings.TrimSpace(buf.String()))
-	}
-
-	return vals
-}
-
-// StringsWithShadows returns list of string divided by given delimiter.
-// Shadows will also be appended if any.
-func (k *Key) StringsWithShadows(delim string) []string {
-	vals := k.ValueWithShadows()
-	results := make([]string, 0, len(vals)*2)
-	for i := range vals {
-		if len(vals) == 0 {
-			continue
-		}
-
-		results = append(results, strings.Split(vals[i], delim)...)
-	}
-
-	for i := range results {
-		results[i] = k.transformValue(strings.TrimSpace(results[i]))
-	}
-	return results
-}
-
-// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Float64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Ints(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), true, false)
-	return vals
-}
-
-// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Int64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Bools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), true, false)
-	return vals
-}
-
-// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) TimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
-	return vals
-}
-
-// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) Times(delim string) []time.Time {
-	return k.TimesFormat(time.RFC3339, delim)
-}
-
-// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
-// it will not be included to result list.
-func (k *Key) ValidFloat64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
-// not be included to result list.
-func (k *Key) ValidInts(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
-// then it will not be included to result list.
-func (k *Key) ValidInt64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
-// then it will not be included to result list.
-func (k *Key) ValidUints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidUint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidBools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimes(delim string) []time.Time {
-	return k.ValidTimesFormat(time.RFC3339, delim)
-}
-
-// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
-	return k.parseFloat64s(k.Strings(delim), false, true)
-}
-
-// StrictInts returns list of int divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInts(delim string) ([]int, error) {
-	return k.parseInts(k.Strings(delim), false, true)
-}
-
-// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInt64s(delim string) ([]int64, error) {
-	return k.parseInt64s(k.Strings(delim), false, true)
-}
-
-// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUints(delim string) ([]uint, error) {
-	return k.parseUints(k.Strings(delim), false, true)
-}
-
-// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
-	return k.parseUint64s(k.Strings(delim), false, true)
-}
-
-// StrictBools returns list of bool divided by given delimiter or error on first invalid input.
-func (k *Key) StrictBools(delim string) ([]bool, error) {
-	return k.parseBools(k.Strings(delim), false, true)
-}
-
-// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
-	return k.parseTimesFormat(format, k.Strings(delim), false, true)
-}
-
-// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
-	return k.StrictTimesFormat(time.RFC3339, delim)
-}
-
-// parseBools transforms strings to bools.
-func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) {
-	vals := make([]bool, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := parseBool(str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(bool))
-		}
-	}
-	return vals, err
-}
-
-// parseFloat64s transforms strings to float64s.
-func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
-	vals := make([]float64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseFloat(str, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(float64))
-		}
-	}
-	return vals, err
-}
-
-// parseInts transforms strings to ints.
-func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
-	vals := make([]int, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, int(val.(int64)))
-		}
-	}
-	return vals, err
-}
-
-// parseInt64s transforms strings to int64s.
-func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
-	vals := make([]int64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(int64))
-		}
-	}
-	return vals, err
-}
-
-// parseUints transforms strings to uints.
-func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
-	vals := make([]uint, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, uint(val.(uint64)))
-		}
-	}
-	return vals, err
-}
-
-// parseUint64s transforms strings to uint64s.
-func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
-	vals := make([]uint64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(uint64))
-		}
-	}
-	return vals, err
-}
-
-type Parser func(str string) (interface{}, error)
-
-// parseTimesFormat transforms strings to times in given format.
-func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
-	vals := make([]time.Time, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := time.Parse(format, str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(time.Time))
-		}
-	}
-	return vals, err
-}
-
-// doParse transforms strings to different types
-func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) {
-	vals := make([]interface{}, 0, len(strs))
-	for _, str := range strs {
-		val, err := parser(str)
-		if err != nil && returnOnInvalid {
-			return nil, err
-		}
-		if err == nil || addInvalid {
-			vals = append(vals, val)
-		}
-	}
-	return vals, nil
-}
-
-// SetValue changes key value.
-func (k *Key) SetValue(v string) {
-	if k.s.f.BlockMode {
-		k.s.f.lock.Lock()
-		defer k.s.f.lock.Unlock()
-	}
-
-	k.value = v
-	k.s.keysHash[k.name] = v
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/parser.go b/notifier/vendor/gopkg.in/ini.v1/parser.go
deleted file mode 100644
index 44fc526c..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/parser.go
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2015 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"regexp"
-	"strconv"
-	"strings"
-	"unicode"
-)
-
-const minReaderBufferSize = 4096
-
-var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`)
-
-type parserOptions struct {
-	IgnoreContinuation          bool
-	IgnoreInlineComment         bool
-	AllowPythonMultilineValues  bool
-	SpaceBeforeInlineComment    bool
-	UnescapeValueDoubleQuotes   bool
-	UnescapeValueCommentSymbols bool
-	PreserveSurroundedQuote     bool
-	DebugFunc                   DebugFunc
-	ReaderBufferSize            int
-}
-
-type parser struct {
-	buf     *bufio.Reader
-	options parserOptions
-
-	isEOF   bool
-	count   int
-	comment *bytes.Buffer
-}
-
-func (p *parser) debug(format string, args ...interface{}) {
-	if p.options.DebugFunc != nil {
-		p.options.DebugFunc(fmt.Sprintf(format, args...))
-	}
-}
-
-func newParser(r io.Reader, opts parserOptions) *parser {
-	size := opts.ReaderBufferSize
-	if size < minReaderBufferSize {
-		size = minReaderBufferSize
-	}
-
-	return &parser{
-		buf:     bufio.NewReaderSize(r, size),
-		options: opts,
-		count:   1,
-		comment: &bytes.Buffer{},
-	}
-}
-
-// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
-// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
-func (p *parser) BOM() error {
-	mask, err := p.buf.Peek(2)
-	if err != nil && err != io.EOF {
-		return err
-	} else if len(mask) < 2 {
-		return nil
-	}
-
-	switch {
-	case mask[0] == 254 && mask[1] == 255:
-		fallthrough
-	case mask[0] == 255 && mask[1] == 254:
-		_, err = p.buf.Read(mask)
-		if err != nil {
-			return err
-		}
-	case mask[0] == 239 && mask[1] == 187:
-		mask, err := p.buf.Peek(3)
-		if err != nil && err != io.EOF {
-			return err
-		} else if len(mask) < 3 {
-			return nil
-		}
-		if mask[2] == 191 {
-			_, err = p.buf.Read(mask)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func (p *parser) readUntil(delim byte) ([]byte, error) {
-	data, err := p.buf.ReadBytes(delim)
-	if err != nil {
-		if err == io.EOF {
-			p.isEOF = true
-		} else {
-			return nil, err
-		}
-	}
-	return data, nil
-}
-
-func cleanComment(in []byte) ([]byte, bool) {
-	i := bytes.IndexAny(in, "#;")
-	if i == -1 {
-		return nil, false
-	}
-	return in[i:], true
-}
-
-func readKeyName(delimiters string, in []byte) (string, int, error) {
-	line := string(in)
-
-	// Check if key name surrounded by quotes.
-	var keyQuote string
-	if line[0] == '"' {
-		if len(line) > 6 && line[0:3] == `"""` {
-			keyQuote = `"""`
-		} else {
-			keyQuote = `"`
-		}
-	} else if line[0] == '`' {
-		keyQuote = "`"
-	}
-
-	// Get out key name
-	var endIdx int
-	if len(keyQuote) > 0 {
-		startIdx := len(keyQuote)
-		// FIXME: fail case -> """"""name"""=value
-		pos := strings.Index(line[startIdx:], keyQuote)
-		if pos == -1 {
-			return "", -1, fmt.Errorf("missing closing key quote: %s", line)
-		}
-		pos += startIdx
-
-		// Find key-value delimiter
-		i := strings.IndexAny(line[pos+startIdx:], delimiters)
-		if i < 0 {
-			return "", -1, ErrDelimiterNotFound{line}
-		}
-		endIdx = pos + i
-		return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
-	}
-
-	endIdx = strings.IndexAny(line, delimiters)
-	if endIdx < 0 {
-		return "", -1, ErrDelimiterNotFound{line}
-	}
-	if endIdx == 0 {
-		return "", -1, ErrEmptyKeyName{line}
-	}
-
-	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
-}
-
-func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := string(data)
-
-		pos := strings.LastIndex(next, valQuote)
-		if pos > -1 {
-			val += next[:pos]
-
-			comment, has := cleanComment([]byte(next[pos:]))
-			if has {
-				p.comment.Write(bytes.TrimSpace(comment))
-			}
-			break
-		}
-		val += next
-		if p.isEOF {
-			return "", fmt.Errorf("missing closing key quote from %q to %q", line, next)
-		}
-	}
-	return val, nil
-}
-
-func (p *parser) readContinuationLines(val string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := strings.TrimSpace(string(data))
-
-		if len(next) == 0 {
-			break
-		}
-		val += next
-		if val[len(val)-1] != '\\' {
-			break
-		}
-		val = val[:len(val)-1]
-	}
-	return val, nil
-}
-
-// hasSurroundedQuote check if and only if the first and last characters
-// are quotes \" or \'.
-// It returns false if any other parts also contain same kind of quotes.
-func hasSurroundedQuote(in string, quote byte) bool {
-	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
-		strings.IndexByte(in[1:], quote) == len(in)-2
-}
-
-func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
-
-	line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
-	if len(line) == 0 {
-		if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
-			return p.readPythonMultilines(line, bufferSize)
-		}
-		return "", nil
-	}
-
-	var valQuote string
-	if len(line) > 3 && line[0:3] == `"""` {
-		valQuote = `"""`
-	} else if line[0] == '`' {
-		valQuote = "`"
-	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
-		valQuote = `"`
-	}
-
-	if len(valQuote) > 0 {
-		startIdx := len(valQuote)
-		pos := strings.LastIndex(line[startIdx:], valQuote)
-		// Check for multi-line value
-		if pos == -1 {
-			return p.readMultilines(line, line[startIdx:], valQuote)
-		}
-
-		if p.options.UnescapeValueDoubleQuotes && valQuote == `"` {
-			return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
-		}
-		return line[startIdx : pos+startIdx], nil
-	}
-
-	lastChar := line[len(line)-1]
-	// Won't be able to reach here if value only contains whitespace
-	line = strings.TrimSpace(line)
-	trimmedLastChar := line[len(line)-1]
-
-	// Check continuation lines when desired
-	if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
-		return p.readContinuationLines(line[:len(line)-1])
-	}
-
-	// Check if ignore inline comment
-	if !p.options.IgnoreInlineComment {
-		var i int
-		if p.options.SpaceBeforeInlineComment {
-			i = strings.Index(line, " #")
-			if i == -1 {
-				i = strings.Index(line, " ;")
-			}
-
-		} else {
-			i = strings.IndexAny(line, "#;")
-		}
-
-		if i > -1 {
-			p.comment.WriteString(line[i:])
-			line = strings.TrimSpace(line[:i])
-		}
-
-	}
-
-	// Trim single and double quotes
-	if (hasSurroundedQuote(line, '\'') ||
-		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
-		line = line[1 : len(line)-1]
-	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
-		line = strings.ReplaceAll(line, `\;`, ";")
-		line = strings.ReplaceAll(line, `\#`, "#")
-	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
-		return p.readPythonMultilines(line, bufferSize)
-	}
-
-	return line, nil
-}
-
-func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
-	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
-	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
-
-	for {
-		peekData, peekErr := peekBuffer.ReadBytes('\n')
-		if peekErr != nil && peekErr != io.EOF {
-			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
-			return "", peekErr
-		}
-
-		p.debug("readPythonMultilines: parsing %q", string(peekData))
-
-		peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
-		p.debug("readPythonMultilines: matched %d parts", len(peekMatches))
-		for n, v := range peekMatches {
-			p.debug("   %d: %q", n, v)
-		}
-
-		// Return if not a Python multiline value.
-		if len(peekMatches) != 3 {
-			p.debug("readPythonMultilines: end of value, got: %q", line)
-			return line, nil
-		}
-
-		// Advance the parser reader (buffer) in-sync with the peek buffer.
-		_, err := p.buf.Discard(len(peekData))
-		if err != nil {
-			p.debug("readPythonMultilines: failed to skip to the end, returning error")
-			return "", err
-		}
-
-		line += "\n" + peekMatches[0]
-	}
-}
-
-// parse parses data through an io.Reader.
-func (f *File) parse(reader io.Reader) (err error) {
-	p := newParser(reader, parserOptions{
-		IgnoreContinuation:          f.options.IgnoreContinuation,
-		IgnoreInlineComment:         f.options.IgnoreInlineComment,
-		AllowPythonMultilineValues:  f.options.AllowPythonMultilineValues,
-		SpaceBeforeInlineComment:    f.options.SpaceBeforeInlineComment,
-		UnescapeValueDoubleQuotes:   f.options.UnescapeValueDoubleQuotes,
-		UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols,
-		PreserveSurroundedQuote:     f.options.PreserveSurroundedQuote,
-		DebugFunc:                   f.options.DebugFunc,
-		ReaderBufferSize:            f.options.ReaderBufferSize,
-	})
-	if err = p.BOM(); err != nil {
-		return fmt.Errorf("BOM: %v", err)
-	}
-
-	// Ignore error because default section name is never empty string.
-	name := DefaultSection
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(DefaultSection)
-	}
-	section, _ := f.NewSection(name)
-
-	// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
-	var isLastValueEmpty bool
-	var lastRegularKey *Key
-
-	var line []byte
-	var inUnparseableSection bool
-
-	// NOTE: Iterate and increase `currentPeekSize` until
-	// the size of the parser buffer is found.
-	// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`.
-	parserBufferSize := 0
-	// NOTE: Peek 4kb at a time.
-	currentPeekSize := minReaderBufferSize
-
-	if f.options.AllowPythonMultilineValues {
-		for {
-			peekBytes, _ := p.buf.Peek(currentPeekSize)
-			peekBytesLength := len(peekBytes)
-
-			if parserBufferSize >= peekBytesLength {
-				break
-			}
-
-			currentPeekSize *= 2
-			parserBufferSize = peekBytesLength
-		}
-	}
-
-	for !p.isEOF {
-		line, err = p.readUntil('\n')
-		if err != nil {
-			return err
-		}
-
-		if f.options.AllowNestedValues &&
-			isLastValueEmpty && len(line) > 0 {
-			if line[0] == ' ' || line[0] == '\t' {
-				err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
-				if err != nil {
-					return err
-				}
-				continue
-			}
-		}
-
-		line = bytes.TrimLeftFunc(line, unicode.IsSpace)
-		if len(line) == 0 {
-			continue
-		}
-
-		// Comments
-		if line[0] == '#' || line[0] == ';' {
-			// Note: we do not care ending line break,
-			// it is needed for adding second line,
-			// so just clean it once at the end when set to value.
-			p.comment.Write(line)
-			continue
-		}
-
-		// Section
-		if line[0] == '[' {
-			// Read to the next ']' (TODO: support quoted strings)
-			closeIdx := bytes.LastIndexByte(line, ']')
-			if closeIdx == -1 {
-				return fmt.Errorf("unclosed section: %s", line)
-			}
-
-			name := string(line[1:closeIdx])
-			section, err = f.NewSection(name)
-			if err != nil {
-				return err
-			}
-
-			comment, has := cleanComment(line[closeIdx+1:])
-			if has {
-				p.comment.Write(comment)
-			}
-
-			section.Comment = strings.TrimSpace(p.comment.String())
-
-			// Reset auto-counter and comments
-			p.comment.Reset()
-			p.count = 1
-			// Nested values can't span sections
-			isLastValueEmpty = false
-
-			inUnparseableSection = false
-			for i := range f.options.UnparseableSections {
-				if f.options.UnparseableSections[i] == name ||
-					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
-					inUnparseableSection = true
-					continue
-				}
-			}
-			continue
-		}
-
-		if inUnparseableSection {
-			section.isRawSection = true
-			section.rawBody += string(line)
-			continue
-		}
-
-		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
-		if err != nil {
-			switch {
-			// Treat as boolean key when desired, and whole line is key name.
-			case IsErrDelimiterNotFound(err):
-				switch {
-				case f.options.AllowBooleanKeys:
-					kname, err := p.readValue(line, parserBufferSize)
-					if err != nil {
-						return err
-					}
-					key, err := section.NewBooleanKey(kname)
-					if err != nil {
-						return err
-					}
-					key.Comment = strings.TrimSpace(p.comment.String())
-					p.comment.Reset()
-					continue
-
-				case f.options.SkipUnrecognizableLines:
-					continue
-				}
-			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines:
-				continue
-			}
-			return err
-		}
-
-		// Auto increment.
-		isAutoIncr := false
-		if kname == "-" {
-			isAutoIncr = true
-			kname = "#" + strconv.Itoa(p.count)
-			p.count++
-		}
-
-		value, err := p.readValue(line[offset:], parserBufferSize)
-		if err != nil {
-			return err
-		}
-		isLastValueEmpty = len(value) == 0
-
-		key, err := section.NewKey(kname, value)
-		if err != nil {
-			return err
-		}
-		key.isAutoIncrement = isAutoIncr
-		key.Comment = strings.TrimSpace(p.comment.String())
-		p.comment.Reset()
-		lastRegularKey = key
-	}
-	return nil
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/section.go b/notifier/vendor/gopkg.in/ini.v1/section.go
deleted file mode 100644
index a3615d82..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/section.go
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"errors"
-	"fmt"
-	"strings"
-)
-
-// Section represents a config section.
-type Section struct {
-	f        *File
-	Comment  string
-	name     string
-	keys     map[string]*Key
-	keyList  []string
-	keysHash map[string]string
-
-	isRawSection bool
-	rawBody      string
-}
-
-func newSection(f *File, name string) *Section {
-	return &Section{
-		f:        f,
-		name:     name,
-		keys:     make(map[string]*Key),
-		keyList:  make([]string, 0, 10),
-		keysHash: make(map[string]string),
-	}
-}
-
-// Name returns name of Section.
-func (s *Section) Name() string {
-	return s.name
-}
-
-// Body returns rawBody of Section if the section was marked as unparseable.
-// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
-func (s *Section) Body() string {
-	return strings.TrimSpace(s.rawBody)
-}
-
-// SetBody updates body content only if section is raw.
-func (s *Section) SetBody(body string) {
-	if !s.isRawSection {
-		return
-	}
-	s.rawBody = body
-}
-
-// NewKey creates a new key to given section.
-func (s *Section) NewKey(name, val string) (*Key, error) {
-	if len(name) == 0 {
-		return nil, errors.New("error creating new key: empty key name")
-	} else if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	if inSlice(name, s.keyList) {
-		if s.f.options.AllowShadows {
-			if err := s.keys[name].addShadow(val); err != nil {
-				return nil, err
-			}
-		} else {
-			s.keys[name].value = val
-			s.keysHash[name] = val
-		}
-		return s.keys[name], nil
-	}
-
-	s.keyList = append(s.keyList, name)
-	s.keys[name] = newKey(s, name, val)
-	s.keysHash[name] = val
-	return s.keys[name], nil
-}
-
-// NewBooleanKey creates a new boolean type key to given section.
-func (s *Section) NewBooleanKey(name string) (*Key, error) {
-	key, err := s.NewKey(name, "true")
-	if err != nil {
-		return nil, err
-	}
-
-	key.isBooleanType = true
-	return key, nil
-}
-
-// GetKey returns key in section by given name.
-func (s *Section) GetKey(name string) (*Key, error) {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-	}
-	if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-	key := s.keys[name]
-	if s.f.BlockMode {
-		s.f.lock.RUnlock()
-	}
-
-	if key == nil {
-		// Check if it is a child-section.
-		sname := s.name
-		for {
-			if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-				sname = sname[:i]
-				sec, err := s.f.GetSection(sname)
-				if err != nil {
-					continue
-				}
-				return sec.GetKey(name)
-			}
-			break
-		}
-		return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name)
-	}
-	return key, nil
-}
-
-// HasKey returns true if section contains a key with given name.
-func (s *Section) HasKey(name string) bool {
-	key, _ := s.GetKey(name)
-	return key != nil
-}
-
-// Deprecated: Use "HasKey" instead.
-func (s *Section) Haskey(name string) bool {
-	return s.HasKey(name)
-}
-
-// HasValue returns true if section contains given raw value.
-func (s *Section) HasValue(value string) bool {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	for _, k := range s.keys {
-		if value == k.value {
-			return true
-		}
-	}
-	return false
-}
-
-// Key assumes named Key exists in section and returns a zero-value when not.
-func (s *Section) Key(name string) *Key {
-	key, err := s.GetKey(name)
-	if err != nil {
-		// It's OK here because the only possible error is empty key name,
-		// but if it's empty, this piece of code won't be executed.
-		key, _ = s.NewKey(name, "")
-		return key
-	}
-	return key
-}
-
-// Keys returns list of keys of section.
-func (s *Section) Keys() []*Key {
-	keys := make([]*Key, len(s.keyList))
-	for i := range s.keyList {
-		keys[i] = s.Key(s.keyList[i])
-	}
-	return keys
-}
-
-// ParentKeys returns list of keys of parent section.
-func (s *Section) ParentKeys() []*Key {
-	var parentKeys []*Key
-	sname := s.name
-	for {
-		if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-			sname = sname[:i]
-			sec, err := s.f.GetSection(sname)
-			if err != nil {
-				continue
-			}
-			parentKeys = append(parentKeys, sec.Keys()...)
-		} else {
-			break
-		}
-
-	}
-	return parentKeys
-}
-
-// KeyStrings returns list of key names of section.
-func (s *Section) KeyStrings() []string {
-	list := make([]string, len(s.keyList))
-	copy(list, s.keyList)
-	return list
-}
-
-// KeysHash returns keys hash consisting of names and values.
-func (s *Section) KeysHash() map[string]string {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	hash := make(map[string]string, len(s.keysHash))
-	for key, value := range s.keysHash {
-		hash[key] = value
-	}
-	return hash
-}
-
-// DeleteKey deletes a key from section.
-func (s *Section) DeleteKey(name string) {
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	for i, k := range s.keyList {
-		if k == name {
-			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
-			delete(s.keys, name)
-			delete(s.keysHash, name)
-			return
-		}
-	}
-}
-
-// ChildSections returns a list of child sections of current section.
-// For example, "[parent.child1]" and "[parent.child12]" are child sections
-// of section "[parent]".
-func (s *Section) ChildSections() []*Section {
-	prefix := s.name + s.f.options.ChildSectionDelimiter
-	children := make([]*Section, 0, 3)
-	for _, name := range s.f.sectionList {
-		if strings.HasPrefix(name, prefix) {
-			children = append(children, s.f.sections[name]...)
-		}
-	}
-	return children
-}
diff --git a/notifier/vendor/gopkg.in/ini.v1/struct.go b/notifier/vendor/gopkg.in/ini.v1/struct.go
deleted file mode 100644
index a486b2fe..00000000
--- a/notifier/vendor/gopkg.in/ini.v1/struct.go
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"reflect"
-	"strings"
-	"time"
-	"unicode"
-)
-
-// NameMapper represents a ini tag name mapper.
-type NameMapper func(string) string
-
-// Built-in name getters.
-var (
-	// SnackCase converts to format SNACK_CASE.
-	SnackCase NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-			}
-			newstr = append(newstr, unicode.ToUpper(chr))
-		}
-		return string(newstr)
-	}
-	// TitleUnderscore converts to format title_underscore.
-	TitleUnderscore NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-				chr -= 'A' - 'a'
-			}
-			newstr = append(newstr, chr)
-		}
-		return string(newstr)
-	}
-)
-
-func (s *Section) parseFieldName(raw, actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	if s.f.NameMapper != nil {
-		return s.f.NameMapper(raw)
-	}
-	return raw
-}
-
-func parseDelim(actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	return ","
-}
-
-var reflectTime = reflect.TypeOf(time.Now()).Kind()
-
-// setSliceWithProperType sets proper values to slice based on its type.
-func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	var strs []string
-	if allowShadow {
-		strs = key.StringsWithShadows(delim)
-	} else {
-		strs = key.Strings(delim)
-	}
-
-	numVals := len(strs)
-	if numVals == 0 {
-		return nil
-	}
-
-	var vals interface{}
-	var err error
-
-	sliceOf := field.Type().Elem().Kind()
-	switch sliceOf {
-	case reflect.String:
-		vals = strs
-	case reflect.Int:
-		vals, err = key.parseInts(strs, true, false)
-	case reflect.Int64:
-		vals, err = key.parseInt64s(strs, true, false)
-	case reflect.Uint:
-		vals, err = key.parseUints(strs, true, false)
-	case reflect.Uint64:
-		vals, err = key.parseUint64s(strs, true, false)
-	case reflect.Float64:
-		vals, err = key.parseFloat64s(strs, true, false)
-	case reflect.Bool:
-		vals, err = key.parseBools(strs, true, false)
-	case reflectTime:
-		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
-	default:
-		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-	}
-	if err != nil && isStrict {
-		return err
-	}
-
-	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
-	for i := 0; i < numVals; i++ {
-		switch sliceOf {
-		case reflect.String:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
-		case reflect.Int:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
-		case reflect.Int64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
-		case reflect.Uint:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
-		case reflect.Uint64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
-		case reflect.Float64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
-		case reflect.Bool:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i]))
-		case reflectTime:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
-		}
-	}
-	field.Set(slice)
-	return nil
-}
-
-func wrapStrictError(err error, isStrict bool) error {
-	if isStrict {
-		return err
-	}
-	return nil
-}
-
-// setWithProperType sets proper value to field based on its type,
-// but it does not return error for failing parsing,
-// because we want to use default value that is already assigned to struct.
-func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	vt := t
-	isPtr := t.Kind() == reflect.Ptr
-	if isPtr {
-		vt = t.Elem()
-	}
-	switch vt.Kind() {
-	case reflect.String:
-		stringVal := key.String()
-		if isPtr {
-			field.Set(reflect.ValueOf(&stringVal))
-		} else if len(stringVal) > 0 {
-			field.SetString(key.String())
-		}
-	case reflect.Bool:
-		boolVal, err := key.Bool()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&boolVal))
-		} else {
-			field.SetBool(boolVal)
-		}
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		// ParseDuration will not return err for `0`, so check the type name
-		if vt.Name() == "Duration" {
-			durationVal, err := key.Duration()
-			if err != nil {
-				if intVal, err := key.Int64(); err == nil {
-					field.SetInt(intVal)
-					return nil
-				}
-				return wrapStrictError(err, isStrict)
-			}
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else if int64(durationVal) > 0 {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		intVal, err := key.Int64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetInt(intVal)
-			field.Set(pv)
-		} else {
-			field.SetInt(intVal)
-		}
-	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
-	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		durationVal, err := key.Duration()
-		// Skip zero value
-		if err == nil && uint64(durationVal) > 0 {
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		uintVal, err := key.Uint64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetUint(uintVal)
-			field.Set(pv)
-		} else {
-			field.SetUint(uintVal)
-		}
-
-	case reflect.Float32, reflect.Float64:
-		floatVal, err := key.Float64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetFloat(floatVal)
-			field.Set(pv)
-		} else {
-			field.SetFloat(floatVal)
-		}
-	case reflectTime:
-		timeVal, err := key.Time()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&timeVal))
-		} else {
-			field.Set(reflect.ValueOf(timeVal))
-		}
-	case reflect.Slice:
-		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) {
-	opts := strings.SplitN(tag, ",", 5)
-	rawName = opts[0]
-	for _, opt := range opts[1:] {
-		omitEmpty = omitEmpty || (opt == "omitempty")
-		allowShadow = allowShadow || (opt == "allowshadow")
-		allowNonUnique = allowNonUnique || (opt == "nonunique")
-		extends = extends || (opt == "extends")
-	}
-	return rawName, omitEmpty, allowShadow, allowNonUnique, extends
-}
-
-// mapToField maps the given value to the matching field of the given section.
-// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
-func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		isStruct := tpField.Type.Kind() == reflect.Struct
-		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
-		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
-		if isAnonymousPtr {
-			field.Set(reflect.New(tpField.Type.Elem()))
-		}
-
-		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) {
-			if isStructPtr && field.IsNil() {
-				field.Set(reflect.New(tpField.Type.Elem()))
-			}
-			fieldSection := s
-			if rawName != "" {
-				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName
-				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) {
-					fieldSection = secs[sectionIndex]
-				}
-			}
-			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil {
-				return fmt.Errorf("map to field %q: %v", fieldName, err)
-			}
-		} else if isAnonymousPtr || isStruct || isStructPtr {
-			if secs, err := s.f.SectionsByName(fieldName); err == nil {
-				if len(secs) <= sectionIndex {
-					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
-				}
-				// Only set the field to non-nil struct value if we have a section for it.
-				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
-				if isStructPtr && field.IsNil() {
-					field.Set(reflect.New(tpField.Type.Elem()))
-				}
-				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil {
-					return fmt.Errorf("map to field %q: %v", fieldName, err)
-				}
-				continue
-			}
-		}
-
-		// Map non-unique sections
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			newField, err := s.mapToSlice(fieldName, field, isStrict)
-			if err != nil {
-				return fmt.Errorf("map to slice %q: %v", fieldName, err)
-			}
-
-			field.Set(newField)
-			continue
-		}
-
-		if key, err := s.GetKey(fieldName); err == nil {
-			delim := parseDelim(tpField.Tag.Get("delim"))
-			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
-				return fmt.Errorf("set field %q: %v", fieldName, err)
-			}
-		}
-	}
-	return nil
-}
-
-// mapToSlice maps all sections with the same name and returns the new value.
-// The type of the Value must be a slice.
-func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
-	secs, err := s.f.SectionsByName(secName)
-	if err != nil {
-		return reflect.Value{}, err
-	}
-
-	typ := val.Type().Elem()
-	for i, sec := range secs {
-		elem := reflect.New(typ)
-		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
-			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
-		}
-
-		val = reflect.Append(val, elem.Elem())
-	}
-	return val, nil
-}
-
-// mapTo maps a section to object v.
-func (s *Section) mapTo(v interface{}, isStrict bool) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-	if typ.Kind() == reflect.Ptr {
-		typ = typ.Elem()
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	if typ.Kind() == reflect.Slice {
-		newField, err := s.mapToSlice(s.name, val, isStrict)
-		if err != nil {
-			return err
-		}
-
-		val.Set(newField)
-		return nil
-	}
-
-	return s.mapToField(val, isStrict, 0, s.name)
-}
-
-// MapTo maps section to given struct.
-func (s *Section) MapTo(v interface{}) error {
-	return s.mapTo(v, false)
-}
-
-// StrictMapTo maps section to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (s *Section) StrictMapTo(v interface{}) error {
-	return s.mapTo(v, true)
-}
-
-// MapTo maps file to given struct.
-func (f *File) MapTo(v interface{}) error {
-	return f.Section("").MapTo(v)
-}
-
-// StrictMapTo maps file to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (f *File) StrictMapTo(v interface{}) error {
-	return f.Section("").StrictMapTo(v)
-}
-
-// MapToWithMapper maps data sources to given struct with name mapper.
-func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.MapTo(v)
-}
-
-// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.StrictMapTo(v)
-}
-
-// MapTo maps data sources to given struct.
-func MapTo(v, source interface{}, others ...interface{}) error {
-	return MapToWithMapper(v, nil, source, others...)
-}
-
-// StrictMapTo maps data sources to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapTo(v, source interface{}, others ...interface{}) error {
-	return StrictMapToWithMapper(v, nil, source, others...)
-}
-
-// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
-func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	slice := field.Slice(0, field.Len())
-	if field.Len() == 0 {
-		return nil
-	}
-	sliceOf := field.Type().Elem().Kind()
-
-	if allowShadow {
-		var keyWithShadows *Key
-		for i := 0; i < field.Len(); i++ {
-			var val string
-			switch sliceOf {
-			case reflect.String:
-				val = slice.Index(i).String()
-			case reflect.Int, reflect.Int64:
-				val = fmt.Sprint(slice.Index(i).Int())
-			case reflect.Uint, reflect.Uint64:
-				val = fmt.Sprint(slice.Index(i).Uint())
-			case reflect.Float64:
-				val = fmt.Sprint(slice.Index(i).Float())
-			case reflect.Bool:
-				val = fmt.Sprint(slice.Index(i).Bool())
-			case reflectTime:
-				val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
-			default:
-				return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-			}
-
-			if i == 0 {
-				keyWithShadows = newKey(key.s, key.name, val)
-			} else {
-				_ = keyWithShadows.AddShadow(val)
-			}
-		}
-		*key = *keyWithShadows
-		return nil
-	}
-
-	var buf bytes.Buffer
-	for i := 0; i < field.Len(); i++ {
-		switch sliceOf {
-		case reflect.String:
-			buf.WriteString(slice.Index(i).String())
-		case reflect.Int, reflect.Int64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
-		case reflect.Uint, reflect.Uint64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
-		case reflect.Float64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
-		case reflect.Bool:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
-		case reflectTime:
-			buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
-		default:
-			return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-		}
-		buf.WriteString(delim)
-	}
-	key.SetValue(buf.String()[:buf.Len()-len(delim)])
-	return nil
-}
-
-// reflectWithProperType does the opposite thing as setWithProperType.
-func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	switch t.Kind() {
-	case reflect.String:
-		key.SetValue(field.String())
-	case reflect.Bool:
-		key.SetValue(fmt.Sprint(field.Bool()))
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		key.SetValue(fmt.Sprint(field.Int()))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		key.SetValue(fmt.Sprint(field.Uint()))
-	case reflect.Float32, reflect.Float64:
-		key.SetValue(fmt.Sprint(field.Float()))
-	case reflectTime:
-		key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
-	case reflect.Slice:
-		return reflectSliceWithProperType(key, field, delim, allowShadow)
-	case reflect.Ptr:
-		if !field.IsNil() {
-			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
-		}
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-// CR: copied from encoding/json/encode.go with modifications of time.Time support.
-// TODO: add more test coverage.
-func isEmptyValue(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	case reflectTime:
-		t, ok := v.Interface().(time.Time)
-		return ok && t.IsZero()
-	}
-	return false
-}
-
-// StructReflector is the interface implemented by struct types that can extract themselves into INI objects.
-type StructReflector interface {
-	ReflectINIStruct(*File) error
-}
-
-func (s *Section) reflectFrom(val reflect.Value) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		if !val.Field(i).CanInterface() {
-			continue
-		}
-
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		if omitEmpty && isEmptyValue(field) {
-			continue
-		}
-
-		if r, ok := field.Interface().(StructReflector); ok {
-			return r.ReflectINIStruct(s.f)
-		}
-
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
-			if err := s.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
-			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
-			// Note: The only error here is section doesn't exist.
-			sec, err := s.f.GetSection(fieldName)
-			if err != nil {
-				// Note: fieldName can never be empty here, ignore error.
-				sec, _ = s.f.NewSection(fieldName)
-			}
-
-			// Add comment from comment tag
-			if len(sec.Comment) == 0 {
-				sec.Comment = tpField.Tag.Get("comment")
-			}
-
-			if err = sec.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			slice := field.Slice(0, field.Len())
-			if field.Len() == 0 {
-				return nil
-			}
-			sliceOf := field.Type().Elem().Kind()
-
-			for i := 0; i < field.Len(); i++ {
-				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
-					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
-				}
-
-				sec, err := s.f.NewSection(fieldName)
-				if err != nil {
-					return err
-				}
-
-				// Add comment from comment tag
-				if len(sec.Comment) == 0 {
-					sec.Comment = tpField.Tag.Get("comment")
-				}
-
-				if err := sec.reflectFrom(slice.Index(i)); err != nil {
-					return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-				}
-			}
-			continue
-		}
-
-		// Note: Same reason as section.
-		key, err := s.GetKey(fieldName)
-		if err != nil {
-			key, _ = s.NewKey(fieldName, "")
-		}
-
-		// Add comment from comment tag
-		if len(key.Comment) == 0 {
-			key.Comment = tpField.Tag.Get("comment")
-		}
-
-		delim := parseDelim(tpField.Tag.Get("delim"))
-		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
-			return fmt.Errorf("reflect field %q: %v", fieldName, err)
-		}
-
-	}
-	return nil
-}
-
-// ReflectFrom reflects section from given struct. It overwrites existing ones.
-func (s *Section) ReflectFrom(v interface{}) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-
-	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
-		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
-		// Clear sections to make sure none exists before adding the new ones
-		s.f.DeleteSection(s.name)
-
-		if typ.Kind() == reflect.Ptr {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-			return sec.reflectFrom(val.Elem())
-		}
-
-		slice := val.Slice(0, val.Len())
-		sliceOf := val.Type().Elem().Kind()
-		if sliceOf != reflect.Ptr {
-			return fmt.Errorf("not a slice of pointers")
-		}
-
-		for i := 0; i < slice.Len(); i++ {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-
-			err = sec.reflectFrom(slice.Index(i))
-			if err != nil {
-				return fmt.Errorf("reflect from %dth field: %v", i, err)
-			}
-		}
-
-		return nil
-	}
-
-	if typ.Kind() == reflect.Ptr {
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	return s.reflectFrom(val)
-}
-
-// ReflectFrom reflects file from given struct.
-func (f *File) ReflectFrom(v interface{}) error {
-	return f.Section("").ReflectFrom(v)
-}
-
-// ReflectFromWithMapper reflects data sources from given struct with name mapper.
-func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
-	cfg.NameMapper = mapper
-	return cfg.ReflectFrom(v)
-}
-
-// ReflectFrom reflects data sources from given struct.
-func ReflectFrom(cfg *File, v interface{}) error {
-	return ReflectFromWithMapper(cfg, v, nil)
-}
diff --git a/notifier/vendor/gorm.io/gorm/association.go b/notifier/vendor/gorm.io/gorm/association.go
index e3f51d17..f210ca0a 100644
--- a/notifier/vendor/gorm.io/gorm/association.go
+++ b/notifier/vendor/gorm.io/gorm/association.go
@@ -19,10 +19,10 @@ type Association struct {
 }
 
 func (db *DB) Association(column string) *Association {
-	association := &Association{DB: db}
+	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
 	table := db.Statement.Table
 
-	if err := db.Statement.Parse(db.Statement.Model); err == nil {
+	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
 		db.Statement.Table = table
 		association.Relationship = db.Statement.Schema.Relationships.Relations[column]
 
@@ -34,8 +34,6 @@ func (db *DB) Association(column string) *Association {
 		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
 			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
 		}
-	} else {
-		association.Error = err
 	}
 
 	return association
@@ -58,6 +56,8 @@ func (association *Association) Find(out interface{}, conds ...interface{}) erro
 }
 
 func (association *Association) Append(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		switch association.Relationship.Type {
 		case schema.HasOne, schema.BelongsTo:
@@ -73,6 +73,8 @@ func (association *Association) Append(values ...interface{}) error {
 }
 
 func (association *Association) Replace(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		reflectValue := association.DB.Statement.ReflectValue
 		rel := association.Relationship
@@ -195,6 +197,8 @@ func (association *Association) Replace(values ...interface{}) error {
 }
 
 func (association *Association) Delete(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		var (
 			reflectValue  = association.DB.Statement.ReflectValue
@@ -431,10 +435,49 @@ func (association *Association) saveAssociation(clear bool, values ...interface{
 				}
 			}
 
+			processMap := func(mapv reflect.Value) {
+				child := reflect.New(association.Relationship.FieldSchema.ModelType)
+
+				switch association.Relationship.Type {
+				case schema.HasMany:
+					for _, ref := range association.Relationship.References {
+						key := reflect.ValueOf(ref.ForeignKey.DBName)
+						if ref.OwnPrimaryKey {
+							v := ref.PrimaryKey.ReflectValueOf(association.DB.Statement.Context, source)
+							mapv.SetMapIndex(key, v)
+						} else if ref.PrimaryValue != "" {
+							mapv.SetMapIndex(key, reflect.ValueOf(ref.PrimaryValue))
+						}
+					}
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+				case schema.Many2Many:
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+
+					for _, key := range mapv.MapKeys() {
+						k := strings.ToLower(key.String())
+						if f, ok := association.Relationship.FieldSchema.FieldsByDBName[k]; ok {
+							_ = f.Set(association.DB.Statement.Context, child, mapv.MapIndex(key).Interface())
+						}
+					}
+					appendToFieldValues(child)
+				}
+			}
+
 			switch rv.Kind() {
+			case reflect.Map:
+				processMap(rv)
 			case reflect.Slice, reflect.Array:
 				for i := 0; i < rv.Len(); i++ {
-					appendToFieldValues(reflect.Indirect(rv.Index(i)).Addr())
+					elem := reflect.Indirect(rv.Index(i))
+					if elem.Kind() == reflect.Map {
+						processMap(elem)
+						continue
+					}
+					appendToFieldValues(elem.Addr())
 				}
 			case reflect.Struct:
 				if !rv.CanAddr() {
@@ -591,3 +634,32 @@ func (association *Association) buildCondition() *DB {
 
 	return tx
 }
+
+func expandValues(values ...any) (results []any) {
+	appendToResult := func(rv reflect.Value) {
+		// unwrap interface
+		if rv.IsValid() && rv.Kind() == reflect.Interface {
+			rv = rv.Elem()
+		}
+		if rv.IsValid() && rv.Kind() == reflect.Struct {
+			p := reflect.New(rv.Type())
+			p.Elem().Set(rv)
+			results = append(results, p.Interface())
+		} else if rv.IsValid() {
+			results = append(results, rv.Interface())
+		}
+	}
+
+	// Process each argument; if an argument is a slice/array, expand its elements
+	for _, value := range values {
+		rv := reflect.ValueOf(value)
+		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
+			for i := 0; i < rv.Len(); i++ {
+				appendToResult(rv.Index(i))
+			}
+		} else {
+			appendToResult(rv)
+		}
+	}
+	return
+}
diff --git a/notifier/vendor/gorm.io/gorm/callbacks.go b/notifier/vendor/gorm.io/gorm/callbacks.go
index 50b5b0e9..bd97f040 100644
--- a/notifier/vendor/gorm.io/gorm/callbacks.go
+++ b/notifier/vendor/gorm.io/gorm/callbacks.go
@@ -89,10 +89,16 @@ func (p *processor) Execute(db *DB) *DB {
 		resetBuildClauses = true
 	}
 
-	if optimizer, ok := db.Statement.Dest.(StatementModifier); ok {
+	if optimizer, ok := stmt.Dest.(StatementModifier); ok {
 		optimizer.ModifyStatement(stmt)
 	}
 
+	if db.DefaultContextTimeout > 0 {
+		if _, ok := stmt.Context.Deadline(); !ok {
+			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
+		}
+	}
+
 	// assign model values
 	if stmt.Model == nil {
 		stmt.Model = stmt.Dest
diff --git a/notifier/vendor/gorm.io/gorm/callbacks/create.go b/notifier/vendor/gorm.io/gorm/callbacks/create.go
index d8701f51..e5929adb 100644
--- a/notifier/vendor/gorm.io/gorm/callbacks/create.go
+++ b/notifier/vendor/gorm.io/gorm/callbacks/create.go
@@ -53,9 +53,13 @@ func Create(config *Config) func(db *gorm.DB) {
 				if _, ok := db.Statement.Clauses["RETURNING"]; !ok {
 					fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue))
 					for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue {
-						fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						if field.Readable {
+							fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						}
+					}
+					if len(fromColumns) > 0 {
+						db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 					}
-					db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 				}
 			}
 		}
@@ -76,8 +80,11 @@ func Create(config *Config) func(db *gorm.DB) {
 		ok, mode := hasReturning(db, supportReturning)
 		if ok {
 			if c, ok := db.Statement.Clauses["ON CONFLICT"]; ok {
-				if onConflict, _ := c.Expression.(clause.OnConflict); onConflict.DoNothing {
+				onConflict, _ := c.Expression.(clause.OnConflict)
+				if onConflict.DoNothing {
 					mode |= gorm.ScanOnConflictDoNothing
+				} else if len(onConflict.DoUpdates) > 0 || onConflict.UpdateAll {
+					mode |= gorm.ScanUpdate
 				}
 			}
 
@@ -122,6 +129,16 @@ func Create(config *Config) func(db *gorm.DB) {
 			pkFieldName = "@id"
 		)
 
+		if db.Statement.Schema != nil {
+			if db.Statement.Schema.PrioritizedPrimaryField == nil ||
+				!db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue ||
+				!db.Statement.Schema.PrioritizedPrimaryField.Readable {
+				return
+			}
+			pkField = db.Statement.Schema.PrioritizedPrimaryField
+			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
+		}
+
 		insertID, err := result.LastInsertId()
 		insertOk := err == nil && insertID > 0
 
@@ -132,14 +149,6 @@ func Create(config *Config) func(db *gorm.DB) {
 			return
 		}
 
-		if db.Statement.Schema != nil {
-			if db.Statement.Schema.PrioritizedPrimaryField == nil || !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue {
-				return
-			}
-			pkField = db.Statement.Schema.PrioritizedPrimaryField
-			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
-		}
-
 		// append @id column with value for auto-increment primary key
 		// the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1
 		switch values := db.Statement.Dest.(type) {
diff --git a/notifier/vendor/gorm.io/gorm/clause/association.go b/notifier/vendor/gorm.io/gorm/clause/association.go
new file mode 100644
index 00000000..a9bf7eb0
--- /dev/null
+++ b/notifier/vendor/gorm.io/gorm/clause/association.go
@@ -0,0 +1,35 @@
+package clause
+
+// AssociationOpType represents association operation types
+type AssociationOpType int
+
+const (
+	OpUnlink AssociationOpType = iota // Unlink association
+	OpDelete                          // Delete association records
+	OpUpdate                          // Update association records
+	OpCreate                          // Create association records with assignments
+)
+
+// Association represents an association operation
+type Association struct {
+	Association string            // Association name
+	Type        AssociationOpType // Operation type
+	Conditions  []Expression      // Filter conditions
+	Set         []Assignment      // Assignment operations (for Update and Create)
+	Values      []interface{}     // Values for Create operation
+}
+
+// AssociationAssigner is an interface for association operation providers
+type AssociationAssigner interface {
+	AssociationAssignments() []Association
+}
+
+// Assignments implements the Assigner interface so that AssociationOperation can be used as a Set method parameter
+func (ao Association) Assignments() []Assignment {
+	return []Assignment{}
+}
+
+// AssociationAssignments implements the AssociationAssigner interface
+func (ao Association) AssociationAssignments() []Association {
+	return []Association{ao}
+}
diff --git a/notifier/vendor/gorm.io/gorm/clause/set.go b/notifier/vendor/gorm.io/gorm/clause/set.go
index 75eb6bdd..cb5f36a0 100644
--- a/notifier/vendor/gorm.io/gorm/clause/set.go
+++ b/notifier/vendor/gorm.io/gorm/clause/set.go
@@ -9,6 +9,11 @@ type Assignment struct {
 	Value  interface{}
 }
 
+// Assigner assignments provider interface
+type Assigner interface {
+	Assignments() []Assignment
+}
+
 func (set Set) Name() string {
 	return "SET"
 }
@@ -37,6 +42,9 @@ func (set Set) MergeClause(clause *Clause) {
 	clause.Expression = Set(copiedAssignments)
 }
 
+// Assignments implements Assigner for Set.
+func (set Set) Assignments() []Assignment { return []Assignment(set) }
+
 func Assignments(values map[string]interface{}) Set {
 	keys := make([]string, 0, len(values))
 	for key := range values {
@@ -58,3 +66,6 @@ func AssignmentColumns(values []string) Set {
 	}
 	return assignments
 }
+
+// Assignments implements Assigner for a single Assignment.
+func (a Assignment) Assignments() []Assignment { return []Assignment{a} }
diff --git a/notifier/vendor/gorm.io/gorm/finisher_api.go b/notifier/vendor/gorm.io/gorm/finisher_api.go
index 57809d17..e601fe66 100644
--- a/notifier/vendor/gorm.io/gorm/finisher_api.go
+++ b/notifier/vendor/gorm.io/gorm/finisher_api.go
@@ -675,9 +675,9 @@ func (db *DB) Begin(opts ...*sql.TxOptions) *DB {
 	}
 
 	ctx := tx.Statement.Context
-	if _, ok := ctx.Deadline(); !ok {
-		if db.Config.DefaultTransactionTimeout > 0 {
-			ctx, _ = context.WithTimeout(ctx, db.Config.DefaultTransactionTimeout)
+	if db.DefaultTransactionTimeout > 0 {
+		if _, ok := ctx.Deadline(); !ok {
+			ctx, _ = context.WithTimeout(ctx, db.DefaultTransactionTimeout)
 		}
 	}
 
diff --git a/notifier/vendor/gorm.io/gorm/generics.go b/notifier/vendor/gorm.io/gorm/generics.go
index ad2d063f..79238d5f 100644
--- a/notifier/vendor/gorm.io/gorm/generics.go
+++ b/notifier/vendor/gorm.io/gorm/generics.go
@@ -3,12 +3,15 @@ package gorm
 import (
 	"context"
 	"database/sql"
+	"errors"
 	"fmt"
+	"reflect"
 	"sort"
 	"strings"
 
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/logger"
+	"gorm.io/gorm/schema"
 )
 
 type result struct {
@@ -35,10 +38,34 @@ type Interface[T any] interface {
 }
 
 type CreateInterface[T any] interface {
-	ChainInterface[T]
+	ExecInterface[T]
+	// chain methods available at start; return ChainInterface
+	Scopes(scopes ...func(db *Statement)) ChainInterface[T]
+	Where(query interface{}, args ...interface{}) ChainInterface[T]
+	Not(query interface{}, args ...interface{}) ChainInterface[T]
+	Or(query interface{}, args ...interface{}) ChainInterface[T]
+	Limit(offset int) ChainInterface[T]
+	Offset(offset int) ChainInterface[T]
+	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[T]
+	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[T]
+	Select(query string, args ...interface{}) ChainInterface[T]
+	Omit(columns ...string) ChainInterface[T]
+	MapColumns(m map[string]string) ChainInterface[T]
+	Distinct(args ...interface{}) ChainInterface[T]
+	Group(name string) ChainInterface[T]
+	Having(query interface{}, args ...interface{}) ChainInterface[T]
+	Order(value interface{}) ChainInterface[T]
+	Build(builder clause.Builder)
+
+	Delete(ctx context.Context) (rowsAffected int, err error)
+	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
+	Updates(ctx context.Context, t T) (rowsAffected int, err error)
+	Count(ctx context.Context, column string) (result int64, err error)
+
 	Table(name string, args ...interface{}) CreateInterface[T]
 	Create(ctx context.Context, r *T) error
 	CreateInBatches(ctx context.Context, r *[]T, batchSize int) error
+	Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T]
 }
 
 type ChainInterface[T any] interface {
@@ -58,15 +85,28 @@ type ChainInterface[T any] interface {
 	Group(name string) ChainInterface[T]
 	Having(query interface{}, args ...interface{}) ChainInterface[T]
 	Order(value interface{}) ChainInterface[T]
+	Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T]
 
 	Build(builder clause.Builder)
 
+	Table(name string, args ...interface{}) ChainInterface[T]
 	Delete(ctx context.Context) (rowsAffected int, err error)
 	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
 	Updates(ctx context.Context, t T) (rowsAffected int, err error)
 	Count(ctx context.Context, column string) (result int64, err error)
 }
 
+// SetUpdateOnlyInterface is returned by Set after chaining; only Update is allowed
+type SetUpdateOnlyInterface[T any] interface {
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
+// SetCreateOrUpdateInterface is returned by Set at start; Create or Update are allowed
+type SetCreateOrUpdateInterface[T any] interface {
+	Create(ctx context.Context) error
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
 type ExecInterface[T any] interface {
 	Scan(ctx context.Context, r interface{}) error
 	First(context.Context) (T, error)
@@ -142,13 +182,15 @@ func (c *g[T]) Raw(sql string, values ...interface{}) ExecInterface[T] {
 	return execG[T]{g: &g[T]{
 		db: c.db,
 		ops: append(c.ops, func(db *DB) *DB {
-			return db.Raw(sql, values...)
+			var r T
+			return db.Model(r).Raw(sql, values...)
 		}),
 	}}
 }
 
 func (c *g[T]) Exec(ctx context.Context, sql string, values ...interface{}) error {
-	return c.apply(ctx).Exec(sql, values...).Error
+	var r T
+	return c.apply(ctx).Model(r).Exec(sql, values...).Error
 }
 
 type createG[T any] struct {
@@ -161,6 +203,10 @@ func (c createG[T]) Table(name string, args ...interface{}) CreateInterface[T] {
 	})}
 }
 
+func (c createG[T]) Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c createG[T]) Create(ctx context.Context, r *T) error {
 	return c.g.apply(ctx).Create(r).Error
 }
@@ -187,6 +233,12 @@ func (c chainG[T]) with(v op) chainG[T] {
 	}
 }
 
+func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
+	return c.with(func(db *DB) *DB {
+		return db.Table(name, args...)
+	})
+}
+
 func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		for _, fc := range scopes {
@@ -196,12 +248,6 @@ func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	})
 }
 
-func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
-	return c.with(func(db *DB) *DB {
-		return db.Table(name, args...)
-	})
-}
-
 func (c chainG[T]) Where(query interface{}, args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Where(query, args...)
@@ -388,6 +434,10 @@ func (c chainG[T]) MapColumns(m map[string]string) ChainInterface[T] {
 	})
 }
 
+func (c chainG[T]) Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c chainG[T]) Distinct(args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Distinct(args...)
@@ -425,12 +475,12 @@ func (c chainG[T]) Preload(association string, query func(db PreloadBuilder) err
 			relation, ok := db.Statement.Schema.Relationships.Relations[association]
 			if !ok {
 				if preloadFields := strings.Split(association, "."); len(preloadFields) > 1 {
-					relationships := db.Statement.Schema.Relationships
+					relationships := &db.Statement.Schema.Relationships
 					for _, field := range preloadFields {
 						var ok bool
 						relation, ok = relationships.Relations[field]
 						if ok {
-							relationships = relation.FieldSchema.Relationships
+							relationships = &relation.FieldSchema.Relationships
 						} else {
 							db.AddError(fmt.Errorf("relation %s not found", association))
 							return nil
@@ -567,7 +617,7 @@ func (g execG[T]) First(ctx context.Context) (T, error) {
 
 func (g execG[T]) Scan(ctx context.Context, result interface{}) error {
 	var r T
-	err := g.g.apply(ctx).Model(r).Find(&result).Error
+	err := g.g.apply(ctx).Model(r).Find(result).Error
 	return err
 }
 
@@ -603,3 +653,242 @@ func (g execG[T]) Row(ctx context.Context) *sql.Row {
 func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) {
 	return g.g.apply(ctx).Rows()
 }
+
+func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdateG[T] {
+	var (
+		assigns  []clause.Assignment
+		assocOps []clause.Association
+	)
+
+	for _, item := range items {
+		// Check if it's an AssociationAssigner
+		if assocAssigner, ok := item.(clause.AssociationAssigner); ok {
+			assocOps = append(assocOps, assocAssigner.AssociationAssignments()...)
+		} else {
+			assigns = append(assigns, item.Assignments()...)
+		}
+	}
+
+	return setCreateOrUpdateG[T]{
+		c:        c,
+		assigns:  assigns,
+		assocOps: assocOps,
+	}
+}
+
+// setCreateOrUpdateG[T] is a struct that holds operations to be executed in a batch.
+// It supports regular assignments and association operations.
+type setCreateOrUpdateG[T any] struct {
+	c        chainG[T]
+	assigns  []clause.Assignment
+	assocOps []clause.Association
+}
+
+func (s setCreateOrUpdateG[T]) Update(ctx context.Context) (rowsAffected int, err error) {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return 0, err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		var r T
+		res := s.c.g.apply(ctx).Model(r).Clauses(clause.Set(s.assigns)).Updates(map[string]interface{}{})
+		return int(res.RowsAffected), res.Error
+	}
+
+	return 0, nil
+}
+
+func (s setCreateOrUpdateG[T]) Create(ctx context.Context) error {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		data := make(map[string]interface{}, len(s.assigns))
+		for _, a := range s.assigns {
+			data[a.Column.Name] = a.Value
+		}
+		var r T
+		return s.c.g.apply(ctx).Model(r).Create(data).Error
+	}
+
+	return nil
+}
+
+// executeAssociationOperation executes an association operation
+func (s setCreateOrUpdateG[T]) executeAssociationOperation(ctx context.Context, op clause.Association) error {
+	var r T
+	base := s.c.g.apply(ctx).Model(r)
+
+	switch op.Type {
+	case clause.OpCreate:
+		return s.handleAssociationCreate(ctx, base, op)
+	case clause.OpUnlink, clause.OpDelete, clause.OpUpdate:
+		return s.handleAssociation(ctx, base, op)
+	default:
+		return fmt.Errorf("unknown association operation type: %v", op.Type)
+	}
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociationCreate(ctx context.Context, base *DB, op clause.Association) error {
+	if len(op.Set) > 0 {
+		return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+			data := make(map[string]interface{}, len(op.Set))
+			for _, a := range op.Set {
+				data[a.Column.Name] = a.Value
+			}
+			return assoc.Append(data)
+		}, op.Association)
+	}
+
+	return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+		return assoc.Append(op.Values...)
+	}, op.Association)
+}
+
+// handleAssociationForOwners is a helper function that handles associations for all owners
+func (s setCreateOrUpdateG[T]) handleAssociationForOwners(base *DB, ctx context.Context, handler func(owner T, association *Association) error, associationName string) error {
+	var owners []T
+	if err := base.Find(&owners).Error; err != nil {
+		return err
+	}
+
+	for _, owner := range owners {
+		assoc := base.Session(&Session{NewDB: true, Context: ctx}).Model(&owner).Association(associationName)
+		if assoc.Error != nil {
+			return assoc.Error
+		}
+
+		if err := handler(owner, assoc); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, base *DB, op clause.Association) error {
+	assoc := base.Association(op.Association)
+	if assoc.Error != nil {
+		return assoc.Error
+	}
+
+	var (
+		rel            = assoc.Relationship
+		assocModel     = reflect.New(rel.FieldSchema.ModelType).Interface()
+		fkNil          = map[string]any{}
+		setMap         = make(map[string]any, len(op.Set))
+		ownerPKNames   []string
+		ownerFKNames   []string
+		primaryColumns []any
+		foreignColumns []any
+	)
+
+	for _, a := range op.Set {
+		setMap[a.Column.Name] = a.Value
+	}
+
+	for _, ref := range rel.References {
+		fkNil[ref.ForeignKey.DBName] = nil
+
+		if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerPKNames = append(ownerPKNames, ref.PrimaryKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+			foreignColumns = append(foreignColumns, clause.Column{Name: ref.ForeignKey.DBName})
+		} else if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerFKNames = append(ownerFKNames, ref.ForeignKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+		}
+	}
+
+	assocDB := s.c.g.db.Session(&Session{NewDB: true, Context: ctx}).Model(assocModel).Where(op.Conditions)
+
+	switch rel.Type {
+	case schema.HasOne, schema.HasMany:
+		assocDB = assocDB.Where("? IN (?)", foreignColumns, base.Select(ownerPKNames))
+		switch op.Type {
+		case clause.OpUnlink:
+			return assocDB.Updates(fkNil).Error
+		case clause.OpDelete:
+			return assocDB.Delete(assocModel).Error
+		case clause.OpUpdate:
+			return assocDB.Updates(setMap).Error
+		}
+	case schema.BelongsTo:
+		switch op.Type {
+		case clause.OpDelete:
+			return base.Transaction(func(tx *DB) error {
+				assocDB.Statement.ConnPool = tx.Statement.ConnPool
+				base.Statement.ConnPool = tx.Statement.ConnPool
+
+				if err := assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Delete(assocModel).Error; err != nil {
+					return err
+				}
+				return base.Updates(fkNil).Error
+			})
+		case clause.OpUnlink:
+			return base.Updates(fkNil).Error
+		case clause.OpUpdate:
+			return assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Updates(setMap).Error
+		}
+	case schema.Many2Many:
+		joinModel := reflect.New(rel.JoinTable.ModelType).Interface()
+		joinDB := base.Session(&Session{NewDB: true, Context: ctx}).Model(joinModel)
+
+		// EXISTS owners: owners.pk = join.owner_fk for all owner refs
+		ownersExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.Schema.Table).Select("1")
+		for _, ref := range rel.References {
+			if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				ownersExists = ownersExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.Schema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+
+		// EXISTS related: related.pk = join.rel_fk for all related refs, plus optional conditions
+		relatedExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Select("1")
+		for _, ref := range rel.References {
+			if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				relatedExists = relatedExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+		relatedExists = relatedExists.Where(op.Conditions)
+
+		switch op.Type {
+		case clause.OpUnlink, clause.OpDelete:
+			joinDB = joinDB.Where("EXISTS (?)", ownersExists)
+			if len(op.Conditions) > 0 {
+				joinDB = joinDB.Where("EXISTS (?)", relatedExists)
+			}
+			return joinDB.Delete(nil).Error
+		case clause.OpUpdate:
+			// Update related table rows that have join rows matching owners
+			relatedDB := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Where(op.Conditions)
+
+			// correlated join subquery: join.rel_fk = related.pk AND EXISTS owners
+			joinSub := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.JoinTable.Table).Select("1")
+			for _, ref := range rel.References {
+				if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+					joinSub = joinSub.Where(clause.Eq{
+						Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+						Value:  clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					})
+				}
+			}
+			joinSub = joinSub.Where("EXISTS (?)", ownersExists)
+			return relatedDB.Where("EXISTS (?)", joinSub).Updates(setMap).Error
+		}
+	}
+	return errors.New("unsupported relationship")
+}
diff --git a/notifier/vendor/gorm.io/gorm/gorm.go b/notifier/vendor/gorm.io/gorm/gorm.go
index 67889262..a209bb09 100644
--- a/notifier/vendor/gorm.io/gorm/gorm.go
+++ b/notifier/vendor/gorm.io/gorm/gorm.go
@@ -23,6 +23,7 @@ type Config struct {
 	// You can disable it by setting `SkipDefaultTransaction` to true
 	SkipDefaultTransaction    bool
 	DefaultTransactionTimeout time.Duration
+	DefaultContextTimeout     time.Duration
 
 	// NamingStrategy tables, columns naming strategy
 	NamingStrategy schema.Namer
@@ -137,6 +138,14 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
 		return isConfig && !isConfig2
 	})
 
+	if len(opts) > 0 {
+		if c, ok := opts[0].(*Config); ok {
+			config = c
+		} else {
+			opts = append([]Option{config}, opts...)
+		}
+	}
+
 	var skipAfterInitialize bool
 	for _, opt := range opts {
 		if opt != nil {
diff --git a/notifier/vendor/gorm.io/gorm/logger/slog.go b/notifier/vendor/gorm.io/gorm/logger/slog.go
new file mode 100644
index 00000000..613234ca
--- /dev/null
+++ b/notifier/vendor/gorm.io/gorm/logger/slog.go
@@ -0,0 +1,100 @@
+//go:build go1.21
+
+package logger
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"log/slog"
+	"time"
+)
+
+type slogLogger struct {
+	Logger                    *slog.Logger
+	LogLevel                  LogLevel
+	SlowThreshold             time.Duration
+	Parameterized             bool
+	Colorful                  bool // Ignored in slog
+	IgnoreRecordNotFoundError bool
+}
+
+func NewSlogLogger(logger *slog.Logger, config Config) Interface {
+	return &slogLogger{
+		Logger:                    logger,
+		LogLevel:                  config.LogLevel,
+		SlowThreshold:             config.SlowThreshold,
+		Parameterized:             config.ParameterizedQueries,
+		IgnoreRecordNotFoundError: config.IgnoreRecordNotFoundError,
+	}
+}
+
+func (l *slogLogger) LogMode(level LogLevel) Interface {
+	newLogger := *l
+	newLogger.LogLevel = level
+	return &newLogger
+}
+
+func (l *slogLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Info {
+		l.Logger.InfoContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Warn {
+		l.Logger.WarnContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Error {
+		l.Logger.ErrorContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	if l.LogLevel <= Silent {
+		return
+	}
+
+	elapsed := time.Since(begin)
+	sql, rows := fc()
+	fields := []slog.Attr{
+		slog.String("duration", fmt.Sprintf("%.3fms", float64(elapsed.Nanoseconds())/1e6)),
+		slog.String("sql", sql),
+	}
+
+	if rows != -1 {
+		fields = append(fields, slog.Int64("rows", rows))
+	}
+
+	switch {
+	case err != nil && (!l.IgnoreRecordNotFoundError || !errors.Is(err, ErrRecordNotFound)):
+		fields = append(fields, slog.String("error", err.Error()))
+		l.Logger.ErrorContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.SlowThreshold != 0 && elapsed > l.SlowThreshold:
+		l.Logger.WarnContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.LogLevel >= Info:
+		l.Logger.InfoContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+	}
+}
+
+// ParamsFilter filter params
+func (l *slogLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) {
+	if l.Parameterized {
+		return sql, nil
+	}
+	return sql, params
+}
diff --git a/notifier/vendor/gorm.io/gorm/migrator/migrator.go b/notifier/vendor/gorm.io/gorm/migrator/migrator.go
index cec4e30f..50a36d10 100644
--- a/notifier/vendor/gorm.io/gorm/migrator/migrator.go
+++ b/notifier/vendor/gorm.io/gorm/migrator/migrator.go
@@ -474,7 +474,6 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 	// found, smart migrate
 	fullDataType := strings.TrimSpace(strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL))
 	realDataType := strings.ToLower(columnType.DatabaseTypeName())
-
 	var (
 		alterColumn bool
 		isSameType  = fullDataType == realDataType
@@ -513,8 +512,19 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 				}
 			}
 		}
+	}
 
-		// check precision
+	// check precision
+	if realDataType == "decimal" || realDataType == "numeric" &&
+		regexp.MustCompile(realDataType+`\(.*\)`).FindString(fullDataType) != "" { // if realDataType has no precision,ignore
+		precision, scale, ok := columnType.DecimalSize()
+		if ok {
+			if !strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d,%d)", realDataType, precision, scale)) &&
+				!strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d)", realDataType, precision)) {
+				alterColumn = true
+			}
+		}
+	} else {
 		if precision, _, ok := columnType.DecimalSize(); ok && int64(field.Precision) != precision {
 			if regexp.MustCompile(fmt.Sprintf("[^0-9]%d[^0-9]", field.Precision)).MatchString(m.DataTypeOf(field)) {
 				alterColumn = true
diff --git a/notifier/vendor/gorm.io/gorm/schema/field.go b/notifier/vendor/gorm.io/gorm/schema/field.go
index a6ff1a72..de797402 100644
--- a/notifier/vendor/gorm.io/gorm/schema/field.go
+++ b/notifier/vendor/gorm.io/gorm/schema/field.go
@@ -448,16 +448,17 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 }
 
 // create valuer, setter when parse struct
-func (field *Field) setupValuerAndSetter() {
+func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
 	// Setup NewValuePool
 	field.setupNewValuePool()
 
 	// ValueOf returns field's value and if it is zero
 	fieldIndex := field.StructField.Index[0]
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
-			fieldValue := reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
+			v = reflect.Indirect(v)
+			fieldValue := v.Field(fieldIndex)
 			return fieldValue.Interface(), fieldValue.IsZero()
 		}
 	default:
@@ -504,9 +505,10 @@ func (field *Field) setupValuerAndSetter() {
 
 	// ReflectValueOf returns field's reflect value
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
-			return reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
+			v = reflect.Indirect(v)
+			return v.Field(fieldIndex)
 		}
 	default:
 		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
diff --git a/notifier/vendor/gorm.io/gorm/schema/relationship.go b/notifier/vendor/gorm.io/gorm/schema/relationship.go
index f1ace924..0535bba4 100644
--- a/notifier/vendor/gorm.io/gorm/schema/relationship.go
+++ b/notifier/vendor/gorm.io/gorm/schema/relationship.go
@@ -75,9 +75,7 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
 		}
 	)
 
-	cacheStore := schema.cacheStore
-
-	if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
+	if relation.FieldSchema, err = getOrParse(fieldValue, schema.cacheStore, schema.namer); err != nil {
 		schema.err = fmt.Errorf("failed to parse field: %s, error: %w", field.Name, err)
 		return nil
 	}
@@ -147,6 +145,9 @@ func hasPolymorphicRelation(tagSettings map[string]string) bool {
 }
 
 func (schema *Schema) setRelation(relation *Relationship) {
+	schema.Relationships.Mux.Lock()
+	defer schema.Relationships.Mux.Unlock()
+
 	// set non-embedded relation
 	if rel := schema.Relationships.Relations[relation.Name]; rel != nil {
 		if len(rel.Field.BindNames) > 1 {
@@ -590,6 +591,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 	// build references
 	for idx, foreignField := range foreignFields {
 		// use same data type for foreign keys
+		schema.Relationships.Mux.Lock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Lock()
+		}
 		if copyableDataType(primaryFields[idx].DataType) {
 			foreignField.DataType = primaryFields[idx].DataType
 		}
@@ -597,6 +602,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 		if foreignField.Size == 0 {
 			foreignField.Size = primaryFields[idx].Size
 		}
+		schema.Relationships.Mux.Unlock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Unlock()
+		}
 
 		relation.References = append(relation.References, &Reference{
 			PrimaryKey:    primaryFields[idx],
diff --git a/notifier/vendor/gorm.io/gorm/schema/schema.go b/notifier/vendor/gorm.io/gorm/schema/schema.go
index db236797..9419846b 100644
--- a/notifier/vendor/gorm.io/gorm/schema/schema.go
+++ b/notifier/vendor/gorm.io/gorm/schema/schema.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"go/ast"
+	"path"
 	"reflect"
 	"strings"
 	"sync"
@@ -59,14 +60,14 @@ type Schema struct {
 	cacheStore                *sync.Map
 }
 
-func (schema Schema) String() string {
+func (schema *Schema) String() string {
 	if schema.ModelType.Name() == "" {
 		return fmt.Sprintf("%s(%s)", schema.Name, schema.Table)
 	}
 	return fmt.Sprintf("%s.%s", schema.ModelType.PkgPath(), schema.ModelType.Name())
 }
 
-func (schema Schema) MakeSlice() reflect.Value {
+func (schema *Schema) MakeSlice() reflect.Value {
 	slice := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(schema.ModelType)), 0, 20)
 	results := reflect.New(slice.Type())
 	results.Elem().Set(slice)
@@ -74,7 +75,7 @@ func (schema Schema) MakeSlice() reflect.Value {
 	return results
 }
 
-func (schema Schema) LookUpField(name string) *Field {
+func (schema *Schema) LookUpField(name string) *Field {
 	if field, ok := schema.FieldsByDBName[name]; ok {
 		return field
 	}
@@ -92,10 +93,7 @@ func (schema Schema) LookUpField(name string) *Field {
 //		}
 //		ID string // is selected by LookUpFieldByBindName([]string{"ID"}, "ID")
 //	}
-func (schema Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
-	if len(bindNames) == 0 {
-		return nil
-	}
+func (schema *Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
 	for i := len(bindNames) - 1; i >= 0; i-- {
 		find := strings.Join(bindNames[:i], ".") + "." + name
 		if field, ok := schema.FieldsByBindName[find]; ok {
@@ -113,6 +111,14 @@ type TablerWithNamer interface {
 	TableName(Namer) string
 }
 
+var callbackTypes = []callbackType{
+	callbackTypeBeforeCreate, callbackTypeAfterCreate,
+	callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
+	callbackTypeBeforeSave, callbackTypeAfterSave,
+	callbackTypeBeforeDelete, callbackTypeAfterDelete,
+	callbackTypeAfterFind,
+}
+
 // Parse get data type from dialector
 func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	return ParseWithSpecialTableName(dest, cacheStore, namer, "")
@@ -124,34 +130,33 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
 	}
 
-	value := reflect.ValueOf(dest)
-	if value.Kind() == reflect.Ptr && value.IsNil() {
-		value = reflect.New(value.Type().Elem())
-	}
-	modelType := reflect.Indirect(value).Type()
-
-	if modelType.Kind() == reflect.Interface {
-		modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
-	}
-
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+	modelType := reflect.ValueOf(dest).Type()
+	if modelType.Kind() == reflect.Ptr {
 		modelType = modelType.Elem()
 	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		if modelType.Kind() == reflect.Interface {
+			modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
+		}
+
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	// Cache the Schema for performance,
 	// Use the modelType or modelType + schemaTable (if it present) as cache key.
-	var schemaCacheKey interface{}
+	var schemaCacheKey interface{} = modelType
 	if specialTableName != "" {
 		schemaCacheKey = fmt.Sprintf("%p-%s", modelType, specialTableName)
-	} else {
-		schemaCacheKey = modelType
 	}
 
 	// Load exist schema cache, return if exists
@@ -162,28 +167,29 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return s, s.err
 	}
 
+	var tableName string
 	modelValue := reflect.New(modelType)
-	tableName := namer.TableName(modelType.Name())
-	if tabler, ok := modelValue.Interface().(Tabler); ok {
+	if specialTableName != "" {
+		tableName = specialTableName
+	} else if en, ok := namer.(embeddedNamer); ok {
+		tableName = en.Table
+	} else if tabler, ok := modelValue.Interface().(Tabler); ok {
 		tableName = tabler.TableName()
-	}
-	if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
+	} else if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
 		tableName = tabler.TableName(namer)
-	}
-	if en, ok := namer.(embeddedNamer); ok {
-		tableName = en.Table
-	}
-	if specialTableName != "" && specialTableName != tableName {
-		tableName = specialTableName
+	} else {
+		tableName = namer.TableName(modelType.Name())
 	}
 
 	schema := &Schema{
 		Name:             modelType.Name(),
 		ModelType:        modelType,
 		Table:            tableName,
-		FieldsByName:     map[string]*Field{},
-		FieldsByBindName: map[string]*Field{},
-		FieldsByDBName:   map[string]*Field{},
+		DBNames:          make([]string, 0, 10),
+		Fields:           make([]*Field, 0, 10),
+		FieldsByName:     make(map[string]*Field, 10),
+		FieldsByBindName: make(map[string]*Field, 10),
+		FieldsByDBName:   make(map[string]*Field, 10),
 		Relationships:    Relationships{Relations: map[string]*Relationship{}},
 		cacheStore:       cacheStore,
 		namer:            namer,
@@ -227,8 +233,9 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 				schema.FieldsByBindName[bindName] = field
 
 				if v != nil && v.PrimaryKey {
+					// remove the existing primary key field
 					for idx, f := range schema.PrimaryFields {
-						if f == v {
+						if f.DBName == v.DBName {
 							schema.PrimaryFields = append(schema.PrimaryFields[0:idx], schema.PrimaryFields[idx+1:]...)
 						}
 					}
@@ -247,7 +254,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 			schema.FieldsByBindName[bindName] = field
 		}
 
-		field.setupValuerAndSetter()
+		field.setupValuerAndSetter(modelType)
 	}
 
 	prioritizedPrimaryField := schema.LookUpField("id")
@@ -283,10 +290,37 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		schema.PrimaryFieldDBNames = append(schema.PrimaryFieldDBNames, field.DBName)
 	}
 
+	_, embedded := schema.cacheStore.Load(embeddedCacheKey)
+	relationshipFields := []*Field{}
 	for _, field := range schema.Fields {
 		if field.DataType != "" && field.HasDefaultValue && field.DefaultValueInterface == nil {
 			schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field)
 		}
+
+		if !embedded {
+			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
+				relationshipFields = append(relationshipFields, field)
+				schema.FieldsByName[field.Name] = field
+				schema.FieldsByBindName[field.BindName()] = field
+			}
+
+			fieldValue := reflect.New(field.IndirectFieldType).Interface()
+			if fc, ok := fieldValue.(CreateClausesInterface); ok {
+				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(QueryClausesInterface); ok {
+				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(UpdateClausesInterface); ok {
+				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(DeleteClausesInterface); ok {
+				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
+			}
+		}
 	}
 
 	if field := schema.PrioritizedPrimaryField; field != nil {
@@ -303,24 +337,6 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}
 
-	callbackTypes := []callbackType{
-		callbackTypeBeforeCreate, callbackTypeAfterCreate,
-		callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
-		callbackTypeBeforeSave, callbackTypeAfterSave,
-		callbackTypeBeforeDelete, callbackTypeAfterDelete,
-		callbackTypeAfterFind,
-	}
-	for _, cbName := range callbackTypes {
-		if methodValue := callBackToMethodValue(modelValue, cbName); methodValue.IsValid() {
-			switch methodValue.Type().String() {
-			case "func(*gorm.DB) error": // TODO hack
-				reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
-			default:
-				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
-			}
-		}
-	}
-
 	// Cache the schema
 	if v, loaded := cacheStore.LoadOrStore(schemaCacheKey, schema); loaded {
 		s := v.(*Schema)
@@ -336,84 +352,47 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}()
 
-	if _, embedded := schema.cacheStore.Load(embeddedCacheKey); !embedded {
-		for _, field := range schema.Fields {
-			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
-				if schema.parseRelation(field); schema.err != nil {
-					return schema, schema.err
+	for _, cbName := range callbackTypes {
+		if methodValue := modelValue.MethodByName(string(cbName)); methodValue.IsValid() {
+			switch methodValue.Type().String() {
+			case "func(*gorm.DB) error":
+				expectedPkgPath := path.Dir(reflect.TypeOf(schema).Elem().PkgPath())
+				if inVarPkg := methodValue.Type().In(0).Elem().PkgPath(); inVarPkg == expectedPkgPath {
+					reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
 				} else {
-					schema.FieldsByName[field.Name] = field
-					schema.FieldsByBindName[field.BindName()] = field
+					logger.Default.Warn(context.Background(), "In model %v, the hook function `%v(*gorm.DB) error` has an incorrect parameter type. The expected parameter type is `%v`, but the provided type is `%v`.", schema, cbName, expectedPkgPath, inVarPkg)
+					// PASS
 				}
+			default:
+				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
 			}
+		}
+	}
 
-			fieldValue := reflect.New(field.IndirectFieldType)
-			fieldInterface := fieldValue.Interface()
-			if fc, ok := fieldInterface.(CreateClausesInterface); ok {
-				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(QueryClausesInterface); ok {
-				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(UpdateClausesInterface); ok {
-				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(DeleteClausesInterface); ok {
-				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
-			}
+	// parse relationships
+	for _, field := range relationshipFields {
+		if schema.parseRelation(field); schema.err != nil {
+			return schema, schema.err
 		}
 	}
 
 	return schema, schema.err
 }
 
-// This unrolling is needed to show to the compiler the exact set of methods
-// that can be used on the modelType.
-// Prior to go1.22 any use of MethodByName would cause the linker to
-// abandon dead code elimination for the entire binary.
-// As of go1.22 the compiler supports one special case of a string constant
-// being passed to MethodByName. For enterprise customers or those building
-// large binaries, this gives a significant reduction in binary size.
-// https://github.com/golang/go/issues/62257
-func callBackToMethodValue(modelType reflect.Value, cbType callbackType) reflect.Value {
-	switch cbType {
-	case callbackTypeBeforeCreate:
-		return modelType.MethodByName(string(callbackTypeBeforeCreate))
-	case callbackTypeAfterCreate:
-		return modelType.MethodByName(string(callbackTypeAfterCreate))
-	case callbackTypeBeforeUpdate:
-		return modelType.MethodByName(string(callbackTypeBeforeUpdate))
-	case callbackTypeAfterUpdate:
-		return modelType.MethodByName(string(callbackTypeAfterUpdate))
-	case callbackTypeBeforeSave:
-		return modelType.MethodByName(string(callbackTypeBeforeSave))
-	case callbackTypeAfterSave:
-		return modelType.MethodByName(string(callbackTypeAfterSave))
-	case callbackTypeBeforeDelete:
-		return modelType.MethodByName(string(callbackTypeBeforeDelete))
-	case callbackTypeAfterDelete:
-		return modelType.MethodByName(string(callbackTypeAfterDelete))
-	case callbackTypeAfterFind:
-		return modelType.MethodByName(string(callbackTypeAfterFind))
-	default:
-		return reflect.ValueOf(nil)
-	}
-}
-
 func getOrParse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	modelType := reflect.ValueOf(dest).Type()
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
-		modelType = modelType.Elem()
-	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	if v, ok := cacheStore.Load(modelType); ok {
diff --git a/notifier/vendor/gorm.io/gorm/schema/utils.go b/notifier/vendor/gorm.io/gorm/schema/utils.go
index fa1c65d4..d4fe252e 100644
--- a/notifier/vendor/gorm.io/gorm/schema/utils.go
+++ b/notifier/vendor/gorm.io/gorm/schema/utils.go
@@ -121,6 +121,17 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
 	}
 
 	switch reflectValue.Kind() {
+	case reflect.Map:
+		results = [][]interface{}{make([]interface{}, len(fields))}
+		for idx, field := range fields {
+			mapValue := reflectValue.MapIndex(reflect.ValueOf(field.DBName))
+			if mapValue.IsZero() {
+				mapValue = reflectValue.MapIndex(reflect.ValueOf(field.Name))
+			}
+			results[0][idx] = mapValue.Interface()
+		}
+
+		dataResults[utils.ToStringKey(results[0]...)] = []reflect.Value{reflectValue}
 	case reflect.Struct:
 		results = [][]interface{}{make([]interface{}, len(fields))}
 
diff --git a/notifier/vendor/gorm.io/gorm/statement.go b/notifier/vendor/gorm.io/gorm/statement.go
index c6183724..736087d7 100644
--- a/notifier/vendor/gorm.io/gorm/statement.go
+++ b/notifier/vendor/gorm.io/gorm/statement.go
@@ -96,7 +96,9 @@ func (stmt *Statement) QuoteTo(writer clause.Writer, field interface{}) {
 		if v.Name == clause.CurrentTable {
 			if stmt.TableExpr != nil {
 				stmt.TableExpr.Build(stmt)
-			} else {
+			} else if stmt.Table != "" {
+				write(v.Raw, stmt.Table)
+			} else if stmt.AddError(stmt.Parse(stmt.Model)) == nil {
 				write(v.Raw, stmt.Table)
 			}
 		} else {
@@ -334,6 +336,8 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 		switch v := arg.(type) {
 		case clause.Expression:
 			conds = append(conds, v)
+		case []clause.Expression:
+			conds = append(conds, v...)
 		case *DB:
 			v.executeScopes()
 
@@ -341,7 +345,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 				if where, ok := cs.Expression.(clause.Where); ok {
 					if len(where.Exprs) == 1 {
 						if orConds, ok := where.Exprs[0].(clause.OrConditions); ok {
-							where.Exprs[0] = clause.AndConditions(orConds)
+							if len(orConds.Exprs) == 1 {
+								where.Exprs[0] = clause.AndConditions(orConds)
+							}
 						}
 					}
 					conds = append(conds, clause.And(where.Exprs...))
@@ -362,6 +368,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 
 			for _, key := range keys {
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				conds = append(conds, clause.Eq{Column: column, Value: v[key]})
 			}
 		case map[string]interface{}:
@@ -374,6 +383,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 			for _, key := range keys {
 				reflectValue := reflect.Indirect(reflect.ValueOf(v[key]))
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				switch reflectValue.Kind() {
 				case reflect.Slice, reflect.Array:
 					if _, ok := v[key].(driver.Valuer); ok {
@@ -650,12 +662,15 @@ func (stmt *Statement) Changed(fields ...string) bool {
 				for destValue.Kind() == reflect.Ptr {
 					destValue = destValue.Elem()
 				}
-
-				changedValue, zero := field.ValueOf(stmt.Context, destValue)
-				if v {
-					return !utils.AssertEqual(changedValue, fieldValue)
+				if descSchema, err := schema.Parse(stmt.Dest, stmt.DB.cacheStore, stmt.DB.NamingStrategy); err == nil {
+					if destField := descSchema.LookUpField(field.DBName); destField != nil {
+						changedValue, zero := destField.ValueOf(stmt.Context, destValue)
+						if v {
+							return !utils.AssertEqual(changedValue, fieldValue)
+						}
+						return !zero && !utils.AssertEqual(changedValue, fieldValue)
+					}
 				}
-				return !zero && !utils.AssertEqual(changedValue, fieldValue)
 			}
 		}
 		return false
diff --git a/notifier/vendor/modules.txt b/notifier/vendor/modules.txt
index 392e10b1..c8f68649 100644
--- a/notifier/vendor/modules.txt
+++ b/notifier/vendor/modules.txt
@@ -161,9 +161,10 @@ github.com/felixge/httpsnoop
 # github.com/firefart/nonamedreturns v1.0.5
 ## explicit; go 1.18
 github.com/firefart/nonamedreturns/analyzer
-# github.com/fsnotify/fsnotify v1.6.0
-## explicit; go 1.16
+# github.com/fsnotify/fsnotify v1.8.0
+## explicit; go 1.17
 github.com/fsnotify/fsnotify
+github.com/fsnotify/fsnotify/internal
 # github.com/fzipp/gocyclo v0.6.0
 ## explicit; go 1.18
 github.com/fzipp/gocyclo
@@ -202,7 +203,7 @@ github.com/go-toolsmith/strparse
 # github.com/go-toolsmith/typep v1.1.0
 ## explicit; go 1.16
 github.com/go-toolsmith/typep
-# github.com/go-viper/mapstructure/v2 v2.2.1
+# github.com/go-viper/mapstructure/v2 v2.4.0
 ## explicit; go 1.18
 github.com/go-viper/mapstructure/v2
 github.com/go-viper/mapstructure/v2/internal/errors
@@ -437,8 +438,8 @@ github.com/gostaticanalysis/forcetypeassert
 # github.com/gostaticanalysis/nilerr v0.1.1
 ## explicit; go 1.15
 github.com/gostaticanalysis/nilerr
-# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
-## explicit; go 1.23.0
+# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
+## explicit; go 1.24.0
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/casing
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/codegenerator
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor
@@ -466,18 +467,6 @@ github.com/hashicorp/go-version
 ## explicit; go 1.18
 github.com/hashicorp/golang-lru/v2/internal
 github.com/hashicorp/golang-lru/v2/simplelru
-# github.com/hashicorp/hcl v1.0.0
-## explicit
-github.com/hashicorp/hcl
-github.com/hashicorp/hcl/hcl/ast
-github.com/hashicorp/hcl/hcl/parser
-github.com/hashicorp/hcl/hcl/printer
-github.com/hashicorp/hcl/hcl/scanner
-github.com/hashicorp/hcl/hcl/strconv
-github.com/hashicorp/hcl/hcl/token
-github.com/hashicorp/hcl/json/parser
-github.com/hashicorp/hcl/json/scanner
-github.com/hashicorp/hcl/json/token
 # github.com/hexops/gotextdiff v1.0.3
 ## explicit; go 1.16
 github.com/hexops/gotextdiff
@@ -492,8 +481,8 @@ github.com/jackc/pgpassfile
 # github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
 ## explicit; go 1.14
 github.com/jackc/pgservicefile
-# github.com/jackc/pgx/v5 v5.7.1
-## explicit; go 1.21
+# github.com/jackc/pgx/v5 v5.7.6
+## explicit; go 1.23.0
 github.com/jackc/pgx/v5
 github.com/jackc/pgx/v5/internal/iobufpool
 github.com/jackc/pgx/v5/internal/pgio
@@ -584,9 +573,6 @@ github.com/lufia/plan9stats
 # github.com/macabu/inamedparam v0.1.3
 ## explicit; go 1.20
 github.com/macabu/inamedparam
-# github.com/magiconair/properties v1.8.7
-## explicit; go 1.19
-github.com/magiconair/properties
 # github.com/maratori/testableexamples v1.0.0
 ## explicit; go 1.19
 github.com/maratori/testableexamples/pkg/testableexamples
@@ -617,9 +603,6 @@ github.com/mgechev/revive/rule
 # github.com/mitchellh/go-homedir v1.1.0
 ## explicit
 github.com/mitchellh/go-homedir
-# github.com/mitchellh/mapstructure v1.5.0
-## explicit; go 1.14
-github.com/mitchellh/mapstructure
 # github.com/moricho/tparallel v0.3.2
 ## explicit; go 1.20
 github.com/moricho/tparallel
@@ -689,8 +672,8 @@ github.com/prometheus/client_model/go
 ## explicit; go 1.21
 github.com/prometheus/common/expfmt
 github.com/prometheus/common/model
-# github.com/prometheus/procfs v0.15.1
-## explicit; go 1.20
+# github.com/prometheus/procfs v0.17.0
+## explicit; go 1.23.0
 github.com/prometheus/procfs
 github.com/prometheus/procfs/internal/fs
 github.com/prometheus/procfs/internal/util
@@ -739,24 +722,24 @@ github.com/rogpeppe/go-internal/internal/syscall/windows
 github.com/rogpeppe/go-internal/internal/syscall/windows/sysdll
 github.com/rogpeppe/go-internal/lockedfile
 github.com/rogpeppe/go-internal/lockedfile/internal/filelock
-# github.com/rs/cors v1.11.0
+# github.com/rs/cors v1.11.1
 ## explicit; go 1.13
 github.com/rs/cors
 github.com/rs/cors/internal
-# github.com/rs/zerolog v1.33.0
+# github.com/rs/zerolog v1.34.0
 ## explicit; go 1.15
 github.com/rs/zerolog
 github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/event-processor v0.0.0-00010101000000-000000000000 => ../event-processor
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/event-processor/api
 # github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000 => ../history-api
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/history-api/pkg/model
 # github.com/runtime-radar/runtime-radar/lib v0.0.24 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/errcommon
 github.com/runtime-radar/runtime-radar/lib/logger
@@ -768,7 +751,7 @@ github.com/runtime-radar/runtime-radar/lib/server/interceptor
 github.com/runtime-radar/runtime-radar/lib/server/middleware
 github.com/runtime-radar/runtime-radar/lib/util/retry
 # github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8 => ../policy-enforcer
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/policy-enforcer/api
 github.com/runtime-radar/runtime-radar/policy-enforcer/pkg/model
 # github.com/ryancurrah/gomodguard v1.3.5
@@ -777,12 +760,9 @@ github.com/ryancurrah/gomodguard
 # github.com/ryanrolds/sqlclosecheck v0.5.1
 ## explicit; go 1.20
 github.com/ryanrolds/sqlclosecheck/pkg/analyzer
-# github.com/sagikazarmark/locafero v0.3.0
-## explicit; go 1.20
+# github.com/sagikazarmark/locafero v0.7.0
+## explicit; go 1.21
 github.com/sagikazarmark/locafero
-# github.com/sagikazarmark/slog-shim v0.1.0
-## explicit; go 1.20
-github.com/sagikazarmark/slog-shim
 # github.com/sanposhiho/wastedassign/v2 v2.1.0
 ## explicit; go 1.18
 github.com/sanposhiho/wastedassign/v2
@@ -843,26 +823,23 @@ github.com/sourcegraph/go-diff/diff
 github.com/spf13/afero
 github.com/spf13/afero/internal/common
 github.com/spf13/afero/mem
-# github.com/spf13/cast v1.5.1
-## explicit; go 1.18
+# github.com/spf13/cast v1.7.1
+## explicit; go 1.19
 github.com/spf13/cast
 # github.com/spf13/cobra v1.9.1
 ## explicit; go 1.15
 github.com/spf13/cobra
-# github.com/spf13/pflag v1.0.6
+# github.com/spf13/pflag v1.0.7
 ## explicit; go 1.12
 github.com/spf13/pflag
-# github.com/spf13/viper v1.17.0
-## explicit; go 1.18
+# github.com/spf13/viper v1.20.1
+## explicit; go 1.21.0
 github.com/spf13/viper
-github.com/spf13/viper/internal/encoding
 github.com/spf13/viper/internal/encoding/dotenv
-github.com/spf13/viper/internal/encoding/hcl
-github.com/spf13/viper/internal/encoding/ini
-github.com/spf13/viper/internal/encoding/javaproperties
 github.com/spf13/viper/internal/encoding/json
 github.com/spf13/viper/internal/encoding/toml
 github.com/spf13/viper/internal/encoding/yaml
+github.com/spf13/viper/internal/features
 # github.com/ssgreg/nlreturn/v2 v2.2.1
 ## explicit; go 1.13
 github.com/ssgreg/nlreturn/v2/pkg/nlreturn
@@ -988,26 +965,22 @@ go.uber.org/zap/internal/exit
 go.uber.org/zap/internal/pool
 go.uber.org/zap/internal/stacktrace
 go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.38.0
+# go.yaml.in/yaml/v3 v3.0.4
+## explicit; go 1.16
+go.yaml.in/yaml/v3
+# golang.org/x/crypto v0.41.0
 ## explicit; go 1.23.0
 golang.org/x/crypto/pbkdf2
-# golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
-## explicit; go 1.22.0
-golang.org/x/exp/constraints
-golang.org/x/exp/slices
-golang.org/x/exp/slog
-golang.org/x/exp/slog/internal
-golang.org/x/exp/slog/internal/buffer
 # golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac
 ## explicit; go 1.18
 golang.org/x/exp/typeparams
-# golang.org/x/mod v0.25.0
+# golang.org/x/mod v0.27.0
 ## explicit; go 1.23.0
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.40.0
+# golang.org/x/net v0.43.0
 ## explicit; go 1.23.0
 golang.org/x/net/http/httpguts
 golang.org/x/net/http2
@@ -1016,16 +989,27 @@ golang.org/x/net/idna
 golang.org/x/net/internal/httpcommon
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
-# golang.org/x/sync v0.15.0
-## explicit; go 1.23.0
+# golang.org/x/sync v0.17.0
+## explicit; go 1.24.0
 golang.org/x/sync/errgroup
 golang.org/x/sync/semaphore
-# golang.org/x/sys v0.33.0
+# golang.org/x/sys v0.35.0
 ## explicit; go 1.23.0
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/text v0.26.0
+# golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
 ## explicit; go 1.23.0
+golang.org/x/telemetry
+golang.org/x/telemetry/counter
+golang.org/x/telemetry/internal/config
+golang.org/x/telemetry/internal/configstore
+golang.org/x/telemetry/internal/counter
+golang.org/x/telemetry/internal/crashmonitor
+golang.org/x/telemetry/internal/mmap
+golang.org/x/telemetry/internal/telemetry
+golang.org/x/telemetry/internal/upload
+# golang.org/x/text v0.29.0
+## explicit; go 1.24.0
 golang.org/x/text/cases
 golang.org/x/text/encoding
 golang.org/x/text/encoding/internal
@@ -1051,7 +1035,7 @@ golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
-# golang.org/x/tools v0.33.0
+# golang.org/x/tools v0.36.0
 ## explicit; go 1.23.0
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/passes/appends
@@ -1103,6 +1087,7 @@ golang.org/x/tools/go/analysis/passes/unusedresult
 golang.org/x/tools/go/analysis/passes/unusedwrite
 golang.org/x/tools/go/analysis/passes/waitgroup
 golang.org/x/tools/go/ast/astutil
+golang.org/x/tools/go/ast/edge
 golang.org/x/tools/go/ast/inspector
 golang.org/x/tools/go/buildutil
 golang.org/x/tools/go/callgraph
@@ -1123,8 +1108,6 @@ golang.org/x/tools/imports
 golang.org/x/tools/internal/aliases
 golang.org/x/tools/internal/analysisinternal
 golang.org/x/tools/internal/astutil
-golang.org/x/tools/internal/astutil/cursor
-golang.org/x/tools/internal/astutil/edge
 golang.org/x/tools/internal/event
 golang.org/x/tools/internal/event/core
 golang.org/x/tools/internal/event/keys
@@ -1141,32 +1124,36 @@ golang.org/x/tools/internal/stdlib
 golang.org/x/tools/internal/typeparams
 golang.org/x/tools/internal/typesinternal
 golang.org/x/tools/internal/versions
-# golang.org/x/vuln v0.2.0
-## explicit; go 1.18
+# golang.org/x/vuln v1.1.4
+## explicit; go 1.22.0
 golang.org/x/vuln/cmd/govulncheck
 golang.org/x/vuln/internal
+golang.org/x/vuln/internal/buildinfo
 golang.org/x/vuln/internal/client
 golang.org/x/vuln/internal/derrors
+golang.org/x/vuln/internal/gosym
+golang.org/x/vuln/internal/goversion
 golang.org/x/vuln/internal/govulncheck
+golang.org/x/vuln/internal/openvex
 golang.org/x/vuln/internal/osv
+golang.org/x/vuln/internal/sarif
 golang.org/x/vuln/internal/scan
 golang.org/x/vuln/internal/semver
+golang.org/x/vuln/internal/traces
 golang.org/x/vuln/internal/vulncheck
-golang.org/x/vuln/internal/vulncheck/internal/buildinfo
-golang.org/x/vuln/internal/vulncheck/internal/gosym
 golang.org/x/vuln/internal/web
 golang.org/x/vuln/scan
-# google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/api
 google.golang.org/genproto/googleapis/api/annotations
 google.golang.org/genproto/googleapis/api/httpbody
 google.golang.org/genproto/googleapis/api/visibility
-# google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/rpc/errdetails
 google.golang.org/genproto/googleapis/rpc/status
-# google.golang.org/grpc v1.73.0
+# google.golang.org/grpc v1.75.1
 ## explicit; go 1.23.0
 google.golang.org/grpc
 google.golang.org/grpc/attributes
@@ -1236,8 +1223,8 @@ google.golang.org/grpc/tap
 # google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
 ## explicit; go 1.21
 google.golang.org/grpc/cmd/protoc-gen-go-grpc
-# google.golang.org/protobuf v1.36.6
-## explicit; go 1.22
+# google.golang.org/protobuf v1.36.10
+## explicit; go 1.23
 google.golang.org/protobuf/cmd/protoc-gen-go
 google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo
 google.golang.org/protobuf/compiler/protogen
@@ -1288,9 +1275,6 @@ google.golang.org/protobuf/types/known/structpb
 google.golang.org/protobuf/types/known/timestamppb
 google.golang.org/protobuf/types/known/wrapperspb
 google.golang.org/protobuf/types/pluginpb
-# gopkg.in/ini.v1 v1.67.0
-## explicit
-gopkg.in/ini.v1
 # gopkg.in/yaml.v2 v2.4.0
 ## explicit; go 1.15
 gopkg.in/yaml.v2
@@ -1300,7 +1284,7 @@ gopkg.in/yaml.v3
 # gorm.io/driver/postgres v1.6.0
 ## explicit; go 1.20
 gorm.io/driver/postgres
-# gorm.io/gorm v1.30.0
+# gorm.io/gorm v1.31.0
 ## explicit; go 1.18
 gorm.io/gorm
 gorm.io/gorm/callbacks
diff --git a/policy-enforcer/Dockerfile b/policy-enforcer/Dockerfile
index e80f3938..6c5e24ec 100644
--- a/policy-enforcer/Dockerfile
+++ b/policy-enforcer/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 ARG BUILD_RELEASE
 ARG BUILD_BRANCH
diff --git a/policy-enforcer/docker-compose.test.yml b/policy-enforcer/docker-compose.test.yml
index e66deb73..f560622f 100644
--- a/policy-enforcer/docker-compose.test.yml
+++ b/policy-enforcer/docker-compose.test.yml
@@ -16,7 +16,7 @@ services:
       - "6379:6379"
 
   test:
-    image: golang:1.24
+    image: golang:1.25
     working_dir: /go/src/repo
     volumes:
       - .:/go/src/repo
diff --git a/policy-enforcer/go.mod b/policy-enforcer/go.mod
index 456e64ad..4710810e 100644
--- a/policy-enforcer/go.mod
+++ b/policy-enforcer/go.mod
@@ -1,6 +1,6 @@
 module github.com/runtime-radar/runtime-radar/policy-enforcer
 
-go 1.23.0
+go 1.25
 
 require (
 	github.com/gobwas/glob v0.2.3
diff --git a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
index fb4087d9..3604294e 100644
--- a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
+++ b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
@@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
+func (jt JSONTime) String() string {
+	return time.Time(jt).String()
+}
+
 type Token struct {
 	Username              string    `json:"username"`
 	UserID                string    `json:"user_id"`
@@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) {
 		return nil, errors.New("unknown authorization format")
 	}
 
-	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) {
+	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) {
 		return key, nil
 	})
 	if err != nil {
diff --git a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
index 79432fec..24b0d6e3 100644
--- a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
+++ b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
@@ -27,7 +27,7 @@ func SetReady() {
 }
 
 // ReadyHandler handles ready probes.
-func ReadyHandler(w http.ResponseWriter, r *http.Request) {
+func ReadyHandler(w http.ResponseWriter, _ *http.Request) {
 	if IsReady() {
 		// Make it simple: do nothing and have 200 OK
 		return
@@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // LiveHandler handles live probes.
-func LiveHandler(w http.ResponseWriter, r *http.Request) {
+func LiveHandler(http.ResponseWriter, *http.Request) {
 	// Make it simple: do nothing and have 200 OK
 }
diff --git a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
index cb9487d6..822eb440 100644
--- a/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
+++ b/policy-enforcer/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
@@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
 
 const CorrelationHeader = "correlation-id"
 
-func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	var corrID string
 
 	md, ok := metadata.FromIncomingContext(ctx)
diff --git a/policy-enforcer/vendor/modules.txt b/policy-enforcer/vendor/modules.txt
index 4ba13d1e..f8a6f534 100644
--- a/policy-enforcer/vendor/modules.txt
+++ b/policy-enforcer/vendor/modules.txt
@@ -760,7 +760,7 @@ github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/lib v0.0.0-00010101000000-000000000000 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/errcommon
 github.com/runtime-radar/runtime-radar/lib/logger
diff --git a/public-api/Dockerfile b/public-api/Dockerfile
index a4f221e8..5ef53445 100644
--- a/public-api/Dockerfile
+++ b/public-api/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 ARG BUILD_RELEASE
 ARG BUILD_BRANCH
diff --git a/public-api/docker-compose.test.yml b/public-api/docker-compose.test.yml
index 3126a730..c59784f0 100644
--- a/public-api/docker-compose.test.yml
+++ b/public-api/docker-compose.test.yml
@@ -1,6 +1,6 @@
 services:
   test:
-      image: golang:1.24
+      image: golang:1.25
       working_dir: /go/src/repo
       volumes:
         - .:/go/src/repo
diff --git a/public-api/go.mod b/public-api/go.mod
index 5adae03e..0500d5b5 100644
--- a/public-api/go.mod
+++ b/public-api/go.mod
@@ -1,6 +1,6 @@
 module github.com/runtime-radar/runtime-radar/public-api
 
-go 1.24.0
+go 1.25
 
 require (
 	github.com/golangci/golangci-lint v1.64.8
@@ -8,17 +8,17 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/gorilla/mux v1.8.1
 	github.com/justinas/alice v1.2.0
-	github.com/rs/cors v1.11.0
-	github.com/rs/zerolog v1.33.0
+	github.com/rs/cors v1.11.1
+	github.com/rs/zerolog v1.34.0
 	github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000
 	github.com/runtime-radar/runtime-radar/lib v0.0.24
 	github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8
 	go.uber.org/automaxprocs v1.6.0
-	golang.org/x/vuln v0.2.0
-	google.golang.org/grpc v1.73.0
-	google.golang.org/protobuf v1.36.6
+	golang.org/x/vuln v1.1.4
+	google.golang.org/grpc v1.75.1
+	google.golang.org/protobuf v1.36.10
 	gorm.io/driver/postgres v1.6.0
-	gorm.io/gorm v1.30.0
+	gorm.io/gorm v1.31.0
 )
 
 require (
@@ -66,7 +66,7 @@ require (
 	github.com/fatih/structtag v1.2.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/firefart/nonamedreturns v1.0.5 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/fsnotify/fsnotify v1.8.0 // indirect
 	github.com/fzipp/gocyclo v0.6.0 // indirect
 	github.com/ghostiam/protogetter v0.3.9 // indirect
 	github.com/go-critic/go-critic v0.12.0 // indirect
@@ -78,7 +78,7 @@ require (
 	github.com/go-toolsmith/astp v1.1.0 // indirect
 	github.com/go-toolsmith/strparse v1.1.0 // indirect
 	github.com/go-toolsmith/typep v1.1.0 // indirect
-	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
+	github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
 	github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
 	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
@@ -96,16 +96,15 @@ require (
 	github.com/gostaticanalysis/comment v1.5.0 // indirect
 	github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect
 	github.com/gostaticanalysis/nilerr v0.1.1 // indirect
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
 	github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
 	github.com/hashicorp/go-version v1.7.0 // indirect
 	github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
-	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/hexops/gotextdiff v1.0.3 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
-	github.com/jackc/pgx/v5 v5.7.1 // indirect
+	github.com/jackc/pgx/v5 v5.7.6 // indirect
 	github.com/jackc/puddle/v2 v2.2.2 // indirect
 	github.com/jgautheron/goconst v1.7.1 // indirect
 	github.com/jingyugao/rowserrcheck v1.1.1 // indirect
@@ -127,7 +126,6 @@ require (
 	github.com/leonklingele/grouper v1.1.2 // indirect
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/macabu/inamedparam v0.1.3 // indirect
-	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/maratori/testableexamples v1.0.0 // indirect
 	github.com/maratori/testpackage v1.1.1 // indirect
 	github.com/matoous/godox v1.1.0 // indirect
@@ -136,7 +134,6 @@ require (
 	github.com/mattn/go-runewidth v0.0.16 // indirect
 	github.com/mgechev/revive v1.7.0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
-	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/moricho/tparallel v0.3.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/nakabonne/nestif v0.3.1 // indirect
@@ -151,7 +148,7 @@ require (
 	github.com/prometheus/client_golang v1.22.0 // indirect
 	github.com/prometheus/client_model v0.6.2 // indirect
 	github.com/prometheus/common v0.62.0 // indirect
-	github.com/prometheus/procfs v0.15.1 // indirect
+	github.com/prometheus/procfs v0.17.0 // indirect
 	github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
 	github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
 	github.com/quasilyte/gogrep v0.5.0 // indirect
@@ -163,8 +160,7 @@ require (
 	github.com/runtime-radar/runtime-radar/event-processor v0.4.14 // indirect
 	github.com/ryancurrah/gomodguard v1.3.5 // indirect
 	github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
-	github.com/sagikazarmark/locafero v0.3.0 // indirect
-	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+	github.com/sagikazarmark/locafero v0.7.0 // indirect
 	github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
 	github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
 	github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
@@ -179,10 +175,10 @@ require (
 	github.com/sourcegraph/conc v0.3.0 // indirect
 	github.com/sourcegraph/go-diff v0.7.0 // indirect
 	github.com/spf13/afero v1.12.0 // indirect
-	github.com/spf13/cast v1.5.1 // indirect
+	github.com/spf13/cast v1.7.1 // indirect
 	github.com/spf13/cobra v1.9.1 // indirect
-	github.com/spf13/pflag v1.0.6 // indirect
-	github.com/spf13/viper v1.17.0 // indirect
+	github.com/spf13/pflag v1.0.7 // indirect
+	github.com/spf13/viper v1.20.1 // indirect
 	github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
 	github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
@@ -211,18 +207,17 @@ require (
 	go-simpler.org/sloglint v0.9.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.38.0 // indirect
-	golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
+	golang.org/x/crypto v0.41.0 // indirect
 	golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
-	golang.org/x/mod v0.25.0 // indirect
-	golang.org/x/net v0.40.0 // indirect
-	golang.org/x/sync v0.15.0 // indirect
-	golang.org/x/sys v0.33.0 // indirect
-	golang.org/x/text v0.26.0 // indirect
-	golang.org/x/tools v0.33.0 // indirect
-	google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
-	gopkg.in/ini.v1 v1.67.0 // indirect
+	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/net v0.43.0 // indirect
+	golang.org/x/sync v0.17.0 // indirect
+	golang.org/x/sys v0.35.0 // indirect
+	golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 // indirect
+	golang.org/x/text v0.29.0 // indirect
+	golang.org/x/tools v0.36.0 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	honnef.co/go/tools v0.6.1 // indirect
diff --git a/public-api/go.sum b/public-api/go.sum
index ffc9ce05..d1e0336f 100644
--- a/public-api/go.sum
+++ b/public-api/go.sum
@@ -96,18 +96,18 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
 github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
 github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
 github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ=
 github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA=
 github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w=
 github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w=
-github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
-github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@@ -135,8 +135,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi
 github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ=
 github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
 github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
-github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
-github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY=
 github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
@@ -200,8 +200,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW
 github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
 github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8=
 github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
 github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
 github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
@@ -211,8 +211,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe
 github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -221,8 +219,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
-github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
-github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
+github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
+github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
 github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
 github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
@@ -271,8 +269,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
 github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
 github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE=
 github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04=
@@ -295,8 +291,6 @@ github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY=
 github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
 github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
@@ -340,8 +334,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
 github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
 github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo=
 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
 github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
@@ -359,20 +353,18 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
 github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
-github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
-github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
-github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
+github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
+github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU=
 github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE=
 github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
 github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
-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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
+github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
 github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
 github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
 github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
@@ -405,15 +397,16 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp
 github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
 github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
 github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
-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/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
 github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
-github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
+github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
 github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0=
 github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
 github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4=
@@ -491,16 +484,16 @@ go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE=
 go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
-go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
-go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
-go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
-go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
-go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
-go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
-go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
-go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
-go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
+go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
+go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
 go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -515,8 +508,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
-golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
+golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
+golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
@@ -534,8 +527,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
-golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
 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=
@@ -551,8 +544,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
-golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
+golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
 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-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -562,8 +555,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -582,7 +575,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -591,8 +583,10 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
+golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -611,8 +605,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
-golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
 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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
@@ -631,27 +625,31 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
-golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
-golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
-golang.org/x/vuln v0.2.0 h1:Dlz47lW0pvPHU7tnb10S8vbMn9GnV2B6eyT7Tem5XBI=
-golang.org/x/vuln v0.2.0/go.mod h1:V0eyhHwaAaHrt42J9bgrN6rd12f6GU4T0Lu0ex2wDg4=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
+golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
+golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
+golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
+golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
 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/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
-google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
-google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
-google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
-google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f h1:OiFuztEyBivVKDvguQJYWq1yDcfAHIID/FVrPR4oiI0=
+google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f/go.mod h1:kprOiu9Tr0JYyD6DORrc4Hfyk3RFXqkQ3ctHEum3ZbM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
+google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
+google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-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.2/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=
@@ -660,8 +658,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
 gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
-gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
-gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
+gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
+gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
 honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
 honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
 mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/public-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
new file mode 100644
index 00000000..f4e7dbf3
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
@@ -0,0 +1,14 @@
+freebsd_task:
+  name: 'FreeBSD'
+  freebsd_instance:
+    image_family: freebsd-14-1
+  install_script:
+    - pkg update -f
+    - pkg install -y go
+  test_script:
+      # run tests as user "cirrus" instead of root
+    - pw useradd cirrus -m
+    - chown -R cirrus:cirrus .
+    - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    -                      sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race    ./...
+    - FSNOTIFY_DEBUG=1     sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/.editorconfig b/public-api/vendor/github.com/fsnotify/fsnotify/.editorconfig
deleted file mode 100644
index fad89585..00000000
--- a/public-api/vendor/github.com/fsnotify/fsnotify/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-root = true
-
-[*.go]
-indent_style = tab
-indent_size = 4
-insert_final_newline = true
-
-[*.{yml,yaml}]
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/.gitattributes b/public-api/vendor/github.com/fsnotify/fsnotify/.gitattributes
deleted file mode 100644
index 32f1001b..00000000
--- a/public-api/vendor/github.com/fsnotify/fsnotify/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-go.sum linguist-generated
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/.gitignore b/public-api/vendor/github.com/fsnotify/fsnotify/.gitignore
index 1d89d85c..daea9dd6 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/.gitignore
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/.gitignore
@@ -4,3 +4,7 @@
 
 # Output of go build ./cmd/fsnotify
 /fsnotify
+/fsnotify.exe
+
+/test/kqueue
+/test/a.out
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/public-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
index 77f9593b..fa854785 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
@@ -1,16 +1,115 @@
 # Changelog
 
-All notable changes to this project will be documented in this file.
+1.8.0 2023-10-31
+----------------
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+### Additions
+
+- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
+
+### Changes and fixes
+
+- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610])
+
+- kqueue: ignore events with Ident=0 ([#590])
+
+- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617])
+
+- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625])
+
+- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620])
+
+- inotify: fix panic when calling Remove() in a goroutine ([#650])
+
+- fen: allow watching subdirectories of watched directories ([#621])
+
+[#590]: https://github.com/fsnotify/fsnotify/pull/590
+[#610]: https://github.com/fsnotify/fsnotify/pull/610
+[#617]: https://github.com/fsnotify/fsnotify/pull/617
+[#619]: https://github.com/fsnotify/fsnotify/pull/619
+[#620]: https://github.com/fsnotify/fsnotify/pull/620
+[#621]: https://github.com/fsnotify/fsnotify/pull/621
+[#625]: https://github.com/fsnotify/fsnotify/pull/625
+[#650]: https://github.com/fsnotify/fsnotify/pull/650
+
+1.7.0 - 2023-10-22
+------------------
+This version of fsnotify needs Go 1.17.
+
+### Additions
+
+- illumos: add FEN backend to support illumos and Solaris. ([#371])
+
+- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful
+  in cases where you can't control the kernel buffer and receive a large number
+  of events in bursts. ([#550], [#572])
+
+- all: add `AddWith()`, which is identical to `Add()` but allows passing
+  options. ([#521])
+
+- windows: allow setting the ReadDirectoryChangesW() buffer size with
+  `fsnotify.WithBufferSize()`; the default of 64K is the highest value that
+  works on all platforms and is enough for most purposes, but in some cases a
+  highest buffer is needed. ([#521])
+
+### Changes and fixes
+
+- inotify: remove watcher if a watched path is renamed ([#518])
+
+  After a rename the reported name wasn't updated, or even an empty string.
+  Inotify doesn't provide any good facilities to update it, so just remove the
+  watcher. This is already how it worked on kqueue and FEN.
+
+  On Windows this does work, and remains working.
+
+- windows: don't listen for file attribute changes ([#520])
+
+  File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API,
+  with no way to see if they're a file write or attribute change, so would show
+  up as a fsnotify.Write event. This is never useful, and could result in many
+  spurious Write events.
+
+- windows: return `ErrEventOverflow` if the buffer is full ([#525])
+
+  Before it would merely return "short read", making it hard to detect this
+  error.
+
+- kqueue: make sure events for all files are delivered properly when removing a
+  watched directory ([#526])
+
+  Previously they would get sent with `""` (empty string) or `"."` as the path
+  name.
+
+- kqueue: don't emit spurious Create events for symbolic links ([#524])
+
+  The link would get resolved but kqueue would "forget" it already saw the link
+  itself, resulting on a Create for every Write event for the directory.
+
+- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516])
 
-## [Unreleased]
+- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in
+  `backend_other.go`, making it easier to use on unsupported platforms such as
+  WASM, AIX, etc. ([#528])
 
-Nothing yet.
+- other: use the `backend_other.go` no-op if the `appengine` build tag is set;
+  Google AppEngine forbids usage of the unsafe package so the inotify backend
+  won't compile there.
 
-## [1.6.0] - 2022-10-13
+[#371]: https://github.com/fsnotify/fsnotify/pull/371
+[#516]: https://github.com/fsnotify/fsnotify/pull/516
+[#518]: https://github.com/fsnotify/fsnotify/pull/518
+[#520]: https://github.com/fsnotify/fsnotify/pull/520
+[#521]: https://github.com/fsnotify/fsnotify/pull/521
+[#524]: https://github.com/fsnotify/fsnotify/pull/524
+[#525]: https://github.com/fsnotify/fsnotify/pull/525
+[#526]: https://github.com/fsnotify/fsnotify/pull/526
+[#528]: https://github.com/fsnotify/fsnotify/pull/528
+[#537]: https://github.com/fsnotify/fsnotify/pull/537
+[#550]: https://github.com/fsnotify/fsnotify/pull/550
+[#572]: https://github.com/fsnotify/fsnotify/pull/572
 
+1.6.0 - 2022-10-13
+------------------
 This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1,
 but not documented). It also increases the minimum Linux version to 2.6.32.
 
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/public-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
index ea379759..e4ac2a2f 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
@@ -1,7 +1,7 @@
 Thank you for your interest in contributing to fsnotify! We try to review and
 merge PRs in a reasonable timeframe, but please be aware that:
 
-- To avoid "wasted" work, please discus changes on the issue tracker first. You
+- To avoid "wasted" work, please discuss changes on the issue tracker first. You
   can just send PRs, but they may end up being rejected for one reason or the
   other.
 
@@ -20,6 +20,124 @@ platforms. Testing different platforms locally can be done with something like
 
 Use the `-short` flag to make the "stress test" run faster.
 
+Writing new tests
+-----------------
+Scripts in the testdata directory allow creating test cases in a "shell-like"
+syntax. The basic format is:
+
+    script
+
+    Output:
+    desired output
+
+For example:
+
+    # Create a new empty file with some data.
+    watch /
+    echo data >/file
+
+    Output:
+        create  /file
+        write   /file
+
+Just create a new file to add a new test; select which tests to run with
+`-run TestScript/[path]`.
+
+script
+------
+The script is a "shell-like" script:
+
+    cmd arg arg
+
+Comments are supported with `#`:
+
+    # Comment
+    cmd arg arg  # Comment
+
+All operations are done in a temp directory; a path like "/foo" is rewritten to
+"/tmp/TestFoo/foo".
+
+Arguments can be quoted with `"` or `'`; there are no escapes and they're
+functionally identical right now, but this may change in the future, so best to
+assume shell-like rules.
+
+    touch "/file with spaces"
+
+End-of-line escapes with `\` are not supported.
+
+### Supported commands
+
+    watch path [ops]    # Watch the path, reporting events for it. Nothing is
+                        # watched by default. Optionally a list of ops can be
+                        # given, as with AddWith(path, WithOps(...)).
+    unwatch path        # Stop watching the path.
+    watchlist n         # Assert watchlist length.
+
+    stop                # Stop running the script; for debugging.
+    debug [yes/no]      # Enable/disable FSNOTIFY_DEBUG (tests are run in
+                          parallel by default, so -parallel=1 is probably a good
+                          idea).
+
+    touch path
+    mkdir [-p] dir
+    ln -s target link   # Only ln -s supported.
+    mkfifo path
+    mknod dev path
+    mv src dst
+    rm [-r] path
+    chmod mode path     # Octal only
+    sleep time-in-ms
+
+    cat path            # Read path (does nothing with the data; just reads it).
+    echo str >>path     # Append "str" to "path".
+    echo str >path      # Truncate "path" and write "str".
+
+    require reason      # Skip the test if "reason" is true; "skip" and
+    skip reason         # "require" behave identical; it supports both for
+                        # readability. Possible reasons are:
+                        #
+                        #   always    Always skip this test.
+                        #   symlink   Symlinks are supported (requires admin
+                        #             permissions on Windows).
+                        #   mkfifo    Platform doesn't support FIFO named sockets.
+                        #   mknod     Platform doesn't support device nodes.
+
+
+output
+------
+After `Output:` the desired output is given; this is indented by convention, but
+that's not required.
+
+The format of that is:
+
+    # Comment
+    event  path  # Comment
+
+    system:
+        event  path
+    system2:
+        event  path
+
+Every event is one line, and any whitespace between the event and path are
+ignored. The path can optionally be surrounded in ". Anything after a "#" is
+ignored.
+
+Platform-specific tests can be added after GOOS; for example:
+
+    watch /
+    touch /file
+
+    Output:
+        # Tested if nothing else matches
+        create    /file
+
+        # Windows-specific test.
+        windows:
+            write  /file
+
+You can specify multiple platforms with a comma (e.g. "windows, linux:").
+"kqueue" is a shortcut for all kqueue systems (BSD, macOS).
+
 
 [goon]: https://github.com/arp242/goon
 [Vagrant]: https://www.vagrantup.com/
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/README.md b/public-api/vendor/github.com/fsnotify/fsnotify/README.md
index d4e6080f..e480733d 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/README.md
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/README.md
@@ -1,29 +1,31 @@
 fsnotify is a Go library to provide cross-platform filesystem notifications on
-Windows, Linux, macOS, and BSD systems.
+Windows, Linux, macOS, BSD, and illumos.
 
-Go 1.16 or newer is required; the full documentation is at
+Go 1.17 or newer is required; the full documentation is at
 https://pkg.go.dev/github.com/fsnotify/fsnotify
 
-**It's best to read the documentation at pkg.go.dev, as it's pinned to the last
-released version, whereas this README is for the last development version which
-may include additions/changes.**
-
 ---
 
 Platform support:
 
-| Adapter               | OS             | Status                                                       |
-| --------------------- | ---------------| -------------------------------------------------------------|
-| inotify               | Linux 2.6.32+  | Supported                                                    |
-| kqueue                | BSD, macOS     | Supported                                                    |
-| ReadDirectoryChangesW | Windows        | Supported                                                    |
-| FSEvents              | macOS          | [Planned](https://github.com/fsnotify/fsnotify/issues/11)    |
-| FEN                   | Solaris 11     | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) |
-| fanotify              | Linux 5.9+     | [Maybe](https://github.com/fsnotify/fsnotify/issues/114)     |
-| USN Journals          | Windows        | [Maybe](https://github.com/fsnotify/fsnotify/issues/53)      |
-| Polling               | *All*          | [Maybe](https://github.com/fsnotify/fsnotify/issues/9)       |
-
-Linux and macOS should include Android and iOS, but these are currently untested.
+| Backend               | OS         | Status                                                                    |
+| :-------------------- | :--------- | :------------------------------------------------------------------------ |
+| inotify               | Linux      | Supported                                                                 |
+| kqueue                | BSD, macOS | Supported                                                                 |
+| ReadDirectoryChangesW | Windows    | Supported                                                                 |
+| FEN                   | illumos    | Supported                                                                 |
+| fanotify              | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114)                |
+| AHAFS                 | AIX        | [aix branch]; experimental due to lack of maintainer and test environment |
+| FSEvents              | macOS      | [Needs support in x/sys/unix][fsevents]                                   |
+| USN Journals          | Windows    | [Needs support in x/sys/windows][usn]                                     |
+| Polling               | *All*      | [Not yet](https://github.com/fsnotify/fsnotify/issues/9)                  |
+
+Linux and illumos should include Android and Solaris, but these are currently
+untested.
+
+[fsevents]:   https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
+[usn]:        https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
+[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
 
 Usage
 -----
@@ -83,20 +85,23 @@ run with:
 
     % go run ./cmd/fsnotify
 
+Further detailed documentation can be found in godoc:
+https://pkg.go.dev/github.com/fsnotify/fsnotify
+
 FAQ
 ---
 ### Will a file still be watched when it's moved to another directory?
 No, not unless you are watching the location it was moved to.
 
-### Are subdirectories watched too?
+### Are subdirectories watched?
 No, you must add watches for any directory you want to watch (a recursive
 watcher is on the roadmap: [#18]).
 
 [#18]: https://github.com/fsnotify/fsnotify/issues/18
 
 ### Do I have to watch the Error and Event channels in a goroutine?
-As of now, yes (you can read both channels in the same goroutine using `select`,
-you don't need a separate goroutine for both channels; see the example).
+Yes. You can read both channels in the same goroutine using `select` (you don't
+need a separate goroutine for both channels; see the example).
 
 ### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys?
 fsnotify requires support from underlying OS to work. The current NFS and SMB
@@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented.
 
 [#9]: https://github.com/fsnotify/fsnotify/issues/9
 
+### Why do I get many Chmod events?
+Some programs may generate a lot of attribute changes; for example Spotlight on
+macOS, anti-virus programs, backup applications, and some others are known to do
+this. As a rule, it's typically best to ignore Chmod events. They're often not
+useful, and tend to cause problems.
+
+Spotlight indexing on macOS can result in multiple events (see [#15]). A
+temporary workaround is to add your folder(s) to the *Spotlight Privacy
+settings* until we have a native FSEvents implementation (see [#11]).
+
+[#11]: https://github.com/fsnotify/fsnotify/issues/11
+[#15]: https://github.com/fsnotify/fsnotify/issues/15
+
+### Watching a file doesn't work well
+Watching individual files (rather than directories) is generally not recommended
+as many programs (especially editors) update files atomically: it will write to
+a temporary file which is then moved to to destination, overwriting the original
+(or some variant thereof). The watcher on the original file is now lost, as that
+no longer exists.
+
+The upshot of this is that a power failure or crash won't leave a half-written
+file.
+
+Watch the parent directory and use `Event.Name` to filter out files you're not
+interested in. There is an example of this in `cmd/fsnotify/file.go`.
+
 Platform-specific notes
 -----------------------
 ### Linux
@@ -151,11 +182,3 @@ these platforms.
 
 The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to
 control the maximum number of open files.
-
-### macOS
-Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary
-workaround is to add your folder(s) to the *Spotlight Privacy settings* until we
-have a native FSEvents implementation (see [#11]).
-
-[#11]: https://github.com/fsnotify/fsnotify/issues/11
-[#15]: https://github.com/fsnotify/fsnotify/issues/15
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/public-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
index 1a95ad8e..c349c326 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/backend_fen.go
@@ -1,162 +1,484 @@
 //go:build solaris
-// +build solaris
+
+// FEN backend for illumos (supported) and Solaris (untested, but should work).
+//
+// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create
 
 package fsnotify
 
 import (
 	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"sync"
+	"time"
+
+	"github.com/fsnotify/fsnotify/internal"
+	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type fen struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
+
+	mu      sync.Mutex
+	port    *unix.EventPort
+	done    chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	dirs    map[string]Op // Explicitly watched directories
+	watches map[string]Op // Explicitly watched non-directories
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, errors.New("FEN based watcher not yet supported for fsnotify\n")
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	w := &fen{
+		Events:  ev,
+		Errors:  errs,
+		dirs:    make(map[string]Op),
+		watches: make(map[string]Op),
+		done:    make(chan struct{}),
+	}
+
+	var err error
+	w.port, err = unix.NewEventPort()
+	if err != nil {
+		return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err)
+	}
+
+	go w.readEvents()
+	return w, nil
+}
+
+// sendEvent attempts to send an event to the user, returning true if the event
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendEvent(name string, op Op) (sent bool) {
+	select {
+	case <-w.done:
+		return false
+	case w.Events <- Event{Name: name, Op: op}:
+		return true
+	}
+}
+
+// sendError attempts to send an error to the user, returning true if the error
+// was put in the channel successfully and false if the watcher has been closed.
+func (w *fen) sendError(err error) (sent bool) {
+	if err == nil {
+		return true
+	}
+	select {
+	case <-w.done:
+		return false
+	case w.Errors <- err:
+		return true
+	}
+}
+
+func (w *fen) isClosed() bool {
+	select {
+	case <-w.done:
+		return true
+	default:
+		return false
+	}
+}
+
+func (w *fen) Close() error {
+	// Take the lock used by associateFile to prevent lingering events from
+	// being processed after the close
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if w.isClosed() {
+		return nil
+	}
+	close(w.done)
+	return w.port.Close()
+}
+
+func (w *fen) Add(name string) error { return w.AddWith(name) }
+
+func (w *fen) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
+	// Currently we resolve symlinks that were explicitly requested to be
+	// watched. Otherwise we would use LStat here.
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Associate all files in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, true, w.associateFile)
+		if err != nil {
+			return err
+		}
+
+		w.mu.Lock()
+		w.dirs[name] = with.op
+		w.mu.Unlock()
+		return nil
+	}
+
+	err = w.associateFile(name, stat, true)
+	if err != nil {
+		return err
+	}
+
+	w.mu.Lock()
+	w.watches[name] = with.op
+	w.mu.Unlock()
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
+func (w *fen) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if !w.port.PathIsWatched(name) {
+		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	// The user has expressed an intent. Immediately remove this name from
+	// whichever watch list it might be in. If it's not in there the delete
+	// doesn't cause harm.
+	w.mu.Lock()
+	delete(w.watches, name)
+	delete(w.dirs, name)
+	w.mu.Unlock()
+
+	stat, err := os.Stat(name)
+	if err != nil {
+		return err
+	}
+
+	// Remove associations for every file in the directory.
+	if stat.IsDir() {
+		err := w.handleDirectory(name, stat, false, w.dissociateFile)
+		if err != nil {
+			return err
+		}
+		return nil
+	}
+
+	err = w.port.DissociatePath(name)
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+// readEvents contains the main loop that runs in a goroutine watching for events.
+func (w *fen) readEvents() {
+	// If this function returns, the watcher has been closed and we can close
+	// these channels
+	defer func() {
+		close(w.Errors)
+		close(w.Events)
+	}()
+
+	pevents := make([]unix.PortEvent, 8)
+	for {
+		count, err := w.port.Get(pevents, 1, nil)
+		if err != nil && err != unix.ETIME {
+			// Interrupted system call (count should be 0) ignore and continue
+			if errors.Is(err, unix.EINTR) && count == 0 {
+				continue
+			}
+			// Get failed because we called w.Close()
+			if errors.Is(err, unix.EBADF) && w.isClosed() {
+				return
+			}
+			// There was an error not caused by calling w.Close()
+			if !w.sendError(err) {
+				return
+			}
+		}
+
+		p := pevents[:count]
+		for _, pevent := range p {
+			if pevent.Source != unix.PORT_SOURCE_FILE {
+				// Event from unexpected source received; should never happen.
+				if !w.sendError(errors.New("Event from unexpected source received")) {
+					return
+				}
+				continue
+			}
+
+			if debug {
+				internal.Debug(pevent.Path, pevent.Events)
+			}
+
+			err = w.handleEvent(&pevent)
+			if !w.sendError(err) {
+				return
+			}
+		}
+	}
+}
+
+func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	// Handle all children of the directory.
+	for _, entry := range files {
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = handler(filepath.Join(path, finfo.Name()), finfo, false)
+		if err != nil {
+			return err
+		}
+	}
+
+	// And finally handle the directory itself.
+	return handler(path, stat, follow)
+}
+
+// handleEvent might need to emit more than one fsnotify event if the events
+// bitmap matches more than one event type (e.g. the file was both modified and
+// had the attributes changed between when the association was created and the
+// when event was returned)
+func (w *fen) handleEvent(event *unix.PortEvent) error {
+	var (
+		events     = event.Events
+		path       = event.Path
+		fmode      = event.Cookie.(os.FileMode)
+		reRegister = true
+	)
+
+	w.mu.Lock()
+	_, watchedDir := w.dirs[path]
+	_, watchedPath := w.watches[path]
+	w.mu.Unlock()
+	isWatched := watchedDir || watchedPath
+
+	if events&unix.FILE_DELETE != 0 {
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_FROM != 0 {
+		if !w.sendEvent(path, Rename) {
+			return nil
+		}
+		// Don't keep watching the new file name
+		reRegister = false
+	}
+	if events&unix.FILE_RENAME_TO != 0 {
+		// We don't report a Rename event for this case, because Rename events
+		// are interpreted as referring to the _old_ name of the file, and in
+		// this case the event would refer to the new name of the file. This
+		// type of rename event is not supported by fsnotify.
+
+		// inotify reports a Remove event in this case, so we simulate this
+		// here.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Don't keep watching the file that was removed
+		reRegister = false
+	}
+
+	// The file is gone, nothing left to do.
+	if !reRegister {
+		if watchedDir {
+			w.mu.Lock()
+			delete(w.dirs, path)
+			w.mu.Unlock()
+		}
+		if watchedPath {
+			w.mu.Lock()
+			delete(w.watches, path)
+			w.mu.Unlock()
+		}
+		return nil
+	}
+
+	// If we didn't get a deletion the file still exists and we're going to have
+	// to watch it again. Let's Stat it now so that we can compare permissions
+	// and have what we need to continue watching the file
+
+	stat, err := os.Lstat(path)
+	if err != nil {
+		// This is unexpected, but we should still emit an event. This happens
+		// most often on "rm -r" of a subdirectory inside a watched directory We
+		// get a modify event of something happening inside, but by the time we
+		// get here, the sudirectory is already gone. Clearly we were watching
+		// this path but now it is gone. Let's tell the user that it was
+		// removed.
+		if !w.sendEvent(path, Remove) {
+			return nil
+		}
+		// Suppress extra write events on removed directories; they are not
+		// informative and can be confusing.
+		return nil
+	}
+
+	// resolve symlinks that were explicitly watched as we would have at Add()
+	// time. this helps suppress spurious Chmod events on watched symlinks
+	if isWatched {
+		stat, err = os.Stat(path)
+		if err != nil {
+			// The symlink still exists, but the target is gone. Report the
+			// Remove similar to above.
+			if !w.sendEvent(path, Remove) {
+				return nil
+			}
+			// Don't return the error
+		}
+	}
+
+	if events&unix.FILE_MODIFIED != 0 {
+		if fmode.IsDir() && watchedDir {
+			if err := w.updateDirectory(path); err != nil {
+				return err
+			}
+		} else {
+			if !w.sendEvent(path, Write) {
+				return nil
+			}
+		}
+	}
+	if events&unix.FILE_ATTRIB != 0 && stat != nil {
+		// Only send Chmod if perms changed
+		if stat.Mode().Perm() != fmode.Perm() {
+			if !w.sendEvent(path, Chmod) {
+				return nil
+			}
+		}
+	}
+
+	if stat != nil {
+		// If we get here, it means we've hit an event above that requires us to
+		// continue watching the file or directory
+		return w.associateFile(path, stat, isWatched)
+	}
+	return nil
+}
+
+func (w *fen) updateDirectory(path string) error {
+	// The directory was modified, so we must find unwatched entities and watch
+	// them. If something was removed from the directory, nothing will happen,
+	// as everything else should still be watched.
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return err
+	}
+
+	for _, entry := range files {
+		path := filepath.Join(path, entry.Name())
+		if w.port.PathIsWatched(path) {
+			continue
+		}
+
+		finfo, err := entry.Info()
+		if err != nil {
+			return err
+		}
+		err = w.associateFile(path, finfo, false)
+		if !w.sendError(err) {
+			return nil
+		}
+		if !w.sendEvent(path, Create) {
+			return nil
+		}
+	}
 	return nil
 }
+
+func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	// This is primarily protecting the call to AssociatePath but it is
+	// important and intentional that the call to PathIsWatched is also
+	// protected by this mutex. Without this mutex, AssociatePath has been seen
+	// to error out that the path is already associated.
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.port.PathIsWatched(path) {
+		// Remove the old association in favor of this one If we get ENOENT,
+		// then while the x/sys/unix wrapper still thought that this path was
+		// associated, the underlying event port did not. This call will have
+		// cleared up that discrepancy. The most likely cause is that the event
+		// has fired but we haven't processed it yet.
+		err := w.port.DissociatePath(path)
+		if err != nil && !errors.Is(err, unix.ENOENT) {
+			return err
+		}
+	}
+
+	var events int
+	if !follow {
+		// Watch symlinks themselves rather than their targets unless this entry
+		// is explicitly watched.
+		events |= unix.FILE_NOFOLLOW
+	}
+	if true { // TODO: implement withOps()
+		events |= unix.FILE_MODIFIED
+	}
+	if true {
+		events |= unix.FILE_ATTRIB
+	}
+	return w.port.AssociatePath(path, stat, events, stat.Mode())
+}
+
+func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
+	if !w.port.PathIsWatched(path) {
+		return nil
+	}
+	return w.port.DissociatePath(path)
+}
+
+func (w *fen) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	entries := make([]string, 0, len(w.watches)+len(w.dirs))
+	for pathname := range w.dirs {
+		entries = append(entries, pathname)
+	}
+	for pathname := range w.watches {
+		entries = append(entries, pathname)
+	}
+
+	return entries
+}
+
+func (w *fen) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/public-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
index 54c77fbb..36c31169 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
@@ -1,5 +1,4 @@
-//go:build linux
-// +build linux
+//go:build linux && !appengine
 
 package fsnotify
 
@@ -7,142 +6,188 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/fs"
 	"os"
 	"path/filepath"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type inotify struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	// Store fd here as os.File.Read() will no longer return on close after
 	// calling Fd(). See: https://github.com/golang/go/issues/26439
 	fd          int
-	mu          sync.Mutex // Map access
 	inotifyFile *os.File
-	watches     map[string]*watch // Map of inotify watches (key: path)
-	paths       map[int]string    // Map of watched paths (key: watch descriptor)
-	done        chan struct{}     // Channel for sending a "quit message" to the reader goroutine
-	doneResp    chan struct{}     // Channel to respond to Close
+	watches     *watches
+	done        chan struct{} // Channel for sending a "quit message" to the reader goroutine
+	doneMu      sync.Mutex
+	doneResp    chan struct{} // Channel to respond to Close
+
+	// Store rename cookies in an array, with the index wrapping to 0. Almost
+	// all of the time what we get is a MOVED_FROM to set the cookie and the
+	// next event inotify sends will be MOVED_TO to read it. However, this is
+	// not guaranteed – as described in inotify(7) – and we may get other events
+	// between the two MOVED_* events (including other MOVED_* ones).
+	//
+	// A second issue is that moving a file outside the watched directory will
+	// trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to
+	// read and delete it. So just storing it in a map would slowly leak memory.
+	//
+	// Doing it like this gives us a simple fast LRU-cache that won't allocate.
+	// Ten items should be more than enough for our purpose, and a loop over
+	// such a short array is faster than a map access anyway (not that it hugely
+	// matters since we're talking about hundreds of ns at the most, but still).
+	cookies     [10]koekje
+	cookieIndex uint8
+	cookiesMu   sync.Mutex
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	// Create inotify fd
-	// Need to set the FD to nonblocking mode in order for SetDeadline methods to work
-	// Otherwise, blocking i/o operations won't terminate on close
+type (
+	watches struct {
+		mu   sync.RWMutex
+		wd   map[uint32]*watch // wd → watch
+		path map[string]uint32 // pathname → wd
+	}
+	watch struct {
+		wd      uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+		flags   uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+		path    string // Watch path.
+		recurse bool   // Recursion with ./...?
+	}
+	koekje struct {
+		cookie uint32
+		path   string
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:   make(map[uint32]*watch),
+		path: make(map[string]uint32),
+	}
+}
+
+func (w *watches) len() int {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return len(w.wd)
+}
+
+func (w *watches) add(ww *watch) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.wd[ww.wd] = ww
+	w.path[ww.path] = ww.wd
+}
+
+func (w *watches) remove(wd uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	watch := w.wd[wd] // Could have had Remove() called. See #616.
+	if watch == nil {
+		return
+	}
+	delete(w.path, watch.path)
+	delete(w.wd, wd)
+}
+
+func (w *watches) removePath(path string) ([]uint32, error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	path, recurse := recursivePath(path)
+	wd, ok := w.path[path]
+	if !ok {
+		return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path)
+	}
+
+	watch := w.wd[wd]
+	if recurse && !watch.recurse {
+		return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path)
+	}
+
+	delete(w.path, path)
+	delete(w.wd, wd)
+	if !watch.recurse {
+		return []uint32{wd}, nil
+	}
+
+	wds := make([]uint32, 0, 8)
+	wds = append(wds, wd)
+	for p, rwd := range w.path {
+		if filepath.HasPrefix(p, path) {
+			delete(w.path, p)
+			delete(w.wd, rwd)
+			wds = append(wds, rwd)
+		}
+	}
+	return wds, nil
+}
+
+func (w *watches) byPath(path string) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[w.path[path]]
+}
+
+func (w *watches) byWd(wd uint32) *watch {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	return w.wd[wd]
+}
+
+func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	var existing *watch
+	wd, ok := w.path[path]
+	if ok {
+		existing = w.wd[wd]
+	}
+
+	upd, err := f(existing)
+	if err != nil {
+		return err
+	}
+	if upd != nil {
+		w.wd[upd.wd] = upd
+		w.path[upd.path] = upd.wd
+
+		if upd.wd != wd {
+			delete(w.wd, wd)
+		}
+	}
+
+	return nil
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
+	// I/O operations won't terminate on close.
 	fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
 	if fd == -1 {
 		return nil, errno
 	}
 
-	w := &Watcher{
+	w := &inotify{
+		Events:      ev,
+		Errors:      errs,
 		fd:          fd,
 		inotifyFile: os.NewFile(uintptr(fd), ""),
-		watches:     make(map[string]*watch),
-		paths:       make(map[int]string),
-		Events:      make(chan Event),
-		Errors:      make(chan error),
+		watches:     newWatches(),
 		done:        make(chan struct{}),
 		doneResp:    make(chan struct{}),
 	}
@@ -152,26 +197,29 @@ func NewWatcher() (*Watcher, error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *inotify) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
-	select {
-	case w.Errors <- err:
+func (w *inotify) sendError(err error) bool {
+	if err == nil {
 		return true
+	}
+	select {
 	case <-w.done:
 		return false
+	case w.Errors <- err:
+		return true
 	}
 }
 
-func (w *Watcher) isClosed() bool {
+func (w *inotify) isClosed() bool {
 	select {
 	case <-w.done:
 		return true
@@ -180,17 +228,14 @@ func (w *Watcher) isClosed() bool {
 	}
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
+func (w *inotify) Close() error {
+	w.doneMu.Lock()
 	if w.isClosed() {
-		w.mu.Unlock()
+		w.doneMu.Unlock()
 		return nil
 	}
-
-	// Send 'close' signal to goroutine, and set the Watcher to closed.
 	close(w.done)
-	w.mu.Unlock()
+	w.doneMu.Unlock()
 
 	// Causes any blocking reads to return with an error, provided the file
 	// still supports deadline operations.
@@ -205,138 +250,168 @@ func (w *Watcher) Close() error {
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) Add(name string) error { return w.AddWith(name) }
+
+func (w *inotify) AddWith(path string, opts ...addOpt) error {
 	if w.isClosed() {
-		return errors.New("inotify instance already closed")
+		return ErrClosed
 	}
-
-	var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
-		unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
-		unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
-
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watchEntry := w.watches[name]
-	if watchEntry != nil {
-		flags |= watchEntry.flags | unix.IN_MASK_ADD
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), path)
 	}
-	wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
-	if wd == -1 {
-		return errno
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
 	}
 
-	if watchEntry == nil {
-		w.watches[name] = &watch{wd: uint32(wd), flags: flags}
-		w.paths[wd] = name
-	} else {
-		watchEntry.wd = uint32(wd)
-		watchEntry.flags = flags
+	path, recurse := recursivePath(path)
+	if recurse {
+		return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
+			if err != nil {
+				return err
+			}
+			if !d.IsDir() {
+				if root == path {
+					return fmt.Errorf("fsnotify: not a directory: %q", path)
+				}
+				return nil
+			}
+
+			// Send a Create event when adding new directory from a recursive
+			// watch; this is for "mkdir -p one/two/three". Usually all those
+			// directories will be created before we can set up watchers on the
+			// subdirectories, so only "one" would be sent as a Create event and
+			// not "one/two" and "one/two/three" (inotifywait -r has the same
+			// problem).
+			if with.sendCreate && root != path {
+				w.sendEvent(Event{Name: root, Op: Create})
+			}
+
+			return w.add(root, with, true)
+		})
 	}
 
-	return nil
+	return w.add(path, with, false)
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	name = filepath.Clean(name)
+func (w *inotify) add(path string, with withOpts, recurse bool) error {
+	var flags uint32
+	if with.noFollow {
+		flags |= unix.IN_DONT_FOLLOW
+	}
+	if with.op.Has(Create) {
+		flags |= unix.IN_CREATE
+	}
+	if with.op.Has(Write) {
+		flags |= unix.IN_MODIFY
+	}
+	if with.op.Has(Remove) {
+		flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
+	}
+	if with.op.Has(Rename) {
+		flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
+	}
+	if with.op.Has(Chmod) {
+		flags |= unix.IN_ATTRIB
+	}
+	if with.op.Has(xUnportableOpen) {
+		flags |= unix.IN_OPEN
+	}
+	if with.op.Has(xUnportableRead) {
+		flags |= unix.IN_ACCESS
+	}
+	if with.op.Has(xUnportableCloseWrite) {
+		flags |= unix.IN_CLOSE_WRITE
+	}
+	if with.op.Has(xUnportableCloseRead) {
+		flags |= unix.IN_CLOSE_NOWRITE
+	}
+	return w.register(path, flags, recurse)
+}
 
-	// Fetch the watch.
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	watch, ok := w.watches[name]
+func (w *inotify) register(path string, flags uint32, recurse bool) error {
+	return w.watches.updatePath(path, func(existing *watch) (*watch, error) {
+		if existing != nil {
+			flags |= existing.flags | unix.IN_MASK_ADD
+		}
 
-	// Remove it from inotify.
-	if !ok {
-		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
-	}
-
-	// We successfully removed the watch if InotifyRmWatch doesn't return an
-	// error, we need to clean up our internal state to ensure it matches
-	// inotify's kernel state.
-	delete(w.paths, int(watch.wd))
-	delete(w.watches, name)
-
-	// inotify_rm_watch will return EINVAL if the file has been deleted;
-	// the inotify will already have been removed.
-	// watches and pathes are deleted in ignoreLinux() implicitly and asynchronously
-	// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
-	// so that EINVAL means that the wd is being rm_watch()ed or its file removed
-	// by another thread and we have not received IN_IGNORE event.
-	success, errno := unix.InotifyRmWatch(w.fd, watch.wd)
-	if success == -1 {
-		// TODO: Perhaps it's not helpful to return an error here in every case;
-		//       The only two possible errors are:
-		//
-		//       - EBADF, which happens when w.fd is not a valid file descriptor
-		//         of any kind.
-		//       - EINVAL, which is when fd is not an inotify descriptor or wd
-		//         is not a valid watch descriptor. Watch descriptors are
-		//         invalidated when they are removed explicitly or implicitly;
-		//         explicitly by inotify_rm_watch, implicitly when the file they
-		//         are watching is deleted.
-		return errno
+		wd, err := unix.InotifyAddWatch(w.fd, path, flags)
+		if wd == -1 {
+			return nil, err
+		}
+
+		if existing == nil {
+			return &watch{
+				wd:      uint32(wd),
+				path:    path,
+				flags:   flags,
+				recurse: recurse,
+			}, nil
+		}
+
+		existing.wd = uint32(wd)
+		existing.flags = flags
+		return existing, nil
+	})
+}
+
+func (w *inotify) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(filepath.Clean(name))
+}
+
+func (w *inotify) remove(name string) error {
+	wds, err := w.watches.removePath(name)
+	if err != nil {
+		return err
 	}
 
+	for _, wd := range wds {
+		_, err := unix.InotifyRmWatch(w.fd, wd)
+		if err != nil {
+			// TODO: Perhaps it's not helpful to return an error here in every
+			// case; the only two possible errors are:
+			//
+			// EBADF, which happens when w.fd is not a valid file descriptor of
+			// any kind.
+			//
+			// EINVAL, which is when fd is not an inotify descriptor or wd is
+			// not a valid watch descriptor. Watch descriptors are invalidated
+			// when they are removed explicitly or implicitly; explicitly by
+			// inotify_rm_watch, implicitly when the file they are watching is
+			// deleted.
+			return err
+		}
+	}
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
+func (w *inotify) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
 
-	entries := make([]string, 0, len(w.watches))
-	for pathname := range w.watches {
+	entries := make([]string, 0, w.watches.len())
+	w.watches.mu.RLock()
+	for pathname := range w.watches.path {
 		entries = append(entries, pathname)
 	}
+	w.watches.mu.RUnlock()
 
 	return entries
 }
 
-type watch struct {
-	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
-	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
-}
-
 // readEvents reads from the inotify file descriptor, converts the
 // received events into Event objects and sends them via the Events channel
-func (w *Watcher) readEvents() {
+func (w *inotify) readEvents() {
 	defer func() {
 		close(w.doneResp)
 		close(w.Errors)
@@ -367,14 +442,11 @@ func (w *Watcher) readEvents() {
 		if n < unix.SizeofInotifyEvent {
 			var err error
 			if n == 0 {
-				// If EOF is received. This should really never happen.
-				err = io.EOF
+				err = io.EOF // If EOF is received. This should really never happen.
 			} else if n < 0 {
-				// If an error occurred while reading.
-				err = errno
+				err = errno // If an error occurred while reading.
 			} else {
-				// Read was too short.
-				err = errors.New("notify: short read in readEvents()")
+				err = errors.New("notify: short read in readEvents()") // Read was too short.
 			}
 			if !w.sendError(err) {
 				return
@@ -382,15 +454,17 @@ func (w *Watcher) readEvents() {
 			continue
 		}
 
-		var offset uint32
 		// We don't know how many events we just read into the buffer
 		// While the offset points to at least one whole event...
+		var offset uint32
 		for offset <= uint32(n-unix.SizeofInotifyEvent) {
 			var (
 				// Point "raw" to the event in the buffer
 				raw     = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
 				mask    = uint32(raw.Mask)
 				nameLen = uint32(raw.Len)
+				// Move to the next event in the buffer
+				next = func() { offset += unix.SizeofInotifyEvent + nameLen }
 			)
 
 			if mask&unix.IN_Q_OVERFLOW != 0 {
@@ -399,46 +473,124 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			// If the event happened to the watched directory or the watched file, the kernel
-			// doesn't append the filename to the event, but we would like to always fill the
-			// the "Name" field with a valid filename. We retrieve the path of the watch from
-			// the "paths" map.
-			w.mu.Lock()
-			name, ok := w.paths[int(raw.Wd)]
-			// IN_DELETE_SELF occurs when the file/directory being watched is removed.
-			// This is a sign to clean up the maps, otherwise we are no longer in sync
-			// with the inotify kernel state which has already deleted the watch
-			// automatically.
-			if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
-				delete(w.paths, int(raw.Wd))
-				delete(w.watches, name)
+			/// If the event happened to the watched directory or the watched
+			/// file, the kernel doesn't append the filename to the event, but
+			/// we would like to always fill the the "Name" field with a valid
+			/// filename. We retrieve the path of the watch from the "paths"
+			/// map.
+			watch := w.watches.byWd(uint32(raw.Wd))
+			/// Can be nil if Remove() was called in another goroutine for this
+			/// path inbetween reading the events from the kernel and reading
+			/// the internal state. Not much we can do about it, so just skip.
+			/// See #616.
+			if watch == nil {
+				next()
+				continue
 			}
-			w.mu.Unlock()
 
+			name := watch.path
 			if nameLen > 0 {
-				// Point "bytes" at the first byte of the filename
+				/// Point "bytes" at the first byte of the filename
 				bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
-				// The filename is padded with NULL bytes. TrimRight() gets rid of those.
+				/// The filename is padded with NULL bytes. TrimRight() gets rid of those.
 				name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
 			}
 
-			event := w.newEvent(name, mask)
+			if debug {
+				internal.Debug(name, raw.Mask, raw.Cookie)
+			}
 
-			// Send the events that are not ignored on the events channel
-			if mask&unix.IN_IGNORED == 0 {
-				if !w.sendEvent(event) {
-					return
+			if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0
+				next()
+				continue
+			}
+
+			// inotify will automatically remove the watch on deletes; just need
+			// to clean our state here.
+			if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
+				w.watches.remove(watch.wd)
+			}
+
+			// We can't really update the state when a watched path is moved;
+			// only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
+			// the watch.
+			if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
+				if watch.recurse {
+					next() // Do nothing
+					continue
+				}
+
+				err := w.remove(watch.path)
+				if err != nil && !errors.Is(err, ErrNonExistentWatch) {
+					if !w.sendError(err) {
+						return
+					}
+				}
+			}
+
+			/// Skip if we're watching both this path and the parent; the parent
+			/// will already send a delete so no need to do it twice.
+			if mask&unix.IN_DELETE_SELF != 0 {
+				if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok {
+					next()
+					continue
+				}
+			}
+
+			ev := w.newEvent(name, mask, raw.Cookie)
+			// Need to update watch path for recurse.
+			if watch.recurse {
+				isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR
+				/// New directory created: set up watch on it.
+				if isDir && ev.Has(Create) {
+					err := w.register(ev.Name, watch.flags, true)
+					if !w.sendError(err) {
+						return
+					}
+
+					// This was a directory rename, so we need to update all
+					// the children.
+					//
+					// TODO: this is of course pretty slow; we should use a
+					// better data structure for storing all of this, e.g. store
+					// children in the watch. I have some code for this in my
+					// kqueue refactor we can use in the future. For now I'm
+					// okay with this as it's not publicly available.
+					// Correctness first, performance second.
+					if ev.renamedFrom != "" {
+						w.watches.mu.Lock()
+						for k, ww := range w.watches.wd {
+							if k == watch.wd || ww.path == ev.Name {
+								continue
+							}
+							if strings.HasPrefix(ww.path, ev.renamedFrom) {
+								ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
+								w.watches.wd[k] = ww
+							}
+						}
+						w.watches.mu.Unlock()
+					}
 				}
 			}
 
-			// Move to the next event in the buffer
-			offset += unix.SizeofInotifyEvent + nameLen
+			/// Send the events that are not ignored on the events channel
+			if !w.sendEvent(ev) {
+				return
+			}
+			next()
 		}
 	}
 }
 
-// newEvent returns an platform-independent Event based on an inotify mask.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *inotify) isRecursive(path string) bool {
+	ww := w.watches.byPath(path)
+	if ww == nil { // path could be a file, so also check the Dir.
+		ww = w.watches.byPath(filepath.Dir(path))
+	}
+	return ww != nil && ww.recurse
+}
+
+func (w *inotify) newEvent(name string, mask, cookie uint32) Event {
 	e := Event{Name: name}
 	if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
 		e.Op |= Create
@@ -449,11 +601,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.IN_MODIFY == unix.IN_MODIFY {
 		e.Op |= Write
 	}
+	if mask&unix.IN_OPEN == unix.IN_OPEN {
+		e.Op |= xUnportableOpen
+	}
+	if mask&unix.IN_ACCESS == unix.IN_ACCESS {
+		e.Op |= xUnportableRead
+	}
+	if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE {
+		e.Op |= xUnportableCloseWrite
+	}
+	if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE {
+		e.Op |= xUnportableCloseRead
+	}
 	if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
 		e.Op |= Rename
 	}
 	if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
 		e.Op |= Chmod
 	}
+
+	if cookie != 0 {
+		if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
+			w.cookiesMu.Lock()
+			w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name}
+			w.cookieIndex++
+			if w.cookieIndex > 9 {
+				w.cookieIndex = 0
+			}
+			w.cookiesMu.Unlock()
+		} else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
+			w.cookiesMu.Lock()
+			var prev string
+			for _, c := range w.cookies {
+				if c.cookie == cookie {
+					prev = c.path
+					break
+				}
+			}
+			w.cookiesMu.Unlock()
+			e.renamedFrom = prev
+		}
+	}
 	return e
 }
+
+func (w *inotify) xSupports(op Op) bool {
+	return true // Supports everything.
+}
+
+func (w *inotify) state() {
+	w.watches.mu.Lock()
+	defer w.watches.mu.Unlock()
+	for wd, ww := range w.watches.wd {
+		fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
+	}
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/public-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
index 29087469..d8de5ab7 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
@@ -1,155 +1,201 @@
 //go:build freebsd || openbsd || netbsd || dragonfly || darwin
-// +build freebsd openbsd netbsd dragonfly darwin
 
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
+	"runtime"
 	"sync"
+	"time"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/unix"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type kqueue struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
-	done         chan struct{}
-	kq           int                         // File descriptor (as returned by the kqueue() syscall).
-	closepipe    [2]int                      // Pipe used for closing.
-	mu           sync.Mutex                  // Protects access to watcher data
-	watches      map[string]int              // Watched file descriptors (key: path).
-	watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)).
-	userWatches  map[string]struct{}         // Watches added with Watcher.Add()
-	dirFlags     map[string]uint32           // Watched directories to fflags used in kqueue.
-	paths        map[int]pathInfo            // File descriptors to path names for processing kqueue events.
-	fileExists   map[string]struct{}         // Keep track of if we know this file exists (to stop duplicate create events).
-	isClosed     bool                        // Set to true when Close() is first called
+	kq        int    // File descriptor (as returned by the kqueue() syscall).
+	closepipe [2]int // Pipe used for closing kq.
+	watches   *watches
+	done      chan struct{}
+	doneMu    sync.Mutex
 }
 
-type pathInfo struct {
-	name  string
-	isDir bool
+type (
+	watches struct {
+		mu     sync.RWMutex
+		wd     map[int]watch               // wd → watch
+		path   map[string]int              // pathname → wd
+		byDir  map[string]map[int]struct{} // dirname(path) → wd
+		seen   map[string]struct{}         // Keep track of if we know this file exists.
+		byUser map[string]struct{}         // Watches added with Watcher.Add()
+	}
+	watch struct {
+		wd       int
+		name     string
+		linkName string // In case of links; name is the target, and this is the link.
+		isDir    bool
+		dirFlags uint32
+	}
+)
+
+func newWatches() *watches {
+	return &watches{
+		wd:     make(map[int]watch),
+		path:   make(map[string]int),
+		byDir:  make(map[string]map[int]struct{}),
+		seen:   make(map[string]struct{}),
+		byUser: make(map[string]struct{}),
+	}
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func (w *watches) listPaths(userOnly bool) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	if userOnly {
+		l := make([]string, 0, len(w.byUser))
+		for p := range w.byUser {
+			l = append(l, p)
+		}
+		return l
+	}
+
+	l := make([]string, 0, len(w.path))
+	for p := range w.path {
+		l = append(l, p)
+	}
+	return l
+}
+
+func (w *watches) watchesInDir(path string) []string {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+
+	l := make([]string, 0, 4)
+	for fd := range w.byDir[path] {
+		info := w.wd[fd]
+		if _, ok := w.byUser[info.name]; !ok {
+			l = append(l, info.name)
+		}
+	}
+	return l
+}
+
+// Mark path as added by the user.
+func (w *watches) addUserWatch(path string) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	w.byUser[path] = struct{}{}
+}
+
+func (w *watches) addLink(path string, fd int) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.seen[path] = struct{}{}
+}
+
+func (w *watches) add(path, linkPath string, fd int, isDir bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	w.path[path] = fd
+	w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir}
+
+	parent := filepath.Dir(path)
+	byDir, ok := w.byDir[parent]
+	if !ok {
+		byDir = make(map[int]struct{}, 1)
+		w.byDir[parent] = byDir
+	}
+	byDir[fd] = struct{}{}
+}
+
+func (w *watches) byWd(fd int) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[fd]
+	return info, ok
+}
+
+func (w *watches) byPath(path string) (watch, bool) {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	info, ok := w.wd[w.path[path]]
+	return info, ok
+}
+
+func (w *watches) updateDirFlags(path string, flags uint32) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	fd := w.path[path]
+	info := w.wd[fd]
+	info.dirFlags = flags
+	w.wd[fd] = info
+}
+
+func (w *watches) remove(fd int, path string) bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	isDir := w.wd[fd].isDir
+	delete(w.path, path)
+	delete(w.byUser, path)
+
+	parent := filepath.Dir(path)
+	delete(w.byDir[parent], fd)
+
+	if len(w.byDir[parent]) == 0 {
+		delete(w.byDir, parent)
+	}
+
+	delete(w.wd, fd)
+	delete(w.seen, path)
+	return isDir
+}
+
+func (w *watches) markSeen(path string, exists bool) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	if exists {
+		w.seen[path] = struct{}{}
+	} else {
+		delete(w.seen, path)
+	}
+}
+
+func (w *watches) seenBefore(path string) bool {
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	_, ok := w.seen[path]
+	return ok
+}
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(0, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	kq, closepipe, err := newKqueue()
 	if err != nil {
 		return nil, err
 	}
 
-	w := &Watcher{
-		kq:           kq,
-		closepipe:    closepipe,
-		watches:      make(map[string]int),
-		watchesByDir: make(map[string]map[int]struct{}),
-		dirFlags:     make(map[string]uint32),
-		paths:        make(map[int]pathInfo),
-		fileExists:   make(map[string]struct{}),
-		userWatches:  make(map[string]struct{}),
-		Events:       make(chan Event),
-		Errors:       make(chan error),
-		done:         make(chan struct{}),
+	w := &kqueue{
+		Events:    ev,
+		Errors:    errs,
+		kq:        kq,
+		closepipe: closepipe,
+		done:      make(chan struct{}),
+		watches:   newWatches(),
 	}
 
 	go w.readEvents()
@@ -174,6 +220,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 		unix.Close(kq)
 		return kq, closepipe, err
 	}
+	unix.CloseOnExec(closepipe[0])
+	unix.CloseOnExec(closepipe[1])
 
 	// Register changes to listen on the closepipe.
 	changes := make([]unix.Kevent_t, 1)
@@ -192,218 +240,172 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
 }
 
 // Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
+func (w *kqueue) sendEvent(e Event) bool {
 	select {
+	case <-w.done:
+		return false
 	case w.Events <- e:
 		return true
-	case <-w.done:
 	}
-	return false
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *kqueue) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
+	case <-w.done:
+		return false
 	case w.Errors <- err:
 		return true
+	}
+}
+
+func (w *kqueue) isClosed() bool {
+	select {
 	case <-w.done:
+		return true
+	default:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *kqueue) Close() error {
+	w.doneMu.Lock()
+	if w.isClosed() {
+		w.doneMu.Unlock()
 		return nil
 	}
-	w.isClosed = true
+	close(w.done)
+	w.doneMu.Unlock()
 
-	// copy paths to remove while locked
-	pathsToRemove := make([]string, 0, len(w.watches))
-	for name := range w.watches {
-		pathsToRemove = append(pathsToRemove, name)
-	}
-	w.mu.Unlock() // Unlock before calling Remove, which also locks
+	pathsToRemove := w.watches.listPaths(false)
 	for _, name := range pathsToRemove {
 		w.Remove(name)
 	}
 
 	// Send "quit" message to the reader goroutine.
 	unix.Close(w.closepipe[1])
-	close(w.done)
-
 	return nil
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	w.userWatches[name] = struct{}{}
-	w.mu.Unlock()
+func (w *kqueue) Add(name string) error { return w.AddWith(name) }
+
+func (w *kqueue) AddWith(name string, opts ...addOpt) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+
 	_, err := w.addWatch(name, noteAllEvents)
-	return err
+	if err != nil {
+		return err
+	}
+	w.watches.addUserWatch(name)
+	return nil
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *kqueue) Remove(name string) error {
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), name)
+	}
+	return w.remove(name, true)
+}
+
+func (w *kqueue) remove(name string, unwatchFiles bool) error {
+	if w.isClosed() {
+		return nil
+	}
+
 	name = filepath.Clean(name)
-	w.mu.Lock()
-	watchfd, ok := w.watches[name]
-	w.mu.Unlock()
+	info, ok := w.watches.byPath(name)
 	if !ok {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_DELETE, 0)
+	err := w.register([]int{info.wd}, unix.EV_DELETE, 0)
 	if err != nil {
 		return err
 	}
 
-	unix.Close(watchfd)
-
-	w.mu.Lock()
-	isDir := w.paths[watchfd].isDir
-	delete(w.watches, name)
-	delete(w.userWatches, name)
-
-	parentName := filepath.Dir(name)
-	delete(w.watchesByDir[parentName], watchfd)
-
-	if len(w.watchesByDir[parentName]) == 0 {
-		delete(w.watchesByDir, parentName)
-	}
+	unix.Close(info.wd)
 
-	delete(w.paths, watchfd)
-	delete(w.dirFlags, name)
-	delete(w.fileExists, name)
-	w.mu.Unlock()
+	isDir := w.watches.remove(info.wd, name)
 
 	// Find all watched paths that are in this directory that are not external.
-	if isDir {
-		var pathsToRemove []string
-		w.mu.Lock()
-		for fd := range w.watchesByDir[name] {
-			path := w.paths[fd]
-			if _, ok := w.userWatches[path.name]; !ok {
-				pathsToRemove = append(pathsToRemove, path.name)
-			}
-		}
-		w.mu.Unlock()
+	if unwatchFiles && isDir {
+		pathsToRemove := w.watches.watchesInDir(name)
 		for _, name := range pathsToRemove {
-			// Since these are internal, not much sense in propagating error
-			// to the user, as that will just confuse them with an error about
-			// a path they did not explicitly watch themselves.
+			// Since these are internal, not much sense in propagating error to
+			// the user, as that will just confuse them with an error about a
+			// path they did not explicitly watch themselves.
 			w.Remove(name)
 		}
 	}
-
 	return nil
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-
-	entries := make([]string, 0, len(w.userWatches))
-	for pathname := range w.userWatches {
-		entries = append(entries, pathname)
+func (w *kqueue) WatchList() []string {
+	if w.isClosed() {
+		return nil
 	}
-
-	return entries
+	return w.watches.listPaths(true)
 }
 
 // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
 const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
 
-// addWatch adds name to the watched file set.
-// The flags are interpreted as described in kevent(2).
-// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
-func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
-	var isDir bool
-	// Make ./name and name equivalent
-	name = filepath.Clean(name)
-
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return "", errors.New("kevent instance already closed")
-	}
-	watchfd, alreadyWatching := w.watches[name]
-	// We already have a watch, but we can still override flags.
-	if alreadyWatching {
-		isDir = w.paths[watchfd].isDir
+// addWatch adds name to the watched file set; the flags are interpreted as
+// described in kevent(2).
+//
+// Returns the real path to the file which was added, with symlinks resolved.
+func (w *kqueue) addWatch(name string, flags uint32) (string, error) {
+	if w.isClosed() {
+		return "", ErrClosed
 	}
-	w.mu.Unlock()
 
+	name = filepath.Clean(name)
+
+	info, alreadyWatching := w.watches.byPath(name)
 	if !alreadyWatching {
 		fi, err := os.Lstat(name)
 		if err != nil {
 			return "", err
 		}
 
-		// Don't watch sockets or named pipes
+		// Don't watch sockets or named pipes.
 		if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) {
 			return "", nil
 		}
 
-		// Follow Symlinks
-		//
-		// Linux can add unresolvable symlinks to the watch list without issue,
-		// and Windows can't do symlinks period. To maintain consistency, we
-		// will act like everything is fine if the link can't be resolved.
-		// There will simply be no file events for broken symlinks. Hence the
-		// returns of nil on errors.
+		// Follow symlinks.
 		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
-			name, err = filepath.EvalSymlinks(name)
+			link, err := os.Readlink(name)
 			if err != nil {
+				// Return nil because Linux can add unresolvable symlinks to the
+				// watch list without problems, so maintain consistency with
+				// that. There will be no file events for broken symlinks.
+				// TODO: more specific check; returns os.PathError; ENOENT?
 				return "", nil
 			}
 
-			w.mu.Lock()
-			_, alreadyWatching = w.watches[name]
-			w.mu.Unlock()
-
+			_, alreadyWatching = w.watches.byPath(link)
 			if alreadyWatching {
-				return name, nil
+				// Add to watches so we don't get spurious Create events later
+				// on when we diff the directories.
+				w.watches.addLink(name, 0)
+				return link, nil
 			}
 
+			info.linkName = name
+			name = link
 			fi, err = os.Lstat(name)
 			if err != nil {
 				return "", nil
@@ -411,9 +413,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 		}
 
 		// Retry on EINTR; open() can return EINTR in practice on macOS.
-		// See #354, and go issues 11180 and 39237.
+		// See #354, and Go issues 11180 and 39237.
 		for {
-			watchfd, err = unix.Open(name, openMode, 0)
+			info.wd, err = unix.Open(name, openMode, 0)
 			if err == nil {
 				break
 			}
@@ -424,41 +426,25 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 			return "", err
 		}
 
-		isDir = fi.IsDir()
+		info.isDir = fi.IsDir()
 	}
 
-	err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
+	err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
 	if err != nil {
-		unix.Close(watchfd)
+		unix.Close(info.wd)
 		return "", err
 	}
 
 	if !alreadyWatching {
-		w.mu.Lock()
-		parentName := filepath.Dir(name)
-		w.watches[name] = watchfd
-
-		watchesByDir, ok := w.watchesByDir[parentName]
-		if !ok {
-			watchesByDir = make(map[int]struct{}, 1)
-			w.watchesByDir[parentName] = watchesByDir
-		}
-		watchesByDir[watchfd] = struct{}{}
-
-		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
-		w.mu.Unlock()
+		w.watches.add(name, info.linkName, info.wd, info.isDir)
 	}
 
-	if isDir {
-		// Watch the directory if it has not been watched before,
-		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
-		w.mu.Lock()
-
+	// Watch the directory if it has not been watched before, or if it was
+	// watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
+	if info.isDir {
 		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
-			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
-		// Store flags so this watch can be updated later
-		w.dirFlags[name] = flags
-		w.mu.Unlock()
+			(!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
+		w.watches.updateDirFlags(name, flags)
 
 		if watchDir {
 			if err := w.watchDirectoryFiles(name); err != nil {
@@ -471,95 +457,110 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
 
 // readEvents reads from kqueue and converts the received kevents into
 // Event values that it sends down the Events channel.
-func (w *Watcher) readEvents() {
+func (w *kqueue) readEvents() {
 	defer func() {
-		err := unix.Close(w.kq)
-		if err != nil {
-			w.Errors <- err
-		}
-		unix.Close(w.closepipe[0])
 		close(w.Events)
 		close(w.Errors)
+		_ = unix.Close(w.kq)
+		unix.Close(w.closepipe[0])
 	}()
 
 	eventBuffer := make([]unix.Kevent_t, 10)
-	for closed := false; !closed; {
+	for {
 		kevents, err := w.read(eventBuffer)
 		// EINTR is okay, the syscall was interrupted before timeout expired.
 		if err != nil && err != unix.EINTR {
 			if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) {
-				closed = true
+				return
 			}
-			continue
 		}
 
-		// Flush the events we received to the Events channel
 		for _, kevent := range kevents {
 			var (
-				watchfd = int(kevent.Ident)
-				mask    = uint32(kevent.Fflags)
+				wd   = int(kevent.Ident)
+				mask = uint32(kevent.Fflags)
 			)
 
 			// Shut down the loop when the pipe is closed, but only after all
 			// other events have been processed.
-			if watchfd == w.closepipe[0] {
-				closed = true
-				continue
+			if wd == w.closepipe[0] {
+				return
 			}
 
-			w.mu.Lock()
-			path := w.paths[watchfd]
-			w.mu.Unlock()
-
-			event := w.newEvent(path.name, mask)
+			path, ok := w.watches.byWd(wd)
+			if debug {
+				internal.Debug(path.name, &kevent)
+			}
 
-			if path.isDir && !event.Has(Remove) {
-				// Double check to make sure the directory exists. This can
-				// happen when we do a rm -fr on a recursively watched folders
-				// and we receive a modification event first but the folder has
-				// been deleted and later receive the delete event.
-				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
-					event.Op |= Remove
-				}
+			// On macOS it seems that sometimes an event with Ident=0 is
+			// delivered, and no other flags/information beyond that, even
+			// though we never saw such a file descriptor. For example in
+			// TestWatchSymlink/277 (usually at the end, but sometimes sooner):
+			//
+			// fmt.Printf("READ: %2d  %#v\n", kevent.Ident, kevent)
+			// unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			// unix.Kevent_t{Ident:0x0,  Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+			//
+			// The first is a normal event, the second with Ident 0. No error
+			// flag, no data, no ... nothing.
+			//
+			// I read a bit through bsd/kern_event.c from the xnu source, but I
+			// don't really see an obvious location where this is triggered –
+			// this doesn't seem intentional, but idk...
+			//
+			// Technically fd 0 is a valid descriptor, so only skip it if
+			// there's no path, and if we're on macOS.
+			if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" {
+				continue
 			}
 
+			event := w.newEvent(path.name, path.linkName, mask)
+
 			if event.Has(Rename) || event.Has(Remove) {
-				w.Remove(event.Name)
-				w.mu.Lock()
-				delete(w.fileExists, event.Name)
-				w.mu.Unlock()
+				w.remove(event.Name, false)
+				w.watches.markSeen(event.Name, false)
 			}
 
 			if path.isDir && event.Has(Write) && !event.Has(Remove) {
-				w.sendDirectoryChangeEvents(event.Name)
-			} else {
-				if !w.sendEvent(event) {
-					closed = true
-					continue
-				}
+				w.dirChange(event.Name)
+			} else if !w.sendEvent(event) {
+				return
 			}
 
 			if event.Has(Remove) {
-				// Look for a file that may have overwritten this.
-				// For example, mv f1 f2 will delete f2, then create f2.
+				// Look for a file that may have overwritten this; for example,
+				// mv f1 f2 will delete f2, then create f2.
 				if path.isDir {
 					fileDir := filepath.Clean(event.Name)
-					w.mu.Lock()
-					_, found := w.watches[fileDir]
-					w.mu.Unlock()
+					_, found := w.watches.byPath(fileDir)
 					if found {
-						// make sure the directory exists before we watch for changes. When we
-						// do a recursive watch and perform rm -fr, the parent directory might
-						// have gone missing, ignore the missing directory and let the
-						// upcoming delete event remove the watch from the parent directory.
-						if _, err := os.Lstat(fileDir); err == nil {
-							w.sendDirectoryChangeEvents(fileDir)
+						// TODO: this branch is never triggered in any test.
+						// Added in d6220df (2012).
+						// isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111
+						//
+						// I don't really get how this can be triggered either.
+						// And it wasn't triggered in the patch that added it,
+						// either.
+						//
+						// Original also had a comment:
+						//   make sure the directory exists before we watch for
+						//   changes. When we do a recursive watch and perform
+						//   rm -rf, the parent directory might have gone
+						//   missing, ignore the missing directory and let the
+						//   upcoming delete event remove the watch from the
+						//   parent directory.
+						err := w.dirChange(fileDir)
+						if !w.sendError(err) {
+							return
 						}
 					}
 				} else {
-					filePath := filepath.Clean(event.Name)
-					if fileInfo, err := os.Lstat(filePath); err == nil {
-						w.sendFileCreatedEventIfNew(filePath, fileInfo)
+					path := filepath.Clean(event.Name)
+					if fi, err := os.Lstat(path); err == nil {
+						err := w.sendCreateIfNew(path, fi)
+						if !w.sendError(err) {
+							return
+						}
 					}
 				}
 			}
@@ -568,8 +569,14 @@ func (w *Watcher) readEvents() {
 }
 
 // newEvent returns an platform-independent Event based on kqueue Fflags.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *kqueue) newEvent(name, linkName string, mask uint32) Event {
 	e := Event{Name: name}
+	if linkName != "" {
+		// If the user watched "/path/link" then emit events as "/path/link"
+		// rather than "/path/target".
+		e.Name = linkName
+	}
+
 	if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
 		e.Op |= Remove
 	}
@@ -582,21 +589,30 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
 		e.Op |= Chmod
 	}
+	// No point sending a write and delete event at the same time: if it's gone,
+	// then it's gone.
+	if e.Op.Has(Write) && e.Op.Has(Remove) {
+		e.Op &^= Write
+	}
 	return e
 }
 
 // watchDirectoryFiles to mimic inotify when adding a watch on a directory
-func (w *Watcher) watchDirectoryFiles(dirPath string) error {
-	// Get all files
-	files, err := ioutil.ReadDir(dirPath)
+func (w *kqueue) watchDirectoryFiles(dirPath string) error {
+	files, err := os.ReadDir(dirPath)
 	if err != nil {
 		return err
 	}
 
-	for _, fileInfo := range files {
-		path := filepath.Join(dirPath, fileInfo.Name())
+	for _, f := range files {
+		path := filepath.Join(dirPath, f.Name())
 
-		cleanPath, err := w.internalWatch(path, fileInfo)
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("%q: %w", path, err)
+		}
+
+		cleanPath, err := w.internalWatch(path, fi)
 		if err != nil {
 			// No permission to read the file; that's not a problem: just skip.
 			// But do add it to w.fileExists to prevent it from being picked up
@@ -606,13 +622,11 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 			case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM):
 				cleanPath = filepath.Clean(path)
 			default:
-				return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err)
+				return fmt.Errorf("%q: %w", path, err)
 			}
 		}
 
-		w.mu.Lock()
-		w.fileExists[cleanPath] = struct{}{}
-		w.mu.Unlock()
+		w.watches.markSeen(cleanPath, true)
 	}
 
 	return nil
@@ -622,58 +636,59 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
 //
 // This functionality is to have the BSD watcher match the inotify, which sends
 // a create event for files created in a watched directory.
-func (w *Watcher) sendDirectoryChangeEvents(dir string) {
-	// Get all files
-	files, err := ioutil.ReadDir(dir)
+func (w *kqueue) dirChange(dir string) error {
+	files, err := os.ReadDir(dir)
 	if err != nil {
-		if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) {
-			return
+		// Directory no longer exists: we can ignore this safely. kqueue will
+		// still give us the correct events.
+		if errors.Is(err, os.ErrNotExist) {
+			return nil
 		}
+		return fmt.Errorf("fsnotify.dirChange: %w", err)
 	}
 
-	// Search for new files
-	for _, fi := range files {
-		err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi)
+	for _, f := range files {
+		fi, err := f.Info()
+		if err != nil {
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
+		}
+
+		err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
 		if err != nil {
-			return
+			// Don't need to send an error if this file isn't readable.
+			if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) {
+				return nil
+			}
+			return fmt.Errorf("fsnotify.dirChange: %w", err)
 		}
 	}
+	return nil
 }
 
-// sendFileCreatedEvent sends a create event if the file isn't already being tracked.
-func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) {
-	w.mu.Lock()
-	_, doesExist := w.fileExists[filePath]
-	w.mu.Unlock()
-	if !doesExist {
-		if !w.sendEvent(Event{Name: filePath, Op: Create}) {
-			return
+// Send a create event if the file isn't already being tracked, and start
+// watching this file.
+func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error {
+	if !w.watches.seenBefore(path) {
+		if !w.sendEvent(Event{Name: path, Op: Create}) {
+			return nil
 		}
 	}
 
-	// like watchDirectoryFiles (but without doing another ReadDir)
-	filePath, err = w.internalWatch(filePath, fileInfo)
+	// Like watchDirectoryFiles, but without doing another ReadDir.
+	path, err := w.internalWatch(path, fi)
 	if err != nil {
 		return err
 	}
-
-	w.mu.Lock()
-	w.fileExists[filePath] = struct{}{}
-	w.mu.Unlock()
-
+	w.watches.markSeen(path, true)
 	return nil
 }
 
-func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) {
-	if fileInfo.IsDir() {
-		// mimic Linux providing delete events for subdirectories
-		// but preserve the flags used if currently watching subdirectory
-		w.mu.Lock()
-		flags := w.dirFlags[name]
-		w.mu.Unlock()
-
-		flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
-		return w.addWatch(name, flags)
+func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) {
+	if fi.IsDir() {
+		// mimic Linux providing delete events for subdirectories, but preserve
+		// the flags used if currently watching subdirectory
+		info, _ := w.watches.byPath(name)
+		return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME)
 	}
 
 	// watch file to mimic Linux inotify
@@ -681,7 +696,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro
 }
 
 // Register events with the queue.
-func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
+func (w *kqueue) register(fds []int, flags int, fflags uint32) error {
 	changes := make([]unix.Kevent_t, len(fds))
 	for i, fd := range fds {
 		// SetKevent converts int to the platform-specific types.
@@ -698,10 +713,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
 }
 
 // read retrieves pending events, or waits until an event occurs.
-func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
+func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
 	n, err := unix.Kevent(w.kq, nil, events, nil)
 	if err != nil {
 		return nil, err
 	}
 	return events[0:n], nil
 }
+
+func (w *kqueue) xSupports(op Op) bool {
+	if runtime.GOOS == "freebsd" {
+		//return true // Supports everything.
+	}
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/backend_other.go b/public-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
index a9bb1c3c..5eb5dbc6 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/backend_other.go
@@ -1,66 +1,23 @@
-//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows
-// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
+//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
 
 package fsnotify
 
-import (
-	"fmt"
-	"runtime"
-)
+import "errors"
 
-// Watcher watches a set of files, delivering events to a channel.
-type Watcher struct{}
-
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
-	return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	return nil
+type other struct {
+	Events chan Event
+	Errors chan error
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	return nil
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return nil, errors.New("fsnotify not supported on the current platform")
 }
-
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
-	return nil
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
+	return newBackend(ev, errs)
 }
+func (w *other) Close() error                              { return nil }
+func (w *other) WatchList() []string                       { return nil }
+func (w *other) Add(name string) error                     { return nil }
+func (w *other) AddWith(name string, opts ...addOpt) error { return nil }
+func (w *other) Remove(name string) error                  { return nil }
+func (w *other) xSupports(op Op) bool                      { return false }
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/public-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
index ae392867..c54a6308 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/backend_windows.go
@@ -1,5 +1,8 @@
 //go:build windows
-// +build windows
+
+// Windows backend based on ReadDirectoryChangesW()
+//
+// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
 
 package fsnotify
 
@@ -12,143 +15,60 @@ import (
 	"runtime"
 	"strings"
 	"sync"
+	"time"
 	"unsafe"
 
+	"github.com/fsnotify/fsnotify/internal"
 	"golang.org/x/sys/windows"
 )
 
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-//     fp := os.Open("file")
-//     os.Remove("file")        // Triggers Chmod
-//     fp.Close()               // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-//     # Default values on Linux 5.18
-//     sysctl fs.inotify.max_user_watches=124983
-//     sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-//     fs.inotify.max_user_watches=124983
-//     fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # macOS notes
-//
-// Spotlight indexing on macOS can result in multiple events (see [#15]). A
-// temporary workaround is to add your folder(s) to the "Spotlight Privacy
-// Settings" until we have a native FSEvents implementation (see [#11]).
-//
-// [#11]: https://github.com/fsnotify/fsnotify/issues/11
-// [#15]: https://github.com/fsnotify/fsnotify/issues/15
-type Watcher struct {
-	// Events sends the filesystem change events.
-	//
-	// fsnotify can send the following events; a "path" here can refer to a
-	// file, directory, symbolic link, or special file like a FIFO.
-	//
-	//   fsnotify.Create    A new path was created; this may be followed by one
-	//                      or more Write events if data also gets written to a
-	//                      file.
-	//
-	//   fsnotify.Remove    A path was removed.
-	//
-	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
-	//                      old path as Event.Name, and a Create event will be
-	//                      sent with the new name. Renames are only sent for
-	//                      paths that are currently watched; e.g. moving an
-	//                      unmonitored file into a monitored directory will
-	//                      show up as just a Create. Similarly, renaming a file
-	//                      to outside a monitored directory will show up as
-	//                      only a Rename.
-	//
-	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
-	//                      also trigger a Write. A single "write action"
-	//                      initiated by the user may show up as one or multiple
-	//                      writes, depending on when the system syncs things to
-	//                      disk. For example when compiling a large Go program
-	//                      you may get hundreds of Write events, so you
-	//                      probably want to wait until you've stopped receiving
-	//                      them (see the dedup example in cmd/fsnotify).
-	//
-	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
-	//                      when a file is removed (or more accurately, when a
-	//                      link to an inode is removed). On kqueue it's sent
-	//                      and on kqueue when a file is truncated. On Windows
-	//                      it's never sent.
+type readDirChangesW struct {
 	Events chan Event
-
-	// Errors sends any errors.
 	Errors chan error
 
 	port  windows.Handle // Handle to completion port
 	input chan *input    // Inputs to the reader are sent on this channel
 	quit  chan chan<- error
 
-	mu       sync.Mutex // Protects access to watches, isClosed
-	watches  watchMap   // Map of watches (key: i-number)
-	isClosed bool       // Set to true when Close() is first called
+	mu      sync.Mutex // Protects access to watches, closed
+	watches watchMap   // Map of watches (key: i-number)
+	closed  bool       // Set to true when Close() is first called
 }
 
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+	return newBufferedBackend(50, ev, errs)
+}
+
+func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) {
 	port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
 	if err != nil {
 		return nil, os.NewSyscallError("CreateIoCompletionPort", err)
 	}
-	w := &Watcher{
+	w := &readDirChangesW{
+		Events:  ev,
+		Errors:  errs,
 		port:    port,
 		watches: make(watchMap),
 		input:   make(chan *input, 1),
-		Events:  make(chan Event, 50),
-		Errors:  make(chan error),
 		quit:    make(chan chan<- error, 1),
 	}
 	go w.readEvents()
 	return w, nil
 }
 
-func (w *Watcher) sendEvent(name string, mask uint64) bool {
+func (w *readDirChangesW) isClosed() bool {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	return w.closed
+}
+
+func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
 	if mask == 0 {
 		return false
 	}
 
 	event := w.newEvent(name, uint32(mask))
+	event.renamedFrom = renamedFrom
 	select {
 	case ch := <-w.quit:
 		w.quit <- ch
@@ -158,23 +78,25 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
 }
 
 // Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *readDirChangesW) sendError(err error) bool {
+	if err == nil {
+		return true
+	}
 	select {
 	case w.Errors <- err:
 		return true
 	case <-w.quit:
+		return false
 	}
-	return false
 }
 
-// Close removes all watches and closes the events channel.
-func (w *Watcher) Close() error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
+func (w *readDirChangesW) Close() error {
+	if w.isClosed() {
 		return nil
 	}
-	w.isClosed = true
+
+	w.mu.Lock()
+	w.closed = true
 	w.mu.Unlock()
 
 	// Send "quit" message to the reader goroutine
@@ -186,49 +108,31 @@ func (w *Watcher) Close() error {
 	return <-ch
 }
 
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; attempting to watch it more than once will
-// return an error. Paths that do not yet exist on the filesystem cannot be
-// added. A watch will be automatically removed if the path is deleted.
-//
-// A path will remain watched if it gets renamed to somewhere else on the same
-// filesystem, but the monitor will get removed if the path gets deleted and
-// re-created, or if it's moved to a different filesystem.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many tools update files atomically. Instead of "just" writing
-// to the file a temporary file will be written to first, and if successful the
-// temporary file is moved to to destination removing the original, or some
-// variant thereof. The watcher on the original file is now lost, as it no
-// longer exists.
-//
-// Instead, watch the parent directory and use Event.Name to filter out files
-// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
-func (w *Watcher) Add(name string) error {
-	w.mu.Lock()
-	if w.isClosed {
-		w.mu.Unlock()
-		return errors.New("watcher already closed")
+func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
+
+func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error {
+	if w.isClosed() {
+		return ErrClosed
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  AddWith(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
+	with := getOptions(opts...)
+	if !w.xSupports(with.op) {
+		return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+	}
+	if with.bufsize < 4096 {
+		return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
 	}
-	w.mu.Unlock()
 
 	in := &input{
-		op:    opAddWatch,
-		path:  filepath.Clean(name),
-		flags: sysFSALLEVENTS,
-		reply: make(chan error),
+		op:      opAddWatch,
+		path:    filepath.Clean(name),
+		flags:   sysFSALLEVENTS,
+		reply:   make(chan error),
+		bufsize: with.bufsize,
 	}
 	w.input <- in
 	if err := w.wakeupReader(); err != nil {
@@ -237,13 +141,15 @@ func (w *Watcher) Add(name string) error {
 	return <-in.reply
 }
 
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-func (w *Watcher) Remove(name string) error {
+func (w *readDirChangesW) Remove(name string) error {
+	if w.isClosed() {
+		return nil
+	}
+	if debug {
+		fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  Remove(%q)\n",
+			time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+	}
+
 	in := &input{
 		op:    opRemoveWatch,
 		path:  filepath.Clean(name),
@@ -256,15 +162,24 @@ func (w *Watcher) Remove(name string) error {
 	return <-in.reply
 }
 
-// WatchList returns all paths added with [Add] (and are not yet removed).
-func (w *Watcher) WatchList() []string {
+func (w *readDirChangesW) WatchList() []string {
+	if w.isClosed() {
+		return nil
+	}
+
 	w.mu.Lock()
 	defer w.mu.Unlock()
 
 	entries := make([]string, 0, len(w.watches))
 	for _, entry := range w.watches {
 		for _, watchEntry := range entry {
-			entries = append(entries, watchEntry.path)
+			for name := range watchEntry.names {
+				entries = append(entries, filepath.Join(watchEntry.path, name))
+			}
+			// the directory itself is being watched
+			if watchEntry.mask != 0 {
+				entries = append(entries, watchEntry.path)
+			}
 		}
 	}
 
@@ -279,7 +194,6 @@ func (w *Watcher) WatchList() []string {
 // This should all be removed at some point, and just use windows.FILE_NOTIFY_*
 const (
 	sysFSALLEVENTS  = 0xfff
-	sysFSATTRIB     = 0x4
 	sysFSCREATE     = 0x100
 	sysFSDELETE     = 0x200
 	sysFSDELETESELF = 0x400
@@ -291,7 +205,7 @@ const (
 	sysFSIGNORED    = 0x8000
 )
 
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
 	e := Event{Name: name}
 	if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
 		e.Op |= Create
@@ -305,9 +219,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
 	if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
 		e.Op |= Rename
 	}
-	if mask&sysFSATTRIB == sysFSATTRIB {
-		e.Op |= Chmod
-	}
 	return e
 }
 
@@ -321,10 +232,11 @@ const (
 )
 
 type input struct {
-	op    int
-	path  string
-	flags uint32
-	reply chan error
+	op      int
+	path    string
+	flags   uint32
+	bufsize int
+	reply   chan error
 }
 
 type inode struct {
@@ -334,13 +246,14 @@ type inode struct {
 }
 
 type watch struct {
-	ov     windows.Overlapped
-	ino    *inode            // i-number
-	path   string            // Directory path
-	mask   uint64            // Directory itself is being watched with these notify flags
-	names  map[string]uint64 // Map of names being watched and their notify flags
-	rename string            // Remembers the old name while renaming a file
-	buf    [65536]byte       // 64K buffer
+	ov      windows.Overlapped
+	ino     *inode            // i-number
+	recurse bool              // Recursive watch?
+	path    string            // Directory path
+	mask    uint64            // Directory itself is being watched with these notify flags
+	names   map[string]uint64 // Map of names being watched and their notify flags
+	rename  string            // Remembers the old name while renaming a file
+	buf     []byte            // buffer, allocated later
 }
 
 type (
@@ -348,7 +261,7 @@ type (
 	watchMap map[uint32]indexMap
 )
 
-func (w *Watcher) wakeupReader() error {
+func (w *readDirChangesW) wakeupReader() error {
 	err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
 	if err != nil {
 		return os.NewSyscallError("PostQueuedCompletionStatus", err)
@@ -356,7 +269,7 @@ func (w *Watcher) wakeupReader() error {
 	return nil
 }
 
-func (w *Watcher) getDir(pathname string) (dir string, err error) {
+func (w *readDirChangesW) getDir(pathname string) (dir string, err error) {
 	attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
 	if err != nil {
 		return "", os.NewSyscallError("GetFileAttributes", err)
@@ -370,7 +283,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
 	return
 }
 
-func (w *Watcher) getIno(path string) (ino *inode, err error) {
+func (w *readDirChangesW) getIno(path string) (ino *inode, err error) {
 	h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
 		windows.FILE_LIST_DIRECTORY,
 		windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
@@ -413,7 +326,9 @@ func (m watchMap) set(ino *inode, watch *watch) {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) addWatch(pathname string, flags uint64) error {
+func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -433,9 +348,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 			return os.NewSyscallError("CreateIoCompletionPort", err)
 		}
 		watchEntry = &watch{
-			ino:   ino,
-			path:  dir,
-			names: make(map[string]uint64),
+			ino:     ino,
+			path:    dir,
+			names:   make(map[string]uint64),
+			recurse: recurse,
+			buf:     make([]byte, bufsize),
 		}
 		w.mu.Lock()
 		w.watches.set(ino, watchEntry)
@@ -464,7 +381,9 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) remWatch(pathname string) error {
+func (w *readDirChangesW) remWatch(pathname string) error {
+	pathname, recurse := recursivePath(pathname)
+
 	dir, err := w.getDir(pathname)
 	if err != nil {
 		return err
@@ -478,6 +397,10 @@ func (w *Watcher) remWatch(pathname string) error {
 	watch := w.watches.get(ino)
 	w.mu.Unlock()
 
+	if recurse && !watch.recurse {
+		return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname)
+	}
+
 	err = windows.CloseHandle(ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CloseHandle", err))
@@ -486,11 +409,11 @@ func (w *Watcher) remWatch(pathname string) error {
 		return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
 	}
 	if pathname == dir {
-		w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+		w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		watch.mask = 0
 	} else {
 		name := filepath.Base(pathname)
-		w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
+		w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED)
 		delete(watch.names, name)
 	}
 
@@ -498,23 +421,23 @@ func (w *Watcher) remWatch(pathname string) error {
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) deleteWatch(watch *watch) {
+func (w *readDirChangesW) deleteWatch(watch *watch) {
 	for name, mask := range watch.names {
 		if mask&provisional == 0 {
-			w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
+			w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED)
 		}
 		delete(watch.names, name)
 	}
 	if watch.mask != 0 {
 		if watch.mask&provisional == 0 {
-			w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+			w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
 		}
 		watch.mask = 0
 	}
 }
 
 // Must run within the I/O thread.
-func (w *Watcher) startRead(watch *watch) error {
+func (w *readDirChangesW) startRead(watch *watch) error {
 	err := windows.CancelIo(watch.ino.handle)
 	if err != nil {
 		w.sendError(os.NewSyscallError("CancelIo", err))
@@ -535,13 +458,16 @@ func (w *Watcher) startRead(watch *watch) error {
 		return nil
 	}
 
-	rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
-		uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+	// We need to pass the array, rather than the slice.
+	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf))
+	rdErr := windows.ReadDirectoryChanges(watch.ino.handle,
+		(*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len),
+		watch.recurse, mask, nil, &watch.ov, 0)
 	if rdErr != nil {
 		err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
 		if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			err = nil
 		}
 		w.deleteWatch(watch)
@@ -554,7 +480,7 @@ func (w *Watcher) startRead(watch *watch) error {
 // readEvents reads from the I/O completion port, converts the
 // received events into Event objects and sends them via the Events channel.
 // Entry point to the I/O thread.
-func (w *Watcher) readEvents() {
+func (w *readDirChangesW) readEvents() {
 	var (
 		n   uint32
 		key uintptr
@@ -563,9 +489,8 @@ func (w *Watcher) readEvents() {
 	runtime.LockOSThread()
 
 	for {
+		// This error is handled after the watch == nil check below.
 		qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE)
-		// This error is handled after the watch == nil check below. NOTE: this
-		// seems odd, note sure if it's correct.
 
 		watch := (*watch)(unsafe.Pointer(ov))
 		if watch == nil {
@@ -595,7 +520,7 @@ func (w *Watcher) readEvents() {
 			case in := <-w.input:
 				switch in.op {
 				case opAddWatch:
-					in.reply <- w.addWatch(in.path, uint64(in.flags))
+					in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize)
 				case opRemoveWatch:
 					in.reply <- w.remWatch(in.path)
 				}
@@ -605,6 +530,8 @@ func (w *Watcher) readEvents() {
 		}
 
 		switch qErr {
+		case nil:
+			// No error
 		case windows.ERROR_MORE_DATA:
 			if watch == nil {
 				w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer"))
@@ -616,7 +543,7 @@ func (w *Watcher) readEvents() {
 			}
 		case windows.ERROR_ACCESS_DENIED:
 			// Watched directory was probably removed
-			w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+			w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
 			w.deleteWatch(watch)
 			w.startRead(watch)
 			continue
@@ -626,13 +553,12 @@ func (w *Watcher) readEvents() {
 		default:
 			w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr))
 			continue
-		case nil:
 		}
 
 		var offset uint32
 		for {
 			if n == 0 {
-				w.sendError(errors.New("short read in readEvents()"))
+				w.sendError(ErrEventOverflow)
 				break
 			}
 
@@ -650,6 +576,10 @@ func (w *Watcher) readEvents() {
 			name := windows.UTF16ToString(buf)
 			fullname := filepath.Join(watch.path, name)
 
+			if debug {
+				internal.Debug(fullname, raw.Action)
+			}
+
 			var mask uint64
 			switch raw.Action {
 			case windows.FILE_ACTION_REMOVED:
@@ -678,21 +608,22 @@ func (w *Watcher) readEvents() {
 				}
 			}
 
-			sendNameEvent := func() {
-				w.sendEvent(fullname, watch.names[name]&mask)
-			}
 			if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
-				sendNameEvent()
+				w.sendEvent(fullname, "", watch.names[name]&mask)
 			}
 			if raw.Action == windows.FILE_ACTION_REMOVED {
-				w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
+				w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED)
 				delete(watch.names, name)
 			}
 
-			w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action))
+			if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
+				w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action))
+			} else {
+				w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action))
+			}
+
 			if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
-				fullname = filepath.Join(watch.path, watch.rename)
-				sendNameEvent()
+				w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
 			}
 
 			// Move to the next event in the buffer
@@ -703,8 +634,8 @@ func (w *Watcher) readEvents() {
 
 			// Error!
 			if offset >= n {
-				w.sendError(errors.New(
-					"Windows system assumed buffer larger than it is, events have likely been missed."))
+				//lint:ignore ST1005 Windows should be capitalized
+				w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed"))
 				break
 			}
 		}
@@ -715,21 +646,18 @@ func (w *Watcher) readEvents() {
 	}
 }
 
-func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
+func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
 	var m uint32
 	if mask&sysFSMODIFY != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
 	}
-	if mask&sysFSATTRIB != 0 {
-		m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES
-	}
 	if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
 		m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME
 	}
 	return m
 }
 
-func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
+func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
 	switch action {
 	case windows.FILE_ACTION_ADDED:
 		return sysFSCREATE
@@ -744,3 +672,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
 	}
 	return 0
 }
+
+func (w *readDirChangesW) xSupports(op Op) bool {
+	if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+		op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+		return false
+	}
+	return true
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/public-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
index 30a5bf0f..0760efe9 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/fsnotify.go
@@ -1,16 +1,148 @@
-//go:build !plan9
-// +build !plan9
-
 // Package fsnotify provides a cross-platform interface for file system
 // notifications.
+//
+// Currently supported systems:
+//
+//   - Linux      via inotify
+//   - BSD, macOS via kqueue
+//   - Windows    via ReadDirectoryChangesW
+//   - illumos    via FEN
+//
+// # FSNOTIFY_DEBUG
+//
+// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to
+// stderr. This can be useful to track down some problems, especially in cases
+// where fsnotify is used as an indirect dependency.
+//
+// Every event will be printed as soon as there's something useful to print,
+// with as little processing from fsnotify.
+//
+// Example output:
+//
+//	FSNOTIFY_DEBUG: 11:34:23.633087586   256:IN_CREATE            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:23.633202319     4:IN_ATTRIB            → "/tmp/file-1"
+//	FSNOTIFY_DEBUG: 11:34:28.989728764   512:IN_DELETE            → "/tmp/file-1"
 package fsnotify
 
 import (
 	"errors"
 	"fmt"
+	"os"
+	"path/filepath"
 	"strings"
 )
 
+// Watcher watches a set of paths, delivering events on a channel.
+//
+// A watcher should not be copied (e.g. pass it by pointer, rather than by
+// value).
+//
+// # Linux notes
+//
+// When a file is removed a Remove event won't be emitted until all file
+// descriptors are closed, and deletes will always emit a Chmod. For example:
+//
+//	fp := os.Open("file")
+//	os.Remove("file")        // Triggers Chmod
+//	fp.Close()               // Triggers Remove
+//
+// This is the event that inotify sends, so not much can be changed about this.
+//
+// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
+// for the number of watches per user, and fs.inotify.max_user_instances
+// specifies the maximum number of inotify instances per user. Every Watcher you
+// create is an "instance", and every path you add is a "watch".
+//
+// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
+// /proc/sys/fs/inotify/max_user_instances
+//
+// To increase them you can use sysctl or write the value to the /proc file:
+//
+//	# Default values on Linux 5.18
+//	sysctl fs.inotify.max_user_watches=124983
+//	sysctl fs.inotify.max_user_instances=128
+//
+// To make the changes persist on reboot edit /etc/sysctl.conf or
+// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
+// your distro's documentation):
+//
+//	fs.inotify.max_user_watches=124983
+//	fs.inotify.max_user_instances=128
+//
+// Reaching the limit will result in a "no space left on device" or "too many open
+// files" error.
+//
+// # kqueue notes (macOS, BSD)
+//
+// kqueue requires opening a file descriptor for every file that's being watched;
+// so if you're watching a directory with five files then that's six file
+// descriptors. You will run in to your system's "max open files" limit faster on
+// these platforms.
+//
+// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
+// control the maximum number of open files, as well as /etc/login.conf on BSD
+// systems.
+//
+// # Windows notes
+//
+// Paths can be added as "C:\\path\\to\\dir", but forward slashes
+// ("C:/path/to/dir") will also work.
+//
+// When a watched directory is removed it will always send an event for the
+// directory itself, but may not send events for all files in that directory.
+// Sometimes it will send events for all files, sometimes it will send no
+// events, and often only for some files.
+//
+// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest
+// value that is guaranteed to work with SMB filesystems. If you have many
+// events in quick succession this may not be enough, and you will have to use
+// [WithBufferSize] to increase the value.
+type Watcher struct {
+	b backend
+
+	// Events sends the filesystem change events.
+	//
+	// fsnotify can send the following events; a "path" here can refer to a
+	// file, directory, symbolic link, or special file like a FIFO.
+	//
+	//   fsnotify.Create    A new path was created; this may be followed by one
+	//                      or more Write events if data also gets written to a
+	//                      file.
+	//
+	//   fsnotify.Remove    A path was removed.
+	//
+	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
+	//                      old path as Event.Name, and a Create event will be
+	//                      sent with the new name. Renames are only sent for
+	//                      paths that are currently watched; e.g. moving an
+	//                      unmonitored file into a monitored directory will
+	//                      show up as just a Create. Similarly, renaming a file
+	//                      to outside a monitored directory will show up as
+	//                      only a Rename.
+	//
+	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
+	//                      also trigger a Write. A single "write action"
+	//                      initiated by the user may show up as one or multiple
+	//                      writes, depending on when the system syncs things to
+	//                      disk. For example when compiling a large Go program
+	//                      you may get hundreds of Write events, and you may
+	//                      want to wait until you've stopped receiving them
+	//                      (see the dedup example in cmd/fsnotify).
+	//
+	//                      Some systems may send Write event for directories
+	//                      when the directory content changes.
+	//
+	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
+	//                      when a file is removed (or more accurately, when a
+	//                      link to an inode is removed). On kqueue it's sent
+	//                      when a file is truncated. On Windows it's never
+	//                      sent.
+	Events chan Event
+
+	// Errors sends any errors.
+	Errors chan error
+}
+
 // Event represents a file system notification.
 type Event struct {
 	// Path to the file or directory.
@@ -25,6 +157,16 @@ type Event struct {
 	// This is a bitmask and some systems may send multiple operations at once.
 	// Use the Event.Has() method instead of comparing with ==.
 	Op Op
+
+	// Create events will have this set to the old path if it's a rename. This
+	// only works when both the source and destination are watched. It's not
+	// reliable when watching individual files, only directories.
+	//
+	// For example "mv /tmp/file /tmp/rename" will emit:
+	//
+	//   Event{Op: Rename, Name: "/tmp/file"}
+	//   Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"}
+	renamedFrom string
 }
 
 // Op describes a set of file operations.
@@ -33,34 +175,204 @@ type Op uint32
 // The operations fsnotify can trigger; see the documentation on [Watcher] for a
 // full description, and check them with [Event.Has].
 const (
+	// A new pathname was created.
 	Create Op = 1 << iota
+
+	// The pathname was written to; this does *not* mean the write has finished,
+	// and a write can be followed by more writes.
 	Write
+
+	// The path was removed; any watches on it will be removed. Some "remove"
+	// operations may trigger a Rename if the file is actually moved (for
+	// example "remove to trash" is often a rename).
 	Remove
+
+	// The path was renamed to something else; any watches on it will be
+	// removed.
 	Rename
+
+	// File attributes were changed.
+	//
+	// It's generally not recommended to take action on this event, as it may
+	// get triggered very frequently by some software. For example, Spotlight
+	// indexing on macOS, anti-virus software, backup software, etc.
 	Chmod
+
+	// File descriptor was opened.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableOpen
+
+	// File was read from.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableRead
+
+	// File opened for writing was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	//
+	// The advantage of using this over Write is that it's more reliable than
+	// waiting for Write events to stop. It's also faster (if you're not
+	// listening to Write events): copying a file of a few GB can easily
+	// generate tens of thousands of Write events in a short span of time.
+	xUnportableCloseWrite
+
+	// File opened for reading was closed.
+	//
+	// Only works on Linux and FreeBSD.
+	xUnportableCloseRead
 )
 
-// Common errors that can be reported by a watcher
 var (
-	ErrNonExistentWatch = errors.New("can't remove non-existent watcher")
-	ErrEventOverflow    = errors.New("fsnotify queue overflow")
+	// ErrNonExistentWatch is used when Remove() is called on a path that's not
+	// added.
+	ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
+
+	// ErrClosed is used when trying to operate on a closed Watcher.
+	ErrClosed = errors.New("fsnotify: watcher already closed")
+
+	// ErrEventOverflow is reported from the Errors channel when there are too
+	// many events:
+	//
+	//  - inotify:      inotify returns IN_Q_OVERFLOW – because there are too
+	//                  many queued events (the fs.inotify.max_queued_events
+	//                  sysctl can be used to increase this).
+	//  - windows:      The buffer size is too small; WithBufferSize() can be used to increase it.
+	//  - kqueue, fen:  Not used.
+	ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
+
+	// ErrUnsupported is returned by AddWith() when WithOps() specified an
+	// Unportable event that's not supported on this platform.
+	xErrUnsupported = errors.New("fsnotify: not supported with this backend")
 )
 
-func (op Op) String() string {
+// NewWatcher creates a new Watcher.
+func NewWatcher() (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBackend(ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
+// channel.
+//
+// The main use case for this is situations with a very large number of events
+// where the kernel buffer size can't be increased (e.g. due to lack of
+// permissions). An unbuffered Watcher will perform better for almost all use
+// cases, and whenever possible you will be better off increasing the kernel
+// buffers instead of adding a large userspace buffer.
+func NewBufferedWatcher(sz uint) (*Watcher, error) {
+	ev, errs := make(chan Event), make(chan error)
+	b, err := newBufferedBackend(sz, ev, errs)
+	if err != nil {
+		return nil, err
+	}
+	return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// Add starts monitoring the path for changes.
+//
+// A path can only be watched once; watching it more than once is a no-op and will
+// not return an error. Paths that do not yet exist on the filesystem cannot be
+// watched.
+//
+// A watch will be automatically removed if the watched path is deleted or
+// renamed. The exception is the Windows backend, which doesn't remove the
+// watcher on renames.
+//
+// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
+// filesystems (/proc, /sys, etc.) generally don't work.
+//
+// Returns [ErrClosed] if [Watcher.Close] was called.
+//
+// See [Watcher.AddWith] for a version that allows adding options.
+//
+// # Watching directories
+//
+// All files in a directory are monitored, including new files that are created
+// after the watcher is started. Subdirectories are not watched (i.e. it's
+// non-recursive).
+//
+// # Watching files
+//
+// Watching individual files (rather than directories) is generally not
+// recommended as many programs (especially editors) update files atomically: it
+// will write to a temporary file which is then moved to destination,
+// overwriting the original (or some variant thereof). The watcher on the
+// original file is now lost, as that no longer exists.
+//
+// The upshot of this is that a power failure or crash won't leave a
+// half-written file.
+//
+// Watch the parent directory and use Event.Name to filter out files you're not
+// interested in. There is an example of this in cmd/fsnotify/file.go.
+func (w *Watcher) Add(path string) error { return w.b.Add(path) }
+
+// AddWith is like [Watcher.Add], but allows adding options. When using Add()
+// the defaults described below are used.
+//
+// Possible options are:
+//
+//   - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
+//     other platforms. The default is 64K (65536 bytes).
+func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) }
+
+// Remove stops monitoring the path for changes.
+//
+// Directories are always removed non-recursively. For example, if you added
+// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
+//
+// Removing a path that has not yet been added returns [ErrNonExistentWatch].
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) Remove(path string) error { return w.b.Remove(path) }
+
+// Close removes all watches and closes the Events channel.
+func (w *Watcher) Close() error { return w.b.Close() }
+
+// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
+// yet removed).
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) WatchList() []string { return w.b.WatchList() }
+
+// Supports reports if all the listed operations are supported by this platform.
+//
+// Create, Write, Remove, Rename, and Chmod are always supported. It can only
+// return false for an Op starting with Unportable.
+func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) }
+
+func (o Op) String() string {
 	var b strings.Builder
-	if op.Has(Create) {
+	if o.Has(Create) {
 		b.WriteString("|CREATE")
 	}
-	if op.Has(Remove) {
+	if o.Has(Remove) {
 		b.WriteString("|REMOVE")
 	}
-	if op.Has(Write) {
+	if o.Has(Write) {
 		b.WriteString("|WRITE")
 	}
-	if op.Has(Rename) {
+	if o.Has(xUnportableOpen) {
+		b.WriteString("|OPEN")
+	}
+	if o.Has(xUnportableRead) {
+		b.WriteString("|READ")
+	}
+	if o.Has(xUnportableCloseWrite) {
+		b.WriteString("|CLOSE_WRITE")
+	}
+	if o.Has(xUnportableCloseRead) {
+		b.WriteString("|CLOSE_READ")
+	}
+	if o.Has(Rename) {
 		b.WriteString("|RENAME")
 	}
-	if op.Has(Chmod) {
+	if o.Has(Chmod) {
 		b.WriteString("|CHMOD")
 	}
 	if b.Len() == 0 {
@@ -70,12 +382,113 @@ func (op Op) String() string {
 }
 
 // Has reports if this operation has the given operation.
-func (o Op) Has(h Op) bool { return o&h == h }
+func (o Op) Has(h Op) bool { return o&h != 0 }
 
 // Has reports if this event has the given operation.
 func (e Event) Has(op Op) bool { return e.Op.Has(op) }
 
 // String returns a string representation of the event with their path.
 func (e Event) String() string {
+	if e.renamedFrom != "" {
+		return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom)
+	}
 	return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
 }
+
+type (
+	backend interface {
+		Add(string) error
+		AddWith(string, ...addOpt) error
+		Remove(string) error
+		WatchList() []string
+		Close() error
+		xSupports(Op) bool
+	}
+	addOpt   func(opt *withOpts)
+	withOpts struct {
+		bufsize    int
+		op         Op
+		noFollow   bool
+		sendCreate bool
+	}
+)
+
+var debug = func() bool {
+	// Check for exactly "1" (rather than mere existence) so we can add
+	// options/flags in the future. I don't know if we ever want that, but it's
+	// nice to leave the option open.
+	return os.Getenv("FSNOTIFY_DEBUG") == "1"
+}()
+
+var defaultOpts = withOpts{
+	bufsize: 65536, // 64K
+	op:      Create | Write | Remove | Rename | Chmod,
+}
+
+func getOptions(opts ...addOpt) withOpts {
+	with := defaultOpts
+	for _, o := range opts {
+		if o != nil {
+			o(&with)
+		}
+	}
+	return with
+}
+
+// WithBufferSize sets the [ReadDirectoryChangesW] buffer size.
+//
+// This only has effect on Windows systems, and is a no-op for other backends.
+//
+// The default value is 64K (65536 bytes) which is the highest value that works
+// on all filesystems and should be enough for most applications, but if you
+// have a large burst of events it may not be enough. You can increase it if
+// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]).
+//
+// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
+func WithBufferSize(bytes int) addOpt {
+	return func(opt *withOpts) { opt.bufsize = bytes }
+}
+
+// WithOps sets which operations to listen for. The default is [Create],
+// [Write], [Remove], [Rename], and [Chmod].
+//
+// Excluding operations you're not interested in can save quite a bit of CPU
+// time; in some use cases there may be hundreds of thousands of useless Write
+// or Chmod operations per second.
+//
+// This can also be used to add unportable operations not supported by all
+// platforms; unportable operations all start with "Unportable":
+// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and
+// [UnportableCloseRead].
+//
+// AddWith returns an error when using an unportable operation that's not
+// supported. Use [Watcher.Support] to check for support.
+func withOps(op Op) addOpt {
+	return func(opt *withOpts) { opt.op = op }
+}
+
+// WithNoFollow disables following symlinks, so the symlinks themselves are
+// watched.
+func withNoFollow() addOpt {
+	return func(opt *withOpts) { opt.noFollow = true }
+}
+
+// "Internal" option for recursive watches on inotify.
+func withCreate() addOpt {
+	return func(opt *withOpts) { opt.sendCreate = true }
+}
+
+var enableRecurse = false
+
+// Check if this path is recursive (ends with "/..." or "\..."), and return the
+// path with the /... stripped.
+func recursivePath(path string) (string, bool) {
+	path = filepath.Clean(path)
+	if !enableRecurse { // Only enabled in tests for now.
+		return path, false
+	}
+	if filepath.Base(path) == "..." {
+		return filepath.Dir(path), true
+	}
+	return path, false
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
new file mode 100644
index 00000000..b0eab100
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
@@ -0,0 +1,39 @@
+//go:build darwin
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+func SetRlimit() {
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = l.Cur
+
+	if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+
+	if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles {
+		maxfiles = uint64(n)
+	}
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
new file mode 100644
index 00000000..928319fb
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
@@ -0,0 +1,57 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_BACKGROUND", unix.NOTE_BACKGROUND},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CRITICAL", unix.NOTE_CRITICAL},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS},
+	{"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR},
+	{"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL},
+	{"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL},
+	{"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK},
+	{"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY},
+	{"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_FUNLOCK", unix.NOTE_FUNLOCK},
+	{"NOTE_LEEWAY", unix.NOTE_LEEWAY},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MACHTIME", unix.NOTE_MACHTIME},
+	{"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME},
+	{"NOTE_NONE", unix.NOTE_NONE},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	//{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!)
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_REAP", unix.NOTE_REAP},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_SIGNAL", unix.NOTE_SIGNAL},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_VM_ERROR", unix.NOTE_VM_ERROR},
+	{"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE},
+	{"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE},
+	{"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
new file mode 100644
index 00000000..3186b0c3
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
@@ -0,0 +1,33 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_OOB", unix.NOTE_OOB},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
new file mode 100644
index 00000000..f69fdb93
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
@@ -0,0 +1,42 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ABSTIME", unix.NOTE_ABSTIME},
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_CLOSE", unix.NOTE_CLOSE},
+	{"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FFAND", unix.NOTE_FFAND},
+	{"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+	{"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+	{"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+	{"NOTE_FFNOP", unix.NOTE_FFNOP},
+	{"NOTE_FFOR", unix.NOTE_FFOR},
+	{"NOTE_FILE_POLL", unix.NOTE_FILE_POLL},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_MSECONDS", unix.NOTE_MSECONDS},
+	{"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+	{"NOTE_OPEN", unix.NOTE_OPEN},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_READ", unix.NOTE_READ},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_SECONDS", unix.NOTE_SECONDS},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+	{"NOTE_USECONDS", unix.NOTE_USECONDS},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
new file mode 100644
index 00000000..607e683b
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
@@ -0,0 +1,32 @@
+//go:build freebsd || openbsd || netbsd || dragonfly || darwin
+
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, kevent *unix.Kevent_t) {
+	mask := uint32(kevent.Fflags)
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-60s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
new file mode 100644
index 00000000..35c734be
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
@@ -0,0 +1,56 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask, cookie uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"IN_ACCESS", unix.IN_ACCESS},
+		{"IN_ATTRIB", unix.IN_ATTRIB},
+		{"IN_CLOSE", unix.IN_CLOSE},
+		{"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE},
+		{"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE},
+		{"IN_CREATE", unix.IN_CREATE},
+		{"IN_DELETE", unix.IN_DELETE},
+		{"IN_DELETE_SELF", unix.IN_DELETE_SELF},
+		{"IN_IGNORED", unix.IN_IGNORED},
+		{"IN_ISDIR", unix.IN_ISDIR},
+		{"IN_MODIFY", unix.IN_MODIFY},
+		{"IN_MOVE", unix.IN_MOVE},
+		{"IN_MOVED_FROM", unix.IN_MOVED_FROM},
+		{"IN_MOVED_TO", unix.IN_MOVED_TO},
+		{"IN_MOVE_SELF", unix.IN_MOVE_SELF},
+		{"IN_OPEN", unix.IN_OPEN},
+		{"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW},
+		{"IN_UNMOUNT", unix.IN_UNMOUNT},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	var c string
+	if cookie > 0 {
+		c = fmt.Sprintf("(cookie: %d) ", cookie)
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-30s → %s%q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name)
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
new file mode 100644
index 00000000..e5b3b6f6
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
@@ -0,0 +1,25 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
new file mode 100644
index 00000000..1dd455bc
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
@@ -0,0 +1,28 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+	n string
+	m uint32
+}{
+	{"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+	// {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386?
+	{"NOTE_CHILD", unix.NOTE_CHILD},
+	{"NOTE_DELETE", unix.NOTE_DELETE},
+	{"NOTE_EOF", unix.NOTE_EOF},
+	{"NOTE_EXEC", unix.NOTE_EXEC},
+	{"NOTE_EXIT", unix.NOTE_EXIT},
+	{"NOTE_EXTEND", unix.NOTE_EXTEND},
+	{"NOTE_FORK", unix.NOTE_FORK},
+	{"NOTE_LINK", unix.NOTE_LINK},
+	{"NOTE_LOWAT", unix.NOTE_LOWAT},
+	{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+	{"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+	{"NOTE_RENAME", unix.NOTE_RENAME},
+	{"NOTE_REVOKE", unix.NOTE_REVOKE},
+	{"NOTE_TRACK", unix.NOTE_TRACK},
+	{"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+	{"NOTE_TRUNCATE", unix.NOTE_TRUNCATE},
+	{"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
new file mode 100644
index 00000000..f1b2e73b
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask int32) {
+	names := []struct {
+		n string
+		m int32
+	}{
+		{"FILE_ACCESS", unix.FILE_ACCESS},
+		{"FILE_MODIFIED", unix.FILE_MODIFIED},
+		{"FILE_ATTRIB", unix.FILE_ATTRIB},
+		{"FILE_TRUNC", unix.FILE_TRUNC},
+		{"FILE_NOFOLLOW", unix.FILE_NOFOLLOW},
+		{"FILE_DELETE", unix.FILE_DELETE},
+		{"FILE_RENAME_TO", unix.FILE_RENAME_TO},
+		{"FILE_RENAME_FROM", unix.FILE_RENAME_FROM},
+		{"UNMOUNTED", unix.UNMOUNTED},
+		{"MOUNTEDOVER", unix.MOUNTEDOVER},
+		{"FILE_EXCEPTION", unix.FILE_EXCEPTION},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %10d:%-30s → %q\n",
+		time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
new file mode 100644
index 00000000..52bf4ce5
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
@@ -0,0 +1,40 @@
+package internal
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"golang.org/x/sys/windows"
+)
+
+func Debug(name string, mask uint32) {
+	names := []struct {
+		n string
+		m uint32
+	}{
+		{"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED},
+		{"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED},
+		{"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED},
+		{"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME},
+		{"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME},
+	}
+
+	var (
+		l       []string
+		unknown = mask
+	)
+	for _, n := range names {
+		if mask&n.m == n.m {
+			l = append(l, n.n)
+			unknown ^= n.m
+		}
+	}
+	if unknown > 0 {
+		l = append(l, fmt.Sprintf("0x%x", unknown))
+	}
+	fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s  %-65s → %q\n",
+		time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name))
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
new file mode 100644
index 00000000..547df1df
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
@@ -0,0 +1,31 @@
+//go:build freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) }
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go
new file mode 100644
index 00000000..7daa45e1
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/internal.go
@@ -0,0 +1,2 @@
+// Package internal contains some helpers.
+package internal
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go
new file mode 100644
index 00000000..30976ce9
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix.go
@@ -0,0 +1,31 @@
+//go:build !windows && !darwin && !freebsd
+
+package internal
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var (
+	SyscallEACCES = syscall.EACCES
+	UnixEACCES    = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+	// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+	var l syscall.Rlimit
+	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+	if err == nil && l.Cur != l.Max {
+		l.Cur = l.Max
+		syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+	}
+	maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64                              { return maxfiles }
+func Mkfifo(path string, mode uint32) error         { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
new file mode 100644
index 00000000..37dfeddc
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
@@ -0,0 +1,7 @@
+//go:build !windows
+
+package internal
+
+func HasPrivilegesForSymlink() bool {
+	return true
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/public-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go
new file mode 100644
index 00000000..a72c6495
--- /dev/null
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/internal/windows.go
@@ -0,0 +1,41 @@
+//go:build windows
+
+package internal
+
+import (
+	"errors"
+
+	"golang.org/x/sys/windows"
+)
+
+// Just a dummy.
+var (
+	SyscallEACCES = errors.New("dummy")
+	UnixEACCES    = errors.New("dummy")
+)
+
+func SetRlimit()                                    {}
+func Maxfiles() uint64                              { return 1<<64 - 1 }
+func Mkfifo(path string, mode uint32) error         { return errors.New("no FIFOs on Windows") }
+func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") }
+
+func HasPrivilegesForSymlink() bool {
+	var sid *windows.SID
+	err := windows.AllocateAndInitializeSid(
+		&windows.SECURITY_NT_AUTHORITY,
+		2,
+		windows.SECURITY_BUILTIN_DOMAIN_RID,
+		windows.DOMAIN_ALIAS_RID_ADMINS,
+		0, 0, 0, 0, 0, 0,
+		&sid)
+	if err != nil {
+		return false
+	}
+	defer windows.FreeSid(sid)
+	token := windows.Token(0)
+	member, err := token.IsMember(sid)
+	if err != nil {
+		return false
+	}
+	return member || token.IsElevated()
+}
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/public-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
deleted file mode 100644
index b09ef768..00000000
--- a/public-api/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env zsh
-[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1
-setopt err_exit no_unset pipefail extended_glob
-
-# Simple script to update the godoc comments on all watchers. Probably took me
-# more time to write this than doing it manually, but ah well 🙃
-
-watcher=$(</tmp/x
-		print -r -- $cmt                >>/tmp/x
-		tail -n+$(( end + 1 ))   $file  >>/tmp/x
-		mv /tmp/x $file
-	done
-}
-
-set-cmt '^type Watcher struct '             $watcher
-set-cmt '^func NewWatcher('                 $new
-set-cmt '^func (w \*Watcher) Add('          $add
-set-cmt '^func (w \*Watcher) Remove('       $remove
-set-cmt '^func (w \*Watcher) Close('        $close
-set-cmt '^func (w \*Watcher) WatchList('    $watchlist
-set-cmt '^[[:space:]]*Events *chan Event$'  $events
-set-cmt '^[[:space:]]*Errors *chan error$'  $errors
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/public-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
index 4322b0b8..f65e8fe3 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/system_bsd.go
@@ -1,5 +1,4 @@
 //go:build freebsd || openbsd || netbsd || dragonfly
-// +build freebsd openbsd netbsd dragonfly
 
 package fsnotify
 
diff --git a/public-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/public-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
index 5da5ffa7..a29fc7aa 100644
--- a/public-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
+++ b/public-api/vendor/github.com/fsnotify/fsnotify/system_darwin.go
@@ -1,5 +1,4 @@
 //go:build darwin
-// +build darwin
 
 package fsnotify
 
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig b/public-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
index 1f664d13..faef0c91 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/.editorconfig
@@ -16,3 +16,6 @@ indent_style = tab
 
 [*.nix]
 indent_size = 2
+
+[.golangci.yaml]
+indent_size = 2
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/public-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
index 763143aa..bda96256 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml
@@ -1,23 +1,48 @@
-run:
-  timeout: 5m
+version: "2"
 
-linters-settings:
-  gci:
-    sections:
-      - standard
-      - default
-      - prefix(github.com/go-viper/mapstructure)
-  golint:
-    min-confidence: 0
-  goimports:
-    local-prefixes: github.com/go-viper/maptstructure
+run:
+  timeout: 10m
 
 linters:
-  disable-all: true
+  enable:
+    - govet
+    - ineffassign
+    # - misspell
+    - nolintlint
+    # - revive
+
+  disable:
+    - errcheck
+    - staticcheck
+    - unused
+
+  settings:
+    misspell:
+      locale: US
+    nolintlint:
+      allow-unused: false # report any unused nolint directives
+      require-specific: false # don't require nolint directives to be specific about which linter is being skipped
+
+formatters:
   enable:
     - gci
     - gofmt
     - gofumpt
     - goimports
-    - staticcheck
-    # - stylecheck
+    # - golines
+
+  settings:
+    gci:
+      sections:
+        - standard
+        - default
+        - localmodule
+    gofmt:
+      simplify: true
+      rewrite-rules:
+        - pattern: interface{}
+          replacement: any
+
+  exclusions:
+    paths:
+      - internal/
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/README.md b/public-api/vendor/github.com/go-viper/mapstructure/v2/README.md
index dd5ec69d..45db7197 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/README.md
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/README.md
@@ -1,8 +1,9 @@
 # mapstructure
 
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
 [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square)
+![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)
 
 mapstructure is a Go library for decoding generic map values to structures
 and vice versa, while providing helpful error handling.
@@ -29,7 +30,7 @@ The API is the same, so you don't need to change anything else.
 Here is a script that can help you with the migration:
 
 ```shell
-sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go')
+sed -i 's|github.com/mitchellh/mapstructure|github.com/go-viper/mapstructure/v2|g' $(find . -type f -name '*.go')
 ```
 
 If you need more time to migrate your code, that is absolutely fine.
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/public-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
index 1f3c69d4..a852a0a0 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go
@@ -13,7 +13,7 @@ import (
 	"time"
 )
 
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// typedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
 func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	// Create variables here so we can reference them with the reflect pkg
@@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 
 	// Fill in the variables into this interface and the rest is done
 	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
+	potential := []any{f1, f2, f3}
 
 	v := reflect.ValueOf(h)
 	vt := v.Type()
@@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 	return nil
 }
 
-// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
+// cachedDecodeHook takes a raw DecodeHookFunc (an any) and turns
 // it into a closure to be used directly
 // if the type fails to convert we return a closure always erroring to keep the previous behaviour
-func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) {
+func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Type(), to.Type(), from.Interface())
 		}
 	case DecodeHookFuncKind:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from.Kind(), to.Kind(), from.Interface())
 		}
 	case DecodeHookFuncValue:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return f(from, to)
 		}
 	default:
-		return func(from reflect.Value, to reflect.Value) (interface{}, error) {
+		return func(from reflect.Value, to reflect.Value) (any, error) {
 			return nil, errors.New("invalid decode hook signature")
 		}
 	}
@@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
 func DecodeHookExec(
 	raw DecodeHookFunc,
 	from reflect.Value, to reflect.Value,
-) (interface{}, error) {
+) (any, error) {
 	switch f := typedDecodeHook(raw).(type) {
 	case DecodeHookFuncType:
 		return f(from.Type(), to.Type(), from.Interface())
@@ -86,11 +86,11 @@ func DecodeHookExec(
 // The composed funcs are called in order, with the result of the
 // previous transformation.
 func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(fs))
 	for _, f := range fs {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		var err error
 		data := f.Interface()
 
@@ -100,7 +100,11 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 			if err != nil {
 				return nil, err
 			}
-			newFrom = reflect.ValueOf(data)
+			if v, ok := data.(reflect.Value); ok {
+				newFrom = v
+			} else {
+				newFrom = reflect.ValueOf(data)
+			}
 		}
 
 		return data, nil
@@ -110,13 +114,13 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 // OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
 // If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
 func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
+	cached := make([]func(from reflect.Value, to reflect.Value) (any, error), 0, len(ff))
 	for _, f := range ff {
 		cached = append(cached, cachedDecodeHook(f))
 	}
-	return func(a, b reflect.Value) (interface{}, error) {
+	return func(a, b reflect.Value) (any, error) {
 		var allErrs string
-		var out interface{}
+		var out any
 		var err error
 
 		for _, c := range cached {
@@ -139,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -157,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 	}
 }
 
+// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
+//
+// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
+// This function removes that check.
+func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
 // StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
 // strings to time.Duration.
 func StringToTimeDurationHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -173,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.ParseDuration(data.(string))
+		d, err := time.ParseDuration(data.(string))
+
+		return d, wrapTimeParseDurationError(err)
+	}
+}
+
+// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
+// strings to *time.Location.
+func StringToTimeLocationHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(time.Local) {
+			return data, nil
+		}
+		d, err := time.LoadLocation(data.(string))
+
+		return d, wrapTimeParseLocationError(err)
 	}
 }
 
@@ -183,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -193,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return url.Parse(data.(string))
+		u, err := url.Parse(data.(string))
+
+		return u, wrapUrlError(err)
 	}
 }
 
@@ -203,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -215,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc {
 		// Convert it by parsing
 		ip := net.ParseIP(data.(string))
 		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
+			return net.IP{}, fmt.Errorf("failed parsing ip")
 		}
 
 		return ip, nil
@@ -228,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -239,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc {
 
 		// Convert it by parsing
 		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
+		return net, wrapNetParseError(err)
 	}
 }
 
@@ -249,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -259,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return time.Parse(layout, data.(string))
+		ti, err := time.Parse(layout, data.(string))
+
+		return ti, wrapTimeParseError(err)
 	}
 }
 
@@ -271,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
 func WeaklyTypedHook(
 	f reflect.Kind,
 	t reflect.Kind,
-	data interface{},
-) (interface{}, error) {
+	data any,
+) (any, error) {
 	dataVal := reflect.ValueOf(data)
 	switch t {
 	case reflect.String:
@@ -301,17 +354,17 @@ func WeaklyTypedHook(
 }
 
 func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
+	return func(f reflect.Value, t reflect.Value) (any, error) {
 		if f.Kind() != reflect.Struct {
 			return f.Interface(), nil
 		}
 
-		var i interface{} = struct{}{}
+		var i any = struct{}{}
 		if t.Type() != reflect.TypeOf(&i).Elem() {
 			return f.Interface(), nil
 		}
 
-		m := make(map[string]interface{})
+		m := make(map[string]any)
 		t.Set(reflect.ValueOf(m))
 
 		return f.Interface(), nil
@@ -325,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -352,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -362,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddr(data.(string))
+		addr, err := netip.ParseAddr(data.(string))
+
+		return addr, wrapNetIPParseAddrError(err)
 	}
 }
 
@@ -372,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 	return func(
 		f reflect.Type,
 		t reflect.Type,
-		data interface{},
-	) (interface{}, error) {
+		data any,
+	) (any, error) {
 		if f.Kind() != reflect.String {
 			return data, nil
 		}
@@ -382,7 +437,31 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
 		}
 
 		// Convert it by parsing
-		return netip.ParseAddrPort(data.(string))
+		addrPort, err := netip.ParseAddrPort(data.(string))
+
+		return addrPort, wrapNetIPParseAddrPortError(err)
+	}
+}
+
+// StringToNetIPPrefixHookFunc returns a DecodeHookFunc that converts
+// strings to netip.Prefix.
+func StringToNetIPPrefixHookFunc() DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data any,
+	) (any, error) {
+		if f.Kind() != reflect.String {
+			return data, nil
+		}
+		if t != reflect.TypeOf(netip.Prefix{}) {
+			return data, nil
+		}
+
+		// Convert it by parsing
+		prefix, err := netip.ParsePrefix(data.(string))
+
+		return prefix, wrapNetIPParsePrefixError(err)
 	}
 }
 
@@ -415,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc {
 // StringToInt8HookFunc returns a DecodeHookFunc that converts
 // strings to int8.
 func StringToInt8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 8)
-		return int8(i64), err
+		return int8(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint8HookFunc returns a DecodeHookFunc that converts
 // strings to uint8.
 func StringToUint8HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 8)
-		return uint8(u64), err
+		return uint8(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt16HookFunc returns a DecodeHookFunc that converts
 // strings to int16.
 func StringToInt16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 16)
-		return int16(i64), err
+		return int16(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint16HookFunc returns a DecodeHookFunc that converts
 // strings to uint16.
 func StringToUint16HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 16)
-		return uint16(u64), err
+		return uint16(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt32HookFunc returns a DecodeHookFunc that converts
 // strings to int32.
 func StringToInt32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 32)
-		return int32(i64), err
+		return int32(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint32HookFunc returns a DecodeHookFunc that converts
 // strings to uint32.
 func StringToUint32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 32)
-		return uint32(u64), err
+		return uint32(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToInt64HookFunc returns a DecodeHookFunc that converts
 // strings to int64.
 func StringToInt64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseInt(data.(string), 0, 64)
+		i64, err := strconv.ParseInt(data.(string), 0, 64)
+		return int64(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUint64HookFunc returns a DecodeHookFunc that converts
 // strings to uint64.
 func StringToUint64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseUint(data.(string), 0, 64)
+		u64, err := strconv.ParseUint(data.(string), 0, 64)
+		return uint64(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToIntHookFunc returns a DecodeHookFunc that converts
 // strings to int.
 func StringToIntHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Int {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		i64, err := strconv.ParseInt(data.(string), 0, 0)
-		return int(i64), err
+		return int(i64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToUintHookFunc returns a DecodeHookFunc that converts
 // strings to uint.
 func StringToUintHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		u64, err := strconv.ParseUint(data.(string), 0, 0)
-		return uint(u64), err
+		return uint(u64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat32HookFunc returns a DecodeHookFunc that converts
 // strings to float32.
 func StringToFloat32HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		f64, err := strconv.ParseFloat(data.(string), 32)
-		return float32(f64), err
+		return float32(f64), wrapStrconvNumError(err)
 	}
 }
 
 // StringToFloat64HookFunc returns a DecodeHookFunc that converts
 // strings to float64.
 func StringToFloat64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseFloat(data.(string), 64)
+		f64, err := strconv.ParseFloat(data.(string), 64)
+		return f64, wrapStrconvNumError(err)
 	}
 }
 
 // StringToBoolHookFunc returns a DecodeHookFunc that converts
 // strings to bool.
 func StringToBoolHookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseBool(data.(string))
+		b, err := strconv.ParseBool(data.(string))
+		return b, wrapStrconvNumError(err)
 	}
 }
 
@@ -605,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc {
 // StringToComplex64HookFunc returns a DecodeHookFunc that converts
 // strings to complex64.
 func StringToComplex64HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
 			return data, nil
 		}
 
 		// Convert it by parsing
 		c128, err := strconv.ParseComplex(data.(string), 64)
-		return complex64(c128), err
+		return complex64(c128), wrapStrconvNumError(err)
 	}
 }
 
 // StringToComplex128HookFunc returns a DecodeHookFunc that converts
 // strings to complex128.
 func StringToComplex128HookFunc() DecodeHookFunc {
-	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
+	return func(f reflect.Type, t reflect.Type, data any) (any, error) {
 		if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
 			return data, nil
 		}
 
 		// Convert it by parsing
-		return strconv.ParseComplex(data.(string), 128)
+		c128, err := strconv.ParseComplex(data.(string), 128)
+		return c128, wrapStrconvNumError(err)
 	}
 }
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/errors.go b/public-api/vendor/github.com/go-viper/mapstructure/v2/errors.go
new file mode 100644
index 00000000..07d31c22
--- /dev/null
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/errors.go
@@ -0,0 +1,244 @@
+package mapstructure
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// Error interface is implemented by all errors emitted by mapstructure.
+//
+// Use [errors.As] to check if an error implements this interface.
+type Error interface {
+	error
+
+	mapstructure()
+}
+
+// DecodeError is a generic error type that holds information about
+// a decoding error together with the name of the field that caused the error.
+type DecodeError struct {
+	name string
+	err  error
+}
+
+func newDecodeError(name string, err error) *DecodeError {
+	return &DecodeError{
+		name: name,
+		err:  err,
+	}
+}
+
+func (e *DecodeError) Name() string {
+	return e.name
+}
+
+func (e *DecodeError) Unwrap() error {
+	return e.err
+}
+
+func (e *DecodeError) Error() string {
+	return fmt.Sprintf("'%s' %s", e.name, e.err)
+}
+
+func (*DecodeError) mapstructure() {}
+
+// ParseError is an error type that indicates a value could not be parsed
+// into the expected type.
+type ParseError struct {
+	Expected reflect.Value
+	Value    any
+	Err      error
+}
+
+func (e *ParseError) Error() string {
+	return fmt.Sprintf("cannot parse value as '%s': %s", e.Expected.Type(), e.Err)
+}
+
+func (*ParseError) mapstructure() {}
+
+// UnconvertibleTypeError is an error type that indicates a value could not be
+// converted to the expected type.
+type UnconvertibleTypeError struct {
+	Expected reflect.Value
+	Value    any
+}
+
+func (e *UnconvertibleTypeError) Error() string {
+	return fmt.Sprintf(
+		"expected type '%s', got unconvertible type '%s'",
+		e.Expected.Type(),
+		reflect.TypeOf(e.Value),
+	)
+}
+
+func (*UnconvertibleTypeError) mapstructure() {}
+
+func wrapStrconvNumError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*strconv.NumError); ok {
+		return &strconvNumError{Err: err}
+	}
+
+	return err
+}
+
+type strconvNumError struct {
+	Err *strconv.NumError
+}
+
+func (e *strconvNumError) Error() string {
+	return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
+}
+
+func (e *strconvNumError) Unwrap() error { return e.Err }
+
+func wrapUrlError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*url.Error); ok {
+		return &urlError{Err: err}
+	}
+
+	return err
+}
+
+type urlError struct {
+	Err *url.Error
+}
+
+func (e *urlError) Error() string {
+	return fmt.Sprintf("%s", e.Err.Err)
+}
+
+func (e *urlError) Unwrap() error { return e.Err }
+
+func wrapNetParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*net.ParseError); ok {
+		return &netParseError{Err: err}
+	}
+
+	return err
+}
+
+type netParseError struct {
+	Err *net.ParseError
+}
+
+func (e *netParseError) Error() string {
+	return "invalid " + e.Err.Type
+}
+
+func (e *netParseError) Unwrap() error { return e.Err }
+
+func wrapTimeParseError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if err, ok := err.(*time.ParseError); ok {
+		return &timeParseError{Err: err}
+	}
+
+	return err
+}
+
+type timeParseError struct {
+	Err *time.ParseError
+}
+
+func (e *timeParseError) Error() string {
+	if e.Err.Message == "" {
+		return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
+	}
+
+	return "parsing time " + e.Err.Message
+}
+
+func (e *timeParseError) Unwrap() error { return e.Err }
+
+func wrapNetIPParseAddrError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapNetIPParseAddrPortError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "invalid port ") {
+		return errors.New("invalid port")
+	} else if strings.HasPrefix(errMsg, "invalid ip:port ") {
+		return errors.New("invalid ip:port")
+	}
+
+	return err
+}
+
+func wrapNetIPParsePrefixError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
+		errPieces := strings.Split(errMsg, ": ")
+
+		return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
+	}
+
+	return err
+}
+
+func wrapTimeParseDurationError(err error) error {
+	if err == nil {
+		return nil
+	}
+
+	errMsg := err.Error()
+	if strings.HasPrefix(errMsg, "time: unknown unit ") {
+		return errors.New("time: unknown unit")
+	} else if strings.HasPrefix(errMsg, "time: ") {
+		idx := strings.LastIndex(errMsg, " ")
+
+		return errors.New(errMsg[:idx])
+	}
+
+	return err
+}
+
+func wrapTimeParseLocationError(err error) error {
+	if err == nil {
+		return nil
+	}
+	errMsg := err.Error()
+	if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
+		return fmt.Errorf("invalid time zone format: %w", err)
+	}
+
+	return err
+}
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
index 4bea8154..5e67bdd6 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.lock
@@ -2,30 +2,28 @@
   "nodes": {
     "cachix": {
       "inputs": {
-        "devenv": "devenv_2",
+        "devenv": [
+          "devenv"
+        ],
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "git-hooks": [
+          "devenv"
         ],
-        "pre-commit-hooks": [
-          "devenv",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs"
       },
       "locked": {
-        "lastModified": 1712055811,
-        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "lastModified": 1742042642,
+        "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
         "owner": "cachix",
         "repo": "cachix",
-        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "latest",
         "repo": "cachix",
         "type": "github"
       }
@@ -33,52 +31,21 @@
     "devenv": {
       "inputs": {
         "cachix": "cachix",
-        "flake-compat": "flake-compat_2",
-        "nix": "nix_2",
-        "nixpkgs": "nixpkgs_2",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1717245169,
-        "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "devenv_2": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "cachix",
-          "flake-compat"
-        ],
+        "flake-compat": "flake-compat",
+        "git-hooks": "git-hooks",
         "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "poetry2nix": "poetry2nix",
-        "pre-commit-hooks": [
-          "devenv",
-          "cachix",
-          "pre-commit-hooks"
-        ]
+        "nixpkgs": "nixpkgs_3"
       },
       "locked": {
-        "lastModified": 1708704632,
-        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
+        "lastModified": 1744876578,
+        "narHash": "sha256-8MTBj2REB8t29sIBLpxbR0+AEGJ7f+RkzZPAGsFd40c=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
+        "rev": "7ff7c351bba20d0615be25ecdcbcf79b57b85fe1",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
-        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -86,27 +53,11 @@
     "flake-compat": {
       "flake": false,
       "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-compat_2": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "lastModified": 1733328505,
+        "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
         "owner": "edolstra",
         "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
         "type": "github"
       },
       "original": {
@@ -117,14 +68,18 @@
     },
     "flake-parts": {
       "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
+        "nixpkgs-lib": [
+          "devenv",
+          "nix",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1717285511,
-        "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
+        "lastModified": 1712014858,
+        "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
+        "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
         "type": "github"
       },
       "original": {
@@ -133,39 +88,46 @@
         "type": "github"
       }
     },
-    "flake-utils": {
+    "flake-parts_2": {
       "inputs": {
-        "systems": "systems"
+        "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1689068808,
-        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "lastModified": 1743550720,
+        "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "c621e8422220273271f52058f618c94e405bb0f5",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
         "type": "github"
       }
     },
-    "flake-utils_2": {
+    "git-hooks": {
       "inputs": {
-        "systems": "systems_2"
+        "flake-compat": [
+          "devenv"
+        ],
+        "gitignore": "gitignore",
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ]
       },
       "locked": {
-        "lastModified": 1710146030,
-        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "lastModified": 1742649964,
+        "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
         "type": "github"
       },
       "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
         "type": "github"
       }
     },
@@ -173,7 +135,7 @@
       "inputs": {
         "nixpkgs": [
           "devenv",
-          "pre-commit-hooks",
+          "git-hooks",
           "nixpkgs"
         ]
       },
@@ -191,166 +153,109 @@
         "type": "github"
       }
     },
-    "nix": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "devenv-2.21",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nix-github-actions": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "poetry2nix",
-          "nixpkgs"
-        ]
-      },
+    "libgit2": {
+      "flake": false,
       "locked": {
-        "lastModified": 1688870561,
-        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
-        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "lastModified": 1697646580,
+        "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
+        "owner": "libgit2",
+        "repo": "libgit2",
+        "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
         "type": "github"
       },
       "original": {
-        "owner": "nix-community",
-        "repo": "nix-github-actions",
+        "owner": "libgit2",
+        "repo": "libgit2",
         "type": "github"
       }
     },
-    "nix_2": {
+    "nix": {
       "inputs": {
         "flake-compat": [
-          "devenv",
-          "flake-compat"
+          "devenv"
         ],
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
+        "flake-parts": "flake-parts",
+        "libgit2": "libgit2",
+        "nixpkgs": "nixpkgs_2",
+        "nixpkgs-23-11": [
+          "devenv"
+        ],
+        "nixpkgs-regression": [
+          "devenv"
         ],
-        "nixpkgs-regression": "nixpkgs-regression_2"
+        "pre-commit-hooks": [
+          "devenv"
+        ]
       },
       "locked": {
-        "lastModified": 1712911606,
-        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "lastModified": 1741798497,
+        "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
+        "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "devenv-2.21",
+        "ref": "devenv-2.24",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1692808169,
-        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
+        "lastModified": 1733212471,
+        "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
+        "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
+        "ref": "nixos-unstable",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs-lib": {
       "locked": {
-        "lastModified": 1717284937,
-        "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      },
-      "original": {
-        "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression_2": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "lastModified": 1743296961,
+        "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
+        "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
         "type": "github"
       },
       "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "owner": "nix-community",
+        "repo": "nixpkgs.lib",
         "type": "github"
       }
     },
-    "nixpkgs-stable": {
+    "nixpkgs_2": {
       "locked": {
-        "lastModified": 1710695816,
-        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
+        "lastModified": 1717432640,
+        "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
+        "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.11",
+        "ref": "release-24.05",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
-    "nixpkgs_2": {
+    "nixpkgs_3": {
       "locked": {
-        "lastModified": 1713361204,
-        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "lastModified": 1733477122,
+        "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
         "owner": "cachix",
         "repo": "devenv-nixpkgs",
-        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
         "type": "github"
       },
       "original": {
@@ -360,13 +265,13 @@
         "type": "github"
       }
     },
-    "nixpkgs_3": {
+    "nixpkgs_4": {
       "locked": {
-        "lastModified": 1717112898,
-        "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=",
+        "lastModified": 1744536153,
+        "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0",
+        "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
         "type": "github"
       },
       "original": {
@@ -376,94 +281,11 @@
         "type": "github"
       }
     },
-    "poetry2nix": {
-      "inputs": {
-        "flake-utils": "flake-utils",
-        "nix-github-actions": "nix-github-actions",
-        "nixpkgs": [
-          "devenv",
-          "cachix",
-          "devenv",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1692876271,
-        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "poetry2nix",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils_2",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1713775815,
-        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
     "root": {
       "inputs": {
         "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_3"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
+        "flake-parts": "flake-parts_2",
+        "nixpkgs": "nixpkgs_4"
       }
     }
   },
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix b/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
index 4ed0f533..3b116f42 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/flake.nix
@@ -5,35 +5,42 @@
     devenv.url = "github:cachix/devenv";
   };
 
-  outputs = inputs@{ flake-parts, ... }:
+  outputs =
+    inputs@{ flake-parts, ... }:
     flake-parts.lib.mkFlake { inherit inputs; } {
       imports = [
         inputs.devenv.flakeModule
       ];
 
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
+      systems = [
+        "x86_64-linux"
+        "x86_64-darwin"
+        "aarch64-darwin"
+      ];
 
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-            };
+      perSystem =
+        { pkgs, ... }:
+        rec {
+          devenv.shells = {
+            default = {
+              languages = {
+                go.enable = true;
+              };
 
-            pre-commit.hooks = {
-              nixpkgs-fmt.enable = true;
-            };
+              pre-commit.hooks = {
+                nixpkgs-fmt.enable = true;
+              };
 
-            packages = with pkgs; [
-              golangci-lint
-            ];
+              packages = with pkgs; [
+                golangci-lint
+              ];
 
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
+              # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
+              containers = pkgs.lib.mkForce { };
+            };
 
-          ci = devenv.shells.default;
+            ci = devenv.shells.default;
+          };
         };
-      };
     };
 }
diff --git a/public-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/public-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
index e77e63ba..7c35bce0 100644
--- a/public-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
+++ b/public-api/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go
@@ -1,5 +1,5 @@
 // Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
+// Go type into another, typically to convert a map[string]any
 // into a native Go structure.
 //
 // The Go structure can be arbitrarily complex, containing slices,
@@ -54,8 +54,8 @@
 //
 // This would require an input that looks like below:
 //
-//	map[string]interface{}{
-//	    "person": map[string]interface{}{"name": "alice"},
+//	map[string]any{
+//	    "person": map[string]any{"name": "alice"},
 //	}
 //
 // If your "person" value is NOT nested, then you can append ",squash" to
@@ -68,7 +68,7 @@
 //
 // Now the following input would be accepted:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -79,7 +79,7 @@
 //
 // Will be decoded into a map:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name": "alice",
 //	}
 //
@@ -95,18 +95,18 @@
 //
 // You can also use the ",remain" suffix on your tag to collect all unused
 // values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
+// probably be a "map[string]any" or "map[any]any".
 // See example below:
 //
 //	type Friend struct {
 //	    Name  string
-//	    Other map[string]interface{} `mapstructure:",remain"`
+//	    Other map[string]any `mapstructure:",remain"`
 //	}
 //
 // Given the input below, Other would be populated with the other
 // values that weren't used (everything but "name"):
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "name":    "bob",
 //	    "address": "123 Maple St.",
 //	}
@@ -115,15 +115,36 @@
 //
 // When decoding from a struct to any other value, you may use the
 // ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
+// the zero value, or a zero-length element. The zero value of all types is
+// specified in the Go specification.
 //
 // For example, the zero type of a numeric type is zero ("0"). If the struct
 // field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil or empty, it won't be encoded into the destination type.
 //
 //	type Source struct {
-//	    Age int `mapstructure:",omitempty"`
+//	    Age  int      `mapstructure:",omitempty"`
+//	    URLs []string `mapstructure:",omitempty"`
+//	}
+//
+// # Omit Zero Values
+//
+// When decoding from a struct to any other value, you may use the
+// ",omitzero" suffix on your tag to omit that value if it equates to the zero
+// value. The zero value of all types is specified in the Go specification.
+//
+// For example, the zero type of a numeric type is zero ("0"). If the struct
+// field value is zero and a numeric type, the field is empty, and it won't
+// be encoded into the destination type. And likewise for the URLs field, if the
+// slice is nil, it won't be encoded into the destination type.
+//
+// Note that if the field is a slice, and it is empty but not nil, it will
+// still be encoded into the destination type.
+//
+//	type Source struct {
+//	    Age  int      `mapstructure:",omitzero"`
+//	    URLs []string `mapstructure:",omitzero"`
 //	}
 //
 // # Unexported fields
@@ -140,7 +161,7 @@
 //
 // Using this map as input:
 //
-//	map[string]interface{}{
+//	map[string]any{
 //	    "private": "I will be ignored",
 //	    "Public":  "I made it through!",
 //	}
@@ -183,19 +204,19 @@ import (
 // we started with Kinds and then realized Types were the better solution,
 // but have a promise to not break backwards compat so we now support
 // both.
-type DecodeHookFunc interface{}
+type DecodeHookFunc any
 
 // DecodeHookFuncType is a DecodeHookFunc which has complete information about
 // the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
+type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
 
 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
 // source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
+type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
 
 // DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
 // values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
+type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
 
 // DecoderConfig is the configuration that is used to create a new decoder
 // and allows customization of various aspects of decoding.
@@ -222,6 +243,12 @@ type DecoderConfig struct {
 	// will affect all nested structs as well.
 	ErrorUnset bool
 
+	// AllowUnsetPointer, if set to true, will prevent fields with pointer types
+	// from being reported as unset, even if ErrorUnset is true and the field was
+	// not present in the input data. This allows pointer fields to be optional
+	// without triggering an error when they are missing.
+	AllowUnsetPointer bool
+
 	// ZeroFields, if set to true, will zero fields before writing them.
 	// For example, a map will be emptied before decoded values are put in
 	// it. If this is false, a map will be merged.
@@ -260,7 +287,7 @@ type DecoderConfig struct {
 
 	// Result is a pointer to the struct that will contain the decoded
 	// value.
-	Result interface{}
+	Result any
 
 	// The tag name that mapstructure reads for field names. This
 	// defaults to "mapstructure"
@@ -292,7 +319,7 @@ type DecoderConfig struct {
 // up the most basic Decoder.
 type Decoder struct {
 	config           *DecoderConfig
-	cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
+	cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
 }
 
 // Metadata contains information about decoding a structure that
@@ -313,7 +340,7 @@ type Metadata struct {
 
 // Decode takes an input structure and uses reflection to translate it to
 // the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
+func Decode(input any, output any) error {
 	config := &DecoderConfig{
 		Metadata: nil,
 		Result:   output,
@@ -329,7 +356,7 @@ func Decode(input interface{}, output interface{}) error {
 
 // WeakDecode is the same as Decode but is shorthand to enable
 // WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
+func WeakDecode(input, output any) error {
 	config := &DecoderConfig{
 		Metadata:         nil,
 		Result:           output,
@@ -346,7 +373,7 @@ func WeakDecode(input, output interface{}) error {
 
 // DecodeMetadata is the same as Decode, but is shorthand to
 // enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func DecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata: metadata,
 		Result:   output,
@@ -363,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e
 // WeakDecodeMetadata is the same as Decode, but is shorthand to
 // enable both WeaklyTypedInput and metadata collection. See
 // DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
+func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
 	config := &DecoderConfig{
 		Metadata:         metadata,
 		Result:           output,
@@ -430,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
 
 // Decode decodes the given raw interface to the target pointer specified
 // by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
+func (d *Decoder) Decode(input any) error {
 	err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
 
 	// Retain some of the original behavior when multiple errors ocurr
@@ -443,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error {
 }
 
 // isNil returns true if the input is nil or a typed nil pointer.
-func isNil(input interface{}) bool {
+func isNil(input any) bool {
 	if input == nil {
 		return true
 	}
@@ -452,7 +479,7 @@ func isNil(input interface{}) bool {
 }
 
 // Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
+func (d *Decoder) decode(name string, input any, outVal reflect.Value) error {
 	var (
 		inputVal   = reflect.ValueOf(input)
 		outputKind = getKind(outVal)
@@ -489,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		// Hooks need a valid inputVal, so reset it to zero value of outVal type.
 		switch outputKind {
 		case reflect.Struct, reflect.Map:
-			var mapVal map[string]interface{}
+			var mapVal map[string]any
 			inputVal = reflect.ValueOf(mapVal) // create nil map pointer
 		case reflect.Slice, reflect.Array:
-			var sliceVal []interface{}
+			var sliceVal []any
 			inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
 		default:
 			inputVal = reflect.Zero(outVal.Type())
@@ -504,7 +531,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		var err error
 		input, err = d.cachedDecodeHook(inputVal, outVal)
 		if err != nil {
-			return fmt.Errorf("error decoding '%s': %w", name, err)
+			return newDecodeError(name, err)
 		}
 	}
 	if isNil(input) {
@@ -542,7 +569,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		err = d.decodeFunc(name, input, outVal)
 	default:
 		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
+		return newDecodeError(name, fmt.Errorf("unsupported type: %s", outputKind))
 	}
 
 	// If we reached here, then we successfully decoded SOMETHING, so
@@ -556,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 
 // This decodes a basic type (bool, int, string, etc.) and sets the
 // value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
 	if val.IsValid() && val.Elem().IsValid() {
 		elem := val.Elem()
 
@@ -603,16 +630,17 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value)
 
 	dataValType := dataVal.Type()
 	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -656,15 +684,16 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
 	}
 
 	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -692,26 +721,34 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
 		if err == nil {
 			val.SetInt(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Int64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetInt(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -720,8 +757,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Int:
 		i := dataVal.Int()
 		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%d overflows uint", i),
+			})
 		}
 		val.SetUint(uint64(i))
 	case dataKind == reflect.Uint:
@@ -729,8 +769,11 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 	case dataKind == reflect.Float32:
 		f := dataVal.Float()
 		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      fmt.Errorf("%f overflows uint", f),
+			})
 		}
 		val.SetUint(uint64(f))
 	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
@@ -749,26 +792,34 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		if err == nil {
 			val.SetUint(i)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := strconv.ParseUint(string(jn), 0, 64)
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 		val.SetUint(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -788,18 +839,23 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
 		} else if dataVal.String() == "" {
 			val.SetBool(false)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'",
-			name, val, dataVal, data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 	dataType := dataVal.Type()
@@ -827,26 +883,34 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
 		if err == nil {
 			val.SetFloat(f)
 		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      wrapStrconvNumError(err),
+			})
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
 		i, err := jn.Float64()
 		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
+			return newDecodeError(name, &ParseError{
+				Expected: val,
+				Value:    data,
+				Err:      err,
+			})
 		}
 		val.SetFloat(i)
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataKind := getKind(dataVal)
 
@@ -854,15 +918,16 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value
 	case dataKind == reflect.Complex64:
 		val.SetComplex(dataVal.Complex())
 	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 
 	return nil
 }
 
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
 	valType := val.Type()
 	valKeyType := valType.Key()
 	valElemType := valType.Elem()
@@ -900,7 +965,10 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
 		fallthrough
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 }
 
@@ -986,7 +1054,10 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 		// to the map value.
 		v := dataVal.Field(i)
 		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
+			return newDecodeError(
+				name+"."+f.Name,
+				fmt.Errorf("cannot assign type %q to map value field of type %q", v.Type(), valMap.Type().Elem()),
+			)
 		}
 
 		tagValue := f.Tag.Get(d.config.TagName)
@@ -1011,6 +1082,11 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 				continue
 			}
 
+			// If "omitzero" is specified in the tag, it ignores zero values.
+			if strings.Index(tagValue[index+1:], "omitzero") != -1 && v.IsZero() {
+				continue
+			}
+
 			// If "squash" is specified in the tag, we squash the field down.
 			squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
 			if squash {
@@ -1021,12 +1097,18 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 
 				// The final type must be a struct
 				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
+					return newDecodeError(
+						name+"."+f.Name,
+						fmt.Errorf("cannot squash non-struct type %q", v.Type()),
+					)
 				}
 			} else {
 				if strings.Index(tagValue[index+1:], "remain") != -1 {
 					if v.Kind() != reflect.Map {
-						return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type())
+						return newDecodeError(
+							name+"."+f.Name,
+							fmt.Errorf("error remain-tag field with invalid type: %q", v.Type()),
+						)
 					}
 
 					ptr := v.MapRange()
@@ -1094,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 	return nil
 }
 
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
+func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
 	// If the input data is nil, then we want to just set the output
 	// pointer to be nil as well.
 	isNil := data == nil
@@ -1141,20 +1223,21 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
 	return false, nil
 }
 
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeFunc(name string, data any, val reflect.Value) error {
 	// Create an element of the concrete (non pointer) type and decode
 	// into that. Then set the value of the pointer to this type.
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
+		return newDecodeError(name, &UnconvertibleTypeError{
+			Expected: val,
+			Value:    data,
+		})
 	}
 	val.Set(dataVal)
 	return nil
 }
 
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1176,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 					return nil
 				}
 				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 
 			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
 				return d.decodeSlice(name, []byte(dataVal.String()), val)
@@ -1185,12 +1268,12 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 			// and "lift" it into it. i.e. a string becomes a string slice.
 			default:
 				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
+				return d.decodeSlice(name, []any{data}, val)
 			}
 		}
 
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
+		return newDecodeError(name,
+			fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 	}
 
 	// If the input value is nil, then don't allocate since empty != nil
@@ -1228,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
 	valType := val.Type()
@@ -1253,17 +1336,17 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 				// and "lift" it into it. i.e. a string becomes a string array.
 				default:
 					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
+					return d.decodeArray(name, []any{data}, val)
 				}
 			}
 
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
+			return newDecodeError(name,
+				fmt.Errorf("source data must be an array or slice, got %s", dataValKind))
 
 		}
 		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
+			return newDecodeError(name,
+				fmt.Errorf("expected source data to have length less or equal to %d, got %d", arrayType.Len(), dataVal.Len()))
 		}
 
 		// Make a new array to hold our result, same size as the original data.
@@ -1289,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
 	return errors.Join(errs...)
 }
 
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
+func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 
 	// If the type of the value to write to and the data match directly,
@@ -1310,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		// as an intermediary.
 
 		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
+		mapType := reflect.TypeOf((map[string]any)(nil))
 		mval := reflect.MakeMap(mapType)
 
 		// Creating a pointer to a map so that other methods can completely
@@ -1328,26 +1411,26 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 		return result
 
 	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		return newDecodeError(name,
+			fmt.Errorf("expected a map or struct, got %q", dataValKind))
 	}
 }
 
 func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
 	dataValType := dataVal.Type()
 	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
+		return newDecodeError(name,
+			fmt.Errorf("needs a map with string keys, has %q keys", kind))
 	}
 
 	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
+	dataValKeysUnused := make(map[any]struct{})
 	for _, dataValKey := range dataVal.MapKeys() {
 		dataValKeys[dataValKey] = struct{}{}
 		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
 	}
 
-	targetValKeysUnused := make(map[interface{}]struct{})
+	targetValKeysUnused := make(map[any]struct{})
 
 	var errs []error
 
@@ -1410,7 +1493,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 						structs = append(structs, fieldVal.Elem().Elem())
 					}
 				default:
-					errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
+					errs = append(errs, newDecodeError(
+						name+"."+fieldType.Name,
+						fmt.Errorf("unsupported type for squash: %s", fieldVal.Kind()),
+					))
 				}
 				continue
 			}
@@ -1461,7 +1547,9 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 			if !rawMapVal.IsValid() {
 				// There was no matching key in the map for the value in
 				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
+				if !(d.config.AllowUnsetPointer && fieldValue.Kind() == reflect.Ptr) {
+					targetValKeysUnused[fieldName] = struct{}{}
+				}
 				continue
 			}
 		}
@@ -1495,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 	// we put the unused keys directly into the remain field.
 	if remainField != nil && len(dataValKeysUnused) > 0 {
 		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
+		remain := map[any]any{}
 		for key := range dataValKeysUnused {
 			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
 		}
@@ -1517,8 +1605,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
@@ -1528,8 +1618,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		}
 		sort.Strings(keys)
 
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errs = append(errs, err)
+		errs = append(errs, newDecodeError(
+			name,
+			fmt.Errorf("has unset fields: %s", strings.Join(keys, ", ")),
+		))
 	}
 
 	if err := errors.Join(errs...); err != nil {
diff --git a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
index a65d88eb..04b4bebf 100644
--- a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
+++ b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel
@@ -27,6 +27,7 @@ go_library(
         "//internal/httprule",
         "//utilities",
         "@org_golang_google_genproto_googleapis_api//httpbody",
+        "@org_golang_google_grpc//:grpc",
         "@org_golang_google_grpc//codes",
         "@org_golang_google_grpc//grpclog",
         "@org_golang_google_grpc//health/grpc_health_v1",
diff --git a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
index 2f2b3424..00b2228a 100644
--- a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
+++ b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
@@ -201,13 +201,13 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
 	if timeout != 0 {
 		ctx, _ = context.WithTimeout(ctx, timeout)
 	}
-	if len(pairs) == 0 {
-		return ctx, nil, nil
-	}
 	md := metadata.Pairs(pairs...)
 	for _, mda := range mux.metadataAnnotators {
 		md = metadata.Join(md, mda(ctx, req))
 	}
+	if len(md) == 0 {
+		return ctx, nil, nil
+	}
 	return ctx, md, nil
 }
 
diff --git a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
index 8376d1e0..3d070630 100644
--- a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
+++ b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go
@@ -66,7 +66,7 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
 
 var (
 	// protoMessageType is stored to prevent constant lookup of the same type at runtime.
-	protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
+	protoMessageType = reflect.TypeFor[proto.Message]()
 )
 
 // marshalNonProto marshals a non-message field of a protobuf message.
@@ -325,9 +325,9 @@ type protoEnum interface {
 	EnumDescriptor() ([]byte, []int)
 }
 
-var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem()
+var typeProtoEnum = reflect.TypeFor[protoEnum]()
 
-var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
+var typeProtoMessage = reflect.TypeFor[proto.Message]()
 
 // Delimiter for newline encoded JSON streams.
 func (j *JSONPb) Delimiter() []byte {
diff --git a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
index 19255ec4..3eb16167 100644
--- a/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
+++ b/public-api/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 
 	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule"
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/health/grpc_health_v1"
@@ -281,12 +282,19 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 			http.MethodGet, endpointPath, func(w http.ResponseWriter, r *http.Request, _ map[string]string,
 			) {
 				_, outboundMarshaler := MarshalerForRequest(s, r)
+				annotatedContext, err := AnnotateContext(r.Context(), s, r, grpc_health_v1.Health_Check_FullMethodName, WithHTTPPathPattern(endpointPath))
+				if err != nil {
+					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					return
+				}
 
-				resp, err := healthCheckClient.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{
+				var md ServerMetadata
+				resp, err := healthCheckClient.Check(annotatedContext, &grpc_health_v1.HealthCheckRequest{
 					Service: r.URL.Query().Get("service"),
-				})
+				}, grpc.Header(&md.HeaderMD), grpc.Trailer(&md.TrailerMD))
+				annotatedContext = NewServerMetadataContext(annotatedContext, md)
 				if err != nil {
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
@@ -300,7 +308,7 @@ func WithHealthEndpointAt(healthCheckClient grpc_health_v1.HealthClient, endpoin
 						err = status.Error(codes.NotFound, resp.String())
 					}
 
-					s.errorHandler(r.Context(), s, outboundMarshaler, w, r, err)
+					s.errorHandler(annotatedContext, s, outboundMarshaler, w, r, err)
 					return
 				}
 
diff --git a/public-api/vendor/github.com/hashicorp/hcl/.gitignore b/public-api/vendor/github.com/hashicorp/hcl/.gitignore
deleted file mode 100644
index 15586a2b..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-y.output
-
-# ignore intellij files
-.idea
-*.iml
-*.ipr
-*.iws
-
-*.test
diff --git a/public-api/vendor/github.com/hashicorp/hcl/.travis.yml b/public-api/vendor/github.com/hashicorp/hcl/.travis.yml
deleted file mode 100644
index cb63a321..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-sudo: false
-
-language: go
-
-go:
-  - 1.x
-  - tip
-
-branches:
-  only:
-    - master
-
-script: make test
diff --git a/public-api/vendor/github.com/hashicorp/hcl/LICENSE b/public-api/vendor/github.com/hashicorp/hcl/LICENSE
deleted file mode 100644
index c33dcc7c..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/LICENSE
+++ /dev/null
@@ -1,354 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. “Contributor”
-
-     means each individual or legal entity that creates, contributes to the
-     creation of, or owns Covered Software.
-
-1.2. “Contributor Version”
-
-     means the combination of the Contributions of others (if any) used by a
-     Contributor and that particular Contributor’s Contribution.
-
-1.3. “Contribution”
-
-     means Covered Software of a particular Contributor.
-
-1.4. “Covered Software”
-
-     means Source Code Form to which the initial Contributor has attached the
-     notice in Exhibit A, the Executable Form of such Source Code Form, and
-     Modifications of such Source Code Form, in each case including portions
-     thereof.
-
-1.5. “Incompatible With Secondary Licenses”
-     means
-
-     a. that the initial Contributor has attached the notice described in
-        Exhibit B to the Covered Software; or
-
-     b. that the Covered Software was made available under the terms of version
-        1.1 or earlier of the License, but not also under the terms of a
-        Secondary License.
-
-1.6. “Executable Form”
-
-     means any form of the work other than Source Code Form.
-
-1.7. “Larger Work”
-
-     means a work that combines Covered Software with other material, in a separate
-     file or files, that is not Covered Software.
-
-1.8. “License”
-
-     means this document.
-
-1.9. “Licensable”
-
-     means having the right to grant, to the maximum extent possible, whether at the
-     time of the initial grant or subsequently, any and all of the rights conveyed by
-     this License.
-
-1.10. “Modifications”
-
-     means any of the following:
-
-     a. any file in Source Code Form that results from an addition to, deletion
-        from, or modification of the contents of Covered Software; or
-
-     b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. “Patent Claims” of a Contributor
-
-      means any patent claim(s), including without limitation, method, process,
-      and apparatus claims, in any patent Licensable by such Contributor that
-      would be infringed, but for the grant of the License, by the making,
-      using, selling, offering for sale, having made, import, or transfer of
-      either its Contributions or its Contributor Version.
-
-1.12. “Secondary License”
-
-      means either the GNU General Public License, Version 2.0, the GNU Lesser
-      General Public License, Version 2.1, the GNU Affero General Public
-      License, Version 3.0, or any later versions of those licenses.
-
-1.13. “Source Code Form”
-
-      means the form of the work preferred for making modifications.
-
-1.14. “You” (or “Your”)
-
-      means an individual or a legal entity exercising rights under this
-      License. For legal entities, “You” includes any entity that controls, is
-      controlled by, or is under common control with You. For purposes of this
-      definition, “control” means (a) the power, direct or indirect, to cause
-      the direction or management of such entity, whether by contract or
-      otherwise, or (b) ownership of more than fifty percent (50%) of the
-      outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
-     Each Contributor hereby grants You a world-wide, royalty-free,
-     non-exclusive license:
-
-     a. under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or as
-        part of a Larger Work; and
-
-     b. under Patent Claims of such Contributor to make, use, sell, offer for
-        sale, have made, import, and otherwise transfer either its Contributions
-        or its Contributor Version.
-
-2.2. Effective Date
-
-     The licenses granted in Section 2.1 with respect to any Contribution become
-     effective for each Contribution on the date the Contributor first distributes
-     such Contribution.
-
-2.3. Limitations on Grant Scope
-
-     The licenses granted in this Section 2 are the only rights granted under this
-     License. No additional rights or licenses will be implied from the distribution
-     or licensing of Covered Software under this License. Notwithstanding Section
-     2.1(b) above, no patent license is granted by a Contributor:
-
-     a. for any code that a Contributor has removed from Covered Software; or
-
-     b. for infringements caused by: (i) Your and any other third party’s
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-     c. under Patent Claims infringed by Covered Software in the absence of its
-        Contributions.
-
-     This License does not grant any rights in the trademarks, service marks, or
-     logos of any Contributor (except as may be necessary to comply with the
-     notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-     No Contributor makes additional grants as a result of Your choice to
-     distribute the Covered Software under a subsequent version of this License
-     (see Section 10.2) or under the terms of a Secondary License (if permitted
-     under the terms of Section 3.3).
-
-2.5. Representation
-
-     Each Contributor represents that the Contributor believes its Contributions
-     are its original creation(s) or it has sufficient rights to grant the
-     rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-     This License is not intended to limit any rights You have under applicable
-     copyright doctrines of fair use, fair dealing, or other equivalents.
-
-2.7. Conditions
-
-     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
-     Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
-     All distribution of Covered Software in Source Code Form, including any
-     Modifications that You create or to which You contribute, must be under the
-     terms of this License. You must inform recipients that the Source Code Form
-     of the Covered Software is governed by the terms of this License, and how
-     they can obtain a copy of this License. You may not attempt to alter or
-     restrict the recipients’ rights in the Source Code Form.
-
-3.2. Distribution of Executable Form
-
-     If You distribute Covered Software in Executable Form then:
-
-     a. such Covered Software must also be made available in Source Code Form,
-        as described in Section 3.1, and You must inform recipients of the
-        Executable Form how they can obtain a copy of such Source Code Form by
-        reasonable means in a timely manner, at a charge no more than the cost
-        of distribution to the recipient; and
-
-     b. You may distribute such Executable Form under the terms of this License,
-        or sublicense it under different terms, provided that the license for
-        the Executable Form does not attempt to limit or alter the recipients’
-        rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-     You may create and distribute a Larger Work under terms of Your choice,
-     provided that You also comply with the requirements of this License for the
-     Covered Software. If the Larger Work is a combination of Covered Software
-     with a work governed by one or more Secondary Licenses, and the Covered
-     Software is not Incompatible With Secondary Licenses, this License permits
-     You to additionally distribute such Covered Software under the terms of
-     such Secondary License(s), so that the recipient of the Larger Work may, at
-     their option, further distribute the Covered Software under the terms of
-     either this License or such Secondary License(s).
-
-3.4. Notices
-
-     You may not remove or alter the substance of any license notices (including
-     copyright notices, patent notices, disclaimers of warranty, or limitations
-     of liability) contained within the Source Code Form of the Covered
-     Software, except that You may alter any license notices to the extent
-     required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-     You may choose to offer, and to charge a fee for, warranty, support,
-     indemnity or liability obligations to one or more recipients of Covered
-     Software. However, You may do so only on Your own behalf, and not on behalf
-     of any Contributor. You must make it absolutely clear that any such
-     warranty, support, indemnity, or liability obligation is offered by You
-     alone, and You hereby agree to indemnify every Contributor for any
-     liability incurred by such Contributor as a result of warranty, support,
-     indemnity or liability terms You offer. You may include additional
-     disclaimers of warranty and limitations of liability specific to any
-     jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
-   If it is impossible for You to comply with any of the terms of this License
-   with respect to some or all of the Covered Software due to statute, judicial
-   order, or regulation then You must: (a) comply with the terms of this License
-   to the maximum extent possible; and (b) describe the limitations and the code
-   they affect. Such description must be placed in a text file included with all
-   distributions of the Covered Software under this License. Except to the
-   extent prohibited by statute or regulation, such description must be
-   sufficiently detailed for a recipient of ordinary skill to be able to
-   understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
-     fail to comply with any of its terms. However, if You become compliant,
-     then the rights granted under this License from a particular Contributor
-     are reinstated (a) provisionally, unless and until such Contributor
-     explicitly and finally terminates Your grants, and (b) on an ongoing basis,
-     if such Contributor fails to notify You of the non-compliance by some
-     reasonable means prior to 60 days after You have come back into compliance.
-     Moreover, Your grants from a particular Contributor are reinstated on an
-     ongoing basis if such Contributor notifies You of the non-compliance by
-     some reasonable means, this is the first time You have received notice of
-     non-compliance with this License from such Contributor, and You become
-     compliant prior to 30 days after Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-     infringement claim (excluding declaratory judgment actions, counter-claims,
-     and cross-claims) alleging that a Contributor Version directly or
-     indirectly infringes any patent, then the rights granted to You by any and
-     all Contributors for the Covered Software under Section 2.1 of this License
-     shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
-     license agreements (excluding distributors and resellers) which have been
-     validly granted by You or Your distributors under this License prior to
-     termination shall survive termination.
-
-6. Disclaimer of Warranty
-
-   Covered Software is provided under this License on an “as is” basis, without
-   warranty of any kind, either expressed, implied, or statutory, including,
-   without limitation, warranties that the Covered Software is free of defects,
-   merchantable, fit for a particular purpose or non-infringing. The entire
-   risk as to the quality and performance of the Covered Software is with You.
-   Should any Covered Software prove defective in any respect, You (not any
-   Contributor) assume the cost of any necessary servicing, repair, or
-   correction. This disclaimer of warranty constitutes an essential part of this
-   License. No use of  any Covered Software is authorized under this License
-   except under this disclaimer.
-
-7. Limitation of Liability
-
-   Under no circumstances and under no legal theory, whether tort (including
-   negligence), contract, or otherwise, shall any Contributor, or anyone who
-   distributes Covered Software as permitted above, be liable to You for any
-   direct, indirect, special, incidental, or consequential damages of any
-   character including, without limitation, damages for lost profits, loss of
-   goodwill, work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses, even if such party shall have been
-   informed of the possibility of such damages. This limitation of liability
-   shall not apply to liability for death or personal injury resulting from such
-   party’s negligence to the extent applicable law prohibits such limitation.
-   Some jurisdictions do not allow the exclusion or limitation of incidental or
-   consequential damages, so this exclusion and limitation may not apply to You.
-
-8. Litigation
-
-   Any litigation relating to this License may be brought only in the courts of
-   a jurisdiction where the defendant maintains its principal place of business
-   and such litigation shall be governed by laws of that jurisdiction, without
-   reference to its conflict-of-law provisions. Nothing in this Section shall
-   prevent a party’s ability to bring cross-claims or counter-claims.
-
-9. Miscellaneous
-
-   This License represents the complete agreement concerning the subject matter
-   hereof. If any provision of this License is held to be unenforceable, such
-   provision shall be reformed only to the extent necessary to make it
-   enforceable. Any law or regulation which provides that the language of a
-   contract shall be construed against the drafter shall not be used to construe
-   this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
-      Mozilla Foundation is the license steward. Except as provided in Section
-      10.3, no one other than the license steward has the right to modify or
-      publish new versions of this License. Each version will be given a
-      distinguishing version number.
-
-10.2. Effect of New Versions
-
-      You may distribute the Covered Software under the terms of the version of
-      the License under which You originally received the Covered Software, or
-      under the terms of any subsequent version published by the license
-      steward.
-
-10.3. Modified Versions
-
-      If you create software not governed by this License, and you want to
-      create a new license for such software, you may create and use a modified
-      version of this License if you rename the license and remove any
-      references to the name of the license steward (except to note that such
-      modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
-      If You choose to distribute Source Code Form that is Incompatible With
-      Secondary Licenses under the terms of this version of the License, the
-      notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
-
-      This Source Code Form is subject to the
-      terms of the Mozilla Public License, v.
-      2.0. If a copy of the MPL was not
-      distributed with this file, You can
-      obtain one at
-      http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file, then
-You may include the notice in a location (such as a LICENSE file in a relevant
-directory) where a recipient would be likely to look for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - “Incompatible With Secondary Licenses” Notice
-
-      This Source Code Form is “Incompatible
-      With Secondary Licenses”, as defined by
-      the Mozilla Public License, v. 2.0.
-
diff --git a/public-api/vendor/github.com/hashicorp/hcl/Makefile b/public-api/vendor/github.com/hashicorp/hcl/Makefile
deleted file mode 100644
index 84fd743f..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-TEST?=./...
-
-default: test
-
-fmt: generate
-	go fmt ./...
-
-test: generate
-	go get -t ./...
-	go test $(TEST) $(TESTARGS)
-
-generate:
-	go generate ./...
-
-updatedeps:
-	go get -u golang.org/x/tools/cmd/stringer
-
-.PHONY: default generate test updatedeps
diff --git a/public-api/vendor/github.com/hashicorp/hcl/README.md b/public-api/vendor/github.com/hashicorp/hcl/README.md
deleted file mode 100644
index c8223326..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/README.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# HCL
-
-[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl)
-
-HCL (HashiCorp Configuration Language) is a configuration language built
-by HashiCorp. The goal of HCL is to build a structured configuration language
-that is both human and machine friendly for use with command-line tools, but
-specifically targeted towards DevOps tools, servers, etc.
-
-HCL is also fully JSON compatible. That is, JSON can be used as completely
-valid input to a system expecting HCL. This helps makes systems
-interoperable with other systems.
-
-HCL is heavily inspired by
-[libucl](https://github.com/vstakhov/libucl),
-nginx configuration, and others similar.
-
-## Why?
-
-A common question when viewing HCL is to ask the question: why not
-JSON, YAML, etc.?
-
-Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com)
-used a variety of configuration languages from full programming languages
-such as Ruby to complete data structure languages such as JSON. What we
-learned is that some people wanted human-friendly configuration languages
-and some people wanted machine-friendly languages.
-
-JSON fits a nice balance in this, but is fairly verbose and most
-importantly doesn't support comments. With YAML, we found that beginners
-had a really hard time determining what the actual structure was, and
-ended up guessing more often than not whether to use a hyphen, colon, etc.
-in order to represent some configuration key.
-
-Full programming languages such as Ruby enable complex behavior
-a configuration language shouldn't usually allow, and also forces
-people to learn some set of Ruby.
-
-Because of this, we decided to create our own configuration language
-that is JSON-compatible. Our configuration language (HCL) is designed
-to be written and modified by humans. The API for HCL allows JSON
-as an input so that it is also machine-friendly (machines can generate
-JSON instead of trying to generate HCL).
-
-Our goal with HCL is not to alienate other configuration languages.
-It is instead to provide HCL as a specialized language for our tools,
-and JSON as the interoperability layer.
-
-## Syntax
-
-For a complete grammar, please see the parser itself. A high-level overview
-of the syntax and grammar is listed here.
-
-  * Single line comments start with `#` or `//`
-
-  * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments
-    are not allowed. A multi-line comment (also known as a block comment)
-    terminates at the first `*/` found.
-
-  * Values are assigned with the syntax `key = value` (whitespace doesn't
-    matter). The value can be any primitive: a string, number, boolean,
-    object, or list.
-
-  * Strings are double-quoted and can contain any UTF-8 characters.
-    Example: `"Hello, World"`
-
-  * Multi-line strings start with `<-
-    echo %Path%
-
-    go version
-
-    go env
-
-    go get -t ./...
-
-build_script:
-- cmd: go test -v ./...
diff --git a/public-api/vendor/github.com/hashicorp/hcl/decoder.go b/public-api/vendor/github.com/hashicorp/hcl/decoder.go
deleted file mode 100644
index bed9ebbe..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/decoder.go
+++ /dev/null
@@ -1,729 +0,0 @@
-package hcl
-
-import (
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// This is the tag to use with structures to have settings for HCL
-const tagName = "hcl"
-
-var (
-	// nodeType holds a reference to the type of ast.Node
-	nodeType reflect.Type = findNodeType()
-)
-
-// Unmarshal accepts a byte slice as input and writes the
-// data to the value pointed to by v.
-func Unmarshal(bs []byte, v interface{}) error {
-	root, err := parse(bs)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(v, root)
-}
-
-// Decode reads the given input and decodes it into the structure
-// given by `out`.
-func Decode(out interface{}, in string) error {
-	obj, err := Parse(in)
-	if err != nil {
-		return err
-	}
-
-	return DecodeObject(out, obj)
-}
-
-// DecodeObject is a lower-level version of Decode. It decodes a
-// raw Object into the given output.
-func DecodeObject(out interface{}, n ast.Node) error {
-	val := reflect.ValueOf(out)
-	if val.Kind() != reflect.Ptr {
-		return errors.New("result must be a pointer")
-	}
-
-	// If we have the file, we really decode the root node
-	if f, ok := n.(*ast.File); ok {
-		n = f.Node
-	}
-
-	var d decoder
-	return d.decode("root", n, val.Elem())
-}
-
-type decoder struct {
-	stack []reflect.Kind
-}
-
-func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
-	k := result
-
-	// If we have an interface with a valid value, we use that
-	// for the check.
-	if result.Kind() == reflect.Interface {
-		elem := result.Elem()
-		if elem.IsValid() {
-			k = elem
-		}
-	}
-
-	// Push current onto stack unless it is an interface.
-	if k.Kind() != reflect.Interface {
-		d.stack = append(d.stack, k.Kind())
-
-		// Schedule a pop
-		defer func() {
-			d.stack = d.stack[:len(d.stack)-1]
-		}()
-	}
-
-	switch k.Kind() {
-	case reflect.Bool:
-		return d.decodeBool(name, node, result)
-	case reflect.Float32, reflect.Float64:
-		return d.decodeFloat(name, node, result)
-	case reflect.Int, reflect.Int32, reflect.Int64:
-		return d.decodeInt(name, node, result)
-	case reflect.Interface:
-		// When we see an interface, we make our own thing
-		return d.decodeInterface(name, node, result)
-	case reflect.Map:
-		return d.decodeMap(name, node, result)
-	case reflect.Ptr:
-		return d.decodePtr(name, node, result)
-	case reflect.Slice:
-		return d.decodeSlice(name, node, result)
-	case reflect.String:
-		return d.decodeString(name, node, result)
-	case reflect.Struct:
-		return d.decodeStruct(name, node, result)
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
-		}
-	}
-}
-
-func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.BOOL {
-			v, err := strconv.ParseBool(n.Token.Text)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
-			v, err := strconv.ParseFloat(n.Token.Text, 64)
-			if err != nil {
-				return err
-			}
-
-			result.Set(reflect.ValueOf(v).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			v, err := strconv.ParseInt(n.Token.Text, 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		case token.STRING:
-			v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
-			if err != nil {
-				return err
-			}
-
-			if result.Kind() == reflect.Interface {
-				result.Set(reflect.ValueOf(int(v)))
-			} else {
-				result.SetInt(v)
-			}
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type %T", name, node),
-	}
-}
-
-func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
-	// When we see an ast.Node, we retain the value to enable deferred decoding.
-	// Very useful in situations where we want to preserve ast.Node information
-	// like Pos
-	if result.Type() == nodeType && result.CanSet() {
-		result.Set(reflect.ValueOf(node))
-		return nil
-	}
-
-	var set reflect.Value
-	redecode := true
-
-	// For testing types, ObjectType should just be treated as a list. We
-	// set this to a temporary var because we want to pass in the real node.
-	testNode := node
-	if ot, ok := node.(*ast.ObjectType); ok {
-		testNode = ot.List
-	}
-
-	switch n := testNode.(type) {
-	case *ast.ObjectList:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
-			set = result
-		}
-	case *ast.ObjectType:
-		// If we're at the root or we're directly within a slice, then we
-		// decode objects into map[string]interface{}, otherwise we decode
-		// them into lists.
-		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
-			var temp map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeMap(
-				reflect.MapOf(
-					reflect.TypeOf(""),
-					tempVal.Type().Elem()))
-
-			set = result
-		} else {
-			var temp []map[string]interface{}
-			tempVal := reflect.ValueOf(temp)
-			result := reflect.MakeSlice(
-				reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
-			set = result
-		}
-	case *ast.ListType:
-		var temp []interface{}
-		tempVal := reflect.ValueOf(temp)
-		result := reflect.MakeSlice(
-			reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
-		set = result
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.BOOL:
-			var result bool
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.FLOAT:
-			var result float64
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.NUMBER:
-			var result int
-			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
-		case token.STRING, token.HEREDOC:
-			set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
-		default:
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
-			}
-		}
-	default:
-		return fmt.Errorf(
-			"%s: cannot decode into interface: %T",
-			name, node)
-	}
-
-	// Set the result to what its supposed to be, then reset
-	// result so we don't reflect into this method anymore.
-	result.Set(set)
-
-	if redecode {
-		// Revisit the node so that we can use the newly instantiated
-		// thing and populate it.
-		if err := d.decode(name, node, result); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
-	if item, ok := node.(*ast.ObjectItem); ok {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	n, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
-		}
-	}
-
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	resultKeyType := resultType.Key()
-	if resultKeyType.Kind() != reflect.String {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: map must have string keys", name),
-		}
-	}
-
-	// Make a map if it is nil
-	resultMap := result
-	if result.IsNil() {
-		resultMap = reflect.MakeMap(
-			reflect.MapOf(resultKeyType, resultElemType))
-	}
-
-	// Go through each element and decode it.
-	done := make(map[string]struct{})
-	for _, item := range n.Items {
-		if item.Val == nil {
-			continue
-		}
-
-		// github.com/hashicorp/terraform/issue/5740
-		if len(item.Keys) == 0 {
-			return &parser.PosError{
-				Pos: node.Pos(),
-				Err: fmt.Errorf("%s: map must have string keys", name),
-			}
-		}
-
-		// Get the key we're dealing with, which is the first item
-		keyStr := item.Keys[0].Token.Value().(string)
-
-		// If we've already processed this key, then ignore it
-		if _, ok := done[keyStr]; ok {
-			continue
-		}
-
-		// Determine the value. If we have more than one key, then we
-		// get the objectlist of only these keys.
-		itemVal := item.Val
-		if len(item.Keys) > 1 {
-			itemVal = n.Filter(keyStr)
-			done[keyStr] = struct{}{}
-		}
-
-		// Make the field name
-		fieldName := fmt.Sprintf("%s.%s", name, keyStr)
-
-		// Get the key/value as reflection values
-		key := reflect.ValueOf(keyStr)
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// If we have a pre-existing value in the map, use that
-		oldVal := resultMap.MapIndex(key)
-		if oldVal.IsValid() {
-			val.Set(oldVal)
-		}
-
-		// Decode!
-		if err := d.decode(fieldName, itemVal, val); err != nil {
-			return err
-		}
-
-		// Set the value on the map
-		resultMap.SetMapIndex(key, val)
-	}
-
-	// Set the final map if we can
-	set.Set(resultMap)
-	return nil
-}
-
-func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	val := reflect.New(resultElemType)
-	if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
-		return err
-	}
-
-	result.Set(val)
-	return nil
-}
-
-func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
-	// If we have an interface, then we can address the interface,
-	// but not the slice itself, so get the element but set the interface
-	set := result
-	if result.Kind() == reflect.Interface {
-		result = result.Elem()
-	}
-	// Create the slice if it isn't nil
-	resultType := result.Type()
-	resultElemType := resultType.Elem()
-	if result.IsNil() {
-		resultSliceType := reflect.SliceOf(resultElemType)
-		result = reflect.MakeSlice(
-			resultSliceType, 0, 0)
-	}
-
-	// Figure out the items we'll be copying into the slice
-	var items []ast.Node
-	switch n := node.(type) {
-	case *ast.ObjectList:
-		items = make([]ast.Node, len(n.Items))
-		for i, item := range n.Items {
-			items[i] = item
-		}
-	case *ast.ObjectType:
-		items = []ast.Node{n}
-	case *ast.ListType:
-		items = n.List
-	default:
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("unknown slice type: %T", node),
-		}
-	}
-
-	for i, item := range items {
-		fieldName := fmt.Sprintf("%s[%d]", name, i)
-
-		// Decode
-		val := reflect.Indirect(reflect.New(resultElemType))
-
-		// if item is an object that was decoded from ambiguous JSON and
-		// flattened, make sure it's expanded if it needs to decode into a
-		// defined structure.
-		item := expandObject(item, val)
-
-		if err := d.decode(fieldName, item, val); err != nil {
-			return err
-		}
-
-		// Append it onto the slice
-		result = reflect.Append(result, val)
-	}
-
-	set.Set(result)
-	return nil
-}
-
-// expandObject detects if an ambiguous JSON object was flattened to a List which
-// should be decoded into a struct, and expands the ast to properly deocode.
-func expandObject(node ast.Node, result reflect.Value) ast.Node {
-	item, ok := node.(*ast.ObjectItem)
-	if !ok {
-		return node
-	}
-
-	elemType := result.Type()
-
-	// our target type must be a struct
-	switch elemType.Kind() {
-	case reflect.Ptr:
-		switch elemType.Elem().Kind() {
-		case reflect.Struct:
-			//OK
-		default:
-			return node
-		}
-	case reflect.Struct:
-		//OK
-	default:
-		return node
-	}
-
-	// A list value will have a key and field name. If it had more fields,
-	// it wouldn't have been flattened.
-	if len(item.Keys) != 2 {
-		return node
-	}
-
-	keyToken := item.Keys[0].Token
-	item.Keys = item.Keys[1:]
-
-	// we need to un-flatten the ast enough to decode
-	newNode := &ast.ObjectItem{
-		Keys: []*ast.ObjectKey{
-			&ast.ObjectKey{
-				Token: keyToken,
-			},
-		},
-		Val: &ast.ObjectType{
-			List: &ast.ObjectList{
-				Items: []*ast.ObjectItem{item},
-			},
-		},
-	}
-
-	return newNode
-}
-
-func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
-	switch n := node.(type) {
-	case *ast.LiteralType:
-		switch n.Token.Type {
-		case token.NUMBER:
-			result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
-			return nil
-		case token.STRING, token.HEREDOC:
-			result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
-			return nil
-		}
-	}
-
-	return &parser.PosError{
-		Pos: node.Pos(),
-		Err: fmt.Errorf("%s: unknown type for string %T", name, node),
-	}
-}
-
-func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
-	var item *ast.ObjectItem
-	if it, ok := node.(*ast.ObjectItem); ok {
-		item = it
-		node = it.Val
-	}
-
-	if ot, ok := node.(*ast.ObjectType); ok {
-		node = ot.List
-	}
-
-	// Handle the special case where the object itself is a literal. Previously
-	// the yacc parser would always ensure top-level elements were arrays. The new
-	// parser does not make the same guarantees, thus we need to convert any
-	// top-level literal elements into a list.
-	if _, ok := node.(*ast.LiteralType); ok && item != nil {
-		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
-	}
-
-	list, ok := node.(*ast.ObjectList)
-	if !ok {
-		return &parser.PosError{
-			Pos: node.Pos(),
-			Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
-		}
-	}
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = result
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
-
-			// Ignore fields with tag name "-"
-			if tagParts[0] == "-" {
-				continue
-			}
-
-			if fieldType.Anonymous {
-				fieldKind := fieldType.Type.Kind()
-				if fieldKind != reflect.Struct {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: unsupported type to struct: %s",
-							fieldType.Name, fieldKind),
-					}
-				}
-
-				// We have an embedded field. We "squash" the fields down
-				// if specified in the tag.
-				squash := false
-				for _, tag := range tagParts[1:] {
-					if tag == "squash" {
-						squash = true
-						break
-					}
-				}
-
-				if squash {
-					structs = append(
-						structs, result.FieldByName(fieldType.Name))
-					continue
-				}
-			}
-
-			// Normal struct field, store it away
-			fields = append(fields, field{fieldType, structVal.Field(i)})
-		}
-	}
-
-	usedKeys := make(map[string]struct{})
-	decodedFields := make([]string, 0, len(fields))
-	decodedFieldsVal := make([]reflect.Value, 0)
-	unusedKeysVal := make([]reflect.Value, 0)
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(tagName)
-		tagParts := strings.SplitN(tagValue, ",", 2)
-		if len(tagParts) >= 2 {
-			switch tagParts[1] {
-			case "decodedFields":
-				decodedFieldsVal = append(decodedFieldsVal, fieldValue)
-				continue
-			case "key":
-				if item == nil {
-					return &parser.PosError{
-						Pos: node.Pos(),
-						Err: fmt.Errorf("%s: %s asked for 'key', impossible",
-							name, fieldName),
-					}
-				}
-
-				fieldValue.SetString(item.Keys[0].Token.Value().(string))
-				continue
-			case "unusedKeys":
-				unusedKeysVal = append(unusedKeysVal, fieldValue)
-				continue
-			}
-		}
-
-		if tagParts[0] != "" {
-			fieldName = tagParts[0]
-		}
-
-		// Determine the element we'll use to decode. If it is a single
-		// match (only object with the field), then we decode it exactly.
-		// If it is a prefix match, then we decode the matches.
-		filter := list.Filter(fieldName)
-
-		prefixMatches := filter.Children()
-		matches := filter.Elem()
-		if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
-			continue
-		}
-
-		// Track the used key
-		usedKeys[fieldName] = struct{}{}
-
-		// Create the field name and decode. We range over the elements
-		// because we actually want the value.
-		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
-		if len(prefixMatches.Items) > 0 {
-			if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
-				return err
-			}
-		}
-		for _, match := range matches.Items {
-			var decodeNode ast.Node = match.Val
-			if ot, ok := decodeNode.(*ast.ObjectType); ok {
-				decodeNode = &ast.ObjectList{Items: ot.List.Items}
-			}
-
-			if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
-				return err
-			}
-		}
-
-		decodedFields = append(decodedFields, field.Name)
-	}
-
-	if len(decodedFieldsVal) > 0 {
-		// Sort it so that it is deterministic
-		sort.Strings(decodedFields)
-
-		for _, v := range decodedFieldsVal {
-			v.Set(reflect.ValueOf(decodedFields))
-		}
-	}
-
-	return nil
-}
-
-// findNodeType returns the type of ast.Node
-func findNodeType() reflect.Type {
-	var nodeContainer struct {
-		Node ast.Node
-	}
-	value := reflect.ValueOf(nodeContainer).FieldByName("Node")
-	return value.Type()
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl.go b/public-api/vendor/github.com/hashicorp/hcl/hcl.go
deleted file mode 100644
index 575a20b5..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Package hcl decodes HCL into usable Go structures.
-//
-// hcl input can come in either pure HCL format or JSON format.
-// It can be parsed into an AST, and then decoded into a structure,
-// or it can be decoded directly from a string into a structure.
-//
-// If you choose to parse HCL into a raw AST, the benefit is that you
-// can write custom visitor implementations to implement custom
-// semantic checks. By default, HCL does not perform any semantic
-// checks.
-package hcl
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
deleted file mode 100644
index 6e5ef654..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package ast declares the types used to represent syntax trees for HCL
-// (HashiCorp Configuration Language)
-package ast
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// Node is an element in the abstract syntax tree.
-type Node interface {
-	node()
-	Pos() token.Pos
-}
-
-func (File) node()         {}
-func (ObjectList) node()   {}
-func (ObjectKey) node()    {}
-func (ObjectItem) node()   {}
-func (Comment) node()      {}
-func (CommentGroup) node() {}
-func (ObjectType) node()   {}
-func (LiteralType) node()  {}
-func (ListType) node()     {}
-
-// File represents a single HCL file
-type File struct {
-	Node     Node            // usually a *ObjectList
-	Comments []*CommentGroup // list of all comments in the source
-}
-
-func (f *File) Pos() token.Pos {
-	return f.Node.Pos()
-}
-
-// ObjectList represents a list of ObjectItems. An HCL file itself is an
-// ObjectList.
-type ObjectList struct {
-	Items []*ObjectItem
-}
-
-func (o *ObjectList) Add(item *ObjectItem) {
-	o.Items = append(o.Items, item)
-}
-
-// Filter filters out the objects with the given key list as a prefix.
-//
-// The returned list of objects contain ObjectItems where the keys have
-// this prefix already stripped off. This might result in objects with
-// zero-length key lists if they have no children.
-//
-// If no matches are found, an empty ObjectList (non-nil) is returned.
-func (o *ObjectList) Filter(keys ...string) *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		// If there aren't enough keys, then ignore this
-		if len(item.Keys) < len(keys) {
-			continue
-		}
-
-		match := true
-		for i, key := range item.Keys[:len(keys)] {
-			key := key.Token.Value().(string)
-			if key != keys[i] && !strings.EqualFold(key, keys[i]) {
-				match = false
-				break
-			}
-		}
-		if !match {
-			continue
-		}
-
-		// Strip off the prefix from the children
-		newItem := *item
-		newItem.Keys = newItem.Keys[len(keys):]
-		result.Add(&newItem)
-	}
-
-	return &result
-}
-
-// Children returns further nested objects (key length > 0) within this
-// ObjectList. This should be used with Filter to get at child items.
-func (o *ObjectList) Children() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) > 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-// Elem returns items in the list that are direct element assignments
-// (key length == 0). This should be used with Filter to get at elements.
-func (o *ObjectList) Elem() *ObjectList {
-	var result ObjectList
-	for _, item := range o.Items {
-		if len(item.Keys) == 0 {
-			result.Add(item)
-		}
-	}
-
-	return &result
-}
-
-func (o *ObjectList) Pos() token.Pos {
-	// always returns the uninitiliazed position
-	return o.Items[0].Pos()
-}
-
-// ObjectItem represents a HCL Object Item. An item is represented with a key
-// (or keys). It can be an assignment or an object (both normal and nested)
-type ObjectItem struct {
-	// keys is only one length long if it's of type assignment. If it's a
-	// nested object it can be larger than one. In that case "assign" is
-	// invalid as there is no assignments for a nested object.
-	Keys []*ObjectKey
-
-	// assign contains the position of "=", if any
-	Assign token.Pos
-
-	// val is the item itself. It can be an object,list, number, bool or a
-	// string. If key length is larger than one, val can be only of type
-	// Object.
-	Val Node
-
-	LeadComment *CommentGroup // associated lead comment
-	LineComment *CommentGroup // associated line comment
-}
-
-func (o *ObjectItem) Pos() token.Pos {
-	// I'm not entirely sure what causes this, but removing this causes
-	// a test failure. We should investigate at some point.
-	if len(o.Keys) == 0 {
-		return token.Pos{}
-	}
-
-	return o.Keys[0].Pos()
-}
-
-// ObjectKeys are either an identifier or of type string.
-type ObjectKey struct {
-	Token token.Token
-}
-
-func (o *ObjectKey) Pos() token.Pos {
-	return o.Token.Pos
-}
-
-// LiteralType represents a literal of basic type. Valid types are:
-// token.NUMBER, token.FLOAT, token.BOOL and token.STRING
-type LiteralType struct {
-	Token token.Token
-
-	// comment types, only used when in a list
-	LeadComment *CommentGroup
-	LineComment *CommentGroup
-}
-
-func (l *LiteralType) Pos() token.Pos {
-	return l.Token.Pos
-}
-
-// ListStatement represents a HCL List type
-type ListType struct {
-	Lbrack token.Pos // position of "["
-	Rbrack token.Pos // position of "]"
-	List   []Node    // the elements in lexical order
-}
-
-func (l *ListType) Pos() token.Pos {
-	return l.Lbrack
-}
-
-func (l *ListType) Add(node Node) {
-	l.List = append(l.List, node)
-}
-
-// ObjectType represents a HCL Object Type
-type ObjectType struct {
-	Lbrace token.Pos   // position of "{"
-	Rbrace token.Pos   // position of "}"
-	List   *ObjectList // the nodes in lexical order
-}
-
-func (o *ObjectType) Pos() token.Pos {
-	return o.Lbrace
-}
-
-// Comment node represents a single //, # style or /*- style commment
-type Comment struct {
-	Start token.Pos // position of / or #
-	Text  string
-}
-
-func (c *Comment) Pos() token.Pos {
-	return c.Start
-}
-
-// CommentGroup node represents a sequence of comments with no other tokens and
-// no empty lines between.
-type CommentGroup struct {
-	List []*Comment // len(List) > 0
-}
-
-func (c *CommentGroup) Pos() token.Pos {
-	return c.List[0].Pos()
-}
-
-//-------------------------------------------------------------------
-// GoStringer
-//-------------------------------------------------------------------
-
-func (o *ObjectKey) GoString() string  { return fmt.Sprintf("*%#v", *o) }
-func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) }
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
deleted file mode 100644
index ba07ad42..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package ast
-
-import "fmt"
-
-// WalkFunc describes a function to be called for each node during a Walk. The
-// returned node can be used to rewrite the AST. Walking stops the returned
-// bool is false.
-type WalkFunc func(Node) (Node, bool)
-
-// Walk traverses an AST in depth-first order: It starts by calling fn(node);
-// node must not be nil. If fn returns true, Walk invokes fn recursively for
-// each of the non-nil children of node, followed by a call of fn(nil). The
-// returned node of fn can be used to rewrite the passed node to fn.
-func Walk(node Node, fn WalkFunc) Node {
-	rewritten, ok := fn(node)
-	if !ok {
-		return rewritten
-	}
-
-	switch n := node.(type) {
-	case *File:
-		n.Node = Walk(n.Node, fn)
-	case *ObjectList:
-		for i, item := range n.Items {
-			n.Items[i] = Walk(item, fn).(*ObjectItem)
-		}
-	case *ObjectKey:
-		// nothing to do
-	case *ObjectItem:
-		for i, k := range n.Keys {
-			n.Keys[i] = Walk(k, fn).(*ObjectKey)
-		}
-
-		if n.Val != nil {
-			n.Val = Walk(n.Val, fn)
-		}
-	case *LiteralType:
-		// nothing to do
-	case *ListType:
-		for i, l := range n.List {
-			n.List[i] = Walk(l, fn)
-		}
-	case *ObjectType:
-		n.List = Walk(n.List, fn).(*ObjectList)
-	default:
-		// should we panic here?
-		fmt.Printf("unknown type: %T\n", n)
-	}
-
-	fn(nil)
-	return rewritten
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
deleted file mode 100644
index 5c99381d..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/error.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package parser
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// PosError is a parse error that contains a position.
-type PosError struct {
-	Pos token.Pos
-	Err error
-}
-
-func (e *PosError) Error() string {
-	return fmt.Sprintf("At %s: %s", e.Pos, e.Err)
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
deleted file mode 100644
index 64c83bcf..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
+++ /dev/null
@@ -1,532 +0,0 @@
-// Package parser implements a parser for HCL (HashiCorp Configuration
-// Language)
-package parser
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strings"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/scanner"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	comments    []*ast.CommentGroup
-	leadComment *ast.CommentGroup // last lead comment
-	lineComment *ast.CommentGroup // last line comment
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	// normalize all line endings
-	// since the scanner and output only work with "\n" line endings, we may
-	// end up with dangling "\r" characters in the parsed data.
-	src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1)
-
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = &PosError{Pos: pos, Err: errors.New(msg)}
-	}
-
-	f.Node, err = p.objectList(false)
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	f.Comments = p.comments
-	return f, nil
-}
-
-// objectList parses a list of items within an object (generally k/v pairs).
-// The parameter" obj" tells this whether to we are within an object (braces:
-// '{', '}') or just at the top level. If we're within an object, we end
-// at an RBRACE.
-func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		if obj {
-			tok := p.scan()
-			p.unscan()
-			if tok.Type == token.RBRACE {
-				break
-			}
-		}
-
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// object lists can be optionally comma-delimited e.g. when a list of maps
-		// is being expressed, so a comma is allowed here - it's simply consumed
-		tok := p.scan()
-		if tok.Type != token.COMMA {
-			p.unscan()
-		}
-	}
-	return node, nil
-}
-
-func (p *Parser) consumeComment() (comment *ast.Comment, endline int) {
-	endline = p.tok.Pos.Line
-
-	// count the endline if it's multiline comment, ie starting with /*
-	if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' {
-		// don't use range here - no need to decode Unicode code points
-		for i := 0; i < len(p.tok.Text); i++ {
-			if p.tok.Text[i] == '\n' {
-				endline++
-			}
-		}
-	}
-
-	comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text}
-	p.tok = p.sc.Scan()
-	return
-}
-
-func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
-	var list []*ast.Comment
-	endline = p.tok.Pos.Line
-
-	for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n {
-		var comment *ast.Comment
-		comment, endline = p.consumeComment()
-		list = append(list, comment)
-	}
-
-	// add comment group to the comments list
-	comments = &ast.CommentGroup{List: list}
-	p.comments = append(p.comments, comments)
-
-	return
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if len(keys) > 0 && err == errEofToken {
-		// We ignore eof token here since it is an error if we didn't
-		// receive a value (but we did receive a key) for the item.
-		err = nil
-	}
-	if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE {
-		// This is a strange boolean statement, but what it means is:
-		// We have keys with no value, and we're likely in an object
-		// (since RBrace ends an object). For this, we set err to nil so
-		// we continue and get the error below of having the wrong value
-		// type.
-		err = nil
-
-		// Reset the token type so we don't think it completed fine. See
-		// objectType which uses p.tok.Type to check if we're done with
-		// the object.
-		p.tok.Type = token.EOF
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	if p.leadComment != nil {
-		o.LeadComment = p.leadComment
-		p.leadComment = nil
-	}
-
-	switch p.tok.Type {
-	case token.ASSIGN:
-		o.Assign = p.tok.Pos
-		o.Val, err = p.object()
-		if err != nil {
-			return nil, err
-		}
-	case token.LBRACE:
-		o.Val, err = p.objectType()
-		if err != nil {
-			return nil, err
-		}
-	default:
-		keyStr := make([]string, 0, len(keys))
-		for _, k := range keys {
-			keyStr = append(keyStr, k.Token.Text)
-		}
-
-		return nil, &PosError{
-			Pos: p.tok.Pos,
-			Err: fmt.Errorf(
-				"key '%s' expected start of object ('{') or assignment ('=')",
-				strings.Join(keyStr, " ")),
-		}
-	}
-
-	// key=#comment
-	// val
-	if p.lineComment != nil {
-		o.LineComment, p.lineComment = p.lineComment, nil
-	}
-
-	// do a look-ahead for line comment
-	p.scan()
-	if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil {
-		o.LineComment = p.lineComment
-		p.lineComment = nil
-	}
-	p.unscan()
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			// It is very important to also return the keys here as well as
-			// the error. This is because we need to be able to tell if we
-			// did parse keys prior to finding the EOF, or if we just found
-			// a bare EOF.
-			return keys, errEofToken
-		case token.ASSIGN:
-			// assignment or object only, but not nested objects. this is not
-			// allowed: `foo bar = {}`
-			if keyCount > 1 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type),
-				}
-			}
-
-			if keyCount == 0 {
-				return nil, &PosError{
-					Pos: p.tok.Pos,
-					Err: errors.New("no object keys found!"),
-				}
-			}
-
-			return keys, nil
-		case token.LBRACE:
-			var err error
-
-			// If we have no keys, then it is a syntax error. i.e. {{}} is not
-			// allowed.
-			if len(keys) == 0 {
-				err = &PosError{
-					Pos: p.tok.Pos,
-					Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type),
-				}
-			}
-
-			// object
-			return keys, err
-		case token.IDENT, token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{Token: p.tok})
-		case token.ILLEGAL:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("illegal character"),
-			}
-		default:
-			return keys, &PosError{
-				Pos: p.tok.Pos,
-				Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type),
-			}
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (ast.Node, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.COMMENT:
-		// implement comment
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, &PosError{
-		Pos: tok.Pos,
-		Err: fmt.Errorf("Unknown token: %+v", tok),
-	}
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{
-		Lbrace: p.tok.Pos,
-	}
-
-	l, err := p.objectList(true)
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	// No error, scan and expect the ending to be a brace
-	if tok := p.scan(); tok.Type != token.RBRACE {
-		return nil, &PosError{
-			Pos: tok.Pos,
-			Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type),
-		}
-	}
-
-	o.List = l
-	o.Rbrace = p.tok.Pos // advanced via parseObjectList
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{
-		Lbrack: p.tok.Pos,
-	}
-
-	needComma := false
-	for {
-		tok := p.scan()
-		if needComma {
-			switch tok.Type {
-			case token.COMMA, token.RBRACK:
-			default:
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error parsing list, expected comma or list end, got: %s",
-						tok.Type),
-				}
-			}
-		}
-		switch tok.Type {
-		case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			// If there is a lead comment, apply it
-			if p.leadComment != nil {
-				node.LeadComment = p.leadComment
-				p.leadComment = nil
-			}
-
-			l.Add(node)
-			needComma = true
-		case token.COMMA:
-			// get next list item or we are at the end
-			// do a look-ahead for line comment
-			p.scan()
-			if p.lineComment != nil && len(l.List) > 0 {
-				lit, ok := l.List[len(l.List)-1].(*ast.LiteralType)
-				if ok {
-					lit.LineComment = p.lineComment
-					l.List[len(l.List)-1] = lit
-					p.lineComment = nil
-				}
-			}
-			p.unscan()
-
-			needComma = false
-			continue
-		case token.LBRACE:
-			// Looks like a nested object, so parse it out
-			node, err := p.objectType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse object within list: %s", err),
-				}
-			}
-			l.Add(node)
-			needComma = true
-		case token.LBRACK:
-			node, err := p.listType()
-			if err != nil {
-				return nil, &PosError{
-					Pos: tok.Pos,
-					Err: fmt.Errorf(
-						"error while trying to parse list within list: %s", err),
-				}
-			}
-			l.Add(node)
-		case token.RBRACK:
-			// finished
-			l.Rbrack = p.tok.Pos
-			return l, nil
-		default:
-			return nil, &PosError{
-				Pos: tok.Pos,
-				Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type),
-			}
-		}
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok,
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead. In the process, it collects any
-// comment groups encountered, and remembers the last lead and line comments.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	// Otherwise read the next token from the scanner and Save it to the buffer
-	// in case we unscan later.
-	prev := p.tok
-	p.tok = p.sc.Scan()
-
-	if p.tok.Type == token.COMMENT {
-		var comment *ast.CommentGroup
-		var endline int
-
-		// fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n",
-		// p.tok.Pos.Line, prev.Pos.Line, endline)
-		if p.tok.Pos.Line == prev.Pos.Line {
-			// The comment is on same line as the previous token; it
-			// cannot be a lead comment but may be a line comment.
-			comment, endline = p.consumeCommentGroup(0)
-			if p.tok.Pos.Line != endline {
-				// The next token is on a different line, thus
-				// the last comment group is a line comment.
-				p.lineComment = comment
-			}
-		}
-
-		// consume successor comments, if any
-		endline = -1
-		for p.tok.Type == token.COMMENT {
-			comment, endline = p.consumeCommentGroup(1)
-		}
-
-		if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE {
-			switch p.tok.Type {
-			case token.RBRACE, token.RBRACK:
-				// Do not count for these cases
-			default:
-				// The next token is following on the line immediately after the
-				// comment group, thus the last comment group is a lead comment.
-				p.leadComment = comment
-			}
-		}
-
-	}
-
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
deleted file mode 100644
index 7c038d12..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go
+++ /dev/null
@@ -1,789 +0,0 @@
-package printer
-
-import (
-	"bytes"
-	"fmt"
-	"sort"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-const (
-	blank    = byte(' ')
-	newline  = byte('\n')
-	tab      = byte('\t')
-	infinity = 1 << 30 // offset or line
-)
-
-var (
-	unindent = []byte("\uE123") // in the private use space
-)
-
-type printer struct {
-	cfg  Config
-	prev token.Pos
-
-	comments           []*ast.CommentGroup // may be nil, contains all comments
-	standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node)
-
-	enableTrace bool
-	indentTrace int
-}
-
-type ByPosition []*ast.CommentGroup
-
-func (b ByPosition) Len() int           { return len(b) }
-func (b ByPosition) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
-func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) }
-
-// collectComments comments all standalone comments which are not lead or line
-// comment
-func (p *printer) collectComments(node ast.Node) {
-	// first collect all comments. This is already stored in
-	// ast.File.(comments)
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.File:
-			p.comments = t.Comments
-			return nn, false
-		}
-		return nn, true
-	})
-
-	standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0)
-	for _, c := range p.comments {
-		standaloneComments[c.Pos()] = c
-	}
-
-	// next remove all lead and line comments from the overall comment map.
-	// This will give us comments which are standalone, comments which are not
-	// assigned to any kind of node.
-	ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
-		switch t := nn.(type) {
-		case *ast.LiteralType:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		case *ast.ObjectItem:
-			if t.LeadComment != nil {
-				for _, comment := range t.LeadComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-
-			if t.LineComment != nil {
-				for _, comment := range t.LineComment.List {
-					if _, ok := standaloneComments[comment.Pos()]; ok {
-						delete(standaloneComments, comment.Pos())
-					}
-				}
-			}
-		}
-
-		return nn, true
-	})
-
-	for _, c := range standaloneComments {
-		p.standaloneComments = append(p.standaloneComments, c)
-	}
-
-	sort.Sort(ByPosition(p.standaloneComments))
-}
-
-// output prints creates b printable HCL output and returns it.
-func (p *printer) output(n interface{}) []byte {
-	var buf bytes.Buffer
-
-	switch t := n.(type) {
-	case *ast.File:
-		// File doesn't trace so we add the tracing here
-		defer un(trace(p, "File"))
-		return p.output(t.Node)
-	case *ast.ObjectList:
-		defer un(trace(p, "ObjectList"))
-
-		var index int
-		for {
-			// Determine the location of the next actual non-comment
-			// item. If we're at the end, the next item is at "infinity"
-			var nextItem token.Pos
-			if index != len(t.Items) {
-				nextItem = t.Items[index].Pos()
-			} else {
-				nextItem = token.Pos{Offset: infinity, Line: infinity}
-			}
-
-			// Go through the standalone comments in the file and print out
-			// the comments that we should be for this object item.
-			for _, c := range p.standaloneComments {
-				// Go through all the comments in the group. The group
-				// should be printed together, not separated by double newlines.
-				printed := false
-				newlinePrinted := false
-				for _, comment := range c.List {
-					// We only care about comments after the previous item
-					// we've printed so that comments are printed in the
-					// correct locations (between two objects for example).
-					// And before the next item.
-					if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-						// if we hit the end add newlines so we can print the comment
-						// we don't do this if prev is invalid which means the
-						// beginning of the file since the first comment should
-						// be at the first line.
-						if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) {
-							buf.Write([]byte{newline, newline})
-							newlinePrinted = true
-						}
-
-						// Write the actual comment.
-						buf.WriteString(comment.Text)
-						buf.WriteByte(newline)
-
-						// Set printed to true to note that we printed something
-						printed = true
-					}
-				}
-
-				// If we're not at the last item, write a new line so
-				// that there is a newline separating this comment from
-				// the next object.
-				if printed && index != len(t.Items) {
-					buf.WriteByte(newline)
-				}
-			}
-
-			if index == len(t.Items) {
-				break
-			}
-
-			buf.Write(p.output(t.Items[index]))
-			if index != len(t.Items)-1 {
-				// Always write a newline to separate us from the next item
-				buf.WriteByte(newline)
-
-				// Need to determine if we're going to separate the next item
-				// with a blank line. The logic here is simple, though there
-				// are a few conditions:
-				//
-				//   1. The next object is more than one line away anyways,
-				//      so we need an empty line.
-				//
-				//   2. The next object is not a "single line" object, so
-				//      we need an empty line.
-				//
-				//   3. This current object is not a single line object,
-				//      so we need an empty line.
-				current := t.Items[index]
-				next := t.Items[index+1]
-				if next.Pos().Line != t.Items[index].Pos().Line+1 ||
-					!p.isSingleLineObject(next) ||
-					!p.isSingleLineObject(current) {
-					buf.WriteByte(newline)
-				}
-			}
-			index++
-		}
-	case *ast.ObjectKey:
-		buf.WriteString(t.Token.Text)
-	case *ast.ObjectItem:
-		p.prev = t.Pos()
-		buf.Write(p.objectItem(t))
-	case *ast.LiteralType:
-		buf.Write(p.literalType(t))
-	case *ast.ListType:
-		buf.Write(p.list(t))
-	case *ast.ObjectType:
-		buf.Write(p.objectType(t))
-	default:
-		fmt.Printf(" unknown type: %T\n", n)
-	}
-
-	return buf.Bytes()
-}
-
-func (p *printer) literalType(lit *ast.LiteralType) []byte {
-	result := []byte(lit.Token.Text)
-	switch lit.Token.Type {
-	case token.HEREDOC:
-		// Clear the trailing newline from heredocs
-		if result[len(result)-1] == '\n' {
-			result = result[:len(result)-1]
-		}
-
-		// Poison lines 2+ so that we don't indent them
-		result = p.heredocIndent(result)
-	case token.STRING:
-		// If this is a multiline string, poison lines 2+ so we don't
-		// indent them.
-		if bytes.IndexRune(result, '\n') >= 0 {
-			result = p.heredocIndent(result)
-		}
-	}
-
-	return result
-}
-
-// objectItem returns the printable HCL form of an object item. An object type
-// starts with one/multiple keys and has a value. The value might be of any
-// type.
-func (p *printer) objectItem(o *ast.ObjectItem) []byte {
-	defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text)))
-	var buf bytes.Buffer
-
-	if o.LeadComment != nil {
-		for _, comment := range o.LeadComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	// If key and val are on different lines, treat line comments like lead comments.
-	if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line {
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-			buf.WriteByte(newline)
-		}
-	}
-
-	for i, k := range o.Keys {
-		buf.WriteString(k.Token.Text)
-		buf.WriteByte(blank)
-
-		// reach end of key
-		if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 {
-			buf.WriteString("=")
-			buf.WriteByte(blank)
-		}
-	}
-
-	buf.Write(p.output(o.Val))
-
-	if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line {
-		buf.WriteByte(blank)
-		for _, comment := range o.LineComment.List {
-			buf.WriteString(comment.Text)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// objectType returns the printable HCL form of an object type. An object type
-// begins with a brace and ends with a brace.
-func (p *printer) objectType(o *ast.ObjectType) []byte {
-	defer un(trace(p, "ObjectType"))
-	var buf bytes.Buffer
-	buf.WriteString("{")
-
-	var index int
-	var nextItem token.Pos
-	var commented, newlinePrinted bool
-	for {
-		// Determine the location of the next actual non-comment
-		// item. If we're at the end, the next item is the closing brace
-		if index != len(o.List.Items) {
-			nextItem = o.List.Items[index].Pos()
-		} else {
-			nextItem = o.Rbrace
-		}
-
-		// Go through the standalone comments in the file and print out
-		// the comments that we should be for this object item.
-		for _, c := range p.standaloneComments {
-			printed := false
-			var lastCommentPos token.Pos
-			for _, comment := range c.List {
-				// We only care about comments after the previous item
-				// we've printed so that comments are printed in the
-				// correct locations (between two objects for example).
-				// And before the next item.
-				if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
-					// If there are standalone comments and the initial newline has not
-					// been printed yet, do it now.
-					if !newlinePrinted {
-						newlinePrinted = true
-						buf.WriteByte(newline)
-					}
-
-					// add newline if it's between other printed nodes
-					if index > 0 {
-						commented = true
-						buf.WriteByte(newline)
-					}
-
-					// Store this position
-					lastCommentPos = comment.Pos()
-
-					// output the comment itself
-					buf.Write(p.indent(p.heredocIndent([]byte(comment.Text))))
-
-					// Set printed to true to note that we printed something
-					printed = true
-
-					/*
-						if index != len(o.List.Items) {
-							buf.WriteByte(newline) // do not print on the end
-						}
-					*/
-				}
-			}
-
-			// Stuff to do if we had comments
-			if printed {
-				// Always write a newline
-				buf.WriteByte(newline)
-
-				// If there is another item in the object and our comment
-				// didn't hug it directly, then make sure there is a blank
-				// line separating them.
-				if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 {
-					buf.WriteByte(newline)
-				}
-			}
-		}
-
-		if index == len(o.List.Items) {
-			p.prev = o.Rbrace
-			break
-		}
-
-		// At this point we are sure that it's not a totally empty block: print
-		// the initial newline if it hasn't been printed yet by the previous
-		// block about standalone comments.
-		if !newlinePrinted {
-			buf.WriteByte(newline)
-			newlinePrinted = true
-		}
-
-		// check if we have adjacent one liner items. If yes we'll going to align
-		// the comments.
-		var aligned []*ast.ObjectItem
-		for _, item := range o.List.Items[index:] {
-			// we don't group one line lists
-			if len(o.List.Items) == 1 {
-				break
-			}
-
-			// one means a oneliner with out any lead comment
-			// two means a oneliner with lead comment
-			// anything else might be something else
-			cur := lines(string(p.objectItem(item)))
-			if cur > 2 {
-				break
-			}
-
-			curPos := item.Pos()
-
-			nextPos := token.Pos{}
-			if index != len(o.List.Items)-1 {
-				nextPos = o.List.Items[index+1].Pos()
-			}
-
-			prevPos := token.Pos{}
-			if index != 0 {
-				prevPos = o.List.Items[index-1].Pos()
-			}
-
-			// fmt.Println("DEBUG ----------------")
-			// fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos)
-			// fmt.Printf("cur = %+v curPos: %s\n", cur, curPos)
-			// fmt.Printf("next = %+v nextPos: %s\n", next, nextPos)
-
-			if curPos.Line+1 == nextPos.Line {
-				aligned = append(aligned, item)
-				index++
-				continue
-			}
-
-			if curPos.Line-1 == prevPos.Line {
-				aligned = append(aligned, item)
-				index++
-
-				// finish if we have a new line or comment next. This happens
-				// if the next item is not adjacent
-				if curPos.Line+1 != nextPos.Line {
-					break
-				}
-				continue
-			}
-
-			break
-		}
-
-		// put newlines if the items are between other non aligned items.
-		// newlines are also added if there is a standalone comment already, so
-		// check it too
-		if !commented && index != len(aligned) {
-			buf.WriteByte(newline)
-		}
-
-		if len(aligned) >= 1 {
-			p.prev = aligned[len(aligned)-1].Pos()
-
-			items := p.alignedItems(aligned)
-			buf.Write(p.indent(items))
-		} else {
-			p.prev = o.List.Items[index].Pos()
-
-			buf.Write(p.indent(p.objectItem(o.List.Items[index])))
-			index++
-		}
-
-		buf.WriteByte(newline)
-	}
-
-	buf.WriteString("}")
-	return buf.Bytes()
-}
-
-func (p *printer) alignedItems(items []*ast.ObjectItem) []byte {
-	var buf bytes.Buffer
-
-	// find the longest key and value length, needed for alignment
-	var longestKeyLen int // longest key length
-	var longestValLen int // longest value length
-	for _, item := range items {
-		key := len(item.Keys[0].Token.Text)
-		val := len(p.output(item.Val))
-
-		if key > longestKeyLen {
-			longestKeyLen = key
-		}
-
-		if val > longestValLen {
-			longestValLen = val
-		}
-	}
-
-	for i, item := range items {
-		if item.LeadComment != nil {
-			for _, comment := range item.LeadComment.List {
-				buf.WriteString(comment.Text)
-				buf.WriteByte(newline)
-			}
-		}
-
-		for i, k := range item.Keys {
-			keyLen := len(k.Token.Text)
-			buf.WriteString(k.Token.Text)
-			for i := 0; i < longestKeyLen-keyLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			// reach end of key
-			if i == len(item.Keys)-1 && len(item.Keys) == 1 {
-				buf.WriteString("=")
-				buf.WriteByte(blank)
-			}
-		}
-
-		val := p.output(item.Val)
-		valLen := len(val)
-		buf.Write(val)
-
-		if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil {
-			for i := 0; i < longestValLen-valLen+1; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range item.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		// do not print for the last item
-		if i != len(items)-1 {
-			buf.WriteByte(newline)
-		}
-	}
-
-	return buf.Bytes()
-}
-
-// list returns the printable HCL form of an list type.
-func (p *printer) list(l *ast.ListType) []byte {
-	if p.isSingleLineList(l) {
-		return p.singleLineList(l)
-	}
-
-	var buf bytes.Buffer
-	buf.WriteString("[")
-	buf.WriteByte(newline)
-
-	var longestLine int
-	for _, item := range l.List {
-		// for now we assume that the list only contains literal types
-		if lit, ok := item.(*ast.LiteralType); ok {
-			lineLen := len(lit.Token.Text)
-			if lineLen > longestLine {
-				longestLine = lineLen
-			}
-		}
-	}
-
-	haveEmptyLine := false
-	for i, item := range l.List {
-		// If we have a lead comment, then we want to write that first
-		leadComment := false
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil {
-			leadComment = true
-
-			// Ensure an empty line before every element with a
-			// lead comment (except the first item in a list).
-			if !haveEmptyLine && i != 0 {
-				buf.WriteByte(newline)
-			}
-
-			for _, comment := range lit.LeadComment.List {
-				buf.Write(p.indent([]byte(comment.Text)))
-				buf.WriteByte(newline)
-			}
-		}
-
-		// also indent each line
-		val := p.output(item)
-		curLen := len(val)
-		buf.Write(p.indent(val))
-
-		// if this item is a heredoc, then we output the comma on
-		// the next line. This is the only case this happens.
-		comma := []byte{','}
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-			comma = p.indent(comma)
-		}
-
-		buf.Write(comma)
-
-		if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil {
-			// if the next item doesn't have any comments, do not align
-			buf.WriteByte(blank) // align one space
-			for i := 0; i < longestLine-curLen; i++ {
-				buf.WriteByte(blank)
-			}
-
-			for _, comment := range lit.LineComment.List {
-				buf.WriteString(comment.Text)
-			}
-		}
-
-		buf.WriteByte(newline)
-
-		// Ensure an empty line after every element with a
-		// lead comment (except the first item in a list).
-		haveEmptyLine = leadComment && i != len(l.List)-1
-		if haveEmptyLine {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// isSingleLineList returns true if:
-// * they were previously formatted entirely on one line
-// * they consist entirely of literals
-// * there are either no heredoc strings or the list has exactly one element
-// * there are no line comments
-func (printer) isSingleLineList(l *ast.ListType) bool {
-	for _, item := range l.List {
-		if item.Pos().Line != l.Lbrack.Line {
-			return false
-		}
-
-		lit, ok := item.(*ast.LiteralType)
-		if !ok {
-			return false
-		}
-
-		if lit.Token.Type == token.HEREDOC && len(l.List) != 1 {
-			return false
-		}
-
-		if lit.LineComment != nil {
-			return false
-		}
-	}
-
-	return true
-}
-
-// singleLineList prints a simple single line list.
-// For a definition of "simple", see isSingleLineList above.
-func (p *printer) singleLineList(l *ast.ListType) []byte {
-	buf := &bytes.Buffer{}
-
-	buf.WriteString("[")
-	for i, item := range l.List {
-		if i != 0 {
-			buf.WriteString(", ")
-		}
-
-		// Output the item itself
-		buf.Write(p.output(item))
-
-		// The heredoc marker needs to be at the end of line.
-		if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC {
-			buf.WriteByte(newline)
-		}
-	}
-
-	buf.WriteString("]")
-	return buf.Bytes()
-}
-
-// indent indents the lines of the given buffer for each non-empty line
-func (p *printer) indent(buf []byte) []byte {
-	var prefix []byte
-	if p.cfg.SpacesWidth != 0 {
-		for i := 0; i < p.cfg.SpacesWidth; i++ {
-			prefix = append(prefix, blank)
-		}
-	} else {
-		prefix = []byte{tab}
-	}
-
-	var res []byte
-	bol := true
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, prefix...)
-		}
-
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// unindent removes all the indentation from the tombstoned lines
-func (p *printer) unindent(buf []byte) []byte {
-	var res []byte
-	for i := 0; i < len(buf); i++ {
-		skip := len(buf)-i <= len(unindent)
-		if !skip {
-			skip = !bytes.Equal(unindent, buf[i:i+len(unindent)])
-		}
-		if skip {
-			res = append(res, buf[i])
-			continue
-		}
-
-		// We have a marker. we have to backtrace here and clean out
-		// any whitespace ahead of our tombstone up to a \n
-		for j := len(res) - 1; j >= 0; j-- {
-			if res[j] == '\n' {
-				break
-			}
-
-			res = res[:j]
-		}
-
-		// Skip the entire unindent marker
-		i += len(unindent) - 1
-	}
-
-	return res
-}
-
-// heredocIndent marks all the 2nd and further lines as unindentable
-func (p *printer) heredocIndent(buf []byte) []byte {
-	var res []byte
-	bol := false
-	for _, c := range buf {
-		if bol && c != '\n' {
-			res = append(res, unindent...)
-		}
-		res = append(res, c)
-		bol = c == '\n'
-	}
-	return res
-}
-
-// isSingleLineObject tells whether the given object item is a single
-// line object such as "obj {}".
-//
-// A single line object:
-//
-//   * has no lead comments (hence multi-line)
-//   * has no assignment
-//   * has no values in the stanza (within {})
-//
-func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool {
-	// If there is a lead comment, can't be one line
-	if val.LeadComment != nil {
-		return false
-	}
-
-	// If there is assignment, we always break by line
-	if val.Assign.IsValid() {
-		return false
-	}
-
-	// If it isn't an object type, then its not a single line object
-	ot, ok := val.Val.(*ast.ObjectType)
-	if !ok {
-		return false
-	}
-
-	// If the object has no items, it is single line!
-	return len(ot.List.Items) == 0
-}
-
-func lines(txt string) int {
-	endline := 1
-	for i := 0; i < len(txt); i++ {
-		if txt[i] == '\n' {
-			endline++
-		}
-	}
-	return endline
-}
-
-// ----------------------------------------------------------------------------
-// Tracing support
-
-func (p *printer) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	i := 2 * p.indentTrace
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *printer, msg string) *printer {
-	p.printTrace(msg, "(")
-	p.indentTrace++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *printer) {
-	p.indentTrace--
-	p.printTrace(")")
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
deleted file mode 100644
index 6617ab8e..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Package printer implements printing of AST nodes to HCL format.
-package printer
-
-import (
-	"bytes"
-	"io"
-	"text/tabwriter"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	"github.com/hashicorp/hcl/hcl/parser"
-)
-
-var DefaultConfig = Config{
-	SpacesWidth: 2,
-}
-
-// A Config node controls the output of Fprint.
-type Config struct {
-	SpacesWidth int // if set, it will use spaces instead of tabs for alignment
-}
-
-func (c *Config) Fprint(output io.Writer, node ast.Node) error {
-	p := &printer{
-		cfg:                *c,
-		comments:           make([]*ast.CommentGroup, 0),
-		standaloneComments: make([]*ast.CommentGroup, 0),
-		// enableTrace:        true,
-	}
-
-	p.collectComments(node)
-
-	if _, err := output.Write(p.unindent(p.output(node))); err != nil {
-		return err
-	}
-
-	// flush tabwriter, if any
-	var err error
-	if tw, _ := output.(*tabwriter.Writer); tw != nil {
-		err = tw.Flush()
-	}
-
-	return err
-}
-
-// Fprint "pretty-prints" an HCL node to output
-// It calls Config.Fprint with default settings.
-func Fprint(output io.Writer, node ast.Node) error {
-	return DefaultConfig.Fprint(output, node)
-}
-
-// Format formats src HCL and returns the result.
-func Format(src []byte) ([]byte, error) {
-	node, err := parser.Parse(src)
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-	if err := DefaultConfig.Fprint(&buf, node); err != nil {
-		return nil, err
-	}
-
-	// Add trailing newline to result
-	buf.WriteString("\n")
-	return buf.Bytes(), nil
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
deleted file mode 100644
index 624a18fe..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go
+++ /dev/null
@@ -1,652 +0,0 @@
-// Package scanner implements a scanner for HCL (HashiCorp Configuration
-// Language) source text.
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"regexp"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/hcl/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == utf8.RuneError && size == 1 {
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	if ch == '\x00' {
-		s.err("unexpected null character (0x00)")
-		return eof
-	}
-
-	if ch == '\uE123' {
-		s.err("unicode code point U+E123 reserved for internal use")
-		return utf8.RuneError
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		tok = token.IDENT
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '#', '/':
-			tok = token.COMMENT
-			s.scanComment(ch)
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '<':
-			tok = token.HEREDOC
-			s.scanHeredoc()
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case '=':
-			tok = token.ASSIGN
-		case '+':
-			tok = token.ADD
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				tok = token.SUB
-			}
-		default:
-			s.err("illegal char")
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-func (s *Scanner) scanComment(ch rune) {
-	// single line comments
-	if ch == '#' || (ch == '/' && s.peek() != '*') {
-		if ch == '/' && s.peek() != '/' {
-			s.err("expected '/' for comment")
-			return
-		}
-
-		ch = s.next()
-		for ch != '\n' && ch >= 0 && ch != eof {
-			ch = s.next()
-		}
-		if ch != eof && ch >= 0 {
-			s.unread()
-		}
-		return
-	}
-
-	// be sure we get the character after /* This allows us to find comment's
-	// that are not erminated
-	if ch == '/' {
-		s.next()
-		ch = s.next() // read character after "/*"
-	}
-
-	// look for /* - style comments
-	for {
-		if ch < 0 || ch == eof {
-			s.err("comment not terminated")
-			break
-		}
-
-		ch0 := ch
-		ch = s.next()
-		if ch0 == '*' && ch == '/' {
-			break
-		}
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	if ch == '0' {
-		// check for hexadecimal, octal or float
-		ch = s.next()
-		if ch == 'x' || ch == 'X' {
-			// hexadecimal
-			ch = s.next()
-			found := false
-			for isHexadecimal(ch) {
-				ch = s.next()
-				found = true
-			}
-
-			if !found {
-				s.err("illegal hexadecimal number")
-			}
-
-			if ch != eof {
-				s.unread()
-			}
-
-			return token.NUMBER
-		}
-
-		// now it's either something like: 0421(octal) or 0.1231(float)
-		illegalOctal := false
-		for isDecimal(ch) {
-			ch = s.next()
-			if ch == '8' || ch == '9' {
-				// this is just a possibility. For example 0159 is illegal, but
-				// 0159.23 is valid. So we mark a possible illegal octal. If
-				// the next character is not a period, we'll print the error.
-				illegalOctal = true
-			}
-		}
-
-		if ch == 'e' || ch == 'E' {
-			ch = s.scanExponent(ch)
-			return token.FLOAT
-		}
-
-		if ch == '.' {
-			ch = s.scanFraction(ch)
-
-			if ch == 'e' || ch == 'E' {
-				ch = s.next()
-				ch = s.scanExponent(ch)
-			}
-			return token.FLOAT
-		}
-
-		if illegalOctal {
-			s.err("illegal octal number")
-		}
-
-		if ch != eof {
-			s.unread()
-		}
-		return token.NUMBER
-	}
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanHeredoc scans a heredoc string
-func (s *Scanner) scanHeredoc() {
-	// Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) {
-				break
-			}
-
-			// Not an anchor match, record the start of a new line
-			lineStart = s.srcPos.Offset
-		}
-
-		if ch == eof {
-			s.err("heredoc not terminated")
-			return
-		}
-	}
-
-	return
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if (ch == '\n' && braces == 0) || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' && braces == 0 {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	start := n
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		if ch == eof {
-			// If we see an EOF, we halt any more scanning of digits
-			// immediately.
-			break
-		}
-
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	if n != start && ch != eof {
-		// we scanned all digits, put the last non digit char back,
-		// only if we read anything at all
-		s.unread()
-	}
-
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isDigit returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isDecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
deleted file mode 100644
index 5f981eaa..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package strconv
-
-import (
-	"errors"
-	"unicode/utf8"
-)
-
-// ErrSyntax indicates that a value does not have the right syntax for the target type.
-var ErrSyntax = errors.New("invalid syntax")
-
-// Unquote interprets s as a single-quoted, double-quoted,
-// or backquoted Go string literal, returning the string value
-// that s quotes.  (If s is single-quoted, it would be a Go
-// character literal; Unquote returns the corresponding
-// one-character string.)
-func Unquote(s string) (t string, err error) {
-	n := len(s)
-	if n < 2 {
-		return "", ErrSyntax
-	}
-	quote := s[0]
-	if quote != s[n-1] {
-		return "", ErrSyntax
-	}
-	s = s[1 : n-1]
-
-	if quote != '"' {
-		return "", ErrSyntax
-	}
-	if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') {
-		return "", ErrSyntax
-	}
-
-	// Is it trivial?  Avoid allocation.
-	if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
-		switch quote {
-		case '"':
-			return s, nil
-		case '\'':
-			r, size := utf8.DecodeRuneInString(s)
-			if size == len(s) && (r != utf8.RuneError || size != 1) {
-				return s, nil
-			}
-		}
-	}
-
-	var runeTmp [utf8.UTFMax]byte
-	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
-	for len(s) > 0 {
-		// If we're starting a '${}' then let it through un-unquoted.
-		// Specifically: we don't unquote any characters within the `${}`
-		// section.
-		if s[0] == '$' && len(s) > 1 && s[1] == '{' {
-			buf = append(buf, '$', '{')
-			s = s[2:]
-
-			// Continue reading until we find the closing brace, copying as-is
-			braces := 1
-			for len(s) > 0 && braces > 0 {
-				r, size := utf8.DecodeRuneInString(s)
-				if r == utf8.RuneError {
-					return "", ErrSyntax
-				}
-
-				s = s[size:]
-
-				n := utf8.EncodeRune(runeTmp[:], r)
-				buf = append(buf, runeTmp[:n]...)
-
-				switch r {
-				case '{':
-					braces++
-				case '}':
-					braces--
-				}
-			}
-			if braces != 0 {
-				return "", ErrSyntax
-			}
-			if len(s) == 0 {
-				// If there's no string left, we're done!
-				break
-			} else {
-				// If there's more left, we need to pop back up to the top of the loop
-				// in case there's another interpolation in this string.
-				continue
-			}
-		}
-
-		if s[0] == '\n' {
-			return "", ErrSyntax
-		}
-
-		c, multibyte, ss, err := unquoteChar(s, quote)
-		if err != nil {
-			return "", err
-		}
-		s = ss
-		if c < utf8.RuneSelf || !multibyte {
-			buf = append(buf, byte(c))
-		} else {
-			n := utf8.EncodeRune(runeTmp[:], c)
-			buf = append(buf, runeTmp[:n]...)
-		}
-		if quote == '\'' && len(s) != 0 {
-			// single-quoted must be single character
-			return "", ErrSyntax
-		}
-	}
-	return string(buf), nil
-}
-
-// contains reports whether the string contains the byte c.
-func contains(s string, c byte) bool {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			return true
-		}
-	}
-	return false
-}
-
-func unhex(b byte) (v rune, ok bool) {
-	c := rune(b)
-	switch {
-	case '0' <= c && c <= '9':
-		return c - '0', true
-	case 'a' <= c && c <= 'f':
-		return c - 'a' + 10, true
-	case 'A' <= c && c <= 'F':
-		return c - 'A' + 10, true
-	}
-	return
-}
-
-func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
-	// easy cases
-	switch c := s[0]; {
-	case c == quote && (quote == '\'' || quote == '"'):
-		err = ErrSyntax
-		return
-	case c >= utf8.RuneSelf:
-		r, size := utf8.DecodeRuneInString(s)
-		return r, true, s[size:], nil
-	case c != '\\':
-		return rune(s[0]), false, s[1:], nil
-	}
-
-	// hard case: c is backslash
-	if len(s) <= 1 {
-		err = ErrSyntax
-		return
-	}
-	c := s[1]
-	s = s[2:]
-
-	switch c {
-	case 'a':
-		value = '\a'
-	case 'b':
-		value = '\b'
-	case 'f':
-		value = '\f'
-	case 'n':
-		value = '\n'
-	case 'r':
-		value = '\r'
-	case 't':
-		value = '\t'
-	case 'v':
-		value = '\v'
-	case 'x', 'u', 'U':
-		n := 0
-		switch c {
-		case 'x':
-			n = 2
-		case 'u':
-			n = 4
-		case 'U':
-			n = 8
-		}
-		var v rune
-		if len(s) < n {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < n; j++ {
-			x, ok := unhex(s[j])
-			if !ok {
-				err = ErrSyntax
-				return
-			}
-			v = v<<4 | x
-		}
-		s = s[n:]
-		if c == 'x' {
-			// single-byte string, possibly not UTF-8
-			value = v
-			break
-		}
-		if v > utf8.MaxRune {
-			err = ErrSyntax
-			return
-		}
-		value = v
-		multibyte = true
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		v := rune(c) - '0'
-		if len(s) < 2 {
-			err = ErrSyntax
-			return
-		}
-		for j := 0; j < 2; j++ { // one digit already; two more
-			x := rune(s[j]) - '0'
-			if x < 0 || x > 7 {
-				err = ErrSyntax
-				return
-			}
-			v = (v << 3) | x
-		}
-		s = s[2:]
-		if v > 255 {
-			err = ErrSyntax
-			return
-		}
-		value = v
-	case '\\':
-		value = '\\'
-	case '\'', '"':
-		if c != quote {
-			err = ErrSyntax
-			return
-		}
-		value = rune(c)
-	default:
-		err = ErrSyntax
-		return
-	}
-	tail = s
-	return
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/public-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go
deleted file mode 100644
index e37c0664..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/hcl/token/token.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Package token defines constants representing the lexical tokens for HCL
-// (HashiCorp Configuration Language)
-package token
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-
-	hclstrconv "github.com/hashicorp/hcl/hcl/strconv"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-	JSON bool
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-	COMMENT
-
-	identifier_beg
-	IDENT // literals
-	literal_beg
-	NUMBER  // 12345
-	FLOAT   // 123.45
-	BOOL    // true,false
-	STRING  // "abc"
-	HEREDOC // < 0 {
-			// Pop the current item
-			n := len(frontier)
-			item := frontier[n-1]
-			frontier = frontier[:n-1]
-
-			switch v := item.Val.(type) {
-			case *ast.ObjectType:
-				items, frontier = flattenObjectType(v, item, items, frontier)
-			case *ast.ListType:
-				items, frontier = flattenListType(v, item, items, frontier)
-			default:
-				items = append(items, item)
-			}
-		}
-
-		// Reverse the list since the frontier model runs things backwards
-		for i := len(items)/2 - 1; i >= 0; i-- {
-			opp := len(items) - 1 - i
-			items[i], items[opp] = items[opp], items[i]
-		}
-
-		// Done! Set the original items
-		list.Items = items
-		return n, true
-	})
-}
-
-func flattenListType(
-	ot *ast.ListType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list is empty, keep the original list
-	if len(ot.List) == 0 {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List {
-		if _, ok := subitem.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, elem := range ot.List {
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        item.Keys,
-			Assign:      item.Assign,
-			Val:         elem,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
-
-func flattenObjectType(
-	ot *ast.ObjectType,
-	item *ast.ObjectItem,
-	items []*ast.ObjectItem,
-	frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
-	// If the list has no items we do not have to flatten anything
-	if ot.List.Items == nil {
-		items = append(items, item)
-		return items, frontier
-	}
-
-	// All the elements of this object must also be objects!
-	for _, subitem := range ot.List.Items {
-		if _, ok := subitem.Val.(*ast.ObjectType); !ok {
-			items = append(items, item)
-			return items, frontier
-		}
-	}
-
-	// Great! We have a match go through all the items and flatten
-	for _, subitem := range ot.List.Items {
-		// Copy the new key
-		keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
-		copy(keys, item.Keys)
-		copy(keys[len(item.Keys):], subitem.Keys)
-
-		// Add it to the frontier so that we can recurse
-		frontier = append(frontier, &ast.ObjectItem{
-			Keys:        keys,
-			Assign:      item.Assign,
-			Val:         subitem.Val,
-			LeadComment: item.LeadComment,
-			LineComment: item.LineComment,
-		})
-	}
-
-	return items, frontier
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/public-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go
deleted file mode 100644
index 125a5f07..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/json/parser/parser.go
+++ /dev/null
@@ -1,313 +0,0 @@
-package parser
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-	"github.com/hashicorp/hcl/json/scanner"
-	"github.com/hashicorp/hcl/json/token"
-)
-
-type Parser struct {
-	sc *scanner.Scanner
-
-	// Last read token
-	tok       token.Token
-	commaPrev token.Token
-
-	enableTrace bool
-	indent      int
-	n           int // buffer size (max = 1)
-}
-
-func newParser(src []byte) *Parser {
-	return &Parser{
-		sc: scanner.New(src),
-	}
-}
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func Parse(src []byte) (*ast.File, error) {
-	p := newParser(src)
-	return p.Parse()
-}
-
-var errEofToken = errors.New("EOF token found")
-
-// Parse returns the fully parsed source and returns the abstract syntax tree.
-func (p *Parser) Parse() (*ast.File, error) {
-	f := &ast.File{}
-	var err, scerr error
-	p.sc.Error = func(pos token.Pos, msg string) {
-		scerr = fmt.Errorf("%s: %s", pos, msg)
-	}
-
-	// The root must be an object in JSON
-	object, err := p.object()
-	if scerr != nil {
-		return nil, scerr
-	}
-	if err != nil {
-		return nil, err
-	}
-
-	// We make our final node an object list so it is more HCL compatible
-	f.Node = object.List
-
-	// Flatten it, which finds patterns and turns them into more HCL-like
-	// AST trees.
-	flattenObjects(f.Node)
-
-	return f, nil
-}
-
-func (p *Parser) objectList() (*ast.ObjectList, error) {
-	defer un(trace(p, "ParseObjectList"))
-	node := &ast.ObjectList{}
-
-	for {
-		n, err := p.objectItem()
-		if err == errEofToken {
-			break // we are finished
-		}
-
-		// we don't return a nil node, because might want to use already
-		// collected items.
-		if err != nil {
-			return node, err
-		}
-
-		node.Add(n)
-
-		// Check for a followup comma. If it isn't a comma, then we're done
-		if tok := p.scan(); tok.Type != token.COMMA {
-			break
-		}
-	}
-
-	return node, nil
-}
-
-// objectItem parses a single object item
-func (p *Parser) objectItem() (*ast.ObjectItem, error) {
-	defer un(trace(p, "ParseObjectItem"))
-
-	keys, err := p.objectKey()
-	if err != nil {
-		return nil, err
-	}
-
-	o := &ast.ObjectItem{
-		Keys: keys,
-	}
-
-	switch p.tok.Type {
-	case token.COLON:
-		pos := p.tok.Pos
-		o.Assign = hcltoken.Pos{
-			Filename: pos.Filename,
-			Offset:   pos.Offset,
-			Line:     pos.Line,
-			Column:   pos.Column,
-		}
-
-		o.Val, err = p.objectValue()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return o, nil
-}
-
-// objectKey parses an object key and returns a ObjectKey AST
-func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
-	keyCount := 0
-	keys := make([]*ast.ObjectKey, 0)
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.EOF:
-			return nil, errEofToken
-		case token.STRING:
-			keyCount++
-			keys = append(keys, &ast.ObjectKey{
-				Token: p.tok.HCLToken(),
-			})
-		case token.COLON:
-			// If we have a zero keycount it means that we never got
-			// an object key, i.e. `{ :`. This is a syntax error.
-			if keyCount == 0 {
-				return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-			}
-
-			// Done
-			return keys, nil
-		case token.ILLEGAL:
-			return nil, errors.New("illegal")
-		default:
-			return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
-		}
-	}
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) objectValue() (ast.Node, error) {
-	defer un(trace(p, "ParseObjectValue"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING:
-		return p.literalType()
-	case token.LBRACE:
-		return p.objectType()
-	case token.LBRACK:
-		return p.listType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok)
-}
-
-// object parses any type of object, such as number, bool, string, object or
-// list.
-func (p *Parser) object() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseType"))
-	tok := p.scan()
-
-	switch tok.Type {
-	case token.LBRACE:
-		return p.objectType()
-	case token.EOF:
-		return nil, errEofToken
-	}
-
-	return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok)
-}
-
-// objectType parses an object type and returns a ObjectType AST
-func (p *Parser) objectType() (*ast.ObjectType, error) {
-	defer un(trace(p, "ParseObjectType"))
-
-	// we assume that the currently scanned token is a LBRACE
-	o := &ast.ObjectType{}
-
-	l, err := p.objectList()
-
-	// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
-	// not a RBRACE, it's an syntax error and we just return it.
-	if err != nil && p.tok.Type != token.RBRACE {
-		return nil, err
-	}
-
-	o.List = l
-	return o, nil
-}
-
-// listType parses a list type and returns a ListType AST
-func (p *Parser) listType() (*ast.ListType, error) {
-	defer un(trace(p, "ParseListType"))
-
-	// we assume that the currently scanned token is a LBRACK
-	l := &ast.ListType{}
-
-	for {
-		tok := p.scan()
-		switch tok.Type {
-		case token.NUMBER, token.FLOAT, token.STRING:
-			node, err := p.literalType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.COMMA:
-			continue
-		case token.LBRACE:
-			node, err := p.objectType()
-			if err != nil {
-				return nil, err
-			}
-
-			l.Add(node)
-		case token.BOOL:
-			// TODO(arslan) should we support? not supported by HCL yet
-		case token.LBRACK:
-			// TODO(arslan) should we support nested lists? Even though it's
-			// written in README of HCL, it's not a part of the grammar
-			// (not defined in parse.y)
-		case token.RBRACK:
-			// finished
-			return l, nil
-		default:
-			return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type)
-		}
-
-	}
-}
-
-// literalType parses a literal type and returns a LiteralType AST
-func (p *Parser) literalType() (*ast.LiteralType, error) {
-	defer un(trace(p, "ParseLiteral"))
-
-	return &ast.LiteralType{
-		Token: p.tok.HCLToken(),
-	}, nil
-}
-
-// scan returns the next token from the underlying scanner. If a token has
-// been unscanned then read that instead.
-func (p *Parser) scan() token.Token {
-	// If we have a token on the buffer, then return it.
-	if p.n != 0 {
-		p.n = 0
-		return p.tok
-	}
-
-	p.tok = p.sc.Scan()
-	return p.tok
-}
-
-// unscan pushes the previously read token back onto the buffer.
-func (p *Parser) unscan() {
-	p.n = 1
-}
-
-// ----------------------------------------------------------------------------
-// Parsing support
-
-func (p *Parser) printTrace(a ...interface{}) {
-	if !p.enableTrace {
-		return
-	}
-
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = len(dots)
-	fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
-
-	i := 2 * p.indent
-	for i > n {
-		fmt.Print(dots)
-		i -= n
-	}
-	// i <= n
-	fmt.Print(dots[0:i])
-	fmt.Println(a...)
-}
-
-func trace(p *Parser, msg string) *Parser {
-	p.printTrace(msg, "(")
-	p.indent++
-	return p
-}
-
-// Usage pattern: defer un(trace(p, "..."))
-func un(p *Parser) {
-	p.indent--
-	p.printTrace(")")
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/public-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
deleted file mode 100644
index fe3f0f09..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go
+++ /dev/null
@@ -1,451 +0,0 @@
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/hashicorp/hcl/json/token"
-)
-
-// eof represents a marker rune for the end of the reader.
-const eof = rune(0)
-
-// Scanner defines a lexical scanner
-type Scanner struct {
-	buf *bytes.Buffer // Source buffer for advancing and scanning
-	src []byte        // Source buffer for immutable access
-
-	// Source Position
-	srcPos  token.Pos // current position
-	prevPos token.Pos // previous position, used for peek() method
-
-	lastCharLen int // length of last character in bytes
-	lastLineLen int // length of last line in characters (for correct column reporting)
-
-	tokStart int // token text start position
-	tokEnd   int // token text end  position
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(pos token.Pos, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// tokPos is the start position of most recently scanned token; set by
-	// Scan. The Filename field is always left untouched by the Scanner.  If
-	// an error is reported (via Error) and Position is invalid, the scanner is
-	// not inside a token.
-	tokPos token.Pos
-}
-
-// New creates and initializes a new instance of Scanner using src as
-// its source content.
-func New(src []byte) *Scanner {
-	// even though we accept a src, we read from a io.Reader compatible type
-	// (*bytes.Buffer). So in the future we might easily change it to streaming
-	// read.
-	b := bytes.NewBuffer(src)
-	s := &Scanner{
-		buf: b,
-		src: src,
-	}
-
-	// srcPosition always starts with 1
-	s.srcPos.Line = 1
-	return s
-}
-
-// next reads the next rune from the bufferred reader. Returns the rune(0) if
-// an error occurs (or io.EOF is returned).
-func (s *Scanner) next() rune {
-	ch, size, err := s.buf.ReadRune()
-	if err != nil {
-		// advance for error reporting
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		return eof
-	}
-
-	if ch == utf8.RuneError && size == 1 {
-		s.srcPos.Column++
-		s.srcPos.Offset += size
-		s.lastCharLen = size
-		s.err("illegal UTF-8 encoding")
-		return ch
-	}
-
-	// remember last position
-	s.prevPos = s.srcPos
-
-	s.srcPos.Column++
-	s.lastCharLen = size
-	s.srcPos.Offset += size
-
-	if ch == '\n' {
-		s.srcPos.Line++
-		s.lastLineLen = s.srcPos.Column
-		s.srcPos.Column = 0
-	}
-
-	// debug
-	// fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column)
-	return ch
-}
-
-// unread unreads the previous read Rune and updates the source position
-func (s *Scanner) unread() {
-	if err := s.buf.UnreadRune(); err != nil {
-		panic(err) // this is user fault, we should catch it
-	}
-	s.srcPos = s.prevPos // put back last position
-}
-
-// peek returns the next rune without advancing the reader.
-func (s *Scanner) peek() rune {
-	peek, _, err := s.buf.ReadRune()
-	if err != nil {
-		return eof
-	}
-
-	s.buf.UnreadRune()
-	return peek
-}
-
-// Scan scans the next token and returns the token.
-func (s *Scanner) Scan() token.Token {
-	ch := s.next()
-
-	// skip white space
-	for isWhitespace(ch) {
-		ch = s.next()
-	}
-
-	var tok token.Type
-
-	// token text markings
-	s.tokStart = s.srcPos.Offset - s.lastCharLen
-
-	// token position, initial next() is moving the offset by one(size of rune
-	// actually), though we are interested with the starting point
-	s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen
-	if s.srcPos.Column > 0 {
-		// common case: last character was not a '\n'
-		s.tokPos.Line = s.srcPos.Line
-		s.tokPos.Column = s.srcPos.Column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.tokPos.Line = s.srcPos.Line - 1
-		s.tokPos.Column = s.lastLineLen
-	}
-
-	switch {
-	case isLetter(ch):
-		lit := s.scanIdentifier()
-		if lit == "true" || lit == "false" {
-			tok = token.BOOL
-		} else if lit == "null" {
-			tok = token.NULL
-		} else {
-			s.err("illegal char")
-		}
-	case isDecimal(ch):
-		tok = s.scanNumber(ch)
-	default:
-		switch ch {
-		case eof:
-			tok = token.EOF
-		case '"':
-			tok = token.STRING
-			s.scanString()
-		case '.':
-			tok = token.PERIOD
-			ch = s.peek()
-			if isDecimal(ch) {
-				tok = token.FLOAT
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '[':
-			tok = token.LBRACK
-		case ']':
-			tok = token.RBRACK
-		case '{':
-			tok = token.LBRACE
-		case '}':
-			tok = token.RBRACE
-		case ',':
-			tok = token.COMMA
-		case ':':
-			tok = token.COLON
-		case '-':
-			if isDecimal(s.peek()) {
-				ch := s.next()
-				tok = s.scanNumber(ch)
-			} else {
-				s.err("illegal char")
-			}
-		default:
-			s.err("illegal char: " + string(ch))
-		}
-	}
-
-	// finish token ending
-	s.tokEnd = s.srcPos.Offset
-
-	// create token literal
-	var tokenText string
-	if s.tokStart >= 0 {
-		tokenText = string(s.src[s.tokStart:s.tokEnd])
-	}
-	s.tokStart = s.tokEnd // ensure idempotency of tokenText() call
-
-	return token.Token{
-		Type: tok,
-		Pos:  s.tokPos,
-		Text: tokenText,
-	}
-}
-
-// scanNumber scans a HCL number definition starting with the given rune
-func (s *Scanner) scanNumber(ch rune) token.Type {
-	zero := ch == '0'
-	pos := s.srcPos
-
-	s.scanMantissa(ch)
-	ch = s.next() // seek forward
-	if ch == 'e' || ch == 'E' {
-		ch = s.scanExponent(ch)
-		return token.FLOAT
-	}
-
-	if ch == '.' {
-		ch = s.scanFraction(ch)
-		if ch == 'e' || ch == 'E' {
-			ch = s.next()
-			ch = s.scanExponent(ch)
-		}
-		return token.FLOAT
-	}
-
-	if ch != eof {
-		s.unread()
-	}
-
-	// If we have a larger number and this is zero, error
-	if zero && pos != s.srcPos {
-		s.err("numbers cannot start with 0")
-	}
-
-	return token.NUMBER
-}
-
-// scanMantissa scans the mantissa beginning from the rune. It returns the next
-// non decimal rune. It's used to determine wheter it's a fraction or exponent.
-func (s *Scanner) scanMantissa(ch rune) rune {
-	scanned := false
-	for isDecimal(ch) {
-		ch = s.next()
-		scanned = true
-	}
-
-	if scanned && ch != eof {
-		s.unread()
-	}
-	return ch
-}
-
-// scanFraction scans the fraction after the '.' rune
-func (s *Scanner) scanFraction(ch rune) rune {
-	if ch == '.' {
-		ch = s.peek() // we peek just to see if we can move forward
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanExponent scans the remaining parts of an exponent after the 'e' or 'E'
-// rune.
-func (s *Scanner) scanExponent(ch rune) rune {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-// scanString scans a quoted string
-func (s *Scanner) scanString() {
-	braces := 0
-	for {
-		// '"' opening already consumed
-		// read character after quote
-		ch := s.next()
-
-		if ch == '\n' || ch < 0 || ch == eof {
-			s.err("literal not terminated")
-			return
-		}
-
-		if ch == '"' {
-			break
-		}
-
-		// If we're going into a ${} then we can ignore quotes for awhile
-		if braces == 0 && ch == '$' && s.peek() == '{' {
-			braces++
-			s.next()
-		} else if braces > 0 && ch == '{' {
-			braces++
-		}
-		if braces > 0 && ch == '}' {
-			braces--
-		}
-
-		if ch == '\\' {
-			s.scanEscape()
-		}
-	}
-
-	return
-}
-
-// scanEscape scans an escape sequence
-func (s *Scanner) scanEscape() rune {
-	// http://en.cppreference.com/w/cpp/language/escape
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"':
-		// nothing to do
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		// octal notation
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		// hexademical notation
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		// universal character name
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.err("illegal char escape")
-	}
-	return ch
-}
-
-// scanDigits scans a rune with the given base for n times. For example an
-// octal notation \184 would yield in scanDigits(ch, 8, 3)
-func (s *Scanner) scanDigits(ch rune, base, n int) rune {
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		n--
-	}
-	if n > 0 {
-		s.err("illegal char escape")
-	}
-
-	// we scanned all digits, put the last non digit char back
-	s.unread()
-	return ch
-}
-
-// scanIdentifier scans an identifier and returns the literal string
-func (s *Scanner) scanIdentifier() string {
-	offs := s.srcPos.Offset - s.lastCharLen
-	ch := s.next()
-	for isLetter(ch) || isDigit(ch) || ch == '-' {
-		ch = s.next()
-	}
-
-	if ch != eof {
-		s.unread() // we got identifier, put back latest char
-	}
-
-	return string(s.src[offs:s.srcPos.Offset])
-}
-
-// recentPosition returns the position of the character immediately after the
-// character or token returned by the last call to Scan.
-func (s *Scanner) recentPosition() (pos token.Pos) {
-	pos.Offset = s.srcPos.Offset - s.lastCharLen
-	switch {
-	case s.srcPos.Column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.srcPos.Line
-		pos.Column = s.srcPos.Column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		pos.Line = s.srcPos.Line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// err prints the error of any scanning to s.Error function. If the function is
-// not defined, by default it prints them to os.Stderr
-func (s *Scanner) err(msg string) {
-	s.ErrorCount++
-	pos := s.recentPosition()
-
-	if s.Error != nil {
-		s.Error(pos, msg)
-		return
-	}
-
-	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
-}
-
-// isHexadecimal returns true if the given rune is a letter
-func isLetter(ch rune) bool {
-	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal digit
-func isDigit(ch rune) bool {
-	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
-}
-
-// isHexadecimal returns true if the given rune is a decimal number
-func isDecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9'
-}
-
-// isHexadecimal returns true if the given rune is an hexadecimal number
-func isHexadecimal(ch rune) bool {
-	return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
-}
-
-// isWhitespace returns true if the rune is a space, tab, newline or carriage return
-func isWhitespace(ch rune) bool {
-	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
-}
-
-// digitVal returns the integer value of a given octal,decimal or hexadecimal rune
-func digitVal(ch rune) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return int(ch - '0')
-	case 'a' <= ch && ch <= 'f':
-		return int(ch - 'a' + 10)
-	case 'A' <= ch && ch <= 'F':
-		return int(ch - 'A' + 10)
-	}
-	return 16 // larger than any legal digit val
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/json/token/position.go b/public-api/vendor/github.com/hashicorp/hcl/json/token/position.go
deleted file mode 100644
index 59c1bb72..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/json/token/position.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package token
-
-import "fmt"
-
-// Pos describes an arbitrary source position
-// including the file, line, and column location.
-// A Position is valid if the line number is > 0.
-type Pos struct {
-	Filename string // filename, if any
-	Offset   int    // offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count)
-}
-
-// IsValid returns true if the position is valid.
-func (p *Pos) IsValid() bool { return p.Line > 0 }
-
-// String returns a string in one of several forms:
-//
-//	file:line:column    valid position with file name
-//	line:column         valid position without file name
-//	file                invalid position with file name
-//	-                   invalid position without file name
-func (p Pos) String() string {
-	s := p.Filename
-	if p.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", p.Line, p.Column)
-	}
-	if s == "" {
-		s = "-"
-	}
-	return s
-}
-
-// Before reports whether the position p is before u.
-func (p Pos) Before(u Pos) bool {
-	return u.Offset > p.Offset || u.Line > p.Line
-}
-
-// After reports whether the position p is after u.
-func (p Pos) After(u Pos) bool {
-	return u.Offset < p.Offset || u.Line < p.Line
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/json/token/token.go b/public-api/vendor/github.com/hashicorp/hcl/json/token/token.go
deleted file mode 100644
index 95a0c3ee..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/json/token/token.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package token
-
-import (
-	"fmt"
-	"strconv"
-
-	hcltoken "github.com/hashicorp/hcl/hcl/token"
-)
-
-// Token defines a single HCL token which can be obtained via the Scanner
-type Token struct {
-	Type Type
-	Pos  Pos
-	Text string
-}
-
-// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language)
-type Type int
-
-const (
-	// Special tokens
-	ILLEGAL Type = iota
-	EOF
-
-	identifier_beg
-	literal_beg
-	NUMBER // 12345
-	FLOAT  // 123.45
-	BOOL   // true,false
-	STRING // "abc"
-	NULL   // null
-	literal_end
-	identifier_end
-
-	operator_beg
-	LBRACK // [
-	LBRACE // {
-	COMMA  // ,
-	PERIOD // .
-	COLON  // :
-
-	RBRACK // ]
-	RBRACE // }
-
-	operator_end
-)
-
-var tokens = [...]string{
-	ILLEGAL: "ILLEGAL",
-
-	EOF: "EOF",
-
-	NUMBER: "NUMBER",
-	FLOAT:  "FLOAT",
-	BOOL:   "BOOL",
-	STRING: "STRING",
-	NULL:   "NULL",
-
-	LBRACK: "LBRACK",
-	LBRACE: "LBRACE",
-	COMMA:  "COMMA",
-	PERIOD: "PERIOD",
-	COLON:  "COLON",
-
-	RBRACK: "RBRACK",
-	RBRACE: "RBRACE",
-}
-
-// String returns the string corresponding to the token tok.
-func (t Type) String() string {
-	s := ""
-	if 0 <= t && t < Type(len(tokens)) {
-		s = tokens[t]
-	}
-	if s == "" {
-		s = "token(" + strconv.Itoa(int(t)) + ")"
-	}
-	return s
-}
-
-// IsIdentifier returns true for tokens corresponding to identifiers and basic
-// type literals; it returns false otherwise.
-func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end }
-
-// IsLiteral returns true for tokens corresponding to basic type literals; it
-// returns false otherwise.
-func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end }
-
-// IsOperator returns true for tokens corresponding to operators and
-// delimiters; it returns false otherwise.
-func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end }
-
-// String returns the token's literal text. Note that this is only
-// applicable for certain token types, such as token.IDENT,
-// token.STRING, etc..
-func (t Token) String() string {
-	return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
-}
-
-// HCLToken converts this token to an HCL token.
-//
-// The token type must be a literal type or this will panic.
-func (t Token) HCLToken() hcltoken.Token {
-	switch t.Type {
-	case BOOL:
-		return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text}
-	case FLOAT:
-		return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text}
-	case NULL:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: ""}
-	case NUMBER:
-		return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text}
-	case STRING:
-		return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true}
-	default:
-		panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type))
-	}
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/lex.go b/public-api/vendor/github.com/hashicorp/hcl/lex.go
deleted file mode 100644
index d9993c29..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/lex.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package hcl
-
-import (
-	"unicode"
-	"unicode/utf8"
-)
-
-type lexModeValue byte
-
-const (
-	lexModeUnknown lexModeValue = iota
-	lexModeHcl
-	lexModeJson
-)
-
-// lexMode returns whether we're going to be parsing in JSON
-// mode or HCL mode.
-func lexMode(v []byte) lexModeValue {
-	var (
-		r      rune
-		w      int
-		offset int
-	)
-
-	for {
-		r, w = utf8.DecodeRune(v[offset:])
-		offset += w
-		if unicode.IsSpace(r) {
-			continue
-		}
-		if r == '{' {
-			return lexModeJson
-		}
-		break
-	}
-
-	return lexModeHcl
-}
diff --git a/public-api/vendor/github.com/hashicorp/hcl/parse.go b/public-api/vendor/github.com/hashicorp/hcl/parse.go
deleted file mode 100644
index 1fca53c4..00000000
--- a/public-api/vendor/github.com/hashicorp/hcl/parse.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package hcl
-
-import (
-	"fmt"
-
-	"github.com/hashicorp/hcl/hcl/ast"
-	hclParser "github.com/hashicorp/hcl/hcl/parser"
-	jsonParser "github.com/hashicorp/hcl/json/parser"
-)
-
-// ParseBytes accepts as input byte slice and returns ast tree.
-//
-// Input can be either JSON or HCL
-func ParseBytes(in []byte) (*ast.File, error) {
-	return parse(in)
-}
-
-// ParseString accepts input as a string and returns ast tree.
-func ParseString(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
-
-func parse(in []byte) (*ast.File, error) {
-	switch lexMode(in) {
-	case lexModeHcl:
-		return hclParser.Parse(in)
-	case lexModeJson:
-		return jsonParser.Parse(in)
-	}
-
-	return nil, fmt.Errorf("unknown config format")
-}
-
-// Parse parses the given input and returns the root object.
-//
-// The input format can be either HCL or JSON.
-func Parse(input string) (*ast.File, error) {
-	return parse([]byte(input))
-}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/.golangci.yml b/public-api/vendor/github.com/jackc/pgx/v5/.golangci.yml
new file mode 100644
index 00000000..ca74c703
--- /dev/null
+++ b/public-api/vendor/github.com/jackc/pgx/v5/.golangci.yml
@@ -0,0 +1,21 @@
+# See for configurations: https://golangci-lint.run/usage/configuration/
+version: 2
+
+# See: https://golangci-lint.run/usage/formatters/
+formatters:
+  default: none
+  enable:
+    - gofmt # https://pkg.go.dev/cmd/gofmt
+    - gofumpt # https://github.com/mvdan/gofumpt
+
+  settings:
+    gofmt:
+      simplify: true # Simplify code: gofmt with `-s` option.
+
+    gofumpt:
+      # Module path which contains the source code being formatted.
+      # Default: ""
+      module-path: github.com/jackc/pgx/v5 # Should match with module in go.mod
+      # Choose whether to use the extra rules.
+      # Default: false
+      extra-rules: true
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md b/public-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
index a0ff9ba3..6c9c99b5 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
+++ b/public-api/vendor/github.com/jackc/pgx/v5/CHANGELOG.md
@@ -1,3 +1,54 @@
+# 5.7.6 (September 8, 2025)
+
+* Use ParseConfigError in pgx.ParseConfig and pgxpool.ParseConfig (Yurasov Ilia)
+* Add PrepareConn hook to pgxpool (Jonathan Hall)
+* Reduce allocations in QueryContext (Dominique Lefevre)
+* Add MarshalJSON and UnmarshalJSON for pgtype.Uint32 (Panos Koutsovasilis)
+* Configure ping behavior on pgxpool with ShouldPing (Christian Kiely)
+* zeronull int types implement Int64Valuer and Int64Scanner (Li Zeghong)
+* Fix panic when receiving terminate connection message during CopyFrom (Michal Drausowski)
+* Fix statement cache not being invalidated on error during batch (Muhammadali Nazarov)
+
+# 5.7.5 (May 17, 2025)
+
+* Support sslnegotiation connection option (divyam234)
+* Update golang.org/x/crypto to v0.37.0. This placates security scanners that were unable to see that pgx did not use the behavior affected by https://pkg.go.dev/vuln/GO-2025-3487.
+* TraceLog now logs Acquire and Release at the debug level (dave sinclair)
+* Add support for PGTZ environment variable
+* Add support for PGOPTIONS environment variable
+* Unpin memory used by Rows quicker
+* Remove PlanScan memoization. This resolves a rare issue where scanning could be broken for one type by first scanning another. The problem was in the memoization system and benchmarking revealed that memoization was not providing any meaningful benefit.
+
+# 5.7.4 (March 24, 2025)
+
+* Fix / revert change to scanning JSON `null` (Felix Röhrich)
+
+# 5.7.3 (March 21, 2025)
+
+* Expose EmptyAcquireWaitTime in pgxpool.Stat (vamshiaruru32)
+* Improve SQL sanitizer performance (ninedraft)
+* Fix Scan confusion with json(b), sql.Scanner, and automatic dereferencing (moukoublen, felix-roehrich)
+* Fix Values() for xml type always returning nil instead of []byte
+* Add ability to send Flush message in pipeline mode (zenkovev)
+* Fix pgtype.Timestamp's JSON behavior to match PostgreSQL (pconstantinou)
+* Better error messages when scanning structs (logicbomb)
+* Fix handling of error on batch write (bonnefoa)
+* Match libpq's connection fallback behavior more closely (felix-roehrich)
+* Add MinIdleConns to pgxpool (djahandarie)
+
+# 5.7.2 (December 21, 2024)
+
+* Fix prepared statement already exists on batch prepare failure
+* Add commit query to tx options (Lucas Hild)
+* Fix pgtype.Timestamp json unmarshal (Shean de Montigny-Desautels)
+* Add message body size limits in frontend and backend (zene)
+* Add xid8 type
+* Ensure planning encodes and scans cannot infinitely recurse
+* Implement pgtype.UUID.String() (Konstantin Grachev)
+* Switch from ExecParams to Exec in ValidateConnectTargetSessionAttrs functions (Alexander Rumyantsev)
+* Update golang.org/x/crypto
+* Fix json(b) columns prefer sql.Scanner interface like database/sql (Ludovico Russo)
+
 # 5.7.1 (September 10, 2024)
 
 * Fix data race in tracelog.TraceLog
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/README.md b/public-api/vendor/github.com/jackc/pgx/v5/README.md
index 0cf2c291..cb709e21 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/README.md
+++ b/public-api/vendor/github.com/jackc/pgx/v5/README.md
@@ -84,7 +84,7 @@ It is also possible to use the `database/sql` interface and convert a connection
 
 ## Testing
 
-See CONTRIBUTING.md for setup instructions.
+See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions.
 
 ## Architecture
 
@@ -92,7 +92,7 @@ See the presentation at Golang Estonia, [PGX Top to Bottom](https://www.youtube.
 
 ## Supported Go and PostgreSQL Versions
 
-pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.21 and higher and PostgreSQL 12 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
+pgx supports the same versions of Go and PostgreSQL that are supported by their respective teams. For [Go](https://golang.org/doc/devel/release.html#policy) that is the two most recent major releases and for [PostgreSQL](https://www.postgresql.org/support/versioning/) the major releases in the last 5 years. This means pgx supports Go 1.23 and higher and PostgreSQL 13 and higher. pgx also is tested against the latest version of [CockroachDB](https://www.cockroachlabs.com/product/).
 
 ## Version Policy
 
@@ -126,7 +126,8 @@ pgerrcode contains constants for the PostgreSQL error codes.
 
 ## Adapters for 3rd Party Tracers
 
-* [https://github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/jackhopner/pgx-xray-tracer](https://github.com/jackhopner/pgx-xray-tracer)
+* [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx)
 
 ## Adapters for 3rd Party Loggers
 
@@ -156,7 +157,7 @@ Library for scanning data from a database into Go structs and more.
 A carefully designed SQL client for making using SQL easier,
 more productive, and less error-prone on Golang.
 
-### [https://github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
+### [github.com/otan/gopgkrb5](https://github.com/otan/gopgkrb5)
 
 Adds GSSAPI / Kerberos authentication support.
 
@@ -169,6 +170,22 @@ Explicit data mapping and scanning library for Go structs and slices.
 Type safe and flexible package for scanning database data into Go types.
 Supports, structs, maps, slices and custom mapping functions.
 
-### [https://github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
+### [github.com/z0ne-dev/mgx](https://github.com/z0ne-dev/mgx)
 
 Code first migration library for native pgx (no database/sql abstraction).
+
+### [github.com/amirsalarsafaei/sqlc-pgx-monitoring](https://github.com/amirsalarsafaei/sqlc-pgx-monitoring)
+
+A database monitoring/metrics library for pgx and sqlc. Trace, log and monitor your sqlc query performance using OpenTelemetry.
+
+### [https://github.com/nikolayk812/pgx-outbox](https://github.com/nikolayk812/pgx-outbox)
+
+Simple Golang implementation for transactional outbox pattern for PostgreSQL using jackc/pgx driver.
+
+### [https://github.com/Arlandaren/pgxWrappy](https://github.com/Arlandaren/pgxWrappy)
+
+Simplifies working with the pgx library, providing convenient scanning of nested structures.
+
+## [https://github.com/KoNekoD/pgx-colon-query-rewriter](https://github.com/KoNekoD/pgx-colon-query-rewriter)
+
+Implementation of the pgx query rewriter to use ':' instead of '@' in named query parameters.
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/Rakefile b/public-api/vendor/github.com/jackc/pgx/v5/Rakefile
index d957573e..3e3aa503 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/Rakefile
+++ b/public-api/vendor/github.com/jackc/pgx/v5/Rakefile
@@ -2,7 +2,7 @@ require "erb"
 
 rule '.go' => '.go.erb' do |task|
   erb = ERB.new(File.read(task.source))
-  File.write(task.name, "// Do not edit. Generated from #{task.source}\n" + erb.result(binding))
+  File.write(task.name, "// Code generated from #{task.source}. DO NOT EDIT.\n\n" + erb.result(binding))
   sh "goimports", "-w", task.name
 end
 
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/batch.go b/public-api/vendor/github.com/jackc/pgx/v5/batch.go
index c3c2834f..1b1cbd84 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/batch.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/batch.go
@@ -43,6 +43,10 @@ func (qq *QueuedQuery) QueryRow(fn func(row Row) error) {
 }
 
 // Exec sets fn to be called when the response to qq is received.
+//
+// Note: for simple batch insert uses where it is not required to handle
+// each potential error individually, it's sufficient to not set any callbacks,
+// and just handle the return value of BatchResults.Close.
 func (qq *QueuedQuery) Exec(fn func(ct pgconn.CommandTag) error) {
 	qq.Fn = func(br BatchResults) error {
 		ct, err := br.Exec()
@@ -83,7 +87,7 @@ func (b *Batch) Len() int {
 
 type BatchResults interface {
 	// Exec reads the results from the next query in the batch as if the query has been sent with Conn.Exec. Prefer
-	// calling Exec on the QueuedQuery.
+	// calling Exec on the QueuedQuery, or just calling Close.
 	Exec() (pgconn.CommandTag, error)
 
 	// Query reads the results from the next query in the batch as if the query has been sent with Conn.Query. Prefer
@@ -98,6 +102,9 @@ type BatchResults interface {
 	// QueuedQuery.Query, QueuedQuery.QueryRow, or QueuedQuery.Exec will be called. If a callback function returns an
 	// error or the batch encounters an error subsequent callback functions will not be called.
 	//
+	// For simple batch inserts inside a transaction or similar queries, it's sufficient to not set any callbacks,
+	// and just handle the return value of Close.
+	//
 	// Close must be called before the underlying connection can be used again. Any error that occurred during a batch
 	// operation may have made it impossible to resyncronize the connection with the server. In this case the underlying
 	// connection will have been closed.
@@ -207,7 +214,6 @@ func (br *batchResults) Query() (Rows, error) {
 func (br *batchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -220,6 +226,8 @@ func (br *batchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err != nil {
@@ -378,7 +386,6 @@ func (br *pipelineBatchResults) Query() (Rows, error) {
 func (br *pipelineBatchResults) QueryRow() Row {
 	rows, _ := br.Query()
 	return (*connRow)(rows.(*baseRows))
-
 }
 
 // Close closes the batch operation. Any error that occurred during a batch operation may have made it impossible to
@@ -391,6 +398,8 @@ func (br *pipelineBatchResults) Close() error {
 			}
 			br.endTraced = true
 		}
+
+		invalidateCachesOnBatchResultsError(br.conn, br.b, br.err)
 	}()
 
 	if br.err == nil && br.lastRows != nil && br.lastRows.err != nil {
@@ -441,3 +450,20 @@ func (br *pipelineBatchResults) nextQueryAndArgs() (query string, args []any, er
 	br.qqIdx++
 	return bi.SQL, bi.Arguments, nil
 }
+
+// invalidates statement and description caches on batch results error
+func invalidateCachesOnBatchResultsError(conn *Conn, b *Batch, err error) {
+	if err != nil && conn != nil && b != nil {
+		if sc := conn.statementCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+
+		if sc := conn.descriptionCache; sc != nil {
+			for _, bi := range b.QueuedQueries {
+				sc.Invalidate(bi.SQL)
+			}
+		}
+	}
+}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/conn.go b/public-api/vendor/github.com/jackc/pgx/v5/conn.go
index 187b3dd5..67b22529 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/conn.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/conn.go
@@ -172,7 +172,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "statement_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse statement_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse statement_cache_capacity", err)
 		}
 		statementCacheCapacity = int(n)
 	}
@@ -182,7 +182,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		delete(config.RuntimeParams, "description_cache_capacity")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse description_cache_capacity: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse description_cache_capacity", err)
 		}
 		descriptionCacheCapacity = int(n)
 	}
@@ -202,7 +202,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		case "simple_protocol":
 			defaultQueryExecMode = QueryExecModeSimpleProtocol
 		default:
-			return nil, fmt.Errorf("invalid default_query_exec_mode: %s", s)
+			return nil, pgconn.NewParseConfigError(connString, "invalid default_query_exec_mode", err)
 		}
 	}
 
@@ -420,7 +420,7 @@ func (c *Conn) IsClosed() bool {
 	return c.pgConn.IsClosed()
 }
 
-func (c *Conn) die(err error) {
+func (c *Conn) die() {
 	if c.IsClosed() {
 		return
 	}
@@ -588,14 +588,6 @@ func (c *Conn) execPrepared(ctx context.Context, sd *pgconn.StatementDescription
 	return result.CommandTag, result.Err
 }
 
-type unknownArgumentTypeQueryExecModeExecError struct {
-	arg any
-}
-
-func (e *unknownArgumentTypeQueryExecModeExecError) Error() string {
-	return fmt.Sprintf("cannot use unregistered type %T as query argument in QueryExecModeExec", e.arg)
-}
-
 func (c *Conn) execSQLParams(ctx context.Context, sql string, args []any) (pgconn.CommandTag, error) {
 	err := c.eqb.Build(c.typeMap, nil, args)
 	if err != nil {
@@ -650,21 +642,33 @@ const (
 	// registered with pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are
 	// unregistered or ambiguous. e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know
 	// the PostgreSQL type can use a map[string]string directly as an argument. This mode cannot.
+	//
+	// On rare occasions user defined types may behave differently when encoded in the text format instead of the binary
+	// format. For example, this could happen if a "type RomanNumeral int32" implements fmt.Stringer to format integers as
+	// Roman numerals (e.g. 7 is VII). The binary format would properly encode the integer 7 as the binary value for 7.
+	// But the text format would encode the integer 7 as the string "VII". As QueryExecModeExec uses the text format, it
+	// is possible that changing query mode from another mode to QueryExecModeExec could change the behavior of the query.
+	// This should not occur with types pgx supports directly and can be avoided by registering the types with
+	// pgtype.Map.RegisterDefaultPgType and implementing the appropriate type interfaces. In the cas of RomanNumeral, it
+	// should implement pgtype.Int64Valuer.
 	QueryExecModeExec
 
-	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments.
-	// Queries are executed in a single round trip. Type mappings can be registered with
+	// Use the simple protocol. Assume the PostgreSQL query parameter types based on the Go type of the arguments. This is
+	// especially significant for []byte values. []byte values are encoded as PostgreSQL bytea. string must be used
+	// instead for text type values including json and jsonb. Type mappings can be registered with
 	// pgtype.Map.RegisterDefaultPgType. Queries will be rejected that have arguments that are unregistered or ambiguous.
-	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use
-	// a map[string]string directly as an argument. This mode cannot.
+	// e.g. A map[string]string may have the PostgreSQL type json or hstore. Modes that know the PostgreSQL type can use a
+	// map[string]string directly as an argument. This mode cannot. Queries are executed in a single round trip.
 	//
-	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec with minor
-	// exceptions such as behavior when multiple result returning queries are erroneously sent in a single string.
+	// QueryExecModeSimpleProtocol should have the user application visible behavior as QueryExecModeExec. This includes
+	// the warning regarding differences in text format and binary format encoding with user defined types. There may be
+	// other minor exceptions such as behavior when multiple result returning queries are erroneously sent in a single
+	// string.
 	//
 	// QueryExecModeSimpleProtocol uses client side parameter interpolation. All values are quoted and escaped. Prefer
-	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol
-	// should only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does
-	// not support the extended protocol.
+	// QueryExecModeExec over QueryExecModeSimpleProtocol whenever possible. In general QueryExecModeSimpleProtocol should
+	// only be used if connecting to a proxy server, connection pool server, or non-PostgreSQL server that does not
+	// support the extended protocol.
 	QueryExecModeSimpleProtocol
 )
 
@@ -904,6 +908,9 @@ func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) Row {
 // SendBatch sends all queued queries to the server at once. All queries are run in an implicit transaction unless
 // explicit transaction control statements are executed. The returned BatchResults must be closed before the connection
 // is used again.
+//
+// Depending on the QueryExecMode, all queries may be prepared before any are executed. This means that creating a table
+// and using it in a subsequent query in the same batch can fail.
 func (c *Conn) SendBatch(ctx context.Context, b *Batch) (br BatchResults) {
 	if c.batchTracer != nil {
 		ctx = c.batchTracer.TraceBatchStart(ctx, c, TraceBatchStartData{Batch: b})
@@ -1126,47 +1133,64 @@ func (c *Conn) sendBatchExtendedWithDescription(ctx context.Context, b *Batch, d
 
 	// Prepare any needed queries
 	if len(distinctNewQueries) > 0 {
-		for _, sd := range distinctNewQueries {
-			pipeline.SendPrepare(sd.Name, sd.SQL, nil)
-		}
+		err := func() (err error) {
+			for _, sd := range distinctNewQueries {
+				pipeline.SendPrepare(sd.Name, sd.SQL, nil)
+			}
 
-		err := pipeline.Sync()
-		if err != nil {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
-		}
+			// Store all statements we are preparing into the cache. It's fine if it overflows because HandleInvalidated will
+			// clean them up later.
+			if sdCache != nil {
+				for _, sd := range distinctNewQueries {
+					sdCache.Put(sd)
+				}
+			}
+
+			// If something goes wrong preparing the statements, we need to invalidate the cache entries we just added.
+			defer func() {
+				if err != nil && sdCache != nil {
+					for _, sd := range distinctNewQueries {
+						sdCache.Invalidate(sd.SQL)
+					}
+				}
+			}()
+
+			err = pipeline.Sync()
+			if err != nil {
+				return err
+			}
+
+			for _, sd := range distinctNewQueries {
+				results, err := pipeline.GetResults()
+				if err != nil {
+					return err
+				}
+
+				resultSD, ok := results.(*pgconn.StatementDescription)
+				if !ok {
+					return fmt.Errorf("expected statement description, got %T", results)
+				}
+
+				// Fill in the previously empty / pending statement descriptions.
+				sd.ParamOIDs = resultSD.ParamOIDs
+				sd.Fields = resultSD.Fields
+			}
 
-		for _, sd := range distinctNewQueries {
 			results, err := pipeline.GetResults()
 			if err != nil {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
+				return err
 			}
 
-			resultSD, ok := results.(*pgconn.StatementDescription)
+			_, ok := results.(*pgconn.PipelineSync)
 			if !ok {
-				return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected statement description, got %T", results), closed: true}
+				return fmt.Errorf("expected sync, got %T", results)
 			}
 
-			// Fill in the previously empty / pending statement descriptions.
-			sd.ParamOIDs = resultSD.ParamOIDs
-			sd.Fields = resultSD.Fields
-		}
-
-		results, err := pipeline.GetResults()
+			return nil
+		}()
 		if err != nil {
 			return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
 		}
-
-		_, ok := results.(*pgconn.PipelineSync)
-		if !ok {
-			return &pipelineBatchResults{ctx: ctx, conn: c, err: fmt.Errorf("expected sync, got %T", results), closed: true}
-		}
-	}
-
-	// Put all statements into the cache. It's fine if it overflows because HandleInvalidated will clean them up later.
-	if sdCache != nil {
-		for _, sd := range distinctNewQueries {
-			sdCache.Put(sd)
-		}
 	}
 
 	// Queue the queries.
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/derived_types.go b/public-api/vendor/github.com/jackc/pgx/v5/derived_types.go
index 22ab069c..72c0a242 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/derived_types.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/derived_types.go
@@ -161,7 +161,7 @@ type derivedTypeInfo struct {
 // The result of this call can be passed into RegisterTypes to complete the process.
 func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Type, error) {
 	m := c.TypeMap()
-	if typeNames == nil || len(typeNames) == 0 {
+	if len(typeNames) == 0 {
 		return nil, fmt.Errorf("No type names were supplied.")
 	}
 
@@ -169,13 +169,7 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 	// the SQL not support recent structures such as multirange
 	serverVersion, _ := serverVersion(c)
 	sql := buildLoadDerivedTypesSQL(serverVersion, typeNames)
-	var rows Rows
-	var err error
-	if typeNames == nil {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol)
-	} else {
-		rows, err = c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
-	}
+	rows, err := c.Query(ctx, sql, QueryExecModeSimpleProtocol, typeNames)
 	if err != nil {
 		return nil, fmt.Errorf("While generating load types query: %w", err)
 	}
@@ -232,15 +226,15 @@ func (c *Conn) LoadTypes(ctx context.Context, typeNames []string) ([]*pgtype.Typ
 		default:
 			return nil, fmt.Errorf("Unknown typtype %q was found while registering %q", ti.Typtype, ti.TypeName)
 		}
-		if type_ != nil {
-			m.RegisterType(type_)
-			if ti.NspName != "" {
-				nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
-				m.RegisterType(nspType)
-				result = append(result, nspType)
-			}
-			result = append(result, type_)
+
+		// the type_ is imposible to be null
+		m.RegisterType(type_)
+		if ti.NspName != "" {
+			nspType := &pgtype.Type{Name: ti.NspName + "." + type_.Name, OID: type_.OID, Codec: type_.Codec}
+			m.RegisterType(nspType)
+			result = append(result, nspType)
 		}
+		result = append(result, type_)
 	}
 	return result, nil
 }
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/doc.go b/public-api/vendor/github.com/jackc/pgx/v5/doc.go
index 0e91d64e..5d2ae388 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/doc.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/doc.go
@@ -183,7 +183,7 @@ For debug tracing of the actual PostgreSQL wire protocol messages see github.com
 
 Lower Level PostgreSQL Functionality
 
-github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn in
+github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn is
 implemented on top of pgconn. The Conn.PgConn() method can be used to access this lower layer.
 
 PgBouncer
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh b/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
new file mode 100644
index 00000000..ec0f7b03
--- /dev/null
+++ b/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/benchmmark.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+current_branch=$(git rev-parse --abbrev-ref HEAD)
+if [ "$current_branch" == "HEAD" ]; then
+    current_branch=$(git rev-parse HEAD)
+fi
+
+restore_branch() {
+    echo "Restoring original branch/commit: $current_branch"
+    git checkout "$current_branch"
+}
+trap restore_branch EXIT
+
+# Check if there are uncommitted changes
+if ! git diff --quiet || ! git diff --cached --quiet; then
+    echo "There are uncommitted changes. Please commit or stash them before running this script."
+    exit 1
+fi
+
+# Ensure that at least one commit argument is passed
+if [ "$#" -lt 1 ]; then
+    echo "Usage: $0   ... "
+    exit 1
+fi
+
+commits=("$@")
+benchmarks_dir=benchmarks
+
+if ! mkdir -p "${benchmarks_dir}"; then
+    echo "Unable to create dir for benchmarks data"
+    exit 1
+fi
+
+# Benchmark results
+bench_files=()
+
+# Run benchmark for each listed commit
+for i in "${!commits[@]}"; do
+    commit="${commits[i]}"
+    git checkout "$commit" || {
+        echo "Failed to checkout $commit"
+        exit 1
+    }
+
+    # Sanitized commmit message
+    commit_message=$(git log -1 --pretty=format:"%s" | tr -c '[:alnum:]-_' '_')
+
+    # Benchmark data will go there
+    bench_file="${benchmarks_dir}/${i}_${commit_message}.bench"
+
+    if ! go test -bench=. -count=10 >"$bench_file"; then
+        echo "Benchmarking failed for commit $commit"
+        exit 1
+    fi
+
+    bench_files+=("$bench_file")
+done
+
+# go install golang.org/x/perf/cmd/benchstat[@latest]
+benchstat "${bench_files[@]}"
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
index df58c448..b516817c 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go
@@ -4,8 +4,10 @@ import (
 	"bytes"
 	"encoding/hex"
 	"fmt"
+	"slices"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 	"unicode/utf8"
 )
@@ -24,18 +26,33 @@ type Query struct {
 // https://github.com/jackc/pgx/issues/1380
 const replacementcharacterwidth = 3
 
+const maxBufSize = 16384 // 16 Ki
+
+var bufPool = &pool[*bytes.Buffer]{
+	new: func() *bytes.Buffer {
+		return &bytes.Buffer{}
+	},
+	reset: func(b *bytes.Buffer) bool {
+		n := b.Len()
+		b.Reset()
+		return n < maxBufSize
+	},
+}
+
+var null = []byte("null")
+
 func (q *Query) Sanitize(args ...any) (string, error) {
 	argUse := make([]bool, len(args))
-	buf := &bytes.Buffer{}
+	buf := bufPool.get()
+	defer bufPool.put(buf)
 
 	for _, part := range q.Parts {
-		var str string
 		switch part := part.(type) {
 		case string:
-			str = part
+			buf.WriteString(part)
 		case int:
 			argIdx := part - 1
-
+			var p []byte
 			if argIdx < 0 {
 				return "", fmt.Errorf("first sql argument must be > 0")
 			}
@@ -43,34 +60,41 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 			if argIdx >= len(args) {
 				return "", fmt.Errorf("insufficient arguments")
 			}
+
+			// Prevent SQL injection via Line Comment Creation
+			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
+			buf.WriteByte(' ')
+
 			arg := args[argIdx]
 			switch arg := arg.(type) {
 			case nil:
-				str = "null"
+				p = null
 			case int64:
-				str = strconv.FormatInt(arg, 10)
+				p = strconv.AppendInt(buf.AvailableBuffer(), arg, 10)
 			case float64:
-				str = strconv.FormatFloat(arg, 'f', -1, 64)
+				p = strconv.AppendFloat(buf.AvailableBuffer(), arg, 'f', -1, 64)
 			case bool:
-				str = strconv.FormatBool(arg)
+				p = strconv.AppendBool(buf.AvailableBuffer(), arg)
 			case []byte:
-				str = QuoteBytes(arg)
+				p = QuoteBytes(buf.AvailableBuffer(), arg)
 			case string:
-				str = QuoteString(arg)
+				p = QuoteString(buf.AvailableBuffer(), arg)
 			case time.Time:
-				str = arg.Truncate(time.Microsecond).Format("'2006-01-02 15:04:05.999999999Z07:00:00'")
+				p = arg.Truncate(time.Microsecond).
+					AppendFormat(buf.AvailableBuffer(), "'2006-01-02 15:04:05.999999999Z07:00:00'")
 			default:
 				return "", fmt.Errorf("invalid arg type: %T", arg)
 			}
 			argUse[argIdx] = true
 
+			buf.Write(p)
+
 			// Prevent SQL injection via Line Comment Creation
 			// https://github.com/jackc/pgx/security/advisories/GHSA-m7wr-2xf7-cm9p
-			str = " " + str + " "
+			buf.WriteByte(' ')
 		default:
 			return "", fmt.Errorf("invalid Part type: %T", part)
 		}
-		buf.WriteString(str)
 	}
 
 	for i, used := range argUse {
@@ -82,26 +106,99 @@ func (q *Query) Sanitize(args ...any) (string, error) {
 }
 
 func NewQuery(sql string) (*Query, error) {
-	l := &sqlLexer{
-		src:     sql,
-		stateFn: rawState,
+	query := &Query{}
+	query.init(sql)
+
+	return query, nil
+}
+
+var sqlLexerPool = &pool[*sqlLexer]{
+	new: func() *sqlLexer {
+		return &sqlLexer{}
+	},
+	reset: func(sl *sqlLexer) bool {
+		*sl = sqlLexer{}
+		return true
+	},
+}
+
+func (q *Query) init(sql string) {
+	parts := q.Parts[:0]
+	if parts == nil {
+		// dirty, but fast heuristic to preallocate for ~90% usecases
+		n := strings.Count(sql, "$") + strings.Count(sql, "--") + 1
+		parts = make([]Part, 0, n)
 	}
 
+	l := sqlLexerPool.get()
+	defer sqlLexerPool.put(l)
+
+	l.src = sql
+	l.stateFn = rawState
+	l.parts = parts
+
 	for l.stateFn != nil {
 		l.stateFn = l.stateFn(l)
 	}
 
-	query := &Query{Parts: l.parts}
-
-	return query, nil
+	q.Parts = l.parts
 }
 
-func QuoteString(str string) string {
-	return "'" + strings.ReplaceAll(str, "'", "''") + "'"
+func QuoteString(dst []byte, str string) []byte {
+	const quote = '\''
+
+	// Preallocate space for the worst case scenario
+	dst = slices.Grow(dst, len(str)*2+2)
+
+	// Add opening quote
+	dst = append(dst, quote)
+
+	// Iterate through the string without allocating
+	for i := 0; i < len(str); i++ {
+		if str[i] == quote {
+			dst = append(dst, quote, quote)
+		} else {
+			dst = append(dst, str[i])
+		}
+	}
+
+	// Add closing quote
+	dst = append(dst, quote)
+
+	return dst
 }
 
-func QuoteBytes(buf []byte) string {
-	return `'\x` + hex.EncodeToString(buf) + "'"
+func QuoteBytes(dst, buf []byte) []byte {
+	if len(buf) == 0 {
+		return append(dst, `'\x'`...)
+	}
+
+	// Calculate required length
+	requiredLen := 3 + hex.EncodedLen(len(buf)) + 1
+
+	// Ensure dst has enough capacity
+	if cap(dst)-len(dst) < requiredLen {
+		newDst := make([]byte, len(dst), len(dst)+requiredLen)
+		copy(newDst, dst)
+		dst = newDst
+	}
+
+	// Record original length and extend slice
+	origLen := len(dst)
+	dst = dst[:origLen+requiredLen]
+
+	// Add prefix
+	dst[origLen] = '\''
+	dst[origLen+1] = '\\'
+	dst[origLen+2] = 'x'
+
+	// Encode bytes directly into dst
+	hex.Encode(dst[origLen+3:len(dst)-1], buf)
+
+	// Add suffix
+	dst[len(dst)-1] = '\''
+
+	return dst
 }
 
 type sqlLexer struct {
@@ -319,13 +416,45 @@ func multilineCommentState(l *sqlLexer) stateFn {
 	}
 }
 
+var queryPool = &pool[*Query]{
+	new: func() *Query {
+		return &Query{}
+	},
+	reset: func(q *Query) bool {
+		n := len(q.Parts)
+		q.Parts = q.Parts[:0]
+		return n < 64 // drop too large queries
+	},
+}
+
 // SanitizeSQL replaces placeholder values with args. It quotes and escapes args
 // as necessary. This function is only safe when standard_conforming_strings is
 // on.
 func SanitizeSQL(sql string, args ...any) (string, error) {
-	query, err := NewQuery(sql)
-	if err != nil {
-		return "", err
-	}
+	query := queryPool.get()
+	query.init(sql)
+	defer queryPool.put(query)
+
 	return query.Sanitize(args...)
 }
+
+type pool[E any] struct {
+	p     sync.Pool
+	new   func() E
+	reset func(E) bool
+}
+
+func (pool *pool[E]) get() E {
+	v, ok := pool.p.Get().(E)
+	if !ok {
+		v = pool.new()
+	}
+
+	return v
+}
+
+func (p *pool[E]) put(v E) {
+	if p.reset(v) {
+		p.p.Put(v)
+	}
+}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go b/public-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
index dec83f47..17fec937 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/internal/stmtcache/lru_cache.go
@@ -31,7 +31,6 @@ func (c *LRUCache) Get(key string) *pgconn.StatementDescription {
 	}
 
 	return nil
-
 }
 
 // Put stores sd in the cache. Put panics if sd.SQL is "". Put does nothing if sd.SQL already exists in the cache or
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
index 06498361..f846ba81 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/auth_scram.go
@@ -263,7 +263,7 @@ func computeClientProof(saltedPassword, authMessage []byte) []byte {
 	return buf
 }
 
-func computeServerSignature(saltedPassword []byte, authMessage []byte) []byte {
+func computeServerSignature(saltedPassword, authMessage []byte) []byte {
 	serverKey := computeHMAC(saltedPassword, []byte("Server Key"))
 	serverSignature := computeHMAC(serverKey, authMessage)
 	buf := make([]byte, base64.StdEncoding.EncodedLen(len(serverSignature)))
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
index 6a198e67..3937dc40 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/config.go
@@ -23,9 +23,11 @@ import (
 	"github.com/jackc/pgx/v5/pgproto3"
 )
 
-type AfterConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
-type GetSSLPasswordFunc func(ctx context.Context) string
+type (
+	AfterConnectFunc    func(ctx context.Context, pgconn *PgConn) error
+	ValidateConnectFunc func(ctx context.Context, pgconn *PgConn) error
+	GetSSLPasswordFunc  func(ctx context.Context) string
+)
 
 // Config is the settings used to establish a connection to a PostgreSQL server. It must be created by [ParseConfig]. A
 // manually initialized Config will cause ConnectConfig to panic.
@@ -51,6 +53,8 @@ type Config struct {
 	KerberosSpn     string
 	Fallbacks       []*FallbackConfig
 
+	SSLNegotiation string // sslnegotiation=postgres or sslnegotiation=direct
+
 	// ValidateConnect is called during a connection attempt after a successful authentication with the PostgreSQL server.
 	// It can be used to validate that the server is acceptable. If this returns an error the connection is closed and the next
 	// fallback config is tried. This allows implementing high availability behavior such as libpq does with target_session_attrs.
@@ -177,7 +181,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //
 // ParseConfig supports specifying multiple hosts in similar manner to libpq. Host and port may include comma separated
 // values that will be tried in order. This can be used as part of a high availability system. See
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS for more information.
 //
 //	# Example URL
 //	postgres://jack:secret@foo.example.com:5432,bar.example.com:5432/mydb
@@ -198,13 +202,15 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 //	PGSSLKEY
 //	PGSSLROOTCERT
 //	PGSSLPASSWORD
+//	PGOPTIONS
 //	PGAPPNAME
 //	PGCONNECT_TIMEOUT
 //	PGTARGETSESSIONATTRS
+//	PGTZ
 //
-// See http://www.postgresql.org/docs/11/static/libpq-envars.html for details on the meaning of environment variables.
+// See http://www.postgresql.org/docs/current/static/libpq-envars.html for details on the meaning of environment variables.
 //
-// See https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
+// See https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS for parameter key word names. They are
 // usually but not always the environment variable name downcased and without the "PG" prefix.
 //
 // Important Security Notes:
@@ -212,7 +218,7 @@ func NetworkAddress(host string, port uint16) (network, address string) {
 // ParseConfig tries to match libpq behavior with regard to PGSSLMODE. This includes defaulting to "prefer" behavior if
 // not set.
 //
-// See http://www.postgresql.org/docs/11/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
+// See http://www.postgresql.org/docs/current/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION for details on what level of
 // security each sslmode provides.
 //
 // The sslmode "prefer" (the default), sslmode "allow", and multiple hosts are implemented via the Fallbacks field of
@@ -318,6 +324,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 		"sslkey":               {},
 		"sslcert":              {},
 		"sslrootcert":          {},
+		"sslnegotiation":       {},
 		"sslpassword":          {},
 		"sslsni":               {},
 		"krbspn":               {},
@@ -386,6 +393,7 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con
 	config.Port = fallbacks[0].Port
 	config.TLSConfig = fallbacks[0].TLSConfig
 	config.Fallbacks = fallbacks[1:]
+	config.SSLNegotiation = settings["sslnegotiation"]
 
 	passfile, err := pgpassfile.ReadPassfile(settings["passfile"])
 	if err == nil {
@@ -449,9 +457,12 @@ func parseEnvSettings() map[string]string {
 		"PGSSLSNI":             "sslsni",
 		"PGSSLROOTCERT":        "sslrootcert",
 		"PGSSLPASSWORD":        "sslpassword",
+		"PGSSLNEGOTIATION":     "sslnegotiation",
 		"PGTARGETSESSIONATTRS": "target_session_attrs",
 		"PGSERVICE":            "service",
 		"PGSERVICEFILE":        "servicefile",
+		"PGTZ":                 "timezone",
+		"PGOPTIONS":            "options",
 	}
 
 	for envname, realname := range nameMap {
@@ -646,6 +657,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 	sslkey := settings["sslkey"]
 	sslpassword := settings["sslpassword"]
 	sslsni := settings["sslsni"]
+	sslnegotiation := settings["sslnegotiation"]
 
 	// Match libpq default behavior
 	if sslmode == "" {
@@ -657,6 +669,13 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 
 	tlsConfig := &tls.Config{}
 
+	if sslnegotiation == "direct" {
+		tlsConfig.NextProtos = []string{"postgresql"}
+		if sslmode == "prefer" {
+			sslmode = "require"
+		}
+	}
+
 	if sslrootcert != "" {
 		var caCertPool *x509.CertPool
 
@@ -696,7 +715,7 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 		// According to PostgreSQL documentation, if a root CA file exists,
 		// the behavior of sslmode=require should be the same as that of verify-ca
 		//
-		// See https://www.postgresql.org/docs/12/libpq-ssl.html
+		// See https://www.postgresql.org/docs/current/libpq-ssl.html
 		if sslrootcert != "" {
 			goto nextCase
 		}
@@ -767,8 +786,8 @@ func configTLS(settings map[string]string, thisHost string, parseConfigOptions P
 			if sslpassword != "" {
 				decryptedKey, decryptedError = x509.DecryptPEMBlock(block, []byte(sslpassword))
 			}
-			//if sslpassword not provided or has decryption error when use it
-			//try to find sslpassword with callback function
+			// if sslpassword not provided or has decryption error when use it
+			// try to find sslpassword with callback function
 			if sslpassword == "" || decryptedError != nil {
 				if parseConfigOptions.GetSSLPassword != nil {
 					sslpassword = parseConfigOptions.GetSSLPassword(context.Background())
@@ -861,12 +880,12 @@ func makeConnectTimeoutDialFunc(timeout time.Duration) DialFunc {
 // ValidateConnectTargetSessionAttrsReadWrite is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-write.
 func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "on" {
+	if string(result[0].Rows[0][0]) == "on" {
 		return errors.New("read only connection")
 	}
 
@@ -876,12 +895,12 @@ func ValidateConnectTargetSessionAttrsReadWrite(ctx context.Context, pgConn *PgC
 // ValidateConnectTargetSessionAttrsReadOnly is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=read-only.
 func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "show transaction_read_only", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "show transaction_read_only").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "on" {
+	if string(result[0].Rows[0][0]) != "on" {
 		return errors.New("connection is not read only")
 	}
 
@@ -891,12 +910,12 @@ func ValidateConnectTargetSessionAttrsReadOnly(ctx context.Context, pgConn *PgCo
 // ValidateConnectTargetSessionAttrsStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=standby.
 func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return errors.New("server is not in hot standby mode")
 	}
 
@@ -906,12 +925,12 @@ func ValidateConnectTargetSessionAttrsStandby(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPrimary is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=primary.
 func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) == "t" {
+	if string(result[0].Rows[0][0]) == "t" {
 		return errors.New("server is in standby mode")
 	}
 
@@ -921,12 +940,12 @@ func ValidateConnectTargetSessionAttrsPrimary(ctx context.Context, pgConn *PgCon
 // ValidateConnectTargetSessionAttrsPreferStandby is a ValidateConnectFunc that implements libpq compatible
 // target_session_attrs=prefer-standby.
 func ValidateConnectTargetSessionAttrsPreferStandby(ctx context.Context, pgConn *PgConn) error {
-	result := pgConn.ExecParams(ctx, "select pg_is_in_recovery()", nil, nil, nil, nil).Read()
-	if result.Err != nil {
-		return result.Err
+	result, err := pgConn.Exec(ctx, "select pg_is_in_recovery()").ReadAll()
+	if err != nil {
+		return err
 	}
 
-	if string(result.Rows[0][0]) != "t" {
+	if string(result[0].Rows[0][0]) != "t" {
 		return &NotPreferredError{err: errors.New("server is not in hot standby mode")}
 	}
 
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
index ec4a6d47..d968d3f0 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/errors.go
@@ -27,7 +27,7 @@ func Timeout(err error) bool {
 }
 
 // PgError represents an error reported by the PostgreSQL server. See
-// http://www.postgresql.org/docs/11/static/protocol-error-fields.html for
+// http://www.postgresql.org/docs/current/static/protocol-error-fields.html for
 // detailed field description.
 type PgError struct {
 	Severity            string
@@ -112,6 +112,14 @@ type ParseConfigError struct {
 	err        error
 }
 
+func NewParseConfigError(conn, msg string, err error) error {
+	return &ParseConfigError{
+		ConnString: conn,
+		msg:        msg,
+		err:        err,
+	}
+}
+
 func (e *ParseConfigError) Error() string {
 	// Now that ParseConfigError is public and ConnString is available to the developer, perhaps it would be better only
 	// return a static string. That would ensure that the error message cannot leak a password. The ConnString field would
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
index 3c1af347..efb0d61b 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/krb5.go
@@ -28,7 +28,7 @@ func RegisterGSSProvider(newGSSArg NewGSSFunc) {
 
 // GSS provides GSSAPI authentication (e.g., Kerberos).
 type GSS interface {
-	GetInitToken(host string, service string) ([]byte, error)
+	GetInitToken(host, service string) ([]byte, error)
 	GetInitTokenFromSPN(spn string) ([]byte, error)
 	Continue(inToken []byte) (done bool, outToken []byte, err error)
 }
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
index 7efb522a..97141c64 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go
@@ -1,6 +1,7 @@
 package pgconn
 
 import (
+	"container/list"
 	"context"
 	"crypto/md5"
 	"crypto/tls"
@@ -134,7 +135,7 @@ func ConnectWithOptions(ctx context.Context, connString string, parseConfigOptio
 //
 // If config.Fallbacks are present they will sequentially be tried in case of error establishing network connection. An
 // authentication error will terminate the chain of attempts (like libpq:
-// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
+// https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error.
 func ConnectConfig(ctx context.Context, config *Config) (*PgConn, error) {
 	// Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from
 	// zero values.
@@ -267,12 +268,15 @@ func connectPreferred(ctx context.Context, config *Config, connectOneConfigs []*
 
 		var pgErr *PgError
 		if errors.As(err, &pgErr) {
-			const ERRCODE_INVALID_PASSWORD = "28P01"                    // wrong password
-			const ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION = "28000" // wrong password or bad pg_hba.conf settings
-			const ERRCODE_INVALID_CATALOG_NAME = "3D000"                // db does not exist
-			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501"              // missing connect privilege
+			// pgx will try next host even if libpq does not in certain cases (see #2246)
+			// consider change for the next major version
+
+			const ERRCODE_INVALID_PASSWORD = "28P01"
+			const ERRCODE_INVALID_CATALOG_NAME = "3D000"   // db does not exist
+			const ERRCODE_INSUFFICIENT_PRIVILEGE = "42501" // missing connect privilege
+
+			// auth failed due to invalid password, db does not exist or user has no permission
 			if pgErr.Code == ERRCODE_INVALID_PASSWORD ||
-				pgErr.Code == ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION && c.tlsConfig != nil ||
 				pgErr.Code == ERRCODE_INVALID_CATALOG_NAME ||
 				pgErr.Code == ERRCODE_INSUFFICIENT_PRIVILEGE {
 				return nil, allErrors
@@ -321,7 +325,15 @@ func connectOne(ctx context.Context, config *Config, connectConfig *connectOneCo
 	if connectConfig.tlsConfig != nil {
 		pgConn.contextWatcher = ctxwatch.NewContextWatcher(&DeadlineContextWatcherHandler{Conn: pgConn.conn})
 		pgConn.contextWatcher.Watch(ctx)
-		tlsConn, err := startTLS(pgConn.conn, connectConfig.tlsConfig)
+		var (
+			tlsConn net.Conn
+			err     error
+		)
+		if config.SSLNegotiation == "direct" {
+			tlsConn = tls.Client(pgConn.conn, connectConfig.tlsConfig)
+		} else {
+			tlsConn, err = startTLS(pgConn.conn, connectConfig.tlsConfig)
+		}
 		pgConn.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
 		if err != nil {
 			pgConn.conn.Close()
@@ -979,7 +991,8 @@ func noticeResponseToNotice(msg *pgproto3.NoticeResponse) *Notice {
 
 // CancelRequest sends a cancel request to the PostgreSQL server. It returns an error if unable to deliver the cancel
 // request, but lack of an error does not ensure that the query was canceled. As specified in the documentation, there
-// is no way to be sure a query was canceled. See https://www.postgresql.org/docs/11/protocol-flow.html#id-1.10.5.7.9
+// is no way to be sure a query was canceled.
+// See https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-CANCELING-REQUESTS
 func (pgConn *PgConn) CancelRequest(ctx context.Context) error {
 	// Open a cancellation request to the same server. The address is taken from the net.Conn directly instead of reusing
 	// the connection config. This is important in high availability configurations where fallback connections may be
@@ -1128,7 +1141,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader {
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1154,7 +1167,7 @@ func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues []
 // binary format. If resultFormats is nil all results will be in text format.
 //
 // ResultReader must be closed before PgConn can be used again.
-func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) *ResultReader {
+func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader {
 	result := pgConn.execExtendedPrefix(ctx, paramValues)
 	if result.closed {
 		return result
@@ -1361,7 +1374,14 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 				close(pgConn.cleanupDone)
 				return CommandTag{}, normalizeTimeoutError(ctx, err)
 			}
-			msg, _ := pgConn.receiveMessage()
+			// peekMessage never returns err in the bufferingReceive mode - it only forwards the bufferingReceive variables.
+			// Therefore, the only case for receiveMessage to return err is during handling of the ErrorResponse message type
+			// and using pgOnError handler to determine the connection is no longer valid (and thus closing the conn).
+			msg, serverError := pgConn.receiveMessage()
+			if serverError != nil {
+				close(abortCopyChan)
+				return CommandTag{}, serverError
+			}
 
 			switch msg := msg.(type) {
 			case *pgproto3.ErrorResponse:
@@ -1408,9 +1428,8 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
 
 // MultiResultReader is a reader for a command that could return multiple results such as Exec or ExecBatch.
 type MultiResultReader struct {
-	pgConn   *PgConn
-	ctx      context.Context
-	pipeline *Pipeline
+	pgConn *PgConn
+	ctx    context.Context
 
 	rr *ResultReader
 
@@ -1443,12 +1462,8 @@ func (mrr *MultiResultReader) receiveMessage() (pgproto3.BackendMessage, error)
 	switch msg := msg.(type) {
 	case *pgproto3.ReadyForQuery:
 		mrr.closed = true
-		if mrr.pipeline != nil {
-			mrr.pipeline.expectedReadyForQueryCount--
-		} else {
-			mrr.pgConn.contextWatcher.Unwatch()
-			mrr.pgConn.unlock()
-		}
+		mrr.pgConn.contextWatcher.Unwatch()
+		mrr.pgConn.unlock()
 	case *pgproto3.ErrorResponse:
 		mrr.err = ErrorResponseToPgError(msg)
 	}
@@ -1672,7 +1687,11 @@ func (rr *ResultReader) receiveMessage() (msg pgproto3.BackendMessage, err error
 	case *pgproto3.EmptyQueryResponse:
 		rr.concludeCommand(CommandTag{}, nil)
 	case *pgproto3.ErrorResponse:
-		rr.concludeCommand(CommandTag{}, ErrorResponseToPgError(msg))
+		pgErr := ErrorResponseToPgError(msg)
+		if rr.pipeline != nil {
+			rr.pipeline.state.HandleError(pgErr)
+		}
+		rr.concludeCommand(CommandTag{}, pgErr)
 	}
 
 	return msg, nil
@@ -1701,7 +1720,7 @@ type Batch struct {
 }
 
 // ExecParams appends an ExecParams command to the batch. See PgConn.ExecParams for parameter descriptions.
-func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1714,7 +1733,7 @@ func (batch *Batch) ExecParams(sql string, paramValues [][]byte, paramOIDs []uin
 }
 
 // ExecPrepared appends an ExecPrepared e command to the batch. See PgConn.ExecPrepared for parameter descriptions.
-func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (batch *Batch) ExecPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if batch.err != nil {
 		return
 	}
@@ -1773,9 +1792,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 
 	batch.buf, batch.err = (&pgproto3.Sync{}).Encode(batch.buf)
 	if batch.err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, batch.err)
 		multiResult.closed = true
-		multiResult.err = batch.err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1783,9 +1803,10 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
 	defer pgConn.exitPotentialWriteReadDeadlock()
 	_, err := pgConn.conn.Write(batch.buf)
 	if err != nil {
+		pgConn.contextWatcher.Unwatch()
+		multiResult.err = normalizeTimeoutError(multiResult.ctx, err)
 		multiResult.closed = true
-		multiResult.err = err
-		pgConn.unlock()
+		pgConn.asyncClose()
 		return multiResult
 	}
 
@@ -1999,9 +2020,7 @@ type Pipeline struct {
 	conn *PgConn
 	ctx  context.Context
 
-	expectedReadyForQueryCount int
-	pendingSync                bool
-
+	state  pipelineState
 	err    error
 	closed bool
 }
@@ -2012,6 +2031,122 @@ type PipelineSync struct{}
 // CloseComplete is returned by GetResults when a CloseComplete message is received.
 type CloseComplete struct{}
 
+type pipelineRequestType int
+
+const (
+	pipelineNil pipelineRequestType = iota
+	pipelinePrepare
+	pipelineQueryParams
+	pipelineQueryPrepared
+	pipelineDeallocate
+	pipelineSyncRequest
+	pipelineFlushRequest
+)
+
+type pipelineRequestEvent struct {
+	RequestType       pipelineRequestType
+	WasSentToServer   bool
+	BeforeFlushOrSync bool
+}
+
+type pipelineState struct {
+	requestEventQueue          list.List
+	lastRequestType            pipelineRequestType
+	pgErr                      *PgError
+	expectedReadyForQueryCount int
+}
+
+func (s *pipelineState) Init() {
+	s.requestEventQueue.Init()
+	s.lastRequestType = pipelineNil
+}
+
+func (s *pipelineState) RegisterSendingToServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.WasSentToServer {
+			return
+		}
+		val.WasSentToServer = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) registerFlushingBufferOnServer() {
+	for elem := s.requestEventQueue.Back(); elem != nil; elem = elem.Prev() {
+		val := elem.Value.(pipelineRequestEvent)
+		if val.BeforeFlushOrSync {
+			return
+		}
+		val.BeforeFlushOrSync = true
+		elem.Value = val
+	}
+}
+
+func (s *pipelineState) PushBackRequestType(req pipelineRequestType) {
+	if req == pipelineNil {
+		return
+	}
+
+	if req != pipelineFlushRequest {
+		s.requestEventQueue.PushBack(pipelineRequestEvent{RequestType: req})
+	}
+	if req == pipelineFlushRequest || req == pipelineSyncRequest {
+		s.registerFlushingBufferOnServer()
+	}
+	s.lastRequestType = req
+
+	if req == pipelineSyncRequest {
+		s.expectedReadyForQueryCount++
+	}
+}
+
+func (s *pipelineState) ExtractFrontRequestType() pipelineRequestType {
+	for {
+		elem := s.requestEventQueue.Front()
+		if elem == nil {
+			return pipelineNil
+		}
+		val := elem.Value.(pipelineRequestEvent)
+		if !(val.WasSentToServer && val.BeforeFlushOrSync) {
+			return pipelineNil
+		}
+
+		s.requestEventQueue.Remove(elem)
+		if val.RequestType == pipelineSyncRequest {
+			s.pgErr = nil
+		}
+		if s.pgErr == nil {
+			return val.RequestType
+		}
+	}
+}
+
+func (s *pipelineState) HandleError(err *PgError) {
+	s.pgErr = err
+}
+
+func (s *pipelineState) HandleReadyForQuery() {
+	s.expectedReadyForQueryCount--
+}
+
+func (s *pipelineState) PendingSync() bool {
+	var notPendingSync bool
+
+	if elem := s.requestEventQueue.Back(); elem != nil {
+		val := elem.Value.(pipelineRequestEvent)
+		notPendingSync = (val.RequestType == pipelineSyncRequest) && val.WasSentToServer
+	} else {
+		notPendingSync = (s.lastRequestType == pipelineSyncRequest) || (s.lastRequestType == pipelineNil)
+	}
+
+	return !notPendingSync
+}
+
+func (s *pipelineState) ExpectedReadyForQuery() int {
+	return s.expectedReadyForQueryCount
+}
+
 // StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
 // to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
 // to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
@@ -2020,16 +2155,21 @@ type CloseComplete struct{}
 // Prefer ExecBatch when only sending one group of queries at once.
 func (pgConn *PgConn) StartPipeline(ctx context.Context) *Pipeline {
 	if err := pgConn.lock(); err != nil {
-		return &Pipeline{
+		pipeline := &Pipeline{
 			closed: true,
 			err:    err,
 		}
+		pipeline.state.Init()
+
+		return pipeline
 	}
 
 	pgConn.pipeline = Pipeline{
 		conn: pgConn,
 		ctx:  ctx,
 	}
+	pgConn.pipeline.state.Init()
+
 	pipeline := &pgConn.pipeline
 
 	if ctx != context.Background() {
@@ -2052,10 +2192,10 @@ func (p *Pipeline) SendPrepare(name, sql string, paramOIDs []uint32) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Name: name, Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelinePrepare)
 }
 
 // SendDeallocate deallocates a prepared statement.
@@ -2063,34 +2203,65 @@ func (p *Pipeline) SendDeallocate(name string) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: name})
+	p.state.PushBackRequestType(pipelineDeallocate)
 }
 
 // SendQueryParams is the pipeline version of *PgConn.QueryParams.
-func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryParams(sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendParse(&pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs})
 	p.conn.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryParams)
 }
 
 // SendQueryPrepared is the pipeline version of *PgConn.QueryPrepared.
-func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats []int16, resultFormats []int16) {
+func (p *Pipeline) SendQueryPrepared(stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) {
 	if p.closed {
 		return
 	}
-	p.pendingSync = true
 
 	p.conn.frontend.SendBind(&pgproto3.Bind{PreparedStatement: stmtName, ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})
 	p.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
 	p.conn.frontend.SendExecute(&pgproto3.Execute{})
+	p.state.PushBackRequestType(pipelineQueryPrepared)
+}
+
+// SendFlushRequest sends a request for the server to flush its output buffer.
+//
+// The server flushes its output buffer automatically as a result of Sync being called,
+// or on any request when not in pipeline mode; this function is useful to cause the server
+// to flush its output buffer in pipeline mode without establishing a synchronization point.
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendFlushRequest.
+func (p *Pipeline) SendFlushRequest() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.Send(&pgproto3.Flush{})
+	p.state.PushBackRequestType(pipelineFlushRequest)
+}
+
+// SendPipelineSync marks a synchronization point in a pipeline by sending a sync message
+// without flushing the send buffer. This serves as the delimiter of an implicit
+// transaction and an error recovery point.
+//
+// Note that the request is not itself flushed to the server automatically; use Flush if
+// necessary. This copies the behavior of libpq PQsendPipelineSync.
+func (p *Pipeline) SendPipelineSync() {
+	if p.closed {
+		return
+	}
+
+	p.conn.frontend.SendSync(&pgproto3.Sync{})
+	p.state.PushBackRequestType(pipelineSyncRequest)
 }
 
 // Flush flushes the queued requests without establishing a synchronization point.
@@ -2115,28 +2286,14 @@ func (p *Pipeline) Flush() error {
 		return err
 	}
 
+	p.state.RegisterSendingToServer()
 	return nil
 }
 
 // Sync establishes a synchronization point and flushes the queued requests.
 func (p *Pipeline) Sync() error {
-	if p.closed {
-		if p.err != nil {
-			return p.err
-		}
-		return errors.New("pipeline closed")
-	}
-
-	p.conn.frontend.SendSync(&pgproto3.Sync{})
-	err := p.Flush()
-	if err != nil {
-		return err
-	}
-
-	p.pendingSync = false
-	p.expectedReadyForQueryCount++
-
-	return nil
+	p.SendPipelineSync()
+	return p.Flush()
 }
 
 // GetResults gets the next results. If results are present, results may be a *ResultReader, *StatementDescription, or
@@ -2150,7 +2307,7 @@ func (p *Pipeline) GetResults() (results any, err error) {
 		return nil, errors.New("pipeline closed")
 	}
 
-	if p.expectedReadyForQueryCount == 0 {
+	if p.state.ExtractFrontRequestType() == pipelineNil {
 		return nil, nil
 	}
 
@@ -2195,13 +2352,13 @@ func (p *Pipeline) getResults() (results any, err error) {
 		case *pgproto3.CloseComplete:
 			return &CloseComplete{}, nil
 		case *pgproto3.ReadyForQuery:
-			p.expectedReadyForQueryCount--
+			p.state.HandleReadyForQuery()
 			return &PipelineSync{}, nil
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		}
-
 	}
 }
 
@@ -2231,6 +2388,7 @@ func (p *Pipeline) getResultsPrepare() (*StatementDescription, error) {
 		// These should never happen here. But don't take chances that could lead to a deadlock.
 		case *pgproto3.ErrorResponse:
 			pgErr := ErrorResponseToPgError(msg)
+			p.state.HandleError(pgErr)
 			return nil, pgErr
 		case *pgproto3.CommandComplete:
 			p.conn.asyncClose()
@@ -2250,7 +2408,7 @@ func (p *Pipeline) Close() error {
 
 	p.closed = true
 
-	if p.pendingSync {
+	if p.state.PendingSync() {
 		p.conn.asyncClose()
 		p.err = errors.New("pipeline has unsynced requests")
 		p.conn.contextWatcher.Unwatch()
@@ -2259,7 +2417,7 @@ func (p *Pipeline) Close() error {
 		return p.err
 	}
 
-	for p.expectedReadyForQueryCount > 0 {
+	for p.state.ExpectedReadyForQuery() > 0 {
 		_, err := p.getResults()
 		if err != nil {
 			p.err = err
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
index ac2962e9..415e1a24 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_cleartext_password.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationCleartextPassword is a message sent from the backend indicating that a clear-text password is required.
-type AuthenticationCleartextPassword struct {
-}
+type AuthenticationCleartextPassword struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationCleartextPassword) Backend() {}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
index ec11d39f..98c0b2d6 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/authentication_ok.go
@@ -9,8 +9,7 @@ import (
 )
 
 // AuthenticationOk is a message sent from the backend indicating that authentication was successful.
-type AuthenticationOk struct {
-}
+type AuthenticationOk struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*AuthenticationOk) Backend() {}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
index d146c338..28cff049 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/backend.go
@@ -175,7 +175,13 @@ func (b *Backend) Receive() (FrontendMessage, error) {
 		}
 
 		b.msgType = header[0]
-		b.bodyLen = int(binary.BigEndian.Uint32(header[1:])) - 4
+
+		msgLength := int(binary.BigEndian.Uint32(header[1:]))
+		if msgLength < 4 {
+			return nil, fmt.Errorf("invalid message length: %d", msgLength)
+		}
+
+		b.bodyLen = msgLength - 4
 		if b.maxBodyLen > 0 && b.bodyLen > b.maxBodyLen {
 			return nil, &ExceededMaxBodyLenErr{b.maxBodyLen, b.bodyLen}
 		}
@@ -282,9 +288,10 @@ func (b *Backend) SetAuthType(authType uint32) error {
 	return nil
 }
 
-// SetMaxBodyLen sets the maximum length of a message body in octets. If a message body exceeds this length, Receive will return
-// an error. This is useful for protecting against malicious clients that send large messages with the intent of
-// causing memory exhaustion.
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against malicious clients that send
+// large messages with the intent of causing memory exhaustion.
 // The default value is 0.
 // If maxBodyLen is 0, then no maximum is enforced.
 func (b *Backend) SetMaxBodyLen(maxBodyLen int) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
index 040814db..c3421a9b 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/copy_done.go
@@ -4,8 +4,7 @@ import (
 	"encoding/json"
 )
 
-type CopyDone struct {
-}
+type CopyDone struct{}
 
 // Backend identifies this message as sendable by the PostgreSQL backend.
 func (*CopyDone) Backend() {}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
index b41abbe1..056e547c 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/frontend.go
@@ -54,6 +54,7 @@ type Frontend struct {
 	portalSuspended                 PortalSuspended
 
 	bodyLen    int
+	maxBodyLen int // maxBodyLen is the maximum length of a message body in octets. If a message body exceeds this length, Receive will return an error.
 	msgType    byte
 	partialMsg bool
 	authType   uint32
@@ -317,6 +318,9 @@ func (f *Frontend) Receive() (BackendMessage, error) {
 		}
 
 		f.bodyLen = msgLength - 4
+		if f.maxBodyLen > 0 && f.bodyLen > f.maxBodyLen {
+			return nil, &ExceededMaxBodyLenErr{f.maxBodyLen, f.bodyLen}
+		}
 		f.partialMsg = true
 	}
 
@@ -452,3 +456,13 @@ func (f *Frontend) GetAuthType() uint32 {
 func (f *Frontend) ReadBufferLen() int {
 	return f.cr.wp - f.cr.rp
 }
+
+// SetMaxBodyLen sets the maximum length of a message body in octets.
+// If a message body exceeds this length, Receive will return an error.
+// This is useful for protecting against a corrupted server that sends
+// messages with incorrect length, which can cause memory exhaustion.
+// The default value is 0.
+// If maxBodyLen is 0, then no maximum is enforced.
+func (f *Frontend) SetMaxBodyLen(maxBodyLen int) {
+	f.maxBodyLen = maxBodyLen
+}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
index 70cb20cd..122d1341 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/gss_enc_request.go
@@ -10,8 +10,7 @@ import (
 
 const gssEncReqNumber = 80877104
 
-type GSSEncRequest struct {
-}
+type GSSEncRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*GSSEncRequest) Frontend() {}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
index d820d327..67b78515 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/password_message.go
@@ -12,7 +12,7 @@ type PasswordMessage struct {
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*PasswordMessage) Frontend() {}
 
-// Frontend identifies this message as an authentication response.
+// InitialResponse identifies this message as an authentication response.
 func (*PasswordMessage) InitialResponse() {}
 
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
index dc2a4ddf..c40a2261 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/row_description.go
@@ -56,7 +56,6 @@ func (*RowDescription) Backend() {}
 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
 // type identifier and 4 byte message length.
 func (dst *RowDescription) Decode(src []byte) error {
-
 	if len(src) < 2 {
 		return &invalidMessageFormatErr{messageType: "RowDescription"}
 	}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
index b0fc2847..bdfc7c42 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgproto3/ssl_request.go
@@ -10,8 +10,7 @@ import (
 
 const sslRequestNumber = 80877103
 
-type SSLRequest struct {
-}
+type SSLRequest struct{}
 
 // Frontend identifies this message as sendable by a PostgreSQL frontend.
 func (*SSLRequest) Frontend() {}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
index 06b824ad..872a0889 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/array.go
@@ -374,8 +374,8 @@ func quoteArrayElementIfNeeded(src string) string {
 	return src
 }
 
-// Array represents a PostgreSQL array for T. It implements the ArrayGetter and ArraySetter interfaces. It preserves
-// PostgreSQL dimensions and custom lower bounds. Use FlatArray if these are not needed.
+// Array represents a PostgreSQL array for T. It implements the [ArrayGetter] and [ArraySetter] interfaces. It preserves
+// PostgreSQL dimensions and custom lower bounds. Use [FlatArray] if these are not needed.
 type Array[T any] struct {
 	Elements []T
 	Dims     []ArrayDimension
@@ -419,8 +419,8 @@ func (a Array[T]) ScanIndexType() any {
 	return new(T)
 }
 
-// FlatArray implements the ArrayGetter and ArraySetter interfaces for any slice of T. It ignores PostgreSQL dimensions
-// and custom lower bounds. Use Array to preserve these.
+// FlatArray implements the [ArrayGetter] and [ArraySetter] interfaces for any slice of T. It ignores PostgreSQL dimensions
+// and custom lower bounds. Use [Array] to preserve these.
 type FlatArray[T any] []T
 
 func (a FlatArray[T]) Dimensions() []ArrayDimension {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
index e7a1d016..2a48e354 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bits.go
@@ -23,16 +23,18 @@ type Bits struct {
 	Valid bool
 }
 
+// ScanBits implements the [BitsScanner] interface.
 func (b *Bits) ScanBits(v Bits) error {
 	*b = v
 	return nil
 }
 
+// BitsValue implements the [BitsValuer] interface.
 func (b Bits) BitsValue() (Bits, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bits) Scan(src any) error {
 	if src == nil {
 		*dst = Bits{}
@@ -47,7 +49,7 @@ func (dst *Bits) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bits) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBitsCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BitsCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
index 71caffa7..955f01fe 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bool.go
@@ -22,16 +22,18 @@ type Bool struct {
 	Valid bool
 }
 
+// ScanBool implements the [BoolScanner] interface.
 func (b *Bool) ScanBool(v Bool) error {
 	*b = v
 	return nil
 }
 
+// BoolValue implements the [BoolValuer] interface.
 func (b Bool) BoolValue() (Bool, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Bool) Scan(src any) error {
 	if src == nil {
 		*dst = Bool{}
@@ -61,7 +63,7 @@ func (dst *Bool) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Bool) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Bool) Value() (driver.Value, error) {
 	return src.Bool, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Bool) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -82,6 +85,7 @@ func (src Bool) MarshalJSON() ([]byte, error) {
 	}
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Bool) UnmarshalJSON(b []byte) error {
 	var v *bool
 	err := json.Unmarshal(b, &v)
@@ -200,7 +204,6 @@ func (encodePlanBoolCodecTextBool) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (BoolCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -328,7 +331,7 @@ func (scanPlanTextAnyToBoolScanner) Scan(src []byte, dst any) error {
 	return s.ScanBool(Bool{Bool: v, Valid: true})
 }
 
-// https://www.postgresql.org/docs/11/datatype-boolean.html
+// https://www.postgresql.org/docs/current/datatype-boolean.html
 func planTextToBool(src []byte) (bool, error) {
 	s := string(bytes.ToLower(bytes.TrimSpace(src)))
 
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
index 887d268b..d243f58e 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/box.go
@@ -24,16 +24,18 @@ type Box struct {
 	Valid bool
 }
 
+// ScanBox implements the [BoxScanner] interface.
 func (b *Box) ScanBox(v Box) error {
 	*b = v
 	return nil
 }
 
+// BoxValue implements the [BoxValuer] interface.
 func (b Box) BoxValue() (Box, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Box) Scan(src any) error {
 	if src == nil {
 		*dst = Box{}
@@ -48,7 +50,7 @@ func (dst *Box) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Box) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanBoxCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (BoxCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
index b39d3fa1..84964425 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/builtin_wrappers.go
@@ -527,6 +527,7 @@ func (w *netIPNetWrapper) ScanNetipPrefix(v netip.Prefix) error {
 
 	return nil
 }
+
 func (w netIPNetWrapper) NetipPrefixValue() (netip.Prefix, error) {
 	ip, ok := netip.AddrFromSlice(w.IP)
 	if !ok {
@@ -881,7 +882,6 @@ func (a *anyMultiDimSliceArray) SetDimensions(dimensions []ArrayDimension) error
 
 		return nil
 	}
-
 }
 
 func (a *anyMultiDimSliceArray) makeMultidimensionalSlice(sliceType reflect.Type, dimensions []ArrayDimension, flatSlice reflect.Value, flatSliceIdx int) reflect.Value {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
index a247705e..6c4f0c5e 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/bytea.go
@@ -148,7 +148,6 @@ func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf
 }
 
 func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
index e8f118cc..fb9b4c11 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/circle.go
@@ -25,16 +25,18 @@ type Circle struct {
 	Valid bool
 }
 
+// ScanCircle implements the [CircleScanner] interface.
 func (c *Circle) ScanCircle(v Circle) error {
 	*c = v
 	return nil
 }
 
+// CircleValue implements the [CircleValuer] interface.
 func (c Circle) CircleValue() (Circle, error) {
 	return c, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Circle) Scan(src any) error {
 	if src == nil {
 		*dst = Circle{}
@@ -49,7 +51,7 @@ func (dst *Circle) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Circle) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
index fb372325..598cf7af 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/composite.go
@@ -276,7 +276,6 @@ func (c *CompositeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byt
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
 
 type CompositeBinaryScanner struct {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
index 784b16de..44705686 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/date.go
@@ -26,11 +26,13 @@ type Date struct {
 	Valid            bool
 }
 
+// ScanDate implements the [DateScanner] interface.
 func (d *Date) ScanDate(v Date) error {
 	*d = v
 	return nil
 }
 
+// DateValue implements the [DateValuer] interface.
 func (d Date) DateValue() (Date, error) {
 	return d, nil
 }
@@ -40,7 +42,7 @@ const (
 	infinityDayOffset         = 2147483647
 )
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Date) Scan(src any) error {
 	if src == nil {
 		*dst = Date{}
@@ -58,7 +60,7 @@ func (dst *Date) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Date) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -70,6 +72,7 @@ func (src Date) Value() (driver.Value, error) {
 	return src.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Date) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -89,6 +92,7 @@ func (src Date) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Date) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -223,7 +227,6 @@ func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
index 7687ea8f..83dfc5de 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/doc.go
@@ -53,8 +53,8 @@ similar fashion to database/sql. The second is to use a pointer to a pointer.
         return err
     }
 
-When using nullable pgtype types as parameters for queries, one has to remember
-to explicitly set their Valid field to true, otherwise the parameter's value will be NULL.
+When using nullable pgtype types as parameters for queries, one has to remember to explicitly set their Valid field to
+true, otherwise the parameter's value will be NULL.
 
 JSON Support
 
@@ -159,11 +159,16 @@ example_child_records_test.go for an example.
 
 Overview of Scanning Implementation
 
-The first step is to use the OID to lookup the correct Codec. If the OID is unavailable, Map will try to find the OID
-from previous calls of Map.RegisterDefaultPgType. The Map will call the Codec's PlanScan method to get a plan for
-scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types are
-interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner and
-PointValuer interfaces.
+The first step is to use the OID to lookup the correct Codec. The Map will call the Codec's PlanScan method to get a
+plan for scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types
+are interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner
+and PointValuer interfaces.
+
+If a Go value is not supported directly by a Codec then Map will try see if it is a sql.Scanner. If is then that
+interface will be used to scan the value. Most sql.Scanners require the input to be in the text format (e.g. UUIDs and
+numeric). However, pgx will typically have received the value in the binary format. In this case the binary value will be
+parsed, reencoded as text, and then passed to the sql.Scanner. This may incur additional overhead for query results with
+a large number of affected values.
 
 If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again.
 For example, Int8Codec does not support scanning into a renamed type (e.g. type myInt64 int64). But Map will detect that
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
index 8646d9d2..241a25ad 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float4.go
@@ -16,26 +16,29 @@ type Float4 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float4) ScanFloat64(n Float8) error {
 	*f = Float4{Float32: float32(n.Float64), Valid: n.Valid}
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float4) Float64Value() (Float8, error) {
 	return Float8{Float64: float64(f.Float32), Valid: f.Valid}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float4) ScanInt64(n Int8) error {
 	*f = Float4{Float32: float32(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float32), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float4) Scan(src any) error {
 	if src == nil {
 		*f = Float4{}
@@ -58,7 +61,7 @@ func (f *Float4) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float4) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -66,6 +69,7 @@ func (f Float4) Value() (driver.Value, error) {
 	return float64(f.Float32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float4) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -73,6 +77,7 @@ func (f Float4) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float32)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float4) UnmarshalJSON(b []byte) error {
 	var n *float32
 	err := json.Unmarshal(b, &n)
@@ -170,7 +175,6 @@ func (encodePlanFloat4CodecBinaryInt64Valuer) Encode(value any, buf []byte) (new
 }
 
 func (Float4Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
index 9c923c9a..54d6781e 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/float8.go
@@ -24,26 +24,29 @@ type Float8 struct {
 	Valid   bool
 }
 
-// ScanFloat64 implements the Float64Scanner interface.
+// ScanFloat64 implements the [Float64Scanner] interface.
 func (f *Float8) ScanFloat64(n Float8) error {
 	*f = n
 	return nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (f Float8) Float64Value() (Float8, error) {
 	return f, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (f *Float8) ScanInt64(n Int8) error {
 	*f = Float8{Float64: float64(n.Int64), Valid: n.Valid}
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (f Float8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(f.Float64), Valid: f.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (f *Float8) Scan(src any) error {
 	if src == nil {
 		*f = Float8{}
@@ -66,7 +69,7 @@ func (f *Float8) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (f Float8) Value() (driver.Value, error) {
 	if !f.Valid {
 		return nil, nil
@@ -74,6 +77,7 @@ func (f Float8) Value() (driver.Value, error) {
 	return f.Float64, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (f Float8) MarshalJSON() ([]byte, error) {
 	if !f.Valid {
 		return []byte("null"), nil
@@ -81,6 +85,7 @@ func (f Float8) MarshalJSON() ([]byte, error) {
 	return json.Marshal(f.Float64)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (f *Float8) UnmarshalJSON(b []byte) error {
 	var n *float64
 	err := json.Unmarshal(b, &n)
@@ -208,7 +213,6 @@ func (encodePlanTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (Float8Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
index 2f34f4c9..ef864928 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/hstore.go
@@ -22,16 +22,18 @@ type HstoreValuer interface {
 // associated with its keys.
 type Hstore map[string]*string
 
+// ScanHstore implements the [HstoreScanner] interface.
 func (h *Hstore) ScanHstore(v Hstore) error {
 	*h = v
 	return nil
 }
 
+// HstoreValue implements the [HstoreValuer] interface.
 func (h Hstore) HstoreValue() (Hstore, error) {
 	return h, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (h *Hstore) Scan(src any) error {
 	if src == nil {
 		*h = nil
@@ -46,7 +48,7 @@ func (h *Hstore) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (h Hstore) Value() (driver.Value, error) {
 	if h == nil {
 		return nil, nil
@@ -162,7 +164,6 @@ func (encodePlanHstoreCodecText) Encode(value any, buf []byte) (newBuf []byte, e
 }
 
 func (HstoreCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
@@ -298,7 +299,7 @@ func (p *hstoreParser) consume() (b byte, end bool) {
 	return b, false
 }
 
-func unexpectedByteErr(actualB byte, expectedB byte) error {
+func unexpectedByteErr(actualB, expectedB byte) error {
 	return fmt.Errorf("expected '%c' ('%#v'); found '%c' ('%#v')", expectedB, expectedB, actualB, actualB)
 }
 
@@ -316,7 +317,7 @@ func (p *hstoreParser) consumeExpectedByte(expectedB byte) error {
 
 // consumeExpected2 consumes two expected bytes or returns an error.
 // This was a bit faster than using a string argument (better inlining? Not sure).
-func (p *hstoreParser) consumeExpected2(one byte, two byte) error {
+func (p *hstoreParser) consumeExpected2(one, two byte) error {
 	if p.pos+2 > len(p.str) {
 		return errors.New("unexpected end of string")
 	}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
index 6ca10ea0..b92edb23 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/inet.go
@@ -24,7 +24,7 @@ type NetipPrefixValuer interface {
 	NetipPrefixValue() (netip.Prefix, error)
 }
 
-// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are netip.Prefix and netip.Addr. If
+// InetCodec handles both inet and cidr PostgreSQL types. The preferred Go types are [netip.Prefix] and [netip.Addr]. If
 // IsValid() is false then they are treated as SQL NULL.
 type InetCodec struct{}
 
@@ -107,7 +107,6 @@ func (encodePlanInetCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (InetCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
index 90a20a26..d1b8eb61 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go
@@ -1,4 +1,5 @@
-// Do not edit. Generated from pgtype/int.go.erb
+// Code generated from pgtype/int.go.erb. DO NOT EDIT.
+
 package pgtype
 
 import (
@@ -25,7 +26,7 @@ type Int2 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int2) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int2{}
@@ -43,11 +44,12 @@ func (dst *Int2) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int2) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int16), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int2) Scan(src any) error {
 	if src == nil {
 		*dst = Int2{}
@@ -86,7 +88,7 @@ func (dst *Int2) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int2) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -94,6 +96,7 @@ func (src Int2) Value() (driver.Value, error) {
 	return int64(src.Int16), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int2) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -101,6 +104,7 @@ func (src Int2) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int16), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int2) UnmarshalJSON(b []byte) error {
 	var n *int16
 	err := json.Unmarshal(b, &n)
@@ -585,7 +589,7 @@ type Int4 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int4) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int4{}
@@ -603,11 +607,12 @@ func (dst *Int4) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int4) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int32), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int4) Scan(src any) error {
 	if src == nil {
 		*dst = Int4{}
@@ -646,7 +651,7 @@ func (dst *Int4) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int4) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -654,6 +659,7 @@ func (src Int4) Value() (driver.Value, error) {
 	return int64(src.Int32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int4) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -661,6 +667,7 @@ func (src Int4) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int32), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int4) UnmarshalJSON(b []byte) error {
 	var n *int32
 	err := json.Unmarshal(b, &n)
@@ -1156,7 +1163,7 @@ type Int8 struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int8) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int8{}
@@ -1174,11 +1181,12 @@ func (dst *Int8) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int8) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int64), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int8) Scan(src any) error {
 	if src == nil {
 		*dst = Int8{}
@@ -1217,7 +1225,7 @@ func (dst *Int8) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int8) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -1225,6 +1233,7 @@ func (src Int8) Value() (driver.Value, error) {
 	return int64(src.Int64), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int8) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -1232,6 +1241,7 @@ func (src Int8) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int64), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int8) UnmarshalJSON(b []byte) error {
 	var n *int64
 	err := json.Unmarshal(b, &n)
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
index e0c8b7a3..c2d40f60 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/int.go.erb
@@ -27,7 +27,7 @@ type Int<%= pg_byte_size %> struct {
 	Valid bool
 }
 
-// ScanInt64 implements the Int64Scanner interface.
+// ScanInt64 implements the [Int64Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	if !n.Valid {
 		*dst = Int<%= pg_byte_size %>{}
@@ -45,11 +45,12 @@ func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) {
 	return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	if src == nil {
 		*dst = Int<%= pg_byte_size %>{}
@@ -88,7 +89,7 @@ func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +97,7 @@ func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
 	return int64(src.Int<%= pg_bit_size %>), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -103,6 +105,7 @@ func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
 	return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error {
 	var n *int<%= pg_bit_size %>
 	err := json.Unmarshal(b, &n)
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
index 0175700a..6f401153 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/integration_benchmark_test.go.erb
@@ -25,7 +25,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_<%= pg_type %>_to_Go_<%= go
       rows, _ := conn.Query(
         ctx,
         `select <% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>n::<%= pg_type %> + <%= col_idx%><% end %> from generate_series(1, <%= rows %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{<% columns.times do |col_idx| %><% if col_idx != 0 %>, <% end %>&v[<%= col_idx%>]<% end %>},  func() error { return nil })
       if err != nil {
@@ -49,7 +49,7 @@ func BenchmarkQuery<%= format_name %>FormatDecode_PG_Int4Array_With_Go_Int4Array
       rows, _ := conn.Query(
         ctx,
         `select array_agg(n) from generate_series(1, <%= array_size %>) n`,
-        []any{pgx.QueryResultFormats{<%= format_code %>}},
+        pgx.QueryResultFormats{<%= format_code %>},
       )
       _, err := pgx.ForEachRow(rows, []any{&v},  func() error { return nil })
       if err != nil {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
index 4b511629..ba5e818f 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/interval.go
@@ -33,16 +33,18 @@ type Interval struct {
 	Valid        bool
 }
 
+// ScanInterval implements the [IntervalScanner] interface.
 func (interval *Interval) ScanInterval(v Interval) error {
 	*interval = v
 	return nil
 }
 
+// IntervalValue implements the [IntervalValuer] interface.
 func (interval Interval) IntervalValue() (Interval, error) {
 	return interval, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (interval *Interval) Scan(src any) error {
 	if src == nil {
 		*interval = Interval{}
@@ -57,7 +59,7 @@ func (interval *Interval) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (interval Interval) Value() (driver.Value, error) {
 	if !interval.Valid {
 		return nil, nil
@@ -157,7 +159,6 @@ func (encodePlanIntervalCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (IntervalCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
index c2aa0d3b..60aa2b71 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/json.go
@@ -71,6 +71,27 @@ func (c *JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Enco
 	}
 }
 
+// JSON needs its on scan plan for pointers to handle 'null'::json(b).
+// Consider making pointerPointerScanPlan more flexible in the future.
+type jsonPointerScanPlan struct {
+	next ScanPlan
+}
+
+func (p jsonPointerScanPlan) Scan(src []byte, dst any) error {
+	el := reflect.ValueOf(dst).Elem()
+	if src == nil || string(src) == "null" {
+		el.SetZero()
+		return nil
+	}
+
+	el.Set(reflect.New(el.Type().Elem()))
+	if p.next != nil {
+		return p.next.Scan(src, el.Interface())
+	}
+
+	return nil
+}
+
 type encodePlanJSONCodecEitherFormatString struct{}
 
 func (encodePlanJSONCodecEitherFormatString) Encode(value any, buf []byte) (newBuf []byte, err error) {
@@ -117,41 +138,35 @@ func (e *encodePlanJSONCodecEitherFormatMarshal) Encode(value any, buf []byte) (
 	return buf, nil
 }
 
-func (c *JSONCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+func (c *JSONCodec) PlanScan(m *Map, oid uint32, formatCode int16, target any) ScanPlan {
+	return c.planScan(m, oid, formatCode, target, 0)
+}
+
+// JSON cannot fallback to pointerPointerScanPlan because of 'null'::json(b),
+// so we need to duplicate the logic here.
+func (c *JSONCodec) planScan(m *Map, oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	switch target.(type) {
 	case *string:
-		return scanPlanAnyToString{}
-
-	case **string:
-		// This is to fix **string scanning. It seems wrong to special case **string, but it's not clear what a better
-		// solution would be.
-		//
-		// https://github.com/jackc/pgx/issues/1470 -- **string
-		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
-
-		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
-				if _, failed := nextPlan.(*scanPlanFail); !failed {
-					wrapperPlan.SetNext(nextPlan)
-					return wrapperPlan
-				}
-			}
-		}
-
+		return &scanPlanAnyToString{}
 	case *[]byte:
-		return scanPlanJSONToByteSlice{}
+		return &scanPlanJSONToByteSlice{}
 	case BytesScanner:
-		return scanPlanBinaryBytesToBytesScanner{}
-
-	// Cannot rely on sql.Scanner being handled later because scanPlanJSONToJSONUnmarshal will take precedence.
-	//
-	// https://github.com/jackc/pgx/issues/1418
+		return &scanPlanBinaryBytesToBytesScanner{}
 	case sql.Scanner:
-		return &scanPlanSQLScanner{formatCode: format}
+		return &scanPlanSQLScanner{formatCode: formatCode}
 	}
 
-	return &scanPlanJSONToJSONUnmarshal{
-		unmarshal: c.Unmarshal,
+	rv := reflect.ValueOf(target)
+	if rv.Kind() == reflect.Pointer && rv.Elem().Kind() == reflect.Pointer {
+		var plan jsonPointerScanPlan
+		plan.next = c.planScan(m, oid, formatCode, rv.Elem().Interface(), depth+1)
+		return plan
+	} else {
+		return &scanPlanJSONToJSONUnmarshal{unmarshal: c.Unmarshal}
 	}
 }
 
@@ -196,7 +211,12 @@ func (s *scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error {
 		return fmt.Errorf("cannot scan NULL into %T", dst)
 	}
 
-	elem := reflect.ValueOf(dst).Elem()
+	v := reflect.ValueOf(dst)
+	if v.Kind() != reflect.Pointer || v.IsNil() {
+		return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", dst)
+	}
+
+	elem := v.Elem()
 	elem.Set(reflect.Zero(elem.Type()))
 
 	return s.unmarshal(src, dst)
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
index 4ae8003e..10efc8ce 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/line.go
@@ -24,11 +24,13 @@ type Line struct {
 	Valid   bool
 }
 
+// ScanLine implements the [LineScanner] interface.
 func (line *Line) ScanLine(v Line) error {
 	*line = v
 	return nil
 }
 
+// LineValue implements the [LineValuer] interface.
 func (line Line) LineValue() (Line, error) {
 	return line, nil
 }
@@ -37,7 +39,7 @@ func (line *Line) Set(src any) error {
 	return fmt.Errorf("cannot convert %v to Line", src)
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (line *Line) Scan(src any) error {
 	if src == nil {
 		*line = Line{}
@@ -52,7 +54,7 @@ func (line *Line) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (line Line) Value() (driver.Value, error) {
 	if !line.Valid {
 		return nil, nil
@@ -129,7 +131,6 @@ func (encodePlanLineCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LineCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
index 05a86e1c..ed0d40d2 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/lseg.go
@@ -24,16 +24,18 @@ type Lseg struct {
 	Valid bool
 }
 
+// ScanLseg implements the [LsegScanner] interface.
 func (lseg *Lseg) ScanLseg(v Lseg) error {
 	*lseg = v
 	return nil
 }
 
+// LsegValue implements the [LsegValuer] interface.
 func (lseg Lseg) LsegValue() (Lseg, error) {
 	return lseg, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (lseg *Lseg) Scan(src any) error {
 	if src == nil {
 		*lseg = Lseg{}
@@ -48,7 +50,7 @@ func (lseg *Lseg) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (lseg Lseg) Value() (driver.Value, error) {
 	if !lseg.Valid {
 		return nil, nil
@@ -127,7 +129,6 @@ func (encodePlanLsegCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (LsegCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
index e5763788..4fe6dd40 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/multirange.go
@@ -374,7 +374,6 @@ parseValueLoop:
 	}
 
 	return elements, nil
-
 }
 
 func parseRange(buf *bytes.Buffer) (string, error) {
@@ -403,8 +402,8 @@ func parseRange(buf *bytes.Buffer) (string, error) {
 
 // Multirange is a generic multirange type.
 //
-// T should implement RangeValuer and *T should implement RangeScanner. However, there does not appear to be a way to
-// enforce the RangeScanner constraint.
+// T should implement [RangeValuer] and *T should implement [RangeScanner]. However, there does not appear to be a way to
+// enforce the [RangeScanner] constraint.
 type Multirange[T RangeValuer] []T
 
 func (r Multirange[T]) IsNull() bool {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
index 4dbec786..7d236902 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/numeric.go
@@ -27,16 +27,20 @@ const (
 	pgNumericNegInfSign = 0xf000
 )
 
-var big0 *big.Int = big.NewInt(0)
-var big1 *big.Int = big.NewInt(1)
-var big10 *big.Int = big.NewInt(10)
-var big100 *big.Int = big.NewInt(100)
-var big1000 *big.Int = big.NewInt(1000)
+var (
+	big0    *big.Int = big.NewInt(0)
+	big1    *big.Int = big.NewInt(1)
+	big10   *big.Int = big.NewInt(10)
+	big100  *big.Int = big.NewInt(100)
+	big1000 *big.Int = big.NewInt(1000)
+)
 
-var bigNBase *big.Int = big.NewInt(nbase)
-var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
-var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
-var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+var (
+	bigNBase   *big.Int = big.NewInt(nbase)
+	bigNBaseX2 *big.Int = big.NewInt(nbase * nbase)
+	bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase)
+	bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase)
+)
 
 type NumericScanner interface {
 	ScanNumeric(v Numeric) error
@@ -54,15 +58,18 @@ type Numeric struct {
 	Valid            bool
 }
 
+// ScanNumeric implements the [NumericScanner] interface.
 func (n *Numeric) ScanNumeric(v Numeric) error {
 	*n = v
 	return nil
 }
 
+// NumericValue implements the [NumericValuer] interface.
 func (n Numeric) NumericValue() (Numeric, error) {
 	return n, nil
 }
 
+// Float64Value implements the [Float64Valuer] interface.
 func (n Numeric) Float64Value() (Float8, error) {
 	if !n.Valid {
 		return Float8{}, nil
@@ -92,6 +99,7 @@ func (n Numeric) Float64Value() (Float8, error) {
 	return Float8{Float64: f, Valid: true}, nil
 }
 
+// ScanInt64 implements the [Int64Scanner] interface.
 func (n *Numeric) ScanInt64(v Int8) error {
 	if !v.Valid {
 		*n = Numeric{}
@@ -102,6 +110,7 @@ func (n *Numeric) ScanInt64(v Int8) error {
 	return nil
 }
 
+// Int64Value implements the [Int64Valuer] interface.
 func (n Numeric) Int64Value() (Int8, error) {
 	if !n.Valid {
 		return Int8{}, nil
@@ -203,7 +212,7 @@ func nbaseDigitsToInt64(src []byte) (accum int64, bytesRead, digitsRead int) {
 	return accum, rp, digits
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (n *Numeric) Scan(src any) error {
 	if src == nil {
 		*n = Numeric{}
@@ -218,7 +227,7 @@ func (n *Numeric) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (n Numeric) Value() (driver.Value, error) {
 	if !n.Valid {
 		return nil, nil
@@ -231,6 +240,7 @@ func (n Numeric) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (n Numeric) MarshalJSON() ([]byte, error) {
 	if !n.Valid {
 		return []byte("null"), nil
@@ -243,6 +253,7 @@ func (n Numeric) MarshalJSON() ([]byte, error) {
 	return n.numberTextBytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (n *Numeric) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte(`null`)) {
 		*n = Numeric{}
@@ -553,7 +564,6 @@ func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) {
 }
 
 func (NumericCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
index 73e0ec52..81dc1e5b 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/path.go
@@ -25,16 +25,18 @@ type Path struct {
 	Valid  bool
 }
 
+// ScanPath implements the [PathScanner] interface.
 func (path *Path) ScanPath(v Path) error {
 	*path = v
 	return nil
 }
 
+// PathValue implements the [PathValuer] interface.
 func (path Path) PathValue() (Path, error) {
 	return path, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (path *Path) Scan(src any) error {
 	if src == nil {
 		*path = Path{}
@@ -49,7 +51,7 @@ func (path *Path) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (path Path) Value() (driver.Value, error) {
 	if !path.Valid {
 		return nil, nil
@@ -154,7 +156,6 @@ func (encodePlanPathCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (PathCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
index bdd9f05c..b3ef3207 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go
@@ -29,6 +29,7 @@ const (
 	XMLOID                 = 142
 	XMLArrayOID            = 143
 	JSONArrayOID           = 199
+	XID8ArrayOID           = 271
 	PointOID               = 600
 	LsegOID                = 601
 	PathOID                = 602
@@ -117,6 +118,7 @@ const (
 	TstzmultirangeOID      = 4534
 	DatemultirangeOID      = 4535
 	Int8multirangeOID      = 4536
+	XID8OID                = 5069
 	Int4multirangeArrayOID = 6150
 	NummultirangeArrayOID  = 6151
 	TsmultirangeArrayOID   = 6152
@@ -200,7 +202,6 @@ type Map struct {
 
 	reflectTypeToType map[reflect.Type]*Type
 
-	memoizedScanPlans   map[uint32]map[reflect.Type][2]ScanPlan
 	memoizedEncodePlans map[uint32]map[reflect.Type][2]EncodePlan
 
 	// TryWrapEncodePlanFuncs is a slice of functions that will wrap a value that cannot be encoded by the Codec. Every
@@ -234,7 +235,6 @@ func NewMap() *Map {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -274,9 +274,6 @@ func (m *Map) RegisterType(t *Type) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -290,9 +287,6 @@ func (m *Map) RegisterDefaultPgType(value any, name string) {
 
 	// Invalidated by type registration
 	m.reflectTypeToType = nil
-	for k := range m.memoizedScanPlans {
-		delete(m.memoizedScanPlans, k)
-	}
 	for k := range m.memoizedEncodePlans {
 		delete(m.memoizedEncodePlans, k)
 	}
@@ -395,6 +389,7 @@ type scanPlanSQLScanner struct {
 
 func (plan *scanPlanSQLScanner) Scan(src []byte, dst any) error {
 	scanner := dst.(sql.Scanner)
+
 	if src == nil {
 		// This is necessary because interface value []byte:nil does not equal nil:nil for the binary format path and the
 		// text format path would be converted to empty string.
@@ -449,14 +444,14 @@ func (plan *scanPlanFail) Scan(src []byte, dst any) error {
 		// As a horrible hack try all types to find anything that can scan into dst.
 		for oid := range plan.m.oidToType {
 			// using planScan instead of Scan or PlanScan to avoid polluting the planned scan cache.
-			plan := plan.m.planScan(oid, plan.formatCode, dst)
+			plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 			if _, ok := plan.(*scanPlanFail); !ok {
 				return plan.Scan(src, dst)
 			}
 		}
 		for oid := range defaultMap.oidToType {
 			if _, ok := plan.m.oidToType[oid]; !ok {
-				plan := plan.m.planScan(oid, plan.formatCode, dst)
+				plan := plan.m.planScan(oid, plan.formatCode, dst, 0)
 				if _, ok := plan.(*scanPlanFail); !ok {
 					return plan.Scan(src, dst)
 				}
@@ -1064,24 +1059,14 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error {
 
 // PlanScan prepares a plan to scan a value into target.
 func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan {
-	oidMemo := m.memoizedScanPlans[oid]
-	if oidMemo == nil {
-		oidMemo = make(map[reflect.Type][2]ScanPlan)
-		m.memoizedScanPlans[oid] = oidMemo
-	}
-	targetReflectType := reflect.TypeOf(target)
-	typeMemo := oidMemo[targetReflectType]
-	plan := typeMemo[formatCode]
-	if plan == nil {
-		plan = m.planScan(oid, formatCode, target)
-		typeMemo[formatCode] = plan
-		oidMemo[targetReflectType] = typeMemo
-	}
-
-	return plan
+	return m.planScan(oid, formatCode, target, 0)
 }
 
-func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
+func (m *Map) planScan(oid uint32, formatCode int16, target any, depth int) ScanPlan {
+	if depth > 8 {
+		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
+	}
+
 	if target == nil {
 		return &scanPlanFail{m: m, oid: oid, formatCode: formatCode}
 	}
@@ -1141,7 +1126,7 @@ func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
 
 	for _, f := range m.TryWrapScanPlanFuncs {
 		if wrapperPlan, nextDst, ok := f(target); ok {
-			if nextPlan := m.planScan(oid, formatCode, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, formatCode, nextDst, depth+1); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
@@ -1198,9 +1183,18 @@ func codecDecodeToTextFormat(codec Codec, m *Map, oid uint32, format int16, src
 	}
 }
 
-// PlanEncode returns an Encode plan for encoding value into PostgreSQL format for oid and format. If no plan can be
+// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be
 // found then nil is returned.
 func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
+	return m.planEncodeDepth(oid, format, value, 0)
+}
+
+func (m *Map) planEncodeDepth(oid uint32, format int16, value any, depth int) EncodePlan {
+	// Guard against infinite recursion.
+	if depth > 8 {
+		return nil
+	}
+
 	oidMemo := m.memoizedEncodePlans[oid]
 	if oidMemo == nil {
 		oidMemo = make(map[reflect.Type][2]EncodePlan)
@@ -1210,7 +1204,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	typeMemo := oidMemo[targetReflectType]
 	plan := typeMemo[format]
 	if plan == nil {
-		plan = m.planEncode(oid, format, value)
+		plan = m.planEncode(oid, format, value, depth)
 		typeMemo[format] = plan
 		oidMemo[targetReflectType] = typeMemo
 	}
@@ -1218,7 +1212,7 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
 	return plan
 }
 
-func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
+func (m *Map) planEncode(oid uint32, format int16, value any, depth int) EncodePlan {
 	if format == TextFormatCode {
 		switch value.(type) {
 		case string:
@@ -1249,7 +1243,7 @@ func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
 
 	for _, f := range m.TryWrapEncodePlanFuncs {
 		if wrapperPlan, nextValue, ok := f(value); ok {
-			if nextPlan := m.PlanEncode(oid, format, nextValue); nextPlan != nil {
+			if nextPlan := m.planEncodeDepth(oid, format, nextValue, depth+1); nextPlan != nil {
 				wrapperPlan.SetNext(nextPlan)
 				return wrapperPlan
 			}
@@ -2012,30 +2006,11 @@ func (w *sqlScannerWrapper) Scan(src any) error {
 	return w.m.Scan(t.OID, TextFormatCode, bufSrc, w.v)
 }
 
-// canBeNil returns true if value can be nil.
-func canBeNil(value any) bool {
-	refVal := reflect.ValueOf(value)
-	kind := refVal.Kind()
-	switch kind {
-	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
-		return true
-	default:
-		return false
-	}
-}
-
-// valuerReflectType is a reflect.Type for driver.Valuer. It has confusing syntax because reflect.TypeOf returns nil
-// when it's argument is a nil interface value. So we use a pointer to the interface and call Elem to get the actual
-// type. Yuck.
-//
-// This can be simplified in Go 1.22 with reflect.TypeFor.
-//
-// var valuerReflectType = reflect.TypeFor[driver.Valuer]()
-var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+var valuerReflectType = reflect.TypeFor[driver.Valuer]()
 
 // isNilDriverValuer returns true if value is any type of nil unless it implements driver.Valuer. *T is not considered to implement
 // driver.Valuer if it is only implemented by T.
-func isNilDriverValuer(value any) (isNil bool, callNilDriverValuer bool) {
+func isNilDriverValuer(value any) (isNil, callNilDriverValuer bool) {
 	if value == nil {
 		return true, false
 	}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
index c8125731..5648d89b 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/pgtype_default.go
@@ -23,7 +23,6 @@ func initDefaultMap() {
 		reflectTypeToName: make(map[reflect.Type]string),
 		oidToFormatCode:   make(map[uint32]int16),
 
-		memoizedScanPlans:   make(map[uint32]map[reflect.Type][2]ScanPlan),
 		memoizedEncodePlans: make(map[uint32]map[reflect.Type][2]EncodePlan),
 
 		TryWrapEncodePlanFuncs: []TryWrapEncodePlanFunc{
@@ -90,7 +89,26 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "varbit", OID: VarbitOID, Codec: BitsCodec{}})
 	defaultMap.RegisterType(&Type{Name: "varchar", OID: VarcharOID, Codec: TextCodec{}})
 	defaultMap.RegisterType(&Type{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}})
-	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{Marshal: xml.Marshal, Unmarshal: xml.Unmarshal}})
+	defaultMap.RegisterType(&Type{Name: "xid8", OID: XID8OID, Codec: Uint64Codec{}})
+	defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{
+		Marshal: xml.Marshal,
+		// xml.Unmarshal does not support unmarshalling into *any. However, XMLCodec.DecodeValue calls Unmarshal with a
+		// *any. Wrap xml.Marshal with a function that copies the data into a new byte slice in this case. Not implementing
+		// directly in XMLCodec.DecodeValue to allow for the unlikely possibility that someone uses an alternative XML
+		// unmarshaler that does support unmarshalling into *any.
+		//
+		// https://github.com/jackc/pgx/issues/2227
+		// https://github.com/jackc/pgx/pull/2228
+		Unmarshal: func(data []byte, v any) error {
+			if v, ok := v.(*any); ok {
+				dstBuf := make([]byte, len(data))
+				copy(dstBuf, data)
+				*v = dstBuf
+				return nil
+			}
+			return xml.Unmarshal(data, v)
+		},
+	}})
 
 	// Range types
 	defaultMap.RegisterType(&Type{Name: "daterange", OID: DaterangeOID, Codec: &RangeCodec{ElementType: defaultMap.oidToType[DateOID]}})
@@ -155,6 +173,7 @@ func initDefaultMap() {
 	defaultMap.RegisterType(&Type{Name: "_varbit", OID: VarbitArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarbitOID]}})
 	defaultMap.RegisterType(&Type{Name: "_varchar", OID: VarcharArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[VarcharOID]}})
 	defaultMap.RegisterType(&Type{Name: "_xid", OID: XIDArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XIDOID]}})
+	defaultMap.RegisterType(&Type{Name: "_xid8", OID: XID8ArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XID8OID]}})
 	defaultMap.RegisterType(&Type{Name: "_xml", OID: XMLArrayOID, Codec: &ArrayCodec{ElementType: defaultMap.oidToType[XMLOID]}})
 
 	// Integer types that directly map to a PostgreSQL type
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
index 09b19bb5..b701513d 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/point.go
@@ -30,11 +30,13 @@ type Point struct {
 	Valid bool
 }
 
+// ScanPoint implements the [PointScanner] interface.
 func (p *Point) ScanPoint(v Point) error {
 	*p = v
 	return nil
 }
 
+// PointValue implements the [PointValuer] interface.
 func (p Point) PointValue() (Point, error) {
 	return p, nil
 }
@@ -68,7 +70,7 @@ func parsePoint(src []byte) (*Point, error) {
 	return &Point{P: Vec2{x, y}, Valid: true}, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Point) Scan(src any) error {
 	if src == nil {
 		*dst = Point{}
@@ -83,7 +85,7 @@ func (dst *Point) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Point) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,7 @@ func (src Point) Value() (driver.Value, error) {
 	return string(buf), err
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Point) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +111,7 @@ func (src Point) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Point) UnmarshalJSON(point []byte) error {
 	p, err := parsePoint(point)
 	if err != nil {
@@ -178,7 +182,6 @@ func (encodePlanPointCodecText) Encode(value any, buf []byte) (newBuf []byte, er
 }
 
 func (PointCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
index 04b0ba6b..a84b25fe 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/polygon.go
@@ -24,16 +24,18 @@ type Polygon struct {
 	Valid bool
 }
 
+// ScanPolygon implements the [PolygonScanner] interface.
 func (p *Polygon) ScanPolygon(v Polygon) error {
 	*p = v
 	return nil
 }
 
+// PolygonValue implements the [PolygonValuer] interface.
 func (p Polygon) PolygonValue() (Polygon, error) {
 	return p, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (p *Polygon) Scan(src any) error {
 	if src == nil {
 		*p = Polygon{}
@@ -48,7 +50,7 @@ func (p *Polygon) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (p Polygon) Value() (driver.Value, error) {
 	if !p.Valid {
 		return nil, nil
@@ -139,7 +141,6 @@ func (encodePlanPolygonCodecText) Encode(value any, buf []byte) (newBuf []byte,
 }
 
 func (PolygonCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
index 16427ccc..62d69990 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/range.go
@@ -191,11 +191,13 @@ type untypedBinaryRange struct {
 // 18 = [      = 10010
 // 24 =        = 11000
 
-const emptyMask = 1
-const lowerInclusiveMask = 2
-const upperInclusiveMask = 4
-const lowerUnboundedMask = 8
-const upperUnboundedMask = 16
+const (
+	emptyMask          = 1
+	lowerInclusiveMask = 2
+	upperInclusiveMask = 4
+	lowerUnboundedMask = 8
+	upperUnboundedMask = 16
+)
 
 func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	ubr := &untypedBinaryRange{}
@@ -273,7 +275,6 @@ func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
 	}
 
 	return ubr, nil
-
 }
 
 // Range is a generic range type.
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
index b3b16604..90b9bd4b 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/record_codec.go
@@ -121,5 +121,4 @@ func (RecordCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (an
 	default:
 		return nil, fmt.Errorf("unknown format code %d", format)
 	}
-
 }
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
index 021ee331..e08b1254 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/text.go
@@ -19,16 +19,18 @@ type Text struct {
 	Valid  bool
 }
 
+// ScanText implements the [TextScanner] interface.
 func (t *Text) ScanText(v Text) error {
 	*t = v
 	return nil
 }
 
+// TextValue implements the [TextValuer] interface.
 func (t Text) TextValue() (Text, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Text) Scan(src any) error {
 	if src == nil {
 		*dst = Text{}
@@ -47,7 +49,7 @@ func (dst *Text) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Text) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -55,6 +57,7 @@ func (src Text) Value() (driver.Value, error) {
 	return src.String, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src Text) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -63,6 +66,7 @@ func (src Text) MarshalJSON() ([]byte, error) {
 	return json.Marshal(src.String)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *Text) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -146,7 +150,6 @@ func (encodePlanTextCodecTextValuer) Encode(value any, buf []byte) (newBuf []byt
 }
 
 func (TextCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case TextFormatCode, BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
index 9bc2c2a1..05c9e6d9 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/tid.go
@@ -35,16 +35,18 @@ type TID struct {
 	Valid        bool
 }
 
+// ScanTID implements the [TIDScanner] interface.
 func (b *TID) ScanTID(v TID) error {
 	*b = v
 	return nil
 }
 
+// TIDValue implements the [TIDValuer] interface.
 func (b TID) TIDValue() (TID, error) {
 	return b, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *TID) Scan(src any) error {
 	if src == nil {
 		*dst = TID{}
@@ -59,7 +61,7 @@ func (dst *TID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src TID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -131,7 +133,6 @@ func (encodePlanTIDCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TIDCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
index f8fd9489..4b8f6908 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/time.go
@@ -29,16 +29,18 @@ type Time struct {
 	Valid        bool
 }
 
+// ScanTime implements the [TimeScanner] interface.
 func (t *Time) ScanTime(v Time) error {
 	*t = v
 	return nil
 }
 
+// TimeValue implements the [TimeValuer] interface.
 func (t Time) TimeValue() (Time, error) {
 	return t, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (t *Time) Scan(src any) error {
 	if src == nil {
 		*t = Time{}
@@ -58,7 +60,7 @@ func (t *Time) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (t Time) Value() (driver.Value, error) {
 	if !t.Valid {
 		return nil, nil
@@ -137,7 +139,6 @@ func (encodePlanTimeCodecText) Encode(value any, buf []byte) (newBuf []byte, err
 }
 
 func (TimeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
index 677a2c6e..861fa883 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamp.go
@@ -11,7 +11,10 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+const (
+	pgTimestampFormat = "2006-01-02 15:04:05.999999999"
+	jsonISO8601       = "2006-01-02T15:04:05.999999999"
+)
 
 type TimestampScanner interface {
 	ScanTimestamp(v Timestamp) error
@@ -28,16 +31,18 @@ type Timestamp struct {
 	Valid            bool
 }
 
+// ScanTimestamp implements the [TimestampScanner] interface.
 func (ts *Timestamp) ScanTimestamp(v Timestamp) error {
 	*ts = v
 	return nil
 }
 
+// TimestampValue implements the [TimestampValuer] interface.
 func (ts Timestamp) TimestampValue() (Timestamp, error) {
 	return ts, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (ts *Timestamp) Scan(src any) error {
 	if src == nil {
 		*ts = Timestamp{}
@@ -55,7 +60,7 @@ func (ts *Timestamp) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (ts Timestamp) Value() (driver.Value, error) {
 	if !ts.Valid {
 		return nil, nil
@@ -67,6 +72,7 @@ func (ts Timestamp) Value() (driver.Value, error) {
 	return ts.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	if !ts.Valid {
 		return []byte("null"), nil
@@ -76,7 +82,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 
 	switch ts.InfinityModifier {
 	case Finite:
-		s = ts.Time.Format(time.RFC3339Nano)
+		s = ts.Time.Format(jsonISO8601)
 	case Infinity:
 		s = "infinity"
 	case NegativeInfinity:
@@ -86,6 +92,7 @@ func (ts Timestamp) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -104,15 +111,23 @@ func (ts *Timestamp) UnmarshalJSON(b []byte) error {
 	case "-infinity":
 		*ts = Timestamp{Valid: true, InfinityModifier: -Infinity}
 	default:
-		// PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz
-		tim, err := time.Parse(time.RFC3339Nano, *s)
-		if err != nil {
-			return err
+		// Parse time with or without timezonr
+		tss := *s
+		//		PostgreSQL uses ISO 8601 without timezone for to_json function and casting from a string to timestampt
+		tim, err := time.Parse(time.RFC3339Nano, tss)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
 		}
-
-		*ts = Timestamp{Time: tim, Valid: true}
+		tim, err = time.ParseInLocation(jsonISO8601, tss, time.UTC)
+		if err == nil {
+			*ts = Timestamp{Time: tim, Valid: true}
+			return nil
+		}
+		ts.Valid = false
+		return fmt.Errorf("cannot unmarshal %s to timestamp with layout %s or %s (%w)",
+			*s, time.RFC3339Nano, jsonISO8601, err)
 	}
-
 	return nil
 }
 
@@ -225,7 +240,6 @@ func discardTimeZone(t time.Time) time.Time {
 }
 
 func (c *TimestampCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
index 7efbcffd..5d67e47f 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/timestamptz.go
@@ -11,10 +11,12 @@ import (
 	"github.com/jackc/pgx/v5/internal/pgio"
 )
 
-const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07"
-const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00"
-const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00"
-const microsecFromUnixEpochToY2K = 946684800 * 1000000
+const (
+	pgTimestamptzHourFormat    = "2006-01-02 15:04:05.999999999Z07"
+	pgTimestamptzMinuteFormat  = "2006-01-02 15:04:05.999999999Z07:00"
+	pgTimestamptzSecondFormat  = "2006-01-02 15:04:05.999999999Z07:00:00"
+	microsecFromUnixEpochToY2K = 946684800 * 1000000
+)
 
 const (
 	negativeInfinityMicrosecondOffset = -9223372036854775808
@@ -36,16 +38,18 @@ type Timestamptz struct {
 	Valid            bool
 }
 
+// ScanTimestamptz implements the [TimestamptzScanner] interface.
 func (tstz *Timestamptz) ScanTimestamptz(v Timestamptz) error {
 	*tstz = v
 	return nil
 }
 
+// TimestamptzValue implements the [TimestamptzValuer] interface.
 func (tstz Timestamptz) TimestamptzValue() (Timestamptz, error) {
 	return tstz, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (tstz *Timestamptz) Scan(src any) error {
 	if src == nil {
 		*tstz = Timestamptz{}
@@ -63,7 +67,7 @@ func (tstz *Timestamptz) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (tstz Timestamptz) Value() (driver.Value, error) {
 	if !tstz.Valid {
 		return nil, nil
@@ -75,6 +79,7 @@ func (tstz Timestamptz) Value() (driver.Value, error) {
 	return tstz.Time, nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	if !tstz.Valid {
 		return []byte("null"), nil
@@ -94,6 +99,7 @@ func (tstz Timestamptz) MarshalJSON() ([]byte, error) {
 	return json.Marshal(s)
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (tstz *Timestamptz) UnmarshalJSON(b []byte) error {
 	var s *string
 	err := json.Unmarshal(b, &s)
@@ -225,7 +231,6 @@ func (encodePlanTimestamptzCodecText) Encode(value any, buf []byte) (newBuf []by
 }
 
 func (c *TimestamptzCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
index f2b2fa6d..e6d4b1cf 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint32.go
@@ -3,6 +3,7 @@ package pgtype
 import (
 	"database/sql/driver"
 	"encoding/binary"
+	"encoding/json"
 	"fmt"
 	"math"
 	"strconv"
@@ -24,16 +25,18 @@ type Uint32 struct {
 	Valid  bool
 }
 
+// ScanUint32 implements the [Uint32Scanner] interface.
 func (n *Uint32) ScanUint32(v Uint32) error {
 	*n = v
 	return nil
 }
 
+// Uint32Value implements the [Uint32Valuer] interface.
 func (n Uint32) Uint32Value() (Uint32, error) {
 	return n, nil
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *Uint32) Scan(src any) error {
 	if src == nil {
 		*dst = Uint32{}
@@ -67,7 +70,7 @@ func (dst *Uint32) Scan(src any) error {
 	return nil
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src Uint32) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -75,6 +78,31 @@ func (src Uint32) Value() (driver.Value, error) {
 	return int64(src.Uint32), nil
 }
 
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
+func (src Uint32) MarshalJSON() ([]byte, error) {
+	if !src.Valid {
+		return []byte("null"), nil
+	}
+	return json.Marshal(src.Uint32)
+}
+
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
+func (dst *Uint32) UnmarshalJSON(b []byte) error {
+	var n *uint32
+	err := json.Unmarshal(b, &n)
+	if err != nil {
+		return err
+	}
+
+	if n == nil {
+		*dst = Uint32{}
+	} else {
+		*dst = Uint32{Uint32: *n, Valid: true}
+	}
+
+	return nil
+}
+
 type Uint32Codec struct{}
 
 func (Uint32Codec) FormatSupported(format int16) bool {
@@ -197,7 +225,6 @@ func (encodePlanUint32CodecTextInt64Valuer) Encode(value any, buf []byte) (newBu
 }
 
 func (Uint32Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
-
 	switch format {
 	case BinaryFormatCode:
 		switch target.(type) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
new file mode 100644
index 00000000..68fd1661
--- /dev/null
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uint64.go
@@ -0,0 +1,323 @@
+package pgtype
+
+import (
+	"database/sql/driver"
+	"encoding/binary"
+	"fmt"
+	"math"
+	"strconv"
+
+	"github.com/jackc/pgx/v5/internal/pgio"
+)
+
+type Uint64Scanner interface {
+	ScanUint64(v Uint64) error
+}
+
+type Uint64Valuer interface {
+	Uint64Value() (Uint64, error)
+}
+
+// Uint64 is the core type that is used to represent PostgreSQL types such as XID8.
+type Uint64 struct {
+	Uint64 uint64
+	Valid  bool
+}
+
+// ScanUint64 implements the [Uint64Scanner] interface.
+func (n *Uint64) ScanUint64(v Uint64) error {
+	*n = v
+	return nil
+}
+
+// Uint64Value implements the [Uint64Valuer] interface.
+func (n Uint64) Uint64Value() (Uint64, error) {
+	return n, nil
+}
+
+// Scan implements the [database/sql.Scanner] interface.
+func (dst *Uint64) Scan(src any) error {
+	if src == nil {
+		*dst = Uint64{}
+		return nil
+	}
+
+	var n uint64
+
+	switch src := src.(type) {
+	case int64:
+		if src < 0 {
+			return fmt.Errorf("%d is less than the minimum value for Uint64", src)
+		}
+		n = uint64(src)
+	case string:
+		un, err := strconv.ParseUint(src, 10, 64)
+		if err != nil {
+			return err
+		}
+		n = un
+	default:
+		return fmt.Errorf("cannot scan %T", src)
+	}
+
+	*dst = Uint64{Uint64: n, Valid: true}
+
+	return nil
+}
+
+// Value implements the [database/sql/driver.Valuer] interface.
+func (src Uint64) Value() (driver.Value, error) {
+	if !src.Valid {
+		return nil, nil
+	}
+
+	// If the value is greater than the maximum value for int64, return it as a string instead of losing data or returning
+	// an error.
+	if src.Uint64 > math.MaxInt64 {
+		return strconv.FormatUint(src.Uint64, 10), nil
+	}
+
+	return int64(src.Uint64), nil
+}
+
+type Uint64Codec struct{}
+
+func (Uint64Codec) FormatSupported(format int16) bool {
+	return format == TextFormatCode || format == BinaryFormatCode
+}
+
+func (Uint64Codec) PreferredFormat() int16 {
+	return BinaryFormatCode
+}
+
+func (Uint64Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
+	switch format {
+	case BinaryFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecBinaryUint64{}
+		case Uint64Valuer:
+			return encodePlanUint64CodecBinaryUint64Valuer{}
+		case Int64Valuer:
+			return encodePlanUint64CodecBinaryInt64Valuer{}
+		}
+	case TextFormatCode:
+		switch value.(type) {
+		case uint64:
+			return encodePlanUint64CodecTextUint64{}
+		case Int64Valuer:
+			return encodePlanUint64CodecTextInt64Valuer{}
+		}
+	}
+
+	return nil
+}
+
+type encodePlanUint64CodecBinaryUint64 struct{}
+
+func (encodePlanUint64CodecBinaryUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return pgio.AppendUint64(buf, v), nil
+}
+
+type encodePlanUint64CodecBinaryUint64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return pgio.AppendUint64(buf, v.Uint64), nil
+}
+
+type encodePlanUint64CodecBinaryInt64Valuer struct{}
+
+func (encodePlanUint64CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return pgio.AppendUint64(buf, uint64(v.Int64)), nil
+}
+
+type encodePlanUint64CodecTextUint64 struct{}
+
+func (encodePlanUint64CodecTextUint64) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v := value.(uint64)
+	return append(buf, strconv.FormatUint(uint64(v), 10)...), nil
+}
+
+type encodePlanUint64CodecTextUint64Valuer struct{}
+
+func (encodePlanUint64CodecTextUint64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Uint64Valuer).Uint64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	return append(buf, strconv.FormatUint(v.Uint64, 10)...), nil
+}
+
+type encodePlanUint64CodecTextInt64Valuer struct{}
+
+func (encodePlanUint64CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
+	v, err := value.(Int64Valuer).Int64Value()
+	if err != nil {
+		return nil, err
+	}
+
+	if !v.Valid {
+		return nil, nil
+	}
+
+	if v.Int64 < 0 {
+		return nil, fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
+	}
+
+	return append(buf, strconv.FormatInt(v.Int64, 10)...), nil
+}
+
+func (Uint64Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
+	switch format {
+	case BinaryFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanBinaryUint64ToUint64{}
+		case Uint64Scanner:
+			return scanPlanBinaryUint64ToUint64Scanner{}
+		case TextScanner:
+			return scanPlanBinaryUint64ToTextScanner{}
+		}
+	case TextFormatCode:
+		switch target.(type) {
+		case *uint64:
+			return scanPlanTextAnyToUint64{}
+		case Uint64Scanner:
+			return scanPlanTextAnyToUint64Scanner{}
+		}
+	}
+
+	return nil
+}
+
+func (c Uint64Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return int64(n), nil
+}
+
+func (c Uint64Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
+	if src == nil {
+		return nil, nil
+	}
+
+	var n uint64
+	err := codecScan(c, m, oid, format, src, &n)
+	if err != nil {
+		return nil, err
+	}
+	return n, nil
+}
+
+type scanPlanBinaryUint64ToUint64 struct{}
+
+func (scanPlanBinaryUint64ToUint64) Scan(src []byte, dst any) error {
+	if src == nil {
+		return fmt.Errorf("cannot scan NULL into %T", dst)
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	p := (dst).(*uint64)
+	*p = binary.BigEndian.Uint64(src)
+
+	return nil
+}
+
+type scanPlanBinaryUint64ToUint64Scanner struct{}
+
+func (scanPlanBinaryUint64ToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := binary.BigEndian.Uint64(src)
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
+
+type scanPlanBinaryUint64ToTextScanner struct{}
+
+func (scanPlanBinaryUint64ToTextScanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(TextScanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanText(Text{})
+	}
+
+	if len(src) != 8 {
+		return fmt.Errorf("invalid length for uint64: %v", len(src))
+	}
+
+	n := uint64(binary.BigEndian.Uint64(src))
+	return s.ScanText(Text{String: strconv.FormatUint(n, 10), Valid: true})
+}
+
+type scanPlanTextAnyToUint64Scanner struct{}
+
+func (scanPlanTextAnyToUint64Scanner) Scan(src []byte, dst any) error {
+	s, ok := (dst).(Uint64Scanner)
+	if !ok {
+		return ErrScanTargetTypeChanged
+	}
+
+	if src == nil {
+		return s.ScanUint64(Uint64{})
+	}
+
+	n, err := strconv.ParseUint(string(src), 10, 64)
+	if err != nil {
+		return err
+	}
+
+	return s.ScanUint64(Uint64{Uint64: n, Valid: true})
+}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
index d57c0f2f..83d0c412 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/uuid.go
@@ -20,11 +20,13 @@ type UUID struct {
 	Valid bool
 }
 
+// ScanUUID implements the [UUIDScanner] interface.
 func (b *UUID) ScanUUID(v UUID) error {
 	*b = v
 	return nil
 }
 
+// UUIDValue implements the [UUIDValuer] interface.
 func (b UUID) UUIDValue() (UUID, error) {
 	return b, nil
 }
@@ -67,7 +69,7 @@ func encodeUUID(src [16]byte) string {
 	return string(buf[:])
 }
 
-// Scan implements the database/sql Scanner interface.
+// Scan implements the [database/sql.Scanner] interface.
 func (dst *UUID) Scan(src any) error {
 	if src == nil {
 		*dst = UUID{}
@@ -87,7 +89,7 @@ func (dst *UUID) Scan(src any) error {
 	return fmt.Errorf("cannot scan %T", src)
 }
 
-// Value implements the database/sql/driver Valuer interface.
+// Value implements the [database/sql/driver.Valuer] interface.
 func (src UUID) Value() (driver.Value, error) {
 	if !src.Valid {
 		return nil, nil
@@ -96,6 +98,15 @@ func (src UUID) Value() (driver.Value, error) {
 	return encodeUUID(src.Bytes), nil
 }
 
+func (src UUID) String() string {
+	if !src.Valid {
+		return ""
+	}
+
+	return encodeUUID(src.Bytes)
+}
+
+// MarshalJSON implements the [encoding/json.Marshaler] interface.
 func (src UUID) MarshalJSON() ([]byte, error) {
 	if !src.Valid {
 		return []byte("null"), nil
@@ -108,6 +119,7 @@ func (src UUID) MarshalJSON() ([]byte, error) {
 	return buff.Bytes(), nil
 }
 
+// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface.
 func (dst *UUID) UnmarshalJSON(src []byte) error {
 	if bytes.Equal(src, []byte("null")) {
 		*dst = UUID{}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
index fb4c49ad..79e3698a 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgtype/xml.go
@@ -113,7 +113,7 @@ func (c *XMLCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPl
 		// https://github.com/jackc/pgx/issues/1691 -- ** anything else
 
 		if wrapperPlan, nextDst, ok := TryPointerPointerScanPlan(target); ok {
-			if nextPlan := m.planScan(oid, format, nextDst); nextPlan != nil {
+			if nextPlan := m.planScan(oid, format, nextDst, 0); nextPlan != nil {
 				if _, failed := nextPlan.(*scanPlanFail); !failed {
 					wrapperPlan.SetNext(nextPlan)
 					return wrapperPlan
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go b/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
index fdcba724..addfb412 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go
@@ -2,7 +2,7 @@ package pgxpool
 
 import (
 	"context"
-	"fmt"
+	"errors"
 	"math/rand"
 	"runtime"
 	"strconv"
@@ -15,11 +15,14 @@ import (
 	"github.com/jackc/puddle/v2"
 )
 
-var defaultMaxConns = int32(4)
-var defaultMinConns = int32(0)
-var defaultMaxConnLifetime = time.Hour
-var defaultMaxConnIdleTime = time.Minute * 30
-var defaultHealthCheckPeriod = time.Minute
+var (
+	defaultMaxConns          = int32(4)
+	defaultMinConns          = int32(0)
+	defaultMinIdleConns      = int32(0)
+	defaultMaxConnLifetime   = time.Hour
+	defaultMaxConnIdleTime   = time.Minute * 30
+	defaultHealthCheckPeriod = time.Minute
+)
 
 type connResource struct {
 	conn       *pgx.Conn
@@ -83,10 +86,12 @@ type Pool struct {
 	config                *Config
 	beforeConnect         func(context.Context, *pgx.ConnConfig) error
 	afterConnect          func(context.Context, *pgx.Conn) error
-	beforeAcquire         func(context.Context, *pgx.Conn) bool
+	prepareConn           func(context.Context, *pgx.Conn) (bool, error)
 	afterRelease          func(*pgx.Conn) bool
 	beforeClose           func(*pgx.Conn)
+	shouldPing            func(context.Context, ShouldPingParams) bool
 	minConns              int32
+	minIdleConns          int32
 	maxConns              int32
 	maxConnLifetime       time.Duration
 	maxConnLifetimeJitter time.Duration
@@ -102,6 +107,12 @@ type Pool struct {
 	closeChan chan struct{}
 }
 
+// ShouldPingParams are the parameters passed to ShouldPing.
+type ShouldPingParams struct {
+	Conn         *pgx.Conn
+	IdleDuration time.Duration
+}
+
 // Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
 // modified.
 type Config struct {
@@ -117,8 +128,23 @@ type Config struct {
 	// BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the
 	// acquisition or false to indicate that the connection should be destroyed and a different connection should be
 	// acquired.
+	//
+	// Deprecated: Use PrepareConn instead. If both PrepareConn and BeforeAcquire are set, PrepareConn will take
+	// precedence, ignoring BeforeAcquire.
 	BeforeAcquire func(context.Context, *pgx.Conn) bool
 
+	// PrepareConn is called before a connection is acquired from the pool. If this function returns true, the connection
+	// is considered valid, otherwise the connection is destroyed. If the function returns a non-nil error, the instigating
+	// query will fail with the returned error.
+	//
+	// Specifically, this means that:
+	//
+	// 	- If it returns true and a nil error, the query proceeds as normal.
+	// 	- If it returns true and an error, the connection will be returned to the pool, and the instigating query will fail with the returned error.
+	// 	- If it returns false, and an error, the connection will be destroyed, and the query will fail with the returned error.
+	// 	- If it returns false and a nil error, the connection will be destroyed, and the instigating query will be retried on a new connection.
+	PrepareConn func(context.Context, *pgx.Conn) (bool, error)
+
 	// AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to
 	// return the connection to the pool or false to destroy the connection.
 	AfterRelease func(*pgx.Conn) bool
@@ -126,6 +152,10 @@ type Config struct {
 	// BeforeClose is called right before a connection is closed and removed from the pool.
 	BeforeClose func(*pgx.Conn)
 
+	// ShouldPing is called after a connection is acquired from the pool. If it returns true, the connection is pinged to check for liveness.
+	// If this func is not set, the default behavior is to ping connections that have been idle for at least 1 second.
+	ShouldPing func(context.Context, ShouldPingParams) bool
+
 	// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
 	MaxConnLifetime time.Duration
 
@@ -144,6 +174,13 @@ type Config struct {
 	// to create new connections.
 	MinConns int32
 
+	// MinIdleConns is the minimum number of idle connections in the pool. You can increase this to ensure that
+	// there are always idle connections available. This can help reduce tail latencies during request processing,
+	// as you can avoid the latency of establishing a new connection while handling requests. It is superior
+	// to MinConns for this purpose.
+	// Similar to MinConns, the pool might temporarily dip below MinIdleConns after connection closes.
+	MinIdleConns int32
+
 	// HealthCheckPeriod is the duration between checks of the health of idle connections.
 	HealthCheckPeriod time.Duration
 
@@ -181,14 +218,22 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		panic("config must be created by ParseConfig")
 	}
 
+	prepareConn := config.PrepareConn
+	if prepareConn == nil && config.BeforeAcquire != nil {
+		prepareConn = func(ctx context.Context, conn *pgx.Conn) (bool, error) {
+			return config.BeforeAcquire(ctx, conn), nil
+		}
+	}
+
 	p := &Pool{
 		config:                config,
 		beforeConnect:         config.BeforeConnect,
 		afterConnect:          config.AfterConnect,
-		beforeAcquire:         config.BeforeAcquire,
+		prepareConn:           prepareConn,
 		afterRelease:          config.AfterRelease,
 		beforeClose:           config.BeforeClose,
 		minConns:              config.MinConns,
+		minIdleConns:          config.MinIdleConns,
 		maxConns:              config.MaxConns,
 		maxConnLifetime:       config.MaxConnLifetime,
 		maxConnLifetimeJitter: config.MaxConnLifetimeJitter,
@@ -206,6 +251,14 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 		p.releaseTracer = t
 	}
 
+	if config.ShouldPing != nil {
+		p.shouldPing = config.ShouldPing
+	} else {
+		p.shouldPing = func(ctx context.Context, params ShouldPingParams) bool {
+			return params.IdleDuration > time.Second
+		}
+	}
+
 	var err error
 	p.p, err = puddle.NewPool(
 		&puddle.Config[*connResource]{
@@ -271,7 +324,8 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 	}
 
 	go func() {
-		p.createIdleResources(ctx, int(p.minConns))
+		targetIdleResources := max(int(p.minConns), int(p.minIdleConns))
+		p.createIdleResources(ctx, targetIdleResources)
 		p.backgroundHealthCheck()
 	}()
 
@@ -281,20 +335,20 @@ func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) {
 // ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the
 // addition of the following variables:
 //
-//   - pool_max_conns: integer greater than 0
-//   - pool_min_conns: integer 0 or greater
-//   - pool_max_conn_lifetime: duration string
-//   - pool_max_conn_idle_time: duration string
-//   - pool_health_check_period: duration string
-//   - pool_max_conn_lifetime_jitter: duration string
+//   - pool_max_conns: integer greater than 0 (default 4)
+//   - pool_min_conns: integer 0 or greater (default 0)
+//   - pool_max_conn_lifetime: duration string (default 1 hour)
+//   - pool_max_conn_idle_time: duration string (default 30 minutes)
+//   - pool_health_check_period: duration string (default 1 minute)
+//   - pool_max_conn_lifetime_jitter: duration string (default 0)
 //
 // See Config for definitions of these arguments.
 //
 //	# Example Keyword/Value
-//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10
+//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 pool_max_conn_lifetime=1h30m
 //
 //	# Example URL
-//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10
+//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10&pool_max_conn_lifetime=1h30m
 func ParseConfig(connString string) (*Config, error) {
 	connConfig, err := pgx.ParseConfig(connString)
 	if err != nil {
@@ -310,10 +364,10 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_max_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conns", err)
 		}
 		if n < 1 {
-			return nil, fmt.Errorf("pool_max_conns too small: %d", n)
+			return nil, pgconn.NewParseConfigError(connString, "pool_max_conns too small", err)
 		}
 		config.MaxConns = int32(n)
 	} else {
@@ -327,18 +381,29 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_min_conns")
 		n, err := strconv.ParseInt(s, 10, 32)
 		if err != nil {
-			return nil, fmt.Errorf("cannot parse pool_min_conns: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_conns", err)
 		}
 		config.MinConns = int32(n)
 	} else {
 		config.MinConns = defaultMinConns
 	}
 
+	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_idle_conns"]; ok {
+		delete(connConfig.Config.RuntimeParams, "pool_min_idle_conns")
+		n, err := strconv.ParseInt(s, 10, 32)
+		if err != nil {
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_min_idle_conns", err)
+		}
+		config.MinIdleConns = int32(n)
+	} else {
+		config.MinIdleConns = defaultMinIdleConns
+	}
+
 	if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime", err)
 		}
 		config.MaxConnLifetime = d
 	} else {
@@ -349,7 +414,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_idle_time")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_idle_time: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_idle_time", err)
 		}
 		config.MaxConnIdleTime = d
 	} else {
@@ -360,7 +425,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_health_check_period")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_health_check_period: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_health_check_period", err)
 		}
 		config.HealthCheckPeriod = d
 	} else {
@@ -371,7 +436,7 @@ func ParseConfig(connString string) (*Config, error) {
 		delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
 		d, err := time.ParseDuration(s)
 		if err != nil {
-			return nil, fmt.Errorf("invalid pool_max_conn_lifetime_jitter: %w", err)
+			return nil, pgconn.NewParseConfigError(connString, "cannot parse pool_max_conn_lifetime_jitter", err)
 		}
 		config.MaxConnLifetimeJitter = d
 	}
@@ -472,7 +537,9 @@ func (p *Pool) checkMinConns() error {
 	// TotalConns can include ones that are being destroyed but we should have
 	// sleep(500ms) around all of the destroys to help prevent that from throwing
 	// off this check
-	toCreate := p.minConns - p.Stat().TotalConns()
+
+	// Create the number of connections needed to get to both minConns and minIdleConns
+	toCreate := max(p.minConns-p.Stat().TotalConns(), p.minIdleConns-p.Stat().IdleConns())
 	if toCreate > 0 {
 		return p.createIdleResources(context.Background(), int(toCreate))
 	}
@@ -521,7 +588,10 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 		}()
 	}
 
-	for {
+	// Try to acquire from the connection pool up to maxConns + 1 times, so that
+	// any that fatal errors would empty the pool and still at least try 1 fresh
+	// connection.
+	for range p.maxConns + 1 {
 		res, err := p.p.Acquire(ctx)
 		if err != nil {
 			return nil, err
@@ -529,7 +599,8 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 
 		cr := res.Value()
 
-		if res.IdleDuration() > time.Second {
+		shouldPingParams := ShouldPingParams{Conn: cr.conn, IdleDuration: res.IdleDuration()}
+		if p.shouldPing(ctx, shouldPingParams) {
 			err := cr.conn.Ping(ctx)
 			if err != nil {
 				res.Destroy()
@@ -537,12 +608,25 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) {
 			}
 		}
 
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			return cr.getConn(p, res), nil
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok {
+				res.Destroy()
+			}
+			if err != nil {
+				if ok {
+					res.Release()
+				}
+				return nil, err
+			}
+			if !ok {
+				continue
+			}
 		}
 
-		res.Destroy()
+		return cr.getConn(p, res), nil
 	}
+	return nil, errors.New("pgxpool: detected infinite loop acquiring connection; likely bug in PrepareConn or BeforeAcquire hook")
 }
 
 // AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the
@@ -565,11 +649,14 @@ func (p *Pool) AcquireAllIdle(ctx context.Context) []*Conn {
 	conns := make([]*Conn, 0, len(resources))
 	for _, res := range resources {
 		cr := res.Value()
-		if p.beforeAcquire == nil || p.beforeAcquire(ctx, cr.conn) {
-			conns = append(conns, cr.getConn(p, res))
-		} else {
-			res.Destroy()
+		if p.prepareConn != nil {
+			ok, err := p.prepareConn(ctx, cr.conn)
+			if !ok || err != nil {
+				res.Destroy()
+				continue
+			}
 		}
+		conns = append(conns, cr.getConn(p, res))
 	}
 
 	return conns
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go b/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
index cfa0c4c5..e02b6ac3 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/pgxpool/stat.go
@@ -82,3 +82,10 @@ func (s *Stat) MaxLifetimeDestroyCount() int64 {
 func (s *Stat) MaxIdleDestroyCount() int64 {
 	return s.idleDestroyCount
 }
+
+// EmptyAcquireWaitTime returns the cumulative time waited for successful acquires
+// from the pool for a resource to be released or constructed because the pool was
+// empty.
+func (s *Stat) EmptyAcquireWaitTime() time.Duration {
+	return s.s.EmptyAcquireWaitTime()
+}
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/rows.go b/public-api/vendor/github.com/jackc/pgx/v5/rows.go
index f23625d4..a5725fdd 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/rows.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/rows.go
@@ -41,22 +41,19 @@ type Rows interface {
 	// when there was an error executing the query.
 	FieldDescriptions() []pgconn.FieldDescription
 
-	// Next prepares the next row for reading. It returns true if there is another
-	// row and false if no more rows are available or a fatal error has occurred.
-	// It automatically closes rows when all rows are read.
+	// Next prepares the next row for reading. It returns true if there is another row and false if no more rows are
+	// available or a fatal error has occurred. It automatically closes rows upon returning false (whether due to all rows
+	// having been read or due to an error).
 	//
-	// Callers should check rows.Err() after rows.Next() returns false to detect
-	// whether result-set reading ended prematurely due to an error. See
-	// Conn.Query for details.
+	// Callers should check rows.Err() after rows.Next() returns false to detect whether result-set reading ended
+	// prematurely due to an error. See Conn.Query for details.
 	//
-	// For simpler error handling, consider using the higher-level pgx v5
-	// CollectRows() and ForEachRow() helpers instead.
+	// For simpler error handling, consider using the higher-level pgx v5 CollectRows() and ForEachRow() helpers instead.
 	Next() bool
 
-	// Scan reads the values from the current row into dest values positionally.
-	// dest can include pointers to core types, values implementing the Scanner
-	// interface, and nil. nil will skip the value entirely. It is an error to
-	// call Scan without first calling Next() and checking that it returned true.
+	// Scan reads the values from the current row into dest values positionally. dest can include pointers to core types,
+	// values implementing the Scanner interface, and nil. nil will skip the value entirely. It is an error to call Scan
+	// without first calling Next() and checking that it returned true. Rows is automatically closed upon error.
 	Scan(dest ...any) error
 
 	// Values returns the decoded row values. As with Scan(), it is an error to
@@ -188,6 +185,17 @@ func (rows *baseRows) Close() {
 	} else if rows.queryTracer != nil {
 		rows.queryTracer.TraceQueryEnd(rows.ctx, rows.conn, TraceQueryEndData{rows.commandTag, rows.err})
 	}
+
+	// Zero references to other memory allocations. This allows them to be GC'd even when the Rows still referenced. In
+	// particular, when using pgxpool GC could be delayed as pgxpool.poolRows are allocated in large slices.
+	//
+	// https://github.com/jackc/pgx/pull/2269
+	rows.values = nil
+	rows.scanPlans = nil
+	rows.scanTypes = nil
+	rows.ctx = nil
+	rows.sql = ""
+	rows.args = nil
 }
 
 func (rows *baseRows) CommandTag() pgconn.CommandTag {
@@ -272,7 +280,7 @@ func (rows *baseRows) Scan(dest ...any) error {
 
 		err := rows.scanPlans[i].Scan(values[i], dst)
 		if err != nil {
-			err = ScanArgError{ColumnIndex: i, Err: err}
+			err = ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 			rows.fatal(err)
 			return err
 		}
@@ -334,11 +342,16 @@ func (rows *baseRows) Conn() *Conn {
 
 type ScanArgError struct {
 	ColumnIndex int
+	FieldName   string
 	Err         error
 }
 
 func (e ScanArgError) Error() string {
-	return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	if e.FieldName == "?column?" { // Don't include the fieldname if it's unknown
+		return fmt.Sprintf("can't scan into dest[%d]: %v", e.ColumnIndex, e.Err)
+	}
+
+	return fmt.Sprintf("can't scan into dest[%d] (col: %s): %v", e.ColumnIndex, e.FieldName, e.Err)
 }
 
 func (e ScanArgError) Unwrap() error {
@@ -366,7 +379,7 @@ func ScanRow(typeMap *pgtype.Map, fieldDescriptions []pgconn.FieldDescription, v
 
 		err := typeMap.Scan(fieldDescriptions[i].DataTypeOID, fieldDescriptions[i].Format, values[i], d)
 		if err != nil {
-			return ScanArgError{ColumnIndex: i, Err: err}
+			return ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
 		}
 	}
 
@@ -468,6 +481,8 @@ func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
 		return value, err
 	}
 
+	// The defer rows.Close() won't have executed yet. If the query returned more than one row, rows would still be open.
+	// rows.Close() must be called before rows.Err() so we explicitly call it here.
 	rows.Close()
 	return value, rows.Err()
 }
@@ -545,7 +560,7 @@ func (rs *mapRowScanner) ScanRow(rows Rows) error {
 	return nil
 }
 
-// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number a public fields as row
+// RowToStructByPos returns a T scanned from row. T must be a struct. T must have the same number of public fields as row
 // has fields. The row and T fields will be matched by position. If the "db" struct tag is "-" then the field will be
 // ignored.
 func RowToStructByPos[T any](row CollectableRow) (T, error) {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go b/public-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
index c1d00ab4..939b9636 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/stdlib/sql.go
@@ -216,7 +216,8 @@ func OpenDB(config pgx.ConnConfig, opts ...OptionOpenDB) *sql.DB {
 
 // OpenDBFromPool creates a new *sql.DB from the given *pgxpool.Pool. Note that this method automatically sets the
 // maximum number of idle connections in *sql.DB to zero, since they must be managed from the *pgxpool.Pool. This is
-// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool.
+// required to avoid acquiring all the connections from the pgxpool and starving any direct users of the pgxpool. Note
+// that closing the returned *sql.DB will not close the *pgxpool.Pool.
 func OpenDBFromPool(pool *pgxpool.Pool, opts ...OptionOpenDB) *sql.DB {
 	c := GetPoolConnector(pool, opts...)
 	db := sql.OpenDB(c)
@@ -470,7 +471,8 @@ func (c *Conn) ExecContext(ctx context.Context, query string, argsV []driver.Nam
 		return nil, driver.ErrBadConn
 	}
 
-	args := namedValueToInterface(argsV)
+	args := make([]any, len(argsV))
+	convertNamedArguments(args, argsV)
 
 	commandTag, err := c.conn.Exec(ctx, query, args...)
 	// if we got a network error before we had a chance to send the query, retry
@@ -487,8 +489,9 @@ func (c *Conn) QueryContext(ctx context.Context, query string, argsV []driver.Na
 		return nil, driver.ErrBadConn
 	}
 
-	args := []any{databaseSQLResultFormats}
-	args = append(args, namedValueToInterface(argsV)...)
+	args := make([]any, 1+len(argsV))
+	args[0] = databaseSQLResultFormats
+	convertNamedArguments(args[1:], argsV)
 
 	rows, err := c.conn.Query(ctx, query, args...)
 	if err != nil {
@@ -847,28 +850,14 @@ func (r *Rows) Next(dest []driver.Value) error {
 	return nil
 }
 
-func valueToInterface(argsV []driver.Value) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
-		if v != nil {
-			args = append(args, v.(any))
-		} else {
-			args = append(args, nil)
-		}
-	}
-	return args
-}
-
-func namedValueToInterface(argsV []driver.NamedValue) []any {
-	args := make([]any, 0, len(argsV))
-	for _, v := range argsV {
+func convertNamedArguments(args []any, argsV []driver.NamedValue) {
+	for i, v := range argsV {
 		if v.Value != nil {
-			args = append(args, v.Value.(any))
+			args[i] = v.Value.(any)
 		} else {
-			args = append(args, nil)
+			args[i] = nil
 		}
 	}
-	return args
 }
 
 type wrapTx struct {
diff --git a/public-api/vendor/github.com/jackc/pgx/v5/tx.go b/public-api/vendor/github.com/jackc/pgx/v5/tx.go
index 8feeb512..571e5e00 100644
--- a/public-api/vendor/github.com/jackc/pgx/v5/tx.go
+++ b/public-api/vendor/github.com/jackc/pgx/v5/tx.go
@@ -3,7 +3,6 @@ package pgx
 import (
 	"context"
 	"errors"
-	"fmt"
 	"strconv"
 	"strings"
 
@@ -48,6 +47,8 @@ type TxOptions struct {
 	// BeginQuery is the SQL query that will be executed to begin the transaction. This allows using non-standard syntax
 	// such as BEGIN PRIORITY HIGH with CockroachDB. If set this will override the other settings.
 	BeginQuery string
+	// CommitQuery is the SQL query that will be executed to commit the transaction.
+	CommitQuery string
 }
 
 var emptyTxOptions TxOptions
@@ -101,11 +102,14 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (Tx, error) {
 	if err != nil {
 		// begin should never fail unless there is an underlying connection issue or
 		// a context timeout. In either case, the connection is possibly broken.
-		c.die(errors.New("failed to begin transaction"))
+		c.die()
 		return nil, err
 	}
 
-	return &dbTx{conn: c}, nil
+	return &dbTx{
+		conn:        c,
+		commitQuery: txOptions.CommitQuery,
+	}, nil
 }
 
 // Tx represents a database transaction.
@@ -154,6 +158,7 @@ type dbTx struct {
 	conn         *Conn
 	savepointNum int64
 	closed       bool
+	commitQuery  string
 }
 
 // Begin starts a pseudo nested transaction implemented with a savepoint.
@@ -177,7 +182,12 @@ func (tx *dbTx) Commit(ctx context.Context) error {
 		return ErrTxClosed
 	}
 
-	commandTag, err := tx.conn.Exec(ctx, "commit")
+	commandSQL := "commit"
+	if tx.commitQuery != "" {
+		commandSQL = tx.commitQuery
+	}
+
+	commandTag, err := tx.conn.Exec(ctx, commandSQL)
 	tx.closed = true
 	if err != nil {
 		if tx.conn.PgConn().TxStatus() != 'I' {
@@ -205,7 +215,7 @@ func (tx *dbTx) Rollback(ctx context.Context) error {
 	tx.closed = true
 	if err != nil {
 		// A rollback failure leaves the connection in an undefined state
-		tx.conn.die(fmt.Errorf("rollback failed: %w", err))
+		tx.conn.die()
 		return err
 	}
 
diff --git a/public-api/vendor/github.com/magiconair/properties/.gitignore b/public-api/vendor/github.com/magiconair/properties/.gitignore
deleted file mode 100644
index e7081ff5..00000000
--- a/public-api/vendor/github.com/magiconair/properties/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-*.sublime-project
-*.sublime-workspace
-*.un~
-*.swp
-.idea/
-*.iml
diff --git a/public-api/vendor/github.com/magiconair/properties/CHANGELOG.md b/public-api/vendor/github.com/magiconair/properties/CHANGELOG.md
deleted file mode 100644
index 842e8e24..00000000
--- a/public-api/vendor/github.com/magiconair/properties/CHANGELOG.md
+++ /dev/null
@@ -1,205 +0,0 @@
-## Changelog
-
-### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022
-
- * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge
-
-   Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch.
-
- * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions
-
-### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022
-
- * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error
-
-   Thanks to [@ellie](https://github.com/ellie) for the patch.
-
- * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible
-
-   This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the
-   author happy until it affects real users.
-
-   Thanks to [@maage](https://github.com/maage) for the patch.
-
-### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021
-
- * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments
-
-   When reading comments \ are loaded correctly, but when writing they are then
-   replaced by \\. This leads to wrong comments when writing and reading multiple times.
-
-   Thanks to [@doxsch](https://github.com/doxsch) for the patch.
-
-### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020
-
- * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references
-
-   Thanks to [@sriv](https://github.com/sriv) for the patch.
-
-### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020
-
- * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference
-
-   The change is include the key in the error message which is causing the circular
-   reference when parsing/loading the properties files.
-
-   Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch.
-
-### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020
-
- * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write
-
-   This patch ensures that backslashes are escaped on write. Existing applications which
-   rely on the old behavior may need to be updated.
-
-   Thanks to [@apesternikov](https://github.com/apesternikov) for the patch.
-
- * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL()
-
-   Thanks to [@aliras1](https://github.com/aliras1) for the patch.
-
- * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write()
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
- * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys
-
-   Thanks to [@mkjor](https://github.com/mkjor) for the patch.
-
-### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019
-
- * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request
-
-   This patch ensures that in `LoadURL` the response body is always closed.
-
-   Thanks to [@liubog2008](https://github.com/liubog2008) for the patch.
-
-### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
-
- * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
-
-   This adds the option to disable property expansion during loading.
-
-   Thanks to [@kmala](https://github.com/kmala) for the patch.
-
-### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
-
- * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
-
-   See PR for an example.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
-
- * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
-
-   Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
-   with a `circular reference error`.
-
-   Thanks to [@yobert](https://github.com/yobert) for the fix.
-
-### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
-
- * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
-
- * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
-
-   Thanks to [@mgurov](https://github.com/mgurov) for the fix.
-
-### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
-
- * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
- * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
-
-### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
-
- * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
- * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
-
-### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
-
- * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
- * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
- * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
- * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
-
-### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
-
- * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
- * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
- * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
-
-### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
-
- * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
-
-### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
-
- * Vendored in gopkg.in/check.v1
-
-### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
-
- * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
-
-### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
-
- * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
-
-### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
-
- * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
-
-### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
-
- * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
- * Add clickable links to README
-
-### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
-
- * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
-   [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
-
-### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
-
- * Added support for single and multi-line comments (reading, writing and updating)
- * The order of keys is now preserved
- * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
- * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
- * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
-
-### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
-
- * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
-
-### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
-
- * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
-
-### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
-
- * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
- * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
-
-### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
-
-* Added support for time.Duration
-* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
-* Changed default of MustXXX() failure from panic to log.Fatal
-
-### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
-
-* Added MustGet... functions
-* Added support for int and uint with range checks on 32 bit platforms
-
-### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
-
-* Renamed from goproperties to properties
-* Added support for expansion of environment vars in
-  filenames and value expressions
-* Fixed bug where value expressions were not at the
-  start of the string
-
-### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
-
-* Initial release
diff --git a/public-api/vendor/github.com/magiconair/properties/LICENSE.md b/public-api/vendor/github.com/magiconair/properties/LICENSE.md
deleted file mode 100644
index 79c87e3e..00000000
--- a/public-api/vendor/github.com/magiconair/properties/LICENSE.md
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2013-2020, Frank Schroeder
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/public-api/vendor/github.com/magiconair/properties/README.md b/public-api/vendor/github.com/magiconair/properties/README.md
deleted file mode 100644
index e2edda02..00000000
--- a/public-api/vendor/github.com/magiconair/properties/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
-[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
-[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
-[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-# Overview
-
-#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
-
-properties is a Go library for reading and writing properties files.
-
-It supports reading from multiple files or URLs and Spring style recursive
-property expansion of expressions like `${key}` to their corresponding value.
-Value expressions can refer to other keys like in `${key}` or to environment
-variables like in `${USER}`.  Filenames can also contain environment variables
-like in `/home/${USER}/myapp.properties`.
-
-Properties can be decoded into structs, maps, arrays and values through
-struct tags.
-
-Comments and the order of keys are preserved. Comments can be modified
-and can be written to the output.
-
-The properties library supports both ISO-8859-1 and UTF-8 encoded data.
-
-Starting from version 1.3.0 the behavior of the MustXXX() functions is
-configurable by providing a custom `ErrorHandler` function. The default has
-changed from `panic` to `log.Fatal` but this is configurable and custom
-error handling functions can be provided. See the package documentation for
-details.
-
-Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
-
-## Getting Started
-
-```go
-import (
-	"flag"
-	"github.com/magiconair/properties"
-)
-
-func main() {
-	// init from a file
-	p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8)
-
-	// or multiple files
-	p = properties.MustLoadFiles([]string{
-			"${HOME}/config.properties",
-			"${HOME}/config-${USER}.properties",
-		}, properties.UTF8, true)
-
-	// or from a map
-	p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"})
-
-	// or from a string
-	p = properties.MustLoadString("key=value\nabc=def")
-
-	// or from a URL
-	p = properties.MustLoadURL("http://host/path")
-
-	// or from multiple URLs
-	p = properties.MustLoadURL([]string{
-			"http://host/config",
-			"http://host/config-${USER}",
-		}, true)
-
-	// or from flags
-	p.MustFlag(flag.CommandLine)
-
-	// get values through getters
-	host := p.MustGetString("host")
-	port := p.GetInt("port", 8080)
-
-	// or through Decode
-	type Config struct {
-		Host    string        `properties:"host"`
-		Port    int           `properties:"port,default=9000"`
-		Accept  []string      `properties:"accept,default=image/png;image;gif"`
-		Timeout time.Duration `properties:"timeout,default=5s"`
-	}
-	var cfg Config
-	if err := p.Decode(&cfg); err != nil {
-		log.Fatal(err)
-	}
-}
-
-```
-
-## Installation and Upgrade
-
-```
-$ go get -u github.com/magiconair/properties
-```
-
-## License
-
-2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details.
-
-## ToDo
-
-* Dump contents with passwords and secrets obscured
-
-## Updated Git tags
-
-#### 13 Feb 2018
-
-I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
-and I've only recently learned that this doesn't play well with `git describe` 😞
-
-I have replaced all lightweight tags with signed tags using this script which should
-retain the commit date, name and email address. Please run `git pull --tags` to update them.
-
-Worst case you have to reclone the repo.
-
-```shell
-#!/bin/bash
-tag=$1
-echo "Updating $tag"
-date=$(git show ${tag}^0 --format=%aD | head -1)
-email=$(git show ${tag}^0 --format=%aE | head -1)
-name=$(git show ${tag}^0 --format=%aN | head -1)
-GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
-```
-
-I apologize for the inconvenience.
-
-Frank
-
diff --git a/public-api/vendor/github.com/magiconair/properties/decode.go b/public-api/vendor/github.com/magiconair/properties/decode.go
deleted file mode 100644
index 8e6aa441..00000000
--- a/public-api/vendor/github.com/magiconair/properties/decode.go
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Decode assigns property values to exported fields of a struct.
-//
-// Decode traverses v recursively and returns an error if a value cannot be
-// converted to the field type or a required value is missing for a field.
-//
-// The following type dependent decodings are used:
-//
-// String, boolean, numeric fields have the value of the property key assigned.
-// The property key name is the name of the field. A different key and a default
-// value can be set in the field's tag. Fields without default value are
-// required. If the value cannot be converted to the field type an error is
-// returned.
-//
-// time.Duration fields have the result of time.ParseDuration() assigned.
-//
-// time.Time fields have the vaule of time.Parse() assigned. The default layout
-// is time.RFC3339 but can be set in the field's tag.
-//
-// Arrays and slices of string, boolean, numeric, time.Duration and time.Time
-// fields have the value interpreted as a comma separated list of values. The
-// individual values are trimmed of whitespace and empty values are ignored. A
-// default value can be provided as a semicolon separated list in the field's
-// tag.
-//
-// Struct fields are decoded recursively using the field name plus "." as
-// prefix. The prefix (without dot) can be overridden in the field's tag.
-// Default values are not supported in the field's tag. Specify them on the
-// fields of the inner struct instead.
-//
-// Map fields must have a key of type string and are decoded recursively by
-// using the field's name plus ".' as prefix and the next element of the key
-// name as map key. The prefix (without dot) can be overridden in the field's
-// tag. Default values are not supported.
-//
-// Examples:
-//
-//	// Field is ignored.
-//	Field int `properties:"-"`
-//
-//	// Field is assigned value of 'Field'.
-//	Field int
-//
-//	// Field is assigned value of 'myName'.
-//	Field int `properties:"myName"`
-//
-//	// Field is assigned value of key 'myName' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:"myName,default=15"`
-//
-//	// Field is assigned value of key 'Field' and has a default
-//	// value 15 if the key does not exist.
-//	Field int `properties:",default=15"`
-//
-//	// Field is assigned value of key 'date' and the date
-//	// is in format 2006-01-02
-//	Field time.Time `properties:"date,layout=2006-01-02"`
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas.
-//	Field []string
-//
-//	// Field is assigned the non-empty and whitespace trimmed
-//	// values of key 'Field' split by commas and has a default
-//	// value ["a", "b", "c"] if the key does not exist.
-//	Field []string `properties:",default=a;b;c"`
-//
-//	// Field is decoded recursively with "Field." as key prefix.
-//	Field SomeStruct
-//
-//	// Field is decoded recursively with "myName." as key prefix.
-//	Field SomeStruct `properties:"myName"`
-//
-//	// Field is decoded recursively with "Field." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string
-//
-//	// Field is decoded recursively with "myName." as key prefix
-//	// and the next dotted element of the key as map key.
-//	Field map[string]string `properties:"myName"`
-func (p *Properties) Decode(x interface{}) error {
-	t, v := reflect.TypeOf(x), reflect.ValueOf(x)
-	if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct {
-		return fmt.Errorf("not a pointer to struct: %s", t)
-	}
-	if err := dec(p, "", nil, nil, v); err != nil {
-		return err
-	}
-	return nil
-}
-
-func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
-	t := v.Type()
-
-	// value returns the property value for key or the default if provided.
-	value := func() (string, error) {
-		if val, ok := p.Get(key); ok {
-			return val, nil
-		}
-		if def != nil {
-			return *def, nil
-		}
-		return "", fmt.Errorf("missing required key %s", key)
-	}
-
-	// conv converts a string to a value of the given type.
-	conv := func(s string, t reflect.Type) (val reflect.Value, err error) {
-		var v interface{}
-
-		switch {
-		case isDuration(t):
-			v, err = time.ParseDuration(s)
-
-		case isTime(t):
-			layout := opts["layout"]
-			if layout == "" {
-				layout = time.RFC3339
-			}
-			v, err = time.Parse(layout, s)
-
-		case isBool(t):
-			v, err = boolVal(s), nil
-
-		case isString(t):
-			v, err = s, nil
-
-		case isFloat(t):
-			v, err = strconv.ParseFloat(s, 64)
-
-		case isInt(t):
-			v, err = strconv.ParseInt(s, 10, 64)
-
-		case isUint(t):
-			v, err = strconv.ParseUint(s, 10, 64)
-
-		default:
-			return reflect.Zero(t), fmt.Errorf("unsupported type %s", t)
-		}
-		if err != nil {
-			return reflect.Zero(t), err
-		}
-		return reflect.ValueOf(v).Convert(t), nil
-	}
-
-	// keydef returns the property key and the default value based on the
-	// name of the struct field and the options in the tag.
-	keydef := func(f reflect.StructField) (string, *string, map[string]string) {
-		_key, _opts := parseTag(f.Tag.Get("properties"))
-
-		var _def *string
-		if d, ok := _opts["default"]; ok {
-			_def = &d
-		}
-		if _key != "" {
-			return _key, _def, _opts
-		}
-		return f.Name, _def, _opts
-	}
-
-	switch {
-	case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t):
-		s, err := value()
-		if err != nil {
-			return err
-		}
-		val, err := conv(s, t)
-		if err != nil {
-			return err
-		}
-		v.Set(val)
-
-	case isPtr(t):
-		return dec(p, key, def, opts, v.Elem())
-
-	case isStruct(t):
-		for i := 0; i < v.NumField(); i++ {
-			fv := v.Field(i)
-			fk, def, opts := keydef(t.Field(i))
-			if !fv.CanSet() {
-				return fmt.Errorf("cannot set %s", t.Field(i).Name)
-			}
-			if fk == "-" {
-				continue
-			}
-			if key != "" {
-				fk = key + "." + fk
-			}
-			if err := dec(p, fk, def, opts, fv); err != nil {
-				return err
-			}
-		}
-		return nil
-
-	case isArray(t):
-		val, err := value()
-		if err != nil {
-			return err
-		}
-		vals := split(val, ";")
-		a := reflect.MakeSlice(t, 0, len(vals))
-		for _, s := range vals {
-			val, err := conv(s, t.Elem())
-			if err != nil {
-				return err
-			}
-			a = reflect.Append(a, val)
-		}
-		v.Set(a)
-
-	case isMap(t):
-		valT := t.Elem()
-		m := reflect.MakeMap(t)
-		for postfix := range p.FilterStripPrefix(key + ".").m {
-			pp := strings.SplitN(postfix, ".", 2)
-			mk, mv := pp[0], reflect.New(valT)
-			if err := dec(p, key+"."+mk, nil, nil, mv); err != nil {
-				return err
-			}
-			m.SetMapIndex(reflect.ValueOf(mk), mv.Elem())
-		}
-		v.Set(m)
-
-	default:
-		return fmt.Errorf("unsupported type %s", t)
-	}
-	return nil
-}
-
-// split splits a string on sep, trims whitespace of elements
-// and omits empty elements
-func split(s string, sep string) []string {
-	var a []string
-	for _, v := range strings.Split(s, sep) {
-		if v = strings.TrimSpace(v); v != "" {
-			a = append(a, v)
-		}
-	}
-	return a
-}
-
-// parseTag parses a "key,k=v,k=v,..."
-func parseTag(tag string) (key string, opts map[string]string) {
-	opts = map[string]string{}
-	for i, s := range strings.Split(tag, ",") {
-		if i == 0 {
-			key = s
-			continue
-		}
-
-		pp := strings.SplitN(s, "=", 2)
-		if len(pp) == 1 {
-			opts[pp[0]] = ""
-		} else {
-			opts[pp[0]] = pp[1]
-		}
-	}
-	return key, opts
-}
-
-func isArray(t reflect.Type) bool    { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice }
-func isBool(t reflect.Type) bool     { return t.Kind() == reflect.Bool }
-func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) }
-func isMap(t reflect.Type) bool      { return t.Kind() == reflect.Map }
-func isPtr(t reflect.Type) bool      { return t.Kind() == reflect.Ptr }
-func isString(t reflect.Type) bool   { return t.Kind() == reflect.String }
-func isStruct(t reflect.Type) bool   { return t.Kind() == reflect.Struct }
-func isTime(t reflect.Type) bool     { return t == reflect.TypeOf(time.Time{}) }
-func isFloat(t reflect.Type) bool {
-	return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64
-}
-func isInt(t reflect.Type) bool {
-	return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64
-}
-func isUint(t reflect.Type) bool {
-	return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/doc.go b/public-api/vendor/github.com/magiconair/properties/doc.go
deleted file mode 100644
index 7c797931..00000000
--- a/public-api/vendor/github.com/magiconair/properties/doc.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package properties provides functions for reading and writing
-// ISO-8859-1 and UTF-8 encoded .properties files and has
-// support for recursive property expansion.
-//
-// Java properties files are ISO-8859-1 encoded and use Unicode
-// literals for characters outside the ISO character set. Unicode
-// literals can be used in UTF-8 encoded properties files but
-// aren't necessary.
-//
-// To load a single properties file use MustLoadFile():
-//
-//	p := properties.MustLoadFile(filename, properties.UTF8)
-//
-// To load multiple properties files use MustLoadFiles()
-// which loads the files in the given order and merges the
-// result. Missing properties files can be ignored if the
-// 'ignoreMissing' flag is set to true.
-//
-// Filenames can contain environment variables which are expanded
-// before loading.
-//
-//	f1 := "/etc/myapp/myapp.conf"
-//	f2 := "/home/${USER}/myapp.conf"
-//	p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)
-//
-// All of the different key/value delimiters ' ', ':' and '=' are
-// supported as well as the comment characters '!' and '#' and
-// multi-line values.
-//
-//	! this is a comment
-//	# and so is this
-//
-//	# the following expressions are equal
-//	key value
-//	key=value
-//	key:value
-//	key = value
-//	key : value
-//	key = val\
-//	      ue
-//
-// Properties stores all comments preceding a key and provides
-// GetComments() and SetComments() methods to retrieve and
-// update them. The convenience functions GetComment() and
-// SetComment() allow access to the last comment. The
-// WriteComment() method writes properties files including
-// the comments and with the keys in the original order.
-// This can be used for sanitizing properties files.
-//
-// Property expansion is recursive and circular references
-// and malformed expressions are not allowed and cause an
-// error. Expansion of environment variables is supported.
-//
-//	# standard property
-//	key = value
-//
-//	# property expansion: key2 = value
-//	key2 = ${key}
-//
-//	# recursive expansion: key3 = value
-//	key3 = ${key2}
-//
-//	# circular reference (error)
-//	key = ${key}
-//
-//	# malformed expression (error)
-//	key = ${ke
-//
-//	# refers to the users' home dir
-//	home = ${HOME}
-//
-//	# local key takes precedence over env var: u = foo
-//	USER = foo
-//	u = ${USER}
-//
-// The default property expansion format is ${key} but can be
-// changed by setting different pre- and postfix values on the
-// Properties object.
-//
-//	p := properties.NewProperties()
-//	p.Prefix = "#["
-//	p.Postfix = "]#"
-//
-// Properties provides convenience functions for getting typed
-// values with default values if the key does not exist or the
-// type conversion failed.
-//
-//	# Returns true if the value is either "1", "on", "yes" or "true"
-//	# Returns false for every other value and the default value if
-//	# the key does not exist.
-//	v = p.GetBool("key", false)
-//
-//	# Returns the value if the key exists and the format conversion
-//	# was successful. Otherwise, the default value is returned.
-//	v = p.GetInt64("key", 999)
-//	v = p.GetUint64("key", 999)
-//	v = p.GetFloat64("key", 123.0)
-//	v = p.GetString("key", "def")
-//	v = p.GetDuration("key", 999)
-//
-// As an alternative properties may be applied with the standard
-// library's flag implementation at any time.
-//
-//	# Standard configuration
-//	v = flag.Int("key", 999, "help message")
-//	flag.Parse()
-//
-//	# Merge p into the flag set
-//	p.MustFlag(flag.CommandLine)
-//
-// Properties provides several MustXXX() convenience functions
-// which will terminate the app if an error occurs. The behavior
-// of the failure is configurable and the default is to call
-// log.Fatal(err). To have the MustXXX() functions panic instead
-// of logging the error set a different ErrorHandler before
-// you use the Properties package.
-//
-//	properties.ErrorHandler = properties.PanicHandler
-//
-//	# Will panic instead of logging an error
-//	p := properties.MustLoadFile("config.properties")
-//
-// You can also provide your own ErrorHandler function. The only requirement
-// is that the error handler function must exit after handling the error.
-//
-//	  properties.ErrorHandler = func(err error) {
-//		     fmt.Println(err)
-//	      os.Exit(1)
-//	  }
-//
-//	  # Will write to stdout and then exit
-//	  p := properties.MustLoadFile("config.properties")
-//
-// Properties can also be loaded into a struct via the `Decode`
-// method, e.g.
-//
-//	type S struct {
-//	    A string        `properties:"a,default=foo"`
-//	    D time.Duration `properties:"timeout,default=5s"`
-//	    E time.Time     `properties:"expires,layout=2006-01-02,default=2015-01-01"`
-//	}
-//
-// See `Decode()` method for the full documentation.
-//
-// The following documents provide a description of the properties
-// file format.
-//
-// http://en.wikipedia.org/wiki/.properties
-//
-// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29
-package properties
diff --git a/public-api/vendor/github.com/magiconair/properties/integrate.go b/public-api/vendor/github.com/magiconair/properties/integrate.go
deleted file mode 100644
index 35d0ae97..00000000
--- a/public-api/vendor/github.com/magiconair/properties/integrate.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import "flag"
-
-// MustFlag sets flags that are skipped by dst.Parse when p contains
-// the respective key for flag.Flag.Name.
-//
-// It's use is recommended with command line arguments as in:
-//
-//	flag.Parse()
-//	p.MustFlag(flag.CommandLine)
-func (p *Properties) MustFlag(dst *flag.FlagSet) {
-	m := make(map[string]*flag.Flag)
-	dst.VisitAll(func(f *flag.Flag) {
-		m[f.Name] = f
-	})
-	dst.Visit(func(f *flag.Flag) {
-		delete(m, f.Name) // overridden
-	})
-
-	for name, f := range m {
-		v, ok := p.Get(name)
-		if !ok {
-			continue
-		}
-
-		if err := f.Value.Set(v); err != nil {
-			ErrorHandler(err)
-		}
-	}
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/lex.go b/public-api/vendor/github.com/magiconair/properties/lex.go
deleted file mode 100644
index 3d15a1f6..00000000
--- a/public-api/vendor/github.com/magiconair/properties/lex.go
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// Parts of the lexer are from the template/text/parser package
-// For these parts the following applies:
-//
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file of the go 1.2
-// distribution.
-
-package properties
-
-import (
-	"fmt"
-	"strconv"
-	"strings"
-	"unicode/utf8"
-)
-
-// item represents a token or text string returned from the scanner.
-type item struct {
-	typ itemType // The type of this item.
-	pos int      // The starting position, in bytes, of this item in the input string.
-	val string   // The value of this item.
-}
-
-func (i item) String() string {
-	switch {
-	case i.typ == itemEOF:
-		return "EOF"
-	case i.typ == itemError:
-		return i.val
-	case len(i.val) > 10:
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError itemType = iota // error occurred; value is text of error
-	itemEOF
-	itemKey     // a key
-	itemValue   // a value
-	itemComment // a comment
-)
-
-// defines a constant for EOF
-const eof = -1
-
-// permitted whitespace characters space, FF and TAB
-const whitespace = " \f\t"
-
-// stateFn represents the state of the scanner as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	input   string    // the string being scanned
-	state   stateFn   // the next lexing function to enter
-	pos     int       // current position in the input
-	start   int       // start position of this item
-	width   int       // width of last rune read from input
-	lastPos int       // position of most recent item returned by nextItem
-	runes   []rune    // scanned runes for this item
-	items   chan item // channel of scanned items
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() rune {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
-	l.width = w
-	l.pos += l.width
-	return r
-}
-
-// peek returns but does not consume the next rune in the input.
-func (l *lexer) peek() rune {
-	r := l.next()
-	l.backup()
-	return r
-}
-
-// backup steps back one rune. Can only be called once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	i := item{t, l.start, string(l.runes)}
-	l.items <- i
-	l.start = l.pos
-	l.runes = l.runes[:0]
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// appends the rune to the current value
-func (l *lexer) appendRune(r rune) {
-	l.runes = append(l.runes, r)
-}
-
-// accept consumes the next rune if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.ContainsRune(valid, l.next()) {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.ContainsRune(valid, l.next()) {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on, based on the position of
-// the previous item returned by nextItem. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.lastPos], "\n")
-}
-
-// errorf returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.nextItem.
-func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
-	return nil
-}
-
-// nextItem returns the next item from the input.
-func (l *lexer) nextItem() item {
-	i := <-l.items
-	l.lastPos = i.pos
-	return i
-}
-
-// lex creates a new scanner for the input string.
-func lex(input string) *lexer {
-	l := &lexer{
-		input: input,
-		items: make(chan item),
-		runes: make([]rune, 0, 32),
-	}
-	go l.run()
-	return l
-}
-
-// run runs the state machine for the lexer.
-func (l *lexer) run() {
-	for l.state = lexBeforeKey(l); l.state != nil; {
-		l.state = l.state(l)
-	}
-}
-
-// state functions
-
-// lexBeforeKey scans until a key begins.
-func lexBeforeKey(l *lexer) stateFn {
-	switch r := l.next(); {
-	case isEOF(r):
-		l.emit(itemEOF)
-		return nil
-
-	case isEOL(r):
-		l.ignore()
-		return lexBeforeKey
-
-	case isComment(r):
-		return lexComment
-
-	case isWhitespace(r):
-		l.ignore()
-		return lexBeforeKey
-
-	default:
-		l.backup()
-		return lexKey
-	}
-}
-
-// lexComment scans a comment line. The comment character has already been scanned.
-func lexComment(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.ignore()
-	for {
-		switch r := l.next(); {
-		case isEOF(r):
-			l.ignore()
-			l.emit(itemEOF)
-			return nil
-		case isEOL(r):
-			l.emit(itemComment)
-			return lexBeforeKey
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// lexKey scans the key up to a delimiter
-func lexKey(l *lexer) stateFn {
-	var r rune
-
-Loop:
-	for {
-		switch r = l.next(); {
-
-		case isEscape(r):
-			err := l.scanEscapeSequence()
-			if err != nil {
-				return l.errorf(err.Error())
-			}
-
-		case isEndOfKey(r):
-			l.backup()
-			break Loop
-
-		case isEOF(r):
-			break Loop
-
-		default:
-			l.appendRune(r)
-		}
-	}
-
-	if len(l.runes) > 0 {
-		l.emit(itemKey)
-	}
-
-	if isEOF(r) {
-		l.emit(itemEOF)
-		return nil
-	}
-
-	return lexBeforeValue
-}
-
-// lexBeforeValue scans the delimiter between key and value.
-// Leading and trailing whitespace is ignored.
-// We expect to be just after the key.
-func lexBeforeValue(l *lexer) stateFn {
-	l.acceptRun(whitespace)
-	l.accept(":=")
-	l.acceptRun(whitespace)
-	l.ignore()
-	return lexValue
-}
-
-// lexValue scans text until the end of the line. We expect to be just after the delimiter.
-func lexValue(l *lexer) stateFn {
-	for {
-		switch r := l.next(); {
-		case isEscape(r):
-			if isEOL(l.peek()) {
-				l.next()
-				l.acceptRun(whitespace)
-			} else {
-				err := l.scanEscapeSequence()
-				if err != nil {
-					return l.errorf(err.Error())
-				}
-			}
-
-		case isEOL(r):
-			l.emit(itemValue)
-			l.ignore()
-			return lexBeforeKey
-
-		case isEOF(r):
-			l.emit(itemValue)
-			l.emit(itemEOF)
-			return nil
-
-		default:
-			l.appendRune(r)
-		}
-	}
-}
-
-// scanEscapeSequence scans either one of the escaped characters
-// or a unicode literal. We expect to be after the escape character.
-func (l *lexer) scanEscapeSequence() error {
-	switch r := l.next(); {
-
-	case isEscapedCharacter(r):
-		l.appendRune(decodeEscapedCharacter(r))
-		return nil
-
-	case atUnicodeLiteral(r):
-		return l.scanUnicodeLiteral()
-
-	case isEOF(r):
-		return fmt.Errorf("premature EOF")
-
-	// silently drop the escape character and append the rune as is
-	default:
-		l.appendRune(r)
-		return nil
-	}
-}
-
-// scans a unicode literal in the form \uXXXX. We expect to be after the \u.
-func (l *lexer) scanUnicodeLiteral() error {
-	// scan the digits
-	d := make([]rune, 4)
-	for i := 0; i < 4; i++ {
-		d[i] = l.next()
-		if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) {
-			return fmt.Errorf("invalid unicode literal")
-		}
-	}
-
-	// decode the digits into a rune
-	r, err := strconv.ParseInt(string(d), 16, 0)
-	if err != nil {
-		return err
-	}
-
-	l.appendRune(rune(r))
-	return nil
-}
-
-// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character.
-func decodeEscapedCharacter(r rune) rune {
-	switch r {
-	case 'f':
-		return '\f'
-	case 'n':
-		return '\n'
-	case 'r':
-		return '\r'
-	case 't':
-		return '\t'
-	default:
-		return r
-	}
-}
-
-// atUnicodeLiteral reports whether we are at a unicode literal.
-// The escape character has already been consumed.
-func atUnicodeLiteral(r rune) bool {
-	return r == 'u'
-}
-
-// isComment reports whether we are at the start of a comment.
-func isComment(r rune) bool {
-	return r == '#' || r == '!'
-}
-
-// isEndOfKey reports whether the rune terminates the current key.
-func isEndOfKey(r rune) bool {
-	return strings.ContainsRune(" \f\t\r\n:=", r)
-}
-
-// isEOF reports whether we are at EOF.
-func isEOF(r rune) bool {
-	return r == eof
-}
-
-// isEOL reports whether we are at a new line character.
-func isEOL(r rune) bool {
-	return r == '\n' || r == '\r'
-}
-
-// isEscape reports whether the rune is the escape character which
-// prefixes unicode literals and other escaped characters.
-func isEscape(r rune) bool {
-	return r == '\\'
-}
-
-// isEscapedCharacter reports whether we are at one of the characters that need escaping.
-// The escape character has already been consumed.
-func isEscapedCharacter(r rune) bool {
-	return strings.ContainsRune(" :=fnrt", r)
-}
-
-// isWhitespace reports whether the rune is a whitespace character.
-func isWhitespace(r rune) bool {
-	return strings.ContainsRune(whitespace, r)
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/load.go b/public-api/vendor/github.com/magiconair/properties/load.go
deleted file mode 100644
index 635368dc..00000000
--- a/public-api/vendor/github.com/magiconair/properties/load.go
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"strings"
-)
-
-// Encoding specifies encoding of the input data.
-type Encoding uint
-
-const (
-	// utf8Default is a private placeholder for the zero value of Encoding to
-	// ensure that it has the correct meaning. UTF8 is the default encoding but
-	// was assigned a non-zero value which cannot be changed without breaking
-	// existing code. Clients should continue to use the public constants.
-	utf8Default Encoding = iota
-
-	// UTF8 interprets the input data as UTF-8.
-	UTF8
-
-	// ISO_8859_1 interprets the input data as ISO-8859-1.
-	ISO_8859_1
-)
-
-type Loader struct {
-	// Encoding determines how the data from files and byte buffers
-	// is interpreted. For URLs the Content-Type header is used
-	// to determine the encoding of the data.
-	Encoding Encoding
-
-	// DisableExpansion configures the property expansion of the
-	// returned property object. When set to true, the property values
-	// will not be expanded and the Property object will not be checked
-	// for invalid expansion expressions.
-	DisableExpansion bool
-
-	// IgnoreMissing configures whether missing files or URLs which return
-	// 404 are reported as errors. When set to true, missing files and 404
-	// status codes are not reported as errors.
-	IgnoreMissing bool
-}
-
-// Load reads a buffer into a Properties struct.
-func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
-	return l.loadBytes(buf, l.Encoding)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into
-// a Properties struct. If IgnoreMissing is true then a 404 status code or
-// missing file will not be reported as error. Encoding sets the encoding for
-// files. For the URLs see LoadURL for the Content-Type header and the
-// encoding.
-func (l *Loader) LoadAll(names []string) (*Properties, error) {
-	all := NewProperties()
-	for _, name := range names {
-		n, err := expandName(name)
-		if err != nil {
-			return nil, err
-		}
-
-		var p *Properties
-		switch {
-		case strings.HasPrefix(n, "http://"):
-			p, err = l.LoadURL(n)
-		case strings.HasPrefix(n, "https://"):
-			p, err = l.LoadURL(n)
-		default:
-			p, err = l.LoadFile(n)
-		}
-		if err != nil {
-			return nil, err
-		}
-		all.Merge(p)
-	}
-
-	all.DisableExpansion = l.DisableExpansion
-	if all.DisableExpansion {
-		return all, nil
-	}
-	return all, all.check()
-}
-
-// LoadFile reads a file into a Properties struct.
-// If IgnoreMissing is true then a missing file will not be
-// reported as error.
-func (l *Loader) LoadFile(filename string) (*Properties, error) {
-	data, err := ioutil.ReadFile(filename)
-	if err != nil {
-		if l.IgnoreMissing && os.IsNotExist(err) {
-			LogPrintf("properties: %s not found. skipping", filename)
-			return NewProperties(), nil
-		}
-		return nil, err
-	}
-	return l.loadBytes(data, l.Encoding)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-//
-// The encoding is determined via the Content-Type header which
-// should be set to 'text/plain'. If the 'charset' parameter is
-// missing, 'iso-8859-1' or 'latin1' the encoding is set to
-// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
-// encoding is set to UTF-8. A missing content type header is
-// interpreted as 'text/plain; charset=utf-8'.
-func (l *Loader) LoadURL(url string) (*Properties, error) {
-	resp, err := http.Get(url)
-	if err != nil {
-		return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode == 404 && l.IgnoreMissing {
-		LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
-		return NewProperties(), nil
-	}
-
-	if resp.StatusCode != 200 {
-		return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
-	}
-
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
-	}
-
-	ct := resp.Header.Get("Content-Type")
-	ct = strings.Join(strings.Fields(ct), "")
-	var enc Encoding
-	switch strings.ToLower(ct) {
-	case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1":
-		enc = ISO_8859_1
-	case "", "text/plain;charset=utf-8":
-		enc = UTF8
-	default:
-		return nil, fmt.Errorf("properties: invalid content type %s", ct)
-	}
-
-	return l.loadBytes(body, enc)
-}
-
-func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) {
-	p, err := parse(convert(buf, enc))
-	if err != nil {
-		return nil, err
-	}
-	p.DisableExpansion = l.DisableExpansion
-	if p.DisableExpansion {
-		return p, nil
-	}
-	return p, p.check()
-}
-
-// Load reads a buffer into a Properties struct.
-func Load(buf []byte, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadBytes(buf)
-}
-
-// LoadString reads an UTF8 string into a properties struct.
-func LoadString(s string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadBytes([]byte(s))
-}
-
-// LoadMap creates a new Properties struct from a string map.
-func LoadMap(m map[string]string) *Properties {
-	p := NewProperties()
-	for k, v := range m {
-		p.Set(k, v)
-	}
-	return p
-}
-
-// LoadFile reads a file into a Properties struct.
-func LoadFile(filename string, enc Encoding) (*Properties, error) {
-	l := &Loader{Encoding: enc}
-	return l.LoadAll([]string{filename})
-}
-
-// LoadFiles reads multiple files in the given order into
-// a Properties struct. If 'ignoreMissing' is true then
-// non-existent files will not be reported as error.
-func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(filenames)
-}
-
-// LoadURL reads the content of the URL into a Properties struct.
-// See Loader#LoadURL for details.
-func LoadURL(url string) (*Properties, error) {
-	l := &Loader{Encoding: UTF8}
-	return l.LoadAll([]string{url})
-}
-
-// LoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct. If IgnoreMissing is true then a 404 status code will
-// not be reported as error. See Loader#LoadURL for the Content-Type header
-// and the encoding.
-func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(urls)
-}
-
-// LoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding.
-func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
-	l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
-	return l.LoadAll(names)
-}
-
-// MustLoadString reads an UTF8 string into a Properties struct and
-// panics on error.
-func MustLoadString(s string) *Properties {
-	return must(LoadString(s))
-}
-
-// MustLoadFile reads a file into a Properties struct and
-// panics on error.
-func MustLoadFile(filename string, enc Encoding) *Properties {
-	return must(LoadFile(filename, enc))
-}
-
-// MustLoadFiles reads multiple files in the given order into
-// a Properties struct and panics on error. If 'ignoreMissing'
-// is true then non-existent files will not be reported as error.
-func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadFiles(filenames, enc, ignoreMissing))
-}
-
-// MustLoadURL reads the content of a URL into a Properties struct and
-// panics on error.
-func MustLoadURL(url string) *Properties {
-	return must(LoadURL(url))
-}
-
-// MustLoadURLs reads the content of multiple URLs in the given order into a
-// Properties struct and panics on error. If 'ignoreMissing' is true then a 404
-// status code will not be reported as error.
-func MustLoadURLs(urls []string, ignoreMissing bool) *Properties {
-	return must(LoadURLs(urls, ignoreMissing))
-}
-
-// MustLoadAll reads the content of multiple URLs or files in the given order into a
-// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
-// not be reported as error. Encoding sets the encoding for files. For the URLs please see
-// LoadURL for the Content-Type header and the encoding. It panics on error.
-func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
-	return must(LoadAll(names, enc, ignoreMissing))
-}
-
-func must(p *Properties, err error) *Properties {
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return p
-}
-
-// expandName expands ${ENV_VAR} expressions in a name.
-// If the environment variable does not exist then it will be replaced
-// with an empty string. Malformed expressions like "${ENV_VAR" will
-// be reported as error.
-func expandName(name string) (string, error) {
-	return expand(name, []string{}, "${", "}", make(map[string]string))
-}
-
-// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
-// For ISO-8859-1 we can convert each byte straight into a rune since the
-// first 256 unicode code points cover ISO-8859-1.
-func convert(buf []byte, enc Encoding) string {
-	switch enc {
-	case utf8Default, UTF8:
-		return string(buf)
-	case ISO_8859_1:
-		runes := make([]rune, len(buf))
-		for i, b := range buf {
-			runes[i] = rune(b)
-		}
-		return string(runes)
-	default:
-		ErrorHandler(fmt.Errorf("unsupported encoding %v", enc))
-	}
-	panic("ErrorHandler should exit")
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/parser.go b/public-api/vendor/github.com/magiconair/properties/parser.go
deleted file mode 100644
index fccfd39f..00000000
--- a/public-api/vendor/github.com/magiconair/properties/parser.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"runtime"
-)
-
-type parser struct {
-	lex *lexer
-}
-
-func parse(input string) (properties *Properties, err error) {
-	p := &parser{lex: lex(input)}
-	defer p.recover(&err)
-
-	properties = NewProperties()
-	key := ""
-	comments := []string{}
-
-	for {
-		token := p.expectOneOf(itemComment, itemKey, itemEOF)
-		switch token.typ {
-		case itemEOF:
-			goto done
-		case itemComment:
-			comments = append(comments, token.val)
-			continue
-		case itemKey:
-			key = token.val
-			if _, ok := properties.m[key]; !ok {
-				properties.k = append(properties.k, key)
-			}
-		}
-
-		token = p.expectOneOf(itemValue, itemEOF)
-		if len(comments) > 0 {
-			properties.c[key] = comments
-			comments = []string{}
-		}
-		switch token.typ {
-		case itemEOF:
-			properties.m[key] = ""
-			goto done
-		case itemValue:
-			properties.m[key] = token.val
-		}
-	}
-
-done:
-	return properties, nil
-}
-
-func (p *parser) errorf(format string, args ...interface{}) {
-	format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
-	panic(fmt.Errorf(format, args...))
-}
-
-func (p *parser) expectOneOf(expected ...itemType) (token item) {
-	token = p.lex.nextItem()
-	for _, v := range expected {
-		if token.typ == v {
-			return token
-		}
-	}
-	p.unexpected(token)
-	panic("unexpected token")
-}
-
-func (p *parser) unexpected(token item) {
-	p.errorf(token.String())
-}
-
-// recover is the handler that turns panics into returns from the top level of Parse.
-func (p *parser) recover(errp *error) {
-	e := recover()
-	if e != nil {
-		if _, ok := e.(runtime.Error); ok {
-			panic(e)
-		}
-		*errp = e.(error)
-	}
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/properties.go b/public-api/vendor/github.com/magiconair/properties/properties.go
deleted file mode 100644
index fb2f7b40..00000000
--- a/public-api/vendor/github.com/magiconair/properties/properties.go
+++ /dev/null
@@ -1,848 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer.
-// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used.
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"regexp"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-	"unicode/utf8"
-)
-
-const maxExpansionDepth = 64
-
-// ErrorHandlerFunc defines the type of function which handles failures
-// of the MustXXX() functions. An error handler function must exit
-// the application after handling the error.
-type ErrorHandlerFunc func(error)
-
-// ErrorHandler is the function which handles failures of the MustXXX()
-// functions. The default is LogFatalHandler.
-var ErrorHandler ErrorHandlerFunc = LogFatalHandler
-
-// LogHandlerFunc defines the function prototype for logging errors.
-type LogHandlerFunc func(fmt string, args ...interface{})
-
-// LogPrintf defines a log handler which uses log.Printf.
-var LogPrintf LogHandlerFunc = log.Printf
-
-// LogFatalHandler handles the error by logging a fatal error and exiting.
-func LogFatalHandler(err error) {
-	log.Fatal(err)
-}
-
-// PanicHandler handles the error by panicking.
-func PanicHandler(err error) {
-	panic(err)
-}
-
-// -----------------------------------------------------------------------------
-
-// A Properties contains the key/value pairs from the properties input.
-// All values are stored in unexpanded form and are expanded at runtime
-type Properties struct {
-	// Pre-/Postfix for property expansion.
-	Prefix  string
-	Postfix string
-
-	// DisableExpansion controls the expansion of properties on Get()
-	// and the check for circular references on Set(). When set to
-	// true Properties behaves like a simple key/value store and does
-	// not check for circular references on Get() or on Set().
-	DisableExpansion bool
-
-	// Stores the key/value pairs
-	m map[string]string
-
-	// Stores the comments per key.
-	c map[string][]string
-
-	// Stores the keys in order of appearance.
-	k []string
-
-	// WriteSeparator specifies the separator of key and value while writing the properties.
-	WriteSeparator string
-}
-
-// NewProperties creates a new Properties struct with the default
-// configuration for "${key}" expressions.
-func NewProperties() *Properties {
-	return &Properties{
-		Prefix:  "${",
-		Postfix: "}",
-		m:       map[string]string{},
-		c:       map[string][]string{},
-		k:       []string{},
-	}
-}
-
-// Load reads a buffer into the given Properties struct.
-func (p *Properties) Load(buf []byte, enc Encoding) error {
-	l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion}
-	newProperties, err := l.LoadBytes(buf)
-	if err != nil {
-		return err
-	}
-	p.Merge(newProperties)
-	return nil
-}
-
-// Get returns the expanded value for the given key if exists.
-// Otherwise, ok is false.
-func (p *Properties) Get(key string) (value string, ok bool) {
-	v, ok := p.m[key]
-	if p.DisableExpansion {
-		return v, ok
-	}
-	if !ok {
-		return "", false
-	}
-
-	expanded, err := p.expand(key, v)
-
-	// we guarantee that the expanded value is free of
-	// circular references and malformed expressions
-	// so we panic if we still get an error here.
-	if err != nil {
-		ErrorHandler(err)
-	}
-
-	return expanded, true
-}
-
-// MustGet returns the expanded value for the given key if exists.
-// Otherwise, it panics.
-func (p *Properties) MustGet(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// ClearComments removes the comments for all keys.
-func (p *Properties) ClearComments() {
-	p.c = map[string][]string{}
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComment returns the last comment before the given key or an empty string.
-func (p *Properties) GetComment(key string) string {
-	comments, ok := p.c[key]
-	if !ok || len(comments) == 0 {
-		return ""
-	}
-	return comments[len(comments)-1]
-}
-
-// ----------------------------------------------------------------------------
-
-// GetComments returns all comments that appeared before the given key or nil.
-func (p *Properties) GetComments(key string) []string {
-	if comments, ok := p.c[key]; ok {
-		return comments
-	}
-	return nil
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComment sets the comment for the key.
-func (p *Properties) SetComment(key, comment string) {
-	p.c[key] = []string{comment}
-}
-
-// ----------------------------------------------------------------------------
-
-// SetComments sets the comments for the key. If the comments are nil then
-// all comments for this key are deleted.
-func (p *Properties) SetComments(key string, comments []string) {
-	if comments == nil {
-		delete(p.c, key)
-		return
-	}
-	p.c[key] = comments
-}
-
-// ----------------------------------------------------------------------------
-
-// GetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the default value is returned.
-func (p *Properties) GetBool(key string, def bool) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetBool checks if the expanded value is one of '1', 'yes',
-// 'true' or 'on' if the key exists. The comparison is case-insensitive.
-// If the key does not exist the function panics.
-func (p *Properties) MustGetBool(key string) bool {
-	v, err := p.getBool(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getBool(key string) (value bool, err error) {
-	if v, ok := p.Get(key); ok {
-		return boolVal(v), nil
-	}
-	return false, invalidKeyError(key)
-}
-
-func boolVal(v string) bool {
-	v = strings.ToLower(v)
-	return v == "1" || v == "true" || v == "yes" || v == "on"
-}
-
-// ----------------------------------------------------------------------------
-
-// GetDuration parses the expanded value as an time.Duration (in ns) if the
-// key exists. If key does not exist or the value cannot be parsed the default
-// value is returned. In almost all cases you want to use GetParsedDuration().
-func (p *Properties) GetDuration(key string, def time.Duration) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return time.Duration(v)
-}
-
-// MustGetDuration parses the expanded value as an time.Duration (in ns) if
-// the key exists. If key does not exist or the value cannot be parsed the
-// function panics. In almost all cases you want to use MustGetParsedDuration().
-func (p *Properties) MustGetDuration(key string) time.Duration {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return time.Duration(v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		return def
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetParsedDuration(key string) time.Duration {
-	s, ok := p.Get(key)
-	if !ok {
-		ErrorHandler(invalidKeyError(key))
-	}
-	v, err := time.ParseDuration(s)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-// ----------------------------------------------------------------------------
-
-// GetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetFloat64(key string, def float64) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetFloat64 parses the expanded value as a float64 if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetFloat64(key string) float64 {
-	v, err := p.getFloat64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getFloat64(key string) (value float64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseFloat(v, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetInt(key string, def int) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return intRangeCheck(key, v)
-}
-
-// MustGetInt parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetInt(key string) int {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return intRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetInt64 parses the expanded value as an int64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetInt64(key string, def int64) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetInt64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetInt64(key string) int64 {
-	v, err := p.getInt64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getInt64(key string) (value int64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseInt(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint parses the expanded value as an uint if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned. If the value does not fit into an int the
-// function panics with an out of range error.
-func (p *Properties) GetUint(key string, def uint) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return uintRangeCheck(key, v)
-}
-
-// MustGetUint parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-// If the value does not fit into an int the function panics with
-// an out of range error.
-func (p *Properties) MustGetUint(key string) uint {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return uintRangeCheck(key, v)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetUint64 parses the expanded value as an uint64 if the key exists.
-// If key does not exist or the value cannot be parsed the default
-// value is returned.
-func (p *Properties) GetUint64(key string, def uint64) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		return def
-	}
-	return v
-}
-
-// MustGetUint64 parses the expanded value as an int if the key exists.
-// If key does not exist or the value cannot be parsed the function panics.
-func (p *Properties) MustGetUint64(key string) uint64 {
-	v, err := p.getUint64(key)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return v
-}
-
-func (p *Properties) getUint64(key string) (value uint64, err error) {
-	if v, ok := p.Get(key); ok {
-		value, err = strconv.ParseUint(v, 10, 64)
-		if err != nil {
-			return 0, err
-		}
-		return value, nil
-	}
-	return 0, invalidKeyError(key)
-}
-
-// ----------------------------------------------------------------------------
-
-// GetString returns the expanded value for the given key if exists or
-// the default value otherwise.
-func (p *Properties) GetString(key, def string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	return def
-}
-
-// MustGetString returns the expanded value for the given key if exists or
-// panics otherwise.
-func (p *Properties) MustGetString(key string) string {
-	if v, ok := p.Get(key); ok {
-		return v
-	}
-	ErrorHandler(invalidKeyError(key))
-	panic("ErrorHandler should exit")
-}
-
-// ----------------------------------------------------------------------------
-
-// Filter returns a new properties object which contains all properties
-// for which the key matches the pattern.
-func (p *Properties) Filter(pattern string) (*Properties, error) {
-	re, err := regexp.Compile(pattern)
-	if err != nil {
-		return nil, err
-	}
-
-	return p.FilterRegexp(re), nil
-}
-
-// FilterRegexp returns a new properties object which contains all properties
-// for which the key matches the regular expression.
-func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if re.MatchString(k) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterPrefix returns a new properties object with a subset of all keys
-// with the given prefix.
-func (p *Properties) FilterPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	for _, k := range p.k {
-		if strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed)
-			pp.Set(k, p.m[k])
-		}
-	}
-	return pp
-}
-
-// FilterStripPrefix returns a new properties object with a subset of all keys
-// with the given prefix and the prefix removed from the keys.
-func (p *Properties) FilterStripPrefix(prefix string) *Properties {
-	pp := NewProperties()
-	n := len(prefix)
-	for _, k := range p.k {
-		if len(k) > len(prefix) && strings.HasPrefix(k, prefix) {
-			// TODO(fs): we are ignoring the error which flags a circular reference.
-			// TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference
-			// TODO(fs): this function should probably return an error but the signature is fixed
-			pp.Set(k[n:], p.m[k])
-		}
-	}
-	return pp
-}
-
-// Len returns the number of keys.
-func (p *Properties) Len() int {
-	return len(p.m)
-}
-
-// Keys returns all keys in the same order as in the input.
-func (p *Properties) Keys() []string {
-	keys := make([]string, len(p.k))
-	copy(keys, p.k)
-	return keys
-}
-
-// Set sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. If the value contains a
-// circular reference or a malformed expression then
-// an error is returned.
-// An empty key is silently ignored.
-func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
-	if key == "" {
-		return "", false, nil
-	}
-
-	// if expansion is disabled we allow circular references
-	if p.DisableExpansion {
-		prev, ok = p.Get(key)
-		p.m[key] = value
-		if !ok {
-			p.k = append(p.k, key)
-		}
-		return prev, ok, nil
-	}
-
-	// to check for a circular reference we temporarily need
-	// to set the new value. If there is an error then revert
-	// to the previous state. Only if all tests are successful
-	// then we add the key to the p.k list.
-	prev, ok = p.Get(key)
-	p.m[key] = value
-
-	// now check for a circular reference
-	_, err = p.expand(key, value)
-	if err != nil {
-
-		// revert to the previous state
-		if ok {
-			p.m[key] = prev
-		} else {
-			delete(p.m, key)
-		}
-
-		return "", false, err
-	}
-
-	if !ok {
-		p.k = append(p.k, key)
-	}
-
-	return prev, ok, nil
-}
-
-// SetValue sets property key to the default string value
-// as defined by fmt.Sprintf("%v").
-func (p *Properties) SetValue(key string, value interface{}) error {
-	_, _, err := p.Set(key, fmt.Sprintf("%v", value))
-	return err
-}
-
-// MustSet sets the property key to the corresponding value.
-// If a value for key existed before then ok is true and prev
-// contains the previous value. An empty key is silently ignored.
-func (p *Properties) MustSet(key, value string) (prev string, ok bool) {
-	prev, ok, err := p.Set(key, value)
-	if err != nil {
-		ErrorHandler(err)
-	}
-	return prev, ok
-}
-
-// String returns a string of all expanded 'key = value' pairs.
-func (p *Properties) String() string {
-	var s string
-	for _, key := range p.k {
-		value, _ := p.Get(key)
-		s = fmt.Sprintf("%s%s = %s\n", s, key, value)
-	}
-	return s
-}
-
-// Sort sorts the properties keys in alphabetical order.
-// This is helpfully before writing the properties.
-func (p *Properties) Sort() {
-	sort.Strings(p.k)
-}
-
-// Write writes all unexpanded 'key = value' pairs to the given writer.
-// Write returns the number of bytes written and any write error encountered.
-func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) {
-	return p.WriteComment(w, "", enc)
-}
-
-// WriteComment writes all unexpanced 'key = value' pairs to the given writer.
-// If prefix is not empty then comments are written with a blank line and the
-// given prefix. The prefix should be either "# " or "! " to be compatible with
-// the properties file format. Otherwise, the properties parser will not be
-// able to read the file back in. It returns the number of bytes written and
-// any write error encountered.
-func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) {
-	var x int
-
-	for _, key := range p.k {
-		value := p.m[key]
-
-		if prefix != "" {
-			if comments, ok := p.c[key]; ok {
-				// don't print comments if they are all empty
-				allEmpty := true
-				for _, c := range comments {
-					if c != "" {
-						allEmpty = false
-						break
-					}
-				}
-
-				if !allEmpty {
-					// add a blank line between entries but not at the top
-					if len(comments) > 0 && n > 0 {
-						x, err = fmt.Fprintln(w)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-
-					for _, c := range comments {
-						x, err = fmt.Fprintf(w, "%s%s\n", prefix, c)
-						if err != nil {
-							return
-						}
-						n += x
-					}
-				}
-			}
-		}
-		sep := " = "
-		if p.WriteSeparator != "" {
-			sep = p.WriteSeparator
-		}
-		x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc))
-		if err != nil {
-			return
-		}
-		n += x
-	}
-	return
-}
-
-// Map returns a copy of the properties as a map.
-func (p *Properties) Map() map[string]string {
-	m := make(map[string]string)
-	for k, v := range p.m {
-		m[k] = v
-	}
-	return m
-}
-
-// FilterFunc returns a copy of the properties which includes the values which passed all filters.
-func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties {
-	pp := NewProperties()
-outer:
-	for k, v := range p.m {
-		for _, f := range filters {
-			if !f(k, v) {
-				continue outer
-			}
-			pp.Set(k, v)
-		}
-	}
-	return pp
-}
-
-// ----------------------------------------------------------------------------
-
-// Delete removes the key and its comments.
-func (p *Properties) Delete(key string) {
-	delete(p.m, key)
-	delete(p.c, key)
-	newKeys := []string{}
-	for _, k := range p.k {
-		if k != key {
-			newKeys = append(newKeys, k)
-		}
-	}
-	p.k = newKeys
-}
-
-// Merge merges properties, comments and keys from other *Properties into p
-func (p *Properties) Merge(other *Properties) {
-	for _, k := range other.k {
-		if _, ok := p.m[k]; !ok {
-			p.k = append(p.k, k)
-		}
-	}
-	for k, v := range other.m {
-		p.m[k] = v
-	}
-	for k, v := range other.c {
-		p.c[k] = v
-	}
-}
-
-// ----------------------------------------------------------------------------
-
-// check expands all values and returns an error if a circular reference or
-// a malformed expression was found.
-func (p *Properties) check() error {
-	for key, value := range p.m {
-		if _, err := p.expand(key, value); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (p *Properties) expand(key, input string) (string, error) {
-	// no pre/postfix -> nothing to expand
-	if p.Prefix == "" && p.Postfix == "" {
-		return input, nil
-	}
-
-	return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
-}
-
-// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
-// The function keeps track of the keys that were already expanded and stops if it
-// detects a circular reference or a malformed expression of the form '(prefix)key'.
-func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
-	if len(keys) > maxExpansionDepth {
-		return "", fmt.Errorf("expansion too deep")
-	}
-
-	for {
-		start := strings.Index(s, prefix)
-		if start == -1 {
-			return s, nil
-		}
-
-		keyStart := start + len(prefix)
-		keyLen := strings.Index(s[keyStart:], postfix)
-		if keyLen == -1 {
-			return "", fmt.Errorf("malformed expression")
-		}
-
-		end := keyStart + keyLen + len(postfix) - 1
-		key := s[keyStart : keyStart+keyLen]
-
-		// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
-
-		for _, k := range keys {
-			if key == k {
-				var b bytes.Buffer
-				b.WriteString("circular reference in:\n")
-				for _, k1 := range keys {
-					fmt.Fprintf(&b, "%s=%s\n", k1, values[k1])
-				}
-				return "", fmt.Errorf(b.String())
-			}
-		}
-
-		val, ok := values[key]
-		if !ok {
-			val = os.Getenv(key)
-		}
-		new_val, err := expand(val, append(keys, key), prefix, postfix, values)
-		if err != nil {
-			return "", err
-		}
-		s = s[:start] + new_val + s[end+1:]
-	}
-}
-
-// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
-func encode(s string, special string, enc Encoding) string {
-	switch enc {
-	case UTF8:
-		return encodeUtf8(s, special)
-	case ISO_8859_1:
-		return encodeIso(s, special)
-	default:
-		panic(fmt.Sprintf("unsupported encoding %v", enc))
-	}
-}
-
-func encodeUtf8(s string, special string) string {
-	v := ""
-	for pos := 0; pos < len(s); {
-		r, w := utf8.DecodeRuneInString(s[pos:])
-		pos += w
-		v += escape(r, special)
-	}
-	return v
-}
-
-func encodeIso(s string, special string) string {
-	var r rune
-	var w int
-	var v string
-	for pos := 0; pos < len(s); {
-		switch r, w = utf8.DecodeRuneInString(s[pos:]); {
-		case r < 1<<8: // single byte rune -> escape special chars only
-			v += escape(r, special)
-		case r < 1<<16: // two byte rune -> unicode literal
-			v += fmt.Sprintf("\\u%04x", r)
-		default: // more than two bytes per rune -> can't encode
-			v += "?"
-		}
-		pos += w
-	}
-	return v
-}
-
-func escape(r rune, special string) string {
-	switch r {
-	case '\f':
-		return "\\f"
-	case '\n':
-		return "\\n"
-	case '\r':
-		return "\\r"
-	case '\t':
-		return "\\t"
-	case '\\':
-		return "\\\\"
-	default:
-		if strings.ContainsRune(special, r) {
-			return "\\" + string(r)
-		}
-		return string(r)
-	}
-}
-
-func invalidKeyError(key string) error {
-	return fmt.Errorf("unknown property: %s", key)
-}
diff --git a/public-api/vendor/github.com/magiconair/properties/rangecheck.go b/public-api/vendor/github.com/magiconair/properties/rangecheck.go
deleted file mode 100644
index dbd60b36..00000000
--- a/public-api/vendor/github.com/magiconair/properties/rangecheck.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-2022 Frank Schroeder. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package properties
-
-import (
-	"fmt"
-	"math"
-)
-
-// make this a var to overwrite it in a test
-var is32Bit = ^uint(0) == math.MaxUint32
-
-// intRangeCheck checks if the value fits into the int type and
-// panics if it does not.
-func intRangeCheck(key string, v int64) int {
-	if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return int(v)
-}
-
-// uintRangeCheck checks if the value fits into the uint type and
-// panics if it does not.
-func uintRangeCheck(key string, v uint64) uint {
-	if is32Bit && v > math.MaxUint32 {
-		panic(fmt.Sprintf("Value %d for key %s out of range", v, key))
-	}
-	return uint(v)
-}
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/public-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
deleted file mode 100644
index c7582349..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ /dev/null
@@ -1,96 +0,0 @@
-## 1.5.0
-
-* New option `IgnoreUntaggedFields` to ignore decoding to any fields
-  without `mapstructure` (or the configured tag name) set [GH-277]
-* New option `ErrorUnset` which makes it an error if any fields
-  in a target struct are not set by the decoding process. [GH-225]
-* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
-* Decoding to slice from array no longer crashes [GH-265]
-* Decode nested struct pointers to map [GH-271]
-* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
-* Fix issue where fields with `,omitempty` would sometimes decode
-  into a map with an empty string key [GH-281]
-
-## 1.4.3
-
-* Fix cases where `json.Number` didn't decode properly [GH-261]
-
-## 1.4.2
-
-* Custom name matchers to support any sort of casing, formatting, etc. for
-  field names. [GH-250]
-* Fix possible panic in ComposeDecodeHookFunc [GH-251]
-
-## 1.4.1
-
-* Fix regression where `*time.Time` value would be set to empty and not be sent
-  to decode hooks properly [GH-232]
-
-## 1.4.0
-
-* A new decode hook type `DecodeHookFuncValue` has been added that has
-  access to the full values. [GH-183]
-* Squash is now supported with embedded fields that are struct pointers [GH-205]
-* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206]
-
-## 1.3.3
-
-* Decoding maps from maps creates a settable value for decode hooks [GH-203]
-
-## 1.3.2
-
-* Decode into interface type with a struct value is supported [GH-187]
-
-## 1.3.1
-
-* Squash should only squash embedded structs. [GH-194]
-
-## 1.3.0
-
-* Added `",omitempty"` support. This will ignore zero values in the source
-  structure when encoding. [GH-145]
-
-## 1.2.3
-
-* Fix duplicate entries in Keys list with pointer values. [GH-185]
-
-## 1.2.2
-
-* Do not add unsettable (unexported) values to the unused metadata key
-  or "remain" value. [GH-150]
-
-## 1.2.1
-
-* Go modules checksum mismatch fix
-
-## 1.2.0
-
-* Added support to capture unused values in a field using the `",remain"` value
-  in the mapstructure tag. There is an example to showcase usage.
-* Added `DecoderConfig` option to always squash embedded structs
-* `json.Number` can decode into `uint` types
-* Empty slices are preserved and not replaced with nil slices
-* Fix panic that can occur in when decoding a map into a nil slice of structs
-* Improved package documentation for godoc
-
-## 1.1.2
-
-* Fix error when decode hook decodes interface implementation into interface
-  type. [GH-140]
-
-## 1.1.1
-
-* Fix panic that can happen in `decodePtr`
-
-## 1.1.0
-
-* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133]
-* Support struct to struct decoding [GH-137]
-* If source map value is nil, then destination map value is nil (instead of empty)
-* If source slice value is nil, then destination slice value is nil (instead of empty)
-* If source pointer is nil, then destination pointer is set to nil (instead of
-  allocated zero value of type)
-
-## 1.0.0
-
-* Initial tagged stable release.
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/LICENSE b/public-api/vendor/github.com/mitchellh/mapstructure/LICENSE
deleted file mode 100644
index f9c841a5..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Mitchell Hashimoto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/README.md b/public-api/vendor/github.com/mitchellh/mapstructure/README.md
deleted file mode 100644
index 0018dc7d..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure)
-
-mapstructure is a Go library for decoding generic map values to structures
-and vice versa, while providing helpful error handling.
-
-This library is most useful when decoding values from some data stream (JSON,
-Gob, etc.) where you don't _quite_ know the structure of the underlying data
-until you read a part of it. You can therefore read a `map[string]interface{}`
-and use this library to decode it into the proper underlying native Go
-structure.
-
-## Installation
-
-Standard `go get`:
-
-```
-$ go get github.com/mitchellh/mapstructure
-```
-
-## Usage & Example
-
-For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).
-
-The `Decode` function has examples associated with it there.
-
-## But Why?!
-
-Go offers fantastic standard libraries for decoding formats such as JSON.
-The standard method is to have a struct pre-created, and populate that struct
-from the bytes of the encoded format. This is great, but the problem is if
-you have configuration or an encoding that changes slightly depending on
-specific fields. For example, consider this JSON:
-
-```json
-{
-  "type": "person",
-  "name": "Mitchell"
-}
-```
-
-Perhaps we can't populate a specific structure without first reading
-the "type" field from the JSON. We could always do two passes over the
-decoding of the JSON (reading the "type" first, and the rest later).
-However, it is much simpler to just decode this into a `map[string]interface{}`
-structure, read the "type" key, then use something like this library
-to decode it into the proper structure.
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/public-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
deleted file mode 100644
index 3a754ca7..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package mapstructure
-
-import (
-	"encoding"
-	"errors"
-	"fmt"
-	"net"
-	"reflect"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
-// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
-func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
-	// Create variables here so we can reference them with the reflect pkg
-	var f1 DecodeHookFuncType
-	var f2 DecodeHookFuncKind
-	var f3 DecodeHookFuncValue
-
-	// Fill in the variables into this interface and the rest is done
-	// automatically using the reflect package.
-	potential := []interface{}{f1, f2, f3}
-
-	v := reflect.ValueOf(h)
-	vt := v.Type()
-	for _, raw := range potential {
-		pt := reflect.ValueOf(raw).Type()
-		if vt.ConvertibleTo(pt) {
-			return v.Convert(pt).Interface()
-		}
-	}
-
-	return nil
-}
-
-// DecodeHookExec executes the given decode hook. This should be used
-// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
-// that took reflect.Kind instead of reflect.Type.
-func DecodeHookExec(
-	raw DecodeHookFunc,
-	from reflect.Value, to reflect.Value) (interface{}, error) {
-
-	switch f := typedDecodeHook(raw).(type) {
-	case DecodeHookFuncType:
-		return f(from.Type(), to.Type(), from.Interface())
-	case DecodeHookFuncKind:
-		return f(from.Kind(), to.Kind(), from.Interface())
-	case DecodeHookFuncValue:
-		return f(from, to)
-	default:
-		return nil, errors.New("invalid decode hook signature")
-	}
-}
-
-// ComposeDecodeHookFunc creates a single DecodeHookFunc that
-// automatically composes multiple DecodeHookFuncs.
-//
-// The composed funcs are called in order, with the result of the
-// previous transformation.
-func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		var err error
-		data := f.Interface()
-
-		newFrom := f
-		for _, f1 := range fs {
-			data, err = DecodeHookExec(f1, newFrom, t)
-			if err != nil {
-				return nil, err
-			}
-			newFrom = reflect.ValueOf(data)
-		}
-
-		return data, nil
-	}
-}
-
-// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
-// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
-func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	return func(a, b reflect.Value) (interface{}, error) {
-		var allErrs string
-		var out interface{}
-		var err error
-
-		for _, f := range ff {
-			out, err = DecodeHookExec(f, a, b)
-			if err != nil {
-				allErrs += err.Error() + "\n"
-				continue
-			}
-
-			return out, nil
-		}
-
-		return nil, errors.New(allErrs)
-	}
-}
-
-// StringToSliceHookFunc returns a DecodeHookFunc that converts
-// string to []string by splitting on the given sep.
-func StringToSliceHookFunc(sep string) DecodeHookFunc {
-	return func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		if f != reflect.String || t != reflect.Slice {
-			return data, nil
-		}
-
-		raw := data.(string)
-		if raw == "" {
-			return []string{}, nil
-		}
-
-		return strings.Split(raw, sep), nil
-	}
-}
-
-// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
-// strings to time.Duration.
-func StringToTimeDurationHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Duration(5)) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.ParseDuration(data.(string))
-	}
-}
-
-// StringToIPHookFunc returns a DecodeHookFunc that converts
-// strings to net.IP
-func StringToIPHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IP{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		ip := net.ParseIP(data.(string))
-		if ip == nil {
-			return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
-		}
-
-		return ip, nil
-	}
-}
-
-// StringToIPNetHookFunc returns a DecodeHookFunc that converts
-// strings to net.IPNet
-func StringToIPNetHookFunc() DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(net.IPNet{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		_, net, err := net.ParseCIDR(data.(string))
-		return net, err
-	}
-}
-
-// StringToTimeHookFunc returns a DecodeHookFunc that converts
-// strings to time.Time.
-func StringToTimeHookFunc(layout string) DecodeHookFunc {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		if t != reflect.TypeOf(time.Time{}) {
-			return data, nil
-		}
-
-		// Convert it by parsing
-		return time.Parse(layout, data.(string))
-	}
-}
-
-// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
-// the decoder.
-//
-// Note that this is significantly different from the WeaklyTypedInput option
-// of the DecoderConfig.
-func WeaklyTypedHook(
-	f reflect.Kind,
-	t reflect.Kind,
-	data interface{}) (interface{}, error) {
-	dataVal := reflect.ValueOf(data)
-	switch t {
-	case reflect.String:
-		switch f {
-		case reflect.Bool:
-			if dataVal.Bool() {
-				return "1", nil
-			}
-			return "0", nil
-		case reflect.Float32:
-			return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
-		case reflect.Int:
-			return strconv.FormatInt(dataVal.Int(), 10), nil
-		case reflect.Slice:
-			dataType := dataVal.Type()
-			elemKind := dataType.Elem().Kind()
-			if elemKind == reflect.Uint8 {
-				return string(dataVal.Interface().([]uint8)), nil
-			}
-		case reflect.Uint:
-			return strconv.FormatUint(dataVal.Uint(), 10), nil
-		}
-	}
-
-	return data, nil
-}
-
-func RecursiveStructToMapHookFunc() DecodeHookFunc {
-	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
-		if f.Kind() != reflect.Struct {
-			return f.Interface(), nil
-		}
-
-		var i interface{} = struct{}{}
-		if t.Type() != reflect.TypeOf(&i).Elem() {
-			return f.Interface(), nil
-		}
-
-		m := make(map[string]interface{})
-		t.Set(reflect.ValueOf(m))
-
-		return f.Interface(), nil
-	}
-}
-
-// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies
-// strings to the UnmarshalText function, when the target type
-// implements the encoding.TextUnmarshaler interface
-func TextUnmarshallerHookFunc() DecodeHookFuncType {
-	return func(
-		f reflect.Type,
-		t reflect.Type,
-		data interface{}) (interface{}, error) {
-		if f.Kind() != reflect.String {
-			return data, nil
-		}
-		result := reflect.New(t).Interface()
-		unmarshaller, ok := result.(encoding.TextUnmarshaler)
-		if !ok {
-			return data, nil
-		}
-		if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil {
-			return nil, err
-		}
-		return result, nil
-	}
-}
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/error.go b/public-api/vendor/github.com/mitchellh/mapstructure/error.go
deleted file mode 100644
index 47a99e5a..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/error.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package mapstructure
-
-import (
-	"errors"
-	"fmt"
-	"sort"
-	"strings"
-)
-
-// Error implements the error interface and can represents multiple
-// errors that occur in the course of a single decode.
-type Error struct {
-	Errors []string
-}
-
-func (e *Error) Error() string {
-	points := make([]string, len(e.Errors))
-	for i, err := range e.Errors {
-		points[i] = fmt.Sprintf("* %s", err)
-	}
-
-	sort.Strings(points)
-	return fmt.Sprintf(
-		"%d error(s) decoding:\n\n%s",
-		len(e.Errors), strings.Join(points, "\n"))
-}
-
-// WrappedErrors implements the errwrap.Wrapper interface to make this
-// return value more useful with the errwrap and go-multierror libraries.
-func (e *Error) WrappedErrors() []error {
-	if e == nil {
-		return nil
-	}
-
-	result := make([]error, len(e.Errors))
-	for i, e := range e.Errors {
-		result[i] = errors.New(e)
-	}
-
-	return result
-}
-
-func appendErrors(errors []string, err error) []string {
-	switch e := err.(type) {
-	case *Error:
-		return append(errors, e.Errors...)
-	default:
-		return append(errors, e.Error())
-	}
-}
diff --git a/public-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/public-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go
deleted file mode 100644
index 1efb22ac..00000000
--- a/public-api/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ /dev/null
@@ -1,1540 +0,0 @@
-// Package mapstructure exposes functionality to convert one arbitrary
-// Go type into another, typically to convert a map[string]interface{}
-// into a native Go structure.
-//
-// The Go structure can be arbitrarily complex, containing slices,
-// other structs, etc. and the decoder will properly decode nested
-// maps and so on into the proper structures in the native Go struct.
-// See the examples to see what the decoder is capable of.
-//
-// The simplest function to start with is Decode.
-//
-// Field Tags
-//
-// When decoding to a struct, mapstructure will use the field name by
-// default to perform the mapping. For example, if a struct has a field
-// "Username" then mapstructure will look for a key in the source value
-// of "username" (case insensitive).
-//
-//     type User struct {
-//         Username string
-//     }
-//
-// You can change the behavior of mapstructure by using struct tags.
-// The default struct tag that mapstructure looks for is "mapstructure"
-// but you can customize it using DecoderConfig.
-//
-// Renaming Fields
-//
-// To rename the key that mapstructure looks for, use the "mapstructure"
-// tag and set a value directly. For example, to change the "username" example
-// above to "user":
-//
-//     type User struct {
-//         Username string `mapstructure:"user"`
-//     }
-//
-// Embedded Structs and Squashing
-//
-// Embedded structs are treated as if they're another field with that name.
-// By default, the two structs below are equivalent when decoding with
-// mapstructure:
-//
-//     type Person struct {
-//         Name string
-//     }
-//
-//     type Friend struct {
-//         Person
-//     }
-//
-//     type Friend struct {
-//         Person Person
-//     }
-//
-// This would require an input that looks like below:
-//
-//     map[string]interface{}{
-//         "person": map[string]interface{}{"name": "alice"},
-//     }
-//
-// If your "person" value is NOT nested, then you can append ",squash" to
-// your tag value and mapstructure will treat it as if the embedded struct
-// were part of the struct directly. Example:
-//
-//     type Friend struct {
-//         Person `mapstructure:",squash"`
-//     }
-//
-// Now the following input would be accepted:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// When decoding from a struct to a map, the squash tag squashes the struct
-// fields into a single map. Using the example structs from above:
-//
-//     Friend{Person: Person{Name: "alice"}}
-//
-// Will be decoded into a map:
-//
-//     map[string]interface{}{
-//         "name": "alice",
-//     }
-//
-// DecoderConfig has a field that changes the behavior of mapstructure
-// to always squash embedded structs.
-//
-// Remainder Values
-//
-// If there are any unmapped keys in the source value, mapstructure by
-// default will silently ignore them. You can error by setting ErrorUnused
-// in DecoderConfig. If you're using Metadata you can also maintain a slice
-// of the unused keys.
-//
-// You can also use the ",remain" suffix on your tag to collect all unused
-// values in a map. The field with this tag MUST be a map type and should
-// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
-// See example below:
-//
-//     type Friend struct {
-//         Name  string
-//         Other map[string]interface{} `mapstructure:",remain"`
-//     }
-//
-// Given the input below, Other would be populated with the other
-// values that weren't used (everything but "name"):
-//
-//     map[string]interface{}{
-//         "name":    "bob",
-//         "address": "123 Maple St.",
-//     }
-//
-// Omit Empty Values
-//
-// When decoding from a struct to any other value, you may use the
-// ",omitempty" suffix on your tag to omit that value if it equates to
-// the zero value. The zero value of all types is specified in the Go
-// specification.
-//
-// For example, the zero type of a numeric type is zero ("0"). If the struct
-// field value is zero and a numeric type, the field is empty, and it won't
-// be encoded into the destination type.
-//
-//     type Source struct {
-//         Age int `mapstructure:",omitempty"`
-//     }
-//
-// Unexported fields
-//
-// Since unexported (private) struct fields cannot be set outside the package
-// where they are defined, the decoder will simply skip them.
-//
-// For this output type definition:
-//
-//     type Exported struct {
-//         private string // this unexported field will be skipped
-//         Public string
-//     }
-//
-// Using this map as input:
-//
-//     map[string]interface{}{
-//         "private": "I will be ignored",
-//         "Public":  "I made it through!",
-//     }
-//
-// The following struct will be decoded:
-//
-//     type Exported struct {
-//         private: "" // field is left with an empty string (zero value)
-//         Public: "I made it through!"
-//     }
-//
-// Other Configuration
-//
-// mapstructure is highly configurable. See the DecoderConfig struct
-// for other features and options that are supported.
-package mapstructure
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"reflect"
-	"sort"
-	"strconv"
-	"strings"
-)
-
-// DecodeHookFunc is the callback function that can be used for
-// data transformations. See "DecodeHook" in the DecoderConfig
-// struct.
-//
-// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or
-// DecodeHookFuncValue.
-// Values are a superset of Types (Values can return types), and Types are a
-// superset of Kinds (Types can return Kinds) and are generally a richer thing
-// to use, but Kinds are simpler if you only need those.
-//
-// The reason DecodeHookFunc is multi-typed is for backwards compatibility:
-// we started with Kinds and then realized Types were the better solution,
-// but have a promise to not break backwards compat so we now support
-// both.
-type DecodeHookFunc interface{}
-
-// DecodeHookFuncType is a DecodeHookFunc which has complete information about
-// the source and target types.
-type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
-
-// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
-// source and target types.
-type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
-
-// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
-// values.
-type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
-
-// DecoderConfig is the configuration that is used to create a new decoder
-// and allows customization of various aspects of decoding.
-type DecoderConfig struct {
-	// DecodeHook, if set, will be called before any decoding and any
-	// type conversion (if WeaklyTypedInput is on). This lets you modify
-	// the values before they're set down onto the resulting struct. The
-	// DecodeHook is called for every map and value in the input. This means
-	// that if a struct has embedded fields with squash tags the decode hook
-	// is called only once with all of the input data, not once for each
-	// embedded struct.
-	//
-	// If an error is returned, the entire decode will fail with that error.
-	DecodeHook DecodeHookFunc
-
-	// If ErrorUnused is true, then it is an error for there to exist
-	// keys in the original map that were unused in the decoding process
-	// (extra keys).
-	ErrorUnused bool
-
-	// If ErrorUnset is true, then it is an error for there to exist
-	// fields in the result that were not set in the decoding process
-	// (extra fields). This only applies to decoding to a struct. This
-	// will affect all nested structs as well.
-	ErrorUnset bool
-
-	// ZeroFields, if set to true, will zero fields before writing them.
-	// For example, a map will be emptied before decoded values are put in
-	// it. If this is false, a map will be merged.
-	ZeroFields bool
-
-	// If WeaklyTypedInput is true, the decoder will make the following
-	// "weak" conversions:
-	//
-	//   - bools to string (true = "1", false = "0")
-	//   - numbers to string (base 10)
-	//   - bools to int/uint (true = 1, false = 0)
-	//   - strings to int/uint (base implied by prefix)
-	//   - int to bool (true if value != 0)
-	//   - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
-	//     FALSE, false, False. Anything else is an error)
-	//   - empty array = empty map and vice versa
-	//   - negative numbers to overflowed uint values (base 10)
-	//   - slice of maps to a merged map
-	//   - single values are converted to slices if required. Each
-	//     element is weakly decoded. For example: "4" can become []int{4}
-	//     if the target type is an int slice.
-	//
-	WeaklyTypedInput bool
-
-	// Squash will squash embedded structs.  A squash tag may also be
-	// added to an individual struct field using a tag.  For example:
-	//
-	//  type Parent struct {
-	//      Child `mapstructure:",squash"`
-	//  }
-	Squash bool
-
-	// Metadata is the struct that will contain extra metadata about
-	// the decoding. If this is nil, then no metadata will be tracked.
-	Metadata *Metadata
-
-	// Result is a pointer to the struct that will contain the decoded
-	// value.
-	Result interface{}
-
-	// The tag name that mapstructure reads for field names. This
-	// defaults to "mapstructure"
-	TagName string
-
-	// IgnoreUntaggedFields ignores all struct fields without explicit
-	// TagName, comparable to `mapstructure:"-"` as default behaviour.
-	IgnoreUntaggedFields bool
-
-	// MatchName is the function used to match the map key to the struct
-	// field name or tag. Defaults to `strings.EqualFold`. This can be used
-	// to implement case-sensitive tag values, support snake casing, etc.
-	MatchName func(mapKey, fieldName string) bool
-}
-
-// A Decoder takes a raw interface value and turns it into structured
-// data, keeping track of rich error information along the way in case
-// anything goes wrong. Unlike the basic top-level Decode method, you can
-// more finely control how the Decoder behaves using the DecoderConfig
-// structure. The top-level Decode method is just a convenience that sets
-// up the most basic Decoder.
-type Decoder struct {
-	config *DecoderConfig
-}
-
-// Metadata contains information about decoding a structure that
-// is tedious or difficult to get otherwise.
-type Metadata struct {
-	// Keys are the keys of the structure which were successfully decoded
-	Keys []string
-
-	// Unused is a slice of keys that were found in the raw value but
-	// weren't decoded since there was no matching field in the result interface
-	Unused []string
-
-	// Unset is a slice of field names that were found in the result interface
-	// but weren't set in the decoding process since there was no matching value
-	// in the input
-	Unset []string
-}
-
-// Decode takes an input structure and uses reflection to translate it to
-// the output structure. output must be a pointer to a map or struct.
-func Decode(input interface{}, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata: nil,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecode is the same as Decode but is shorthand to enable
-// WeaklyTypedInput. See DecoderConfig for more info.
-func WeakDecode(input, output interface{}) error {
-	config := &DecoderConfig{
-		Metadata:         nil,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// DecodeMetadata is the same as Decode, but is shorthand to
-// enable metadata collection. See DecoderConfig for more info.
-func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata: metadata,
-		Result:   output,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// WeakDecodeMetadata is the same as Decode, but is shorthand to
-// enable both WeaklyTypedInput and metadata collection. See
-// DecoderConfig for more info.
-func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
-	config := &DecoderConfig{
-		Metadata:         metadata,
-		Result:           output,
-		WeaklyTypedInput: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(input)
-}
-
-// NewDecoder returns a new decoder for the given configuration. Once
-// a decoder has been returned, the same configuration must not be used
-// again.
-func NewDecoder(config *DecoderConfig) (*Decoder, error) {
-	val := reflect.ValueOf(config.Result)
-	if val.Kind() != reflect.Ptr {
-		return nil, errors.New("result must be a pointer")
-	}
-
-	val = val.Elem()
-	if !val.CanAddr() {
-		return nil, errors.New("result must be addressable (a pointer)")
-	}
-
-	if config.Metadata != nil {
-		if config.Metadata.Keys == nil {
-			config.Metadata.Keys = make([]string, 0)
-		}
-
-		if config.Metadata.Unused == nil {
-			config.Metadata.Unused = make([]string, 0)
-		}
-
-		if config.Metadata.Unset == nil {
-			config.Metadata.Unset = make([]string, 0)
-		}
-	}
-
-	if config.TagName == "" {
-		config.TagName = "mapstructure"
-	}
-
-	if config.MatchName == nil {
-		config.MatchName = strings.EqualFold
-	}
-
-	result := &Decoder{
-		config: config,
-	}
-
-	return result, nil
-}
-
-// Decode decodes the given raw interface to the target pointer specified
-// by the configuration.
-func (d *Decoder) Decode(input interface{}) error {
-	return d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
-}
-
-// Decodes an unknown data type into a specific reflection value.
-func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
-	var inputVal reflect.Value
-	if input != nil {
-		inputVal = reflect.ValueOf(input)
-
-		// We need to check here if input is a typed nil. Typed nils won't
-		// match the "input == nil" below so we check that here.
-		if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() {
-			input = nil
-		}
-	}
-
-	if input == nil {
-		// If the data is nil, then we don't set anything, unless ZeroFields is set
-		// to true.
-		if d.config.ZeroFields {
-			outVal.Set(reflect.Zero(outVal.Type()))
-
-			if d.config.Metadata != nil && name != "" {
-				d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-			}
-		}
-		return nil
-	}
-
-	if !inputVal.IsValid() {
-		// If the input value is invalid, then we just set the value
-		// to be the zero value.
-		outVal.Set(reflect.Zero(outVal.Type()))
-		if d.config.Metadata != nil && name != "" {
-			d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-		}
-		return nil
-	}
-
-	if d.config.DecodeHook != nil {
-		// We have a DecodeHook, so let's pre-process the input.
-		var err error
-		input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal)
-		if err != nil {
-			return fmt.Errorf("error decoding '%s': %s", name, err)
-		}
-	}
-
-	var err error
-	outputKind := getKind(outVal)
-	addMetaKey := true
-	switch outputKind {
-	case reflect.Bool:
-		err = d.decodeBool(name, input, outVal)
-	case reflect.Interface:
-		err = d.decodeBasic(name, input, outVal)
-	case reflect.String:
-		err = d.decodeString(name, input, outVal)
-	case reflect.Int:
-		err = d.decodeInt(name, input, outVal)
-	case reflect.Uint:
-		err = d.decodeUint(name, input, outVal)
-	case reflect.Float32:
-		err = d.decodeFloat(name, input, outVal)
-	case reflect.Struct:
-		err = d.decodeStruct(name, input, outVal)
-	case reflect.Map:
-		err = d.decodeMap(name, input, outVal)
-	case reflect.Ptr:
-		addMetaKey, err = d.decodePtr(name, input, outVal)
-	case reflect.Slice:
-		err = d.decodeSlice(name, input, outVal)
-	case reflect.Array:
-		err = d.decodeArray(name, input, outVal)
-	case reflect.Func:
-		err = d.decodeFunc(name, input, outVal)
-	default:
-		// If we reached this point then we weren't able to decode it
-		return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
-	}
-
-	// If we reached here, then we successfully decoded SOMETHING, so
-	// mark the key as used if we're tracking metainput.
-	if addMetaKey && d.config.Metadata != nil && name != "" {
-		d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
-	}
-
-	return err
-}
-
-// This decodes a basic type (bool, int, string, etc.) and sets the
-// value to "data" of that type.
-func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
-	if val.IsValid() && val.Elem().IsValid() {
-		elem := val.Elem()
-
-		// If we can't address this element, then its not writable. Instead,
-		// we make a copy of the value (which is a pointer and therefore
-		// writable), decode into that, and replace the whole value.
-		copied := false
-		if !elem.CanAddr() {
-			copied = true
-
-			// Make *T
-			copy := reflect.New(elem.Type())
-
-			// *T = elem
-			copy.Elem().Set(elem)
-
-			// Set elem so we decode into it
-			elem = copy
-		}
-
-		// Decode. If we have an error then return. We also return right
-		// away if we're not a copy because that means we decoded directly.
-		if err := d.decode(name, data, elem); err != nil || !copied {
-			return err
-		}
-
-		// If we're a copy, we need to set te final result
-		val.Set(elem.Elem())
-		return nil
-	}
-
-	dataVal := reflect.ValueOf(data)
-
-	// If the input data is a pointer, and the assigned type is the dereference
-	// of that exact pointer, then indirect it so that we can assign it.
-	// Example: *string to string
-	if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() {
-		dataVal = reflect.Indirect(dataVal)
-	}
-
-	if !dataVal.IsValid() {
-		dataVal = reflect.Zero(val.Type())
-	}
-
-	dataValType := dataVal.Type()
-	if !dataValType.AssignableTo(val.Type()) {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got '%s'",
-			name, val.Type(), dataValType)
-	}
-
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	converted := true
-	switch {
-	case dataKind == reflect.String:
-		val.SetString(dataVal.String())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetString("1")
-		} else {
-			val.SetString("0")
-		}
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatInt(dataVal.Int(), 10))
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
-	case dataKind == reflect.Slice && d.config.WeaklyTypedInput,
-		dataKind == reflect.Array && d.config.WeaklyTypedInput:
-		dataType := dataVal.Type()
-		elemKind := dataType.Elem().Kind()
-		switch elemKind {
-		case reflect.Uint8:
-			var uints []uint8
-			if dataKind == reflect.Array {
-				uints = make([]uint8, dataVal.Len(), dataVal.Len())
-				for i := range uints {
-					uints[i] = dataVal.Index(i).Interface().(uint8)
-				}
-			} else {
-				uints = dataVal.Interface().([]uint8)
-			}
-			val.SetString(string(uints))
-		default:
-			converted = false
-		}
-	default:
-		converted = false
-	}
-
-	if !converted {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetInt(dataVal.Int())
-	case dataKind == reflect.Uint:
-		val.SetInt(int64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetInt(int64(dataVal.Float()))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetInt(1)
-		} else {
-			val.SetInt(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseInt(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetInt(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Int64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetInt(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		i := dataVal.Int()
-		if i < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %d overflows uint",
-				name, i)
-		}
-		val.SetUint(uint64(i))
-	case dataKind == reflect.Uint:
-		val.SetUint(dataVal.Uint())
-	case dataKind == reflect.Float32:
-		f := dataVal.Float()
-		if f < 0 && !d.config.WeaklyTypedInput {
-			return fmt.Errorf("cannot parse '%s', %f overflows uint",
-				name, f)
-		}
-		val.SetUint(uint64(f))
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetUint(1)
-		} else {
-			val.SetUint(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		i, err := strconv.ParseUint(str, 0, val.Type().Bits())
-		if err == nil {
-			val.SetUint(i)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := strconv.ParseUint(string(jn), 0, 64)
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetUint(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-
-	switch {
-	case dataKind == reflect.Bool:
-		val.SetBool(dataVal.Bool())
-	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Int() != 0)
-	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Uint() != 0)
-	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
-		val.SetBool(dataVal.Float() != 0)
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		b, err := strconv.ParseBool(dataVal.String())
-		if err == nil {
-			val.SetBool(b)
-		} else if dataVal.String() == "" {
-			val.SetBool(false)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
-		}
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataKind := getKind(dataVal)
-	dataType := dataVal.Type()
-
-	switch {
-	case dataKind == reflect.Int:
-		val.SetFloat(float64(dataVal.Int()))
-	case dataKind == reflect.Uint:
-		val.SetFloat(float64(dataVal.Uint()))
-	case dataKind == reflect.Float32:
-		val.SetFloat(dataVal.Float())
-	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
-		if dataVal.Bool() {
-			val.SetFloat(1)
-		} else {
-			val.SetFloat(0)
-		}
-	case dataKind == reflect.String && d.config.WeaklyTypedInput:
-		str := dataVal.String()
-		if str == "" {
-			str = "0"
-		}
-
-		f, err := strconv.ParseFloat(str, val.Type().Bits())
-		if err == nil {
-			val.SetFloat(f)
-		} else {
-			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
-		}
-	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
-		jn := data.(json.Number)
-		i, err := jn.Float64()
-		if err != nil {
-			return fmt.Errorf(
-				"error decoding json.Number into %s: %s", name, err)
-		}
-		val.SetFloat(i)
-	default:
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// By default we overwrite keys in the current map
-	valMap := val
-
-	// If the map is nil or we're purposely zeroing fields, make a new map
-	if valMap.IsNil() || d.config.ZeroFields {
-		// Make a new map to hold our result
-		mapType := reflect.MapOf(valKeyType, valElemType)
-		valMap = reflect.MakeMap(mapType)
-	}
-
-	// Check input type and based on the input type jump to the proper func
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	switch dataVal.Kind() {
-	case reflect.Map:
-		return d.decodeMapFromMap(name, dataVal, val, valMap)
-
-	case reflect.Struct:
-		return d.decodeMapFromStruct(name, dataVal, val, valMap)
-
-	case reflect.Array, reflect.Slice:
-		if d.config.WeaklyTypedInput {
-			return d.decodeMapFromSlice(name, dataVal, val, valMap)
-		}
-
-		fallthrough
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	// Special case for BC reasons (covered by tests)
-	if dataVal.Len() == 0 {
-		val.Set(valMap)
-		return nil
-	}
-
-	for i := 0; i < dataVal.Len(); i++ {
-		err := d.decode(
-			name+"["+strconv.Itoa(i)+"]",
-			dataVal.Index(i).Interface(), val)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	valType := val.Type()
-	valKeyType := valType.Key()
-	valElemType := valType.Elem()
-
-	// Accumulate errors
-	errors := make([]string, 0)
-
-	// If the input data is empty, then we just match what the input data is.
-	if dataVal.Len() == 0 {
-		if dataVal.IsNil() {
-			if !val.IsNil() {
-				val.Set(dataVal)
-			}
-		} else {
-			// Set to empty allocated value
-			val.Set(valMap)
-		}
-
-		return nil
-	}
-
-	for _, k := range dataVal.MapKeys() {
-		fieldName := name + "[" + k.String() + "]"
-
-		// First decode the key into the proper type
-		currentKey := reflect.Indirect(reflect.New(valKeyType))
-		if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		// Next decode the data into the proper type
-		v := dataVal.MapIndex(k).Interface()
-		currentVal := reflect.Indirect(reflect.New(valElemType))
-		if err := d.decode(fieldName, v, currentVal); err != nil {
-			errors = appendErrors(errors, err)
-			continue
-		}
-
-		valMap.SetMapIndex(currentKey, currentVal)
-	}
-
-	// Set the built up map to the value
-	val.Set(valMap)
-
-	// If we had errors, return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
-	typ := dataVal.Type()
-	for i := 0; i < typ.NumField(); i++ {
-		// Get the StructField first since this is a cheap operation. If the
-		// field is unexported, then ignore it.
-		f := typ.Field(i)
-		if f.PkgPath != "" {
-			continue
-		}
-
-		// Next get the actual value of this field and verify it is assignable
-		// to the map value.
-		v := dataVal.Field(i)
-		if !v.Type().AssignableTo(valMap.Type().Elem()) {
-			return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem())
-		}
-
-		tagValue := f.Tag.Get(d.config.TagName)
-		keyName := f.Name
-
-		if tagValue == "" && d.config.IgnoreUntaggedFields {
-			continue
-		}
-
-		// If Squash is set in the config, we squash the field down.
-		squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
-
-		v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
-
-		// Determine the name of the key in the map
-		if index := strings.Index(tagValue, ","); index != -1 {
-			if tagValue[:index] == "-" {
-				continue
-			}
-			// If "omitempty" is specified in the tag, it ignores empty values.
-			if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) {
-				continue
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
-			if squash {
-				// When squashing, the embedded type can be a pointer to a struct.
-				if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
-					v = v.Elem()
-				}
-
-				// The final type must be a struct
-				if v.Kind() != reflect.Struct {
-					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
-				}
-			}
-			if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
-				keyName = keyNameTagValue
-			}
-		} else if len(tagValue) > 0 {
-			if tagValue == "-" {
-				continue
-			}
-			keyName = tagValue
-		}
-
-		switch v.Kind() {
-		// this is an embedded struct, so handle it differently
-		case reflect.Struct:
-			x := reflect.New(v.Type())
-			x.Elem().Set(v)
-
-			vType := valMap.Type()
-			vKeyType := vType.Key()
-			vElemType := vType.Elem()
-			mType := reflect.MapOf(vKeyType, vElemType)
-			vMap := reflect.MakeMap(mType)
-
-			// Creating a pointer to a map so that other methods can completely
-			// overwrite the map if need be (looking at you decodeMapFromMap). The
-			// indirection allows the underlying map to be settable (CanSet() == true)
-			// where as reflect.MakeMap returns an unsettable map.
-			addrVal := reflect.New(vMap.Type())
-			reflect.Indirect(addrVal).Set(vMap)
-
-			err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal))
-			if err != nil {
-				return err
-			}
-
-			// the underlying map may have been completely overwritten so pull
-			// it indirectly out of the enclosing value.
-			vMap = reflect.Indirect(addrVal)
-
-			if squash {
-				for _, k := range vMap.MapKeys() {
-					valMap.SetMapIndex(k, vMap.MapIndex(k))
-				}
-			} else {
-				valMap.SetMapIndex(reflect.ValueOf(keyName), vMap)
-			}
-
-		default:
-			valMap.SetMapIndex(reflect.ValueOf(keyName), v)
-		}
-	}
-
-	if val.CanAddr() {
-		val.Set(valMap)
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
-	// If the input data is nil, then we want to just set the output
-	// pointer to be nil as well.
-	isNil := data == nil
-	if !isNil {
-		switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
-		case reflect.Chan,
-			reflect.Func,
-			reflect.Interface,
-			reflect.Map,
-			reflect.Ptr,
-			reflect.Slice:
-			isNil = v.IsNil()
-		}
-	}
-	if isNil {
-		if !val.IsNil() && val.CanSet() {
-			nilValue := reflect.New(val.Type()).Elem()
-			val.Set(nilValue)
-		}
-
-		return true, nil
-	}
-
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	valType := val.Type()
-	valElemType := valType.Elem()
-	if val.CanSet() {
-		realVal := val
-		if realVal.IsNil() || d.config.ZeroFields {
-			realVal = reflect.New(valElemType)
-		}
-
-		if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
-			return false, err
-		}
-
-		val.Set(realVal)
-	} else {
-		if err := d.decode(name, data, reflect.Indirect(val)); err != nil {
-			return false, err
-		}
-	}
-	return false, nil
-}
-
-func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
-	// Create an element of the concrete (non pointer) type and decode
-	// into that. Then set the value of the pointer to this type.
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	if val.Type() != dataVal.Type() {
-		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
-			name, val.Type(), dataVal.Type(), data)
-	}
-	val.Set(dataVal)
-	return nil
-}
-
-func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	sliceType := reflect.SliceOf(valElemType)
-
-	// If we have a non array/slice type then we first attempt to convert.
-	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-		if d.config.WeaklyTypedInput {
-			switch {
-			// Slice and array we use the normal logic
-			case dataValKind == reflect.Slice, dataValKind == reflect.Array:
-				break
-
-			// Empty maps turn into empty slices
-			case dataValKind == reflect.Map:
-				if dataVal.Len() == 0 {
-					val.Set(reflect.MakeSlice(sliceType, 0, 0))
-					return nil
-				}
-				// Create slice of maps of other sizes
-				return d.decodeSlice(name, []interface{}{data}, val)
-
-			case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
-				return d.decodeSlice(name, []byte(dataVal.String()), val)
-
-			// All other types we try to convert to the slice type
-			// and "lift" it into it. i.e. a string becomes a string slice.
-			default:
-				// Just re-try this function with data as a slice.
-				return d.decodeSlice(name, []interface{}{data}, val)
-			}
-		}
-
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
-	}
-
-	// If the input value is nil, then don't allocate since empty != nil
-	if dataValKind != reflect.Array && dataVal.IsNil() {
-		return nil
-	}
-
-	valSlice := val
-	if valSlice.IsNil() || d.config.ZeroFields {
-		// Make a new slice to hold our result, same size as the original data.
-		valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		for valSlice.Len() <= i {
-			valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
-		}
-		currentField := valSlice.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the slice we built up
-	val.Set(valSlice)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	dataValKind := dataVal.Kind()
-	valType := val.Type()
-	valElemType := valType.Elem()
-	arrayType := reflect.ArrayOf(valType.Len(), valElemType)
-
-	valArray := val
-
-	if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields {
-		// Check input type
-		if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-			if d.config.WeaklyTypedInput {
-				switch {
-				// Empty maps turn into empty arrays
-				case dataValKind == reflect.Map:
-					if dataVal.Len() == 0 {
-						val.Set(reflect.Zero(arrayType))
-						return nil
-					}
-
-				// All other types we try to convert to the array type
-				// and "lift" it into it. i.e. a string becomes a string array.
-				default:
-					// Just re-try this function with data as a slice.
-					return d.decodeArray(name, []interface{}{data}, val)
-				}
-			}
-
-			return fmt.Errorf(
-				"'%s': source data must be an array or slice, got %s", name, dataValKind)
-
-		}
-		if dataVal.Len() > arrayType.Len() {
-			return fmt.Errorf(
-				"'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len())
-
-		}
-
-		// Make a new array to hold our result, same size as the original data.
-		valArray = reflect.New(arrayType).Elem()
-	}
-
-	// Accumulate any errors
-	errors := make([]string, 0)
-
-	for i := 0; i < dataVal.Len(); i++ {
-		currentData := dataVal.Index(i).Interface()
-		currentField := valArray.Index(i)
-
-		fieldName := name + "[" + strconv.Itoa(i) + "]"
-		if err := d.decode(fieldName, currentData, currentField); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// Finally, set the value to the array we built up
-	val.Set(valArray)
-
-	// If there were errors, we return those
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	return nil
-}
-
-func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-
-	// If the type of the value to write to and the data match directly,
-	// then we just set it directly instead of recursing into the structure.
-	if dataVal.Type() == val.Type() {
-		val.Set(dataVal)
-		return nil
-	}
-
-	dataValKind := dataVal.Kind()
-	switch dataValKind {
-	case reflect.Map:
-		return d.decodeStructFromMap(name, dataVal, val)
-
-	case reflect.Struct:
-		// Not the most efficient way to do this but we can optimize later if
-		// we want to. To convert from struct to struct we go to map first
-		// as an intermediary.
-
-		// Make a new map to hold our result
-		mapType := reflect.TypeOf((map[string]interface{})(nil))
-		mval := reflect.MakeMap(mapType)
-
-		// Creating a pointer to a map so that other methods can completely
-		// overwrite the map if need be (looking at you decodeMapFromMap). The
-		// indirection allows the underlying map to be settable (CanSet() == true)
-		// where as reflect.MakeMap returns an unsettable map.
-		addrVal := reflect.New(mval.Type())
-
-		reflect.Indirect(addrVal).Set(mval)
-		if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil {
-			return err
-		}
-
-		result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val)
-		return result
-
-	default:
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-}
-
-func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
-	dataValType := dataVal.Type()
-	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
-		return fmt.Errorf(
-			"'%s' needs a map with string keys, has '%s' keys",
-			name, dataValType.Key().Kind())
-	}
-
-	dataValKeys := make(map[reflect.Value]struct{})
-	dataValKeysUnused := make(map[interface{}]struct{})
-	for _, dataValKey := range dataVal.MapKeys() {
-		dataValKeys[dataValKey] = struct{}{}
-		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
-	}
-
-	targetValKeysUnused := make(map[interface{}]struct{})
-	errors := make([]string, 0)
-
-	// This slice will keep track of all the structs we'll be decoding.
-	// There can be more than one struct if there are embedded structs
-	// that are squashed.
-	structs := make([]reflect.Value, 1, 5)
-	structs[0] = val
-
-	// Compile the list of all the fields that we're going to be decoding
-	// from all the structs.
-	type field struct {
-		field reflect.StructField
-		val   reflect.Value
-	}
-
-	// remainField is set to a valid field set with the "remain" tag if
-	// we are keeping track of remaining values.
-	var remainField *field
-
-	fields := []field{}
-	for len(structs) > 0 {
-		structVal := structs[0]
-		structs = structs[1:]
-
-		structType := structVal.Type()
-
-		for i := 0; i < structType.NumField(); i++ {
-			fieldType := structType.Field(i)
-			fieldVal := structVal.Field(i)
-			if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct {
-				// Handle embedded struct pointers as embedded structs.
-				fieldVal = fieldVal.Elem()
-			}
-
-			// If "squash" is specified in the tag, we squash the field down.
-			squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous
-			remain := false
-
-			// We always parse the tags cause we're looking for other tags too
-			tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
-			for _, tag := range tagParts[1:] {
-				if tag == "squash" {
-					squash = true
-					break
-				}
-
-				if tag == "remain" {
-					remain = true
-					break
-				}
-			}
-
-			if squash {
-				if fieldVal.Kind() != reflect.Struct {
-					errors = appendErrors(errors,
-						fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
-				} else {
-					structs = append(structs, fieldVal)
-				}
-				continue
-			}
-
-			// Build our field
-			if remain {
-				remainField = &field{fieldType, fieldVal}
-			} else {
-				// Normal struct field, store it away
-				fields = append(fields, field{fieldType, fieldVal})
-			}
-		}
-	}
-
-	// for fieldType, field := range fields {
-	for _, f := range fields {
-		field, fieldValue := f.field, f.val
-		fieldName := field.Name
-
-		tagValue := field.Tag.Get(d.config.TagName)
-		tagValue = strings.SplitN(tagValue, ",", 2)[0]
-		if tagValue != "" {
-			fieldName = tagValue
-		}
-
-		rawMapKey := reflect.ValueOf(fieldName)
-		rawMapVal := dataVal.MapIndex(rawMapKey)
-		if !rawMapVal.IsValid() {
-			// Do a slower search by iterating over each key and
-			// doing case-insensitive search.
-			for dataValKey := range dataValKeys {
-				mK, ok := dataValKey.Interface().(string)
-				if !ok {
-					// Not a string key
-					continue
-				}
-
-				if d.config.MatchName(mK, fieldName) {
-					rawMapKey = dataValKey
-					rawMapVal = dataVal.MapIndex(dataValKey)
-					break
-				}
-			}
-
-			if !rawMapVal.IsValid() {
-				// There was no matching key in the map for the value in
-				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
-				continue
-			}
-		}
-
-		if !fieldValue.IsValid() {
-			// This should never happen
-			panic("field is not valid")
-		}
-
-		// If we can't set the field, then it is unexported or something,
-		// and we just continue onwards.
-		if !fieldValue.CanSet() {
-			continue
-		}
-
-		// Delete the key we're using from the unused map so we stop tracking
-		delete(dataValKeysUnused, rawMapKey.Interface())
-
-		// If the name is empty string, then we're at the root, and we
-		// don't dot-join the fields.
-		if name != "" {
-			fieldName = name + "." + fieldName
-		}
-
-		if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
-			errors = appendErrors(errors, err)
-		}
-	}
-
-	// If we have a "remain"-tagged field and we have unused keys then
-	// we put the unused keys directly into the remain field.
-	if remainField != nil && len(dataValKeysUnused) > 0 {
-		// Build a map of only the unused values
-		remain := map[interface{}]interface{}{}
-		for key := range dataValKeysUnused {
-			remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
-		}
-
-		// Decode it as-if we were just decoding this map onto our map.
-		if err := d.decodeMap(name, remain, remainField.val); err != nil {
-			errors = appendErrors(errors, err)
-		}
-
-		// Set the map to nil so we have none so that the next check will
-		// not error (ErrorUnused)
-		dataValKeysUnused = nil
-	}
-
-	if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
-		keys := make([]string, 0, len(dataValKeysUnused))
-		for rawKey := range dataValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
-		keys := make([]string, 0, len(targetValKeysUnused))
-		for rawKey := range targetValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
-	if len(errors) > 0 {
-		return &Error{errors}
-	}
-
-	// Add the unused keys to the list of unused keys if we're tracking metadata
-	if d.config.Metadata != nil {
-		for rawKey := range dataValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
-		}
-		for rawKey := range targetValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
-		}
-	}
-
-	return nil
-}
-
-func isEmptyValue(v reflect.Value) bool {
-	switch getKind(v) {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	}
-	return false
-}
-
-func getKind(val reflect.Value) reflect.Kind {
-	kind := val.Kind()
-
-	switch {
-	case kind >= reflect.Int && kind <= reflect.Int64:
-		return reflect.Int
-	case kind >= reflect.Uint && kind <= reflect.Uint64:
-		return reflect.Uint
-	case kind >= reflect.Float32 && kind <= reflect.Float64:
-		return reflect.Float32
-	default:
-		return kind
-	}
-}
-
-func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
-	for i := 0; i < typ.NumField(); i++ {
-		f := typ.Field(i)
-		if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
-			return true
-		}
-		if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
-			return true
-		}
-	}
-	return false
-}
-
-func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
-	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
-		return v
-	}
-	deref := v.Elem()
-	derefT := deref.Type()
-	if isStructTypeConvertibleToMap(derefT, true, tagName) {
-		return deref
-	}
-	return v
-}
diff --git a/public-api/vendor/github.com/prometheus/procfs/.golangci.yml b/public-api/vendor/github.com/prometheus/procfs/.golangci.yml
index 126df9e6..3c3bf910 100644
--- a/public-api/vendor/github.com/prometheus/procfs/.golangci.yml
+++ b/public-api/vendor/github.com/prometheus/procfs/.golangci.yml
@@ -1,22 +1,45 @@
----
+version: "2"
 linters:
   enable:
-  - errcheck
-  - godot
-  - gosimple
-  - govet
-  - ineffassign
-  - misspell
-  - revive
-  - staticcheck
-  - testifylint
-  - unused
-
-linter-settings:
-  godot:
-    capital: true
-    exclude:
-    # Ignore "See: URL"
-    - 'See:'
-  misspell:
-    locale: US
+    - forbidigo
+    - godot
+    - misspell
+    - revive
+    - testifylint
+  settings:
+    forbidigo:
+      forbid:
+        - pattern: ^fmt\.Print.*$
+          msg: Do not commit print statements.
+    godot:
+      exclude:
+        # Ignore "See: URL".
+        - 'See:'
+      capital: true
+    misspell:
+      locale: US
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
+formatters:
+  enable:
+    - gofmt
+    - goimports
+  settings:
+    goimports:
+      local-prefixes:
+        - github.com/prometheus/procfs
+  exclusions:
+    generated: lax
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/public-api/vendor/github.com/prometheus/procfs/Makefile.common b/public-api/vendor/github.com/prometheus/procfs/Makefile.common
index 16172923..4de21512 100644
--- a/public-api/vendor/github.com/prometheus/procfs/Makefile.common
+++ b/public-api/vendor/github.com/prometheus/procfs/Makefile.common
@@ -61,7 +61,8 @@ PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_
 SKIP_GOLANGCI_LINT :=
 GOLANGCI_LINT :=
 GOLANGCI_LINT_OPTS ?=
-GOLANGCI_LINT_VERSION ?= v1.59.0
+GOLANGCI_LINT_VERSION ?= v2.1.5
+GOLANGCI_FMT_OPTS ?=
 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
 # windows isn't included here because of the path separator being different.
 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
@@ -156,9 +157,13 @@ $(GOTEST_DIR):
 	@mkdir -p $@
 
 .PHONY: common-format
-common-format:
+common-format: $(GOLANGCI_LINT)
 	@echo ">> formatting code"
 	$(GO) fmt $(pkgs)
+ifdef GOLANGCI_LINT
+	@echo ">> formatting code with golangci-lint"
+	$(GOLANGCI_LINT) fmt $(GOLANGCI_FMT_OPTS)
+endif
 
 .PHONY: common-vet
 common-vet:
@@ -248,8 +253,8 @@ $(PROMU):
 	cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu
 	rm -r $(PROMU_TMP)
 
-.PHONY: proto
-proto:
+.PHONY: common-proto
+common-proto:
 	@echo ">> generating code from proto files"
 	@./scripts/genproto.sh
 
@@ -275,3 +280,9 @@ $(1)_precheck:
 		exit 1; \
 	fi
 endef
+
+govulncheck: install-govulncheck
+	govulncheck ./...
+
+install-govulncheck:
+	command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest
diff --git a/public-api/vendor/github.com/prometheus/procfs/README.md b/public-api/vendor/github.com/prometheus/procfs/README.md
index 1224816c..0718239c 100644
--- a/public-api/vendor/github.com/prometheus/procfs/README.md
+++ b/public-api/vendor/github.com/prometheus/procfs/README.md
@@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`.
 The procfs library includes a set of test fixtures which include many example files from
 the `/proc` and `/sys` filesystems.  These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
 which is extracted automatically during testing.  To add/update the test fixtures, first
-ensure the `fixtures` directory is up to date by removing the existing directory and then
-extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
+ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then
+extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`.
 
 ```bash
 rm -rf testdata/fixtures
 make test
 ```
 
-Next, make the required changes to the extracted files in the `fixtures` directory.  When
+Next, make the required changes to the extracted files in the `testdata/fixtures` directory.  When
 the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file
 based on the updated `fixtures` directory.  And finally, verify the changes using
 `git diff testdata/fixtures.ttar`.
diff --git a/public-api/vendor/github.com/prometheus/procfs/arp.go b/public-api/vendor/github.com/prometheus/procfs/arp.go
index cdcc8a7c..2e533441 100644
--- a/public-api/vendor/github.com/prometheus/procfs/arp.go
+++ b/public-api/vendor/github.com/prometheus/procfs/arp.go
@@ -23,9 +23,9 @@ import (
 
 // Learned from include/uapi/linux/if_arp.h.
 const (
-	// completed entry (ha valid).
+	// Completed entry (ha valid).
 	ATFComplete = 0x02
-	// permanent entry.
+	// Permanent entry.
 	ATFPermanent = 0x04
 	// Publish entry.
 	ATFPublish = 0x08
diff --git a/public-api/vendor/github.com/prometheus/procfs/fs.go b/public-api/vendor/github.com/prometheus/procfs/fs.go
index 4980c875..9bdaccc7 100644
--- a/public-api/vendor/github.com/prometheus/procfs/fs.go
+++ b/public-api/vendor/github.com/prometheus/procfs/fs.go
@@ -24,8 +24,14 @@ type FS struct {
 	isReal bool
 }
 
-// DefaultMountPoint is the common mount point of the proc filesystem.
-const DefaultMountPoint = fs.DefaultProcMountPoint
+const (
+	// DefaultMountPoint is the common mount point of the proc filesystem.
+	DefaultMountPoint = fs.DefaultProcMountPoint
+
+	// SectorSize represents the size of a sector in bytes.
+	// It is specific to Linux block I/O operations.
+	SectorSize = 512
+)
 
 // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
 // It will error if the mount point directory can't be read or is a file.
diff --git a/public-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/public-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
index 134767d6..1b5bdbdf 100644
--- a/public-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
+++ b/public-api/vendor/github.com/prometheus/procfs/fs_statfs_notype.go
@@ -17,7 +17,7 @@
 package procfs
 
 // isRealProc returns true on architectures that don't have a Type argument
-// in their Statfs_t struct
-func isRealProc(mountPoint string) (bool, error) {
+// in their Statfs_t struct.
+func isRealProc(_ string) (bool, error) {
 	return true, nil
 }
diff --git a/public-api/vendor/github.com/prometheus/procfs/fscache.go b/public-api/vendor/github.com/prometheus/procfs/fscache.go
index cf2e3eaa..7db86330 100644
--- a/public-api/vendor/github.com/prometheus/procfs/fscache.go
+++ b/public-api/vendor/github.com/prometheus/procfs/fscache.go
@@ -162,7 +162,7 @@ type Fscacheinfo struct {
 	ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
 	// Number of release reqs ignored due to in-progress store
 	ReleaseRequestsIgnoredDueToInProgressStore uint64
-	// Number of page stores cancelled due to release req
+	// Number of page stores canceled due to release req
 	PageStoresCancelledByReleaseRequests uint64
 	VmscanWaiting                        uint64
 	// Number of times async ops added to pending queues
@@ -171,11 +171,11 @@ type Fscacheinfo struct {
 	OpsRunning uint64
 	// Number of times async ops queued for processing
 	OpsEnqueued uint64
-	// Number of async ops cancelled
+	// Number of async ops canceled
 	OpsCancelled uint64
 	// Number of async ops rejected due to object lookup/create failure
 	OpsRejected uint64
-	// Number of async ops initialised
+	// Number of async ops initialized
 	OpsInitialised uint64
 	// Number of async ops queued for deferred release
 	OpsDeferred uint64
diff --git a/public-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/public-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
index 3c18c761..3a43e839 100644
--- a/public-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
+++ b/public-api/vendor/github.com/prometheus/procfs/internal/fs/fs.go
@@ -28,6 +28,9 @@ const (
 
 	// DefaultConfigfsMountPoint is the common mount point of the configfs.
 	DefaultConfigfsMountPoint = "/sys/kernel/config"
+
+	// DefaultSelinuxMountPoint is the common mount point of the selinuxfs.
+	DefaultSelinuxMountPoint = "/sys/fs/selinux"
 )
 
 // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
diff --git a/public-api/vendor/github.com/prometheus/procfs/internal/util/parse.go b/public-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
index 14272dc7..5a7d2df0 100644
--- a/public-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
+++ b/public-api/vendor/github.com/prometheus/procfs/internal/util/parse.go
@@ -14,6 +14,7 @@
 package util
 
 import (
+	"errors"
 	"os"
 	"strconv"
 	"strings"
@@ -110,3 +111,16 @@ func ParseBool(b string) *bool {
 	}
 	return &truth
 }
+
+// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX.
+func ReadHexFromFile(path string) (uint64, error) {
+	data, err := os.ReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	hexString := strings.TrimSpace(string(data))
+	if !strings.HasPrefix(hexString, "0x") {
+		return 0, errors.New("invalid format: hex string does not start with '0x'")
+	}
+	return strconv.ParseUint(hexString[2:], 16, 64)
+}
diff --git a/public-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/public-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
index 1ab875ce..d5404a6d 100644
--- a/public-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
+++ b/public-api/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go
@@ -20,6 +20,8 @@ package util
 import (
 	"bytes"
 	"os"
+	"strconv"
+	"strings"
 	"syscall"
 )
 
@@ -48,3 +50,21 @@ func SysReadFile(file string) (string, error) {
 
 	return string(bytes.TrimSpace(b[:n])), nil
 }
+
+// SysReadUintFromFile reads a file using SysReadFile and attempts to parse a uint64 from it.
+func SysReadUintFromFile(path string) (uint64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
+}
+
+// SysReadIntFromFile reads a file using SysReadFile and attempts to parse a int64 from it.
+func SysReadIntFromFile(path string) (int64, error) {
+	data, err := SysReadFile(path)
+	if err != nil {
+		return 0, err
+	}
+	return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
+}
diff --git a/public-api/vendor/github.com/prometheus/procfs/mdstat.go b/public-api/vendor/github.com/prometheus/procfs/mdstat.go
index 67a9d2b4..1fd4381b 100644
--- a/public-api/vendor/github.com/prometheus/procfs/mdstat.go
+++ b/public-api/vendor/github.com/prometheus/procfs/mdstat.go
@@ -123,13 +123,16 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
 		finish := float64(0)
 		pct := float64(0)
 		recovering := strings.Contains(lines[syncLineIdx], "recovery")
+		reshaping := strings.Contains(lines[syncLineIdx], "reshape")
 		resyncing := strings.Contains(lines[syncLineIdx], "resync")
 		checking := strings.Contains(lines[syncLineIdx], "check")
 
 		// Append recovery and resyncing state info.
-		if recovering || resyncing || checking {
+		if recovering || resyncing || checking || reshaping {
 			if recovering {
 				state = "recovering"
+			} else if reshaping {
+				state = "reshaping"
 			} else if checking {
 				state = "checking"
 			} else {
diff --git a/public-api/vendor/github.com/prometheus/procfs/meminfo.go b/public-api/vendor/github.com/prometheus/procfs/meminfo.go
index 4b2c4050..937e1f96 100644
--- a/public-api/vendor/github.com/prometheus/procfs/meminfo.go
+++ b/public-api/vendor/github.com/prometheus/procfs/meminfo.go
@@ -66,6 +66,10 @@ type Meminfo struct {
 	// Memory which has been evicted from RAM, and is temporarily
 	// on the disk
 	SwapFree *uint64
+	// Memory consumed by the zswap backend (compressed size)
+	Zswap *uint64
+	// Amount of anonymous memory stored in zswap (original size)
+	Zswapped *uint64
 	// Memory which is waiting to get written back to the disk
 	Dirty *uint64
 	// Memory which is actively being written back to the disk
@@ -85,6 +89,8 @@ type Meminfo struct {
 	// amount of memory dedicated to the lowest level of page
 	// tables.
 	PageTables *uint64
+	// secondary page tables.
+	SecPageTables *uint64
 	// NFS pages sent to the server, but not yet committed to
 	// stable storage
 	NFSUnstable *uint64
@@ -129,15 +135,18 @@ type Meminfo struct {
 	Percpu            *uint64
 	HardwareCorrupted *uint64
 	AnonHugePages     *uint64
+	FileHugePages     *uint64
 	ShmemHugePages    *uint64
 	ShmemPmdMapped    *uint64
 	CmaTotal          *uint64
 	CmaFree           *uint64
+	Unaccepted        *uint64
 	HugePagesTotal    *uint64
 	HugePagesFree     *uint64
 	HugePagesRsvd     *uint64
 	HugePagesSurp     *uint64
 	Hugepagesize      *uint64
+	Hugetlb           *uint64
 	DirectMap4k       *uint64
 	DirectMap2M       *uint64
 	DirectMap1G       *uint64
@@ -161,6 +170,8 @@ type Meminfo struct {
 	MlockedBytes           *uint64
 	SwapTotalBytes         *uint64
 	SwapFreeBytes          *uint64
+	ZswapBytes             *uint64
+	ZswappedBytes          *uint64
 	DirtyBytes             *uint64
 	WritebackBytes         *uint64
 	AnonPagesBytes         *uint64
@@ -171,6 +182,7 @@ type Meminfo struct {
 	SUnreclaimBytes        *uint64
 	KernelStackBytes       *uint64
 	PageTablesBytes        *uint64
+	SecPageTablesBytes     *uint64
 	NFSUnstableBytes       *uint64
 	BounceBytes            *uint64
 	WritebackTmpBytes      *uint64
@@ -182,11 +194,14 @@ type Meminfo struct {
 	PercpuBytes            *uint64
 	HardwareCorruptedBytes *uint64
 	AnonHugePagesBytes     *uint64
+	FileHugePagesBytes     *uint64
 	ShmemHugePagesBytes    *uint64
 	ShmemPmdMappedBytes    *uint64
 	CmaTotalBytes          *uint64
 	CmaFreeBytes           *uint64
+	UnacceptedBytes        *uint64
 	HugepagesizeBytes      *uint64
+	HugetlbBytes           *uint64
 	DirectMap4kBytes       *uint64
 	DirectMap2MBytes       *uint64
 	DirectMap1GBytes       *uint64
@@ -287,6 +302,12 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "SwapFree:":
 			m.SwapFree = &val
 			m.SwapFreeBytes = &valBytes
+		case "Zswap:":
+			m.Zswap = &val
+			m.ZswapBytes = &valBytes
+		case "Zswapped:":
+			m.Zswapped = &val
+			m.ZswapBytes = &valBytes
 		case "Dirty:":
 			m.Dirty = &val
 			m.DirtyBytes = &valBytes
@@ -317,6 +338,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "PageTables:":
 			m.PageTables = &val
 			m.PageTablesBytes = &valBytes
+		case "SecPageTables:":
+			m.SecPageTables = &val
+			m.SecPageTablesBytes = &valBytes
 		case "NFS_Unstable:":
 			m.NFSUnstable = &val
 			m.NFSUnstableBytes = &valBytes
@@ -350,6 +374,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "AnonHugePages:":
 			m.AnonHugePages = &val
 			m.AnonHugePagesBytes = &valBytes
+		case "FileHugePages:":
+			m.FileHugePages = &val
+			m.FileHugePagesBytes = &valBytes
 		case "ShmemHugePages:":
 			m.ShmemHugePages = &val
 			m.ShmemHugePagesBytes = &valBytes
@@ -362,6 +389,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "CmaFree:":
 			m.CmaFree = &val
 			m.CmaFreeBytes = &valBytes
+		case "Unaccepted:":
+			m.Unaccepted = &val
+			m.UnacceptedBytes = &valBytes
 		case "HugePages_Total:":
 			m.HugePagesTotal = &val
 		case "HugePages_Free:":
@@ -373,6 +403,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
 		case "Hugepagesize:":
 			m.Hugepagesize = &val
 			m.HugepagesizeBytes = &valBytes
+		case "Hugetlb:":
+			m.Hugetlb = &val
+			m.HugetlbBytes = &valBytes
 		case "DirectMap4k:":
 			m.DirectMap4k = &val
 			m.DirectMap4kBytes = &valBytes
diff --git a/public-api/vendor/github.com/prometheus/procfs/mountstats.go b/public-api/vendor/github.com/prometheus/procfs/mountstats.go
index 75a3b6c8..50caa732 100644
--- a/public-api/vendor/github.com/prometheus/procfs/mountstats.go
+++ b/public-api/vendor/github.com/prometheus/procfs/mountstats.go
@@ -45,11 +45,11 @@ const (
 	fieldTransport11TCPLen = 13
 	fieldTransport11UDPLen = 10
 
-	// kernel version >= 4.14 MaxLen
+	// Kernel version >= 4.14 MaxLen
 	// See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
 	fieldTransport11RDMAMaxLen = 28
 
-	// kernel version <= 4.2 MinLen
+	// Kernel version <= 4.2 MinLen
 	// See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
 	fieldTransport11RDMAMinLen = 20
 )
@@ -601,11 +601,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	switch statVersion {
 	case statVersion10:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport10TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport10UDPLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if len(ss) != expectedLength {
@@ -613,13 +614,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 		}
 	case statVersion11:
 		var expectedLength int
-		if protocol == "tcp" {
+		switch protocol {
+		case "tcp":
 			expectedLength = fieldTransport11TCPLen
-		} else if protocol == "udp" {
+		case "udp":
 			expectedLength = fieldTransport11UDPLen
-		} else if protocol == "rdma" {
+		case "rdma":
 			expectedLength = fieldTransport11RDMAMinLen
-		} else {
+		default:
 			return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
 		}
 		if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) ||
@@ -655,11 +657,12 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	// For the udp RPC transport there is no connection count, connect idle time,
 	// or idle time (fields #3, #4, and #5); all other fields are the same. So
 	// we set them to 0 here.
-	if protocol == "udp" {
+	switch protocol {
+	case "udp":
 		ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
-	} else if protocol == "tcp" {
+	case "tcp":
 		ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...)
-	} else if protocol == "rdma" {
+	case "rdma":
 		ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...)
 	}
 
diff --git a/public-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/public-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
new file mode 100644
index 00000000..f50b38e3
--- /dev/null
+++ b/public-api/vendor/github.com/prometheus/procfs/net_dev_snmp6.go
@@ -0,0 +1,96 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc//net/dev_snmp6/.
+// The outer map's keys are interface names and the inner map's keys are stat names.
+//
+// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type.
+type NetDevSNMP6 map[string]map[string]uint64
+
+// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/
+// directory.
+func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6"))
+}
+
+// Returns kernel/system statistics read from interface files within the /proc//net/dev_snmp6/
+// directory.
+func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) {
+	return newNetDevSNMP6(p.path("net/dev_snmp6"))
+}
+
+// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory.
+func newNetDevSNMP6(dir string) (NetDevSNMP6, error) {
+	netDevSNMP6 := make(NetDevSNMP6)
+
+	// The net/dev_snmp6 folders contain one file per interface
+	ifaceFiles, err := os.ReadDir(dir)
+	if err != nil {
+		// On systems with IPv6 disabled, this directory won't exist.
+		// Do nothing.
+		if errors.Is(err, os.ErrNotExist) {
+			return netDevSNMP6, err
+		}
+		return netDevSNMP6, err
+	}
+
+	for _, iFaceFile := range ifaceFiles {
+		f, err := os.Open(dir + "/" + iFaceFile.Name())
+		if err != nil {
+			return netDevSNMP6, err
+		}
+		defer f.Close()
+
+		netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f)
+		if err != nil {
+			return netDevSNMP6, err
+		}
+	}
+
+	return netDevSNMP6, nil
+}
+
+func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) {
+	m := make(map[string]uint64)
+
+	scanner := bufio.NewScanner(r)
+	for scanner.Scan() {
+		stat := strings.Fields(scanner.Text())
+		if len(stat) < 2 {
+			continue
+		}
+		key, val := stat[0], stat[1]
+
+		// Expect stat name to contain "6" or be "ifIndex"
+		if strings.Contains(key, "6") || key == "ifIndex" {
+			v, err := strconv.ParseUint(val, 10, 64)
+			if err != nil {
+				return m, err
+			}
+
+			m[key] = v
+		}
+	}
+	return m, scanner.Err()
+}
diff --git a/public-api/vendor/github.com/prometheus/procfs/net_ip_socket.go b/public-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
index b70f1fc7..19e3378f 100644
--- a/public-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
+++ b/public-api/vendor/github.com/prometheus/procfs/net_ip_socket.go
@@ -25,7 +25,7 @@ import (
 )
 
 const (
-	// readLimit is used by io.LimitReader while reading the content of the
+	// Maximum size limit used by io.LimitReader while reading the content of the
 	// /proc/net/udp{,6} files. The number of lines inside such a file is dynamic
 	// as each line represents a single used socket.
 	// In theory, the number of available sockets is 65535 (2^16 - 1) per IP.
@@ -50,12 +50,12 @@ type (
 		// UsedSockets shows the total number of parsed lines representing the
 		// number of used sockets.
 		UsedSockets uint64
-		// Drops shows the total number of dropped packets of all UPD sockets.
+		// Drops shows the total number of dropped packets of all UDP sockets.
 		Drops *uint64
 	}
 
-	// netIPSocketLine represents the fields parsed from a single line
-	// in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped.
+	// A single line parser for fields from /proc/net/{t,u}dp{,6}.
+	// Fields which are not used by IPSocket are skipped.
 	// Drops is non-nil for udp{,6}, but nil for tcp{,6}.
 	// For the proc file format details, see https://linux.die.net/man/5/proc.
 	netIPSocketLine struct {
diff --git a/public-api/vendor/github.com/prometheus/procfs/net_protocols.go b/public-api/vendor/github.com/prometheus/procfs/net_protocols.go
index b6c77b70..8d4b1ac0 100644
--- a/public-api/vendor/github.com/prometheus/procfs/net_protocols.go
+++ b/public-api/vendor/github.com/prometheus/procfs/net_protocols.go
@@ -115,22 +115,24 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro
 	if err != nil {
 		return nil, err
 	}
-	if fields[4] == enabled {
+	switch fields[4] {
+	case enabled:
 		line.Pressure = 1
-	} else if fields[4] == disabled {
+	case disabled:
 		line.Pressure = 0
-	} else {
+	default:
 		line.Pressure = -1
 	}
 	line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64)
 	if err != nil {
 		return nil, err
 	}
-	if fields[6] == enabled {
+	switch fields[6] {
+	case enabled:
 		line.Slab = true
-	} else if fields[6] == disabled {
+	case disabled:
 		line.Slab = false
-	} else {
+	default:
 		return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name)
 	}
 	line.ModuleName = fields[7]
@@ -168,11 +170,12 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro
 	}
 
 	for i := 0; i < len(capabilities); i++ {
-		if capabilities[i] == "y" {
+		switch capabilities[i] {
+		case "y":
 			*capabilityFields[i] = true
-		} else if capabilities[i] == "n" {
+		case "n":
 			*capabilityFields[i] = false
-		} else {
+		default:
 			return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i)
 		}
 	}
diff --git a/public-api/vendor/github.com/prometheus/procfs/net_tcp.go b/public-api/vendor/github.com/prometheus/procfs/net_tcp.go
index 52776295..0396d720 100644
--- a/public-api/vendor/github.com/prometheus/procfs/net_tcp.go
+++ b/public-api/vendor/github.com/prometheus/procfs/net_tcp.go
@@ -25,24 +25,28 @@ type (
 
 // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCP() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp6"))
 }
 
 // NetTCPSummary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6Summary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp6"))
 }
diff --git a/public-api/vendor/github.com/prometheus/procfs/net_unix.go b/public-api/vendor/github.com/prometheus/procfs/net_unix.go
index d868cebd..d7e0cacb 100644
--- a/public-api/vendor/github.com/prometheus/procfs/net_unix.go
+++ b/public-api/vendor/github.com/prometheus/procfs/net_unix.go
@@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
 	return &nu, nil
 }
 
-func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) {
+func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) {
 	fields := strings.Fields(line)
 
 	l := len(fields)
-	if l < min {
-		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l)
+	if l < minFields {
+		return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l)
 	}
 
 	// Field offsets are as follows:
@@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine,
 	}
 
 	// Path field is optional.
-	if l > min {
+	if l > minFields {
 		// Path occurs at either index 6 or 7 depending on whether inode is
 		// already present.
 		pathIdx := 7
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc.go b/public-api/vendor/github.com/prometheus/procfs/proc.go
index 14279636..368187fa 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc.go
@@ -37,9 +37,9 @@ type Proc struct {
 type Procs []Proc
 
 var (
-	ErrFileParse  = errors.New("Error Parsing File")
-	ErrFileRead   = errors.New("Error Reading File")
-	ErrMountPoint = errors.New("Error Accessing Mount point")
+	ErrFileParse  = errors.New("error parsing file")
+	ErrFileRead   = errors.New("error reading file")
+	ErrMountPoint = errors.New("error accessing mount point")
 )
 
 func (p Procs) Len() int           { return len(p) }
@@ -79,7 +79,7 @@ func (fs FS) Self() (Proc, error) {
 	if err != nil {
 		return Proc{}, err
 	}
-	pid, err := strconv.Atoi(strings.Replace(p, string(fs.proc), "", -1))
+	pid, err := strconv.Atoi(strings.ReplaceAll(p, string(fs.proc), ""))
 	if err != nil {
 		return Proc{}, err
 	}
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_cgroup.go b/public-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
index daeed7f5..4a64347c 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_cgroup.go
@@ -24,7 +24,7 @@ import (
 )
 
 // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a
-// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource
+// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource
 // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies
 // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in
 // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_io.go b/public-api/vendor/github.com/prometheus/procfs/proc_io.go
index 776f3497..d15b66dd 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_io.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_io.go
@@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) {
 
 	ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
 		"read_bytes: %d\nwrite_bytes: %d\n" +
-		"cancelled_write_bytes: %d\n"
+		"cancelled_write_bytes: %d\n" //nolint:misspell
 
 	_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
 		&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_netstat.go b/public-api/vendor/github.com/prometheus/procfs/proc_netstat.go
index 8e3ff4d7..4248c171 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_netstat.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_netstat.go
@@ -209,232 +209,232 @@ func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
 			case "TcpExt":
 				switch key {
 				case "SyncookiesSent":
-					procNetstat.TcpExt.SyncookiesSent = &value
+					procNetstat.SyncookiesSent = &value
 				case "SyncookiesRecv":
-					procNetstat.TcpExt.SyncookiesRecv = &value
+					procNetstat.SyncookiesRecv = &value
 				case "SyncookiesFailed":
-					procNetstat.TcpExt.SyncookiesFailed = &value
+					procNetstat.SyncookiesFailed = &value
 				case "EmbryonicRsts":
-					procNetstat.TcpExt.EmbryonicRsts = &value
+					procNetstat.EmbryonicRsts = &value
 				case "PruneCalled":
-					procNetstat.TcpExt.PruneCalled = &value
+					procNetstat.PruneCalled = &value
 				case "RcvPruned":
-					procNetstat.TcpExt.RcvPruned = &value
+					procNetstat.RcvPruned = &value
 				case "OfoPruned":
-					procNetstat.TcpExt.OfoPruned = &value
+					procNetstat.OfoPruned = &value
 				case "OutOfWindowIcmps":
-					procNetstat.TcpExt.OutOfWindowIcmps = &value
+					procNetstat.OutOfWindowIcmps = &value
 				case "LockDroppedIcmps":
-					procNetstat.TcpExt.LockDroppedIcmps = &value
+					procNetstat.LockDroppedIcmps = &value
 				case "ArpFilter":
-					procNetstat.TcpExt.ArpFilter = &value
+					procNetstat.ArpFilter = &value
 				case "TW":
-					procNetstat.TcpExt.TW = &value
+					procNetstat.TW = &value
 				case "TWRecycled":
-					procNetstat.TcpExt.TWRecycled = &value
+					procNetstat.TWRecycled = &value
 				case "TWKilled":
-					procNetstat.TcpExt.TWKilled = &value
+					procNetstat.TWKilled = &value
 				case "PAWSActive":
-					procNetstat.TcpExt.PAWSActive = &value
+					procNetstat.PAWSActive = &value
 				case "PAWSEstab":
-					procNetstat.TcpExt.PAWSEstab = &value
+					procNetstat.PAWSEstab = &value
 				case "DelayedACKs":
-					procNetstat.TcpExt.DelayedACKs = &value
+					procNetstat.DelayedACKs = &value
 				case "DelayedACKLocked":
-					procNetstat.TcpExt.DelayedACKLocked = &value
+					procNetstat.DelayedACKLocked = &value
 				case "DelayedACKLost":
-					procNetstat.TcpExt.DelayedACKLost = &value
+					procNetstat.DelayedACKLost = &value
 				case "ListenOverflows":
-					procNetstat.TcpExt.ListenOverflows = &value
+					procNetstat.ListenOverflows = &value
 				case "ListenDrops":
-					procNetstat.TcpExt.ListenDrops = &value
+					procNetstat.ListenDrops = &value
 				case "TCPHPHits":
-					procNetstat.TcpExt.TCPHPHits = &value
+					procNetstat.TCPHPHits = &value
 				case "TCPPureAcks":
-					procNetstat.TcpExt.TCPPureAcks = &value
+					procNetstat.TCPPureAcks = &value
 				case "TCPHPAcks":
-					procNetstat.TcpExt.TCPHPAcks = &value
+					procNetstat.TCPHPAcks = &value
 				case "TCPRenoRecovery":
-					procNetstat.TcpExt.TCPRenoRecovery = &value
+					procNetstat.TCPRenoRecovery = &value
 				case "TCPSackRecovery":
-					procNetstat.TcpExt.TCPSackRecovery = &value
+					procNetstat.TCPSackRecovery = &value
 				case "TCPSACKReneging":
-					procNetstat.TcpExt.TCPSACKReneging = &value
+					procNetstat.TCPSACKReneging = &value
 				case "TCPSACKReorder":
-					procNetstat.TcpExt.TCPSACKReorder = &value
+					procNetstat.TCPSACKReorder = &value
 				case "TCPRenoReorder":
-					procNetstat.TcpExt.TCPRenoReorder = &value
+					procNetstat.TCPRenoReorder = &value
 				case "TCPTSReorder":
-					procNetstat.TcpExt.TCPTSReorder = &value
+					procNetstat.TCPTSReorder = &value
 				case "TCPFullUndo":
-					procNetstat.TcpExt.TCPFullUndo = &value
+					procNetstat.TCPFullUndo = &value
 				case "TCPPartialUndo":
-					procNetstat.TcpExt.TCPPartialUndo = &value
+					procNetstat.TCPPartialUndo = &value
 				case "TCPDSACKUndo":
-					procNetstat.TcpExt.TCPDSACKUndo = &value
+					procNetstat.TCPDSACKUndo = &value
 				case "TCPLossUndo":
-					procNetstat.TcpExt.TCPLossUndo = &value
+					procNetstat.TCPLossUndo = &value
 				case "TCPLostRetransmit":
-					procNetstat.TcpExt.TCPLostRetransmit = &value
+					procNetstat.TCPLostRetransmit = &value
 				case "TCPRenoFailures":
-					procNetstat.TcpExt.TCPRenoFailures = &value
+					procNetstat.TCPRenoFailures = &value
 				case "TCPSackFailures":
-					procNetstat.TcpExt.TCPSackFailures = &value
+					procNetstat.TCPSackFailures = &value
 				case "TCPLossFailures":
-					procNetstat.TcpExt.TCPLossFailures = &value
+					procNetstat.TCPLossFailures = &value
 				case "TCPFastRetrans":
-					procNetstat.TcpExt.TCPFastRetrans = &value
+					procNetstat.TCPFastRetrans = &value
 				case "TCPSlowStartRetrans":
-					procNetstat.TcpExt.TCPSlowStartRetrans = &value
+					procNetstat.TCPSlowStartRetrans = &value
 				case "TCPTimeouts":
-					procNetstat.TcpExt.TCPTimeouts = &value
+					procNetstat.TCPTimeouts = &value
 				case "TCPLossProbes":
-					procNetstat.TcpExt.TCPLossProbes = &value
+					procNetstat.TCPLossProbes = &value
 				case "TCPLossProbeRecovery":
-					procNetstat.TcpExt.TCPLossProbeRecovery = &value
+					procNetstat.TCPLossProbeRecovery = &value
 				case "TCPRenoRecoveryFail":
-					procNetstat.TcpExt.TCPRenoRecoveryFail = &value
+					procNetstat.TCPRenoRecoveryFail = &value
 				case "TCPSackRecoveryFail":
-					procNetstat.TcpExt.TCPSackRecoveryFail = &value
+					procNetstat.TCPSackRecoveryFail = &value
 				case "TCPRcvCollapsed":
-					procNetstat.TcpExt.TCPRcvCollapsed = &value
+					procNetstat.TCPRcvCollapsed = &value
 				case "TCPDSACKOldSent":
-					procNetstat.TcpExt.TCPDSACKOldSent = &value
+					procNetstat.TCPDSACKOldSent = &value
 				case "TCPDSACKOfoSent":
-					procNetstat.TcpExt.TCPDSACKOfoSent = &value
+					procNetstat.TCPDSACKOfoSent = &value
 				case "TCPDSACKRecv":
-					procNetstat.TcpExt.TCPDSACKRecv = &value
+					procNetstat.TCPDSACKRecv = &value
 				case "TCPDSACKOfoRecv":
-					procNetstat.TcpExt.TCPDSACKOfoRecv = &value
+					procNetstat.TCPDSACKOfoRecv = &value
 				case "TCPAbortOnData":
-					procNetstat.TcpExt.TCPAbortOnData = &value
+					procNetstat.TCPAbortOnData = &value
 				case "TCPAbortOnClose":
-					procNetstat.TcpExt.TCPAbortOnClose = &value
+					procNetstat.TCPAbortOnClose = &value
 				case "TCPDeferAcceptDrop":
-					procNetstat.TcpExt.TCPDeferAcceptDrop = &value
+					procNetstat.TCPDeferAcceptDrop = &value
 				case "IPReversePathFilter":
-					procNetstat.TcpExt.IPReversePathFilter = &value
+					procNetstat.IPReversePathFilter = &value
 				case "TCPTimeWaitOverflow":
-					procNetstat.TcpExt.TCPTimeWaitOverflow = &value
+					procNetstat.TCPTimeWaitOverflow = &value
 				case "TCPReqQFullDoCookies":
-					procNetstat.TcpExt.TCPReqQFullDoCookies = &value
+					procNetstat.TCPReqQFullDoCookies = &value
 				case "TCPReqQFullDrop":
-					procNetstat.TcpExt.TCPReqQFullDrop = &value
+					procNetstat.TCPReqQFullDrop = &value
 				case "TCPRetransFail":
-					procNetstat.TcpExt.TCPRetransFail = &value
+					procNetstat.TCPRetransFail = &value
 				case "TCPRcvCoalesce":
-					procNetstat.TcpExt.TCPRcvCoalesce = &value
+					procNetstat.TCPRcvCoalesce = &value
 				case "TCPRcvQDrop":
-					procNetstat.TcpExt.TCPRcvQDrop = &value
+					procNetstat.TCPRcvQDrop = &value
 				case "TCPOFOQueue":
-					procNetstat.TcpExt.TCPOFOQueue = &value
+					procNetstat.TCPOFOQueue = &value
 				case "TCPOFODrop":
-					procNetstat.TcpExt.TCPOFODrop = &value
+					procNetstat.TCPOFODrop = &value
 				case "TCPOFOMerge":
-					procNetstat.TcpExt.TCPOFOMerge = &value
+					procNetstat.TCPOFOMerge = &value
 				case "TCPChallengeACK":
-					procNetstat.TcpExt.TCPChallengeACK = &value
+					procNetstat.TCPChallengeACK = &value
 				case "TCPSYNChallenge":
-					procNetstat.TcpExt.TCPSYNChallenge = &value
+					procNetstat.TCPSYNChallenge = &value
 				case "TCPFastOpenActive":
-					procNetstat.TcpExt.TCPFastOpenActive = &value
+					procNetstat.TCPFastOpenActive = &value
 				case "TCPFastOpenActiveFail":
-					procNetstat.TcpExt.TCPFastOpenActiveFail = &value
+					procNetstat.TCPFastOpenActiveFail = &value
 				case "TCPFastOpenPassive":
-					procNetstat.TcpExt.TCPFastOpenPassive = &value
+					procNetstat.TCPFastOpenPassive = &value
 				case "TCPFastOpenPassiveFail":
-					procNetstat.TcpExt.TCPFastOpenPassiveFail = &value
+					procNetstat.TCPFastOpenPassiveFail = &value
 				case "TCPFastOpenListenOverflow":
-					procNetstat.TcpExt.TCPFastOpenListenOverflow = &value
+					procNetstat.TCPFastOpenListenOverflow = &value
 				case "TCPFastOpenCookieReqd":
-					procNetstat.TcpExt.TCPFastOpenCookieReqd = &value
+					procNetstat.TCPFastOpenCookieReqd = &value
 				case "TCPFastOpenBlackhole":
-					procNetstat.TcpExt.TCPFastOpenBlackhole = &value
+					procNetstat.TCPFastOpenBlackhole = &value
 				case "TCPSpuriousRtxHostQueues":
-					procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value
+					procNetstat.TCPSpuriousRtxHostQueues = &value
 				case "BusyPollRxPackets":
-					procNetstat.TcpExt.BusyPollRxPackets = &value
+					procNetstat.BusyPollRxPackets = &value
 				case "TCPAutoCorking":
-					procNetstat.TcpExt.TCPAutoCorking = &value
+					procNetstat.TCPAutoCorking = &value
 				case "TCPFromZeroWindowAdv":
-					procNetstat.TcpExt.TCPFromZeroWindowAdv = &value
+					procNetstat.TCPFromZeroWindowAdv = &value
 				case "TCPToZeroWindowAdv":
-					procNetstat.TcpExt.TCPToZeroWindowAdv = &value
+					procNetstat.TCPToZeroWindowAdv = &value
 				case "TCPWantZeroWindowAdv":
-					procNetstat.TcpExt.TCPWantZeroWindowAdv = &value
+					procNetstat.TCPWantZeroWindowAdv = &value
 				case "TCPSynRetrans":
-					procNetstat.TcpExt.TCPSynRetrans = &value
+					procNetstat.TCPSynRetrans = &value
 				case "TCPOrigDataSent":
-					procNetstat.TcpExt.TCPOrigDataSent = &value
+					procNetstat.TCPOrigDataSent = &value
 				case "TCPHystartTrainDetect":
-					procNetstat.TcpExt.TCPHystartTrainDetect = &value
+					procNetstat.TCPHystartTrainDetect = &value
 				case "TCPHystartTrainCwnd":
-					procNetstat.TcpExt.TCPHystartTrainCwnd = &value
+					procNetstat.TCPHystartTrainCwnd = &value
 				case "TCPHystartDelayDetect":
-					procNetstat.TcpExt.TCPHystartDelayDetect = &value
+					procNetstat.TCPHystartDelayDetect = &value
 				case "TCPHystartDelayCwnd":
-					procNetstat.TcpExt.TCPHystartDelayCwnd = &value
+					procNetstat.TCPHystartDelayCwnd = &value
 				case "TCPACKSkippedSynRecv":
-					procNetstat.TcpExt.TCPACKSkippedSynRecv = &value
+					procNetstat.TCPACKSkippedSynRecv = &value
 				case "TCPACKSkippedPAWS":
-					procNetstat.TcpExt.TCPACKSkippedPAWS = &value
+					procNetstat.TCPACKSkippedPAWS = &value
 				case "TCPACKSkippedSeq":
-					procNetstat.TcpExt.TCPACKSkippedSeq = &value
+					procNetstat.TCPACKSkippedSeq = &value
 				case "TCPACKSkippedFinWait2":
-					procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value
+					procNetstat.TCPACKSkippedFinWait2 = &value
 				case "TCPACKSkippedTimeWait":
-					procNetstat.TcpExt.TCPACKSkippedTimeWait = &value
+					procNetstat.TCPACKSkippedTimeWait = &value
 				case "TCPACKSkippedChallenge":
-					procNetstat.TcpExt.TCPACKSkippedChallenge = &value
+					procNetstat.TCPACKSkippedChallenge = &value
 				case "TCPWinProbe":
-					procNetstat.TcpExt.TCPWinProbe = &value
+					procNetstat.TCPWinProbe = &value
 				case "TCPKeepAlive":
-					procNetstat.TcpExt.TCPKeepAlive = &value
+					procNetstat.TCPKeepAlive = &value
 				case "TCPMTUPFail":
-					procNetstat.TcpExt.TCPMTUPFail = &value
+					procNetstat.TCPMTUPFail = &value
 				case "TCPMTUPSuccess":
-					procNetstat.TcpExt.TCPMTUPSuccess = &value
+					procNetstat.TCPMTUPSuccess = &value
 				case "TCPWqueueTooBig":
-					procNetstat.TcpExt.TCPWqueueTooBig = &value
+					procNetstat.TCPWqueueTooBig = &value
 				}
 			case "IpExt":
 				switch key {
 				case "InNoRoutes":
-					procNetstat.IpExt.InNoRoutes = &value
+					procNetstat.InNoRoutes = &value
 				case "InTruncatedPkts":
-					procNetstat.IpExt.InTruncatedPkts = &value
+					procNetstat.InTruncatedPkts = &value
 				case "InMcastPkts":
-					procNetstat.IpExt.InMcastPkts = &value
+					procNetstat.InMcastPkts = &value
 				case "OutMcastPkts":
-					procNetstat.IpExt.OutMcastPkts = &value
+					procNetstat.OutMcastPkts = &value
 				case "InBcastPkts":
-					procNetstat.IpExt.InBcastPkts = &value
+					procNetstat.InBcastPkts = &value
 				case "OutBcastPkts":
-					procNetstat.IpExt.OutBcastPkts = &value
+					procNetstat.OutBcastPkts = &value
 				case "InOctets":
-					procNetstat.IpExt.InOctets = &value
+					procNetstat.InOctets = &value
 				case "OutOctets":
-					procNetstat.IpExt.OutOctets = &value
+					procNetstat.OutOctets = &value
 				case "InMcastOctets":
-					procNetstat.IpExt.InMcastOctets = &value
+					procNetstat.InMcastOctets = &value
 				case "OutMcastOctets":
-					procNetstat.IpExt.OutMcastOctets = &value
+					procNetstat.OutMcastOctets = &value
 				case "InBcastOctets":
-					procNetstat.IpExt.InBcastOctets = &value
+					procNetstat.InBcastOctets = &value
 				case "OutBcastOctets":
-					procNetstat.IpExt.OutBcastOctets = &value
+					procNetstat.OutBcastOctets = &value
 				case "InCsumErrors":
-					procNetstat.IpExt.InCsumErrors = &value
+					procNetstat.InCsumErrors = &value
 				case "InNoECTPkts":
-					procNetstat.IpExt.InNoECTPkts = &value
+					procNetstat.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procNetstat.IpExt.InECT1Pkts = &value
+					procNetstat.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procNetstat.IpExt.InECT0Pkts = &value
+					procNetstat.InECT0Pkts = &value
 				case "InCEPkts":
-					procNetstat.IpExt.InCEPkts = &value
+					procNetstat.InCEPkts = &value
 				case "ReasmOverlaps":
-					procNetstat.IpExt.ReasmOverlaps = &value
+					procNetstat.ReasmOverlaps = &value
 				}
 			}
 		}
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_smaps.go b/public-api/vendor/github.com/prometheus/procfs/proc_smaps.go
index 09060e82..9a297afc 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_smaps.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_smaps.go
@@ -19,7 +19,6 @@ package procfs
 import (
 	"bufio"
 	"errors"
-	"fmt"
 	"os"
 	"regexp"
 	"strconv"
@@ -29,7 +28,7 @@ import (
 )
 
 var (
-	// match the header line before each mapped zone in `/proc/pid/smaps`.
+	// Match the header line before each mapped zone in `/proc/pid/smaps`.
 	procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`)
 )
 
@@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) {
 func (s *ProcSMapsRollup) parseLine(line string) error {
 	kv := strings.SplitN(line, ":", 2)
 	if len(kv) != 2 {
-		fmt.Println(line)
 		return errors.New("invalid net/dev line, missing colon")
 	}
 
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_snmp.go b/public-api/vendor/github.com/prometheus/procfs/proc_snmp.go
index b9d2cf64..4bdc90b0 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_snmp.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_snmp.go
@@ -173,138 +173,138 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) {
 			case "Ip":
 				switch key {
 				case "Forwarding":
-					procSnmp.Ip.Forwarding = &value
+					procSnmp.Forwarding = &value
 				case "DefaultTTL":
-					procSnmp.Ip.DefaultTTL = &value
+					procSnmp.DefaultTTL = &value
 				case "InReceives":
-					procSnmp.Ip.InReceives = &value
+					procSnmp.InReceives = &value
 				case "InHdrErrors":
-					procSnmp.Ip.InHdrErrors = &value
+					procSnmp.InHdrErrors = &value
 				case "InAddrErrors":
-					procSnmp.Ip.InAddrErrors = &value
+					procSnmp.InAddrErrors = &value
 				case "ForwDatagrams":
-					procSnmp.Ip.ForwDatagrams = &value
+					procSnmp.ForwDatagrams = &value
 				case "InUnknownProtos":
-					procSnmp.Ip.InUnknownProtos = &value
+					procSnmp.InUnknownProtos = &value
 				case "InDiscards":
-					procSnmp.Ip.InDiscards = &value
+					procSnmp.InDiscards = &value
 				case "InDelivers":
-					procSnmp.Ip.InDelivers = &value
+					procSnmp.InDelivers = &value
 				case "OutRequests":
-					procSnmp.Ip.OutRequests = &value
+					procSnmp.OutRequests = &value
 				case "OutDiscards":
-					procSnmp.Ip.OutDiscards = &value
+					procSnmp.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp.Ip.OutNoRoutes = &value
+					procSnmp.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp.Ip.ReasmTimeout = &value
+					procSnmp.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp.Ip.ReasmReqds = &value
+					procSnmp.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp.Ip.ReasmOKs = &value
+					procSnmp.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp.Ip.ReasmFails = &value
+					procSnmp.ReasmFails = &value
 				case "FragOKs":
-					procSnmp.Ip.FragOKs = &value
+					procSnmp.FragOKs = &value
 				case "FragFails":
-					procSnmp.Ip.FragFails = &value
+					procSnmp.FragFails = &value
 				case "FragCreates":
-					procSnmp.Ip.FragCreates = &value
+					procSnmp.FragCreates = &value
 				}
 			case "Icmp":
 				switch key {
 				case "InMsgs":
-					procSnmp.Icmp.InMsgs = &value
+					procSnmp.InMsgs = &value
 				case "InErrors":
 					procSnmp.Icmp.InErrors = &value
 				case "InCsumErrors":
 					procSnmp.Icmp.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp.Icmp.InDestUnreachs = &value
+					procSnmp.InDestUnreachs = &value
 				case "InTimeExcds":
-					procSnmp.Icmp.InTimeExcds = &value
+					procSnmp.InTimeExcds = &value
 				case "InParmProbs":
-					procSnmp.Icmp.InParmProbs = &value
+					procSnmp.InParmProbs = &value
 				case "InSrcQuenchs":
-					procSnmp.Icmp.InSrcQuenchs = &value
+					procSnmp.InSrcQuenchs = &value
 				case "InRedirects":
-					procSnmp.Icmp.InRedirects = &value
+					procSnmp.InRedirects = &value
 				case "InEchos":
-					procSnmp.Icmp.InEchos = &value
+					procSnmp.InEchos = &value
 				case "InEchoReps":
-					procSnmp.Icmp.InEchoReps = &value
+					procSnmp.InEchoReps = &value
 				case "InTimestamps":
-					procSnmp.Icmp.InTimestamps = &value
+					procSnmp.InTimestamps = &value
 				case "InTimestampReps":
-					procSnmp.Icmp.InTimestampReps = &value
+					procSnmp.InTimestampReps = &value
 				case "InAddrMasks":
-					procSnmp.Icmp.InAddrMasks = &value
+					procSnmp.InAddrMasks = &value
 				case "InAddrMaskReps":
-					procSnmp.Icmp.InAddrMaskReps = &value
+					procSnmp.InAddrMaskReps = &value
 				case "OutMsgs":
-					procSnmp.Icmp.OutMsgs = &value
+					procSnmp.OutMsgs = &value
 				case "OutErrors":
-					procSnmp.Icmp.OutErrors = &value
+					procSnmp.OutErrors = &value
 				case "OutDestUnreachs":
-					procSnmp.Icmp.OutDestUnreachs = &value
+					procSnmp.OutDestUnreachs = &value
 				case "OutTimeExcds":
-					procSnmp.Icmp.OutTimeExcds = &value
+					procSnmp.OutTimeExcds = &value
 				case "OutParmProbs":
-					procSnmp.Icmp.OutParmProbs = &value
+					procSnmp.OutParmProbs = &value
 				case "OutSrcQuenchs":
-					procSnmp.Icmp.OutSrcQuenchs = &value
+					procSnmp.OutSrcQuenchs = &value
 				case "OutRedirects":
-					procSnmp.Icmp.OutRedirects = &value
+					procSnmp.OutRedirects = &value
 				case "OutEchos":
-					procSnmp.Icmp.OutEchos = &value
+					procSnmp.OutEchos = &value
 				case "OutEchoReps":
-					procSnmp.Icmp.OutEchoReps = &value
+					procSnmp.OutEchoReps = &value
 				case "OutTimestamps":
-					procSnmp.Icmp.OutTimestamps = &value
+					procSnmp.OutTimestamps = &value
 				case "OutTimestampReps":
-					procSnmp.Icmp.OutTimestampReps = &value
+					procSnmp.OutTimestampReps = &value
 				case "OutAddrMasks":
-					procSnmp.Icmp.OutAddrMasks = &value
+					procSnmp.OutAddrMasks = &value
 				case "OutAddrMaskReps":
-					procSnmp.Icmp.OutAddrMaskReps = &value
+					procSnmp.OutAddrMaskReps = &value
 				}
 			case "IcmpMsg":
 				switch key {
 				case "InType3":
-					procSnmp.IcmpMsg.InType3 = &value
+					procSnmp.InType3 = &value
 				case "OutType3":
-					procSnmp.IcmpMsg.OutType3 = &value
+					procSnmp.OutType3 = &value
 				}
 			case "Tcp":
 				switch key {
 				case "RtoAlgorithm":
-					procSnmp.Tcp.RtoAlgorithm = &value
+					procSnmp.RtoAlgorithm = &value
 				case "RtoMin":
-					procSnmp.Tcp.RtoMin = &value
+					procSnmp.RtoMin = &value
 				case "RtoMax":
-					procSnmp.Tcp.RtoMax = &value
+					procSnmp.RtoMax = &value
 				case "MaxConn":
-					procSnmp.Tcp.MaxConn = &value
+					procSnmp.MaxConn = &value
 				case "ActiveOpens":
-					procSnmp.Tcp.ActiveOpens = &value
+					procSnmp.ActiveOpens = &value
 				case "PassiveOpens":
-					procSnmp.Tcp.PassiveOpens = &value
+					procSnmp.PassiveOpens = &value
 				case "AttemptFails":
-					procSnmp.Tcp.AttemptFails = &value
+					procSnmp.AttemptFails = &value
 				case "EstabResets":
-					procSnmp.Tcp.EstabResets = &value
+					procSnmp.EstabResets = &value
 				case "CurrEstab":
-					procSnmp.Tcp.CurrEstab = &value
+					procSnmp.CurrEstab = &value
 				case "InSegs":
-					procSnmp.Tcp.InSegs = &value
+					procSnmp.InSegs = &value
 				case "OutSegs":
-					procSnmp.Tcp.OutSegs = &value
+					procSnmp.OutSegs = &value
 				case "RetransSegs":
-					procSnmp.Tcp.RetransSegs = &value
+					procSnmp.RetransSegs = &value
 				case "InErrs":
-					procSnmp.Tcp.InErrs = &value
+					procSnmp.InErrs = &value
 				case "OutRsts":
-					procSnmp.Tcp.OutRsts = &value
+					procSnmp.OutRsts = &value
 				case "InCsumErrors":
 					procSnmp.Tcp.InCsumErrors = &value
 				}
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_snmp6.go b/public-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
index 3059cc6a..fb7fd399 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_snmp6.go
@@ -182,161 +182,161 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 			case "Ip6":
 				switch key {
 				case "InReceives":
-					procSnmp6.Ip6.InReceives = &value
+					procSnmp6.InReceives = &value
 				case "InHdrErrors":
-					procSnmp6.Ip6.InHdrErrors = &value
+					procSnmp6.InHdrErrors = &value
 				case "InTooBigErrors":
-					procSnmp6.Ip6.InTooBigErrors = &value
+					procSnmp6.InTooBigErrors = &value
 				case "InNoRoutes":
-					procSnmp6.Ip6.InNoRoutes = &value
+					procSnmp6.InNoRoutes = &value
 				case "InAddrErrors":
-					procSnmp6.Ip6.InAddrErrors = &value
+					procSnmp6.InAddrErrors = &value
 				case "InUnknownProtos":
-					procSnmp6.Ip6.InUnknownProtos = &value
+					procSnmp6.InUnknownProtos = &value
 				case "InTruncatedPkts":
-					procSnmp6.Ip6.InTruncatedPkts = &value
+					procSnmp6.InTruncatedPkts = &value
 				case "InDiscards":
-					procSnmp6.Ip6.InDiscards = &value
+					procSnmp6.InDiscards = &value
 				case "InDelivers":
-					procSnmp6.Ip6.InDelivers = &value
+					procSnmp6.InDelivers = &value
 				case "OutForwDatagrams":
-					procSnmp6.Ip6.OutForwDatagrams = &value
+					procSnmp6.OutForwDatagrams = &value
 				case "OutRequests":
-					procSnmp6.Ip6.OutRequests = &value
+					procSnmp6.OutRequests = &value
 				case "OutDiscards":
-					procSnmp6.Ip6.OutDiscards = &value
+					procSnmp6.OutDiscards = &value
 				case "OutNoRoutes":
-					procSnmp6.Ip6.OutNoRoutes = &value
+					procSnmp6.OutNoRoutes = &value
 				case "ReasmTimeout":
-					procSnmp6.Ip6.ReasmTimeout = &value
+					procSnmp6.ReasmTimeout = &value
 				case "ReasmReqds":
-					procSnmp6.Ip6.ReasmReqds = &value
+					procSnmp6.ReasmReqds = &value
 				case "ReasmOKs":
-					procSnmp6.Ip6.ReasmOKs = &value
+					procSnmp6.ReasmOKs = &value
 				case "ReasmFails":
-					procSnmp6.Ip6.ReasmFails = &value
+					procSnmp6.ReasmFails = &value
 				case "FragOKs":
-					procSnmp6.Ip6.FragOKs = &value
+					procSnmp6.FragOKs = &value
 				case "FragFails":
-					procSnmp6.Ip6.FragFails = &value
+					procSnmp6.FragFails = &value
 				case "FragCreates":
-					procSnmp6.Ip6.FragCreates = &value
+					procSnmp6.FragCreates = &value
 				case "InMcastPkts":
-					procSnmp6.Ip6.InMcastPkts = &value
+					procSnmp6.InMcastPkts = &value
 				case "OutMcastPkts":
-					procSnmp6.Ip6.OutMcastPkts = &value
+					procSnmp6.OutMcastPkts = &value
 				case "InOctets":
-					procSnmp6.Ip6.InOctets = &value
+					procSnmp6.InOctets = &value
 				case "OutOctets":
-					procSnmp6.Ip6.OutOctets = &value
+					procSnmp6.OutOctets = &value
 				case "InMcastOctets":
-					procSnmp6.Ip6.InMcastOctets = &value
+					procSnmp6.InMcastOctets = &value
 				case "OutMcastOctets":
-					procSnmp6.Ip6.OutMcastOctets = &value
+					procSnmp6.OutMcastOctets = &value
 				case "InBcastOctets":
-					procSnmp6.Ip6.InBcastOctets = &value
+					procSnmp6.InBcastOctets = &value
 				case "OutBcastOctets":
-					procSnmp6.Ip6.OutBcastOctets = &value
+					procSnmp6.OutBcastOctets = &value
 				case "InNoECTPkts":
-					procSnmp6.Ip6.InNoECTPkts = &value
+					procSnmp6.InNoECTPkts = &value
 				case "InECT1Pkts":
-					procSnmp6.Ip6.InECT1Pkts = &value
+					procSnmp6.InECT1Pkts = &value
 				case "InECT0Pkts":
-					procSnmp6.Ip6.InECT0Pkts = &value
+					procSnmp6.InECT0Pkts = &value
 				case "InCEPkts":
-					procSnmp6.Ip6.InCEPkts = &value
+					procSnmp6.InCEPkts = &value
 
 				}
 			case "Icmp6":
 				switch key {
 				case "InMsgs":
-					procSnmp6.Icmp6.InMsgs = &value
+					procSnmp6.InMsgs = &value
 				case "InErrors":
 					procSnmp6.Icmp6.InErrors = &value
 				case "OutMsgs":
-					procSnmp6.Icmp6.OutMsgs = &value
+					procSnmp6.OutMsgs = &value
 				case "OutErrors":
-					procSnmp6.Icmp6.OutErrors = &value
+					procSnmp6.OutErrors = &value
 				case "InCsumErrors":
 					procSnmp6.Icmp6.InCsumErrors = &value
 				case "InDestUnreachs":
-					procSnmp6.Icmp6.InDestUnreachs = &value
+					procSnmp6.InDestUnreachs = &value
 				case "InPktTooBigs":
-					procSnmp6.Icmp6.InPktTooBigs = &value
+					procSnmp6.InPktTooBigs = &value
 				case "InTimeExcds":
-					procSnmp6.Icmp6.InTimeExcds = &value
+					procSnmp6.InTimeExcds = &value
 				case "InParmProblems":
-					procSnmp6.Icmp6.InParmProblems = &value
+					procSnmp6.InParmProblems = &value
 				case "InEchos":
-					procSnmp6.Icmp6.InEchos = &value
+					procSnmp6.InEchos = &value
 				case "InEchoReplies":
-					procSnmp6.Icmp6.InEchoReplies = &value
+					procSnmp6.InEchoReplies = &value
 				case "InGroupMembQueries":
-					procSnmp6.Icmp6.InGroupMembQueries = &value
+					procSnmp6.InGroupMembQueries = &value
 				case "InGroupMembResponses":
-					procSnmp6.Icmp6.InGroupMembResponses = &value
+					procSnmp6.InGroupMembResponses = &value
 				case "InGroupMembReductions":
-					procSnmp6.Icmp6.InGroupMembReductions = &value
+					procSnmp6.InGroupMembReductions = &value
 				case "InRouterSolicits":
-					procSnmp6.Icmp6.InRouterSolicits = &value
+					procSnmp6.InRouterSolicits = &value
 				case "InRouterAdvertisements":
-					procSnmp6.Icmp6.InRouterAdvertisements = &value
+					procSnmp6.InRouterAdvertisements = &value
 				case "InNeighborSolicits":
-					procSnmp6.Icmp6.InNeighborSolicits = &value
+					procSnmp6.InNeighborSolicits = &value
 				case "InNeighborAdvertisements":
-					procSnmp6.Icmp6.InNeighborAdvertisements = &value
+					procSnmp6.InNeighborAdvertisements = &value
 				case "InRedirects":
-					procSnmp6.Icmp6.InRedirects = &value
+					procSnmp6.InRedirects = &value
 				case "InMLDv2Reports":
-					procSnmp6.Icmp6.InMLDv2Reports = &value
+					procSnmp6.InMLDv2Reports = &value
 				case "OutDestUnreachs":
-					procSnmp6.Icmp6.OutDestUnreachs = &value
+					procSnmp6.OutDestUnreachs = &value
 				case "OutPktTooBigs":
-					procSnmp6.Icmp6.OutPktTooBigs = &value
+					procSnmp6.OutPktTooBigs = &value
 				case "OutTimeExcds":
-					procSnmp6.Icmp6.OutTimeExcds = &value
+					procSnmp6.OutTimeExcds = &value
 				case "OutParmProblems":
-					procSnmp6.Icmp6.OutParmProblems = &value
+					procSnmp6.OutParmProblems = &value
 				case "OutEchos":
-					procSnmp6.Icmp6.OutEchos = &value
+					procSnmp6.OutEchos = &value
 				case "OutEchoReplies":
-					procSnmp6.Icmp6.OutEchoReplies = &value
+					procSnmp6.OutEchoReplies = &value
 				case "OutGroupMembQueries":
-					procSnmp6.Icmp6.OutGroupMembQueries = &value
+					procSnmp6.OutGroupMembQueries = &value
 				case "OutGroupMembResponses":
-					procSnmp6.Icmp6.OutGroupMembResponses = &value
+					procSnmp6.OutGroupMembResponses = &value
 				case "OutGroupMembReductions":
-					procSnmp6.Icmp6.OutGroupMembReductions = &value
+					procSnmp6.OutGroupMembReductions = &value
 				case "OutRouterSolicits":
-					procSnmp6.Icmp6.OutRouterSolicits = &value
+					procSnmp6.OutRouterSolicits = &value
 				case "OutRouterAdvertisements":
-					procSnmp6.Icmp6.OutRouterAdvertisements = &value
+					procSnmp6.OutRouterAdvertisements = &value
 				case "OutNeighborSolicits":
-					procSnmp6.Icmp6.OutNeighborSolicits = &value
+					procSnmp6.OutNeighborSolicits = &value
 				case "OutNeighborAdvertisements":
-					procSnmp6.Icmp6.OutNeighborAdvertisements = &value
+					procSnmp6.OutNeighborAdvertisements = &value
 				case "OutRedirects":
-					procSnmp6.Icmp6.OutRedirects = &value
+					procSnmp6.OutRedirects = &value
 				case "OutMLDv2Reports":
-					procSnmp6.Icmp6.OutMLDv2Reports = &value
+					procSnmp6.OutMLDv2Reports = &value
 				case "InType1":
-					procSnmp6.Icmp6.InType1 = &value
+					procSnmp6.InType1 = &value
 				case "InType134":
-					procSnmp6.Icmp6.InType134 = &value
+					procSnmp6.InType134 = &value
 				case "InType135":
-					procSnmp6.Icmp6.InType135 = &value
+					procSnmp6.InType135 = &value
 				case "InType136":
-					procSnmp6.Icmp6.InType136 = &value
+					procSnmp6.InType136 = &value
 				case "InType143":
-					procSnmp6.Icmp6.InType143 = &value
+					procSnmp6.InType143 = &value
 				case "OutType133":
-					procSnmp6.Icmp6.OutType133 = &value
+					procSnmp6.OutType133 = &value
 				case "OutType135":
-					procSnmp6.Icmp6.OutType135 = &value
+					procSnmp6.OutType135 = &value
 				case "OutType136":
-					procSnmp6.Icmp6.OutType136 = &value
+					procSnmp6.OutType136 = &value
 				case "OutType143":
-					procSnmp6.Icmp6.OutType143 = &value
+					procSnmp6.OutType143 = &value
 				}
 			case "Udp6":
 				switch key {
@@ -355,7 +355,7 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
 				case "InCsumErrors":
 					procSnmp6.Udp6.InCsumErrors = &value
 				case "IgnoredMulti":
-					procSnmp6.Udp6.IgnoredMulti = &value
+					procSnmp6.IgnoredMulti = &value
 				}
 			case "UdpLite6":
 				switch key {
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_stat.go b/public-api/vendor/github.com/prometheus/procfs/proc_stat.go
index 06a8d931..3328556b 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_stat.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_stat.go
@@ -101,6 +101,12 @@ type ProcStat struct {
 	RSS int
 	// Soft limit in bytes on the rss of the process.
 	RSSLimit uint64
+	// The address above which program text can run.
+	StartCode uint64
+	// The address below which program text can run.
+	EndCode uint64
+	// The address of the start (i.e., bottom) of the stack.
+	StartStack uint64
 	// CPU number last executed on.
 	Processor uint
 	// Real-time scheduling priority, a number in the range 1 to 99 for processes
@@ -177,9 +183,9 @@ func (p Proc) Stat() (ProcStat, error) {
 		&s.VSize,
 		&s.RSS,
 		&s.RSSLimit,
-		&ignoreUint64,
-		&ignoreUint64,
-		&ignoreUint64,
+		&s.StartCode,
+		&s.EndCode,
+		&s.StartStack,
 		&ignoreUint64,
 		&ignoreUint64,
 		&ignoreUint64,
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_statm.go b/public-api/vendor/github.com/prometheus/procfs/proc_statm.go
new file mode 100644
index 00000000..ed579842
--- /dev/null
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_statm.go
@@ -0,0 +1,116 @@
+// Copyright 2025 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/prometheus/procfs/internal/util"
+)
+
+// - https://man7.org/linux/man-pages/man5/proc_pid_statm.5.html
+
+// ProcStatm Provides memory usage information for a process, measured in memory pages.
+// Read from /proc/[pid]/statm.
+type ProcStatm struct {
+	// The process ID.
+	PID int
+	// total program size (same as VmSize in status)
+	Size uint64
+	// resident set size (same as VmRSS in status)
+	Resident uint64
+	// number of resident shared pages (i.e., backed by a file)
+	Shared uint64
+	// text (code)
+	Text uint64
+	// library (unused since Linux 2.6; always 0)
+	Lib uint64
+	// data + stack
+	Data uint64
+	// dirty pages (unused since Linux 2.6; always 0)
+	Dt uint64
+}
+
+// NewStatm returns the current status information of the process.
+// Deprecated: Use p.Statm() instead.
+func (p Proc) NewStatm() (ProcStatm, error) {
+	return p.Statm()
+}
+
+// Statm returns the current memory usage information of the process.
+func (p Proc) Statm() (ProcStatm, error) {
+	data, err := util.ReadFileNoStat(p.path("statm"))
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	statmSlice, err := parseStatm(data)
+	if err != nil {
+		return ProcStatm{}, err
+	}
+
+	procStatm := ProcStatm{
+		PID:      p.PID,
+		Size:     statmSlice[0],
+		Resident: statmSlice[1],
+		Shared:   statmSlice[2],
+		Text:     statmSlice[3],
+		Lib:      statmSlice[4],
+		Data:     statmSlice[5],
+		Dt:       statmSlice[6],
+	}
+
+	return procStatm, nil
+}
+
+// parseStatm return /proc/[pid]/statm data to uint64 slice.
+func parseStatm(data []byte) ([]uint64, error) {
+	var statmSlice []uint64
+	statmItems := strings.Fields(string(data))
+	for i := 0; i < len(statmItems); i++ {
+		statmItem, err := strconv.ParseUint(statmItems[i], 10, 64)
+		if err != nil {
+			return nil, err
+		}
+		statmSlice = append(statmSlice, statmItem)
+	}
+	return statmSlice, nil
+}
+
+// SizeBytes returns the process of total program size in bytes.
+func (s ProcStatm) SizeBytes() uint64 {
+	return s.Size * uint64(os.Getpagesize())
+}
+
+// ResidentBytes returns the process of resident set size in bytes.
+func (s ProcStatm) ResidentBytes() uint64 {
+	return s.Resident * uint64(os.Getpagesize())
+}
+
+// SHRBytes returns the process of share memory size in bytes.
+func (s ProcStatm) SHRBytes() uint64 {
+	return s.Shared * uint64(os.Getpagesize())
+}
+
+// TextBytes returns the process of text (code) size in bytes.
+func (s ProcStatm) TextBytes() uint64 {
+	return s.Text * uint64(os.Getpagesize())
+}
+
+// DataBytes returns the process of data + stack size in bytes.
+func (s ProcStatm) DataBytes() uint64 {
+	return s.Data * uint64(os.Getpagesize())
+}
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_status.go b/public-api/vendor/github.com/prometheus/procfs/proc_status.go
index a055197c..dd8aa568 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_status.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_status.go
@@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
 			}
 		}
 	case "NSpid":
-		s.NSpids = calcNSPidsList(vString)
+		nspids, err := calcNSPidsList(vString)
+		if err != nil {
+			return err
+		}
+		s.NSpids = nspids
 	case "VmPeak":
 		s.VmPeak = vUintBytes
 	case "VmSize":
@@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 {
 	return g
 }
 
-func calcNSPidsList(nspidsString string) []uint64 {
-	s := strings.Split(nspidsString, " ")
+func calcNSPidsList(nspidsString string) ([]uint64, error) {
+	s := strings.Split(nspidsString, "\t")
 	var nspids []uint64
 
 	for _, nspid := range s {
-		nspid, _ := strconv.ParseUint(nspid, 10, 64)
-		if nspid == 0 {
-			continue
+		nspid, err := strconv.ParseUint(nspid, 10, 64)
+		if err != nil {
+			return nil, err
 		}
 		nspids = append(nspids, nspid)
 	}
 
-	return nspids
+	return nspids, nil
 }
diff --git a/public-api/vendor/github.com/prometheus/procfs/proc_sys.go b/public-api/vendor/github.com/prometheus/procfs/proc_sys.go
index 5eefbe2e..3810d1ac 100644
--- a/public-api/vendor/github.com/prometheus/procfs/proc_sys.go
+++ b/public-api/vendor/github.com/prometheus/procfs/proc_sys.go
@@ -21,7 +21,7 @@ import (
 )
 
 func sysctlToPath(sysctl string) string {
-	return strings.Replace(sysctl, ".", "/", -1)
+	return strings.ReplaceAll(sysctl, ".", "/")
 }
 
 func (fs FS) SysctlStrings(sysctl string) ([]string, error) {
diff --git a/public-api/vendor/github.com/prometheus/procfs/softirqs.go b/public-api/vendor/github.com/prometheus/procfs/softirqs.go
index 28708e07..403e6ae7 100644
--- a/public-api/vendor/github.com/prometheus/procfs/softirqs.go
+++ b/public-api/vendor/github.com/prometheus/procfs/softirqs.go
@@ -68,8 +68,8 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 		if len(parts) < 2 {
 			continue
 		}
-		switch {
-		case parts[0] == "HI:":
+		switch parts[0] {
+		case "HI:":
 			perCPU := parts[1:]
 			softirqs.Hi = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -77,7 +77,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TIMER:":
+		case "TIMER:":
 			perCPU := parts[1:]
 			softirqs.Timer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -85,7 +85,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_TX:":
+		case "NET_TX:":
 			perCPU := parts[1:]
 			softirqs.NetTx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -93,7 +93,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "NET_RX:":
+		case "NET_RX:":
 			perCPU := parts[1:]
 			softirqs.NetRx = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -101,7 +101,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "BLOCK:":
+		case "BLOCK:":
 			perCPU := parts[1:]
 			softirqs.Block = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -109,7 +109,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "IRQ_POLL:":
+		case "IRQ_POLL:":
 			perCPU := parts[1:]
 			softirqs.IRQPoll = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -117,7 +117,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "TASKLET:":
+		case "TASKLET:":
 			perCPU := parts[1:]
 			softirqs.Tasklet = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -125,7 +125,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "SCHED:":
+		case "SCHED:":
 			perCPU := parts[1:]
 			softirqs.Sched = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -133,7 +133,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "HRTIMER:":
+		case "HRTIMER:":
 			perCPU := parts[1:]
 			softirqs.HRTimer = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
@@ -141,7 +141,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
 					return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
 				}
 			}
-		case parts[0] == "RCU:":
+		case "RCU:":
 			perCPU := parts[1:]
 			softirqs.RCU = make([]uint64, len(perCPU))
 			for i, count := range perCPU {
diff --git a/public-api/vendor/github.com/rs/cors/cors.go b/public-api/vendor/github.com/rs/cors/cors.go
index da80d343..724f242a 100644
--- a/public-api/vendor/github.com/rs/cors/cors.go
+++ b/public-api/vendor/github.com/rs/cors/cors.go
@@ -364,9 +364,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	// Note: the Fetch standard guarantees that at most one
 	// Access-Control-Request-Headers header is present in the preflight request;
 	// see step 5.2 in https://fetch.spec.whatwg.org/#cors-preflight-fetch-0.
-	reqHeaders, found := first(r.Header, "Access-Control-Request-Headers")
-	if found && !c.allowedHeadersAll && !c.allowedHeaders.Subsumes(reqHeaders[0]) {
-		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders[0])
+	// However, some gateways split that header into multiple headers of the same name;
+	// see https://github.com/rs/cors/issues/184.
+	reqHeaders, found := r.Header["Access-Control-Request-Headers"]
+	if found && !c.allowedHeadersAll && !c.allowedHeaders.Accepts(reqHeaders) {
+		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders)
 		return
 	}
 	if c.allowedOriginsAll {
@@ -391,9 +393,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
 	if len(c.maxAge) > 0 {
 		headers["Access-Control-Max-Age"] = c.maxAge
 	}
-	if c.Log != nil {
-		c.logf("  Preflight response headers: %v", headers)
-	}
+	c.logf("  Preflight response headers: %v", headers)
 }
 
 // handleActualRequest handles simple cross-origin requests, actual request or redirects
@@ -440,9 +440,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
 	if c.allowCredentials {
 		headers["Access-Control-Allow-Credentials"] = headerTrue
 	}
-	if c.Log != nil {
-		c.logf("  Actual response added headers: %v", headers)
-	}
+	c.logf("  Actual response added headers: %v", headers)
 }
 
 // convenience method. checks if a logger is set.
diff --git a/public-api/vendor/github.com/rs/cors/internal/sortedset.go b/public-api/vendor/github.com/rs/cors/internal/sortedset.go
index 513da20f..844f3f9e 100644
--- a/public-api/vendor/github.com/rs/cors/internal/sortedset.go
+++ b/public-api/vendor/github.com/rs/cors/internal/sortedset.go
@@ -52,46 +52,134 @@ func (set SortedSet) String() string {
 	return strings.Join(elems, ",")
 }
 
-// Subsumes reports whether csv is a sequence of comma-separated names that are
-//   - all elements of set,
-//   - sorted in lexicographically order,
+// Accepts reports whether values is a sequence of list-based field values
+// whose elements are
+//   - all members of set,
+//   - sorted in lexicographical order,
 //   - unique.
-func (set SortedSet) Subsumes(csv string) bool {
-	if csv == "" {
-		return true
+func (set SortedSet) Accepts(values []string) bool {
+	var ( // effectively constant
+		maxLen = maxOWSBytes + set.maxLen + maxOWSBytes + 1 // +1 for comma
+	)
+	var (
+		posOfLastNameSeen = -1
+		name              string
+		commaFound        bool
+		emptyElements     int
+		ok                bool
+	)
+	for _, s := range values {
+		for {
+			// As a defense against maliciously long names in s,
+			// we process only a small number of s's leading bytes per iteration.
+			name, s, commaFound = cutAtComma(s, maxLen)
+			name, ok = trimOWS(name, maxOWSBytes)
+			if !ok {
+				return false
+			}
+			if name == "" {
+				// RFC 9110 requires recipients to tolerate
+				// "a reasonable number of empty list elements"; see
+				// https://httpwg.org/specs/rfc9110.html#abnf.extension.recipient.
+				emptyElements++
+				if emptyElements > maxEmptyElements {
+					return false
+				}
+				if !commaFound { // We have now exhausted the names in s.
+					break
+				}
+				continue
+			}
+			pos, ok := set.m[name]
+			if !ok {
+				return false
+			}
+			// The names in s are expected to be sorted in lexicographical order
+			// and to each appear at most once.
+			// Therefore, the positions (in set) of the names that
+			// appear in s should form a strictly increasing sequence.
+			// If that's not actually the case, bail out.
+			if pos <= posOfLastNameSeen {
+				return false
+			}
+			posOfLastNameSeen = pos
+			if !commaFound { // We have now exhausted the names in s.
+				break
+			}
+		}
+	}
+	return true
+}
+
+const (
+	maxOWSBytes      = 1  // number of leading/trailing OWS bytes tolerated
+	maxEmptyElements = 16 // number of empty list elements tolerated
+)
+
+func cutAtComma(s string, n int) (before, after string, found bool) {
+	// Note: this implementation draws inspiration from strings.Cut's.
+	end := min(len(s), n)
+	if i := strings.IndexByte(s[:end], ','); i >= 0 {
+		after = s[i+1:] // deal with this first to save one bounds check
+		return s[:i], after, true
+	}
+	return s, "", false
+}
+
+// TrimOWS trims up to n bytes of [optional whitespace (OWS)]
+// from the start of and/or the end of s.
+// If no more than n bytes of OWS are found at the start of s
+// and no more than n bytes of OWS are found at the end of s,
+// it returns the trimmed result and true.
+// Otherwise, it returns the original string and false.
+//
+// [optional whitespace (OWS)]: https://httpwg.org/specs/rfc9110.html#whitespace
+func trimOWS(s string, n int) (trimmed string, ok bool) {
+	if s == "" {
+		return s, true
+	}
+	trimmed, ok = trimRightOWS(s, n)
+	if !ok {
+		return s, false
 	}
-	posOfLastNameSeen := -1
-	chunkSize := set.maxLen + 1 // (to accommodate for at least one comma)
-	for {
-		// As a defense against maliciously long names in csv,
-		// we only process at most chunkSize bytes per iteration.
-		end := min(len(csv), chunkSize)
-		comma := strings.IndexByte(csv[:end], ',')
-		var name string
-		if comma == -1 {
-			name = csv
-		} else {
-			name = csv[:comma]
+	trimmed, ok = trimLeftOWS(trimmed, n)
+	if !ok {
+		return s, false
+	}
+	return trimmed, true
+}
+
+func trimLeftOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		pos, found := set.m[name]
-		if !found {
-			return false
+		if !(s[0] == ' ' || s[0] == '\t') {
+			break
 		}
-		// The names in csv are expected to be sorted in lexicographical order
-		// and appear at most once in csv.
-		// Therefore, the positions (in set) of the names that
-		// appear in csv should form a strictly increasing sequence.
-		// If that's not actually the case, bail out.
-		if pos <= posOfLastNameSeen {
-			return false
+		s = s[1:]
+		i++
+	}
+	return s, true
+}
+
+func trimRightOWS(s string, n int) (string, bool) {
+	sCopy := s
+	var i int
+	for len(s) > 0 {
+		if i > n {
+			return sCopy, false
 		}
-		posOfLastNameSeen = pos
-		if comma < 0 { // We've now processed all the names in csv.
+		last := len(s) - 1
+		if !(s[last] == ' ' || s[last] == '\t') {
 			break
 		}
-		csv = csv[comma+1:]
+		s = s[:last]
+		i++
 	}
-	return true
+	return s, true
 }
 
 // TODO: when updating go directive to 1.21 or later,
diff --git a/public-api/vendor/github.com/rs/cors/utils.go b/public-api/vendor/github.com/rs/cors/utils.go
index 7019f45c..41b0c283 100644
--- a/public-api/vendor/github.com/rs/cors/utils.go
+++ b/public-api/vendor/github.com/rs/cors/utils.go
@@ -1,7 +1,6 @@
 package cors
 
 import (
-	"net/http"
 	"strings"
 )
 
@@ -24,11 +23,3 @@ func convert(s []string, f func(string) string) []string {
 	}
 	return out
 }
-
-func first(hdrs http.Header, k string) ([]string, bool) {
-	v, found := hdrs[k]
-	if !found || len(v) == 0 {
-		return nil, false
-	}
-	return v[:1], true
-}
diff --git a/public-api/vendor/github.com/rs/zerolog/CNAME b/public-api/vendor/github.com/rs/zerolog/CNAME
deleted file mode 100644
index 9ce57a6e..00000000
--- a/public-api/vendor/github.com/rs/zerolog/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-zerolog.io
\ No newline at end of file
diff --git a/public-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md b/public-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md
new file mode 100644
index 00000000..a09e9e21
--- /dev/null
+++ b/public-api/vendor/github.com/rs/zerolog/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contributing to Zerolog
+
+Thank you for your interest in contributing to **Zerolog**!
+
+Zerolog is a **feature-complete**, high-performance logging library designed to be **lean** and **non-bloated**. The focus of ongoing development is on **bug fixes**, **performance improvements**, and **modernization efforts** (such as keeping up with Go best practices and compatibility with newer Go versions).
+
+## What We're Looking For
+
+We welcome contributions in the following areas:
+
+- **Bug Fixes**: If you find an issue or unexpected behavior, please open an issue and/or submit a fix.
+- **Performance Optimizations**: Improvements that reduce memory usage, allocation count, or CPU cycles without introducing complexity are appreciated.
+- **Modernization**: Compatibility updates for newer Go versions or idiomatic improvements that do not increase library size or complexity.
+- **Documentation Enhancements**: Corrections, clarifications, and improvements to documentation or code comments.
+
+## What We're *Not* Looking For
+
+Zerolog is intended to remain **minimalistic and efficient**. Therefore, we are **not accepting**:
+
+- New features that add optional behaviors or extend API surface area.
+- Built-in support for frameworks or external systems (e.g., bindings, integrations).
+- General-purpose abstractions or configuration helpers.
+
+If you're unsure whether a change aligns with the project's philosophy, feel free to open an issue for discussion before submitting a PR.
+
+## Contributing Guidelines
+
+1. **Fork the repository**
+2. **Create a branch** for your fix or improvement
+3. **Write tests** to cover your changes
+4. Ensure `go test ./...` passes
+5. Run `go fmt` and `go vet` to ensure code consistency
+6. **Submit a pull request** with a clear explanation of the motivation and impact
+
+## Code Style
+
+- Keep the code simple, efficient, and idiomatic.
+- Avoid introducing new dependencies.
+- Preserve backwards compatibility unless explicitly discussed.
+
+---
+
+We appreciate your effort in helping us keep Zerolog fast, minimal, and reliable!
diff --git a/public-api/vendor/github.com/rs/zerolog/README.md b/public-api/vendor/github.com/rs/zerolog/README.md
index 1306a6c1..9d4e8e8d 100644
--- a/public-api/vendor/github.com/rs/zerolog/README.md
+++ b/public-api/vendor/github.com/rs/zerolog/README.md
@@ -366,6 +366,37 @@ log.Info().Str("foo", "bar").Msg("Hello World")
 // Output: 2006-01-02T15:04:05Z07:00 | INFO  | ***Hello World**** foo:BAR
 ```
 
+To use custom advanced formatting:
+
+```go
+output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true,
+    PartsOrder:    []string{"level", "one", "two", "three", "message"},
+    FieldsExclude: []string{"one", "two", "three"}}
+output.FormatLevel = func(i interface{}) string { return strings.ToUpper(fmt.Sprintf("%-6s", i)) }
+output.FormatFieldName = func(i interface{}) string { return fmt.Sprintf("%s:", i) }
+output.FormatPartValueByName = func(i interface{}, s string) string {
+    var ret string
+    switch s {
+    case "one":
+        ret = strings.ToUpper(fmt.Sprintf("%s", i))
+    case "two":
+        ret = strings.ToLower(fmt.Sprintf("%s", i))
+    case "three":
+        ret = strings.ToLower(fmt.Sprintf("(%s)", i))
+    }
+    return ret
+}
+log := zerolog.New(output)
+
+log.Info().Str("foo", "bar").
+    Str("two", "TEST_TWO").
+    Str("one", "test_one").
+    Str("three", "test_three").
+    Msg("Hello World")
+    
+// Output: INFO   TEST_ONE test_two (test_three) Hello World foo:bar
+```
+
 ### Sub dictionary
 
 ```go
diff --git a/public-api/vendor/github.com/rs/zerolog/_config.yml b/public-api/vendor/github.com/rs/zerolog/_config.yml
deleted file mode 100644
index a1e896d7..00000000
--- a/public-api/vendor/github.com/rs/zerolog/_config.yml
+++ /dev/null
@@ -1 +0,0 @@
-remote_theme: rs/gh-readme
diff --git a/public-api/vendor/github.com/rs/zerolog/console.go b/public-api/vendor/github.com/rs/zerolog/console.go
index 7e65e86f..6c881ef6 100644
--- a/public-api/vendor/github.com/rs/zerolog/console.go
+++ b/public-api/vendor/github.com/rs/zerolog/console.go
@@ -47,6 +47,10 @@ const (
 // Formatter transforms the input into a formatted string.
 type Formatter func(interface{}) string
 
+// FormatterByFieldName transforms the input into a formatted string,
+// being able to differentiate formatting based on field name.
+type FormatterByFieldName func(interface{}, string) string
+
 // ConsoleWriter parses the JSON input and writes it in an
 // (optionally) colorized, human-friendly format to Out.
 type ConsoleWriter struct {
@@ -85,6 +89,9 @@ type ConsoleWriter struct {
 	FormatFieldValue    Formatter
 	FormatErrFieldName  Formatter
 	FormatErrFieldValue Formatter
+	// If this is configured it is used for "part" values and
+	// has precedence on FormatFieldValue
+	FormatPartValueByName FormatterByFieldName
 
 	FormatExtra func(map[string]interface{}, *bytes.Buffer) error
 
@@ -282,8 +289,9 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
 // writePart appends a formatted part to buf.
 func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{}, p string) {
 	var f Formatter
+	var fvn FormatterByFieldName
 
-	if w.PartsExclude != nil && len(w.PartsExclude) > 0 {
+	if len(w.PartsExclude) > 0 {
 		for _, exclude := range w.PartsExclude {
 			if exclude == p {
 				return
@@ -317,14 +325,21 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
 			f = w.FormatCaller
 		}
 	default:
-		if w.FormatFieldValue == nil {
-			f = consoleDefaultFormatFieldValue
-		} else {
+		if w.FormatPartValueByName != nil {
+			fvn = w.FormatPartValueByName
+		} else if w.FormatFieldValue != nil {
 			f = w.FormatFieldValue
+		} else {
+			f = consoleDefaultFormatFieldValue
 		}
 	}
 
-	var s = f(evt[p])
+	var s string
+	if f == nil {
+		s = fvn(evt[p], p)
+	} else {
+		s = f(evt[p])
+	}
 
 	if len(s) > 0 {
 		if buf.Len() > 0 {
diff --git a/public-api/vendor/github.com/rs/zerolog/log.go b/public-api/vendor/github.com/rs/zerolog/log.go
index 6c1d4ead..ea2cd62b 100644
--- a/public-api/vendor/github.com/rs/zerolog/log.go
+++ b/public-api/vendor/github.com/rs/zerolog/log.go
@@ -494,7 +494,7 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event {
 	if level != NoLevel && LevelFieldName != "" {
 		e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
 	}
-	if l.context != nil && len(l.context) > 1 {
+	if len(l.context) > 1 {
 		e.buf = enc.AppendObjectData(e.buf, l.context)
 	}
 	if l.stack {
diff --git a/public-api/vendor/github.com/rs/zerolog/sampler.go b/public-api/vendor/github.com/rs/zerolog/sampler.go
index 83ce2ed3..19e04bd4 100644
--- a/public-api/vendor/github.com/rs/zerolog/sampler.go
+++ b/public-api/vendor/github.com/rs/zerolog/sampler.go
@@ -47,6 +47,9 @@ type BasicSampler struct {
 // Sample implements the Sampler interface.
 func (s *BasicSampler) Sample(lvl Level) bool {
 	n := s.N
+	if n == 0 {
+		return false
+	}
 	if n == 1 {
 		return true
 	}
@@ -87,7 +90,7 @@ func (s *BurstSampler) inc() uint32 {
 	now := TimestampFunc().UnixNano()
 	resetAt := atomic.LoadInt64(&s.resetAt)
 	var c uint32
-	if now > resetAt {
+	if now >= resetAt {
 		c = 1
 		atomic.StoreUint32(&s.counter, c)
 		newResetAt := now + s.Period.Nanoseconds()
diff --git a/public-api/vendor/github.com/rs/zerolog/writer.go b/public-api/vendor/github.com/rs/zerolog/writer.go
index 41b394d7..0fc5ff59 100644
--- a/public-api/vendor/github.com/rs/zerolog/writer.go
+++ b/public-api/vendor/github.com/rs/zerolog/writer.go
@@ -213,6 +213,15 @@ func (w *FilteredLevelWriter) WriteLevel(level Level, p []byte) (int, error) {
 	return len(p), nil
 }
 
+// Call the underlying writer's Close method if it is an io.Closer. Otherwise
+// does nothing.
+func (w *FilteredLevelWriter) Close() error {
+	if closer, ok := w.Writer.(io.Closer); ok {
+		return closer.Close()
+	}
+	return nil
+}
+
 var triggerWriterPool = &sync.Pool{
 	New: func() interface{} {
 		return bytes.NewBuffer(make([]byte, 0, 1024))
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
index 0b8155aa..f13675ed 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/config.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -25,72 +26,77 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Add(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Add_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq Config
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq Config
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Add(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigController_Read_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq emptypb.Empty
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq emptypb.Empty
+		metadata runtime.ServerMetadata
+	)
 	msg, err := server.Read(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterConfigControllerHandlerServer registers the http handlers for service ConfigController to "mux".
 // UnaryRPC     :call ConfigControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterConfigControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ConfigControllerServer) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -102,20 +108,15 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -127,9 +128,7 @@ func RegisterConfigControllerHandlerServer(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -156,7 +155,6 @@ func RegisterConfigControllerHandlerFromEndpoint(ctx context.Context, mux *runti
 			}
 		}()
 	}()
-
 	return RegisterConfigControllerHandler(ctx, mux, conn)
 }
 
@@ -170,16 +168,13 @@ func RegisterConfigControllerHandler(ctx context.Context, mux *runtime.ServeMux,
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ConfigControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ConfigControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "ConfigControllerClient" to call the correct interceptors.
+// "ConfigControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ConfigControllerClient) error {
-
-	mux.Handle("POST", pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigController_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Add", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -190,18 +185,13 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigController_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_config.ConfigController/Read", runtime.WithHTTPPathPattern("/api/v1/config/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -212,22 +202,17 @@ func RegisterConfigControllerHandlerClient(ctx context.Context, mux *runtime.Ser
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigController_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_ConfigController_Add_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
-
+	pattern_ConfigController_Add_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 	pattern_ConfigController_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "config", "event-processor"}, ""))
 )
 
 var (
-	forward_ConfigController_Add_0 = runtime.ForwardResponseMessage
-
+	forward_ConfigController_Add_0  = runtime.ForwardResponseMessage
 	forward_ConfigController_Read_0 = runtime.ForwardResponseMessage
 )
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
index 6246b4bf..c5b245fe 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/event-processor/api/detector.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,160 +25,144 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Create_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateDetectorReq
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Create(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_DetectorController_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteDetectorReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteDetectorReq
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Delete(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_DetectorController_ListPage_0 = &utilities.DoubleArray{Encoding: map[string]int{"page_num": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, client DetectorControllerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ListPage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_DetectorController_ListPage_0(ctx context.Context, marshaler runtime.Marshaler, server DetectorControllerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListDetectorPageReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListDetectorPageReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["page_num"]
+	val, ok := pathParams["page_num"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "page_num")
 	}
-
 	protoReq.PageNum, err = runtime.Uint32(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "page_num", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_DetectorController_ListPage_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ListPage(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterDetectorControllerHandlerServer registers the http handlers for service DetectorController to "mux".
 // UnaryRPC     :call DetectorControllerServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDetectorControllerHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DetectorControllerServer) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -189,20 +174,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -214,20 +194,15 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -239,9 +214,7 @@ func RegisterDetectorControllerHandlerServer(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -268,7 +241,6 @@ func RegisterDetectorControllerHandlerFromEndpoint(ctx context.Context, mux *run
 			}
 		}()
 	}()
-
 	return RegisterDetectorControllerHandler(ctx, mux, conn)
 }
 
@@ -282,16 +254,13 @@ func RegisterDetectorControllerHandler(ctx context.Context, mux *runtime.ServeMu
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DetectorControllerClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DetectorControllerClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "DetectorControllerClient" to call the correct interceptors.
+// "DetectorControllerClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DetectorControllerClient) error {
-
-	mux.Handle("POST", pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_DetectorController_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Create", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -302,18 +271,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_DetectorController_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/Delete", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -324,18 +288,13 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_DetectorController_ListPage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/detector.DetectorController/ListPage", runtime.WithHTTPPathPattern("/api/v1/detector/event-processor/page/{page_num}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -346,26 +305,19 @@ func RegisterDetectorControllerHandlerClient(ctx context.Context, mux *runtime.S
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_DetectorController_ListPage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_DetectorController_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
-	pattern_DetectorController_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
-
+	pattern_DetectorController_Create_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
+	pattern_DetectorController_Delete_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "detector", "event-processor"}, ""))
 	pattern_DetectorController_ListPage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "detector", "event-processor", "page", "page_num"}, ""))
 )
 
 var (
-	forward_DetectorController_Create_0 = runtime.ForwardResponseMessage
-
-	forward_DetectorController_Delete_0 = runtime.ForwardResponseMessage
-
+	forward_DetectorController_Create_0   = runtime.ForwardResponseMessage
+	forward_DetectorController_Delete_0   = runtime.ForwardResponseMessage
 	forward_DetectorController_ListPage_0 = runtime.ForwardResponseMessage
 )
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.go
index 781c182c..2fe7ff5b 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.go
@@ -7,16 +7,15 @@
 package api
 
 import (
-	reflect "reflect"
-	sync "sync"
-	unsafe "unsafe"
-
 	_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
 	api "github.com/runtime-radar/runtime-radar/event-processor/api"
 	_ "google.golang.org/genproto/googleapis/api/annotations"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+	reflect "reflect"
+	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.gw.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.gw.go
index ab660ffd..6a777296 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.gw.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,218 +25,166 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_RuntimeHistory_Read_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeHistoryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ReadRuntimeEventReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ReadRuntimeEventReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["id"]
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["id"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
 	}
-
 	protoReq.Id, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
 	}
-
 	msg, err := client.Read(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RuntimeHistory_Read_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeHistoryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ReadRuntimeEventReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ReadRuntimeEventReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["id"]
+	val, ok := pathParams["id"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
 	}
-
 	protoReq.Id, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
 	}
-
 	msg, err := server.Read(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RuntimeHistory_ListRuntimeEventSlice_0 = &utilities.DoubleArray{Encoding: map[string]int{"direction": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
-)
+var filter_RuntimeHistory_ListRuntimeEventSlice_0 = &utilities.DoubleArray{Encoding: map[string]int{"direction": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_RuntimeHistory_ListRuntimeEventSlice_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeHistoryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListRuntimeEventSliceReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListRuntimeEventSliceReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["direction"]
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["direction"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "direction")
 	}
-
 	protoReq.Direction, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "direction", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeHistory_ListRuntimeEventSlice_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ListRuntimeEventSlice(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RuntimeHistory_ListRuntimeEventSlice_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeHistoryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ListRuntimeEventSliceReq
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ListRuntimeEventSliceReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["direction"]
+	val, ok := pathParams["direction"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "direction")
 	}
-
 	protoReq.Direction, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "direction", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeHistory_ListRuntimeEventSlice_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ListRuntimeEventSlice(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_RuntimeHistory_FilterRuntimeEventSlice_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeHistoryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq FilterRuntimeEventSliceReq
-	var metadata runtime.ServerMetadata
-
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq FilterRuntimeEventSliceReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["direction"]
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
+	val, ok := pathParams["direction"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "direction")
 	}
-
 	protoReq.Direction, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "direction", err)
 	}
-
 	msg, err := client.FilterRuntimeEventSlice(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RuntimeHistory_FilterRuntimeEventSlice_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeHistoryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq FilterRuntimeEventSliceReq
-	var metadata runtime.ServerMetadata
-
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq FilterRuntimeEventSliceReq
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["direction"]
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	val, ok := pathParams["direction"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "direction")
 	}
-
 	protoReq.Direction, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "direction", err)
 	}
-
 	msg, err := server.FilterRuntimeEventSlice(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterRuntimeHistoryHandlerServer registers the http handlers for service RuntimeHistory to "mux".
 // UnaryRPC     :call RuntimeHistoryServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterRuntimeHistoryHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterRuntimeHistoryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server RuntimeHistoryServer) error {
-
-	mux.Handle("GET", pattern_RuntimeHistory_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeHistory_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/Read", runtime.WithHTTPPathPattern("/api/v1/runtime-event/{id}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/Read", runtime.WithHTTPPathPattern("/api/v1/runtime-event/{id}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -247,20 +196,15 @@ func RegisterRuntimeHistoryHandlerServer(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RuntimeHistory_ListRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeHistory_ListRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/ListRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/slice/{direction}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/ListRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/slice/{direction}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -272,20 +216,15 @@ func RegisterRuntimeHistoryHandlerServer(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_ListRuntimeEventSlice_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_RuntimeHistory_FilterRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RuntimeHistory_FilterRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/FilterRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/by-filter/slice/{direction}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_history.RuntimeHistory/FilterRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/by-filter/slice/{direction}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -297,9 +236,7 @@ func RegisterRuntimeHistoryHandlerServer(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_FilterRuntimeEventSlice_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -308,25 +245,24 @@ func RegisterRuntimeHistoryHandlerServer(ctx context.Context, mux *runtime.Serve
 // RegisterRuntimeHistoryHandlerFromEndpoint is same as RegisterRuntimeHistoryHandler but
 // automatically dials to "endpoint" and closes the connection when "ctx" gets done.
 func RegisterRuntimeHistoryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
-	conn, err := grpc.Dial(endpoint, opts...)
+	conn, err := grpc.NewClient(endpoint, opts...)
 	if err != nil {
 		return err
 	}
 	defer func() {
 		if err != nil {
 			if cerr := conn.Close(); cerr != nil {
-				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
 			}
 			return
 		}
 		go func() {
 			<-ctx.Done()
 			if cerr := conn.Close(); cerr != nil {
-				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
 			}
 		}()
 	}()
-
 	return RegisterRuntimeHistoryHandler(ctx, mux, conn)
 }
 
@@ -340,16 +276,13 @@ func RegisterRuntimeHistoryHandler(ctx context.Context, mux *runtime.ServeMux, c
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "RuntimeHistoryClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "RuntimeHistoryClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "RuntimeHistoryClient" to call the correct interceptors.
+// "RuntimeHistoryClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterRuntimeHistoryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client RuntimeHistoryClient) error {
-
-	mux.Handle("GET", pattern_RuntimeHistory_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeHistory_Read_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/Read", runtime.WithHTTPPathPattern("/api/v1/runtime-event/{id}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/Read", runtime.WithHTTPPathPattern("/api/v1/runtime-event/{id}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -360,18 +293,13 @@ func RegisterRuntimeHistoryHandlerClient(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_Read_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RuntimeHistory_ListRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeHistory_ListRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/ListRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/slice/{direction}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/ListRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/slice/{direction}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -382,18 +310,13 @@ func RegisterRuntimeHistoryHandlerClient(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_ListRuntimeEventSlice_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_RuntimeHistory_FilterRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RuntimeHistory_FilterRuntimeEventSlice_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/FilterRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/by-filter/slice/{direction}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_history.RuntimeHistory/FilterRuntimeEventSlice", runtime.WithHTTPPathPattern("/api/v1/runtime-event/by-filter/slice/{direction}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -404,26 +327,19 @@ func RegisterRuntimeHistoryHandlerClient(ctx context.Context, mux *runtime.Serve
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeHistory_FilterRuntimeEventSlice_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_RuntimeHistory_Read_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "runtime-event", "id"}, ""))
-
-	pattern_RuntimeHistory_ListRuntimeEventSlice_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "runtime-event", "slice", "direction"}, ""))
-
+	pattern_RuntimeHistory_Read_0                    = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "runtime-event", "id"}, ""))
+	pattern_RuntimeHistory_ListRuntimeEventSlice_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"api", "v1", "runtime-event", "slice", "direction"}, ""))
 	pattern_RuntimeHistory_FilterRuntimeEventSlice_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "runtime-event", "by-filter", "slice", "direction"}, ""))
 )
 
 var (
-	forward_RuntimeHistory_Read_0 = runtime.ForwardResponseMessage
-
-	forward_RuntimeHistory_ListRuntimeEventSlice_0 = runtime.ForwardResponseMessage
-
+	forward_RuntimeHistory_Read_0                    = runtime.ForwardResponseMessage
+	forward_RuntimeHistory_ListRuntimeEventSlice_0   = runtime.ForwardResponseMessage
 	forward_RuntimeHistory_FilterRuntimeEventSlice_0 = runtime.ForwardResponseMessage
 )
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history_grpc.pb.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history_grpc.pb.go
index db96e33e..12801adc 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history_grpc.pb.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_history_grpc.pb.go
@@ -8,7 +8,6 @@ package api
 
 import (
 	context "context"
-
 	api "github.com/runtime-radar/runtime-radar/event-processor/api"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_stats.pb.gw.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_stats.pb.gw.go
index e10d722c..87be0983 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_stats.pb.gw.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/history-api/api/runtime_stats.pb.gw.go
@@ -10,6 +10,7 @@ package api
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,64 +25,64 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
-
 var (
-	filter_RuntimeStats_CountEvents_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
 )
 
-func request_RuntimeStats_CountEvents_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeStatsClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq RuntimeEventsCounterReq
-	var metadata runtime.ServerMetadata
+var filter_RuntimeStats_CountEvents_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
+func request_RuntimeStats_CountEvents_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeStatsClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq RuntimeEventsCounterReq
+		metadata runtime.ServerMetadata
+	)
+	if req.Body != nil {
+		_, _ = io.Copy(io.Discard, req.Body)
+	}
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeStats_CountEvents_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.CountEvents(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RuntimeStats_CountEvents_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeStatsServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq RuntimeEventsCounterReq
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq RuntimeEventsCounterReq
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeStats_CountEvents_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.CountEvents(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterRuntimeStatsHandlerServer registers the http handlers for service RuntimeStats to "mux".
 // UnaryRPC     :call RuntimeStatsServer directly.
 // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterRuntimeStatsHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterRuntimeStatsHandlerServer(ctx context.Context, mux *runtime.ServeMux, server RuntimeStatsServer) error {
-
-	mux.Handle("GET", pattern_RuntimeStats_CountEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeStats_CountEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_stats.RuntimeStats/CountEvents", runtime.WithHTTPPathPattern("/api/v1/stats/runtime-event/count"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/runtime_stats.RuntimeStats/CountEvents", runtime.WithHTTPPathPattern("/api/v1/stats/runtime-event/count"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -93,9 +94,7 @@ func RegisterRuntimeStatsHandlerServer(ctx context.Context, mux *runtime.ServeMu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeStats_CountEvents_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -104,25 +103,24 @@ func RegisterRuntimeStatsHandlerServer(ctx context.Context, mux *runtime.ServeMu
 // RegisterRuntimeStatsHandlerFromEndpoint is same as RegisterRuntimeStatsHandler but
 // automatically dials to "endpoint" and closes the connection when "ctx" gets done.
 func RegisterRuntimeStatsHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
-	conn, err := grpc.Dial(endpoint, opts...)
+	conn, err := grpc.NewClient(endpoint, opts...)
 	if err != nil {
 		return err
 	}
 	defer func() {
 		if err != nil {
 			if cerr := conn.Close(); cerr != nil {
-				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
 			}
 			return
 		}
 		go func() {
 			<-ctx.Done()
 			if cerr := conn.Close(); cerr != nil {
-				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
 			}
 		}()
 	}()
-
 	return RegisterRuntimeStatsHandler(ctx, mux, conn)
 }
 
@@ -136,16 +134,13 @@ func RegisterRuntimeStatsHandler(ctx context.Context, mux *runtime.ServeMux, con
 // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "RuntimeStatsClient".
 // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "RuntimeStatsClient"
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "RuntimeStatsClient" to call the correct interceptors.
+// "RuntimeStatsClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterRuntimeStatsHandlerClient(ctx context.Context, mux *runtime.ServeMux, client RuntimeStatsClient) error {
-
-	mux.Handle("GET", pattern_RuntimeStats_CountEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RuntimeStats_CountEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/runtime_stats.RuntimeStats/CountEvents", runtime.WithHTTPPathPattern("/api/v1/stats/runtime-event/count"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/runtime_stats.RuntimeStats/CountEvents", runtime.WithHTTPPathPattern("/api/v1/stats/runtime-event/count"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -156,11 +151,8 @@ func RegisterRuntimeStatsHandlerClient(ctx context.Context, mux *runtime.ServeMu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RuntimeStats_CountEvents_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
index fb4087d9..3604294e 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
@@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
+func (jt JSONTime) String() string {
+	return time.Time(jt).String()
+}
+
 type Token struct {
 	Username              string    `json:"username"`
 	UserID                string    `json:"user_id"`
@@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) {
 		return nil, errors.New("unknown authorization format")
 	}
 
-	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) {
+	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) {
 		return key, nil
 	})
 	if err != nil {
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
index 79432fec..24b0d6e3 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
@@ -27,7 +27,7 @@ func SetReady() {
 }
 
 // ReadyHandler handles ready probes.
-func ReadyHandler(w http.ResponseWriter, r *http.Request) {
+func ReadyHandler(w http.ResponseWriter, _ *http.Request) {
 	if IsReady() {
 		// Make it simple: do nothing and have 200 OK
 		return
@@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // LiveHandler handles live probes.
-func LiveHandler(w http.ResponseWriter, r *http.Request) {
+func LiveHandler(http.ResponseWriter, *http.Request) {
 	// Make it simple: do nothing and have 200 OK
 }
diff --git a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
index cb9487d6..822eb440 100644
--- a/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
+++ b/public-api/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
@@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
 
 const CorrelationHeader = "correlation-id"
 
-func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	var corrID string
 
 	md, ok := metadata.FromIncomingContext(ctx)
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/.envrc b/public-api/vendor/github.com/sagikazarmark/locafero/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/public-api/vendor/github.com/sagikazarmark/locafero/.envrc
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/finder.go b/public-api/vendor/github.com/sagikazarmark/locafero/finder.go
index 754c8b26..ef8d5471 100644
--- a/public-api/vendor/github.com/sagikazarmark/locafero/finder.go
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/finder.go
@@ -27,7 +27,7 @@ type Finder struct {
 	// It provides the capability to search for entries with depth,
 	// meaning it can target deeper locations within the directory structure.
 	//
-	// It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns.
+	// It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns.
 	//
 	// Examples:
 	//   - config.yaml
@@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 			// pool.Go(func() ([]string, error) {
 			// 	// If the name contains any glob character, perform a glob match
-			// 	if strings.ContainsAny(searchName, "*?[]\\^") {
+			// 	if strings.ContainsAny(searchName, globMatch) {
 			// 		return globWalkSearch(fsys, searchPath, searchName, f.Type)
 			// 	}
 			//
@@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) {
 
 	allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
 		// If the name contains any glob character, perform a glob match
-		if strings.ContainsAny(item.name, "*?[]\\^") {
+		if strings.ContainsAny(item.name, globMatch) {
 			return globWalkSearch(fsys, item.path, item.name, f.Type)
 		}
 
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/flake.lock b/public-api/vendor/github.com/sagikazarmark/locafero/flake.lock
index 46d28f80..df2a8cce 100644
--- a/public-api/vendor/github.com/sagikazarmark/locafero/flake.lock
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1725907707,
+        "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "2bbbbc468fc02257265a79652a8350651cca495a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
+        "lastModified": 1725234343,
+        "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
+        "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6",
         "type": "github"
       },
       "original": {
@@ -60,11 +138,29 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -82,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -95,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
+      "inputs": {
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
         "nixpkgs": [
           "devenv",
           "nixpkgs"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -153,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
+        "lastModified": 1725233747,
+        "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -187,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-23.05",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1694343207,
-        "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1725910328,
+        "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "78058d810644f5ed276804ce7ea9e82d92bee293",
+        "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4",
         "type": "github"
       },
       "original": {
@@ -217,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -232,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -249,7 +433,7 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
       }
     },
     "systems": {
@@ -266,6 +450,21 @@
         "repo": "default",
         "type": "github"
       }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/flake.nix b/public-api/vendor/github.com/sagikazarmark/locafero/flake.nix
index 209ecf28..312f1ec8 100644
--- a/public-api/vendor/github.com/sagikazarmark/locafero/flake.nix
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.lib.mkDefault pkgs.go_1_23;
             };
 
             packages = with pkgs; [
@@ -34,11 +35,27 @@
 
           ci = devenv.shells.default;
 
-          ci_1_20 = {
+          ci_1_21 = {
             imports = [ devenv.shells.ci ];
 
             languages = {
-              go.package = pkgs.go_1_20;
+              go.package = pkgs.go_1_21;
+            };
+          };
+
+          ci_1_22 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_22;
+            };
+          };
+
+          ci_1_23 = {
+            imports = [ devenv.shells.ci ];
+
+            languages = {
+              go.package = pkgs.go_1_23;
             };
           };
         };
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/glob.go b/public-api/vendor/github.com/sagikazarmark/locafero/glob.go
new file mode 100644
index 00000000..00f833e9
--- /dev/null
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/glob.go
@@ -0,0 +1,5 @@
+//go:build !windows
+
+package locafero
+
+const globMatch = "*?[]\\^"
diff --git a/public-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/public-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go
new file mode 100644
index 00000000..7aec2b24
--- /dev/null
+++ b/public-api/vendor/github.com/sagikazarmark/locafero/glob_windows.go
@@ -0,0 +1,8 @@
+//go:build windows
+
+package locafero
+
+// See [filepath.Match]:
+//
+//	On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
+const globMatch = "*?[]^"
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/public-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
deleted file mode 100644
index 1fb0e1be..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/.editorconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.nix]
-indent_size = 2
-
-[{Makefile,*.mk}]
-indent_style = tab
-
-[Taskfile.yaml]
-indent_size = 2
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/.envrc b/public-api/vendor/github.com/sagikazarmark/slog-shim/.envrc
deleted file mode 100644
index 3ce7171a..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/.envrc
+++ /dev/null
@@ -1,4 +0,0 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
-fi
-use flake . --impure
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/public-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore
deleted file mode 100644
index dc6d8b58..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/.devenv/
-/.direnv/
-/.task/
-/build/
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/public-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE
deleted file mode 100644
index 6a66aea5..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/README.md b/public-api/vendor/github.com/sagikazarmark/slog-shim/README.md
deleted file mode 100644
index 1f5be85e..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# [slog](https://pkg.go.dev/log/slog) shim
-
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml)
-[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square)
-[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org)
-
-Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library.
-Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately,
-especially since updating to Go 1.21 is a decision that most libraries won't make overnight.
-
-Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog).
-While it's generally advised against using experimental packages in production,
-this one served as a sort of backport package for the last few years,
-incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`).
-
-This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`.
-
-**How does it achieve backwards compatibility?**
-
-Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is.
-(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.)
-
-This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`.
-Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly.
-
-For older Go versions, the library might become unstable after removing the shim.
-However, since those older versions are no longer supported, the promise of backward compatibility remains intact.
-
-## Installation
-
-```shell
-go get github.com/sagikazarmark/slog-shim
-```
-
-## Usage
-
-Import this package into your library and use it in your public API:
-
-```go
-package mylib
-
-import slog "github.com/sagikazarmark/slog-shim"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21):
-
-```go
-package main
-
-import "log/slog"
-
-// OR
-
-import "golang.org/x/exp/slog"
-
-mylib.New(slog.Default())
-```
-
-**Make sure consumers are aware that your API behaves differently on different Go versions.**
-
-Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code:
-
-```diff
-package mylib
-
-- import slog "github.com/sagikazarmark/slog-shim"
-+ import "log/slog"
-
-func New(logger *slog.Logger) MyLib {
-    // ...
-}
-```
-
-## License
-
-The project is licensed under a [BSD-style license](LICENSE).
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/attr.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/attr.go
deleted file mode 100644
index 89608bf3..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/attr.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
deleted file mode 100644
index b6648133..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/attr_120.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// An Attr is a key-value pair.
-type Attr = slog.Attr
-
-// String returns an Attr for a string value.
-func String(key, value string) Attr {
-	return slog.String(key, value)
-}
-
-// Int64 returns an Attr for an int64.
-func Int64(key string, value int64) Attr {
-	return slog.Int64(key, value)
-}
-
-// Int converts an int to an int64 and returns
-// an Attr with that value.
-func Int(key string, value int) Attr {
-	return slog.Int(key, value)
-}
-
-// Uint64 returns an Attr for a uint64.
-func Uint64(key string, v uint64) Attr {
-	return slog.Uint64(key, v)
-}
-
-// Float64 returns an Attr for a floating-point number.
-func Float64(key string, v float64) Attr {
-	return slog.Float64(key, v)
-}
-
-// Bool returns an Attr for a bool.
-func Bool(key string, v bool) Attr {
-	return slog.Bool(key, v)
-}
-
-// Time returns an Attr for a time.Time.
-// It discards the monotonic portion.
-func Time(key string, v time.Time) Attr {
-	return slog.Time(key, v)
-}
-
-// Duration returns an Attr for a time.Duration.
-func Duration(key string, v time.Duration) Attr {
-	return slog.Duration(key, v)
-}
-
-// Group returns an Attr for a Group Value.
-// The first argument is the key; the remaining arguments
-// are converted to Attrs as in [Logger.Log].
-//
-// Use Group to collect several key-value pairs under a single
-// key on a log line, or as the result of LogValue
-// in order to log a single value as multiple Attrs.
-func Group(key string, args ...any) Attr {
-	return slog.Group(key, args...)
-}
-
-// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
-func Any(key string, value any) Attr {
-	return slog.Any(key, value)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock
deleted file mode 100644
index 7e8898e9..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.lock
+++ /dev/null
@@ -1,273 +0,0 @@
-{
-  "nodes": {
-    "devenv": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nix": "nix",
-        "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
-      },
-      "locked": {
-        "lastModified": 1694097209,
-        "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=",
-        "owner": "cachix",
-        "repo": "devenv",
-        "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "devenv",
-        "type": "github"
-      }
-    },
-    "flake-compat": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1673956053,
-        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-parts": {
-      "inputs": {
-        "nixpkgs-lib": "nixpkgs-lib"
-      },
-      "locked": {
-        "lastModified": 1693611461,
-        "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "flake-parts",
-        "type": "github"
-      }
-    },
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "gitignore": {
-      "inputs": {
-        "nixpkgs": [
-          "devenv",
-          "pre-commit-hooks",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "type": "github"
-      }
-    },
-    "lowdown-src": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
-        "type": "github"
-      },
-      "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "type": "github"
-      }
-    },
-    "nix": {
-      "inputs": {
-        "lowdown-src": "lowdown-src",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-regression": "nixpkgs-regression"
-      },
-      "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
-        "owner": "domenkozar",
-        "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
-        "type": "github"
-      },
-      "original": {
-        "owner": "domenkozar",
-        "ref": "relaxed-flakes",
-        "repo": "nix",
-        "type": "github"
-      }
-    },
-    "nixpkgs": {
-      "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-lib": {
-      "locked": {
-        "dir": "lib",
-        "lastModified": 1693471703,
-        "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
-        "type": "github"
-      },
-      "original": {
-        "dir": "lib",
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-regression": {
-      "locked": {
-        "lastModified": 1643052045,
-        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
-        "type": "github"
-      }
-    },
-    "nixpkgs-stable": {
-      "locked": {
-        "lastModified": 1685801374,
-        "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-23.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1694345580,
-        "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "master",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": [
-          "devenv",
-          "flake-compat"
-        ],
-        "flake-utils": "flake-utils",
-        "gitignore": "gitignore",
-        "nixpkgs": [
-          "devenv",
-          "nixpkgs"
-        ],
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1688056373,
-        "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
-    "root": {
-      "inputs": {
-        "devenv": "devenv",
-        "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    }
-  },
-  "root": "root",
-  "version": 7
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix
deleted file mode 100644
index 7239bbc2..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/flake.nix
+++ /dev/null
@@ -1,57 +0,0 @@
-{
-  inputs = {
-    # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
-    nixpkgs.url = "github:NixOS/nixpkgs/master";
-    flake-parts.url = "github:hercules-ci/flake-parts";
-    devenv.url = "github:cachix/devenv";
-  };
-
-  outputs = inputs@{ flake-parts, ... }:
-    flake-parts.lib.mkFlake { inherit inputs; } {
-      imports = [
-        inputs.devenv.flakeModule
-      ];
-
-      systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
-
-      perSystem = { config, self', inputs', pkgs, system, ... }: rec {
-        devenv.shells = {
-          default = {
-            languages = {
-              go.enable = true;
-              go.package = pkgs.lib.mkDefault pkgs.go_1_21;
-            };
-
-            # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
-            containers = pkgs.lib.mkForce { };
-          };
-
-          ci = devenv.shells.default;
-
-          ci_1_19 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_19;
-            };
-          };
-
-          ci_1_20 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_20;
-            };
-          };
-
-          ci_1_21 = {
-            imports = [ devenv.shells.ci ];
-
-            languages = {
-              go.package = pkgs.go_1_21;
-            };
-          };
-        };
-      };
-    };
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/handler.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/handler.go
deleted file mode 100644
index f55556ae..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/handler.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
deleted file mode 100644
index 67005757..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/handler_120.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Handler handles log records produced by a Logger..
-//
-// A typical handler may print log records to standard error,
-// or write them to a file or database, or perhaps augment them
-// with additional attributes and pass them on to another handler.
-//
-// Any of the Handler's methods may be called concurrently with itself
-// or with other methods. It is the responsibility of the Handler to
-// manage this concurrency.
-//
-// Users of the slog package should not invoke Handler methods directly.
-// They should use the methods of [Logger] instead.
-type Handler = slog.Handler
-
-// HandlerOptions are options for a TextHandler or JSONHandler.
-// A zero HandlerOptions consists entirely of default values.
-type HandlerOptions = slog.HandlerOptions
-
-// Keys for "built-in" attributes.
-const (
-	// TimeKey is the key used by the built-in handlers for the time
-	// when the log method is called. The associated Value is a [time.Time].
-	TimeKey = slog.TimeKey
-	// LevelKey is the key used by the built-in handlers for the level
-	// of the log call. The associated value is a [Level].
-	LevelKey = slog.LevelKey
-	// MessageKey is the key used by the built-in handlers for the
-	// message of the log call. The associated value is a string.
-	MessageKey = slog.MessageKey
-	// SourceKey is the key used by the built-in handlers for the source file
-	// and line of the log call. The associated value is a string.
-	SourceKey = slog.SourceKey
-)
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
deleted file mode 100644
index 7c22bd81..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
deleted file mode 100644
index 7b14f10b..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// JSONHandler is a Handler that writes Records to an io.Writer as
-// line-delimited JSON objects.
-type JSONHandler = slog.JSONHandler
-
-// NewJSONHandler creates a JSONHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {
-	return slog.NewJSONHandler(w, opts)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/level.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/level.go
deleted file mode 100644
index 07288cf8..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/level.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go
deleted file mode 100644
index d3feb942..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/level_120.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"golang.org/x/exp/slog"
-)
-
-// A Level is the importance or severity of a log event.
-// The higher the level, the more important or severe the event.
-type Level = slog.Level
-
-// Level numbers are inherently arbitrary,
-// but we picked them to satisfy three constraints.
-// Any system can map them to another numbering scheme if it wishes.
-//
-// First, we wanted the default level to be Info, Since Levels are ints, Info is
-// the default value for int, zero.
-//
-// Second, we wanted to make it easy to use levels to specify logger verbosity.
-// Since a larger level means a more severe event, a logger that accepts events
-// with smaller (or more negative) level means a more verbose logger. Logger
-// verbosity is thus the negation of event severity, and the default verbosity
-// of 0 accepts all events at least as severe as INFO.
-//
-// Third, we wanted some room between levels to accommodate schemes with named
-// levels between ours. For example, Google Cloud Logging defines a Notice level
-// between Info and Warn. Since there are only a few of these intermediate
-// levels, the gap between the numbers need not be large. Our gap of 4 matches
-// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the
-// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog
-// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog
-// does not. But those OpenTelemetry levels can still be represented as slog
-// Levels by using the appropriate integers.
-//
-// Names for common levels.
-const (
-	LevelDebug Level = slog.LevelDebug
-	LevelInfo  Level = slog.LevelInfo
-	LevelWarn  Level = slog.LevelWarn
-	LevelError Level = slog.LevelError
-)
-
-// A LevelVar is a Level variable, to allow a Handler level to change
-// dynamically.
-// It implements Leveler as well as a Set method,
-// and it is safe for use by multiple goroutines.
-// The zero LevelVar corresponds to LevelInfo.
-type LevelVar = slog.LevelVar
-
-// A Leveler provides a Level value.
-//
-// As Level itself implements Leveler, clients typically supply
-// a Level value wherever a Leveler is needed, such as in HandlerOptions.
-// Clients who need to vary the level dynamically can provide a more complex
-// Leveler implementation such as *LevelVar.
-type Leveler = slog.Leveler
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/logger.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/logger.go
deleted file mode 100644
index e80036be..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/logger.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-	"log/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
deleted file mode 100644
index 97ebdd5e..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/logger_120.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"context"
-	"log"
-
-	"golang.org/x/exp/slog"
-)
-
-// Default returns the default Logger.
-func Default() *Logger { return slog.Default() }
-
-// SetDefault makes l the default Logger.
-// After this call, output from the log package's default Logger
-// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler.
-func SetDefault(l *Logger) {
-	slog.SetDefault(l)
-}
-
-// A Logger records structured information about each call to its
-// Log, Debug, Info, Warn, and Error methods.
-// For each call, it creates a Record and passes it to a Handler.
-//
-// To create a new Logger, call [New] or a Logger method
-// that begins "With".
-type Logger = slog.Logger
-
-// New creates a new Logger with the given non-nil Handler.
-func New(h Handler) *Logger {
-	return slog.New(h)
-}
-
-// With calls Logger.With on the default logger.
-func With(args ...any) *Logger {
-	return slog.With(args...)
-}
-
-// NewLogLogger returns a new log.Logger such that each call to its Output method
-// dispatches a Record to the specified handler. The logger acts as a bridge from
-// the older log API to newer structured logging handlers.
-func NewLogLogger(h Handler, level Level) *log.Logger {
-	return slog.NewLogLogger(h, level)
-}
-
-// Debug calls Logger.Debug on the default logger.
-func Debug(msg string, args ...any) {
-	slog.Debug(msg, args...)
-}
-
-// DebugContext calls Logger.DebugContext on the default logger.
-func DebugContext(ctx context.Context, msg string, args ...any) {
-	slog.DebugContext(ctx, msg, args...)
-}
-
-// Info calls Logger.Info on the default logger.
-func Info(msg string, args ...any) {
-	slog.Info(msg, args...)
-}
-
-// InfoContext calls Logger.InfoContext on the default logger.
-func InfoContext(ctx context.Context, msg string, args ...any) {
-	slog.InfoContext(ctx, msg, args...)
-}
-
-// Warn calls Logger.Warn on the default logger.
-func Warn(msg string, args ...any) {
-	slog.Warn(msg, args...)
-}
-
-// WarnContext calls Logger.WarnContext on the default logger.
-func WarnContext(ctx context.Context, msg string, args ...any) {
-	slog.WarnContext(ctx, msg, args...)
-}
-
-// Error calls Logger.Error on the default logger.
-func Error(msg string, args ...any) {
-	slog.Error(msg, args...)
-}
-
-// ErrorContext calls Logger.ErrorContext on the default logger.
-func ErrorContext(ctx context.Context, msg string, args ...any) {
-	slog.ErrorContext(ctx, msg, args...)
-}
-
-// Log calls Logger.Log on the default logger.
-func Log(ctx context.Context, level Level, msg string, args ...any) {
-	slog.Log(ctx, level, msg, args...)
-}
-
-// LogAttrs calls Logger.LogAttrs on the default logger.
-func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
-	slog.LogAttrs(ctx, level, msg, attrs...)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/record.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/record.go
deleted file mode 100644
index 85ad1f78..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/record.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go
deleted file mode 100644
index c2eaf4e7..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/record_120.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Record holds information about a log event.
-// Copies of a Record share state.
-// Do not modify a Record after handing out a copy to it.
-// Call [NewRecord] to create a new Record.
-// Use [Record.Clone] to create a copy with no shared state.
-type Record = slog.Record
-
-// NewRecord creates a Record from the given arguments.
-// Use [Record.AddAttrs] to add attributes to the Record.
-//
-// NewRecord is intended for logging APIs that want to support a [Handler] as
-// a backend.
-func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record {
-	return slog.NewRecord(t, level, msg, pc)
-}
-
-// Source describes the location of a line of source code.
-type Source = slog.Source
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
deleted file mode 100644
index 45f6cfcb..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"io"
-	"log/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
deleted file mode 100644
index a69d63cc..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"io"
-
-	"golang.org/x/exp/slog"
-)
-
-// TextHandler is a Handler that writes Records to an io.Writer as a
-// sequence of key=value pairs separated by spaces and followed by a newline.
-type TextHandler = slog.TextHandler
-
-// NewTextHandler creates a TextHandler that writes to w,
-// using the given options.
-// If opts is nil, the default options are used.
-func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
-	return slog.NewTextHandler(w, opts)
-}
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/value.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/value.go
deleted file mode 100644
index 61173eb9..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/value.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-
-package slog
-
-import (
-	"log/slog"
-	"time"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/public-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/public-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go
deleted file mode 100644
index 0f9f871e..00000000
--- a/public-api/vendor/github.com/sagikazarmark/slog-shim/value_120.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.21
-
-package slog
-
-import (
-	"time"
-
-	"golang.org/x/exp/slog"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value = slog.Value
-
-// Kind is the kind of a Value.
-type Kind = slog.Kind
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-const (
-	KindAny       = slog.KindAny
-	KindBool      = slog.KindBool
-	KindDuration  = slog.KindDuration
-	KindFloat64   = slog.KindFloat64
-	KindInt64     = slog.KindInt64
-	KindString    = slog.KindString
-	KindTime      = slog.KindTime
-	KindUint64    = slog.KindUint64
-	KindGroup     = slog.KindGroup
-	KindLogValuer = slog.KindLogValuer
-)
-
-//////////////// Constructors
-
-// StringValue returns a new Value for a string.
-func StringValue(value string) Value {
-	return slog.StringValue(value)
-}
-
-// IntValue returns a Value for an int.
-func IntValue(v int) Value {
-	return slog.IntValue(v)
-}
-
-// Int64Value returns a Value for an int64.
-func Int64Value(v int64) Value {
-	return slog.Int64Value(v)
-}
-
-// Uint64Value returns a Value for a uint64.
-func Uint64Value(v uint64) Value {
-	return slog.Uint64Value(v)
-}
-
-// Float64Value returns a Value for a floating-point number.
-func Float64Value(v float64) Value {
-	return slog.Float64Value(v)
-}
-
-// BoolValue returns a Value for a bool.
-func BoolValue(v bool) Value {
-	return slog.BoolValue(v)
-}
-
-// TimeValue returns a Value for a time.Time.
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
-	return slog.TimeValue(v)
-}
-
-// DurationValue returns a Value for a time.Duration.
-func DurationValue(v time.Duration) Value {
-	return slog.DurationValue(v)
-}
-
-// GroupValue returns a new Value for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
-	return slog.GroupValue(as...)
-}
-
-// AnyValue returns a Value for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// String, Bool, Uint64, Int64, or Float64. The width of the
-// original numeric type is not preserved.
-//
-// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
-// KindTime or KindDuration. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind KindAny.
-func AnyValue(v any) Value {
-	return slog.AnyValue(v)
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer = slog.LogValuer
diff --git a/public-api/vendor/github.com/spf13/cast/README.md b/public-api/vendor/github.com/spf13/cast/README.md
index 58141f02..1be666a4 100644
--- a/public-api/vendor/github.com/spf13/cast/README.md
+++ b/public-api/vendor/github.com/spf13/cast/README.md
@@ -1,9 +1,9 @@
 # cast
 
-[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml)
+[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast)
 ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
-[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast)
+[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast)
 
 Easy and safe casting from one type to another in Go
 
diff --git a/public-api/vendor/github.com/spf13/cast/caste.go b/public-api/vendor/github.com/spf13/cast/caste.go
index d49bbf83..4181a2e7 100644
--- a/public-api/vendor/github.com/spf13/cast/caste.go
+++ b/public-api/vendor/github.com/spf13/cast/caste.go
@@ -18,6 +18,14 @@ import (
 
 var errNegativeNotAllowed = errors.New("unable to cast negative value")
 
+type float64EProvider interface {
+	Float64() (float64, error)
+}
+
+type float64Provider interface {
+	Float64() float64
+}
+
 // ToTimeE casts an interface to a time.Time type.
 func ToTimeE(i interface{}) (tim time.Time, err error) {
 	return ToTimeInDefaultLocationE(i, time.UTC)
@@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
 			d, err = time.ParseDuration(s + "ns")
 		}
 		return
-	case json.Number:
+	case float64EProvider:
 		var v float64
 		v, err = s.Float64()
 		d = time.Duration(v)
 		return
+	case float64Provider:
+		d = time.Duration(s.Float64())
+		return
 	default:
 		err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
 		return
@@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
+	case float64Provider:
+		return s.Float64(), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
-	case json.Number:
+	case float64EProvider:
 		v, err := s.Float64()
 		if err == nil {
 			return float32(v), nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
+	case float64Provider:
+		return float32(s.Float64()), nil
 	case bool:
 		if s {
 			return 1, nil
@@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) {
 
 	switch s := i.(type) {
 	case string:
-		v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
+		v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0)
 		if err == nil {
 			if v < 0 {
 				return 0, errNegativeNotAllowed
 			}
-			return uint64(v), nil
+			return v, nil
 		}
 		return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
 	case json.Number:
@@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
 		return nil
 	}
 
-	var errorType = reflect.TypeOf((*error)(nil)).Elem()
-	var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+	errorType := reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
 
 	v := reflect.ValueOf(a)
 	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
@@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
 
 // ToStringMapStringE casts an interface to a map[string]string type.
 func ToStringMapStringE(i interface{}) (map[string]string, error) {
-	var m = map[string]string{}
+	m := map[string]string{}
 
 	switch v := i.(type) {
 	case map[string]string:
@@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
 
 // ToStringMapStringSliceE casts an interface to a map[string][]string type.
 func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
-	var m = map[string][]string{}
+	m := map[string][]string{}
 
 	switch v := i.(type) {
 	case map[string][]string:
@@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
 
 // ToStringMapBoolE casts an interface to a map[string]bool type.
 func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
-	var m = map[string]bool{}
+	m := map[string]bool{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
 
 // ToStringMapE casts an interface to a map[string]interface{} type.
 func ToStringMapE(i interface{}) (map[string]interface{}, error) {
-	var m = map[string]interface{}{}
+	m := map[string]interface{}{}
 
 	switch v := i.(type) {
 	case map[interface{}]interface{}:
@@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
 
 // ToStringMapIntE casts an interface to a map[string]int{} type.
 func ToStringMapIntE(i interface{}) (map[string]int, error) {
-	var m = map[string]int{}
+	m := map[string]int{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
 	}
@@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
 
 // ToStringMapInt64E casts an interface to a map[string]int64{} type.
 func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
-	var m = map[string]int64{}
+	m := map[string]int64{}
 	if i == nil {
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
 	}
@@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
 	return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
 }
 
-var (
-	timeFormats = []timeFormat{
-		// Keep common formats at the top.
-		{"2006-01-02", timeFormatNoTimezone},
-		{time.RFC3339, timeFormatNumericTimezone},
-		{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
-		{time.RFC1123Z, timeFormatNumericTimezone},
-		{time.RFC1123, timeFormatNamedTimezone},
-		{time.RFC822Z, timeFormatNumericTimezone},
-		{time.RFC822, timeFormatNamedTimezone},
-		{time.RFC850, timeFormatNamedTimezone},
-		{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
-		{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
-		{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
-		{"2006-01-02 15:04:05", timeFormatNoTimezone},
-		{time.ANSIC, timeFormatNoTimezone},
-		{time.UnixDate, timeFormatNamedTimezone},
-		{time.RubyDate, timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
-		{"02 Jan 2006", timeFormatNoTimezone},
-		{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
-		{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
-		{time.Kitchen, timeFormatTimeOnly},
-		{time.Stamp, timeFormatTimeOnly},
-		{time.StampMilli, timeFormatTimeOnly},
-		{time.StampMicro, timeFormatTimeOnly},
-		{time.StampNano, timeFormatTimeOnly},
-	}
-)
+var timeFormats = []timeFormat{
+	// Keep common formats at the top.
+	{"2006-01-02", timeFormatNoTimezone},
+	{time.RFC3339, timeFormatNumericTimezone},
+	{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
+	{time.RFC1123Z, timeFormatNumericTimezone},
+	{time.RFC1123, timeFormatNamedTimezone},
+	{time.RFC822Z, timeFormatNumericTimezone},
+	{time.RFC822, timeFormatNamedTimezone},
+	{time.RFC850, timeFormatNamedTimezone},
+	{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
+	{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
+	{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
+	{"2006-01-02 15:04:05", timeFormatNoTimezone},
+	{time.ANSIC, timeFormatNoTimezone},
+	{time.UnixDate, timeFormatNamedTimezone},
+	{time.RubyDate, timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
+	{"02 Jan 2006", timeFormatNoTimezone},
+	{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
+	{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
+	{time.Kitchen, timeFormatTimeOnly},
+	{time.Stamp, timeFormatTimeOnly},
+	{time.StampMilli, timeFormatTimeOnly},
+	{time.StampMicro, timeFormatTimeOnly},
+	{time.StampNano, timeFormatTimeOnly},
+}
 
 func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
-
 	for _, format := range formats {
 		if d, e = time.Parse(format.format, s); e == nil {
 
diff --git a/public-api/vendor/github.com/spf13/pflag/README.md b/public-api/vendor/github.com/spf13/pflag/README.md
index 7eacc5bd..388c4e5e 100644
--- a/public-api/vendor/github.com/spf13/pflag/README.md
+++ b/public-api/vendor/github.com/spf13/pflag/README.md
@@ -284,6 +284,33 @@ func main() {
 }
 ```
 
+### Using pflag with go test
+`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`).
+For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details.
+
+For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this:
+```bash
+go test /your/tests -run ^YourTest -v --your-test-pflags
+```
+will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
+To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
+
+**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
+```go
+import (
+	goflag "flag"
+	flag "github.com/spf13/pflag"
+)
+
+var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+
+func main() {
+	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
+    flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
+	flag.Parse()
+}
+```
+
 ## More info
 
 You can see the full reference documentation of the pflag package
diff --git a/public-api/vendor/github.com/spf13/pflag/bool_func.go b/public-api/vendor/github.com/spf13/pflag/bool_func.go
new file mode 100644
index 00000000..83d77afa
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/pflag/bool_func.go
@@ -0,0 +1,40 @@
+package pflag
+
+// -- func Value
+type boolfuncValue func(string) error
+
+func (f boolfuncValue) Set(s string) error { return f(s) }
+
+func (f boolfuncValue) Type() string { return "boolfunc" }
+
+func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+func (f boolfuncValue) IsBoolFlag() bool { return true }
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) {
+	f.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	var val Value = boolfuncValue(fn)
+	flag := f.VarPF(val, name, shorthand, usage)
+	flag.NoOptDefVal = "true"
+}
+
+// BoolFunc defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
+// on the command line.
+func BoolFunc(name string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, "", usage, fn)
+}
+
+// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
+func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.BoolFuncP(name, shorthand, usage, fn)
+}
diff --git a/public-api/vendor/github.com/spf13/pflag/count.go b/public-api/vendor/github.com/spf13/pflag/count.go
index a0b2679f..d49c0143 100644
--- a/public-api/vendor/github.com/spf13/pflag/count.go
+++ b/public-api/vendor/github.com/spf13/pflag/count.go
@@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
 
 // Count defines a count flag with specified name, default value, and usage string.
 // The return value is the address of an int variable that stores the value of the flag.
-// A count flag will add 1 to its value evey time it is found on the command line
+// A count flag will add 1 to its value every time it is found on the command line
 func Count(name string, usage string) *int {
 	return CommandLine.CountP(name, "", usage)
 }
diff --git a/public-api/vendor/github.com/spf13/pflag/errors.go b/public-api/vendor/github.com/spf13/pflag/errors.go
new file mode 100644
index 00000000..ff11b66b
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/pflag/errors.go
@@ -0,0 +1,149 @@
+package pflag
+
+import "fmt"
+
+// notExistErrorMessageType specifies which flavor of "flag does not exist"
+// is printed by NotExistError. This allows the related errors to be grouped
+// under a single NotExistError struct without making a breaking change to
+// the error message text.
+type notExistErrorMessageType int
+
+const (
+	flagNotExistMessage notExistErrorMessageType = iota
+	flagNotDefinedMessage
+	flagNoSuchFlagMessage
+	flagUnknownFlagMessage
+	flagUnknownShorthandFlagMessage
+)
+
+// NotExistError is the error returned when trying to access a flag that
+// does not exist in the FlagSet.
+type NotExistError struct {
+	name                string
+	specifiedShorthands string
+	messageType         notExistErrorMessageType
+}
+
+// Error implements error.
+func (e *NotExistError) Error() string {
+	switch e.messageType {
+	case flagNotExistMessage:
+		return fmt.Sprintf("flag %q does not exist", e.name)
+
+	case flagNotDefinedMessage:
+		return fmt.Sprintf("flag accessed but not defined: %s", e.name)
+
+	case flagNoSuchFlagMessage:
+		return fmt.Sprintf("no such flag -%v", e.name)
+
+	case flagUnknownFlagMessage:
+		return fmt.Sprintf("unknown flag: --%s", e.name)
+
+	case flagUnknownShorthandFlagMessage:
+		c := rune(e.name[0])
+		return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *NotExistError) GetSpecifiedName() string {
+	return e.name
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *NotExistError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// ValueRequiredError is the error returned when a flag needs an argument but
+// no argument was provided.
+type ValueRequiredError struct {
+	flag                *Flag
+	specifiedName       string
+	specifiedShorthands string
+}
+
+// Error implements error.
+func (e *ValueRequiredError) Error() string {
+	if len(e.specifiedShorthands) > 0 {
+		c := rune(e.specifiedName[0])
+		return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
+	}
+
+	return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *ValueRequiredError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetSpecifiedName returns the name of the flag (without dashes) as it
+// appeared in the parsed arguments.
+func (e *ValueRequiredError) GetSpecifiedName() string {
+	return e.specifiedName
+}
+
+// GetSpecifiedShortnames returns the group of shorthand arguments
+// (without dashes) that the flag appeared within. If the flag was not in a
+// shorthand group, this will return an empty string.
+func (e *ValueRequiredError) GetSpecifiedShortnames() string {
+	return e.specifiedShorthands
+}
+
+// InvalidValueError is the error returned when an invalid value is used
+// for a flag.
+type InvalidValueError struct {
+	flag  *Flag
+	value string
+	cause error
+}
+
+// Error implements error.
+func (e *InvalidValueError) Error() string {
+	flag := e.flag
+	var flagName string
+	if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
+		flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
+	} else {
+		flagName = fmt.Sprintf("--%s", flag.Name)
+	}
+	return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
+}
+
+// Unwrap implements errors.Unwrap.
+func (e *InvalidValueError) Unwrap() error {
+	return e.cause
+}
+
+// GetFlag returns the flag for which the error occurred.
+func (e *InvalidValueError) GetFlag() *Flag {
+	return e.flag
+}
+
+// GetValue returns the invalid value that was provided.
+func (e *InvalidValueError) GetValue() string {
+	return e.value
+}
+
+// InvalidSyntaxError is the error returned when a bad flag name is passed on
+// the command line.
+type InvalidSyntaxError struct {
+	specifiedFlag string
+}
+
+// Error implements error.
+func (e *InvalidSyntaxError) Error() string {
+	return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
+}
+
+// GetSpecifiedName returns the exact flag (with dashes) as it
+// appeared in the parsed arguments.
+func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
+	return e.specifiedFlag
+}
diff --git a/public-api/vendor/github.com/spf13/pflag/flag.go b/public-api/vendor/github.com/spf13/pflag/flag.go
index 7c058de3..d4dfbc5e 100644
--- a/public-api/vendor/github.com/spf13/pflag/flag.go
+++ b/public-api/vendor/github.com/spf13/pflag/flag.go
@@ -27,23 +27,32 @@ unaffected.
 Define flags using flag.String(), Bool(), Int(), etc.
 
 This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
+
 	var ip = flag.Int("flagname", 1234, "help message for flagname")
+
 If you like, you can bind the flag to a variable using the Var() functions.
+
 	var flagvar int
 	func init() {
 		flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
 	}
+
 Or you can create custom flags that satisfy the Value interface (with
 pointer receivers) and couple them to flag parsing by
+
 	flag.Var(&flagVal, "name", "help message for flagname")
+
 For such flags, the default value is just the initial value of the variable.
 
 After all flags are defined, call
+
 	flag.Parse()
+
 to parse the command line into the defined flags.
 
 Flags may then be used directly. If you're using the flags themselves,
 they are all pointers; if you bind to variables, they're values.
+
 	fmt.Println("ip has value ", *ip)
 	fmt.Println("flagvar has value ", flagvar)
 
@@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1.
 The pflag package also defines some new functions that are not in flag,
 that give one-letter shorthands for flags. You can use these by appending
 'P' to the name of any function that defines a flag.
+
 	var ip = flag.IntP("flagname", "f", 1234, "help message")
 	var flagvar bool
 	func init() {
 		flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
 	}
 	flag.VarP(&flagval, "varname", "v", "help message")
+
 Shorthand letters can be used with single dashes on the command line.
 Boolean shorthand flags can be combined with other shorthand flags.
 
 Command line flag syntax:
+
 	--flag    // boolean flags only
 	--flag=x
 
 Unlike the flag package, a single dash before an option means something
 different than a double dash. Single dashes signify a series of shorthand
 letters for flags. All but the last shorthand letter must be boolean flags.
+
 	// boolean flags
 	-f
 	-abc
@@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
 func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
 	flag := f.Lookup(name)
 	if flag == nil {
-		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
 		return nil, err
 	}
 
@@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
 func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	if usageMessage == "" {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
 func (f *FlagSet) MarkHidden(name string) error {
 	flag := f.Lookup(name)
 	if flag == nil {
-		return fmt.Errorf("flag %q does not exist", name)
+		return &NotExistError{name: name, messageType: flagNotExistMessage}
 	}
 	flag.Hidden = true
 	return nil
@@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 
 	err := flag.Value.Set(value)
 	if err != nil {
-		var flagName string
-		if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
-			flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
-		} else {
-			flagName = fmt.Sprintf("--%s", flag.Name)
+		return &InvalidValueError{
+			flag:  flag,
+			value: value,
+			cause: err,
 		}
-		return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
 	}
 
 	if !flag.Changed {
@@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
 	normalName := f.normalizeFlagName(name)
 	flag, ok := f.formal[normalName]
 	if !ok {
-		return fmt.Errorf("no such flag -%v", name)
+		return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
 	}
 	if flag.Annotations == nil {
 		flag.Annotations = map[string][]string{}
@@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() {
 func (f *Flag) defaultIsZeroValue() bool {
 	switch f.Value.(type) {
 	case boolFlag:
-		return f.DefValue == "false"
+		return f.DefValue == "false" || f.DefValue == ""
 	case *durationValue:
 		// Beginning in Go 1.7, duration zero values are "0s"
 		return f.DefValue == "0" || f.DefValue == "0s"
@@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool {
 	case *intSliceValue, *stringSliceValue, *stringArrayValue:
 		return f.DefValue == "[]"
 	default:
-		switch f.Value.String() {
+		switch f.DefValue {
 		case "false":
 			return true
 		case "":
@@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
 
 	name = flag.Value.Type()
 	switch name {
-	case "bool":
+	case "bool", "boolfunc":
 		name = ""
+	case "func":
+		name = "value"
 	case "float64":
 		name = "float"
 	case "int64":
@@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 			switch flag.Value.Type() {
 			case "string":
 				line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
-			case "bool":
+			case "bool", "boolfunc":
 				if flag.NoOptDefVal != "true" {
 					line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
 				}
@@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) {
 	CommandLine.VarP(value, name, shorthand, usage)
 }
 
-// failf prints to standard error a formatted error and usage message and
+// fail prints an error message and usage message to standard error and
 // returns the error.
-func (f *FlagSet) failf(format string, a ...interface{}) error {
-	err := fmt.Errorf(format, a...)
+func (f *FlagSet) fail(err error) error {
 	if f.errorHandling != ContinueOnError {
 		fmt.Fprintln(f.Output(), err)
 		f.usage()
@@ -934,9 +946,9 @@ func (f *FlagSet) usage() {
 	}
 }
 
-//--unknown (args will be empty)
-//--unknown --next-flag ... (args will be --next-flag ...)
-//--unknown arg ... (args will be arg ...)
+// --unknown (args will be empty)
+// --unknown --next-flag ... (args will be --next-flag ...)
+// --unknown arg ... (args will be arg ...)
 func stripUnknownFlagValue(args []string) []string {
 	if len(args) == 0 {
 		//--unknown
@@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 	a = args
 	name := s[2:]
 	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
-		err = f.failf("bad flag syntax: %s", s)
+		err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
 		return
 	}
 
@@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 
 			return stripUnknownFlagValue(a), nil
 		default:
-			err = f.failf("unknown flag: --%s", name)
+			err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
 			return
 		}
 	}
@@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 		a = a[1:]
 	} else {
 		// '--flag' (arg was required)
-		err = f.failf("flag needs an argument: %s", s)
+		err = f.fail(&ValueRequiredError{
+			flag:          flag,
+			specifiedName: name,
+		})
 		return
 	}
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
 	outArgs = args
 
-	if strings.HasPrefix(shorthands, "test.") {
+	if isGotestShorthandFlag(shorthands) {
 		return
 	}
 
@@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 			outArgs = stripUnknownFlagValue(outArgs)
 			return
 		default:
-			err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
+			err = f.fail(&NotExistError{
+				name:                string(c),
+				specifiedShorthands: shorthands,
+				messageType:         flagUnknownShorthandFlagMessage,
+			})
 			return
 		}
 	}
@@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 		outArgs = args[1:]
 	} else {
 		// '-f' (arg was required)
-		err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
+		err = f.fail(&ValueRequiredError{
+			flag:                flag,
+			specifiedName:       string(c),
+			specifiedShorthands: shorthands,
+		})
 		return
 	}
 
@@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 
 	err = fn(flag, value)
 	if err != nil {
-		f.failf(err.Error())
+		f.fail(err)
 	}
 	return
 }
@@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error {
 	}
 	f.parsed = true
 
-	if len(arguments) < 0 {
+	if len(arguments) == 0 {
 		return nil
 	}
 
diff --git a/public-api/vendor/github.com/spf13/pflag/func.go b/public-api/vendor/github.com/spf13/pflag/func.go
new file mode 100644
index 00000000..9f4d88f2
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/pflag/func.go
@@ -0,0 +1,37 @@
+package pflag
+
+// -- func Value
+type funcValue func(string) error
+
+func (f funcValue) Set(s string) error { return f(s) }
+
+func (f funcValue) Type() string { return "func" }
+
+func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func (f *FlagSet) Func(name string, usage string, fn func(string) error) {
+	f.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) {
+	var val Value = funcValue(fn)
+	f.VarP(val, name, shorthand, usage)
+}
+
+// Func defines a func flag with specified name, callback function and usage string.
+//
+// The callback function will be called every time "--{name}={value}" (or equivalent) is
+// parsed on the command line, with "{value}" as an argument.
+func Func(name string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, "", usage, fn)
+}
+
+// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
+func FuncP(name, shorthand string, usage string, fn func(string) error) {
+	CommandLine.FuncP(name, shorthand, usage, fn)
+}
diff --git a/public-api/vendor/github.com/spf13/pflag/golangflag.go b/public-api/vendor/github.com/spf13/pflag/golangflag.go
index d3dd72b7..f563907e 100644
--- a/public-api/vendor/github.com/spf13/pflag/golangflag.go
+++ b/public-api/vendor/github.com/spf13/pflag/golangflag.go
@@ -10,6 +10,15 @@ import (
 	"strings"
 )
 
+// go test flags prefixes
+func isGotestFlag(flag string) bool {
+	return strings.HasPrefix(flag, "-test.")
+}
+
+func isGotestShorthandFlag(flag string) bool {
+	return strings.HasPrefix(flag, "test.")
+}
+
 // flagValueWrapper implements pflag.Value around a flag.Value.  The main
 // difference here is the addition of the Type method that returns a string
 // name of the type.  As this is generally unknown, we approximate that with
@@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
 	}
 	f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
 }
+
+// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(),
+// since by default those are skipped by pflag.Parse().
+// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)`
+func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
+	var skippedFlags []string
+	for _, f := range osArgs {
+		if isGotestFlag(f) {
+			skippedFlags = append(skippedFlags, f)
+		}
+	}
+	return goFlagSet.Parse(skippedFlags)
+}
diff --git a/public-api/vendor/github.com/spf13/pflag/ipnet_slice.go b/public-api/vendor/github.com/spf13/pflag/ipnet_slice.go
index 6b541aa8..c6e89da1 100644
--- a/public-api/vendor/github.com/spf13/pflag/ipnet_slice.go
+++ b/public-api/vendor/github.com/spf13/pflag/ipnet_slice.go
@@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string {
 
 func ipNetSliceConv(val string) (interface{}, error) {
 	val = strings.Trim(val, "[]")
-	// Emtpy string would cause a slice with one (empty) entry
+	// Empty string would cause a slice with one (empty) entry
 	if len(val) == 0 {
 		return []net.IPNet{}, nil
 	}
diff --git a/public-api/vendor/github.com/spf13/pflag/text.go b/public-api/vendor/github.com/spf13/pflag/text.go
new file mode 100644
index 00000000..886d5a3d
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/pflag/text.go
@@ -0,0 +1,81 @@
+package pflag
+
+import (
+	"encoding"
+	"fmt"
+	"reflect"
+)
+
+// following is copied from go 1.23.4 flag.go
+type textValue struct{ p encoding.TextUnmarshaler }
+
+func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
+	ptrVal := reflect.ValueOf(p)
+	if ptrVal.Kind() != reflect.Ptr {
+		panic("variable value type must be a pointer")
+	}
+	defVal := reflect.ValueOf(val)
+	if defVal.Kind() == reflect.Ptr {
+		defVal = defVal.Elem()
+	}
+	if defVal.Type() != ptrVal.Type().Elem() {
+		panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
+	}
+	ptrVal.Elem().Set(defVal)
+	return textValue{p}
+}
+
+func (v textValue) Set(s string) error {
+	return v.p.UnmarshalText([]byte(s))
+}
+
+func (v textValue) Get() interface{} {
+	return v.p
+}
+
+func (v textValue) String() string {
+	if m, ok := v.p.(encoding.TextMarshaler); ok {
+		if b, err := m.MarshalText(); err == nil {
+			return string(b)
+		}
+	}
+	return ""
+}
+
+//end of copy
+
+func (v textValue) Type() string {
+	return reflect.ValueOf(v.p).Type().Name()
+}
+
+// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
+func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
+	flag := f.Lookup(name)
+	if flag == nil {
+		return fmt.Errorf("flag accessed but not defined: %s", name)
+	}
+	if flag.Value.Type() != reflect.TypeOf(out).Name() {
+		return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
+	}
+	return out.UnmarshalText([]byte(flag.Value.String()))
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	f.VarP(newTextValue(value, p), name, shorthand, usage)
+}
+
+// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
+func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, "", usage)
+}
+
+// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
+func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
+	CommandLine.VarP(newTextValue(value, p), name, shorthand, usage)
+}
diff --git a/public-api/vendor/github.com/spf13/pflag/time.go b/public-api/vendor/github.com/spf13/pflag/time.go
new file mode 100644
index 00000000..dc024807
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/pflag/time.go
@@ -0,0 +1,118 @@
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"time"
+)
+
+// TimeValue adapts time.Time for use as a flag.
+type timeValue struct {
+	*time.Time
+	formats []string
+}
+
+func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue {
+	*p = val
+	return &timeValue{
+		Time:    p,
+		formats: formats,
+	}
+}
+
+// Set time.Time value from string based on accepted formats.
+func (d *timeValue) Set(s string) error {
+	s = strings.TrimSpace(s)
+	for _, f := range d.formats {
+		v, err := time.Parse(f, s)
+		if err != nil {
+			continue
+		}
+		*d.Time = v
+		return nil
+	}
+
+	formatsString := ""
+	for i, f := range d.formats {
+		if i > 0 {
+			formatsString += ", "
+		}
+		formatsString += fmt.Sprintf("`%s`", f)
+	}
+
+	return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString)
+}
+
+// Type name for time.Time flags.
+func (d *timeValue) Type() string {
+	return "time"
+}
+
+func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) }
+
+// GetTime return the time value of a flag with the given name
+func (f *FlagSet) GetTime(name string) (time.Time, error) {
+	flag := f.Lookup(name)
+	if flag == nil {
+		err := fmt.Errorf("flag accessed but not defined: %s", name)
+		return time.Time{}, err
+	}
+
+	if flag.Value.Type() != "time" {
+		err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type())
+		return time.Time{}, err
+	}
+
+	val, ok := flag.Value.(*timeValue)
+	if !ok {
+		return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value)
+	}
+
+	return *val.Time, nil
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	f.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	f.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// TimeVar defines a time.Time flag with specified name, default value, and usage string.
+// The argument p points to a time.Time variable in which to store the value of the flag.
+func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
+	CommandLine.TimeVarP(p, name, "", value, formats, usage)
+}
+
+// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
+func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
+	CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return f.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	p := new(time.Time)
+	f.TimeVarP(p, name, shorthand, value, formats, usage)
+	return p
+}
+
+// Time defines a time.Time flag with specified name, default value, and usage string.
+// The return value is the address of a time.Time variable that stores the value of the flag.
+func Time(name string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, "", value, formats, usage)
+}
+
+// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
+func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
+	return CommandLine.TimeP(name, shorthand, value, formats, usage)
+}
diff --git a/public-api/vendor/github.com/spf13/viper/.envrc b/public-api/vendor/github.com/spf13/viper/.envrc
index 3ce7171a..2e0f9f5f 100644
--- a/public-api/vendor/github.com/spf13/viper/.envrc
+++ b/public-api/vendor/github.com/spf13/viper/.envrc
@@ -1,4 +1,4 @@
-if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
-  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
+if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
+  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
 fi
 use flake . --impure
diff --git a/public-api/vendor/github.com/spf13/viper/.golangci.yaml b/public-api/vendor/github.com/spf13/viper/.golangci.yaml
index acd9eeba..474f4163 100644
--- a/public-api/vendor/github.com/spf13/viper/.golangci.yaml
+++ b/public-api/vendor/github.com/spf13/viper/.golangci.yaml
@@ -7,8 +7,16 @@ linters-settings:
             - standard
             - default
             - prefix(github.com/spf13/viper)
-    golint:
-        min-confidence: 0
+    gocritic:
+        # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
+        enabled-tags:
+            - diagnostic
+            - experimental
+            - opinionated
+            - style
+        disabled-checks:
+            - importShadow
+            - unnamedResult
     goimports:
         local-prefixes: github.com/spf13/viper
 
@@ -20,8 +28,9 @@ linters:
         - dupl
         - durationcheck
         - exhaustive
-        - exportloopref
         - gci
+        - gocritic
+        - godot
         - gofmt
         - gofumpt
         - goimports
@@ -62,9 +71,7 @@ linters:
         # - gochecknoinits
         # - gocognit
         # - goconst
-        # - gocritic
         # - gocyclo
-        # - godot
         # - gosec
         # - gosimple
         # - ifshort
diff --git a/public-api/vendor/github.com/spf13/viper/README.md b/public-api/vendor/github.com/spf13/viper/README.md
index 78102fbe..769a5d90 100644
--- a/public-api/vendor/github.com/spf13/viper/README.md
+++ b/public-api/vendor/github.com/spf13/viper/README.md
@@ -3,7 +3,8 @@
 >
 > **Thank you!**
 
-![Viper](.github/logo.png?raw=true)
+![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e)
+
 
 [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
 [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
@@ -11,7 +12,7 @@
 [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
 [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-61CFDD.svg?style=flat-square)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square)
 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
 
 **Go configuration with fangs!**
@@ -39,7 +40,7 @@ Many Go projects are built using Viper including:
 go get github.com/spf13/viper
 ```
 
-**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
+**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
 
 
 ## What is Viper?
@@ -418,7 +419,9 @@ in a Key/Value store such as etcd or Consul.  These values take precedence over
 default values, but are overridden by configuration values retrieved from disk,
 flags, or environment variables.
 
-Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
+Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
+
+Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
 configuration from the K/V store, which means that you can store your
 configuration values encrypted and have them automatically decrypted if you have
 the correct gpg keyring.  Encryption is optional.
@@ -430,7 +433,7 @@ independently of it.
 K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
 
 ```bash
-$ go get github.com/bketelsen/crypt/bin/crypt
+$ go get github.com/sagikazarmark/crypt/bin/crypt
 $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
 ```
 
@@ -563,6 +566,9 @@ 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
 has been provided.
 
+The zero value will also be returned if the value is set, but fails to parse
+as the requested type.
+
 Example:
 ```go
 viper.GetString("logfile") // case-insensitive Setting & Getting
@@ -797,7 +803,7 @@ if err != nil {
 }
 ```
 
-Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
+Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
 
 ### Decoding custom formats
 
@@ -831,13 +837,15 @@ func yamlStringSettings() string {
 
 ## Viper or Vipers?
 
-Viper comes ready to use out of the box. There is no configuration or
-initialization needed to begin using Viper. Since most applications will want
-to use a single central repository for their configuration, the viper package
-provides this. It is similar to a singleton.
+Viper comes with a global instance (singleton) out of the box.
+
+Although it makes setting up configuration easy,
+using it is generally discouraged as it makes testing harder and can lead to unexpected behavior.
+
+The best practice is to initialize a Viper instance and pass that around when necessary.
 
-In all of the examples above, they demonstrate using viper in its singleton
-style approach.
+The global instance _MAY_ be deprecated in the future.
+See [#1855](https://github.com/spf13/viper/issues/1855) for more details.
 
 ### Working with multiple vipers
 
diff --git a/public-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/public-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
index c4e36c68..b68993d4 100644
--- a/public-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
+++ b/public-api/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
@@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
 ```
 
 As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
-Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
+Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
 
 The solution is easy: switch to using Go Modules.
-Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that.
+Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
 
 **tl;dr* `export GO111MODULE=on`
 
diff --git a/public-api/vendor/github.com/spf13/viper/UPDATES.md b/public-api/vendor/github.com/spf13/viper/UPDATES.md
new file mode 100644
index 00000000..ccf413ed
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/UPDATES.md
@@ -0,0 +1,126 @@
+# Update Log
+
+**This document details any major updates required to use new features or improvements in Viper.**
+
+## v1.20.x
+
+### New file searching API
+
+Viper now includes a new file searching API that allows users to customize how Viper looks for config files.
+
+Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation:
+
+```go
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+```
+
+It is supposed to return a list of paths to config files.
+
+The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood.
+
+You can supply your own implementation using `WithFinder`:
+
+```go
+v := viper.NewWithOptions(
+    viper.WithFinder(&MyFinder{}),
+)
+```
+
+For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder)
+and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package.
+
+### New encoding API
+
+Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data:
+
+```go
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+```
+
+By default, Viper includes the following codecs:
+
+- JSON
+- TOML
+- YAML
+- Dotenv
+
+The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding)
+
+Customizing the encoding layer is possible by providing a custom registry of codecs:
+
+- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry)
+- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry)
+- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry)
+
+You can supply the registry of codecs to Viper using the appropriate `With*Registry` function:
+
+```go
+codecRegistry := viper.NewCodecRegistry()
+
+codecRegistry.RegisterCodec("myformat", &MyCodec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
+
+### BREAKING: HCL, Java properties, INI removed from core
+
+In order to reduce third-party dependencies, Viper dropped support for the following formats from the core:
+
+- HCL
+- Java properties
+- INI
+
+You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding):
+
+```go
+import (
+    "github.com/go-viper/encoding/hcl"
+    "github.com/go-viper/encoding/javaproperties"
+    "github.com/go-viper/encoding/ini"
+)
+
+codecRegistry := viper.NewCodecRegistry()
+
+{
+    codec := hcl.Codec{}
+
+    codecRegistry.RegisterCodec("hcl", codec)
+    codecRegistry.RegisterCodec("tfvars", codec)
+
+}
+
+{
+    codec := &javaproperties.Codec{}
+
+    codecRegistry.RegisterCodec("properties", codec)
+    codecRegistry.RegisterCodec("props", codec)
+    codecRegistry.RegisterCodec("prop", codec)
+}
+
+codecRegistry.RegisterCodec("ini", ini.Codec{})
+
+v := viper.NewWithOptions(
+    viper.WithCodecRegistry(codecRegistry),
+)
+```
diff --git a/public-api/vendor/github.com/spf13/viper/encoding.go b/public-api/vendor/github.com/spf13/viper/encoding.go
new file mode 100644
index 00000000..a7da5586
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/encoding.go
@@ -0,0 +1,181 @@
+package viper
+
+import (
+	"errors"
+	"strings"
+	"sync"
+
+	"github.com/spf13/viper/internal/encoding/dotenv"
+	"github.com/spf13/viper/internal/encoding/json"
+	"github.com/spf13/viper/internal/encoding/toml"
+	"github.com/spf13/viper/internal/encoding/yaml"
+)
+
+// Encoder encodes Viper's internal data structures into a byte representation.
+// It's primarily used for encoding a map[string]any into a file format.
+type Encoder interface {
+	Encode(v map[string]any) ([]byte, error)
+}
+
+// Decoder decodes the contents of a byte slice into Viper's internal data structures.
+// It's primarily used for decoding contents of a file into a map[string]any.
+type Decoder interface {
+	Decode(b []byte, v map[string]any) error
+}
+
+// Codec combines [Encoder] and [Decoder] interfaces.
+type Codec interface {
+	Encoder
+	Decoder
+}
+
+// TODO: consider adding specific errors for not found scenarios
+
+// EncoderRegistry returns an [Encoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [EncoderRegistry] returns an error if no [Encoder] is registered for the format.
+type EncoderRegistry interface {
+	Encoder(format string) (Encoder, error)
+}
+
+// DecoderRegistry returns an [Decoder] for a given format.
+//
+// Format is case-insensitive.
+//
+// [DecoderRegistry] returns an error if no [Decoder] is registered for the format.
+type DecoderRegistry interface {
+	Decoder(format string) (Decoder, error)
+}
+
+// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces.
+type CodecRegistry interface {
+	EncoderRegistry
+	DecoderRegistry
+}
+
+// WithEncoderRegistry sets a custom [EncoderRegistry].
+func WithEncoderRegistry(r EncoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+	})
+}
+
+// WithDecoderRegistry sets a custom [DecoderRegistry].
+func WithDecoderRegistry(r DecoderRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.decoderRegistry = r
+	})
+}
+
+// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry].
+func WithCodecRegistry(r CodecRegistry) Option {
+	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
+		v.encoderRegistry = r
+		v.decoderRegistry = r
+	})
+}
+
+// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s.
+type DefaultCodecRegistry struct {
+	codecs map[string]Codec
+
+	mu   sync.RWMutex
+	once sync.Once
+}
+
+// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s.
+func NewCodecRegistry() *DefaultCodecRegistry {
+	r := &DefaultCodecRegistry{}
+
+	r.init()
+
+	return r
+}
+
+func (r *DefaultCodecRegistry) init() {
+	r.once.Do(func() {
+		r.codecs = map[string]Codec{}
+	})
+}
+
+// RegisterCodec registers a custom [Codec].
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error {
+	r.init()
+
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	r.codecs[strings.ToLower(format)] = codec
+
+	return nil
+}
+
+// Encoder implements the [EncoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) {
+	encoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("encoder not found for this format")
+	}
+
+	return encoder, nil
+}
+
+// Decoder implements the [DecoderRegistry] interface.
+//
+// Format is case-insensitive.
+func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) {
+	decoder, ok := r.codec(format)
+	if !ok {
+		return nil, errors.New("decoder not found for this format")
+	}
+
+	return decoder, nil
+}
+
+func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	format = strings.ToLower(format)
+
+	if r.codecs != nil {
+		codec, ok := r.codecs[format]
+		if ok {
+			return codec, true
+		}
+	}
+
+	switch format {
+	case "yaml", "yml":
+		return yaml.Codec{}, true
+
+	case "json":
+		return json.Codec{}, true
+
+	case "toml":
+		return toml.Codec{}, true
+
+	case "dotenv", "env":
+		return &dotenv.Codec{}, true
+	}
+
+	return nil, false
+}
diff --git a/public-api/vendor/github.com/spf13/viper/experimental.go b/public-api/vendor/github.com/spf13/viper/experimental.go
new file mode 100644
index 00000000..6e19e8a1
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/experimental.go
@@ -0,0 +1,8 @@
+package viper
+
+// ExperimentalBindStruct tells Viper to use the new bind struct feature.
+func ExperimentalBindStruct() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalBindStruct = true
+	})
+}
diff --git a/public-api/vendor/github.com/spf13/viper/file.go b/public-api/vendor/github.com/spf13/viper/file.go
new file mode 100644
index 00000000..50a40581
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/file.go
@@ -0,0 +1,104 @@
+package viper
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/sagikazarmark/locafero"
+	"github.com/spf13/afero"
+)
+
+// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files.
+func ExperimentalFinder() Option {
+	return optionFunc(func(v *Viper) {
+		v.experimentalFinder = true
+	})
+}
+
+// Search for a config file.
+func (v *Viper) findConfigFile() (string, error) {
+	finder := v.finder
+
+	if finder == nil && v.experimentalFinder {
+		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,
+		}
+	}
+
+	if finder != nil {
+		return v.findConfigFileWithFinder(finder)
+	}
+
+	return v.findConfigFileOld()
+}
+
+func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) {
+	results, err := finder.Find(v.fs)
+	if err != nil {
+		return "", err
+	}
+
+	if len(results) == 0 {
+		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+	}
+
+	// We call clean on the final result to ensure that the path is in its canonical form.
+	// This is mostly for consistent path handling and to make sure tests pass.
+	return results[0], nil
+}
+
+// Search all configPaths for any config file.
+// Returns the first path that exists (and is a config file).
+func (v *Viper) findConfigFileOld() (string, error) {
+	v.logger.Info("searching for config in paths", "paths", v.configPaths)
+
+	for _, cp := range v.configPaths {
+		file := v.searchInPath(cp)
+		if file != "" {
+			return file, nil
+		}
+	}
+	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
+}
+
+func (v *Viper) searchInPath(in string) (filename string) {
+	v.logger.Debug("searching for config in path", "path", in)
+	for _, ext := range SupportedExts {
+		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
+			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
+			return filepath.Join(in, v.configName+"."+ext)
+		}
+	}
+
+	if v.configType != "" {
+		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
+			return filepath.Join(in, v.configName)
+		}
+	}
+
+	return ""
+}
+
+// exists checks if file exists.
+func exists(fs afero.Fs, path string) (bool, error) {
+	stat, err := fs.Stat(path)
+	if err == nil {
+		return !stat.IsDir(), nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
diff --git a/public-api/vendor/github.com/spf13/viper/finder.go b/public-api/vendor/github.com/spf13/viper/finder.go
new file mode 100644
index 00000000..9b203ea6
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/finder.go
@@ -0,0 +1,55 @@
+package viper
+
+import (
+	"errors"
+
+	"github.com/spf13/afero"
+)
+
+// WithFinder sets a custom [Finder].
+func WithFinder(f Finder) Option {
+	return optionFunc(func(v *Viper) {
+		if f == nil {
+			return
+		}
+
+		v.finder = f
+	})
+}
+
+// Finder looks for files and directories in an [afero.Fs] filesystem.
+type Finder interface {
+	Find(fsys afero.Fs) ([]string, error)
+}
+
+// Finders combines multiple finders into one.
+func Finders(finders ...Finder) Finder {
+	return &combinedFinder{finders: finders}
+}
+
+// combinedFinder is a Finder that combines multiple finders.
+type combinedFinder struct {
+	finders []Finder
+}
+
+// Find implements the [Finder] interface.
+func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) {
+	var results []string
+	var errs []error
+
+	for _, finder := range c.finders {
+		if finder == nil {
+			continue
+		}
+
+		r, err := finder.Find(fsys)
+		if err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		results = append(results, r...)
+	}
+
+	return results, errors.Join(errs...)
+}
diff --git a/public-api/vendor/github.com/spf13/viper/flags.go b/public-api/vendor/github.com/spf13/viper/flags.go
index ddb4da60..de033ed5 100644
--- a/public-api/vendor/github.com/spf13/viper/flags.go
+++ b/public-api/vendor/github.com/spf13/viper/flags.go
@@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
 }
 
 // pflagValue is a wrapper around *pflag.flag
-// that implements FlagValue
+// that implements FlagValue.
 type pflagValue struct {
 	flag *pflag.Flag
 }
diff --git a/public-api/vendor/github.com/spf13/viper/flake.lock b/public-api/vendor/github.com/spf13/viper/flake.lock
index 78da5109..d76dfbdd 100644
--- a/public-api/vendor/github.com/spf13/viper/flake.lock
+++ b/public-api/vendor/github.com/spf13/viper/flake.lock
@@ -1,22 +1,84 @@
 {
   "nodes": {
+    "cachix": {
+      "inputs": {
+        "devenv": "devenv_2",
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
+        ],
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": [
+          "devenv",
+          "pre-commit-hooks"
+        ]
+      },
+      "locked": {
+        "lastModified": 1712055811,
+        "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
     "devenv": {
       "inputs": {
-        "flake-compat": "flake-compat",
+        "cachix": "cachix",
+        "flake-compat": "flake-compat_2",
+        "nix": "nix_2",
+        "nixpkgs": "nixpkgs_2",
+        "pre-commit-hooks": "pre-commit-hooks"
+      },
+      "locked": {
+        "lastModified": 1724763216,
+        "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=",
+        "owner": "cachix",
+        "repo": "devenv",
+        "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "devenv",
+        "type": "github"
+      }
+    },
+    "devenv_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "cachix",
+          "flake-compat"
+        ],
         "nix": "nix",
         "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "poetry2nix": "poetry2nix",
+        "pre-commit-hooks": [
+          "devenv",
+          "cachix",
+          "pre-commit-hooks"
+        ]
       },
       "locked": {
-        "lastModified": 1687972261,
-        "narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=",
+        "lastModified": 1708704632,
+        "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
         "owner": "cachix",
         "repo": "devenv",
-        "rev": "e85df562088573305e55906eaa964341f8cb0d9f",
+        "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
         "type": "github"
       },
       "original": {
         "owner": "cachix",
+        "ref": "python-rewrite",
         "repo": "devenv",
         "type": "github"
       }
@@ -37,16 +99,32 @@
         "type": "github"
       }
     },
+    "flake-compat_2": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": "nixpkgs-lib"
       },
       "locked": {
-        "lastModified": 1687762428,
-        "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=",
+        "lastModified": 1722555600,
+        "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
         "owner": "hercules-ci",
         "repo": "flake-parts",
-        "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836",
+        "rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
         "type": "github"
       },
       "original": {
@@ -56,12 +134,33 @@
       }
     },
     "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
       "locked": {
-        "lastModified": 1667395993,
-        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "inputs": {
+        "systems": "systems_2"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
         "type": "github"
       },
       "original": {
@@ -79,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
         "type": "github"
       },
       "original": {
@@ -92,53 +191,90 @@
         "type": "github"
       }
     },
-    "lowdown-src": {
-      "flake": false,
+    "nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
       "locked": {
-        "lastModified": 1633514407,
-        "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-        "owner": "kristapsdz",
-        "repo": "lowdown",
-        "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
+        "owner": "domenkozar",
+        "repo": "nix",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
-        "owner": "kristapsdz",
-        "repo": "lowdown",
+        "owner": "domenkozar",
+        "ref": "devenv-2.21",
+        "repo": "nix",
         "type": "github"
       }
     },
-    "nix": {
+    "nix-github-actions": {
       "inputs": {
-        "lowdown-src": "lowdown-src",
         "nixpkgs": [
           "devenv",
+          "cachix",
+          "devenv",
+          "poetry2nix",
           "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1688870561,
+        "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nix-github-actions",
+        "type": "github"
+      }
+    },
+    "nix_2": {
+      "inputs": {
+        "flake-compat": [
+          "devenv",
+          "flake-compat"
         ],
-        "nixpkgs-regression": "nixpkgs-regression"
+        "nixpkgs": [
+          "devenv",
+          "nixpkgs"
+        ],
+        "nixpkgs-regression": "nixpkgs-regression_2"
       },
       "locked": {
-        "lastModified": 1676545802,
-        "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
+        "lastModified": 1712911606,
+        "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
         "owner": "domenkozar",
         "repo": "nix",
-        "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
+        "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
         "type": "github"
       },
       "original": {
         "owner": "domenkozar",
-        "ref": "relaxed-flakes",
+        "ref": "devenv-2.21",
         "repo": "nix",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1678875422,
-        "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
+        "lastModified": 1692808169,
+        "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
+        "rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
         "type": "github"
       },
       "original": {
@@ -150,23 +286,33 @@
     },
     "nixpkgs-lib": {
       "locked": {
-        "dir": "lib",
-        "lastModified": 1685564631,
-        "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=",
+        "lastModified": 1722555339,
+        "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       },
       "original": {
-        "dir": "lib",
         "owner": "NixOS",
-        "ref": "nixos-unstable",
         "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
         "type": "github"
       }
     },
-    "nixpkgs-regression": {
+    "nixpkgs-regression_2": {
       "locked": {
         "lastModified": 1643052045,
         "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
@@ -184,27 +330,43 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1678872516,
-        "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixos-22.11",
+        "ref": "nixos-23.11",
         "repo": "nixpkgs",
         "type": "github"
       }
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1687886075,
-        "narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=",
+        "lastModified": 1713361204,
+        "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
+        "owner": "cachix",
+        "repo": "devenv-nixpkgs",
+        "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "rolling",
+        "repo": "devenv-nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1724748588,
+        "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "a565059a348422af5af9026b5174dc5c0dcefdae",
+        "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99",
         "type": "github"
       },
       "original": {
@@ -214,13 +376,38 @@
         "type": "github"
       }
     },
+    "poetry2nix": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nix-github-actions": "nix-github-actions",
+        "nixpkgs": [
+          "devenv",
+          "cachix",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1692876271,
+        "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "poetry2nix",
+        "type": "github"
+      }
+    },
     "pre-commit-hooks": {
       "inputs": {
         "flake-compat": [
           "devenv",
           "flake-compat"
         ],
-        "flake-utils": "flake-utils",
+        "flake-utils": "flake-utils_2",
         "gitignore": "gitignore",
         "nixpkgs": [
           "devenv",
@@ -229,11 +416,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1686050334,
-        "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=",
+        "lastModified": 1713775815,
+        "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
         "owner": "cachix",
         "repo": "pre-commit-hooks.nix",
-        "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc",
+        "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
         "type": "github"
       },
       "original": {
@@ -246,7 +433,37 @@
       "inputs": {
         "devenv": "devenv",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_3"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
       }
     }
   },
diff --git a/public-api/vendor/github.com/spf13/viper/flake.nix b/public-api/vendor/github.com/spf13/viper/flake.nix
index 9b26c3fc..52ad7d58 100644
--- a/public-api/vendor/github.com/spf13/viper/flake.nix
+++ b/public-api/vendor/github.com/spf13/viper/flake.nix
@@ -20,6 +20,7 @@
           default = {
             languages = {
               go.enable = true;
+              go.package = pkgs.go_1_23;
             };
 
             pre-commit.hooks = {
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go
deleted file mode 100644
index 8a7b1dbc..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/decoder.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Decoder decodes the contents of b into v.
-// It's primarily used for decoding contents of a file into a map[string]any.
-type Decoder interface {
-	Decode(b []byte, v map[string]any) error
-}
-
-const (
-	// ErrDecoderNotFound is returned when there is no decoder registered for a format.
-	ErrDecoderNotFound = encodingError("decoder not found for this format")
-
-	// ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
-	ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
-)
-
-// DecoderRegistry can choose an appropriate Decoder based on the provided format.
-type DecoderRegistry struct {
-	decoders map[string]Decoder
-
-	mu sync.RWMutex
-}
-
-// NewDecoderRegistry returns a new, initialized DecoderRegistry.
-func NewDecoderRegistry() *DecoderRegistry {
-	return &DecoderRegistry{
-		decoders: make(map[string]Decoder),
-	}
-}
-
-// RegisterDecoder registers a Decoder for a format.
-// Registering a Decoder for an already existing format is not supported.
-func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.decoders[format]; ok {
-		return ErrDecoderFormatAlreadyRegistered
-	}
-
-	e.decoders[format] = enc
-
-	return nil
-}
-
-// Decode calls the underlying Decoder based on the format.
-func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
-	e.mu.RLock()
-	decoder, ok := e.decoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return ErrDecoderNotFound
-	}
-
-	return decoder.Decode(b, v)
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
index 1340c730..8bfe0a9d 100644
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
+++ b/public-api/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
@@ -8,8 +8,8 @@ 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]any, m map[string]any, prefix string, delimiter string) map[string]any {
+// TODO: move it to a common place.
+func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
 	if shadow != nil && prefix != "" && shadow[prefix] != nil {
 		// prefix is shadowed => nothing more to flatten
 		return shadow
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go
deleted file mode 100644
index 65958596..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/encoder.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package encoding
-
-import (
-	"sync"
-)
-
-// Encoder encodes the contents of v into a byte representation.
-// It's primarily used for encoding a map[string]any into a file format.
-type Encoder interface {
-	Encode(v map[string]any) ([]byte, error)
-}
-
-const (
-	// ErrEncoderNotFound is returned when there is no encoder registered for a format.
-	ErrEncoderNotFound = encodingError("encoder not found for this format")
-
-	// ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format.
-	ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format")
-)
-
-// EncoderRegistry can choose an appropriate Encoder based on the provided format.
-type EncoderRegistry struct {
-	encoders map[string]Encoder
-
-	mu sync.RWMutex
-}
-
-// NewEncoderRegistry returns a new, initialized EncoderRegistry.
-func NewEncoderRegistry() *EncoderRegistry {
-	return &EncoderRegistry{
-		encoders: make(map[string]Encoder),
-	}
-}
-
-// RegisterEncoder registers an Encoder for a format.
-// Registering a Encoder for an already existing format is not supported.
-func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
-	e.mu.Lock()
-	defer e.mu.Unlock()
-
-	if _, ok := e.encoders[format]; ok {
-		return ErrEncoderFormatAlreadyRegistered
-	}
-
-	e.encoders[format] = enc
-
-	return nil
-}
-
-func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
-	e.mu.RLock()
-	encoder, ok := e.encoders[format]
-	e.mu.RUnlock()
-
-	if !ok {
-		return nil, ErrEncoderNotFound
-	}
-
-	return encoder.Encode(v)
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/error.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/error.go
deleted file mode 100644
index e4cde02d..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/error.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package encoding
-
-type encodingError string
-
-func (e encodingError) Error() string {
-	return string(e)
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
deleted file mode 100644
index d7fa8a1b..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package hcl
-
-import (
-	"bytes"
-	"encoding/json"
-
-	"github.com/hashicorp/hcl"
-	"github.com/hashicorp/hcl/hcl/printer"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding.
-// TODO: add printer config to the codec?
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
-	b, err := json.Marshal(v)
-	if err != nil {
-		return nil, err
-	}
-
-	// TODO: use printer.Format? Is the trailing newline an issue?
-
-	ast, err := hcl.Parse(string(b))
-	if err != nil {
-		return nil, err
-	}
-
-	var buf bytes.Buffer
-
-	err = printer.Fprint(&buf, ast.Node)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
-	return hcl.Unmarshal(b, &v)
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
deleted file mode 100644
index d91cf59d..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package ini
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/spf13/cast"
-	"gopkg.in/ini.v1"
-)
-
-// LoadOptions contains all customized options used for load data source(s).
-// This type is added here for convenience: this way consumers can import a single package called "ini".
-type LoadOptions = ini.LoadOptions
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding.
-type Codec struct {
-	KeyDelimiter string
-	LoadOptions  LoadOptions
-}
-
-func (c Codec) Encode(v map[string]any) ([]byte, error) {
-	cfg := ini.Empty()
-	ini.PrettyFormat = false
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		sectionName, keyName := "", key
-
-		lastSep := strings.LastIndex(key, ".")
-		if lastSep != -1 {
-			sectionName = key[:(lastSep)]
-			keyName = key[(lastSep + 1):]
-		}
-
-		// TODO: is this a good idea?
-		if sectionName == "default" {
-			sectionName = ""
-		}
-
-		cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
-	}
-
-	var buf bytes.Buffer
-
-	_, err := cfg.WriteTo(&buf)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-func (c Codec) Decode(b []byte, v map[string]any) error {
-	cfg := ini.Empty(c.LoadOptions)
-
-	err := cfg.Append(b)
-	if err != nil {
-		return err
-	}
-
-	sections := cfg.Sections()
-
-	for i := 0; i < len(sections); i++ {
-		section := sections[i]
-		keys := section.Keys()
-
-		for j := 0; j < len(keys); j++ {
-			key := keys[j]
-			value := cfg.Section(section.Name()).Key(key.Name()).String()
-
-			deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
-
-			// set innermost value
-			deepestMap[key.Name()] = value
-		}
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
deleted file mode 100644
index c1919a38..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package ini
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
deleted file mode 100644
index e92e5172..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package javaproperties
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-
-	"github.com/magiconair/properties"
-	"github.com/spf13/cast"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
-type Codec struct {
-	KeyDelimiter string
-
-	// Store read properties on the object so that we can write back in order with comments.
-	// This will only be used if the configuration read is a properties file.
-	// TODO: drop this feature in v2
-	// TODO: make use of the global properties object optional
-	Properties *properties.Properties
-}
-
-func (c *Codec) Encode(v map[string]any) ([]byte, error) {
-	if c.Properties == nil {
-		c.Properties = properties.NewProperties()
-	}
-
-	flattened := map[string]any{}
-
-	flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
-	keys := make([]string, 0, len(flattened))
-
-	for key := range flattened {
-		keys = append(keys, key)
-	}
-
-	sort.Strings(keys)
-
-	for _, key := range keys {
-		_, _, err := c.Properties.Set(key, cast.ToString(flattened[key]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	var buf bytes.Buffer
-
-	_, err := c.Properties.WriteComment(&buf, "#", properties.UTF8)
-	if err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-}
-
-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 {
-		return err
-	}
-
-	for _, key := range c.Properties.Keys() {
-		// ignore existence check: we know it's there
-		value, _ := c.Properties.Get(key)
-
-		// recursively build nested maps
-		path := strings.Split(key, c.keyDelimiter())
-		lastKey := strings.ToLower(path[len(path)-1])
-		deepestMap := deepSearch(v, path[0:len(path)-1])
-
-		// set innermost value
-		deepestMap[lastKey] = value
-	}
-
-	return nil
-}
-
-func (c Codec) keyDelimiter() string {
-	if c.KeyDelimiter == "" {
-		return "."
-	}
-
-	return c.KeyDelimiter
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
deleted file mode 100644
index 8386920a..00000000
--- a/public-api/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package javaproperties
-
-import (
-	"strings"
-
-	"github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// 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]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]any)
-			m[k] = m3
-			m = m3
-			continue
-		}
-		m3, ok := m2.(map[string]any)
-		if !ok {
-			// intermediate key is a value
-			// => replace with a new map
-			m3 = make(map[string]any)
-			m[k] = m3
-		}
-		// continue search from here
-		m = m3
-	}
-	return m
-}
-
-// 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]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]any)
-	}
-
-	var m2 map[string]any
-	if prefix != "" {
-		prefix += delimiter
-	}
-	for k, val := range m {
-		fullKey := prefix + k
-		switch val := val.(type) {
-		case map[string]any:
-			m2 = val
-		case map[any]any:
-			m2 = cast.ToStringMap(val)
-		default:
-			// immediate value
-			shadow[strings.ToLower(fullKey)] = val
-			continue
-		}
-		// recursively merge to shadow map
-		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
-	}
-	return shadow
-}
diff --git a/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go b/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go
new file mode 100644
index 00000000..89302c21
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct.go
@@ -0,0 +1,5 @@
+//go:build viper_bind_struct
+
+package features
+
+const BindStruct = true
diff --git a/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go b/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
new file mode 100644
index 00000000..edfaf73b
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_bind_struct
+
+package features
+
+const BindStruct = false
diff --git a/public-api/vendor/github.com/spf13/viper/internal/features/finder.go b/public-api/vendor/github.com/spf13/viper/internal/features/finder.go
new file mode 100644
index 00000000..983ea3a9
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/internal/features/finder.go
@@ -0,0 +1,5 @@
+//go:build viper_finder
+
+package features
+
+const Finder = true
diff --git a/public-api/vendor/github.com/spf13/viper/internal/features/finder_default.go b/public-api/vendor/github.com/spf13/viper/internal/features/finder_default.go
new file mode 100644
index 00000000..89bcb06e
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/internal/features/finder_default.go
@@ -0,0 +1,5 @@
+//go:build !viper_finder
+
+package features
+
+const Finder = false
diff --git a/public-api/vendor/github.com/spf13/viper/logger.go b/public-api/vendor/github.com/spf13/viper/logger.go
index 8938053b..828042f2 100644
--- a/public-api/vendor/github.com/spf13/viper/logger.go
+++ b/public-api/vendor/github.com/spf13/viper/logger.go
@@ -2,46 +2,9 @@ package viper
 
 import (
 	"context"
-
-	slog "github.com/sagikazarmark/slog-shim"
+	"log/slog"
 )
 
-// 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 ...any)
-
-	// Debug logs a Debug event.
-	//
-	// A verbose series of information events.
-	// They are useful when debugging the system.
-	Debug(msg string, keyvals ...any)
-
-	// Info logs an Info event.
-	//
-	// General information about what's happening inside the system.
-	Info(msg string, keyvals ...any)
-
-	// Warn logs a Warn(ing) event.
-	//
-	// Non-critical events that should be looked at.
-	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 ...any)
-}
-
 // WithLogger sets a custom logger.
 func WithLogger(l *slog.Logger) Option {
 	return optionFunc(func(v *Viper) {
diff --git a/public-api/vendor/github.com/spf13/viper/remote.go b/public-api/vendor/github.com/spf13/viper/remote.go
new file mode 100644
index 00000000..bdde7de2
--- /dev/null
+++ b/public-api/vendor/github.com/spf13/viper/remote.go
@@ -0,0 +1,256 @@
+package viper
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"slices"
+)
+
+// SupportedRemoteProviders are universally supported remote providers.
+var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+
+func resetRemote() {
+	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
+}
+
+type remoteConfigFactory interface {
+	Get(rp RemoteProvider) (io.Reader, error)
+	Watch(rp RemoteProvider) (io.Reader, error)
+	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
+}
+
+type RemoteResponse struct {
+	Value []byte
+	Error error
+}
+
+// RemoteConfig is optional, see the remote package.
+var RemoteConfig remoteConfigFactory
+
+// UnsupportedRemoteProviderError denotes encountering an unsupported remote
+// provider. Currently only etcd and Consul are supported.
+type UnsupportedRemoteProviderError string
+
+// Error returns the formatted remote provider error.
+func (str UnsupportedRemoteProviderError) Error() string {
+	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
+}
+
+// RemoteConfigError denotes encountering an error while trying to
+// pull the configuration from the remote provider.
+type RemoteConfigError string
+
+// Error returns the formatted remote provider error.
+func (rce RemoteConfigError) Error() string {
+	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
+}
+
+type defaultRemoteProvider struct {
+	provider      string
+	endpoint      string
+	path          string
+	secretKeyring string
+}
+
+func (rp defaultRemoteProvider) Provider() string {
+	return rp.provider
+}
+
+func (rp defaultRemoteProvider) Endpoint() string {
+	return rp.endpoint
+}
+
+func (rp defaultRemoteProvider) Path() string {
+	return rp.path
+}
+
+func (rp defaultRemoteProvider) SecretKeyring() string {
+	return rp.secretKeyring
+}
+
+// RemoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type RemoteProvider interface {
+	Provider() string
+	Endpoint() string
+	Path() string
+	SecretKeyring() string
+}
+
+// AddRemoteProvider adds a remote configuration source.
+// Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+func AddRemoteProvider(provider, endpoint, path string) error {
+	return v.AddRemoteProvider(provider, endpoint, path)
+}
+
+func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint: endpoint,
+			provider: provider,
+			path:     path,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+// AddSecureRemoteProvider adds a remote configuration source.
+// Secure Remote Providers are searched in the order they are added.
+// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
+// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp".
+// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
+func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
+}
+
+func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
+	if !slices.Contains(SupportedRemoteProviders, provider) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
+
+		rp := &defaultRemoteProvider{
+			endpoint:      endpoint,
+			provider:      provider,
+			path:          path,
+			secretKeyring: secretkeyring,
+		}
+		if !v.providerPathExists(rp) {
+			v.remoteProviders = append(v.remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
+	for _, y := range v.remoteProviders {
+		if reflect.DeepEqual(y, p) {
+			return true
+		}
+	}
+	return false
+}
+
+// ReadRemoteConfig attempts to get configuration from a remote source
+// and read it in the remote configuration registry.
+func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
+
+func (v *Viper) ReadRemoteConfig() error {
+	return v.getKeyValueConfig()
+}
+
+func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
+func (v *Viper) WatchRemoteConfig() error {
+	return v.watchKeyValueConfig()
+}
+
+func (v *Viper) WatchRemoteConfigOnChannel() error {
+	return v.watchKeyValueConfigOnChannel()
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) getKeyValueConfig() error {
+	if RemoteConfig == nil {
+		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
+	}
+
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.getRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
+
+			continue
+		}
+
+		v.kvstore = val
+
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Get(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfigOnChannel() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		respc, _ := RemoteConfig.WatchChannel(rp)
+		// Todo: Add quit channel
+		go func(rc <-chan *RemoteResponse) {
+			for {
+				b := <-rc
+				reader := bytes.NewReader(b.Value)
+				v.unmarshalReader(reader, v.kvstore)
+			}
+		}(respc)
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+// Retrieve the first found remote configuration.
+func (v *Viper) watchKeyValueConfig() error {
+	if len(v.remoteProviders) == 0 {
+		return RemoteConfigError("No Remote Providers")
+	}
+
+	for _, rp := range v.remoteProviders {
+		val, err := v.watchRemoteConfig(rp)
+		if err != nil {
+			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
+
+			continue
+		}
+		v.kvstore = val
+		return nil
+	}
+	return RemoteConfigError("No Files Found")
+}
+
+func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
+	reader, err := RemoteConfig.Watch(provider)
+	if err != nil {
+		return nil, err
+	}
+	err = v.unmarshalReader(reader, v.kvstore)
+	return v.kvstore, err
+}
diff --git a/public-api/vendor/github.com/spf13/viper/util.go b/public-api/vendor/github.com/spf13/viper/util.go
index 52116ac4..2a08074b 100644
--- a/public-api/vendor/github.com/spf13/viper/util.go
+++ b/public-api/vendor/github.com/spf13/viper/util.go
@@ -12,13 +12,13 @@ package viper
 
 import (
 	"fmt"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"runtime"
 	"strings"
 	"unicode"
 
-	slog "github.com/sagikazarmark/slog-shim"
 	"github.com/spf13/cast"
 )
 
@@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string {
 	return ""
 }
 
-func stringInSlice(a string, list []string) bool {
-	for _, b := range list {
-		if b == a {
-			return true
-		}
-	}
-	return false
-}
-
 func userHomeDir() string {
 	if runtime.GOOS == "windows" {
 		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
@@ -156,7 +147,7 @@ func safeMul(a, b uint) uint {
 	return c
 }
 
-// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
+// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
 func parseSizeInBytes(sizeStr string) uint {
 	sizeStr = strings.TrimSpace(sizeStr)
 	lastChar := len(sizeStr) - 1
diff --git a/public-api/vendor/github.com/spf13/viper/viper.go b/public-api/vendor/github.com/spf13/viper/viper.go
index c1eab71b..a58d757b 100644
--- a/public-api/vendor/github.com/spf13/viper/viper.go
+++ b/public-api/vendor/github.com/spf13/viper/viper.go
@@ -25,29 +25,23 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"reflect"
+	"slices"
 	"strconv"
 	"strings"
 	"sync"
 	"time"
 
 	"github.com/fsnotify/fsnotify"
-	"github.com/mitchellh/mapstructure"
-	slog "github.com/sagikazarmark/slog-shim"
+	"github.com/go-viper/mapstructure/v2"
 	"github.com/spf13/afero"
 	"github.com/spf13/cast"
 	"github.com/spf13/pflag"
 
-	"github.com/spf13/viper/internal/encoding"
-	"github.com/spf13/viper/internal/encoding/dotenv"
-	"github.com/spf13/viper/internal/encoding/hcl"
-	"github.com/spf13/viper/internal/encoding/ini"
-	"github.com/spf13/viper/internal/encoding/javaproperties"
-	"github.com/spf13/viper/internal/encoding/json"
-	"github.com/spf13/viper/internal/encoding/toml"
-	"github.com/spf13/viper/internal/encoding/yaml"
+	"github.com/spf13/viper/internal/features"
 )
 
 // ConfigMarshalError happens when failing to marshal the configuration.
@@ -62,24 +56,10 @@ func (e ConfigMarshalError) Error() string {
 
 var v *Viper
 
-type RemoteResponse struct {
-	Value []byte
-	Error error
-}
-
 func init() {
 	v = New()
 }
 
-type remoteConfigFactory interface {
-	Get(rp RemoteProvider) (io.Reader, error)
-	Watch(rp RemoteProvider) (io.Reader, error)
-	WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
-}
-
-// RemoteConfig is optional, see the remote package
-var RemoteConfig remoteConfigFactory
-
 // UnsupportedConfigError denotes encountering an unsupported
 // configuration filetype.
 type UnsupportedConfigError string
@@ -89,24 +69,6 @@ func (str UnsupportedConfigError) Error() string {
 	return fmt.Sprintf("Unsupported Config Type %q", string(str))
 }
 
-// UnsupportedRemoteProviderError denotes encountering an unsupported remote
-// provider. Currently only etcd and Consul are supported.
-type UnsupportedRemoteProviderError string
-
-// Error returns the formatted remote provider error.
-func (str UnsupportedRemoteProviderError) Error() string {
-	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
-}
-
-// RemoteConfigError denotes encountering an error while trying to
-// pull the configuration from the remote provider.
-type RemoteConfigError string
-
-// Error returns the formatted remote provider error
-func (rce RemoteConfigError) Error() string {
-	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
-}
-
 // ConfigFileNotFoundError denotes failing to find configuration file.
 type ConfigFileNotFoundError struct {
 	name, locations string
@@ -126,7 +88,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string {
 }
 
 // A DecoderConfigOption can be passed to viper.Unmarshal to configure
-// mapstructure.DecoderConfig options
+// mapstructure.DecoderConfig options.
 type DecoderConfigOption func(*mapstructure.DecoderConfig)
 
 // DecodeHook returns a DecoderConfigOption which overrides the default
@@ -189,6 +151,8 @@ type Viper struct {
 	// The filesystem to read config from.
 	fs afero.Fs
 
+	finder Finder
+
 	// A set of remote providers to search for the configuration
 	remoteProviders []*defaultRemoteProvider
 
@@ -199,9 +163,6 @@ type Viper struct {
 	configPermissions os.FileMode
 	envPrefix         string
 
-	// Specific commands for ini parsing
-	iniLoadOptions ini.LoadOptions
-
 	automaticEnvApplied bool
 	envKeyReplacer      StringReplacer
 	allowEmptyEnv       bool
@@ -220,9 +181,13 @@ type Viper struct {
 
 	logger *slog.Logger
 
-	// TODO: should probably be protected with a mutex
-	encoderRegistry *encoding.EncoderRegistry
-	decoderRegistry *encoding.DecoderRegistry
+	encoderRegistry EncoderRegistry
+	decoderRegistry DecoderRegistry
+
+	decodeHook mapstructure.DecodeHookFunc
+
+	experimentalFinder     bool
+	experimentalBindStruct bool
 }
 
 // New returns an initialized Viper instance.
@@ -243,7 +208,13 @@ func New() *Viper {
 	v.typeByDefValue = false
 	v.logger = slog.New(&discardHandler{})
 
-	v.resetEncoding()
+	codecRegistry := NewCodecRegistry()
+
+	v.encoderRegistry = codecRegistry
+	v.decoderRegistry = codecRegistry
+
+	v.experimentalFinder = features.Finder
+	v.experimentalBindStruct = features.BindStruct
 
 	return v
 }
@@ -279,10 +250,25 @@ type StringReplacer interface {
 // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys.
 func EnvKeyReplacer(r StringReplacer) Option {
 	return optionFunc(func(v *Viper) {
+		if r == nil {
+			return
+		}
+
 		v.envKeyReplacer = r
 	})
 }
 
+// WithDecodeHook sets a default decode hook for mapstructure.
+func WithDecodeHook(h mapstructure.DecodeHookFunc) Option {
+	return optionFunc(func(v *Viper) {
+		if h == nil {
+			return
+		}
+
+		v.decodeHook = h
+	})
+}
+
 // NewWithOptions creates a new Viper instance.
 func NewWithOptions(opts ...Option) *Viper {
 	v := New()
@@ -291,138 +277,32 @@ func NewWithOptions(opts ...Option) *Viper {
 		opt.apply(v)
 	}
 
-	v.resetEncoding()
-
 	return v
 }
 
+// SetOptions sets the options on the global Viper instance.
+//
+// Be careful when using this function: subsequent calls may override options you set.
+// It's always better to use a local Viper instance.
+func SetOptions(opts ...Option) {
+	for _, opt := range opts {
+		opt.apply(v)
+	}
+}
+
 // Reset is intended for testing, will reset all to default settings.
 // In the public interface for the viper package so applications
 // can use it in their testing as well.
 func Reset() {
 	v = New()
 	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
-	SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-}
-
-// TODO: make this lazy initialization instead
-func (v *Viper) resetEncoding() {
-	encoderRegistry := encoding.NewEncoderRegistry()
-	decoderRegistry := encoding.NewDecoderRegistry()
-
-	{
-		codec := yaml.Codec{}
-
-		encoderRegistry.RegisterEncoder("yaml", codec)
-		decoderRegistry.RegisterDecoder("yaml", codec)
-
-		encoderRegistry.RegisterEncoder("yml", codec)
-		decoderRegistry.RegisterDecoder("yml", codec)
-	}
-
-	{
-		codec := json.Codec{}
-
-		encoderRegistry.RegisterEncoder("json", codec)
-		decoderRegistry.RegisterDecoder("json", codec)
-	}
-
-	{
-		codec := toml.Codec{}
-
-		encoderRegistry.RegisterEncoder("toml", codec)
-		decoderRegistry.RegisterDecoder("toml", codec)
-	}
-
-	{
-		codec := hcl.Codec{}
-
-		encoderRegistry.RegisterEncoder("hcl", codec)
-		decoderRegistry.RegisterDecoder("hcl", codec)
-
-		encoderRegistry.RegisterEncoder("tfvars", codec)
-		decoderRegistry.RegisterDecoder("tfvars", codec)
-	}
-
-	{
-		codec := ini.Codec{
-			KeyDelimiter: v.keyDelim,
-			LoadOptions:  v.iniLoadOptions,
-		}
-
-		encoderRegistry.RegisterEncoder("ini", codec)
-		decoderRegistry.RegisterDecoder("ini", codec)
-	}
-
-	{
-		codec := &javaproperties.Codec{
-			KeyDelimiter: v.keyDelim,
-		}
-
-		encoderRegistry.RegisterEncoder("properties", codec)
-		decoderRegistry.RegisterDecoder("properties", codec)
-
-		encoderRegistry.RegisterEncoder("props", codec)
-		decoderRegistry.RegisterDecoder("props", codec)
-
-		encoderRegistry.RegisterEncoder("prop", codec)
-		decoderRegistry.RegisterDecoder("prop", codec)
-	}
-
-	{
-		codec := &dotenv.Codec{}
 
-		encoderRegistry.RegisterEncoder("dotenv", codec)
-		decoderRegistry.RegisterDecoder("dotenv", codec)
-
-		encoderRegistry.RegisterEncoder("env", codec)
-		decoderRegistry.RegisterDecoder("env", codec)
-	}
-
-	v.encoderRegistry = encoderRegistry
-	v.decoderRegistry = decoderRegistry
-}
-
-type defaultRemoteProvider struct {
-	provider      string
-	endpoint      string
-	path          string
-	secretKeyring string
-}
-
-func (rp defaultRemoteProvider) Provider() string {
-	return rp.provider
-}
-
-func (rp defaultRemoteProvider) Endpoint() string {
-	return rp.endpoint
-}
-
-func (rp defaultRemoteProvider) Path() string {
-	return rp.path
-}
-
-func (rp defaultRemoteProvider) SecretKeyring() string {
-	return rp.secretKeyring
-}
-
-// RemoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type RemoteProvider interface {
-	Provider() string
-	Endpoint() string
-	Path() string
-	SecretKeyring() string
+	resetRemote()
 }
 
 // SupportedExts are universally supported extensions.
 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
 
-// SupportedRemoteProviders are universally supported remote providers.
-var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-
 // OnConfigChange sets the event handler that is called when a config file changes.
 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
 
@@ -439,7 +319,7 @@ func (v *Viper) WatchConfig() {
 	initWG := sync.WaitGroup{}
 	initWG.Add(1)
 	go func() {
-		watcher, err := newWatcher()
+		watcher, err := fsnotify.NewWatcher()
 		if err != nil {
 			v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
 			os.Exit(1)
@@ -573,90 +453,20 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile }
 func AddConfigPath(in string) { v.AddConfigPath(in) }
 
 func (v *Viper) AddConfigPath(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath"))
+	}
+
 	if in != "" {
 		absin := absPathify(v.logger, in)
 
 		v.logger.Info("adding path to search paths", "path", absin)
-		if !stringInSlice(absin, v.configPaths) {
+		if !slices.Contains(v.configPaths, absin) {
 			v.configPaths = append(v.configPaths, absin)
 		}
 	}
 }
 
-// AddRemoteProvider adds a remote configuration source.
-// Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-func AddRemoteProvider(provider, endpoint, path string) error {
-	return v.AddRemoteProvider(provider, endpoint, path)
-}
-
-func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint: endpoint,
-			provider: provider,
-			path:     path,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-// AddSecureRemoteProvider adds a remote configuration source.
-// Secure Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
-// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp"
-// Secure Remote Providers are implemented with github.com/bketelsen/crypt
-func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
-}
-
-func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
-	if !stringInSlice(provider, SupportedRemoteProviders) {
-		return UnsupportedRemoteProviderError(provider)
-	}
-	if provider != "" && endpoint != "" {
-		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
-		rp := &defaultRemoteProvider{
-			endpoint:      endpoint,
-			provider:      provider,
-			path:          path,
-			secretKeyring: secretkeyring,
-		}
-		if !v.providerPathExists(rp) {
-			v.remoteProviders = append(v.remoteProviders, rp)
-		}
-	}
-	return nil
-}
-
-func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
-	for _, y := range v.remoteProviders {
-		if reflect.DeepEqual(y, p) {
-			return true
-		}
-	}
-	return false
-}
-
 // 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.
@@ -827,10 +637,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string
 //	"foo.bar.baz" in a lower-priority map
 func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
 	// unify input map
-	var m map[string]any
-	switch mi.(type) {
-	case map[string]string, map[string]FlagValue:
-		m = cast.ToStringMap(mi)
+	var m map[string]interface{}
+	switch miv := mi.(type) {
+	case map[string]string:
+		m = castMapStringToMapInterface(miv)
+	case map[string]FlagValue:
+		m = castMapFlagToMapInterface(miv)
 	default:
 		return ""
 	}
@@ -957,10 +769,12 @@ func (v *Viper) Sub(key string) *Viper {
 	}
 
 	if reflect.TypeOf(data).Kind() == reflect.Map {
-		subv.parents = append(v.parents, strings.ToLower(key))
+		subv.parents = append([]string(nil), v.parents...)
+		subv.parents = append(subv.parents, strings.ToLower(key))
 		subv.automaticEnvApplied = v.automaticEnvApplied
 		subv.envPrefix = v.envPrefix
 		subv.envKeyReplacer = v.envKeyReplacer
+		subv.keyDelim = v.keyDelim
 		subv.config = cast.ToStringMap(data)
 		return subv
 	}
@@ -1002,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 {
 	return cast.ToInt64(v.Get(key))
 }
 
+// GetUint8 returns the value associated with the key as an unsigned integer.
+func GetUint8(key string) uint8 { return v.GetUint8(key) }
+
+func (v *Viper) GetUint8(key string) uint8 {
+	return cast.ToUint8(v.Get(key))
+}
+
 // GetUint returns the value associated with the key as an unsigned integer.
 func GetUint(key string) uint { return v.GetUint(key) }
 
@@ -1101,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
+	return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...))
 }
 
 // Unmarshal unmarshals the config into a Struct. Make sure that the tags
@@ -1111,28 +932,91 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
-	return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...))
+}
+
+func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
+	var structKeyMap map[string]any
+
+	err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...))
+	if err != nil {
+		return nil, err
+	}
+
+	flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
+
+	r := make([]string, 0, len(flattenedStructKeyMap))
+	for v := range flattenedStructKeyMap {
+		r = append(r, v)
+	}
+
+	return r, nil
 }
 
 // defaultDecoderConfig returns default mapstructure.DecoderConfig with support
-// of time.Duration values & string slices
-func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+// of time.Duration values & string slices.
+func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
+	decodeHook := v.decodeHook
+	if decodeHook == nil {
+		decodeHook = mapstructure.ComposeDecodeHookFunc(
+			mapstructure.StringToTimeDurationHookFunc(),
+			// mapstructure.StringToSliceHookFunc(","),
+			stringToWeakSliceHookFunc(","),
+		)
+	}
+
 	c := &mapstructure.DecoderConfig{
 		Metadata:         nil,
-		Result:           output,
 		WeaklyTypedInput: true,
-		DecodeHook: mapstructure.ComposeDecodeHookFunc(
-			mapstructure.StringToTimeDurationHookFunc(),
-			mapstructure.StringToSliceHookFunc(","),
-		),
+		DecodeHook:       decodeHook,
 	}
+
 	for _, opt := range opts {
 		opt(c)
 	}
+
+	// Do not allow overwriting the output
+	c.Result = output
+
 	return c
 }
 
-// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
+// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice.
+// This function removes that check.
+// TODO: implement a function that checks if the value can be converted to the return type and use it instead.
+func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data interface{},
+	) (interface{}, error) {
+		if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
+			return data, nil
+		}
+
+		raw := data.(string)
+		if raw == "" {
+			return []string{}, nil
+		}
+
+		return strings.Split(raw, sep), nil
+	}
+}
+
+// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
 func decode(input any, config *mapstructure.DecoderConfig) error {
 	decoder, err := mapstructure.NewDecoder(config)
 	if err != nil {
@@ -1148,10 +1032,23 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
 }
 
 func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
-	config := defaultDecoderConfig(rawVal, opts...)
+	config := v.defaultDecoderConfig(rawVal, opts...)
 	config.ErrorUnused = true
 
-	return decode(v.AllSettings(), config)
+	keys := v.AllKeys()
+
+	if v.experimentalBindStruct {
+		// TODO: make this optional?
+		structKeys, err := v.decodeStructKeys(rawVal, opts...)
+		if err != nil {
+			return err
+		}
+
+		keys = append(keys, structKeys...)
+	}
+
+	// TODO: struct keys should be enough?
+	return decode(v.getSettings(keys), config)
 }
 
 // BindPFlags binds a full flag set to the configuration, using each flag's long
@@ -1405,11 +1302,11 @@ 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	r := csv.NewReader(strings.NewReader(val))
@@ -1429,11 +1326,11 @@ func stringToStringConv(val string) any {
 }
 
 // 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]any is returned in order to enable cast.ToStringMap
+// 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 {
+	if val == "" {
 		return map[string]any{}
 	}
 	ss := strings.Split(val, ",")
@@ -1481,13 +1378,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
 
 // RegisterAlias creates an alias that provides another accessor for the same key.
 // This enables one to change a name without breaking the application.
-func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
+func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
 
-func (v *Viper) RegisterAlias(alias string, key string) {
+func (v *Viper) RegisterAlias(alias, key string) {
 	v.registerAlias(alias, strings.ToLower(key))
 }
 
-func (v *Viper) registerAlias(alias string, key string) {
+func (v *Viper) registerAlias(alias, key string) {
 	alias = strings.ToLower(alias)
 	if alias != key && alias != v.realKey(key) {
 		_, exists := v.aliases[alias]
@@ -1590,7 +1487,7 @@ func (v *Viper) ReadInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1621,7 +1518,7 @@ func (v *Viper) MergeInConfig() error {
 		return err
 	}
 
-	if !stringInSlice(v.getConfigType(), SupportedExts) {
+	if !slices.Contains(SupportedExts, v.getConfigType()) {
 		return UnsupportedConfigError(v.getConfigType())
 	}
 
@@ -1638,19 +1535,29 @@ 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]any)
-	return v.unmarshalReader(in, v.config)
+	config := make(map[string]any)
+
+	err := v.unmarshalReader(in, config)
+	if err != nil {
+		return err
+	}
+
+	v.config = config
+
+	return nil
 }
 
 // MergeConfig merges a new configuration with an existing config.
 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
 
 func (v *Viper) MergeConfig(in io.Reader) error {
-	cfg := make(map[string]any)
-	if err := v.unmarshalReader(in, cfg); err != nil {
+	config := make(map[string]any)
+
+	if err := v.unmarshalReader(in, config); err != nil {
 		return err
 	}
-	return v.MergeConfigMap(cfg)
+
+	return v.MergeConfigMap(config)
 }
 
 // MergeConfigMap merges the configuration from the map given with an existing config.
@@ -1694,6 +1601,19 @@ func (v *Viper) WriteConfigAs(filename string) error {
 	return v.writeConfig(filename, true)
 }
 
+// WriteConfigTo writes current configuration to an [io.Writer].
+func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) }
+
+func (v *Viper) WriteConfigTo(w io.Writer) error {
+	format := strings.ToLower(v.getConfigType())
+
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	return v.marshalWriter(w, format)
+}
+
 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
 
@@ -1720,7 +1640,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 		return fmt.Errorf("config type could not be determined for %s", filename)
 	}
 
-	if !stringInSlice(configType, SupportedExts) {
+	if !slices.Contains(SupportedExts, configType) {
 		return UnsupportedConfigError(configType)
 	}
 	if v.config == nil {
@@ -1743,22 +1663,30 @@ func (v *Viper) writeConfig(filename string, force bool) error {
 	return f.Sync()
 }
 
-// Unmarshal a Reader into a map.
-// Should probably be an unexported function.
-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]any) error {
+	format := strings.ToLower(v.getConfigType())
+	if format == "" {
+		return errors.New("cannot decode configuration: unable to determine config type")
+	}
+
 	buf := new(bytes.Buffer)
 	buf.ReadFrom(in)
 
-	switch format := strings.ToLower(v.getConfigType()); format {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
-		err := v.decoderRegistry.Decode(format, buf.Bytes(), c)
-		if err != nil {
-			return ConfigParseError{err}
-		}
+	// TODO: remove this once SupportedExts is deprecated/removed
+	if !slices.Contains(SupportedExts, format) {
+		return UnsupportedConfigError(format)
+	}
+
+	// TODO: return [UnsupportedConfigError] if the registry does not contain the format
+	// TODO: consider deprecating this error type
+	decoder, err := v.decoderRegistry.Decoder(format)
+	if err != nil {
+		return ConfigParseError{err}
+	}
+
+	err = decoder.Decode(buf.Bytes(), c)
+	if err != nil {
+		return ConfigParseError{err}
 	}
 
 	insensitiviseMap(c)
@@ -1766,20 +1694,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
 }
 
 // Marshal a map into Writer.
-func (v *Viper) marshalWriter(f afero.File, configType string) error {
+func (v *Viper) marshalWriter(w io.Writer, configType string) error {
 	c := v.AllSettings()
-	switch configType {
-	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
-		b, err := v.encoderRegistry.Encode(configType, c)
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
 
-		_, err = f.WriteString(string(b))
-		if err != nil {
-			return ConfigMarshalError{err}
-		}
+	encoder, err := v.encoderRegistry.Encoder(configType)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	b, err := encoder.Encode(c)
+	if err != nil {
+		return ConfigMarshalError{err}
+	}
+
+	_, err = w.Write(b)
+	if err != nil {
+		return ConfigMarshalError{err}
 	}
+
 	return nil
 }
 
@@ -1911,108 +1843,8 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
 	}
 }
 
-// ReadRemoteConfig attempts to get configuration from a remote source
-// and read it in the remote configuration registry.
-func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
-
-func (v *Viper) ReadRemoteConfig() error {
-	return v.getKeyValueConfig()
-}
-
-func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
-func (v *Viper) WatchRemoteConfig() error {
-	return v.watchKeyValueConfig()
-}
-
-func (v *Viper) WatchRemoteConfigOnChannel() error {
-	return v.watchKeyValueConfigOnChannel()
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) getKeyValueConfig() error {
-	if RemoteConfig == nil {
-		return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
-	}
-
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.getRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
-
-			continue
-		}
-
-		v.kvstore = val
-
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Get(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfigOnChannel() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		respc, _ := RemoteConfig.WatchChannel(rp)
-		// Todo: Add quit channel
-		go func(rc <-chan *RemoteResponse) {
-			for {
-				b := <-rc
-				reader := bytes.NewReader(b.Value)
-				v.unmarshalReader(reader, v.kvstore)
-			}
-		}(respc)
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfig() error {
-	if len(v.remoteProviders) == 0 {
-		return RemoteConfigError("No Remote Providers")
-	}
-
-	for _, rp := range v.remoteProviders {
-		val, err := v.watchRemoteConfig(rp)
-		if err != nil {
-			v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
-
-			continue
-		}
-		v.kvstore = val
-		return nil
-	}
-	return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
-	reader, err := RemoteConfig.Watch(provider)
-	if err != nil {
-		return nil, err
-	}
-	err = v.unmarshalReader(reader, v.kvstore)
-	return v.kvstore, err
-}
-
 // AllKeys returns all keys holding a value, regardless of where they are set.
-// Nested keys are returned with a v.keyDelim separator
+// Nested keys are returned with a v.keyDelim separator.
 func AllKeys() []string { return v.AllKeys() }
 
 func (v *Viper) AllKeys() []string {
@@ -2098,9 +1930,13 @@ outer:
 func AllSettings() map[string]any { return v.AllSettings() }
 
 func (v *Viper) AllSettings() map[string]any {
+	return v.getSettings(v.AllKeys())
+}
+
+func (v *Viper) getSettings(keys []string) 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() {
+	for _, k := range keys {
 		value := v.Get(k)
 		if value == nil {
 			// should not happen, since AllKeys() returns only keys holding a value,
@@ -2128,6 +1964,10 @@ func (v *Viper) SetFs(fs afero.Fs) {
 func SetConfigName(in string) { v.SetConfigName(in) }
 
 func (v *Viper) SetConfigName(in string) {
+	if v.finder != nil {
+		v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName"))
+	}
+
 	if in != "" {
 		v.configName = in
 		v.configFile = ""
@@ -2151,13 +1991,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) {
 	v.configPermissions = perm.Perm()
 }
 
-// IniLoadOptions sets the load options for ini parsing.
-func IniLoadOptions(in ini.LoadOptions) Option {
-	return optionFunc(func(v *Viper) {
-		v.iniLoadOptions = in
-	})
-}
-
 func (v *Viper) getConfigType() string {
 	if v.configType != "" {
 		return v.configType
diff --git a/public-api/vendor/github.com/spf13/viper/viper_go1_15.go b/public-api/vendor/github.com/spf13/viper/viper_go1_15.go
deleted file mode 100644
index 7fc6aff3..00000000
--- a/public-api/vendor/github.com/spf13/viper/viper_go1_15.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build !finder
-
-package viper
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-
-	"github.com/spf13/afero"
-)
-
-// Search all configPaths for any config file.
-// Returns the first path that exists (and is a config file).
-func (v *Viper) findConfigFile() (string, error) {
-	v.logger.Info("searching for config in paths", "paths", v.configPaths)
-
-	for _, cp := range v.configPaths {
-		file := v.searchInPath(cp)
-		if file != "" {
-			return file, nil
-		}
-	}
-	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-}
-
-func (v *Viper) searchInPath(in string) (filename string) {
-	v.logger.Debug("searching for config in path", "path", in)
-	for _, ext := range SupportedExts {
-		v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
-			v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
-			return filepath.Join(in, v.configName+"."+ext)
-		}
-	}
-
-	if v.configType != "" {
-		if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
-			return filepath.Join(in, v.configName)
-		}
-	}
-
-	return ""
-}
-
-// Check if file Exists
-func exists(fs afero.Fs, path string) (bool, error) {
-	stat, err := fs.Stat(path)
-	if err == nil {
-		return !stat.IsDir(), nil
-	}
-	if os.IsNotExist(err) {
-		return false, nil
-	}
-	return false, err
-}
diff --git a/public-api/vendor/github.com/spf13/viper/viper_go1_16.go b/public-api/vendor/github.com/spf13/viper/viper_go1_16.go
deleted file mode 100644
index d96a1bd2..00000000
--- a/public-api/vendor/github.com/spf13/viper/viper_go1_16.go
+++ /dev/null
@@ -1,38 +0,0 @@
-//go:build finder
-
-package viper
-
-import (
-	"fmt"
-
-	"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) {
-	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,
-	}
-
-	results, err := finder.Find(v.fs)
-	if err != nil {
-		return "", err
-	}
-
-	if len(results) == 0 {
-		return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-	}
-
-	return results[0], nil
-}
diff --git a/public-api/vendor/github.com/spf13/viper/watch.go b/public-api/vendor/github.com/spf13/viper/watch.go
deleted file mode 100644
index e98fce89..00000000
--- a/public-api/vendor/github.com/spf13/viper/watch.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
-
-package viper
-
-import "github.com/fsnotify/fsnotify"
-
-type watcher = fsnotify.Watcher
-
-func newWatcher() (*watcher, error) {
-	return fsnotify.NewWatcher()
-}
diff --git a/public-api/vendor/github.com/spf13/viper/watch_unsupported.go b/public-api/vendor/github.com/spf13/viper/watch_unsupported.go
deleted file mode 100644
index 70764056..00000000
--- a/public-api/vendor/github.com/spf13/viper/watch_unsupported.go
+++ /dev/null
@@ -1,31 +0,0 @@
-//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
-
-package viper
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/fsnotify/fsnotify"
-)
-
-func newWatcher() (*watcher, error) {
-	return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
-}
-
-type watcher struct {
-	Events chan fsnotify.Event
-	Errors chan error
-}
-
-func (*watcher) Close() error {
-	return nil
-}
-
-func (*watcher) Add(name string) error {
-	return nil
-}
-
-func (*watcher) Remove(name string) error {
-	return nil
-}
diff --git a/public-api/vendor/golang.org/x/exp/constraints/constraints.go b/public-api/vendor/golang.org/x/exp/constraints/constraints.go
deleted file mode 100644
index 2c033dff..00000000
--- a/public-api/vendor/golang.org/x/exp/constraints/constraints.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package constraints defines a set of useful constraints to be used
-// with type parameters.
-package constraints
-
-// Signed is a constraint that permits any signed integer type.
-// If future releases of Go add new predeclared signed integer types,
-// this constraint will be modified to include them.
-type Signed interface {
-	~int | ~int8 | ~int16 | ~int32 | ~int64
-}
-
-// Unsigned is a constraint that permits any unsigned integer type.
-// If future releases of Go add new predeclared unsigned integer types,
-// this constraint will be modified to include them.
-type Unsigned interface {
-	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
-// Integer is a constraint that permits any integer type.
-// If future releases of Go add new predeclared integer types,
-// this constraint will be modified to include them.
-type Integer interface {
-	Signed | Unsigned
-}
-
-// Float is a constraint that permits any floating-point type.
-// If future releases of Go add new predeclared floating-point types,
-// this constraint will be modified to include them.
-type Float interface {
-	~float32 | ~float64
-}
-
-// Complex is a constraint that permits any complex numeric type.
-// If future releases of Go add new predeclared complex numeric types,
-// this constraint will be modified to include them.
-type Complex interface {
-	~complex64 | ~complex128
-}
-
-// Ordered is a constraint that permits any ordered type: any type
-// that supports the operators < <= >= >.
-// If future releases of Go add new ordered types,
-// this constraint will be modified to include them.
-type Ordered interface {
-	Integer | Float | ~string
-}
diff --git a/public-api/vendor/golang.org/x/exp/slices/cmp.go b/public-api/vendor/golang.org/x/exp/slices/cmp.go
deleted file mode 100644
index fbf1934a..00000000
--- a/public-api/vendor/golang.org/x/exp/slices/cmp.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-import "golang.org/x/exp/constraints"
-
-// min is a version of the predeclared function from the Go 1.21 release.
-func min[T constraints.Ordered](a, b T) T {
-	if a < b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// max is a version of the predeclared function from the Go 1.21 release.
-func max[T constraints.Ordered](a, b T) T {
-	if a > b || isNaN(a) {
-		return a
-	}
-	return b
-}
-
-// cmpLess is a copy of cmp.Less from the Go 1.21 release.
-func cmpLess[T constraints.Ordered](x, y T) bool {
-	return (isNaN(x) && !isNaN(y)) || x < y
-}
-
-// cmpCompare is a copy of cmp.Compare from the Go 1.21 release.
-func cmpCompare[T constraints.Ordered](x, y T) int {
-	xNaN := isNaN(x)
-	yNaN := isNaN(y)
-	if xNaN && yNaN {
-		return 0
-	}
-	if xNaN || x < y {
-		return -1
-	}
-	if yNaN || x > y {
-		return +1
-	}
-	return 0
-}
diff --git a/public-api/vendor/golang.org/x/exp/slices/slices.go b/public-api/vendor/golang.org/x/exp/slices/slices.go
deleted file mode 100644
index 46ceac34..00000000
--- a/public-api/vendor/golang.org/x/exp/slices/slices.go
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package slices defines various functions useful with slices of any type.
-package slices
-
-import (
-	"unsafe"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Equal reports whether two slices are equal: the same length and all
-// elements equal. If the lengths are different, Equal returns false.
-// Otherwise, the elements are compared in increasing index order, and the
-// comparison stops at the first unequal pair.
-// Floating point NaNs are not considered equal.
-func Equal[S ~[]E, E comparable](s1, s2 S) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i := range s1 {
-		if s1[i] != s2[i] {
-			return false
-		}
-	}
-	return true
-}
-
-// EqualFunc reports whether two slices are equal using an equality
-// function on each pair of elements. If the lengths are different,
-// EqualFunc returns false. Otherwise, the elements are compared in
-// increasing index order, and the comparison stops at the first index
-// for which eq returns false.
-func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
-	if len(s1) != len(s2) {
-		return false
-	}
-	for i, v1 := range s1 {
-		v2 := s2[i]
-		if !eq(v1, v2) {
-			return false
-		}
-	}
-	return true
-}
-
-// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair
-// of elements. The elements are compared sequentially, starting at index 0,
-// until one element is not equal to the other.
-// The result of comparing the first non-matching elements is returned.
-// If both slices are equal until one of them ends, the shorter slice is
-// considered less than the longer one.
-// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2.
-func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmpCompare(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// CompareFunc is like [Compare] but uses a custom comparison function on each
-// pair of elements.
-// The result is the first non-zero result of cmp; if cmp always
-// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
-// and +1 if len(s1) > len(s2).
-func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
-	for i, v1 := range s1 {
-		if i >= len(s2) {
-			return +1
-		}
-		v2 := s2[i]
-		if c := cmp(v1, v2); c != 0 {
-			return c
-		}
-	}
-	if len(s1) < len(s2) {
-		return -1
-	}
-	return 0
-}
-
-// Index returns the index of the first occurrence of v in s,
-// or -1 if not present.
-func Index[S ~[]E, E comparable](s S, v E) int {
-	for i := range s {
-		if v == s[i] {
-			return i
-		}
-	}
-	return -1
-}
-
-// IndexFunc returns the first index i satisfying f(s[i]),
-// or -1 if none do.
-func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
-	for i := range s {
-		if f(s[i]) {
-			return i
-		}
-	}
-	return -1
-}
-
-// Contains reports whether v is present in s.
-func Contains[S ~[]E, E comparable](s S, v E) bool {
-	return Index(s, v) >= 0
-}
-
-// ContainsFunc reports whether at least one
-// element e of s satisfies f(e).
-func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
-	return IndexFunc(s, f) >= 0
-}
-
-// Insert inserts the values v... into s at index i,
-// returning the modified slice.
-// The elements at s[i:] are shifted up to make room.
-// In the returned slice r, r[i] == v[0],
-// and r[i+len(v)] == value originally at r[i].
-// Insert panics if i is out of range.
-// This function is O(len(s) + len(v)).
-func Insert[S ~[]E, E any](s S, i int, v ...E) S {
-	m := len(v)
-	if m == 0 {
-		return s
-	}
-	n := len(s)
-	if i == n {
-		return append(s, v...)
-	}
-	if n+m > cap(s) {
-		// Use append rather than make so that we bump the size of
-		// the slice up to the next storage class.
-		// This is what Grow does but we don't call Grow because
-		// that might copy the values twice.
-		s2 := append(s[:i], make(S, n+m-i)...)
-		copy(s2[i:], v)
-		copy(s2[i+m:], s[i:])
-		return s2
-	}
-	s = s[:n+m]
-
-	// before:
-	// s: aaaaaaaabbbbccccccccdddd
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// after:
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	//
-	// a are the values that don't move in s.
-	// v are the values copied in from v.
-	// b and c are the values from s that are shifted up in index.
-	// d are the values that get overwritten, never to be seen again.
-
-	if !overlaps(v, s[i+m:]) {
-		// Easy case - v does not overlap either the c or d regions.
-		// (It might be in some of a or b, or elsewhere entirely.)
-		// The data we copy up doesn't write to v at all, so just do it.
-
-		copy(s[i+m:], s[i:])
-
-		// Now we have
-		// s: aaaaaaaabbbbbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// Note the b values are duplicated.
-
-		copy(s[i:], v)
-
-		// Now we have
-		// s: aaaaaaaavvvvbbbbcccccccc
-		//            ^   ^       ^   ^
-		//            i  i+m      n  n+m
-		// That's the result we want.
-		return s
-	}
-
-	// The hard case - v overlaps c or d. We can't just shift up
-	// the data because we'd move or clobber the values we're trying
-	// to insert.
-	// So instead, write v on top of d, then rotate.
-	copy(s[n:], v)
-
-	// Now we have
-	// s: aaaaaaaabbbbccccccccvvvv
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-
-	rotateRight(s[i:], m)
-
-	// Now we have
-	// s: aaaaaaaavvvvbbbbcccccccc
-	//            ^   ^       ^   ^
-	//            i  i+m      n  n+m
-	// That's the result we want.
-	return s
-}
-
-// clearSlice sets all elements up to the length of s to the zero value of E.
-// We may use the builtin clear func instead, and remove clearSlice, when upgrading
-// to Go 1.21+.
-func clearSlice[S ~[]E, E any](s S) {
-	var zero E
-	for i := range s {
-		s[i] = zero
-	}
-}
-
-// Delete removes the elements s[i:j] from s, returning the modified slice.
-// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
-// Delete is O(len(s)-i), so if many items must be deleted, it is better to
-// make a single call deleting them all together than to delete one at a time.
-// Delete zeroes the elements s[len(s)-(j-i):len(s)].
-func Delete[S ~[]E, E any](s S, i, j int) S {
-	_ = s[i:j:len(s)] // bounds check
-
-	if i == j {
-		return s
-	}
-
-	oldlen := len(s)
-	s = append(s[:i], s[j:]...)
-	clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC
-	return s
-}
-
-// DeleteFunc removes any elements from s for which del returns true,
-// returning the modified slice.
-// DeleteFunc zeroes the elements between the new length and the original length.
-func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
-	i := IndexFunc(s, del)
-	if i == -1 {
-		return s
-	}
-	// Don't start copying elements until we find one to delete.
-	for j := i + 1; j < len(s); j++ {
-		if v := s[j]; !del(v) {
-			s[i] = v
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Replace replaces the elements s[i:j] by the given v, and returns the
-// modified slice. Replace panics if s[i:j] is not a valid slice of s.
-// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
-func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
-	_ = s[i:j] // verify that i:j is a valid subslice
-
-	if i == j {
-		return Insert(s, i, v...)
-	}
-	if j == len(s) {
-		return append(s[:i], v...)
-	}
-
-	tot := len(s[:i]) + len(v) + len(s[j:])
-	if tot > cap(s) {
-		// Too big to fit, allocate and copy over.
-		s2 := append(s[:i], make(S, tot-i)...) // See Insert
-		copy(s2[i:], v)
-		copy(s2[i+len(v):], s[j:])
-		return s2
-	}
-
-	r := s[:tot]
-
-	if i+len(v) <= j {
-		// Easy, as v fits in the deleted portion.
-		copy(r[i:], v)
-		if i+len(v) != j {
-			copy(r[i+len(v):], s[j:])
-		}
-		clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC
-		return r
-	}
-
-	// We are expanding (v is bigger than j-i).
-	// The situation is something like this:
-	// (example has i=4,j=8,len(s)=16,len(v)=6)
-	// s: aaaaxxxxbbbbbbbbyy
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	// a: prefix of s
-	// x: deleted range
-	// b: more of s
-	// y: area to expand into
-
-	if !overlaps(r[i+len(v):], v) {
-		// Easy, as v is not clobbered by the first copy.
-		copy(r[i+len(v):], s[j:])
-		copy(r[i:], v)
-		return r
-	}
-
-	// This is a situation where we don't have a single place to which
-	// we can copy v. Parts of it need to go to two different places.
-	// We want to copy the prefix of v into y and the suffix into x, then
-	// rotate |y| spots to the right.
-	//
-	//        v[2:]      v[:2]
-	//         |           |
-	// s: aaaavvvvbbbbbbbbvv
-	//        ^   ^       ^ ^
-	//        i   j  len(s) tot
-	//
-	// If either of those two destinations don't alias v, then we're good.
-	y := len(v) - (j - i) // length of y portion
-
-	if !overlaps(r[i:j], v) {
-		copy(r[i:j], v[y:])
-		copy(r[len(s):], v[:y])
-		rotateRight(r[i:], y)
-		return r
-	}
-	if !overlaps(r[len(s):], v) {
-		copy(r[len(s):], v[:y])
-		copy(r[i:j], v[y:])
-		rotateRight(r[i:], y)
-		return r
-	}
-
-	// Now we know that v overlaps both x and y.
-	// That means that the entirety of b is *inside* v.
-	// So we don't need to preserve b at all; instead we
-	// can copy v first, then copy the b part of v out of
-	// v to the right destination.
-	k := startIdx(v, s[j:])
-	copy(r[i:], v)
-	copy(r[i+len(v):], r[i+k:])
-	return r
-}
-
-// Clone returns a copy of the slice.
-// The elements are copied using assignment, so this is a shallow clone.
-func Clone[S ~[]E, E any](s S) S {
-	// Preserve nil in case it matters.
-	if s == nil {
-		return nil
-	}
-	return append(S([]E{}), s...)
-}
-
-// Compact replaces consecutive runs of equal elements with a single copy.
-// This is like the uniq command found on Unix.
-// Compact modifies the contents of the slice s and returns the modified slice,
-// which may have a smaller length.
-// Compact zeroes the elements between the new length and the original length.
-func Compact[S ~[]E, E comparable](s S) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if s[k] != s[k-1] {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// CompactFunc is like [Compact] but uses an equality function to compare elements.
-// For runs of elements that compare equal, CompactFunc keeps the first one.
-// CompactFunc zeroes the elements between the new length and the original length.
-func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
-	if len(s) < 2 {
-		return s
-	}
-	i := 1
-	for k := 1; k < len(s); k++ {
-		if !eq(s[k], s[k-1]) {
-			if i != k {
-				s[i] = s[k]
-			}
-			i++
-		}
-	}
-	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
-	return s[:i]
-}
-
-// Grow increases the slice's capacity, if necessary, to guarantee space for
-// another n elements. After Grow(n), at least n elements can be appended
-// to the slice without another allocation. If n is negative or too large to
-// allocate the memory, Grow panics.
-func Grow[S ~[]E, E any](s S, n int) S {
-	if n < 0 {
-		panic("cannot be negative")
-	}
-	if n -= cap(s) - len(s); n > 0 {
-		// TODO(https://go.dev/issue/53888): Make using []E instead of S
-		// to workaround a compiler bug where the runtime.growslice optimization
-		// does not take effect. Revert when the compiler is fixed.
-		s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)]
-	}
-	return s
-}
-
-// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
-func Clip[S ~[]E, E any](s S) S {
-	return s[:len(s):len(s)]
-}
-
-// Rotation algorithm explanation:
-//
-// rotate left by 2
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join first parts
-//   89234567 01
-// recursively rotate first left part by 2
-//   23456789 01
-// join at the end
-//   2345678901
-//
-// rotate left by 8
-// start with
-//   0123456789
-// split up like this
-//   01 234567 89
-// swap first 2 and last 2
-//   89 234567 01
-// join last parts
-//   89 23456701
-// recursively rotate second part left by 6
-//   89 01234567
-// join at the end
-//   8901234567
-
-// TODO: There are other rotate algorithms.
-// This algorithm has the desirable property that it moves each element exactly twice.
-// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes.
-// The follow-cycles algorithm can be 1-write but it is not very cache friendly.
-
-// rotateLeft rotates b left by n spaces.
-// s_final[i] = s_orig[i+r], wrapping around.
-func rotateLeft[E any](s []E, r int) {
-	for r != 0 && r != len(s) {
-		if r*2 <= len(s) {
-			swap(s[:r], s[len(s)-r:])
-			s = s[:len(s)-r]
-		} else {
-			swap(s[:len(s)-r], s[r:])
-			s, r = s[len(s)-r:], r*2-len(s)
-		}
-	}
-}
-func rotateRight[E any](s []E, r int) {
-	rotateLeft(s, len(s)-r)
-}
-
-// swap swaps the contents of x and y. x and y must be equal length and disjoint.
-func swap[E any](x, y []E) {
-	for i := 0; i < len(x); i++ {
-		x[i], y[i] = y[i], x[i]
-	}
-}
-
-// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap.
-func overlaps[E any](a, b []E) bool {
-	if len(a) == 0 || len(b) == 0 {
-		return false
-	}
-	elemSize := unsafe.Sizeof(a[0])
-	if elemSize == 0 {
-		return false
-	}
-	// TODO: use a runtime/unsafe facility once one becomes available. See issue 12445.
-	// Also see crypto/internal/alias/alias.go:AnyOverlap
-	return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) &&
-		uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1)
-}
-
-// startIdx returns the index in haystack where the needle starts.
-// prerequisite: the needle must be aliased entirely inside the haystack.
-func startIdx[E any](haystack, needle []E) int {
-	p := &needle[0]
-	for i := range haystack {
-		if p == &haystack[i] {
-			return i
-		}
-	}
-	// TODO: what if the overlap is by a non-integral number of Es?
-	panic("needle not found")
-}
-
-// Reverse reverses the elements of the slice in place.
-func Reverse[S ~[]E, E any](s S) {
-	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
-		s[i], s[j] = s[j], s[i]
-	}
-}
diff --git a/public-api/vendor/golang.org/x/exp/slices/sort.go b/public-api/vendor/golang.org/x/exp/slices/sort.go
deleted file mode 100644
index f58bbc7b..00000000
--- a/public-api/vendor/golang.org/x/exp/slices/sort.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp
-
-package slices
-
-import (
-	"math/bits"
-
-	"golang.org/x/exp/constraints"
-)
-
-// Sort sorts a slice of any ordered type in ascending order.
-// When sorting floating-point numbers, NaNs are ordered before other values.
-func Sort[S ~[]E, E constraints.Ordered](x S) {
-	n := len(x)
-	pdqsortOrdered(x, 0, n, bits.Len(uint(n)))
-}
-
-// SortFunc sorts the slice x in ascending order as determined by the cmp
-// function. This sort is not guaranteed to be stable.
-// cmp(a, b) should return a negative number when a < b, a positive number when
-// a > b and zero when a == b or when a is not comparable to b in the sense
-// of the formal definition of Strict Weak Ordering.
-//
-// SortFunc requires that cmp is a strict weak ordering.
-// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings.
-// To indicate 'uncomparable', return 0 from the function.
-func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	n := len(x)
-	pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp)
-}
-
-// SortStableFunc sorts the slice x while keeping the original order of equal
-// elements, using cmp to compare elements in the same way as [SortFunc].
-func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
-	stableCmpFunc(x, len(x), cmp)
-}
-
-// IsSorted reports whether x is sorted in ascending order.
-func IsSorted[S ~[]E, E constraints.Ordered](x S) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmpLess(x[i], x[i-1]) {
-			return false
-		}
-	}
-	return true
-}
-
-// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
-// comparison function as defined by [SortFunc].
-func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
-	for i := len(x) - 1; i > 0; i-- {
-		if cmp(x[i], x[i-1]) < 0 {
-			return false
-		}
-	}
-	return true
-}
-
-// Min returns the minimal value in x. It panics if x is empty.
-// For floating-point numbers, Min propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Min[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Min: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = min(m, x[i])
-	}
-	return m
-}
-
-// MinFunc returns the minimal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one minimal element
-// according to the cmp function, MinFunc returns the first one.
-func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MinFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) < 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// Max returns the maximal value in x. It panics if x is empty.
-// For floating-point E, Max propagates NaNs (any NaN value in x
-// forces the output to be NaN).
-func Max[S ~[]E, E constraints.Ordered](x S) E {
-	if len(x) < 1 {
-		panic("slices.Max: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		m = max(m, x[i])
-	}
-	return m
-}
-
-// MaxFunc returns the maximal value in x, using cmp to compare elements.
-// It panics if x is empty. If there is more than one maximal element
-// according to the cmp function, MaxFunc returns the first one.
-func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
-	if len(x) < 1 {
-		panic("slices.MaxFunc: empty list")
-	}
-	m := x[0]
-	for i := 1; i < len(x); i++ {
-		if cmp(x[i], m) > 0 {
-			m = x[i]
-		}
-	}
-	return m
-}
-
-// BinarySearch searches for target in a sorted slice and returns the position
-// where target is found, or the position where target would appear in the
-// sort order; it also returns a bool saying whether the target is really found
-// in the slice. The slice must be sorted in increasing order.
-func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) {
-	// Inlining is faster than calling BinarySearchFunc with a lambda.
-	n := len(x)
-	// Define x[-1] < target and x[n] >= target.
-	// Invariant: x[i-1] < target, x[j] >= target.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmpLess(x[h], target) {
-			i = h + 1 // preserves x[i-1] < target
-		} else {
-			j = h // preserves x[j] >= target
-		}
-	}
-	// i == j, x[i-1] < target, and x[j] (= x[i]) >= target  =>  answer is i.
-	return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
-}
-
-// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
-// function. The slice must be sorted in increasing order, where "increasing"
-// is defined by cmp. cmp should return 0 if the slice element matches
-// the target, a negative number if the slice element precedes the target,
-// or a positive number if the slice element follows the target.
-// cmp must implement the same ordering as the slice, such that if
-// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice.
-func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) {
-	n := len(x)
-	// Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 .
-	// Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0.
-	i, j := 0, n
-	for i < j {
-		h := int(uint(i+j) >> 1) // avoid overflow when computing h
-		// i ≤ h < j
-		if cmp(x[h], target) < 0 {
-			i = h + 1 // preserves cmp(x[i - 1], target) < 0
-		} else {
-			j = h // preserves cmp(x[j], target) >= 0
-		}
-	}
-	// i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0  =>  answer is i.
-	return i, i < n && cmp(x[i], target) == 0
-}
-
-type sortedHint int // hint for pdqsort when choosing the pivot
-
-const (
-	unknownHint sortedHint = iota
-	increasingHint
-	decreasingHint
-)
-
-// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
-type xorshift uint64
-
-func (r *xorshift) Next() uint64 {
-	*r ^= *r << 13
-	*r ^= *r >> 17
-	*r ^= *r << 5
-	return uint64(*r)
-}
-
-func nextPowerOfTwo(length int) uint {
-	return 1 << bits.Len(uint(length))
-}
-
-// isNaN reports whether x is a NaN without requiring the math package.
-// This will always return false if T is not floating-point.
-func isNaN[T constraints.Ordered](x T) bool {
-	return x != x
-}
diff --git a/public-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/public-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go
deleted file mode 100644
index 06f2c7a2..00000000
--- a/public-api/vendor/golang.org/x/exp/slices/zsortanyfunc.go
+++ /dev/null
@@ -1,479 +0,0 @@
-// Code generated by gen_sort_variants.go; DO NOT EDIT.
-
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package slices
-
-// insertionSortCmpFunc sorts data[a:b] using insertion sort.
-func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	for i := a + 1; i < b; i++ {
-		for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- {
-			data[j], data[j-1] = data[j-1], data[j]
-		}
-	}
-}
-
-// siftDownCmpFunc implements the heap property on data[lo:hi].
-// first is an offset into the array where the root of the heap lies.
-func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) {
-	root := lo
-	for {
-		child := 2*root + 1
-		if child >= hi {
-			break
-		}
-		if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) {
-			child++
-		}
-		if !(cmp(data[first+root], data[first+child]) < 0) {
-			return
-		}
-		data[first+root], data[first+child] = data[first+child], data[first+root]
-		root = child
-	}
-}
-
-func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) {
-	first := a
-	lo := 0
-	hi := b - a
-
-	// Build heap with greatest element at top.
-	for i := (hi - 1) / 2; i >= 0; i-- {
-		siftDownCmpFunc(data, i, hi, first, cmp)
-	}
-
-	// Pop elements, largest first, into end of data.
-	for i := hi - 1; i >= 0; i-- {
-		data[first], data[first+i] = data[first+i], data[first]
-		siftDownCmpFunc(data, lo, i, first, cmp)
-	}
-}
-
-// pdqsortCmpFunc sorts data[a:b].
-// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
-// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
-// C++ implementation: https://github.com/orlp/pdqsort
-// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
-// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
-func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) {
-	const maxInsertion = 12
-
-	var (
-		wasBalanced    = true // whether the last partitioning was reasonably balanced
-		wasPartitioned = true // whether the slice was already partitioned
-	)
-
-	for {
-		length := b - a
-
-		if length <= maxInsertion {
-			insertionSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// Fall back to heapsort if too many bad choices were made.
-		if limit == 0 {
-			heapSortCmpFunc(data, a, b, cmp)
-			return
-		}
-
-		// If the last partitioning was imbalanced, we need to breaking patterns.
-		if !wasBalanced {
-			breakPatternsCmpFunc(data, a, b, cmp)
-			limit--
-		}
-
-		pivot, hint := choosePivotCmpFunc(data, a, b, cmp)
-		if hint == decreasingHint {
-			reverseRangeCmpFunc(data, a, b, cmp)
-			// The chosen pivot was pivot-a elements after the start of the array.
-			// After reversing it is pivot-a elements before the end of the array.
-			// The idea came from Rust's implementation.
-			pivot = (b - 1) - (pivot - a)
-			hint = increasingHint
-		}
-
-		// The slice is likely already sorted.
-		if wasBalanced && wasPartitioned && hint == increasingHint {
-			if partialInsertionSortCmpFunc(data, a, b, cmp) {
-				return
-			}
-		}
-
-		// Probably the slice contains many duplicate elements, partition the slice into
-		// elements equal to and elements greater than the pivot.
-		if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) {
-			mid := partitionEqualCmpFunc(data, a, b, pivot, cmp)
-			a = mid
-			continue
-		}
-
-		mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp)
-		wasPartitioned = alreadyPartitioned
-
-		leftLen, rightLen := mid-a, b-mid
-		balanceThreshold := length / 8
-		if leftLen < rightLen {
-			wasBalanced = leftLen >= balanceThreshold
-			pdqsortCmpFunc(data, a, mid, limit, cmp)
-			a = mid + 1
-		} else {
-			wasBalanced = rightLen >= balanceThreshold
-			pdqsortCmpFunc(data, mid+1, b, limit, cmp)
-			b = mid
-		}
-	}
-}
-
-// partitionCmpFunc does one quicksort partition.
-// Let p = data[pivot]
-// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/public-api/vendor/golang.org/x/exp/slices/zsortordered.go b/public-api/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c39..00000000 --- a/public-api/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/public-api/vendor/golang.org/x/exp/slog/attr.go b/public-api/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/public-api/vendor/golang.org/x/exp/slog/doc.go b/public-api/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf867..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/public-api/vendor/golang.org/x/exp/slog/handler.go b/public-api/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb8..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/public-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/public-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/public-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/public-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/public-api/vendor/golang.org/x/exp/slog/json_handler.go b/public-api/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada86..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/public-api/vendor/golang.org/x/exp/slog/level.go b/public-api/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0a..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/public-api/vendor/golang.org/x/exp/slog/logger.go b/public-api/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec993..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/public-api/vendor/golang.org/x/exp/slog/noplog.bench b/public-api/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/public-api/vendor/golang.org/x/exp/slog/record.go b/public-api/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/public-api/vendor/golang.org/x/exp/slog/text_handler.go b/public-api/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b71..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/public-api/vendor/golang.org/x/exp/slog/value.go b/public-api/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46f..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/public-api/vendor/golang.org/x/exp/slog/value_119.go b/public-api/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d732..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/public-api/vendor/golang.org/x/exp/slog/value_120.go b/public-api/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c093..00000000 --- a/public-api/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/public-api/vendor/golang.org/x/net/http2/frame.go b/public-api/vendor/golang.org/x/net/http2/frame.go index 97bd8b06..db3264da 100644 --- a/public-api/vendor/golang.org/x/net/http2/frame.go +++ b/public-api/vendor/golang.org/x/net/http2/frame.go @@ -39,7 +39,7 @@ const ( FrameContinuation FrameType = 0x9 ) -var frameName = map[FrameType]string{ +var frameNames = [...]string{ FrameData: "DATA", FrameHeaders: "HEADERS", FramePriority: "PRIORITY", @@ -53,10 +53,10 @@ var frameName = map[FrameType]string{ } func (t FrameType) String() string { - if s, ok := frameName[t]; ok { - return s + if int(t) < len(frameNames) { + return frameNames[t] } - return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) + return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t) } // Flags is a bitmask of HTTP/2 flags. @@ -124,7 +124,7 @@ var flagName = map[FrameType]map[Flags]string{ // might be 0). type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) -var frameParsers = map[FrameType]frameParser{ +var frameParsers = [...]frameParser{ FrameData: parseDataFrame, FrameHeaders: parseHeadersFrame, FramePriority: parsePriorityFrame, @@ -138,8 +138,8 @@ var frameParsers = map[FrameType]frameParser{ } func typeFrameParser(t FrameType) frameParser { - if f := frameParsers[t]; f != nil { - return f + if int(t) < len(frameParsers) { + return frameParsers[t] } return parseUnknownFrame } @@ -509,7 +509,7 @@ func (fr *Framer) ReadFrame() (Frame, error) { } if fh.Length > fr.maxReadSize { if fh == invalidHTTP1LookingFrameHeader() { - return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge) } return nil, ErrFrameTooLarge } diff --git a/public-api/vendor/golang.org/x/net/http2/http2.go b/public-api/vendor/golang.org/x/net/http2/http2.go index 6c18ea23..ea5ae629 100644 --- a/public-api/vendor/golang.org/x/net/http2/http2.go +++ b/public-api/vendor/golang.org/x/net/http2/http2.go @@ -11,8 +11,6 @@ // requires Go 1.6 or later) // // See https://http2.github.io/ for more information on HTTP/2. -// -// See https://http2.golang.org/ for a test server running this code. package http2 // import "golang.org/x/net/http2" import ( diff --git a/public-api/vendor/golang.org/x/net/trace/events.go b/public-api/vendor/golang.org/x/net/trace/events.go index c646a695..3aaffdd1 100644 --- a/public-api/vendor/golang.org/x/net/trace/events.go +++ b/public-api/vendor/golang.org/x/net/trace/events.go @@ -508,7 +508,7 @@ const eventsHTML = ` {{$el.When}} {{$el.ElapsedTime}} - {{$el.Title}} + {{$el.Title}} {{if $.Expanded}} diff --git a/public-api/vendor/golang.org/x/sync/errgroup/errgroup.go b/public-api/vendor/golang.org/x/sync/errgroup/errgroup.go index cb6bb9ad..1d8cffae 100644 --- a/public-api/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/public-api/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -12,8 +12,6 @@ package errgroup import ( "context" "fmt" - "runtime" - "runtime/debug" "sync" ) @@ -33,10 +31,6 @@ type Group struct { errOnce sync.Once err error - - mu sync.Mutex - panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked. - abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit). } func (g *Group) done() { @@ -56,22 +50,13 @@ func WithContext(ctx context.Context) (*Group, context.Context) { return &Group{cancel: cancel}, ctx } -// Wait blocks until all function calls from the Go method have returned -// normally, then returns the first non-nil error (if any) from them. -// -// If any of the calls panics, Wait panics with a [PanicValue]; -// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit. +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. func (g *Group) Wait() error { g.wg.Wait() if g.cancel != nil { g.cancel(g.err) } - if g.panicValue != nil { - panic(g.panicValue) - } - if g.abnormal { - runtime.Goexit() - } return g.err } @@ -81,53 +66,31 @@ func (g *Group) Wait() error { // It blocks until the new goroutine can be added without the number of // goroutines in the group exceeding the configured limit. // -// The first goroutine in the group that returns a non-nil error, panics, or -// invokes [runtime.Goexit] will cancel the associated Context, if any. +// The first goroutine in the group that returns a non-nil error will +// cancel the associated Context, if any. The error will be returned +// by Wait. func (g *Group) Go(f func() error) { if g.sem != nil { g.sem <- token{} } - g.add(f) -} - -func (g *Group) add(f func() error) { g.wg.Add(1) go func() { defer g.done() - normalReturn := false - defer func() { - if normalReturn { - return - } - v := recover() - g.mu.Lock() - defer g.mu.Unlock() - if !g.abnormal { - if g.cancel != nil { - g.cancel(g.err) - } - g.abnormal = true - } - if v != nil && g.panicValue == nil { - switch v := v.(type) { - case error: - g.panicValue = PanicError{ - Recovered: v, - Stack: debug.Stack(), - } - default: - g.panicValue = PanicValue{ - Recovered: v, - Stack: debug.Stack(), - } - } - } - }() - err := f() - normalReturn = true - if err != nil { + // It is tempting to propagate panics from f() + // up to the goroutine that calls Wait, but + // it creates more problems than it solves: + // - it delays panics arbitrarily, + // making bugs harder to detect; + // - it turns f's panic stack into a mere value, + // hiding it from crash-monitoring tools; + // - it risks deadlocks that hide the panic entirely, + // if f's panic leaves the program in a state + // that prevents the Wait call from being reached. + // See #53757, #74275, #74304, #74306. + + if err := f(); err != nil { g.errOnce.Do(func() { g.err = err if g.cancel != nil { @@ -152,7 +115,19 @@ func (g *Group) TryGo(f func() error) bool { } } - g.add(f) + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() return true } @@ -174,34 +149,3 @@ func (g *Group) SetLimit(n int) { } g.sem = make(chan token, n) } - -// PanicError wraps an error recovered from an unhandled panic -// when calling a function passed to Go or TryGo. -type PanicError struct { - Recovered error - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicError) Error() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} - -func (p PanicError) Unwrap() error { return p.Recovered } - -// PanicValue wraps a value that does not implement the error interface, -// recovered from an unhandled panic when calling a function passed to Go or -// TryGo. -type PanicValue struct { - Recovered any - Stack []byte // result of call to [debug.Stack] -} - -func (p PanicValue) String() string { - if len(p.Stack) > 0 { - return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack) - } - return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered) -} diff --git a/public-api/vendor/golang.org/x/sys/unix/mkerrors.sh b/public-api/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c..d1c8b264 100644 --- a/public-api/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/public-api/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/public-api/vendor/golang.org/x/sys/unix/syscall_darwin.go b/public-api/vendor/golang.org/x/sys/unix/syscall_darwin.go index 798f61ad..7838ca5d 100644 --- a/public-api/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/public-api/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,14 +602,9 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) const minIovec = 8 func Readv(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = readv(fd, iovecs) @@ -618,9 +613,6 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { } func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = preadv(fd, iovecs, offset) @@ -629,10 +621,6 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -644,10 +632,6 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -707,45 +691,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } } -func darwinMajorMinPatch() (maj, min, patch int, err error) { - var un Utsname - err = Uname(&un) - if err != nil { - return - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range un.Release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return 0, 0, 0, ENOTSUP - } - case b == 0: - break Loop - default: - return 0, 0, 0, ENOTSUP - } - } - if c != 2 { - return 0, 0, 0, ENOTSUP - } - return mmp[0], mmp[1], mmp[2], nil -} - -func darwinKernelVersionMin(maj, min, patch int) bool { - actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() - if err != nil { - return false - } - return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) -} - +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux.go index 4f432bfe..b6db27d9 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -319,6 +319,7 @@ const ( AUDIT_INTEGRITY_POLICY_RULE = 0x70f AUDIT_INTEGRITY_RULE = 0x70d AUDIT_INTEGRITY_STATUS = 0x70a + AUDIT_INTEGRITY_USERSPACE = 0x710 AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f AUDIT_IPE_ACCESS = 0x58c @@ -327,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -491,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -527,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -554,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -843,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2023-03-01)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x30 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -936,11 +942,10 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 + ETHTOOL_FAMILY_NAME = "ethtool" + ETHTOOL_FAMILY_VERSION = 0x1 ETHTOOL_FEC_AUTO = 0x2 ETHTOOL_FEC_BASER = 0x10 ETHTOOL_FEC_LLRS = 0x20 @@ -1203,13 +1208,18 @@ const ( FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 FAN_EPIDFD = -0x2 + FAN_ERRNO_BITS = 0x8 + FAN_ERRNO_MASK = 0xff + FAN_ERRNO_SHIFT = 0x18 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 + FAN_EVENT_INFO_TYPE_RANGE = 0x6 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_FS_ERROR = 0x8000 @@ -1224,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1240,6 +1253,7 @@ const ( FAN_OPEN_EXEC = 0x1000 FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 + FAN_PRE_ACCESS = 0x100000 FAN_Q_OVERFLOW = 0x4000 FAN_RENAME = 0x10000000 FAN_REPORT_DFID_NAME = 0xc00 @@ -1247,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1266,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1574,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1625,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1687,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1809,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2485,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2644,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2724,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2787,7 +2813,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1e + RTA_MAX = 0x1f RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -2864,10 +2890,12 @@ const ( RTM_DELACTION = 0x31 RTM_DELADDR = 0x15 RTM_DELADDRLABEL = 0x49 + RTM_DELANYCAST = 0x3d RTM_DELCHAIN = 0x65 RTM_DELLINK = 0x11 RTM_DELLINKPROP = 0x6d RTM_DELMDB = 0x55 + RTM_DELMULTICAST = 0x39 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 @@ -2917,11 +2945,13 @@ const ( RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 + RTM_NEWANYCAST = 0x3c RTM_NEWCACHEREPORT = 0x60 RTM_NEWCHAIN = 0x64 RTM_NEWLINK = 0x10 RTM_NEWLINKPROP = 0x6c RTM_NEWMDB = 0x54 + RTM_NEWMULTICAST = 0x38 RTM_NEWNDUSEROPT = 0x44 RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 @@ -2970,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -2987,11 +3018,12 @@ const ( RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 RWF_ATOMIC = 0x40 + RWF_DONTCACHE = 0x80 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x7f + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3271,6 +3303,7 @@ const ( STATX_BTIME = 0x800 STATX_CTIME = 0x80 STATX_DIOALIGN = 0x2000 + STATX_DIO_READ_ALIGN = 0x20000 STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 @@ -3322,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xe + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3392,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3503,6 +3534,7 @@ const ( TP_STATUS_WRONG_FORMAT = 0x4 TRACEFS_MAGIC = 0x74726163 TS_COMM_LEN = 0x20 + UBI_IOCECNFO = 0xc01c6f06 UDF_SUPER_MAGIC = 0x15013346 UDP_CORK = 0x1 UDP_ENCAP = 0x64 @@ -3515,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3559,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3673,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 75207613..1c37f9fb 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -372,6 +374,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c68acda5..6f54d34a 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -373,6 +375,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index a8c607ab..783ec5c1 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -378,6 +380,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 18563dd8..ca83d3ba 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 22912cda..607e611c 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -365,6 +367,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 29344eb3..b9cb5bd3 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 20d51fb9..65b078a6 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 321b6090..5298a303 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 9bacdf1e..7bc557c8 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 @@ -371,6 +373,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c2242726..152399bb 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -426,6 +428,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 6270c8ee..1a1ce240 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 9966c194..4231a1fb 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 @@ -430,6 +432,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 848e5fcc..21c0e952 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -362,6 +364,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 669b2adb..f00d1cd7 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 @@ -434,6 +436,7 @@ const ( SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 diff --git a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 4834e575..bc8d539e 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 @@ -473,6 +475,7 @@ const ( SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff3..aca56ee4 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb45069..2ea1ef58 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e50297..d22c8af3 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec5..5ee264ae 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a..f9f03ebf 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a33..87c2118e 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b99622..391ad102 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9..56561577 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc..0482b52e 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfb..71806f08 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b4463650..e35a7105 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c1..2aea4767 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 84053916..6c9bb4e5 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790..680bc991 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f..620f2710 100644 --- a/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux.go index a46abe64..cd236443 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -114,8 +114,10 @@ type Statx_t struct { Atomic_write_unit_min uint32 Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 _ [1]uint32 - _ [9]uint64 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2226,8 +2229,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -2314,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2594,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -3802,7 +3813,16 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2d + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3842,7 +3862,17 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -3949,7 +3979,12 @@ const ( ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb ETHTOOL_A_RINGS_CQE_SIZE = 0xc ETHTOOL_A_RINGS_TX_PUSH = 0xd - ETHTOOL_A_RINGS_MAX = 0x10 + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 ETHTOOL_A_CHANNELS_UNSPEC = 0x0 ETHTOOL_A_CHANNELS_HEADER = 0x1 ETHTOOL_A_CHANNELS_RX_MAX = 0x2 @@ -4015,7 +4050,9 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x6 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4101,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4613,6 +4663,7 @@ const ( NL80211_ATTR_AKM_SUITES = 0x4c NL80211_ATTR_AP_ISOLATE = 0x60 NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a NL80211_ATTR_AUTH_DATA = 0x9c NL80211_ATTR_AUTH_TYPE = 0x35 NL80211_ATTR_BANDS = 0xef @@ -4623,6 +4674,7 @@ const ( NL80211_ATTR_BSS_BASIC_RATES = 0x24 NL80211_ATTR_BSS = 0x2f NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 NL80211_ATTR_BSS_HT_OPMODE = 0x6d NL80211_ATTR_BSSID = 0xf5 NL80211_ATTR_BSS_SELECT = 0xe3 @@ -4682,6 +4734,7 @@ const ( NL80211_ATTR_DTIM_PERIOD = 0xd NL80211_ATTR_DURATION = 0x57 NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 NL80211_ATTR_EML_CAPABILITY = 0x13d NL80211_ATTR_EXT_CAPA = 0xa9 NL80211_ATTR_EXT_CAPA_MASK = 0xaa @@ -4717,6 +4770,7 @@ const ( NL80211_ATTR_HIDDEN_SSID = 0x7e NL80211_ATTR_HT_CAPABILITY = 0x1f NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 NL80211_ATTR_IE_ASSOC_RESP = 0x80 NL80211_ATTR_IE = 0x2a NL80211_ATTR_IE_PROBE_RESP = 0x7f @@ -4747,9 +4801,10 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14d + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 NL80211_ATTR_MAX_MATCH_SETS = 0x85 NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 @@ -4774,9 +4829,12 @@ const ( NL80211_ATTR_MGMT_SUBTYPE = 0x29 NL80211_ATTR_MLD_ADDR = 0x13a NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 NL80211_ATTR_MLO_LINK_ID = 0x139 NL80211_ATTR_MLO_LINKS = 0x138 NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 NL80211_ATTR_MNTR_FLAGS = 0x17 NL80211_ATTR_MPATH_INFO = 0x1b NL80211_ATTR_MPATH_NEXT_HOP = 0x1a @@ -4809,12 +4867,14 @@ const ( NL80211_ATTR_PORT_AUTHORIZED = 0x103 NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 NL80211_ATTR_PREV_BSSID = 0x4f NL80211_ATTR_PRIVACY = 0x46 NL80211_ATTR_PROBE_RESP = 0x91 NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 NL80211_ATTR_PROTOCOL_FEATURES = 0xad NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 NL80211_ATTR_QOS_MAP = 0xc7 NL80211_ATTR_RADAR_BACKGROUND = 0x134 NL80211_ATTR_RADAR_EVENT = 0xa8 @@ -4943,7 +5003,9 @@ const ( NL80211_ATTR_WIPHY_FREQ = 0x26 NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 @@ -4978,6 +5040,8 @@ const ( NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 NL80211_BAND_ATTR_MAX = 0xd NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc NL80211_BAND_ATTR_VHT_CAPA = 0x8 NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 @@ -5001,6 +5065,10 @@ const ( NL80211_BSS_BEACON_INTERVAL = 0x4 NL80211_BSS_BEACON_TSF = 0xd NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 NL80211_BSS_CAPABILITY = 0x5 NL80211_BSS_CHAIN_SIGNAL = 0x13 NL80211_BSS_CHAN_WIDTH_10 = 0x1 @@ -5032,6 +5100,9 @@ const ( NL80211_BSS_STATUS = 0x9 NL80211_BSS_STATUS_IBSS_JOINED = 0x2 NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 NL80211_CHAN_HT20 = 0x1 NL80211_CHAN_HT40MINUS = 0x2 NL80211_CHAN_HT40PLUS = 0x3 @@ -5117,7 +5188,8 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9b + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5161,6 +5233,7 @@ const ( NL80211_CMD_SET_COALESCE = 0x65 NL80211_CMD_SET_CQM = 0x3f NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 NL80211_CMD_SET_INTERFACE = 0x6 NL80211_CMD_SET_KEY = 0xa NL80211_CMD_SET_MAC_ACL = 0x5d @@ -5180,6 +5253,7 @@ const ( NL80211_CMD_SET_SAR_SPECS = 0x8c NL80211_CMD_SET_STATION = 0x12 NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 NL80211_CMD_SET_WDS_PEER = 0x42 NL80211_CMD_SET_WIPHY = 0x2 @@ -5247,6 +5321,7 @@ const ( NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 @@ -5262,6 +5337,7 @@ const ( NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 @@ -5281,9 +5357,12 @@ const ( NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c NL80211_EXT_FEATURE_RRM = 0x1 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 @@ -5295,8 +5374,10 @@ const ( NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f NL80211_EXT_FEATURE_SECURE_RTT = 0x38 NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 NL80211_EXT_FEATURE_TXQS = 0x1c NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 @@ -5343,7 +5424,10 @@ const ( NL80211_FREQUENCY_ATTR_2MHZ = 0x16 NL80211_FREQUENCY_ATTR_4MHZ = 0x17 NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 NL80211_FREQUENCY_ATTR_DISABLED = 0x2 @@ -5351,12 +5435,14 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b NL80211_FREQUENCY_ATTR_NO_HE = 0x13 @@ -5364,8 +5450,11 @@ const ( NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e NL80211_FREQUENCY_ATTR_OFFSET = 0x14 NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c NL80211_FREQUENCY_ATTR_RADAR = 0x5 NL80211_FREQUENCY_ATTR_WMM = 0x12 NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 @@ -5430,6 +5519,7 @@ const ( NL80211_IFTYPE_STATION = 0x2 NL80211_IFTYPE_UNSPECIFIED = 0x0 NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 NL80211_KCK_EXT_LEN = 0x18 NL80211_KCK_LEN = 0x10 NL80211_KEK_EXT_LEN = 0x20 @@ -5458,9 +5548,10 @@ const ( NL80211_MAX_SUPP_HT_RATES = 0x4d NL80211_MAX_SUPP_RATES = 0x20 NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 @@ -5703,11 +5794,16 @@ const ( NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c NL80211_RATE_INFO_BITRATE32 = 0x5 NL80211_RATE_INFO_BITRATE = 0x1 NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 @@ -5753,6 +5849,8 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 NL80211_RATE_INFO_SHORT_GI = 0x4 NL80211_RATE_INFO_VHT_MCS = 0x6 NL80211_RATE_INFO_VHT_NSS = 0x7 @@ -5770,14 +5868,19 @@ const ( NL80211_REKEY_DATA_KEK = 0x1 NL80211_REKEY_DATA_REPLAY_CTR = 0x3 NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 NL80211_RRF_AUTO_BW = 0x800 NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 NL80211_RRF_GO_CONCURRENT = 0x1000 NL80211_RRF_IR_CONCURRENT = 0x1000 NL80211_RRF_NO_160MHZ = 0x10000 NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 NL80211_RRF_NO_80MHZ = 0x8000 NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 NL80211_RRF_NO_HE = 0x20000 NL80211_RRF_NO_HT40 = 0x6000 NL80211_RRF_NO_HT40MINUS = 0x2000 @@ -5788,7 +5891,10 @@ const ( NL80211_RRF_NO_IR = 0x80 NL80211_RRF_NO_OFDM = 0x1 NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 NL80211_RRF_PTMP_ONLY = 0x40 NL80211_RRF_PTP_ONLY = 0x20 NL80211_RXMGMT_FLAG_ANSWERED = 0x1 @@ -5849,6 +5955,7 @@ const ( NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 NL80211_STA_FLAG_TDLS_PEER = 0x6 NL80211_STA_FLAG_WME = 0x3 NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 @@ -6007,6 +6114,13 @@ const ( NL80211_VHT_CAPABILITY_LEN = 0xc NL80211_VHT_NSS_MAX = 0x8 NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 NL80211_WMMR_AIFSN = 0x3 NL80211_WMMR_CW_MAX = 0x2 NL80211_WMMR_CW_MIN = 0x1 @@ -6038,6 +6152,7 @@ const ( NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fd402da4..485f2d3a 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -338,6 +338,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index eb7a5e18..ecbd1ad8 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -351,6 +351,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index d78ac108..02f0463a 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -329,6 +329,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index cd06d47f..6f4d400d 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -330,6 +330,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2f28fe26..cd532cfa 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -331,6 +331,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 71d6cac2..41336208 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8596d453..eaa37eb7 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index cd60ea18..98ae6a1e 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -333,6 +333,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b0ae420c..cae19615 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -334,6 +334,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 83597287..6ce3b4e0 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,7 +285,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -341,6 +341,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 69eb6a5c..c7429c6a 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5f583cb6..4bf4baf4 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -340,6 +340,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index ad05b51a..e9709d70 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -358,6 +358,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cf3ce900..fb44268c 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -353,6 +353,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 590b5673..9c38265c 100644 --- a/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/public-api/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -335,6 +335,22 @@ type Taskstats struct { Wpcopy_delay_total uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 diff --git a/public-api/vendor/golang.org/x/telemetry/.dockerignore b/public-api/vendor/golang.org/x/telemetry/.dockerignore new file mode 100644 index 00000000..416ae44a --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.dockerignore @@ -0,0 +1,17 @@ +.git +.localstorage +node_modules +devtools +.eslint* +.gitignore +.prettier* +.stylelint* +CONTRIBUTING.md +LICENSE +npm +npx +package-lock.json +package.json +PATENTS +README.md +tsconfig.json \ No newline at end of file diff --git a/public-api/vendor/golang.org/x/telemetry/.eslintrc.json b/public-api/vendor/golang.org/x/telemetry/.eslintrc.json new file mode 100644 index 00000000..ba5e242b --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "root": true, + "ignorePatterns": ["*.min.js"] +} diff --git a/public-api/vendor/golang.org/x/telemetry/.gitattributes b/public-api/vendor/golang.org/x/telemetry/.gitattributes new file mode 100644 index 00000000..f529a114 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.gitattributes @@ -0,0 +1,14 @@ +# Treat all files in the repo as binary, with no git magic updating +# line endings. This produces predictable results in different environments. +# +# Windows users contributing to Go will need to use a modern version +# of git and editors capable of LF line endings. +# +# Windows .bat files are known to have multiple bugs when run with LF +# endings. So if they are checked in with CRLF endings, there should +# be a test like the one in test/winbatch.go in the go repository. +# (See golang.org/issue/37791.) +# +# See golang.org/issue/9281. + +* -text diff --git a/public-api/vendor/golang.org/x/telemetry/.gitignore b/public-api/vendor/golang.org/x/telemetry/.gitignore new file mode 100644 index 00000000..46770c48 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.gitignore @@ -0,0 +1,2 @@ +node_modules +.localstorage \ No newline at end of file diff --git a/public-api/vendor/golang.org/x/telemetry/.prettierrc.json b/public-api/vendor/golang.org/x/telemetry/.prettierrc.json new file mode 100644 index 00000000..91c0b944 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.prettierrc.json @@ -0,0 +1 @@ +{"proseWrap": "always"} diff --git a/public-api/vendor/golang.org/x/telemetry/.stylelintrc.json b/public-api/vendor/golang.org/x/telemetry/.stylelintrc.json new file mode 100644 index 00000000..adccf47b --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/.stylelintrc.json @@ -0,0 +1,11 @@ +{ + "extends": ["stylelint-config-standard"], + "rules": { + "declaration-property-value-allowed-list": { + "/color/": ["/^var\\(--/", "transparent"] + }, + "unit-disallowed-list": ["px"], + "selector-class-pattern": "^[a-zA-Z\\-]+$" + }, + "ignoreFiles": ["**/*.min.css"] +} diff --git a/public-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md b/public-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md new file mode 100644 index 00000000..e913373f --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these +five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the +[golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead +of the issue tracker. The gophers there will answer or ask you to file an issue +if you've tripped over a bug. + +## Contributing code + +Please read the +[Contribution Guidelines](https://golang.org/doc/contribute.html) before sending +patches. + +Unless otherwise noted, the Go source files are distributed under the BSD-style +license found in the LICENSE file. diff --git a/public-api/vendor/golang.org/x/exp/LICENSE b/public-api/vendor/golang.org/x/telemetry/LICENSE similarity index 100% rename from public-api/vendor/golang.org/x/exp/LICENSE rename to public-api/vendor/golang.org/x/telemetry/LICENSE diff --git a/public-api/vendor/golang.org/x/exp/PATENTS b/public-api/vendor/golang.org/x/telemetry/PATENTS similarity index 100% rename from public-api/vendor/golang.org/x/exp/PATENTS rename to public-api/vendor/golang.org/x/telemetry/PATENTS diff --git a/public-api/vendor/golang.org/x/telemetry/README.md b/public-api/vendor/golang.org/x/telemetry/README.md new file mode 100644 index 00000000..81a15749 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/README.md @@ -0,0 +1,62 @@ +# Go Telemetry + +This repository holds the Go Telemetry server code and libraries, used for +hosting [telemetry.go.dev](https://telemetry.go.dev) and instrumenting Go +toolchain programs with opt-in telemetry. + +**Warning**: this repository is intended for use only in tools maintained by +the Go team, including tools in the Go distribution and auxiliary tools like +[gopls](https://pkg.go.dev/golang.org/x/tools/gopls) or +[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck). There are +no compatibility guarantees for any of the packages here: public APIs will +change in breaking ways as the telemetry integration is refined. + +## Notable Packages + +- The [x/telemetry/counter](https://pkg.go.dev/golang.org/x/telemetry/counter) + package provides a library for instrumenting programs with counters and stack + reports. +- The [x/telemetry/upload](https://pkg.go.dev/golang.org/x/telemetry/upload) + package provides a hook for Go toolchain programs to upload telemetry data, + if the user has opted in to telemetry uploading. +- The [x/telemetry/cmd/gotelemetry](https://pkg.go.dev/pkg/golang.org/x/telemetry/cmd/gotelemetry) + command is used for managing telemetry data and configuration. +- The [x/telemetry/config](https://pkg.go.dev/pkg/golang.org/x/telemetry/config) + package defines the subset of telemetry data that has been approved for + uploading by the telemetry proposal process. +- The [x/telemetry/godev](https://pkg.go.dev/pkg/golang.org/x/telemetry/godev) directory defines + the services running at [telemetry.go.dev](https://telemetry.go.dev). + +## Contributing + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/telemetry. + +The main issue tracker for the telemetry repository is located at +https://go.dev/issues. Prefix your issue with "x/telemetry:" in +the subject line, so it is easy to find. + +### Linting & Formatting + +This repository uses [eslint](https://eslint.org/) to format TS files, +[stylelint](https://stylelint.io/) to format CSS files, and +[prettier](https://prettier.io/) to format TS, CSS, Markdown, and YAML files. + +See the style guides: + +- [TypeScript](https://google.github.io/styleguide/tsguide.html) +- [CSS](https://go.dev/wiki/CSSStyleGuide) + +It is encouraged that all TS and CSS code be run through formatters before +submitting a change. However, it is not a strict requirement enforced by CI. + +### Installing npm Dependencies: + +1. Install [docker](https://docs.docker.com/get-docker/) +2. Run `./npm install` + +### Run ESLint, Stylelint, & Prettier + + ./npm run all diff --git a/public-api/vendor/golang.org/x/telemetry/counter/counter.go b/public-api/vendor/golang.org/x/telemetry/counter/counter.go new file mode 100644 index 00000000..fe2d0f69 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/counter/counter.go @@ -0,0 +1,146 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +// The implementation of this package and tests are located in +// internal/counter, which can be shared with the upload package. +// TODO(hyangah): use of type aliases prevents nice documentation +// rendering in go doc or pkgsite. Fix this either by avoiding +// type aliasing or restructuring the internal/counter package. +import ( + "flag" + "path" + "runtime/debug" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// Inc increments the counter with the given name. +func Inc(name string) { + New(name).Inc() +} + +// Add adds n to the counter with the given name. +func Add(name string, n int64) { + New(name).Add(n) +} + +// New returns a counter with the given name. +// New can be called in global initializers and will be compiled down to +// linker-initialized data. That is, calling New to initialize a global +// has no cost at program startup. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func New(name string) *Counter { + // Note: not calling DefaultFile.New in order to keep this + // function something the compiler can inline and convert + // into static data initializations, with no init-time footprint. + // TODO(hyangah): is it trivial enough for the compiler to inline? + return counter.New(name) +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter = counter.Counter + +// A StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter = counter.StackCounter + +// NewStack returns a new stack counter with the given name and depth. +// +// See "Counter Naming" in the package doc for a description of counter naming +// conventions. +func NewStack(name string, depth int) *StackCounter { + return counter.NewStack(name, depth) +} + +// Open prepares telemetry counters for recording to the file system. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Open should only be called from short-lived processes such as command line +// tools. If your process is long-running, use [OpenAndRotate]. +func Open() { + counter.Open(false) +} + +// OpenAndRotate is like [Open], but also schedules a rotation of the counter +// file when it expires. +// +// See golang/go#68497 for background on why [OpenAndRotate] is a separate API. +// +// TODO(rfindley): refactor Open and OpenAndRotate for Go 1.24. +func OpenAndRotate() { + counter.Open(true) +} + +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open(false) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +// +// For instance, CountFlags("gopls/flag:", *flag.CommandLine) +func CountFlags(prefix string, fs flag.FlagSet) { + fs.Visit(func(f *flag.Flag) { + New(prefix + f.Name).Inc() + }) +} + +// CountCommandLineFlags creates a counter for every flag +// that is set in the default flag.CommandLine FlagSet using +// the counter name binaryName+"/flag:"+flagName where +// binaryName is the base name of the Path embedded in the +// binary's build info. If the binary does not have embedded build +// info, the "flag:"+flagName counter will be incremented. +// +// CountCommandLineFlags must be called after flags are parsed +// with flag.Parse. +// +// For instance, if the -S flag is passed to cmd/compile and +// CountCommandLineFlags is called after flags are parsed, +// the "compile/flag:S" counter will be incremented. +func CountCommandLineFlags() { + prefix := "flag:" + if buildInfo, ok := debug.ReadBuildInfo(); ok && buildInfo.Path != "" { + prefix = path.Base(buildInfo.Path) + "/" + prefix + } + CountFlags(prefix, *flag.CommandLine) +} diff --git a/public-api/vendor/golang.org/x/telemetry/counter/doc.go b/public-api/vendor/golang.org/x/telemetry/counter/doc.go new file mode 100644 index 00000000..639e9ea3 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/counter/doc.go @@ -0,0 +1,58 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package counter implements a simple counter system for collecting +// totally public telemetry data. +// +// There are two kinds of counters, basic counters and stack counters. +// Basic counters are created by [New]. +// Stack counters are created by [NewStack]. +// Both are incremented by calling Inc(). +// +// Basic counters are very cheap. Stack counters are more expensive, as they +// require parsing the stack. (Stack counters are implemented as basic counters +// whose names are the concatenation of the name and the stack trace. There is +// an upper limit on the size of this name, about 4K bytes. If the name is too +// long the stack will be truncated and "truncated" appended.) +// +// When counter files expire they are turned into reports by the upload +// package. The first time any counter file is created for a user, a random day +// of the week is selected on which counter files will expire. For the first +// week, that day is more than 7 days (but not more than two weeks) in the +// future. After that the counter files expire weekly on the same day of the +// week. +// +// # Counter Naming +// +// Counter names passed to [New] and [NewStack] should follow these +// conventions: +// +// - Names cannot contain whitespace or newlines. +// +// - Names must be valid unicode, with no unprintable characters. +// +// - Names may contain at most one ':'. In the counter "foo:bar", we refer to +// "foo" as the "chart name" and "bar" as the "bucket name". +// +// - The '/' character should partition counter names into a hierarchy. The +// root of this hierarchy should identify the logical entity that "owns" +// the counter. This could be an application, such as "gopls" in the case +// of "gopls/client:vscode", or a shared library, such as "crash" in the +// case of the "crash/crash" counter owned by the crashmonitor library. If +// the entity name itself contains a '/', that's ok: "cmd/go/flag" is fine. +// +// - Words should be '-' separated, as in "gopls/completion/errors-latency" +// +// - Histograms should use bucket names identifying upper bounds with '<'. +// For example given two counters "gopls/completion/latency:<50ms" and +// "gopls/completion/latency:<100ms", the "<100ms" bucket counts events +// with latency in the half-open interval [50ms, 100ms). +// +// # Debugging +// +// The GODEBUG environment variable can enable printing of additional debug +// information for counters. Adding GODEBUG=countertrace=1 to the environment +// of a process using counters causes the x/telemetry/counter package to log +// counter information to stderr. +package counter diff --git a/public-api/vendor/golang.org/x/telemetry/dir.go b/public-api/vendor/golang.org/x/telemetry/dir.go new file mode 100644 index 00000000..5931669e --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/dir.go @@ -0,0 +1,12 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Dir returns the telemetry directory. +func Dir() string { + return telemetry.Default.Dir() +} diff --git a/public-api/vendor/golang.org/x/telemetry/doc.go b/public-api/vendor/golang.org/x/telemetry/doc.go new file mode 100644 index 00000000..073f40d2 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/doc.go @@ -0,0 +1 @@ +package telemetry diff --git a/public-api/vendor/golang.org/x/telemetry/internal/config/config.go b/public-api/vendor/golang.org/x/telemetry/internal/config/config.go new file mode 100644 index 00000000..533a889c --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/config/config.go @@ -0,0 +1,140 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package config provides methods for loading and querying a +// telemetry upload config file. +package config + +import ( + "encoding/json" + "os" + "strings" + + "golang.org/x/telemetry/internal/telemetry" +) + +// Config is a wrapper around telemetry.UploadConfig that provides some +// convenience methods for checking the contents of a report. +type Config struct { + *telemetry.UploadConfig + program map[string]bool + goos map[string]bool + goarch map[string]bool + goversion map[string]bool + pgversion map[pgkey]bool + pgcounter map[pgkey]bool + pgcounterprefix map[pgkey]bool + pgstack map[pgkey]bool + rate map[pgkey]float64 +} + +type pgkey struct { + program, key string +} + +func ReadConfig(file string) (*Config, error) { + data, err := os.ReadFile(file) + if err != nil { + return nil, err + } + var cfg telemetry.UploadConfig + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + return NewConfig(&cfg), nil +} + +func NewConfig(cfg *telemetry.UploadConfig) *Config { + ucfg := Config{UploadConfig: cfg} + ucfg.goos = set(ucfg.GOOS) + ucfg.goarch = set(ucfg.GOARCH) + ucfg.goversion = set(ucfg.GoVersion) + ucfg.program = make(map[string]bool, len(ucfg.Programs)) + ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs)) + ucfg.rate = make(map[pgkey]float64) + for _, p := range ucfg.Programs { + ucfg.program[p.Name] = true + for _, v := range p.Versions { + ucfg.pgversion[pgkey{p.Name, v}] = true + } + for _, c := range p.Counters { + for _, e := range Expand(c.Name) { + ucfg.pgcounter[pgkey{p.Name, e}] = true + ucfg.rate[pgkey{p.Name, e}] = c.Rate + } + prefix, _, found := strings.Cut(c.Name, ":") + if found { + ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true + } + } + for _, s := range p.Stacks { + ucfg.pgstack[pgkey{p.Name, s.Name}] = true + ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate + } + } + return &ucfg +} + +func (r *Config) HasProgram(s string) bool { + return r.program[s] +} + +func (r *Config) HasGOOS(s string) bool { + return r.goos[s] +} + +func (r *Config) HasGOARCH(s string) bool { + return r.goarch[s] +} + +func (r *Config) HasGoVersion(s string) bool { + return r.goversion[s] +} + +func (r *Config) HasVersion(program, version string) bool { + return r.pgversion[pgkey{program, version}] +} + +func (r *Config) HasCounter(program, counter string) bool { + return r.pgcounter[pgkey{program, counter}] +} + +func (r *Config) HasCounterPrefix(program, prefix string) bool { + return r.pgcounterprefix[pgkey{program, prefix}] +} + +func (r *Config) HasStack(program, stack string) bool { + return r.pgstack[pgkey{program, stack}] +} + +func (r *Config) Rate(program, name string) float64 { + return r.rate[pgkey{program, name}] +} + +func set(slice []string) map[string]bool { + s := make(map[string]bool, len(slice)) + for _, v := range slice { + s[v] = true + } + return s +} + +// Expand takes a counter defined with buckets and expands it into distinct +// strings for each bucket. +func Expand(counter string) []string { + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { + buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",") + for _, b := range buckets { + counters = append(counters, prefix+b) + } + } else { + counters = append(counters, prefix) + } + return counters +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/configstore/download.go b/public-api/vendor/golang.org/x/telemetry/internal/configstore/download.go new file mode 100644 index 00000000..e60ab7e9 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/configstore/download.go @@ -0,0 +1,86 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package configstore abstracts interaction with the telemetry config server. +// Telemetry config (golang.org/x/telemetry/config) is distributed as a go +// module containing go.mod and config.json. Programs that upload collected +// counters download the latest config using `go mod download`. This provides +// verification of downloaded configuration and cacheability. +package configstore + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "sync/atomic" + + "golang.org/x/telemetry/internal/telemetry" +) + +const ( + ModulePath = "golang.org/x/telemetry/config" + configFileName = "config.json" +) + +// needNoConsole is used on windows to set the windows.CREATE_NO_WINDOW +// creation flag. +var needNoConsole = func(cmd *exec.Cmd) {} + +var downloads int64 + +// Downloads reports, for testing purposes, the number of times [Download] has +// been called. +func Downloads() int64 { + return atomic.LoadInt64(&downloads) +} + +// Download fetches the requested telemetry UploadConfig using "go mod +// download". If envOverlay is provided, it is appended to the environment used +// for invoking the go command. +// +// The second result is the canonical version of the requested configuration. +func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) { + atomic.AddInt64(&downloads, 1) + + if version == "" { + version = "latest" + } + modVer := ModulePath + "@" + version + var stdout, stderr bytes.Buffer + cmd := exec.Command("go", "mod", "download", "-json", modVer) + needNoConsole(cmd) + cmd.Env = append(os.Environ(), envOverlay...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + var info struct { + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err == nil && info.Error != "" { + return nil, "", fmt.Errorf("failed to download config module: %v", info.Error) + } + return nil, "", fmt.Errorf("failed to download config module: %w\n%s", err, &stderr) + } + + var info struct { + Dir string + Version string + Error string + } + if err := json.Unmarshal(stdout.Bytes(), &info); err != nil || info.Dir == "" { + return nil, "", fmt.Errorf("failed to download config module (invalid JSON): %w", err) + } + data, err := os.ReadFile(filepath.Join(info.Dir, configFileName)) + if err != nil { + return nil, "", fmt.Errorf("invalid config module: %w", err) + } + cfg := new(telemetry.UploadConfig) + if err := json.Unmarshal(data, cfg); err != nil { + return nil, "", fmt.Errorf("invalid config: %w", err) + } + return cfg, info.Version, nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go b/public-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go new file mode 100644 index 00000000..1368de19 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/configstore/download_windows.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package configstore + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + needNoConsole = needNoConsoleWindows +} + +func needNoConsoleWindows(cmd *exec.Cmd) { + // The uploader main process is likely a daemonized process with no console. + // (see x/telemetry/start_windows.go) The console creation behavior when + // a parent is a console process without console is not clearly documented + // but empirically we observed the new console is created and attached to the + // subprocess in the default setup. + // + // Ensure no new console is attached to the subprocess by setting CREATE_NO_WINDOW. + // https://learn.microsoft.com/en-us/windows/console/creation-of-a-console + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.CREATE_NO_WINDOW, + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/counter/counter.go b/public-api/vendor/golang.org/x/telemetry/internal/counter/counter.go new file mode 100644 index 00000000..c08115e5 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/counter/counter.go @@ -0,0 +1,401 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal/counter implements the internals of the public counter package. +// In addition to the public API, this package also includes APIs to parse and +// manage the counter files, needed by the upload package. +package counter + +import ( + "fmt" + "os" + "runtime" + "strings" + "sync/atomic" +) + +var ( + // Note: not using internal/godebug, so that internal/godebug can use + // internal/counter. + debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") + CrashOnBugs = false // for testing; if set, exit on fatal log messages +) + +// debugPrintf formats a debug message if GODEBUG=countertrace=1. +func debugPrintf(format string, args ...any) { + if debugCounter { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter: "+format, args...) + } +} + +// debugFatalf logs a fatal error if GODEBUG=countertrace=1. +func debugFatalf(format string, args ...any) { + if debugCounter || CrashOnBugs { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter bug: "+format, args...) + os.Exit(1) + } +} + +// A Counter is a single named event counter. +// A Counter is safe for use by multiple goroutines simultaneously. +// +// Counters should typically be created using New +// and stored as global variables, like: +// +// package mypackage +// var errorCount = counter.New("mypackage/errors") +// +// (The initialization of errorCount in this example is handled +// entirely by the compiler and linker; this line executes no code +// at program startup.) +// +// Then code can call Add to increment the counter +// each time the corresponding event is observed. +// +// Although it is possible to use New to create +// a Counter each time a particular event needs to be recorded, +// that usage fails to amortize the construction cost over +// multiple calls to Add, so it is more expensive and not recommended. +type Counter struct { + name string + file *file + + next atomic.Pointer[Counter] + state counterState + ptr counterPtr +} + +func (c *Counter) Name() string { + return c.name +} + +type counterPtr struct { + m *mappedFile + count *atomic.Uint64 +} + +type counterState struct { + bits atomic.Uint64 +} + +func (s *counterState) load() counterStateBits { + return counterStateBits(s.bits.Load()) +} + +func (s *counterState) update(old *counterStateBits, new counterStateBits) bool { + if s.bits.CompareAndSwap(uint64(*old), uint64(new)) { + *old = new + return true + } + return false +} + +type counterStateBits uint64 + +const ( + stateReaders counterStateBits = 1<<30 - 1 + stateLocked counterStateBits = stateReaders + stateHavePtr counterStateBits = 1 << 30 + stateExtraShift = 31 + stateExtra counterStateBits = 1<<64 - 1<> stateExtraShift } + +func (b counterStateBits) incReader() counterStateBits { return b + 1 } +func (b counterStateBits) decReader() counterStateBits { return b - 1 } +func (b counterStateBits) setLocked() counterStateBits { return b | stateLocked } +func (b counterStateBits) clearLocked() counterStateBits { return b &^ stateLocked } +func (b counterStateBits) setHavePtr() counterStateBits { return b | stateHavePtr } +func (b counterStateBits) clearHavePtr() counterStateBits { return b &^ stateHavePtr } +func (b counterStateBits) clearExtra() counterStateBits { return b &^ stateExtra } +func (b counterStateBits) addExtra(n uint64) counterStateBits { + const maxExtra = uint64(stateExtra) >> stateExtraShift // 0x1ffffffff + x := b.extra() + if x+n < x || x+n > maxExtra { + x = maxExtra + } else { + x += n + } + return b.clearExtra() | counterStateBits(x)< count=%d\n", c.name, extra, sum) + } + + // Took care of refreshing ptr and flushing extra. + // Now we can release the lock, unless of course + // another goroutine cleared havePtr or added to extra, + // in which case we go around again. + if !c.state.update(&state, state.clearLocked()) { + continue + } + debugPrintf("releaseLock %s: unlocked\n", c.name) + return + } +} + +// add wraps the atomic.Uint64.Add operation to handle integer overflow. +func (c *Counter) add(n uint64) uint64 { + count := c.ptr.count + for { + old := count.Load() + sum := old + n + if sum < old { + sum = ^uint64(0) + } + if count.CompareAndSwap(old, sum) { + runtime.KeepAlive(c.ptr.m) + return sum + } + } +} + +func (c *Counter) invalidate() { + for { + state := c.state.load() + if !state.havePtr() { + debugPrintf("invalidate %s: no ptr\n", c.name) + return + } + if c.state.update(&state, state.clearHavePtr()) { + debugPrintf("invalidate %s: cleared havePtr\n", c.name) + return + } + } +} + +func (c *Counter) refresh() { + for { + state := c.state.load() + if state.havePtr() || state.readers() > 0 || state.extra() == 0 { + debugPrintf("refresh %s: havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + return + } + if c.state.update(&state, state.setLocked()) { + debugPrintf("refresh %s: locked havePtr=%v readers=%d extra=%d\n", c.name, state.havePtr(), state.readers(), state.extra()) + c.releaseLock(state) + return + } + } +} + +// Read reads the given counter. +// This is the implementation of x/telemetry/counter/countertest.ReadCounter. +func Read(c *Counter) (uint64, error) { + if c.file.current.Load() == nil { + return c.state.load().extra(), nil + } + pf, err := readFile(c.file) + if err != nil { + return 0, err + } + v, ok := pf.Count[DecodeStack(c.Name())] + if !ok { + return v, fmt.Errorf("not found:%q", DecodeStack(c.Name())) + } + return v, nil +} + +func readFile(f *file) (*File, error) { + if f == nil { + debugPrintf("No file") + return nil, fmt.Errorf("counter is not initialized - was Open called?") + } + + // Note: don't call f.rotate here as this will enqueue a follow-up rotation. + f.rotate1() + + if f.err != nil { + return nil, fmt.Errorf("failed to rotate mapped file - %v", f.err) + } + current := f.current.Load() + if current == nil { + return nil, fmt.Errorf("counter has no mapped file") + } + name := current.f.Name() + data, err := ReadMapped(name) + if err != nil { + return nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, fmt.Errorf("failed to parse: %v", err) + } + return pf, nil +} + +// ReadFile reads the counters and stack counters from the given file. +// This is the implementation of x/telemetry/counter/countertest.ReadFile. +func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) { + // TODO: Document the format of the stackCounters names. + + data, err := ReadMapped(name) + if err != nil { + return nil, nil, fmt.Errorf("failed to read from file: %v", err) + } + pf, err := Parse(name, data) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse: %v", err) + } + counters = make(map[string]uint64) + stackCounters = make(map[string]uint64) + for k, v := range pf.Count { + if IsStackCounter(k) { + stackCounters[DecodeStack(k)] = v + } else { + counters[k] = v + } + } + return counters, stackCounters, nil +} + +// ReadMapped reads the contents of the given file by memory mapping. +// +// This avoids file synchronization issues. +func ReadMapped(name string) ([]byte, error) { + f, err := os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + mapping, err := memmap(f) + if err != nil { + return nil, err + } + data := make([]byte, fi.Size()) + copy(data, mapping.Data) + munmap(mapping) + return data, nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/counter/file.go b/public-api/vendor/golang.org/x/telemetry/internal/counter/file.go new file mode 100644 index 00000000..872a6f6a --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -0,0 +1,814 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "errors" + "fmt" + "math/rand" + "os" + "path" + "path/filepath" + "runtime" + "runtime/debug" + "sync" + "sync/atomic" + "time" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" + "golang.org/x/telemetry/internal/telemetry" +) + +// A file is a counter file. +type file struct { + // Linked list of all known counters. + // (Linked list insertion is easy to make lock-free, + // and we don't want the initial counters incremented + // by a program to cause significant contention.) + counters atomic.Pointer[Counter] // head of list + end Counter // list ends at &end instead of nil + + mu sync.Mutex + buildInfo *debug.BuildInfo + timeBegin, timeEnd time.Time + err error + // current holds the current file mapping, which may change when the file is + // rotated or extended. + // + // current may be read without holding mu, but may be nil. + // + // The cleanup logic for file mappings is complicated, because invalidating + // counter pointers is reentrant: [file.invalidateCounters] may call + // [file.lookup], which acquires mu. Therefore, writing current must be done + // as follows: + // 1. record the previous value of current + // 2. Store a new value in current + // 3. unlock mu + // 4. call invalidateCounters + // 5. close the previous mapped value from (1) + // TODO(rfindley): simplify + current atomic.Pointer[mappedFile] +} + +var defaultFile file + +// register ensures that the counter c is registered with the file. +func (f *file) register(c *Counter) { + debugPrintf("register %s %p\n", c.Name(), c) + + // If counter is not registered with file, register it. + // Doing this lazily avoids init-time work + // as well as any execution cost at all for counters + // that are not used in a given program. + wroteNext := false + for wroteNext || c.next.Load() == nil { + head := f.counters.Load() + next := head + if next == nil { + next = &f.end + } + debugPrintf("register %s next %p\n", c.Name(), next) + if !wroteNext { + if !c.next.CompareAndSwap(nil, next) { + debugPrintf("register %s cas failed %p\n", c.Name(), c.next.Load()) + continue + } + wroteNext = true + } else { + c.next.Store(next) + } + if f.counters.CompareAndSwap(head, c) { + debugPrintf("registered %s %p\n", c.Name(), f.counters.Load()) + return + } + debugPrintf("register %s cas2 failed %p %p\n", c.Name(), f.counters.Load(), head) + } +} + +// invalidateCounters marks as invalid all the pointers +// held by f's counters and then refreshes them. +// +// invalidateCounters cannot be called while holding f.mu, +// because a counter refresh may call f.lookup. +func (f *file) invalidateCounters() { + // Mark every counter as needing to refresh its count pointer. + if head := f.counters.Load(); head != nil { + for c := head; c != &f.end; c = c.next.Load() { + c.invalidate() + } + for c := head; c != &f.end; c = c.next.Load() { + c.refresh() + } + } +} + +// lookup looks up the counter with the given name in the file, +// allocating it if needed, and returns a pointer to the atomic.Uint64 +// containing the counter data. +// If the file has not been opened yet, lookup returns nil. +func (f *file) lookup(name string) counterPtr { + current := f.current.Load() + if current == nil { + debugPrintf("lookup %s - no mapped file\n", name) + return counterPtr{} + } + ptr := f.newCounter(name) + if ptr == nil { + return counterPtr{} + } + return counterPtr{current, ptr} +} + +// ErrDisabled is the error returned when telemetry is disabled. +var ErrDisabled = errors.New("counter: disabled as Go telemetry is off") + +var ( + errNoBuildInfo = errors.New("counter: missing build info") + errCorrupt = errors.New("counter: corrupt counter file") +) + +// weekEnd returns the day of the week on which uploads occur (and therefore +// counters expire). +// +// Reads the weekends file, creating one if none exists. +func weekEnd() (time.Weekday, error) { + // If there is no 'weekends' file create it and initialize it + // to a random day of the week. There is a short interval for + // a race. + weekends := filepath.Join(telemetry.Default.LocalDir(), "weekends") + day := fmt.Sprintf("%d\n", rand.Intn(7)) + if _, err := os.ReadFile(weekends); err != nil { + if err := os.MkdirAll(telemetry.Default.LocalDir(), 0777); err != nil { + debugPrintf("%v: could not create telemetry.LocalDir %s", err, telemetry.Default.LocalDir()) + return 0, err + } + if err = os.WriteFile(weekends, []byte(day), 0666); err != nil { + return 0, err + } + } + + // race is over, read the file + buf, err := os.ReadFile(weekends) + // There is no reasonable way of recovering from errors + // so we just fail + if err != nil { + return 0, err + } + buf = bytes.TrimSpace(buf) + if len(buf) == 0 { + return 0, fmt.Errorf("empty weekends file") + } + weekend := time.Weekday(buf[0] - '0') // 0 is Sunday + // paranoia to make sure the value is legal + weekend %= 7 + if weekend < 0 { + weekend += 7 + } + return weekend, nil +} + +// rotate checks to see whether the file f needs to be rotated, +// meaning to start a new counter file with a different date in the name. +// rotate is also used to open the file initially, meaning f.current can be nil. +// In general rotate should be called just once for each file. +// rotate will arrange a timer to call itself again when necessary. +func (f *file) rotate() { + expiry := f.rotate1() + if !expiry.IsZero() { + delay := time.Until(expiry) + // Some tests set CounterTime to a time in the past, causing delay to be + // negative. Avoid infinite loops by delaying at least a short interval. + // + // TODO(rfindley): instead, just also mock AfterFunc. + const minDelay = 1 * time.Minute + if delay < minDelay { + delay = minDelay + } + // TODO(rsc): Does this do the right thing for laptops closing? + time.AfterFunc(delay, f.rotate) + } +} + +func nop() {} + +// CounterTime returns the current UTC time. +// Mutable for testing. +var CounterTime = func() time.Time { + return time.Now().UTC() +} + +// counterSpan returns the current time span for a counter file, as determined +// by [CounterTime] and the [weekEnd]. +func counterSpan() (begin, end time.Time, _ error) { + year, month, day := CounterTime().Date() + begin = time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + // files always begin today, but expire on the next day of the week + // from the 'weekends' file. + weekend, err := weekEnd() + if err != nil { + return time.Time{}, time.Time{}, err + } + incr := int(weekend - begin.Weekday()) + if incr <= 0 { + incr += 7 // ensure that end is later than begin + } + end = time.Date(year, month, day+incr, 0, 0, 0, 0, time.UTC) + return begin, end, nil +} + +// rotate1 rotates the current counter file, returning its expiry, or the zero +// time if rotation failed. +func (f *file) rotate1() time.Time { + // Cleanup must be performed while unlocked, since invalidateCounters may + // involve calls to f.lookup. + var previous *mappedFile // read below while holding the f.mu. + defer func() { + // Counters must be invalidated whenever the mapped file changes. + if next := f.current.Load(); next != previous { + f.invalidateCounters() + // Ensure that the previous counter mapped file is closed. + if previous != nil { + previous.close() // safe to call multiple times + } + } + }() + + f.mu.Lock() + defer f.mu.Unlock() + + previous = f.current.Load() + + if f.err != nil { + return time.Time{} // already in failed state; nothing to do + } + + fail := func(err error) { + debugPrintf("rotate: %v", err) + f.err = err + f.current.Store(nil) + } + + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // TODO(rfindley): do we ever want to make ErrDisabled recoverable? + // Specifically, if f.err is ErrDisabled, should we check again during when + // rotating? + fail(ErrDisabled) + return time.Time{} + } + + if f.buildInfo == nil { + bi, ok := debug.ReadBuildInfo() + if !ok { + fail(errNoBuildInfo) + return time.Time{} + } + f.buildInfo = bi + } + + begin, end, err := counterSpan() + if err != nil { + fail(err) + return time.Time{} + } + if f.timeBegin.Equal(begin) && f.timeEnd.Equal(end) { + return f.timeEnd // nothing to do + } + f.timeBegin, f.timeEnd = begin, end + + goVers, progPath, progVers := telemetry.ProgramInfo(f.buildInfo) + meta := fmt.Sprintf("TimeBegin: %s\nTimeEnd: %s\nProgram: %s\nVersion: %s\nGoVersion: %s\nGOOS: %s\nGOARCH: %s\n\n", + f.timeBegin.Format(time.RFC3339), f.timeEnd.Format(time.RFC3339), + progPath, progVers, goVers, runtime.GOOS, runtime.GOARCH) + if len(meta) > maxMetaLen { // should be impossible for our use + fail(fmt.Errorf("metadata too long")) + return time.Time{} + } + + if progVers != "" { + progVers = "@" + progVers + } + baseName := fmt.Sprintf("%s%s-%s-%s-%s-%s.%s.count", + path.Base(progPath), + progVers, + goVers, + runtime.GOOS, + runtime.GOARCH, + f.timeBegin.Format(telemetry.DateOnly), + FileVersion, + ) + dir := telemetry.Default.LocalDir() + if err := os.MkdirAll(dir, 0777); err != nil { + fail(fmt.Errorf("making local dir: %v", err)) + return time.Time{} + } + name := filepath.Join(dir, baseName) + + m, err := openMapped(name, meta) + if err != nil { + // Mapping failed: + // If there used to be a mapped file, after cleanup + // incrementing counters will only change their internal state. + // (before cleanup the existing mapped file would be updated) + fail(fmt.Errorf("openMapped: %v", err)) + return time.Time{} + } + + debugPrintf("using %v", m.f.Name()) + f.current.Store(m) + return f.timeEnd +} + +func (f *file) newCounter(name string) *atomic.Uint64 { + v, cleanup := f.newCounter1(name) + cleanup() + return v +} + +func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { + f.mu.Lock() + defer f.mu.Unlock() + + current := f.current.Load() + if current == nil { + return nil, nop + } + debugPrintf("newCounter %s in %s\n", name, current.f.Name()) + if v, _, _, _ := current.lookup(name); v != nil { + return v, nop + } + v, newM, err := current.newCounter(name) + if err != nil { + debugPrintf("newCounter %s: %v\n", name, err) + return nil, nop + } + + cleanup = nop + if newM != nil { + f.current.Store(newM) + cleanup = func() { + f.invalidateCounters() + current.close() + } + } + return v, cleanup +} + +var ( + openOnce sync.Once + // rotating reports whether the call to Open had rotate = true. + // + // In golang/go#68497, we observed that file rotation can break runtime + // deadlock detection. To minimize the fix for 1.23, we are splitting the + // Open API into one version that rotates the counter file, and another that + // does not. The rotating variable guards against use of both APIs from the + // same process. + rotating bool +) + +// Open associates counting with the defaultFile. +// The returned function is for testing only, and should +// be called after all Inc()s are finished, but before +// any reports are generated. +// (Otherwise expired count files will not be deleted on Windows.) +func Open(rotate bool) func() { + if telemetry.DisabledOnPlatform { + return func() {} + } + close := func() {} + openOnce.Do(func() { + rotating = rotate + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. + return + } + debugPrintf("Open(%v)", rotate) + if rotate { + defaultFile.rotate() // calls rotate1 and schedules a rotation + } else { + defaultFile.rotate1() + } + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + if rotating != rotate { + panic("BUG: Open called with inconsistent values for 'rotate'") + } + return close +} + +const ( + FileVersion = "v1" + hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" + recordUnit = 32 + maxMetaLen = 512 + numHash = 512 // 2kB for hash table + maxNameLen = 4 * 1024 + limitOff = 0 + hashOff = 4 + pageSize = 16 * 1024 + minFileLen = 16 * 1024 +) + +// A mappedFile is a counter file mmapped into memory. +// +// The file layout for a mappedFile m is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, hdrLen: header, containing metadata; see [mappedHeader] +// hdrLen+limitOff, 4: uint32 allocation limit (byte offset of the end of counter records) +// hdrLen+hashOff, 4*numHash: hash table, stores uint32 heads of a linked list of records, keyed by name hash +// hdrLen+hashOff+4*numHash to limit: counter records: see record syntax below +// +// The record layout is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, 8: uint64 counter value +// 8, 12: uint32 name length +// 12, 16: uint32 offset of next record in linked list +// 16, name length: counter name +type mappedFile struct { + meta string + hdrLen uint32 + zero [4]byte + closeOnce sync.Once + f *os.File + mapping *mmap.Data +} + +// openMapped opens and memory maps a file. +// +// name is the path to the file. +// +// meta is the file metadata, which must match the metadata of the file on disk +// exactly. +// +// existing should be nil the first time this is called for a file, +// and when remapping, should be the previous mappedFile. +func openMapped(name, meta string) (_ *mappedFile, err error) { + hdr, err := mappedHeader(meta) + if err != nil { + return nil, err + } + + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + // Note: using local variable m here, not return value, + // so that return nil, err does not set m = nil and break the code in the defer. + m := &mappedFile{ + f: f, + meta: meta, + } + + defer func() { + if err != nil { + m.close() + } + }() + + info, err := f.Stat() + if err != nil { + return nil, err + } + + // Establish file header and initial data area if not already present. + if info.Size() < minFileLen { + if _, err := f.WriteAt(hdr, 0); err != nil { + return nil, err + } + // Write zeros at the end of the file to extend it to minFileLen. + if _, err := f.WriteAt(m.zero[:], int64(minFileLen-len(m.zero))); err != nil { + return nil, err + } + info, err = f.Stat() + if err != nil { + return nil, err + } + if info.Size() < minFileLen { + return nil, fmt.Errorf("counter: writing file did not extend it") + } + } + + // Map into memory. + mapping, err := memmap(f) + if err != nil { + return nil, err + } + m.mapping = mapping + if !bytes.HasPrefix(m.mapping.Data, hdr) { + // TODO(rfindley): we can and should do better here, reading the mapped + // header length and comparing headers exactly. + return nil, fmt.Errorf("counter: header mismatch") + } + m.hdrLen = uint32(len(hdr)) + + return m, nil +} + +func mappedHeader(meta string) ([]byte, error) { + if len(meta) > maxMetaLen { + return nil, fmt.Errorf("counter: metadata too large") + } + np := round(len(hdrPrefix), 4) + n := round(np+4+len(meta), 32) + hdr := make([]byte, n) + copy(hdr, hdrPrefix) + *(*uint32)(unsafe.Pointer(&hdr[np])) = uint32(n) + copy(hdr[np+4:], meta) + return hdr, nil +} + +func (m *mappedFile) place(limit uint32, name string) (start, end uint32) { + if limit == 0 { + // first record in file + limit = m.hdrLen + hashOff + 4*numHash + } + n := round(uint32(16+len(name)), recordUnit) + start = round(limit, recordUnit) // should already be rounded but just in case + // Note: Checking for crossing a page boundary would be + // start/pageSize != (start+n-1)/pageSize, + // but we are checking for reaching the page end, so no -1. + // The page end is reserved for use by extend. + // See the comment in m.extend. + if start/pageSize != (start+n)/pageSize { + // bump start to next page + start = round(limit, pageSize) + } + return start, start + n +} + +var memmap = mmap.Mmap +var munmap = mmap.Munmap + +func (m *mappedFile) close() { + m.closeOnce.Do(func() { + if m.mapping != nil { + munmap(m.mapping) + m.mapping = nil + } + if m.f != nil { + m.f.Close() // best effort + m.f = nil + } + }) +} + +// hash returns the hash code for name. +// The implementation is FNV-1a. +// This hash function is a fixed detail of the file format. +// It cannot be changed without also changing the file format version. +func hash(name string) uint32 { + const ( + offset32 = 2166136261 + prime32 = 16777619 + ) + h := uint32(offset32) + for i := 0; i < len(name); i++ { + c := name[i] + h = (h ^ uint32(c)) * prime32 + } + return (h ^ (h >> 16)) % numHash +} + +func (m *mappedFile) load32(off uint32) uint32 { + if int64(off) >= int64(len(m.mapping.Data)) { + return 0 + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).Load() +} + +func (m *mappedFile) cas32(off, old, new uint32) bool { + if int64(off) >= int64(len(m.mapping.Data)) { + panic("bad cas32") // return false would probably loop + } + return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).CompareAndSwap(old, new) +} + +// entryAt reads a counter record at the given byte offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Uint64, ok bool) { + if off < m.hdrLen+hashOff || int64(off)+16 > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + nameLen := m.load32(off+8) & 0x00ffffff + if nameLen == 0 || int64(off)+16+int64(nameLen) > int64(len(m.mapping.Data)) { + return nil, 0, nil, false + } + name = m.mapping.Data[off+16 : off+16+nameLen] + next = m.load32(off + 12) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return name, next, v, true +} + +// writeEntryAt writes a new counter record at the given offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +// +// writeEntryAt only returns false in the presence of some form of corruption: +// an offset outside the bounds of the record region in the mapped file. +func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, v *atomic.Uint64, ok bool) { + // TODO(rfindley): shouldn't this first condition be off < m.hdrLen+hashOff+4*numHash? + if off < m.hdrLen+hashOff || int64(off)+16+int64(len(name)) > int64(len(m.mapping.Data)) { + return nil, nil, false + } + copy(m.mapping.Data[off+16:], name) + atomic.StoreUint32((*uint32)(unsafe.Pointer(&m.mapping.Data[off+8])), uint32(len(name))|0xff000000) + next = (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off+12])) + v = (*atomic.Uint64)(unsafe.Pointer(&m.mapping.Data[off])) + return next, v, true +} + +// lookup searches the mapped file for a counter record with the given name, returning: +// - v: the mapped counter value +// - headOff: the offset of the head pointer (see [mappedFile]) +// - head: the value of the head pointer +// - ok: whether lookup succeeded +func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32, ok bool) { + h := hash(name) + headOff = m.hdrLen + hashOff + h*4 + head = m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return nil, 0, 0, false + } + if string(ename) == name { + return v, headOff, head, true + } + off = next + } + return nil, headOff, head, true +} + +// newCounter allocates and writes a new counter record with the given name. +// +// If name is already recorded in the file, newCounter returns the existing counter. +func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, err error) { + if len(name) > maxNameLen { + return nil, nil, fmt.Errorf("counter name too long") + } + orig := m + defer func() { + if m != orig { + if err != nil { + m.close() + } else { + m1 = m + } + } + }() + + v, headOff, head, ok := m.lookup(name) + for tries := 0; !ok; tries++ { + if tries >= 10 { + debugFatalf("corrupt: failed to remap after 10 tries") + return nil, nil, errCorrupt + } + // Lookup found an invalid pointer, + // perhaps because the file has grown larger than the mapping. + limit := m.load32(m.hdrLen + limitOff) + if limit, datalen := int64(limit), int64(len(m.mapping.Data)); limit <= datalen { + // Mapping doesn't need to grow, so lookup found actual corruption, + // in the form of an entry pointer that exceeds the recorded allocation + // limit. This should never happen, unless the actual file contents are + // corrupt. + debugFatalf("corrupt: limit %d is within mapping length %d", limit, datalen) + return nil, nil, errCorrupt + } + // That the recorded limit is greater than the mapped data indicates that + // an external process has extended the file. Re-map to pick up this extension. + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, nil, err + } + if limit, datalen := int64(limit), int64(len(newM.mapping.Data)); limit > datalen { + // We've re-mapped, yet limit still exceeds the data length. This + // indicates that the underlying file was somehow truncated, or the + // recorded limit is corrupt. + debugFatalf("corrupt: limit %d exceeds file size %d", limit, datalen) + return nil, nil, errCorrupt + } + // If m != orig, this is at least the second time around the loop + // trying to open the mapping. Close the previous attempt. + if m != orig { + m.close() + } + m = newM + v, headOff, head, ok = m.lookup(name) + } + if v != nil { + return v, nil, nil + } + + // Reserve space for new record. + // We are competing against other programs using the same file, + // so we use a compare-and-swap on the allocation limit in the header. + var start, end uint32 + for { + // Determine where record should end, and grow file if needed. + limit := m.load32(m.hdrLen + limitOff) + start, end = m.place(limit, name) + debugPrintf("place %s at %#x-%#x\n", name, start, end) + if int64(end) > int64(len(m.mapping.Data)) { + newM, err := m.extend(end) + if err != nil { + return nil, nil, err + } + if m != orig { + m.close() + } + m = newM + continue + } + + // Attempt to reserve that space for our record. + if m.cas32(m.hdrLen+limitOff, limit, end) { + break + } + } + + // Write record. + next, v, ok := m.writeEntryAt(start, name) + if !ok { + debugFatalf("corrupt: failed to write entry: %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) + return nil, nil, errCorrupt // more likely our math is wrong + } + + // Link record into hash chain, making sure not to introduce a duplicate. + // We know name does not appear in the chain starting at head. + for { + next.Store(head) + if m.cas32(headOff, head, start) { + return v, nil, nil + } + + // Check new elements in chain for duplicates. + old := head + head = m.load32(headOff) + for off := head; off != old; { + ename, enext, v, ok := m.entryAt(off) + if !ok { + return nil, nil, errCorrupt + } + if string(ename) == name { + next.Store(^uint32(0)) // mark ours as dead + return v, nil, nil + } + off = enext + } + } +} + +func (m *mappedFile) extend(end uint32) (*mappedFile, error) { + end = round(end, pageSize) + info, err := m.f.Stat() + if err != nil { + return nil, err + } + if info.Size() < int64(end) { + // Note: multiple processes could be calling extend at the same time, + // but this write only writes the last 4 bytes of the page. + // The last 4 bytes of the page are reserved for this purpose and hold no data. + // (In m.place, if a new record would extend to the very end of the page, + // it is placed in the next page instead.) + // So it is fine if multiple processes extend at the same time. + if _, err := m.f.WriteAt(m.zero[:], int64(end)-int64(len(m.zero))); err != nil { + return nil, err + } + } + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, err + } + if int64(len(newM.mapping.Data)) < int64(end) { + // File system or logic bug: new file is somehow not extended. + // See go.dev/issue/68311, where this appears to have been happening. + newM.close() + return nil, errCorrupt + } + return newM, err +} + +// round returns x rounded up to the next multiple of unit, +// which must be a power of two. +func round[T int | uint32](x T, unit T) T { + return (x + unit - 1) &^ (unit - 1) +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/counter/parse.go b/public-api/vendor/golang.org/x/telemetry/internal/counter/parse.go new file mode 100644 index 00000000..a42a3513 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/counter/parse.go @@ -0,0 +1,82 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "bytes" + "fmt" + "strings" + "unsafe" + + "golang.org/x/telemetry/internal/mmap" +) + +type File struct { + Meta map[string]string + Count map[string]uint64 +} + +func Parse(filename string, data []byte) (*File, error) { + if !bytes.HasPrefix(data, []byte(hdrPrefix)) || len(data) < pageSize { + if len(data) < pageSize { + return nil, fmt.Errorf("%s: file too short (%d<%d)", filename, len(data), pageSize) + } + return nil, fmt.Errorf("%s: wrong hdr (not %q)", filename, hdrPrefix) + } + corrupt := func() (*File, error) { + // TODO(rfindley): return a useful error message. + return nil, fmt.Errorf("%s: corrupt counter file", filename) + } + + f := &File{ + Meta: make(map[string]string), + Count: make(map[string]uint64), + } + np := round(len(hdrPrefix), 4) + hdrLen := *(*uint32)(unsafe.Pointer(&data[np])) + if hdrLen > pageSize { + return corrupt() + } + meta := data[np+4 : hdrLen] + if i := bytes.IndexByte(meta, 0); i >= 0 { + meta = meta[:i] + } + m := &mappedFile{ + meta: string(meta), + hdrLen: hdrLen, + mapping: &mmap.Data{Data: data}, + } + + lines := strings.Split(m.meta, "\n") + for _, line := range lines { + if line == "" { + continue + } + k, v, ok := strings.Cut(line, ": ") + if !ok { + return corrupt() + } + f.Meta[k] = v + } + + for i := uint32(0); i < numHash; i++ { + headOff := hdrLen + hashOff + i*4 + head := m.load32(headOff) + off := head + for off != 0 { + ename, next, v, ok := m.entryAt(off) + if !ok { + return corrupt() + } + if _, ok := f.Count[string(ename)]; ok { + return corrupt() + } + ctrName := DecodeStack(string(ename)) + f.Count[ctrName] = v.Load() + off = next + } + } + return f, nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go b/public-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go new file mode 100644 index 00000000..3e7ffdeb --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/counter/stackcounter.go @@ -0,0 +1,212 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package counter + +import ( + "fmt" + "runtime" + "strings" + "sync" +) + +// On the disk, and upstream, stack counters look like sets of +// regular counters with names that include newlines. + +// a StackCounter is the in-memory knowledge about a stack counter. +// StackCounters are more expensive to use than regular Counters, +// requiring, at a minimum, a call to runtime.Callers. +type StackCounter struct { + name string + depth int + file *file + + mu sync.Mutex + // as this is a detail of the implementation, it could be replaced + // by a more efficient mechanism + stacks []stack +} + +type stack struct { + pcs []uintptr + counter *Counter +} + +func NewStack(name string, depth int) *StackCounter { + return &StackCounter{name: name, depth: depth, file: &defaultFile} +} + +// Inc increments a stack counter. It computes the caller's stack and +// looks up the corresponding counter. It then increments that counter, +// creating it if necessary. +func (c *StackCounter) Inc() { + pcs := make([]uintptr, c.depth) + n := runtime.Callers(2, pcs) // caller of Inc + pcs = pcs[:n] + + c.mu.Lock() + defer c.mu.Unlock() + + // Existing counter? + var ctr *Counter + for _, s := range c.stacks { + if eq(s.pcs, pcs) { + if s.counter != nil { + ctr = s.counter + break + } + } + } + + if ctr == nil { + // Create new counter. + ctr = &Counter{ + name: EncodeStack(pcs, c.name), + file: c.file, + } + c.stacks = append(c.stacks, stack{pcs: pcs, counter: ctr}) + } + + ctr.Inc() +} + +// EncodeStack returns the name of the counter to +// use for the given stack of program counters. +// The name encodes the stack. +func EncodeStack(pcs []uintptr, prefix string) string { + var locs []string + lastImport := "" + frs := runtime.CallersFrames(pcs) + for { + fr, more := frs.Next() + // TODO(adonovan): this CutLast(".") operation isn't + // appropriate for generic function symbols. + path, fname := cutLastDot(fr.Function) + if path == lastImport { + path = `"` // (a ditto mark) + } else { + lastImport = path + } + var loc string + if fr.Func != nil { + // Use function-relative line numbering. + // f:+2 means two lines into function f. + // f:-1 should never happen, but be conservative. + // + // An inlined call is replaced by a NOP instruction + // with the correct pclntab information. + _, entryLine := fr.Func.FileLine(fr.Entry) + loc = fmt.Sprintf("%s.%s:%+d,+0x%x", path, fname, fr.Line-entryLine, fr.PC-fr.Entry) + } else { + // The function is non-Go code or is fully inlined: + // use absolute line number within enclosing file. + // + // For inlined calls, the PC and Entry values + // both refer to the enclosing combined function. + // For example, both these PCs are relative to "caller": + // + // callee:=1,+0x12 ('=' means inlined) + // caller:+2,+0x34 + loc = fmt.Sprintf("%s.%s:=%d,+0x%x", path, fname, fr.Line, fr.PC-fr.Entry) + } + locs = append(locs, loc) + if !more { + break + } + } + + name := prefix + "\n" + strings.Join(locs, "\n") + if len(name) > maxNameLen { + const bad = "\ntruncated\n" + name = name[:maxNameLen-len(bad)] + bad + } + return name +} + +// DecodeStack expands the (compressed) stack encoded in the counter name. +func DecodeStack(ename string) string { + if !strings.Contains(ename, "\n") { + return ename // not a stack counter + } + lines := strings.Split(ename, "\n") + var lastPath string // empty or ends with . + for i, line := range lines { + path, rest := cutLastDot(line) + if len(path) == 0 { + continue // unchanged + } + if len(path) == 1 && path[0] == '"' { + lines[i] = lastPath + rest + } else { + lastPath = path + "." + // line unchanged + } + } + return strings.Join(lines, "\n") // trailing \n? +} + +// input is . +// output is (import path, function name) +func cutLastDot(x string) (before, after string) { + i := strings.LastIndex(x, ".") + if i < 0 { + return "", x + } + return x[:i], x[i+1:] +} + +// Names reports all the counter names associated with a StackCounter. +func (c *StackCounter) Names() []string { + c.mu.Lock() + defer c.mu.Unlock() + names := make([]string, len(c.stacks)) + for i, s := range c.stacks { + names[i] = s.counter.Name() + } + return names +} + +// Counters returns the known Counters for a StackCounter. +// There may be more in the count file. +func (c *StackCounter) Counters() []*Counter { + c.mu.Lock() + defer c.mu.Unlock() + counters := make([]*Counter, len(c.stacks)) + for i, s := range c.stacks { + counters[i] = s.counter + } + return counters +} + +func eq(a, b []uintptr) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +// ReadStack reads the given stack counter. +// This is the implementation of +// golang.org/x/telemetry/counter/countertest.ReadStackCounter. +func ReadStack(c *StackCounter) (map[string]uint64, error) { + ret := map[string]uint64{} + for _, ctr := range c.Counters() { + v, err := Read(ctr) + if err != nil { + return nil, err + } + ret[DecodeStack(ctr.Name())] = v + } + return ret, nil +} + +// IsStackCounter reports whether the counter name is for a stack counter. +func IsStackCounter(name string) bool { + return strings.Contains(name, "\n") +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go b/public-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go new file mode 100644 index 00000000..53966ad2 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go @@ -0,0 +1,336 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crashmonitor + +// This file defines a monitor that reports arbitrary Go runtime +// crashes to telemetry. + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "reflect" + "runtime/debug" + "strconv" + "strings" + + "golang.org/x/telemetry/internal/counter" +) + +// Parent sets up the parent side of the crashmonitor. It requires +// exclusive use of a writable pipe connected to the child process's stdin. +func Parent(pipe *os.File) { + writeSentinel(pipe) + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + debug.SetCrashOutput(pipe, debug.CrashOptions{}) // ignore error +} + +// Child runs the part of the crashmonitor that runs in the child process. +// It expects its stdin to be connected via a pipe to the parent which has +// run Parent. +func Child() { + // Wait for parent process's dying gasp. + // If the parent dies for any reason this read will return. + data, err := io.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("failed to read from input pipe: %v", err) + } + + // If the only line is the sentinel, it wasn't a crash. + if bytes.Count(data, []byte("\n")) < 2 { + childExitHook() + os.Exit(0) // parent exited without crash report + } + + log.Printf("parent reported crash:\n%s", data) + + // Parse the stack out of the crash report + // and record a telemetry count for it. + name, err := telemetryCounterName(data) + if err != nil { + // Keep count of how often this happens + // so that we can investigate if necessary. + incrementCounter("crash/malformed") + + // Something went wrong. + // Save the crash securely in the file system. + f, err := os.CreateTemp(os.TempDir(), "*.crash") + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(data); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + log.Printf("failed to report crash to telemetry: %v", err) + log.Fatalf("crash report saved at %s", f.Name()) + } + + incrementCounter(name) + + childExitHook() + log.Fatalf("telemetry crash recorded") +} + +// (stubbed by test) +var ( + incrementCounter = func(name string) { counter.New(name).Inc() } + childExitHook = func() {} +) + +// The sentinel function returns its address. The difference between +// this value as observed by calls in two different processes of the +// same executable tells us the relative offset of their text segments. +// +// It would be nice if SetCrashOutput took care of this as it's fiddly +// and likely to confuse every user at first. +func sentinel() uint64 { + return uint64(reflect.ValueOf(sentinel).Pointer()) +} + +func writeSentinel(out io.Writer) { + fmt.Fprintf(out, "sentinel %x\n", sentinel()) +} + +// telemetryCounterName parses a crash report produced by the Go +// runtime, extracts the stack of the first runnable goroutine, +// converts each line into telemetry form ("symbol:relative-line"), +// and returns this as the name of a counter. +func telemetryCounterName(crash []byte) (string, error) { + pcs, err := parseStackPCs(string(crash)) + if err != nil { + return "", err + } + + // Limit the number of frames we request. + pcs = pcs[:min(len(pcs), 16)] + + if len(pcs) == 0 { + // This can occur if all goroutines are idle, as when + // caught in a deadlock, or killed by an async signal + // while blocked. + // + // TODO(adonovan): consider how to report such + // situations. Reporting a goroutine in [sleep] or + // [select] state could be quite confusing without + // further information about the nature of the crash, + // as the problem is not local to the code location. + // + // For now, we keep count of this situation so that we + // can access whether it needs a more involved solution. + return "crash/no-running-goroutine", nil + } + + // This string appears at the start of all + // crashmonitor-generated counter names. + // + // It is tempting to expose this as a parameter of Start, but + // it is not without risk. What value should most programs + // provide? There's no point giving the name of the executable + // as this is already recorded by telemetry. What if the + // application runs in multiple modes? Then it might be useful + // to record the mode. The problem is that an application with + // multiple modes probably doesn't know its mode by line 1 of + // main.main: it might require flag or argument parsing, or + // even validation of an environment variable, and we really + // want to steer users aware from any logic before Start. The + // flags and arguments will be wrong in the child process, and + // every extra conditional branch creates a risk that the + // recursively executed child program will behave not like the + // monitor but like the application. If the child process + // exits before calling Start, then the parent application + // will not have a monitor, and its crash reports will be + // discarded (written in to a pipe that is never read). + // + // So for now, we use this constant string. + const prefix = "crash/crash" + return counter.EncodeStack(pcs, prefix), nil +} + +// parseStackPCs parses the parent process's program counters for the +// first running goroutine out of a GOTRACEBACK=system traceback, +// adjusting them so that they are valid for the child process's text +// segment. +// +// This function returns only program counter values, ensuring that +// there is no possibility of strings from the crash report (which may +// contain PII) leaking into the telemetry system. +func parseStackPCs(crash string) ([]uintptr, error) { + // getSymbol parses the symbol name out of a line of the form: + // SYMBOL(ARGS) + // + // Note: SYMBOL may contain parens "pkg.(*T).method". However, type + // parameters are always replaced with ..., so they cannot introduce + // more parens. e.g., "pkg.(*T[...]).method". + // + // ARGS can contain parens. We want the first paren that is not + // immediately preceded by a ".". + // + // TODO(prattmic): This is mildly complicated and is only used to find + // runtime.sigpanic, so perhaps simplify this by checking explicitly + // for sigpanic. + getSymbol := func(line string) (string, error) { + var prev rune + for i, c := range line { + if line[i] != '(' { + prev = c + continue + } + if prev == '.' { + prev = c + continue + } + return line[:i], nil + } + return "", fmt.Errorf("no symbol for stack frame: %s", line) + } + + // getPC parses the PC out of a line of the form: + // \tFILE:LINE +0xRELPC sp=... fp=... pc=... + getPC := func(line string) (uint64, error) { + _, pcstr, ok := strings.Cut(line, " pc=") // e.g. pc=0x%x + if !ok { + return 0, fmt.Errorf("no pc= for stack frame: %s", line) + } + return strconv.ParseUint(pcstr, 0, 64) // 0 => allow 0x prefix + } + + var ( + pcs []uintptr + parentSentinel uint64 + childSentinel = sentinel() + on = false // are we in the first running goroutine? + lines = strings.Split(crash, "\n") + symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. + currSymbol string + prevSymbol string // symbol of the most recent previous frame with a PC. + ) + for i := 0; i < len(lines); i++ { + line := lines[i] + + // Read sentinel value. + if parentSentinel == 0 && strings.HasPrefix(line, "sentinel ") { + _, err := fmt.Sscanf(line, "sentinel %x", &parentSentinel) + if err != nil { + return nil, fmt.Errorf("can't read sentinel line") + } + continue + } + + // Search for "goroutine GID [STATUS]" + if !on { + if strings.HasPrefix(line, "goroutine ") && + strings.Contains(line, " [running]:") { + on = true + + if parentSentinel == 0 { + return nil, fmt.Errorf("no sentinel value in crash report") + } + } + continue + } + + // A blank line marks end of a goroutine stack. + if line == "" { + break + } + + // Skip the final "created by SYMBOL in goroutine GID" part. + if strings.HasPrefix(line, "created by ") { + break + } + + // Expect a pair of lines: + // SYMBOL(ARGS) + // \tFILE:LINE +0xRELPC sp=0x%x fp=0x%x pc=0x%x + // Note: SYMBOL may contain parens "pkg.(*T).method" + // The RELPC is sometimes missing. + + if symLine { + var err error + currSymbol, err = getSymbol(line) + if err != nil { + return nil, fmt.Errorf("error extracting symbol: %v", err) + } + + symLine = false // Next line is FILE:LINE. + } else { + // Parse the PC, and correct for the parent and child's + // different mappings of the text section. + pc, err := getPC(line) + if err != nil { + // Inlined frame, perhaps; skip it. + + // Done with this frame. Next line is a new frame. + // + // Don't update prevSymbol; we only want to + // track frames with a PC. + currSymbol = "" + symLine = true + continue + } + + pc = pc - parentSentinel + childSentinel + + // If the previous frame was sigpanic, then this frame + // was a trap (e.g., SIGSEGV). + // + // Typically all middle frames are calls, and report + // the "return PC". That is, the instruction following + // the CALL where the callee will eventually return to. + // + // runtime.CallersFrames is aware of this property and + // will decrement each PC by 1 to "back up" to the + // location of the CALL, which is the actual line + // number the user expects. + // + // This does not work for traps, as a trap is not a + // call, so the reported PC is not the return PC, but + // the actual PC of the trap. + // + // runtime.Callers is aware of this and will + // intentionally increment trap PCs in order to correct + // for the decrement performed by + // runtime.CallersFrames. See runtime.tracebackPCs and + // runtume.(*unwinder).symPC. + // + // We must emulate the same behavior, otherwise we will + // report the location of the instruction immediately + // prior to the trap, which may be on a different line, + // or even a different inlined functions. + // + // TODO(prattmic): The runtime applies the same trap + // behavior for other "injected calls", see injectCall + // in runtime.(*unwinder).next. Do we want to handle + // those as well? I don't believe we'd ever see + // runtime.asyncPreempt or runtime.debugCallV2 in a + // typical crash. + if prevSymbol == "runtime.sigpanic" { + pc++ + } + + pcs = append(pcs, uintptr(pc)) + + // Done with this frame. Next line is a new frame. + prevSymbol = currSymbol + currSymbol = "" + symLine = true + } + } + return pcs, nil +} + +func min(x, y int) int { + if x < y { + return x + } else { + return y + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go new file mode 100644 index 00000000..2febe3ec --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package is a lightly modified version of the mmap code +// in github.com/google/codesearch/index. + +// The mmap package provides an abstraction for memory mapping files +// on different platforms. +package mmap + +import ( + "os" +) + +// The backing file is never closed, so Data +// remains valid for the lifetime of the process. +type Data struct { + // TODO(pjw): might be better to define versions of Data + // for the 3 specializations + f *os.File + Data []byte + // Some windows magic + Windows interface{} +} + +// Mmap maps the given file into memory. +// When remapping a file, pass the most recently returned Data. +func Mmap(f *os.File) (*Data, error) { + return mmapFile(f) +} + +// Munmap unmaps the given file from memory. +func Munmap(d *Data) error { + return munmapFile(d) +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go new file mode 100644 index 00000000..610ab1a1 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go @@ -0,0 +1,25 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || wasip1 || plan9 + +package mmap + +import ( + "io" + "os" +) + +// mmapFile on other systems doesn't mmap the file. It just reads everything. +func mmapFile(f *os.File) (*Data, error) { + b, err := io.ReadAll(f) + if err != nil { + return nil, err + } + return &Data{f, b, nil}, nil +} + +func munmapFile(_ *Data) error { + return nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go new file mode 100644 index 00000000..72ad91d5 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go @@ -0,0 +1,47 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix + +package mmap + +import ( + "fmt" + "io/fs" + "os" + "syscall" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + pagesize := int64(os.Getpagesize()) + if int64(int(size+(pagesize-1))) != size+(pagesize-1) { + return nil, fmt.Errorf("%s: too large for mmap", f.Name()) + } + n := int(size) + if n == 0 { + return &Data{f, nil, nil}, nil + } + mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size + data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} + } + return &Data{f, data[:n], nil}, nil +} + +func munmapFile(d *Data) error { + if len(d.Data) == 0 { + return nil + } + err := syscall.Munmap(d.Data) + if err != nil { + return &fs.PathError{Op: "munmap", Path: d.f.Name(), Err: err} + } + return nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go new file mode 100644 index 00000000..2e8dfbea --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go @@ -0,0 +1,52 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mmap + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +func mmapFile(f *os.File) (*Data, error) { + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + if size == 0 { + return &Data{f, nil, nil}, nil + } + // set the min and max sizes to zero to map the whole file, as described in + // https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object#file-mapping-size + h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, syscall.PAGE_READWRITE, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) + } + // the mapping extends from zero to the end of the file mapping + // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile + addr, err := windows.MapViewOfFile(h, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, 0) + if err != nil { + return nil, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) + } + // Note: previously, we called windows.VirtualQuery here to get the exact + // size of the memory mapped region, but VirtualQuery reported sizes smaller + // than the actual file size (hypothesis: VirtualQuery only reports pages in + // a certain state, and newly written pages may not be counted). + return &Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil +} + +func munmapFile(d *Data) error { + err := windows.UnmapViewOfFile(uintptr(unsafe.Pointer(&d.Data[0]))) + x, ok := d.Windows.(windows.Handle) + if ok { + windows.CloseHandle(x) + } + d.f.Close() + return err +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go new file mode 100644 index 00000000..71953018 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dateonly.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// TODO(rfindley): replace uses of DateOnly with time.DateOnly once we no +// longer support building gopls with go 1.19. +const DateOnly = "2006-01-02" diff --git a/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go new file mode 100644 index 00000000..0673be56 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/dir.go @@ -0,0 +1,163 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package telemetry manages the telemetry mode file. +package telemetry + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" +) + +// Default is the default directory containing Go telemetry configuration and +// data. +// +// If Default is uninitialized, Default.Mode will be "off". As a consequence, +// no data should be written to the directory, and so the path values of +// LocalDir, UploadDir, etc. must not matter. +// +// Default is a global for convenience and testing, but should not be mutated +// outside of tests. +// +// TODO(rfindley): it would be nice to completely eliminate this global state, +// or at least push it in the golang.org/x/telemetry package +var Default Dir + +// A Dir holds paths to telemetry data inside a directory. +type Dir struct { + dir, local, upload, debug, modefile string +} + +// NewDir creates a new Dir encapsulating paths in the given dir. +// +// NewDir does not create any new directories or files--it merely encapsulates +// the telemetry directory layout. +func NewDir(dir string) Dir { + return Dir{ + dir: dir, + local: filepath.Join(dir, "local"), + upload: filepath.Join(dir, "upload"), + debug: filepath.Join(dir, "debug"), + modefile: filepath.Join(dir, "mode"), + } +} + +func init() { + cfgDir, err := os.UserConfigDir() + if err != nil { + return + } + Default = NewDir(filepath.Join(cfgDir, "go", "telemetry")) +} + +func (d Dir) Dir() string { + return d.dir +} + +func (d Dir) LocalDir() string { + return d.local +} + +func (d Dir) UploadDir() string { + return d.upload +} + +func (d Dir) DebugDir() string { + return d.debug +} + +func (d Dir) ModeFile() string { + return d.modefile +} + +// SetMode updates the telemetry mode with the given mode. +// Acceptable values for mode are "on", "off", or "local". +// +// SetMode always writes the mode file, and explicitly records the date at +// which the modefile was updated. This means that calling SetMode with "on" +// effectively resets the timeout before the next telemetry report is uploaded. +func (d Dir) SetMode(mode string) error { + return d.SetModeAsOf(mode, time.Now()) +} + +// SetModeAsOf is like SetMode, but accepts an explicit time to use to +// back-date the mode state. This exists only for testing purposes. +func (d Dir) SetModeAsOf(mode string, asofTime time.Time) error { + mode = strings.TrimSpace(mode) + switch mode { + case "on", "off", "local": + default: + return fmt.Errorf("invalid telemetry mode: %q", mode) + } + if d.modefile == "" { + return fmt.Errorf("cannot determine telemetry mode file name") + } + // TODO(rfindley): why is this not 777, consistent with the use of 666 below? + if err := os.MkdirAll(filepath.Dir(d.modefile), 0755); err != nil { + return fmt.Errorf("cannot create a telemetry mode file: %w", err) + } + + asof := asofTime.UTC().Format(DateOnly) + // Defensively guarantee that we can parse the asof time. + if _, err := time.Parse(DateOnly, asof); err != nil { + return fmt.Errorf("internal error: invalid mode date %q: %v", asof, err) + } + + data := []byte(mode + " " + asof) + return os.WriteFile(d.modefile, data, 0666) +} + +// Mode returns the current telemetry mode, as well as the time that the mode +// was effective. +// +// If there is no effective time, the second result is the zero time. +// +// If Mode is "off", no data should be written to the telemetry directory, and +// the other paths values referenced by Dir should be considered undefined. +// This accounts for the case where initializing [Default] fails, and therefore +// local telemetry paths are unknown. +func (d Dir) Mode() (string, time.Time) { + if d.modefile == "" { + return "off", time.Time{} // it's likely LocalDir/UploadDir are empty too. Turn off telemetry. + } + data, err := os.ReadFile(d.modefile) + if err != nil { + return "local", time.Time{} // default + } + mode := string(data) + mode = strings.TrimSpace(mode) + + // Forward compatibility for https://go.dev/issue/63142#issuecomment-1734025130 + // + // If the modefile contains a date, return it. + if idx := strings.Index(mode, " "); idx >= 0 { + d, err := time.Parse(DateOnly, mode[idx+1:]) + if err != nil { + d = time.Time{} + } + return mode[:idx], d + } + + return mode, time.Time{} +} + +// DisabledOnPlatform indicates whether telemetry is disabled +// due to bugs in the current platform. +// +// TODO(rfindley): move to a more appropriate file. +const DisabledOnPlatform = false || + // The following platforms could potentially be supported in the future: + runtime.GOOS == "openbsd" || // #60614 + runtime.GOOS == "solaris" || // #60968 #60970 + runtime.GOOS == "android" || // #60967 + runtime.GOOS == "illumos" || // #65544 + // These platforms fundamentally can't be supported: + runtime.GOOS == "js" || // #60971 + runtime.GOOS == "wasip1" || // #60971 + runtime.GOOS == "plan9" || // https://github.com/golang/go/issues/57540#issuecomment-1470766639 + runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" // mips lacks cross-process 64-bit atomics diff --git a/public-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go new file mode 100644 index 00000000..5ff7d34f --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -0,0 +1,57 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "go/version" + "os" + "path/filepath" + "runtime/debug" + "strings" +) + +// IsToolchainProgram reports whether a program with the given path is a Go +// toolchain program. +func IsToolchainProgram(progPath string) bool { + return strings.HasPrefix(progPath, "cmd/") +} + +// ProgramInfo extracts the go version, program package path, and program +// version to use for counter files. +// +// For programs in the Go toolchain, the program version will be the same as +// the Go version, and will typically be of the form "go1.2.3", not a semantic +// version of the form "v1.2.3". Go versions may also include spaces and +// special characters. +func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { + goVers = info.GoVersion + if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") || !version.IsValid(goVers) { + goVers = "devel" + } + + progPath = info.Path + if progPath == "" { + progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + + // Main module version information is not populated for the cmd module, but + // we can re-use the Go version here. + if IsToolchainProgram(progPath) { + progVers = goVers + } else { + progVers = info.Main.Version + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). + progVers = "devel" + } + } + + return goVers, progPath, progVers +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go new file mode 100644 index 00000000..0fd61f8d --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/telemetry/types.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig struct { + GOOS []string + GOARCH []string + GoVersion []string + SampleRate float64 + Programs []*ProgramConfig +} + +type ProgramConfig struct { + // the counter names may have to be + // repeated for each program. (e.g., if the counters are in a package + // that is used in more than one program.) + Name string + Versions []string // versions present in a counterconfig + Counters []CounterConfig `json:",omitempty"` + Stacks []CounterConfig `json:",omitempty"` +} + +type CounterConfig struct { + Name string // The "collapsed" counter: :{,,...} + Rate float64 // If X <= Rate, report this counter + Depth int `json:",omitempty"` // for stack counters +} + +// A Report is the weekly aggregate of counters. +type Report struct { + Week string // End day this report covers (YYYY-MM-DD) + LastWeek string // Week field from latest previous report uploaded + X float64 // A random probability used to determine which counters are uploaded + Programs []*ProgramReport + Config string // version of UploadConfig used +} + +type ProgramReport struct { + Program string // Package path of the program. + Version string // Program version. Go version if the program is part of the go distribution. Module version, otherwise. + GoVersion string // Go version used to build the program. + GOOS string + GOARCH string + Counters map[string]int64 + Stacks map[string]int64 +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt b/public-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt new file mode 100644 index 00000000..45601e65 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/Doc.txt @@ -0,0 +1,45 @@ +The upload process converts count files into reports, and +uploads reports. There will be only one report, named YYYY-MM-DD.json, +for a given day. + +First phase. Look at the localdir (os.UserConfigdir()/go/telemetry/local) +and find all .count and .json files. Find the count files that are no +longer active by looking at their metadata. + +Second phase. Group the inactive count files by their expiry date, and +for each date generate the local report and the upload report. (The upload +report only contains the counters in the upload configuration.) The upload +report is saved in the local directory with a name like YYYY-MM-DD.json, if +there is no file already existing with that name. +If the local report is different, it is saved in the local directory +with a name like local.YYYY-MM-DD.json. The new upload report is +added to the list of .json files from the first phase. At this point +the count files are no longer needed and can be deleted. + +Third phase. Look at the .json files in the list from the first phase. +If the name starts with local, skip it. If there is a file with the +identical name in the upload directory, remove the one in the local directory. +Otherwise try to upload the one in the local directory, +If the upload succeeds, move the file to the uploaded directory. + + +There are various error conditions. +1. Several processes could look at localdir and see work to do. +1A. They could see different sets of expired count files for some day. + This could happen if another process is removing count files. In this + case there is already a YYYY-MM-DD.json file either in localdir + or updatedir, so the process seeing fewer count files will not generate + a report. +1B. They could see the same count files, and no report in either directory. + They will both generate (in memory) reports and check to see if there + is a YYYY-MM-DD.json file in either directory. They could both then + write two files with the same name, but different X values, but + otherwise the same contents. The X values are very close to the front + of the file. Assuming reasonable file system semantics one version of + the file will be written. To minimize this, just before writing reports + the code checks again to see if they exist. +1C. Once there is an existing well-formed file YYYY-MM-DD.json in localdir + eventually the upload will succeed, and the file will be moved to updatedir. + It is possible that other processes will not see the file in updatedir and + upload it again and also move it to uploaddir. This is harmless as all + the uploaded files are identical. diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/date.go b/public-api/vendor/golang.org/x/telemetry/internal/upload/date.go new file mode 100644 index 00000000..d6d67a16 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/date.go @@ -0,0 +1,85 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "os" + "sync" + "time" + + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// time and date handling + +var distantPast = 21 * 24 * time.Hour + +// reports that are too old (21 days) are not uploaded +func (u *uploader) tooOld(date string, uploadStartTime time.Time) bool { + t, err := time.Parse(telemetry.DateOnly, date) + if err != nil { + u.logger.Printf("tooOld: %v", err) + return false + } + age := uploadStartTime.Sub(t) + return age > distantPast +} + +// counterDateSpan parses the counter file named fname and returns the (begin, +// end) span recorded in its metadata, or an error if this data could not be +// extracted. +func (u *uploader) counterDateSpan(fname string) (begin, end time.Time, _ error) { + parsed, err := u.parseCountFile(fname) + if err != nil { + return time.Time{}, time.Time{}, err + } + timeBegin, ok := parsed.Meta["TimeBegin"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeBegin") + } + begin, err = time.Parse(time.RFC3339, timeBegin) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeBegin: %v", err) + } + timeEnd, ok := parsed.Meta["TimeEnd"] + if !ok { + return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeEnd") + } + end, err = time.Parse(time.RFC3339, timeEnd) + if err != nil { + return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeEnd: %v", err) + } + return begin, end, nil +} + +// avoid parsing count files multiple times +type parsedCache struct { + mu sync.Mutex + m map[string]*counter.File +} + +func (u *uploader) parseCountFile(fname string) (*counter.File, error) { + u.cache.mu.Lock() + defer u.cache.mu.Unlock() + if u.cache.m == nil { + u.cache.m = make(map[string]*counter.File) + } + if f, ok := u.cache.m[fname]; ok { + return f, nil + } + buf, err := os.ReadFile(fname) + if err != nil { + return nil, fmt.Errorf("parse ReadFile: %v for %s", err, fname) + } + f, err := counter.Parse(fname, buf) + if err != nil { + + return nil, fmt.Errorf("parse Parse: %v for %s", err, fname) + } + u.cache.m[fname] = f + return f, nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go b/public-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go new file mode 100644 index 00000000..2b165be3 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/findwork.go @@ -0,0 +1,102 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "os" + "path/filepath" + "strings" +) + +// files to handle +type work struct { + // absolute file names + countfiles []string // count files to process + readyfiles []string // old reports to upload + // relative names + uploaded map[string]bool // reports that have been uploaded +} + +// find all the files that look like counter files or reports +// that need to be uploaded. (There may be unexpected leftover files +// and uploading is supposed to be idempotent.) +func (u *uploader) findWork() work { + localdir, uploaddir := u.dir.LocalDir(), u.dir.UploadDir() + var ans work + fis, err := os.ReadDir(localdir) + if err != nil { + u.logger.Printf("Could not find work: failed to read local dir %s: %v", localdir, err) + return ans + } + + mode, asof := u.dir.Mode() + u.logger.Printf("Finding work: mode %s asof %s", mode, asof) + + // count files end in .v1.count + // reports end in .json. If they are not to be uploaded they + // start with local. + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".v1.count") { + fname := filepath.Join(localdir, fi.Name()) + _, expiry, err := u.counterDateSpan(fname) + switch { + case err != nil: + u.logger.Printf("Error reading expiry for count file %s: %v", fi.Name(), err) + case expiry.After(u.startTime): + u.logger.Printf("Skipping count file %s: still active", fi.Name()) + default: + u.logger.Printf("Collecting count file %s", fi.Name()) + ans.countfiles = append(ans.countfiles, fname) + } + } else if strings.HasPrefix(fi.Name(), "local.") { + // skip + } else if strings.HasSuffix(fi.Name(), ".json") && mode == "on" { + // Collect reports that are ready for upload. + reportDate := u.uploadReportDate(fi.Name()) + if !asof.IsZero() && !reportDate.IsZero() { + // If both the mode asof date and the report date are present, do the + // right thing... + // + // (see https://github.com/golang/go/issues/63142#issuecomment-1734025130) + if asof.Before(reportDate) { + // Note: since this report was created after telemetry was enabled, + // we can only assume that the process that created it checked that + // the counter data contained therein was all from after the asof + // date. + // + // TODO(rfindley): store the begin date in reports, so that we can + // verify this assumption. + u.logger.Printf("Uploadable: %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } else { + // ...otherwise fall back on the old behavior of uploading all + // unuploaded files. + // + // TODO(rfindley): invert this logic following more testing. We + // should only upload if we know both the asof date and the report + // date, and they are acceptable. + u.logger.Printf("Uploadable (missing date): %s", fi.Name()) + ans.readyfiles = append(ans.readyfiles, filepath.Join(localdir, fi.Name())) + } + } + } + + fis, err = os.ReadDir(uploaddir) + if err != nil { + os.MkdirAll(uploaddir, 0777) + return ans + } + // There should be only one of these per day; maybe sometime + // we'll want to clean the directory. + ans.uploaded = make(map[string]bool) + for _, fi := range fis { + if strings.HasSuffix(fi.Name(), ".json") { + u.logger.Printf("Already uploaded: %s", fi.Name()) + ans.uploaded[fi.Name()] = true + } + } + return ans +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/reports.go b/public-api/vendor/golang.org/x/telemetry/internal/upload/reports.go new file mode 100644 index 00000000..34bb29d8 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/reports.go @@ -0,0 +1,344 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "crypto/rand" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/telemetry/internal/config" + "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" +) + +// reports generates reports from inactive count files +func (u *uploader) reports(todo *work) ([]string, error) { + if mode, _ := u.dir.Mode(); mode == "off" { + return nil, nil // no reports + } + thisInstant := u.startTime + today := thisInstant.Format(telemetry.DateOnly) + lastWeek := latestReport(todo.uploaded) + if lastWeek >= today { //should never happen + lastWeek = "" + } + u.logger.Printf("Last week: %s, today: %s", lastWeek, today) + countFiles := make(map[string][]string) // expiry date string->filenames + earliest := make(map[string]time.Time) // earliest begin time for any counter + for _, f := range todo.countfiles { + begin, end, err := u.counterDateSpan(f) + if err != nil { + // This shouldn't happen: we should have already skipped count files that + // don't contain valid start or end times. + u.logger.Printf("BUG: failed to parse expiry for collected count file: %v", err) + continue + } + + if end.Before(thisInstant) { + expiry := end.Format(dateFormat) + countFiles[expiry] = append(countFiles[expiry], f) + if earliest[expiry].IsZero() || earliest[expiry].After(begin) { + earliest[expiry] = begin + } + } + } + for expiry, files := range countFiles { + if notNeeded(expiry, *todo) { + u.logger.Printf("Files for %s not needed, deleting %v", expiry, files) + // The report already exists. + // There's another check in createReport. + u.deleteFiles(files) + continue + } + fname, err := u.createReport(earliest[expiry], expiry, files, lastWeek) + if err != nil { + u.logger.Printf("Failed to create report for %s: %v", expiry, err) + continue + } + if fname != "" { + u.logger.Printf("Ready to upload: %s", filepath.Base(fname)) + todo.readyfiles = append(todo.readyfiles, fname) + } + } + return todo.readyfiles, nil +} + +// latestReport returns the YYYY-MM-DD of the last report uploaded +// or the empty string if there are no reports. +func latestReport(uploaded map[string]bool) string { + var latest string + for name := range uploaded { + if strings.HasSuffix(name, ".json") { + if name > latest { + latest = name + } + } + } + if latest == "" { + return "" + } + // strip off the .json + return latest[:len(latest)-len(".json")] +} + +// notNeeded returns true if the report for date has already been created +func notNeeded(date string, todo work) bool { + if todo.uploaded != nil && todo.uploaded[date+".json"] { + return true + } + // maybe the report is already in todo.readyfiles + for _, f := range todo.readyfiles { + if strings.Contains(f, date) { + return true + } + } + return false +} + +func (u *uploader) deleteFiles(files []string) { + for _, f := range files { + if err := os.Remove(f); err != nil { + // this could be a race condition. + // conversely, on Windows, err may be nil and + // the file not deleted if anyone has it open. + u.logger.Printf("%v failed to remove %s", err, f) + } + } +} + +// createReport creates local and upload report files by +// combining all the count files for the expiryDate, and +// returns the upload report file's path. +// It may delete the count files once local and upload report +// files are successfully created. +func (u *uploader) createReport(start time.Time, expiryDate string, countFiles []string, lastWeek string) (string, error) { + uploadOK := true + mode, asof := u.dir.Mode() + if mode != "on" { + u.logger.Printf("No upload config or mode %q is not 'on'", mode) + uploadOK = false // no config, nothing to upload + } + if u.tooOld(expiryDate, u.startTime) { + u.logger.Printf("Expiry date %s is too old", expiryDate) + uploadOK = false + } + // If the mode is recorded with an asof date, don't upload if the report + // includes any data on or before the asof date. + if !asof.IsZero() && !asof.Before(start) { + u.logger.Printf("As-of date %s is not before start %s", asof, start) + uploadOK = false + } + // TODO(rfindley): check that all the x.Meta are consistent for GOOS, GOARCH, etc. + report := &telemetry.Report{ + Config: u.configVersion, + X: computeRandom(), // json encodes all the bits + Week: expiryDate, + LastWeek: lastWeek, + } + if report.X > u.config.SampleRate && u.config.SampleRate > 0 { + u.logger.Printf("X: %f > SampleRate:%f, not uploadable", report.X, u.config.SampleRate) + uploadOK = false + } + var succeeded bool + for _, f := range countFiles { + fok := false + x, err := u.parseCountFile(f) + if err != nil { + u.logger.Printf("Unparseable count file %s: %v", filepath.Base(f), err) + continue + } + prog := findProgReport(x.Meta, report) + for k, v := range x.Count { + if counter.IsStackCounter(k) { + // stack + prog.Stacks[k] += int64(v) + } else { + // counter + prog.Counters[k] += int64(v) + } + succeeded = true + fok = true + } + if !fok { + u.logger.Printf("no counters found in %s", f) + } + } + if !succeeded { + return "", fmt.Errorf("none of the %d count files for %s contained counters", len(countFiles), expiryDate) + } + // 1. generate the local report + localContents, err := json.MarshalIndent(report, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal report for %s: %v", expiryDate, err) + } + // check that the report can be read back + // TODO(pjw): remove for production? + var report2 telemetry.Report + if err := json.Unmarshal(localContents, &report2); err != nil { + return "", fmt.Errorf("failed to unmarshal local report for %s: %v", expiryDate, err) + } + + var uploadContents []byte + if uploadOK { + // 2. create the uploadable version + cfg := config.NewConfig(u.config) + upload := &telemetry.Report{ + Week: report.Week, + LastWeek: report.LastWeek, + X: report.X, + Config: report.Config, + } + for _, p := range report.Programs { + // does the uploadConfig want this program? + // if so, copy over the Stacks and Counters + // that the uploadConfig mentions. + if !cfg.HasGoVersion(p.GoVersion) || !cfg.HasProgram(p.Program) || !cfg.HasVersion(p.Program, p.Version) { + continue + } + x := &telemetry.ProgramReport{ + Program: p.Program, + Version: p.Version, + GOOS: p.GOOS, + GOARCH: p.GOARCH, + GoVersion: p.GoVersion, + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + upload.Programs = append(upload.Programs, x) + for k, v := range p.Counters { + if cfg.HasCounter(p.Program, k) && report.X <= cfg.Rate(p.Program, k) { + x.Counters[k] = v + } + } + // and the same for Stacks + // this can be made more efficient, when it matters + for k, v := range p.Stacks { + before, _, _ := strings.Cut(k, "\n") + if cfg.HasStack(p.Program, before) && report.X <= cfg.Rate(p.Program, before) { + x.Stacks[k] = v + } + } + } + + uploadContents, err = json.MarshalIndent(upload, "", " ") + if err != nil { + return "", fmt.Errorf("failed to marshal upload report for %s: %v", expiryDate, err) + } + } + localFileName := filepath.Join(u.dir.LocalDir(), "local."+expiryDate+".json") + uploadFileName := filepath.Join(u.dir.LocalDir(), expiryDate+".json") + + /* Prepare to write files */ + // if either file exists, someone has been here ahead of us + // (there is still a race, but this check shortens the open window) + if _, err := os.Stat(localFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("local report %s already exists", localFileName) + } + if _, err := os.Stat(uploadFileName); err == nil { + u.deleteFiles(countFiles) + return "", fmt.Errorf("report %s already exists", uploadFileName) + } + // write the uploadable file + var errUpload, errLocal error + if uploadOK { + _, errUpload = exclusiveWrite(uploadFileName, uploadContents) + } + // write the local file + _, errLocal = exclusiveWrite(localFileName, localContents) + /* Wrote the files */ + + // even though these errors won't occur, what should happen + // if errUpload == nil and it is ok to upload, and errLocal != nil? + if errLocal != nil { + return "", fmt.Errorf("failed to write local file %s (%v)", localFileName, errLocal) + } + if errUpload != nil { + return "", fmt.Errorf("failed to write upload file %s (%v)", uploadFileName, errUpload) + } + u.logger.Printf("Created %s, deleting %d count files", filepath.Base(uploadFileName), len(countFiles)) + u.deleteFiles(countFiles) + if uploadOK { + return uploadFileName, nil + } + return "", nil +} + +// exclusiveWrite attempts to create filename exclusively, and if successful, +// writes content to the resulting file handle. +// +// It returns a boolean indicating whether the exclusive handle was acquired, +// and an error indicating whether the operation succeeded. +// If the file already exists, exclusiveWrite returns (false, nil). +func exclusiveWrite(filename string, content []byte) (_ bool, rerr error) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + if os.IsExist(err) { + return false, nil + } + return false, err + } + defer func() { + if err := f.Close(); err != nil && rerr == nil { + rerr = err + } + }() + if _, err := f.Write(content); err != nil { + return false, err + } + return true, nil +} + +// return an existing ProgremReport, or create anew +func findProgReport(meta map[string]string, report *telemetry.Report) *telemetry.ProgramReport { + for _, prog := range report.Programs { + if prog.Program == meta["Program"] && prog.Version == meta["Version"] && + prog.GoVersion == meta["GoVersion"] && prog.GOOS == meta["GOOS"] && + prog.GOARCH == meta["GOARCH"] { + return prog + } + } + prog := telemetry.ProgramReport{ + Program: meta["Program"], + Version: meta["Version"], + GoVersion: meta["GoVersion"], + GOOS: meta["GOOS"], + GOARCH: meta["GOARCH"], + Counters: make(map[string]int64), + Stacks: make(map[string]int64), + } + report.Programs = append(report.Programs, &prog) + return &prog +} + +// computeRandom returns a cryptographic random float64 in the range [0, 1], +// with 52 bits of precision. +func computeRandom() float64 { + for { + b := make([]byte, 8) + _, err := rand.Read(b) + if err != nil { + panic(fmt.Sprintf("rand.Read failed: %v", err)) + } + // and turn it into a float64 + x := math.Float64frombits(binary.LittleEndian.Uint64(b)) + if math.IsNaN(x) || math.IsInf(x, 0) { + continue + } + x = math.Abs(x) + if x < 0x1p-1000 { // avoid underflow patterns + continue + } + frac, _ := math.Frexp(x) // 52 bits of randomness + return frac*2 - 1 + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/run.go b/public-api/vendor/golang.org/x/telemetry/internal/upload/run.go new file mode 100644 index 00000000..e9c8dc20 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/run.go @@ -0,0 +1,226 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "fmt" + "io" + "log" + "os" + "path" + "path/filepath" + "runtime/debug" + "strings" + "time" + + "golang.org/x/telemetry/internal/configstore" + "golang.org/x/telemetry/internal/telemetry" +) + +// RunConfig configures non-default behavior of a call to Run. +// +// All fields are optional, for testing or observability. +type RunConfig struct { + TelemetryDir string // if set, overrides the telemetry data directory + UploadURL string // if set, overrides the telemetry upload endpoint + LogWriter io.Writer // if set, used for detailed logging of the upload process + Env []string // if set, appended to the config download environment + StartTime time.Time // if set, overrides the upload start time +} + +// Run generates and uploads reports, as allowed by the mode file. +func Run(config RunConfig) error { + defer func() { + if err := recover(); err != nil { + log.Printf("upload recover: %v", err) + } + }() + uploader, err := newUploader(config) + if err != nil { + return err + } + defer uploader.Close() + return uploader.Run() +} + +// uploader encapsulates a single upload operation, carrying parameters and +// shared state. +type uploader struct { + // config is used to select counters to upload. + config *telemetry.UploadConfig // + configVersion string // version of the config + dir telemetry.Dir // the telemetry dir to process + + uploadServerURL string + startTime time.Time + + cache parsedCache + + logFile *os.File + logger *log.Logger +} + +// newUploader creates a new uploader to use for running the upload for the +// given config. +// +// Uploaders should only be used for one call to [uploader.Run]. +func newUploader(rcfg RunConfig) (*uploader, error) { + // Determine the upload directory. + var dir telemetry.Dir + if rcfg.TelemetryDir != "" { + dir = telemetry.NewDir(rcfg.TelemetryDir) + } else { + dir = telemetry.Default + } + + // Determine the upload URL. + uploadURL := rcfg.UploadURL + if uploadURL == "" { + uploadURL = "https://telemetry.go.dev/upload" + } + + // Determine the upload logger. + // + // This depends on the provided rcfg.LogWriter and the presence of + // dir.DebugDir, as follows: + // 1. If LogWriter is present, log to it. + // 2. If DebugDir is present, log to a file within it. + // 3. If both LogWriter and DebugDir are present, log to a multi writer. + // 4. If neither LogWriter nor DebugDir are present, log to a noop logger. + var logWriters []io.Writer + logFile, err := debugLogFile(dir.DebugDir()) + if err != nil { + logFile = nil + } + if logFile != nil { + logWriters = append(logWriters, logFile) + } + if rcfg.LogWriter != nil { + logWriters = append(logWriters, rcfg.LogWriter) + } + var logWriter io.Writer + switch len(logWriters) { + case 0: + logWriter = io.Discard + case 1: + logWriter = logWriters[0] + default: + logWriter = io.MultiWriter(logWriters...) + } + logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile) + + // Fetch the upload config, if it is not provided. + var ( + config *telemetry.UploadConfig + configVersion string + ) + + if mode, _ := dir.Mode(); mode == "on" { + // golang/go#68946: only download the upload config if it will be used. + // + // TODO(rfindley): This is a narrow change aimed at minimally fixing the + // associated bug. In the future, we should read the mode only once during + // the upload process. + config, configVersion, err = configstore.Download("latest", rcfg.Env) + if err != nil { + return nil, err + } + } else { + config = &telemetry.UploadConfig{} + configVersion = "v0.0.0-0" + } + + // Set the start time, if it is not provided. + startTime := time.Now().UTC() + if !rcfg.StartTime.IsZero() { + startTime = rcfg.StartTime + } + + return &uploader{ + config: config, + configVersion: configVersion, + dir: dir, + uploadServerURL: uploadURL, + startTime: startTime, + + logFile: logFile, + logger: logger, + }, nil +} + +// Close cleans up any resources associated with the uploader. +func (u *uploader) Close() error { + if u.logFile == nil { + return nil + } + return u.logFile.Close() +} + +// Run generates and uploads reports +func (u *uploader) Run() error { + if telemetry.DisabledOnPlatform { + return nil + } + todo := u.findWork() + ready, err := u.reports(&todo) + if err != nil { + u.logger.Printf("Error building reports: %v", err) + return fmt.Errorf("reports failed: %v", err) + } + u.logger.Printf("Uploading %d reports", len(ready)) + for _, f := range ready { + u.uploadReport(f) + } + return nil +} + +// debugLogFile arranges to write a log file in the given debug directory, if +// it exists. +func debugLogFile(debugDir string) (*os.File, error) { + fd, err := os.Stat(debugDir) + if os.IsNotExist(err) { + return nil, nil + } + if err != nil { + return nil, err + } + if !fd.IsDir() { + return nil, fmt.Errorf("debug path %q is not a directory", debugDir) + } + info, ok := debug.ReadBuildInfo() + if !ok { + return nil, fmt.Errorf("no build info") + } + year, month, day := time.Now().UTC().Date() + goVers := info.GoVersion + // E.g., goVers:"go1.22-20240109-RC01 cl/597041403 +dcbe772469 X:loopvar" + words := strings.Fields(goVers) + goVers = words[0] + progPkgPath := info.Path + if progPkgPath == "" { + progPkgPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } + prog := path.Base(progPkgPath) + progVers := info.Main.Version + if progVers == "(devel)" { // avoid special characters in created file names + progVers = "devel" + } + logBase := strings.ReplaceAll( + fmt.Sprintf("%s-%s-%s-%4d%02d%02d-%d.log", prog, progVers, goVers, year, month, day, os.Getpid()), + " ", "") + fname := filepath.Join(debugDir, logBase) + if _, err := os.Stat(fname); err == nil { + // This process previously called upload.Run + return nil, nil + } + f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return nil, nil // this process previously called upload.Run + } + return nil, err + } + return f, nil +} diff --git a/public-api/vendor/golang.org/x/telemetry/internal/upload/upload.go b/public-api/vendor/golang.org/x/telemetry/internal/upload/upload.go new file mode 100644 index 00000000..419745f6 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/internal/upload/upload.go @@ -0,0 +1,117 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package upload + +import ( + "bytes" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + "time" + + "golang.org/x/telemetry/internal/telemetry" +) + +var ( + dateRE = regexp.MustCompile(`(\d\d\d\d-\d\d-\d\d)[.]json$`) + dateFormat = telemetry.DateOnly + // TODO(rfindley): use dateFormat throughout. +) + +// uploadReportDate returns the date component of the upload file name, or "" if the +// date was unmatched. +func (u *uploader) uploadReportDate(fname string) time.Time { + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("malformed report name: missing date: %q", filepath.Base(fname)) + return time.Time{} + } + d, err := time.Parse(dateFormat, match[1]) + if err != nil { + u.logger.Printf("malformed report name: bad date: %q", filepath.Base(fname)) + return time.Time{} + } + return d +} + +func (u *uploader) uploadReport(fname string) { + thisInstant := u.startTime + // TODO(rfindley): use uploadReportDate here, once we've done a gopls release. + + // first make sure it is not in the future + today := thisInstant.Format(telemetry.DateOnly) + match := dateRE.FindStringSubmatch(fname) + if match == nil || len(match) < 2 { + u.logger.Printf("Report name %q missing date", filepath.Base(fname)) + } else if match[1] > today { + u.logger.Printf("Report date for %q is later than today (%s)", filepath.Base(fname), today) + return // report is in the future, which shouldn't happen + } + buf, err := os.ReadFile(fname) + if err != nil { + u.logger.Printf("%v reading %s", err, fname) + return + } + if u.uploadReportContents(fname, buf) { + // anything left to do? + } +} + +// try to upload the report, 'true' if successful +func (u *uploader) uploadReportContents(fname string, buf []byte) bool { + fdate := strings.TrimSuffix(filepath.Base(fname), ".json") + fdate = fdate[len(fdate)-len(telemetry.DateOnly):] + + newname := filepath.Join(u.dir.UploadDir(), fdate+".json") + + // Lock the upload, to prevent duplicate uploads. + { + lockname := newname + ".lock" + lockfile, err := os.OpenFile(lockname, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + u.logger.Printf("Failed to acquire lock %s: %v", lockname, err) + return false + } + _ = lockfile.Close() + defer os.Remove(lockname) + } + + if _, err := os.Stat(newname); err == nil { + // Another process uploaded but failed to clean up (or hasn't yet cleaned + // up). Ensure that cleanup occurs. + u.logger.Printf("After acquire: report already uploaded") + _ = os.Remove(fname) + return false + } + + endpoint := u.uploadServerURL + "/" + fdate + b := bytes.NewReader(buf) + resp, err := http.Post(endpoint, "application/json", b) + if err != nil { + u.logger.Printf("Error upload %s to %s: %v", filepath.Base(fname), endpoint, err) + return false + } + // hope for a 200, remove file on a 4xx, otherwise it will be retried by another process + if resp.StatusCode != 200 { + u.logger.Printf("Failed to upload %s to %s: %s", filepath.Base(fname), endpoint, resp.Status) + if resp.StatusCode >= 400 && resp.StatusCode < 500 { + err := os.Remove(fname) + if err == nil { + u.logger.Printf("Removed local/%s", filepath.Base(fname)) + } else { + u.logger.Printf("Error removing local/%s: %v", filepath.Base(fname), err) + } + } + return false + } + // Store a copy of the uploaded report in the uploaded directory. + if err := os.WriteFile(newname, buf, 0644); err == nil { + os.Remove(fname) // if it exists + } + u.logger.Printf("Uploaded %s to %q", fdate+".json", endpoint) + return true +} diff --git a/public-api/vendor/golang.org/x/telemetry/mode.go b/public-api/vendor/golang.org/x/telemetry/mode.go new file mode 100644 index 00000000..8cdcd134 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/mode.go @@ -0,0 +1,38 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Mode returns the current telemetry mode. +// +// The telemetry mode is a global value that controls both the local collection +// and uploading of telemetry data. Possible mode values are: +// - "on": both collection and uploading is enabled +// - "local": collection is enabled, but uploading is disabled +// - "off": both collection and uploading are disabled +// +// When mode is "on", or "local", telemetry data is written to the local file +// system and may be inspected with the [gotelemetry] command. +// +// If an error occurs while reading the telemetry mode from the file system, +// Mode returns the default value "local". +// +// [gotelemetry]: https://pkg.go.dev/golang.org/x/telemetry/cmd/gotelemetry +func Mode() string { + mode, _ := telemetry.Default.Mode() + return mode +} + +// SetMode sets the global telemetry mode to the given value. +// +// See the documentation of [Mode] for a description of the supported mode +// values. +// +// An error is returned if the provided mode value is invalid, or if an error +// occurs while persisting the mode value to the file system. +func SetMode(mode string) error { + return telemetry.Default.SetMode(mode) +} diff --git a/public-api/vendor/golang.org/x/telemetry/npm b/public-api/vendor/golang.org/x/telemetry/npm new file mode 100644 index 00000000..a5455cfb --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/npm @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npm \ + node:18.16.0-slim \ + $@ diff --git a/public-api/vendor/golang.org/x/telemetry/npx b/public-api/vendor/golang.org/x/telemetry/npx new file mode 100644 index 00000000..47bb38bb --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/npx @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 2022 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +docker run \ + --rm \ + --volume $(pwd):/workspace \ + --workdir /workspace \ + --env NODE_OPTIONS="--dns-result-order=ipv4first" \ + --entrypoint npx \ + node:18.16.0-slim \ + $@ diff --git a/public-api/vendor/golang.org/x/telemetry/package-lock.json b/public-api/vendor/golang.org/x/telemetry/package-lock.json new file mode 100644 index 00000000..9c86033e --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/package-lock.json @@ -0,0 +1,4363 @@ +{ + "name": "workspace", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.1.1.tgz", + "integrity": "sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.1.tgz", + "integrity": "sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.4.tgz", + "integrity": "sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@observablehq/plot": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.9.tgz", + "integrity": "sha512-vwV6bzQsGjv2XrPEpc3Voixcz2e5EVvCSzzcs/uW9KXO5ZM8GdMVXtNTaRwYXUOk98nbiYFCFwzMaIyRjrt9IA==", + "dependencies": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.6", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.3.tgz", + "integrity": "sha512-JRHwbQQ84XuAESWhvIPaUV4/1UYTBOLiOPGWqgFDHZS1D5QN9c57FbH3QpEnQMYiOXNzKUQyGTZf+EVO7RT5TQ==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "dependencies": { + "binary-search-bounds": "^2.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", + "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.1.1", + "@csstools/css-tokenizer": "^2.1.1", + "@csstools/media-query-list-parser": "^2.0.4", + "@csstools/selector-specificity": "^2.2.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.1.3", + "css-functions-list": "^3.1.0", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.27.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.12", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-12.0.0.tgz", + "integrity": "sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "33.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-33.0.0.tgz", + "integrity": "sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^12.0.0" + }, + "peerDependencies": { + "stylelint": "^15.5.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/package.json b/public-api/vendor/golang.org/x/telemetry/package.json new file mode 100644 index 00000000..3680ce22 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/package.json @@ -0,0 +1,23 @@ +{ + "scripts": { + "eslint": "eslint . --fix", + "stylelint": "stylelint '**/*.css' --fix", + "prettier": "prettier --write **/*.{css,ts,md,yaml} !**/*.min.css", + "all": "run-s --continue-on-error eslint stylelint prettier" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", + "eslint": "8.40.0", + "eslint-config-prettier": "8.8.0", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "stylelint": "15.6.2", + "stylelint-config-standard": "33.0.0", + "typescript": "5.0.4" + }, + "dependencies": { + "@observablehq/plot": "0.6.9", + "d3": "7.8.5" + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/start.go b/public-api/vendor/golang.org/x/telemetry/start.go new file mode 100644 index 00000000..9c0519a6 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/start.go @@ -0,0 +1,354 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "sync" + "time" + + "golang.org/x/sync/errgroup" + "golang.org/x/telemetry/counter" + "golang.org/x/telemetry/internal/crashmonitor" + "golang.org/x/telemetry/internal/telemetry" + "golang.org/x/telemetry/internal/upload" +) + +// Config controls the behavior of [Start]. +type Config struct { + // ReportCrashes, if set, will enable crash reporting. + // ReportCrashes uses the [debug.SetCrashOutput] mechanism, which is a + // process-wide resource. + // Do not make other calls to that function within your application. + // ReportCrashes is a non-functional unless the program is built with go1.23+. + ReportCrashes bool + + // Upload causes this program to periodically upload approved counters + // from the local telemetry database to telemetry.go.dev. + // + // This option has no effect unless the user has given consent + // to enable data collection, for example by running + // cmd/gotelemetry or affirming the gopls dialog. + // + // (This feature is expected to be used only by gopls. + // Longer term, the go command may become the sole program + // responsible for uploading.) + Upload bool + + // TelemetryDir, if set, will specify an alternate telemetry + // directory to write data to. If not set, it uses the default + // directory. + // This field is intended to be used for isolating testing environments. + TelemetryDir string + + // UploadStartTime, if set, overrides the time used as the upload start time, + // which is the time used by the upload logic to determine whether counter + // file data should be uploaded. Only counter files that have expired before + // the start time are considered for upload. + // + // This field can be used to simulate a future upload that collects recently + // modified counters. + UploadStartTime time.Time + + // UploadURL, if set, overrides the URL used to receive uploaded reports. If + // unset, this URL defaults to https://telemetry.go.dev/upload. + UploadURL string +} + +// Start initializes telemetry using the specified configuration. +// +// Start opens the local telemetry database so that counter increment +// operations are durably recorded in the local file system. +// +// If [Config.Upload] is set, and the user has opted in to telemetry +// uploading, this process may attempt to upload approved counters +// to telemetry.go.dev. +// +// If [Config.ReportCrashes] is set, any fatal crash will be +// recorded by incrementing a counter named for the stack of the +// first running goroutine in the traceback. +// +// If either of these flags is set, Start re-executes the current +// executable as a child process, in a special mode in which it +// acts as a telemetry sidecar for the parent process (the application). +// In that mode, the call to Start will never return, so Start must +// be called immediately within main, even before such things as +// inspecting the command line. The application should avoid expensive +// steps or external side effects in init functions, as they will +// be executed twice (parent and child). +// +// Start returns a StartResult, which may be awaited via [StartResult.Wait] to +// wait for all work done by Start to complete. +func Start(config Config) *StartResult { + switch v := os.Getenv(telemetryChildVar); v { + case "": + // The subprocess started by parent has GO_TELEMETRY_CHILD=1. + return parent(config) + case "1": + child(config) // child will exit the process when it's done. + case "2": + // Do nothing: this was executed directly or indirectly by a child. + default: + log.Fatalf("unexpected value for %q: %q", telemetryChildVar, v) + } + + return &StartResult{} +} + +// MaybeChild executes the telemetry child logic if the calling program is +// the telemetry child process, and does nothing otherwise. It is meant to be +// called as the first thing in a program that uses telemetry.Start but cannot +// call telemetry.Start immediately when it starts. +func MaybeChild(config Config) { + if v := os.Getenv(telemetryChildVar); v == "1" { + child(config) // child will exit the process when it's done. + } + // other values of the telemetryChildVar environment variable + // will be handled by telemetry.Start. +} + +// A StartResult is a handle to the result of a call to [Start]. Call +// [StartResult.Wait] to wait for the completion of all work done on behalf of +// Start. +type StartResult struct { + wg sync.WaitGroup +} + +// Wait waits for the completion of all work initiated by [Start]. +func (res *StartResult) Wait() { + if res == nil { + return + } + res.wg.Wait() +} + +var daemonize = func(cmd *exec.Cmd) {} + +// If telemetryChildVar is set to "1" in the environment, this is the telemetry +// child. +// +// If telemetryChildVar is set to "2", this is a child of the child, and no +// further forking should occur. +const telemetryChildVar = "GO_TELEMETRY_CHILD" + +// If telemetryUploadVar is set to "1" in the environment, the upload token has been +// acquired by the parent, and the child should attempt an upload. +const telemetryUploadVar = "GO_TELEMETRY_CHILD_UPLOAD" + +func parent(config Config) *StartResult { + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + result := new(StartResult) + + mode, _ := telemetry.Default.Mode() + if mode == "off" { + // Telemetry is turned off. Crash reporting doesn't work without telemetry + // at least set to "local". The upload process runs in both "on" and "local" modes. + // In local mode the upload process builds local reports but does not do the upload. + return result + } + + counter.Open() + + if _, err := os.Stat(telemetry.Default.LocalDir()); err != nil { + // There was a problem statting LocalDir, which is needed for both + // crash monitoring and counter uploading. Most likely, there was an + // error creating telemetry.LocalDir in the counter.Open call above. + // Don't start the child. + return result + } + + childShouldUpload := config.Upload && acquireUploadToken() + reportCrashes := config.ReportCrashes + + if reportCrashes || childShouldUpload { + startChild(reportCrashes, childShouldUpload, result) + } + + return result +} + +func startChild(reportCrashes, upload bool, result *StartResult) { + // This process is the application (parent). + // Fork+exec the telemetry child. + exe, err := os.Executable() + if err != nil { + // There was an error getting os.Executable. It's possible + // for this to happen on AIX if os.Args[0] is not an absolute + // path and we can't find os.Args[0] in PATH. + log.Printf("failed to start telemetry sidecar: os.Executable: %v", err) + return + } + cmd := exec.Command(exe, "** telemetry **") // this unused arg is just for ps(1) + daemonize(cmd) + cmd.Env = append(os.Environ(), telemetryChildVar+"=1") + if upload { + cmd.Env = append(cmd.Env, telemetryUploadVar+"=1") + } + cmd.Dir = telemetry.Default.LocalDir() + + // The child process must write to a log file, not + // the stderr file it inherited from the parent, as + // the child may outlive the parent but should not prolong + // the life of any pipes created (by the grandparent) + // to gather the output of the parent. + // + // By default, we discard the child process's stderr, + // but in line with the uploader, log to a file in debug + // only if that directory was created by the user. + fd, err := os.Stat(telemetry.Default.DebugDir()) + if err != nil { + if !os.IsNotExist(err) { + log.Printf("failed to stat debug directory: %v", err) + return + } + } else if fd.IsDir() { + // local/debug exists and is a directory. Set stderr to a log file path + // in local/debug. + childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log") + childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) + if err != nil { + log.Printf("opening sidecar log file for child: %v", err) + return + } + defer childLog.Close() + cmd.Stderr = childLog + } + + var crashOutputFile *os.File + if reportCrashes { + pipe, err := cmd.StdinPipe() + if err != nil { + log.Printf("StdinPipe: %v", err) + return + } + + crashOutputFile = pipe.(*os.File) // (this conversion is safe) + } + + if err := cmd.Start(); err != nil { + // The child couldn't be started. Log the failure. + log.Printf("can't start telemetry child process: %v", err) + return + } + if reportCrashes { + crashmonitor.Parent(crashOutputFile) + } + result.wg.Add(1) + go func() { + cmd.Wait() // Release resources if cmd happens not to outlive this process. + result.wg.Done() + }() +} + +func child(config Config) { + log.SetPrefix(fmt.Sprintf("telemetry-sidecar (pid %v): ", os.Getpid())) + + if config.TelemetryDir != "" { + telemetry.Default = telemetry.NewDir(config.TelemetryDir) + } + + // golang/go#67211: be sure to set telemetryChildVar before running the + // child, because the child itself invokes the go command to download the + // upload config. If the telemetryChildVar variable is still set to "1", + // that delegated go command may think that it is itself a telemetry + // child. + // + // On the other hand, if telemetryChildVar were simply unset, then the + // delegated go commands would fork themselves recursively. Short-circuit + // this recursion. + os.Setenv(telemetryChildVar, "2") + upload := os.Getenv(telemetryUploadVar) == "1" + + // The crashmonitor and/or upload process may themselves record counters. + counter.Open() + + // Start crashmonitoring and uploading depending on what's requested + // and wait for the longer running child to complete before exiting: + // if we collected a crash before the upload finished, wait for the + // upload to finish before exiting + var g errgroup.Group + + if config.ReportCrashes { + g.Go(func() error { + crashmonitor.Child() + return nil + }) + } + if upload { + g.Go(func() error { + uploaderChild(config.UploadStartTime, config.UploadURL) + return nil + }) + } + g.Wait() + + os.Exit(0) +} + +func uploaderChild(asof time.Time, uploadURL string) { + if err := upload.Run(upload.RunConfig{ + UploadURL: uploadURL, + LogWriter: os.Stderr, + StartTime: asof, + }); err != nil { + log.Printf("upload failed: %v", err) + } +} + +// acquireUploadToken acquires a token permitting the caller to upload. +// To limit the frequency of uploads, only one token is issue per +// machine per time period. +// The boolean indicates whether the token was acquired. +func acquireUploadToken() bool { + if telemetry.Default.LocalDir() == "" { + // The telemetry dir wasn't initialized properly, probably because + // os.UserConfigDir did not complete successfully. In that case + // there are no counters to upload, so we should just do nothing. + return false + } + tokenfile := filepath.Join(telemetry.Default.LocalDir(), "upload.token") + const period = 24 * time.Hour + + // A process acquires a token by successfully creating a + // well-known file. If the file already exists and has an + // mtime age less then than the period, the process does + // not acquire the token. If the file is older than the + // period, the process is allowed to remove the file and + // try to re-create it. + fi, err := os.Stat(tokenfile) + if err == nil { + if time.Since(fi.ModTime()) < period { + return false + } + // There's a possible race here where two processes check the + // token file and see that it's older than the period, then the + // first one removes it and creates another, and then a second one + // removes the newly created file and creates yet another + // file. Then both processes would act as though they had the token. + // This is very rare, but it's also okay because we're only grabbing + // the token to do rate limiting, not for correctness. + _ = os.Remove(tokenfile) + } else if !os.IsNotExist(err) { + log.Printf("error acquiring upload taken: statting token file: %v", err) + return false + } + + f, err := os.OpenFile(tokenfile, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + if os.IsExist(err) { + return false + } + log.Printf("error acquiring upload token: creating token file: %v", err) + return false + } + _ = f.Close() + return true +} diff --git a/public-api/vendor/golang.org/x/telemetry/start_posix.go b/public-api/vendor/golang.org/x/telemetry/start_posix.go new file mode 100644 index 00000000..078b2353 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/start_posix.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package telemetry + +import ( + "os/exec" + "syscall" +) + +func init() { + daemonize = daemonizePosix +} + +func daemonizePosix(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/start_windows.go b/public-api/vendor/golang.org/x/telemetry/start_windows.go new file mode 100644 index 00000000..ceb2c029 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/start_windows.go @@ -0,0 +1,29 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package telemetry + +import ( + "os/exec" + "syscall" + + "golang.org/x/sys/windows" +) + +func init() { + daemonize = daemonizeWindows +} + +func daemonizeWindows(cmd *exec.Cmd) { + // Set DETACHED_PROCESS creation flag so that closing + // the console window the parent process was run in + // does not kill the child. + // See documentation of creation flags in the Microsoft documentation: + // https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: windows.DETACHED_PROCESS, + } +} diff --git a/public-api/vendor/golang.org/x/telemetry/tsconfig.json b/public-api/vendor/golang.org/x/telemetry/tsconfig.json new file mode 100644 index 00000000..7833e310 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/tsconfig.json @@ -0,0 +1,26 @@ +{ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "node", + + "strict": true, + "allowUnusedLabels": false, + "allowUnreachableCode": false, + "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "checkJs": true, + + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, +} \ No newline at end of file diff --git a/public-api/vendor/golang.org/x/telemetry/types_alias.go b/public-api/vendor/golang.org/x/telemetry/types_alias.go new file mode 100644 index 00000000..83ba7e05 --- /dev/null +++ b/public-api/vendor/golang.org/x/telemetry/types_alias.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package telemetry + +import "golang.org/x/telemetry/internal/telemetry" + +// Common types and directories used by multiple packages. + +// An UploadConfig controls what data is uploaded. +type UploadConfig = telemetry.UploadConfig + +type ProgramConfig = telemetry.ProgramConfig + +type CounterConfig = telemetry.CounterConfig + +// A Report is what's uploaded (or saved locally) +type Report = telemetry.Report + +type ProgramReport = telemetry.ProgramReport diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index 436b03cb..1aa7afb9 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -57,7 +57,7 @@ type asmArch struct { // include the first integer register and first floating-point register. Accessing // any of them counts as writing to result. retRegs []string - // writeResult is a list of instructions that will change result register implicity. + // writeResult is a list of instructions that will change result register implicitly. writeResult []string // calculated during initialization sizes types.Sizes diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go index 1413ee13..1914bb47 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go @@ -9,11 +9,11 @@ package assign import ( _ "embed" - "fmt" "go/ast" "go/token" "go/types" "reflect" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -48,31 +48,84 @@ func run(pass *analysis.Pass) (any, error) { // If LHS and RHS have different cardinality, they can't be the same. return } + + // Delete redundant LHS, RHS pairs, taking care + // to include intervening commas. + var ( + exprs []string // expressions appearing on both sides (x = x) + edits []analysis.TextEdit + runStartLHS, runStartRHS token.Pos // non-zero => within a run + ) for i, lhs := range stmt.Lhs { rhs := stmt.Rhs[i] - if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || - analysisutil.HasSideEffects(pass.TypesInfo, rhs) || - isMapIndex(pass.TypesInfo, lhs) { - continue // expressions may not be equal - } - if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { - continue // short-circuit the heavy-weight gofmt check + isSelfAssign := false + var le string + + if !analysisutil.HasSideEffects(pass.TypesInfo, lhs) && + !analysisutil.HasSideEffects(pass.TypesInfo, rhs) && + !isMapIndex(pass.TypesInfo, lhs) && + reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check + + le = analysisinternal.Format(pass.Fset, lhs) + re := analysisinternal.Format(pass.Fset, rhs) + if le == re { + isSelfAssign = true + } } - le := analysisinternal.Format(pass.Fset, lhs) - re := analysisinternal.Format(pass.Fset, rhs) - if le == re { - pass.Report(analysis.Diagnostic{ - Pos: stmt.Pos(), Message: fmt.Sprintf("self-assignment of %s to %s", re, le), - SuggestedFixes: []analysis.SuggestedFix{{ - Message: "Remove self-assignment", - TextEdits: []analysis.TextEdit{{ - Pos: stmt.Pos(), - End: stmt.End(), - }}}, - }, - }) + + if isSelfAssign { + exprs = append(exprs, le) + if !runStartLHS.IsValid() { + // Start of a new run of self-assignments. + if i > 0 { + runStartLHS = stmt.Lhs[i-1].End() + runStartRHS = stmt.Rhs[i-1].End() + } else { + runStartLHS = lhs.Pos() + runStartRHS = rhs.Pos() + } + } + } else if runStartLHS.IsValid() { + // End of a run of self-assignments. + endLHS, endRHS := stmt.Lhs[i-1].End(), stmt.Rhs[i-1].End() + if runStartLHS == stmt.Lhs[0].Pos() { + endLHS, endRHS = lhs.Pos(), rhs.Pos() + } + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: endLHS}, + analysis.TextEdit{Pos: runStartRHS, End: endRHS}, + ) + runStartLHS, runStartRHS = 0, 0 } } + + // If a run of self-assignments continues to the end of the statement, close it. + if runStartLHS.IsValid() { + last := len(stmt.Lhs) - 1 + edits = append(edits, + analysis.TextEdit{Pos: runStartLHS, End: stmt.Lhs[last].End()}, + analysis.TextEdit{Pos: runStartRHS, End: stmt.Rhs[last].End()}, + ) + } + + if len(exprs) == 0 { + return + } + + if len(exprs) == len(stmt.Lhs) { + // If every part of the statement is a self-assignment, + // remove the whole statement. + edits = []analysis.TextEdit{{Pos: stmt.Pos(), End: stmt.End()}} + } + + pass.Report(analysis.Diagnostic{ + Pos: stmt.Pos(), + Message: "self-assignment of " + strings.Join(exprs, ", "), + SuggestedFixes: []analysis.SuggestedFix{{ + Message: "Remove self-assignment", + TextEdits: edits, + }}, + }) }) return nil, nil diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 25c98a97..ed2284e6 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -153,7 +153,8 @@ func isLocalType(pass *analysis.Pass, typ types.Type) bool { return isLocalType(pass, x.Elem()) case interface{ Obj() *types.TypeName }: // *Named or *TypeParam (aliases were removed already) // names in package foo are local to foo_test too - return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") + return x.Obj().Pkg() != nil && + strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") } return false } diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go index ba94fd68..ff9c8b4f 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go @@ -28,9 +28,9 @@ var Analyzer = &analysis.Analyzer{ // Per-architecture checks for instructions. // Assume comments, leading and trailing spaces are removed. type arch struct { - isFPWrite func(string) bool - isFPRead func(string) bool - isBranch func(string) bool + isFPWrite func(string) bool + isFPRead func(string) bool + isUnconditionalBranch func(string) bool } var re = regexp.MustCompile @@ -48,8 +48,8 @@ var arches = map[string]arch{ "amd64": { isFPWrite: re(`,\s*BP$`).MatchString, // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely. isFPRead: re(`\bBP\b`).MatchString, - isBranch: func(s string) bool { - return hasAnyPrefix(s, "J", "RET") + isUnconditionalBranch: func(s string) bool { + return hasAnyPrefix(s, "JMP", "RET") }, }, "arm64": { @@ -70,49 +70,16 @@ var arches = map[string]arch{ return false }, isFPRead: re(`\bR29\b`).MatchString, - isBranch: func(s string) bool { + isUnconditionalBranch: func(s string) bool { // Get just the instruction if i := strings.IndexFunc(s, unicode.IsSpace); i > 0 { s = s[:i] } - return arm64Branch[s] + return s == "B" || s == "JMP" || s == "RET" }, }, } -// arm64 has many control flow instructions. -// ^(B|RET) isn't sufficient or correct (e.g. BIC, BFI aren't control flow.) -// It's easier to explicitly enumerate them in a map than to write a regex. -// Borrowed from Go tree, cmd/asm/internal/arch/arm64.go -var arm64Branch = map[string]bool{ - "B": true, - "BL": true, - "BEQ": true, - "BNE": true, - "BCS": true, - "BHS": true, - "BCC": true, - "BLO": true, - "BMI": true, - "BPL": true, - "BVS": true, - "BVC": true, - "BHI": true, - "BLS": true, - "BGE": true, - "BLT": true, - "BGT": true, - "BLE": true, - "CBZ": true, - "CBZW": true, - "CBNZ": true, - "CBNZW": true, - "JMP": true, - "TBNZ": true, - "TBZ": true, - "RET": true, -} - func run(pass *analysis.Pass) (any, error) { arch, ok := arches[build.Default.GOARCH] if !ok { @@ -164,7 +131,7 @@ func run(pass *analysis.Pass) (any, error) { active = false continue } - if arch.isFPRead(line) || arch.isBranch(line) { + if arch.isFPRead(line) || arch.isUnconditionalBranch(line) { active = false continue } diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go index 64df1b10..2580a0ac 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go @@ -88,7 +88,7 @@ func run(pass *analysis.Pass) (any, error) { // // TODO: consider allowing the "last" go/defer/Go statement to be followed by // N "trivial" statements, possibly under a recursive definition of "trivial" - // so that that checker could, for example, conclude that a go statement is + // so that checker could, for example, conclude that a go statement is // followed by an if statement made of only trivial statements and trivial expressions, // and hence the go statement could still be checked. forEachLastStmt(body.List, func(last ast.Stmt) { diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index a28ed365..159a95ae 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/internal/analysisinternal" + "golang.org/x/tools/internal/astutil" "golang.org/x/tools/internal/fmtstr" "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/versions" @@ -540,7 +541,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", name) + pass.ReportRangef(call.Args[firstArg], "%s call has arguments but no formatting directives", name) } return } @@ -552,7 +553,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C if err != nil { // All error messages are in predicate form ("call has a problem") // so that they may be affixed into a subject ("log.Printf "). - pass.ReportRangef(call.Args[idx], "%s %s", name, err) + pass.ReportRangef(formatArg, "%s %s", name, err) return } @@ -560,20 +561,21 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C maxArgIndex := firstArg - 1 anyIndex := false // Check formats against args. - for _, operation := range operations { - if operation.Prec.Index != -1 || - operation.Width.Index != -1 || - operation.Verb.Index != -1 { + for _, op := range operations { + if op.Prec.Index != -1 || + op.Width.Index != -1 || + op.Verb.Index != -1 { anyIndex = true } - if !okPrintfArg(pass, call, &maxArgIndex, firstArg, name, operation) { + rng := opRange(formatArg, op) + if !okPrintfArg(pass, call, rng, &maxArgIndex, firstArg, name, op) { // One error per format is enough. return } - if operation.Verb.Verb == 'w' { + if op.Verb.Verb == 'w' { switch kind { case KindNone, KindPrint, KindPrintf: - pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", name) + pass.ReportRangef(rng, "%s does not support error-wrapping directive %%w", name) return } } @@ -594,6 +596,18 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C } } +// opRange returns the source range for the specified printf operation, +// such as the position of the %v substring of "...%v...". +func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range { + if lit, ok := formatArg.(*ast.BasicLit); ok { + start, end, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End) + if err == nil { + return analysisinternal.Range(start, end) // position of "%v" + } + } + return formatArg // entire format string +} + // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask. type printfArgType int @@ -657,7 +671,7 @@ var printVerbs = []printVerb{ // okPrintfArg compares the operation to the arguments actually present, // reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index. // If the final argument is ellipsissed, there's little it can do for that. -func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { +func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) { verb := operation.Verb.Verb var v printVerb found := false @@ -680,7 +694,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if !formatter { if !found { - pass.ReportRangef(call, "%s format %s has unknown verb %c", name, operation.Text, verb) + pass.ReportRangef(rng, "%s format %s has unknown verb %c", name, operation.Text, verb) return false } for _, flag := range operation.Flags { @@ -690,7 +704,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs continue } if !strings.ContainsRune(v.flags, rune(flag)) { - pass.ReportRangef(call, "%s format %s has unrecognized flag %c", name, operation.Text, flag) + pass.ReportRangef(rng, "%s format %s has unrecognized flag %c", name, operation.Text, flag) return false } } @@ -707,7 +721,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // If len(argIndexes)>0, we have something like %.*s and all // indexes in argIndexes must be an integer. for _, argIndex := range argIndexes { - if !argCanBeChecked(pass, call, argIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, argIndex, firstArg, operation, name) { return } arg := call.Args[argIndex] @@ -716,7 +730,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) + pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details) return false } } @@ -738,12 +752,12 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs // Now check verb's type. verbArgIndex := operation.Verb.ArgIndex - if !argCanBeChecked(pass, call, verbArgIndex, firstArg, operation, name) { + if !argCanBeChecked(pass, call, rng, verbArgIndex, firstArg, operation, name) { return false } arg := call.Args[verbArgIndex] if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' { - pass.ReportRangef(call, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) + pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg)) return false } if reason, ok := matchArgType(pass, v.typ, arg); !ok { @@ -755,12 +769,14 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, maxArgIndex *int, firs if reason != "" { details = " (" + reason + ")" } - pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) + pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details) return false } - if v.typ&argString != 0 && v.verb != 'T' && !strings.Contains(operation.Flags, "#") { + // Detect recursive formatting via value's String/Error methods. + // The '#' flag suppresses the methods, except with %x, %X, and %q. + if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) { if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) + pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName) return false } } @@ -844,7 +860,7 @@ func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { // argCanBeChecked reports whether the specified argument is statically present; // it may be beyond the list of arguments or in a terminal slice... argument, which // means we can't see it. -func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { +func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, argIndex, firstArg int, operation *fmtstr.Operation, name string) bool { if argIndex <= 0 { // Shouldn't happen, so catch it with prejudice. panic("negative argIndex") @@ -861,7 +877,7 @@ func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, argIndex, firstArg // There are bad indexes in the format or there are fewer arguments than the format needs. // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". arg := argIndex - firstArg + 1 // People think of arguments as 1-indexed. - pass.ReportRangef(call, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) + pass.ReportRangef(rng, "%s format %s reads arg #%d, but call has %v", name, operation.Text, arg, count(len(call.Args)-firstArg, "arg")) return false } diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index a23721cd..7dbff1e4 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/typesinternal" ) //go:embed doc.go @@ -60,12 +61,11 @@ func describe(typ, inType types.Type, inName string) string { } func typeName(t types.Type) string { - type hasTypeName interface{ Obj() *types.TypeName } // Alias, Named, TypeParam - switch t := t.(type) { - case *types.Basic: - return t.Name() - case hasTypeName: - return t.Obj().Name() + if basic, ok := t.(*types.Basic); ok { + return basic.Name() // may be (e.g.) "untyped int", which has no TypeName + } + if tname := typesinternal.TypeNameFor(t); tname != nil { + return tname.Name() } return "" } diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go index 13a99973..cc90f733 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/structtag/structtag.go @@ -107,7 +107,7 @@ func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, s // Embedded struct. Nothing to do for now, but that // may change, depending on what happens with issue 7363. - // TODO(adonovan): investigate, now that that issue is fixed. + // TODO(adonovan): investigate, now that issue is fixed. if field.Anonymous() { return } diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 9f59006e..d4e9b025 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -447,18 +447,6 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { } } -type tokenRange struct { - p, e token.Pos -} - -func (r tokenRange) Pos() token.Pos { - return r.p -} - -func (r tokenRange) End() token.Pos { - return r.e -} - func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { // Want functions with 0 results and 1 parameter. if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || @@ -476,8 +464,9 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 { // Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters. // We have currently decided to also warn before compilation/package loading. This can help users in IDEs. - at := tokenRange{tparams.Opening, tparams.Closing} - pass.ReportRangef(at, "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix) + pass.ReportRangef(analysisinternal.Range(tparams.Opening, tparams.Closing), + "%s has type parameters: it will not be run by go test as a %sXXX function", + fn.Name.Name, prefix) } if !isTestSuffix(fn.Name.Name[len(prefix):]) { diff --git a/public-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/public-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index 932f1347..556ffed7 100644 --- a/public-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/public-api/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -26,6 +26,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/analysisinternal" ) //go:embed doc.go @@ -59,23 +60,62 @@ func init() { // The context.With{Cancel,Deadline,Timeout} entries are // effectively redundant wrt the lostcancel analyzer. funcs = stringSetFlag{ - "context.WithCancel": true, - "context.WithDeadline": true, - "context.WithTimeout": true, - "context.WithValue": true, - "errors.New": true, - "fmt.Errorf": true, - "fmt.Sprint": true, - "fmt.Sprintf": true, - "slices.Clip": true, - "slices.Compact": true, - "slices.CompactFunc": true, - "slices.Delete": true, - "slices.DeleteFunc": true, - "slices.Grow": true, - "slices.Insert": true, - "slices.Replace": true, - "sort.Reverse": true, + "context.WithCancel": true, + "context.WithDeadline": true, + "context.WithTimeout": true, + "context.WithValue": true, + "errors.New": true, + "fmt.Append": true, + "fmt.Appendf": true, + "fmt.Appendln": true, + "fmt.Errorf": true, + "fmt.Sprint": true, + "fmt.Sprintf": true, + "fmt.Sprintln": true, + "maps.All": true, + "maps.Clone": true, + "maps.Collect": true, + "maps.Equal": true, + "maps.EqualFunc": true, + "maps.Keys": true, + "maps.Values": true, + "slices.All": true, + "slices.AppendSeq": true, + "slices.Backward": true, + "slices.BinarySearch": true, + "slices.BinarySearchFunc": true, + "slices.Chunk": true, + "slices.Clip": true, + "slices.Clone": true, + "slices.Collect": true, + "slices.Compact": true, + "slices.CompactFunc": true, + "slices.Compare": true, + "slices.CompareFunc": true, + "slices.Concat": true, + "slices.Contains": true, + "slices.ContainsFunc": true, + "slices.Delete": true, + "slices.DeleteFunc": true, + "slices.Equal": true, + "slices.EqualFunc": true, + "slices.Grow": true, + "slices.Index": true, + "slices.IndexFunc": true, + "slices.Insert": true, + "slices.IsSorted": true, + "slices.IsSortedFunc": true, + "slices.Max": true, + "slices.MaxFunc": true, + "slices.Min": true, + "slices.MinFunc": true, + "slices.Repeat": true, + "slices.Replace": true, + "slices.Sorted": true, + "slices.SortedFunc": true, + "slices.SortedStableFunc": true, + "slices.Values": true, + "sort.Reverse": true, } Analyzer.Flags.Var(&funcs, "funcs", "comma-separated list of functions whose results must be used") @@ -114,14 +154,16 @@ func run(pass *analysis.Pass) (any, error) { // method (e.g. foo.String()) if types.Identical(sig, sigNoArgsStringResult) { if stringMethods[fn.Name()] { - pass.Reportf(call.Lparen, "result of (%s).%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of (%s).%s call not used", sig.Recv().Type(), fn.Name()) } } } else { // package-level function (e.g. fmt.Errorf) if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] { - pass.Reportf(call.Lparen, "result of %s.%s call not used", + pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen), + "result of %s.%s call not used", fn.Pkg().Path(), fn.Name()) } } diff --git a/public-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/public-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6e34df46..0fb4e7ee 100644 --- a/public-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/public-api/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -113,7 +113,7 @@ func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Nod // childrenOf elides the FuncType node beneath FuncDecl. // Add it back here for TypeParams, Params, Results, // all FieldLists). But we don't add it back for the "func" token - // even though it is is the tree at FuncDecl.Type.Func. + // even though it is the tree at FuncDecl.Type.Func. if decl, ok := node.(*ast.FuncDecl); ok { if fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv { path = append(path, decl.Type) @@ -207,6 +207,9 @@ func childrenOf(n ast.Node) []ast.Node { return false // no recursion }) + // TODO(adonovan): be more careful about missing (!Pos.Valid) + // tokens in trees produced from invalid input. + // Then add fake Nodes for bare tokens. switch n := n.(type) { case *ast.ArrayType: @@ -226,9 +229,12 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) + if n.Lbrace.IsValid() { + children = append(children, tok(n.Lbrace, len("{"))) + } + if n.Rbrace.IsValid() { + children = append(children, tok(n.Rbrace, len("}"))) + } case *ast.BranchStmt: children = append(children, @@ -304,9 +310,12 @@ func childrenOf(n ast.Node) []ast.Node { // TODO(adonovan): Field.{Doc,Comment,Tag}? case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), // or len("[") - tok(n.Closing, len(")"))) // or len("]") + if n.Opening.IsValid() { + children = append(children, tok(n.Opening, len("("))) + } + if n.Closing.IsValid() { + children = append(children, tok(n.Closing, len(")"))) + } case *ast.File: // TODO test: Doc diff --git a/public-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/public-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index 5c8dbbb7..4ad05493 100644 --- a/public-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/public-api/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -67,6 +67,10 @@ var abort = new(int) // singleton, to signal termination of Apply // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. +// +// This type is not to be confused with [inspector.Cursor] from +// package [golang.org/x/tools/go/ast/inspector], which provides +// stateless navigation of immutable syntax trees. type Cursor struct { parent ast.Node name string diff --git a/public-api/vendor/golang.org/x/tools/internal/astutil/edge/edge.go b/public-api/vendor/golang.org/x/tools/go/ast/edge/edge.go similarity index 100% rename from public-api/vendor/golang.org/x/tools/internal/astutil/edge/edge.go rename to public-api/vendor/golang.org/x/tools/go/ast/edge/edge.go diff --git a/public-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/public-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go new file mode 100644 index 00000000..31c8d2f2 --- /dev/null +++ b/public-api/vendor/golang.org/x/tools/go/ast/inspector/cursor.go @@ -0,0 +1,502 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package inspector + +import ( + "fmt" + "go/ast" + "go/token" + "iter" + "reflect" + + "golang.org/x/tools/go/ast/edge" +) + +// A Cursor represents an [ast.Node]. It is immutable. +// +// Two Cursors compare equal if they represent the same node. +// +// Call [Inspector.Root] to obtain a valid cursor for the virtual root +// node of the traversal. +// +// Use the following methods to navigate efficiently around the tree: +// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing]; +// - for children, use [Cursor.Child], [Cursor.Children], +// [Cursor.FirstChild], and [Cursor.LastChild]; +// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling]; +// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode], +// [Cursor.Inspect], and [Cursor.Preorder]. +// +// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for +// information about the edges in a tree: which field (and slice +// element) of the parent node holds the child. +type Cursor struct { + in *Inspector + index int32 // index of push node; -1 for virtual root node +} + +// Root returns a cursor for the virtual root node, +// whose children are the files provided to [New]. +// +// Its [Cursor.Node] and [Cursor.Stack] methods return nil. +func (in *Inspector) Root() Cursor { + return Cursor{in, -1} +} + +// At returns the cursor at the specified index in the traversal, +// which must have been obtained from [Cursor.Index] on a Cursor +// belonging to the same Inspector (see [Cursor.Inspector]). +func (in *Inspector) At(index int32) Cursor { + if index < 0 { + panic("negative index") + } + if int(index) >= len(in.events) { + panic("index out of range for this inspector") + } + if in.events[index].index < index { + panic("invalid index") // (a push, not a pop) + } + return Cursor{in, index} +} + +// Inspector returns the cursor's Inspector. +func (c Cursor) Inspector() *Inspector { return c.in } + +// Index returns the index of this cursor position within the package. +// +// Clients should not assume anything about the numeric Index value +// except that it increases monotonically throughout the traversal. +// It is provided for use with [At]. +// +// Index must not be called on the Root node. +func (c Cursor) Index() int32 { + if c.index < 0 { + panic("Index called on Root node") + } + return c.index +} + +// Node returns the node at the current cursor position, +// or nil for the cursor returned by [Inspector.Root]. +func (c Cursor) Node() ast.Node { + if c.index < 0 { + return nil + } + return c.in.events[c.index].node +} + +// String returns information about the cursor's node, if any. +func (c Cursor) String() string { + if c.in == nil { + return "(invalid)" + } + if c.index < 0 { + return "(root)" + } + return reflect.TypeOf(c.Node()).String() +} + +// indices return the [start, end) half-open interval of event indices. +func (c Cursor) indices() (int32, int32) { + if c.index < 0 { + return 0, int32(len(c.in.events)) // root: all events + } else { + return c.index, c.in.events[c.index].index + 1 // just one subtree + } +} + +// Preorder returns an iterator over the nodes of the subtree +// represented by c in depth-first order. Each node in the sequence is +// represented by a Cursor that allows access to the Node, but may +// also be used to start a new traversal, or to obtain the stack of +// nodes enclosing the cursor. +// +// The traversal sequence is determined by [ast.Inspect]. The types +// argument, if non-empty, enables type-based filtering of events. The +// function f if is called only for nodes whose type matches an +// element of the types slice. +// +// If you need control over descent into subtrees, +// or need both pre- and post-order notifications, use [Cursor.Inspect] +func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain types: skip. + i = pop + 1 + continue + } + } + i++ + } + } +} + +// Inspect visits the nodes of the subtree represented by c in +// depth-first order. It calls f(n) for each node n before it +// visits n's children. If f returns true, Inspect invokes f +// recursively for each of the non-nil children of the node. +// +// Each node is represented by a Cursor that allows access to the +// Node, but may also be used to start a new traversal, or to obtain +// the stack of nodes enclosing the cursor. +// +// The complete traversal sequence is determined by [ast.Inspect]. +// The types argument, if non-empty, enables type-based filtering of +// events. The function f if is called only for nodes whose type +// matches an element of the types slice. +func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { + mask := maskOf(types) + events := c.in.events + for i, limit := c.indices(); i < limit; { + ev := events[i] + if ev.index > i { + // push + pop := ev.index + if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || + events[pop].typ&mask == 0 { + // The user opted not to descend, or the + // subtree does not contain types: + // skip past the pop. + i = pop + 1 + continue + } + } + i++ + } +} + +// Enclosing returns an iterator over the nodes enclosing the current +// current node, starting with the Cursor itself. +// +// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// The types argument, if non-empty, enables type-based filtering of +// events: the sequence includes only enclosing nodes whose type +// matches an element of the types slice. +func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { + if c.index < 0 { + panic("Cursor.Enclosing called on Root node") + } + + mask := maskOf(types) + + return func(yield func(Cursor) bool) { + events := c.in.events + for i := c.index; i >= 0; i = events[i].parent { + if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { + break + } + } + } +} + +// Parent returns the parent of the current node. +// +// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Parent() Cursor { + if c.index < 0 { + panic("Cursor.Parent called on Root node") + } + + return Cursor{c.in, c.in.events[c.index].parent} +} + +// ParentEdge returns the identity of the field in the parent node +// that holds this cursor's node, and if it is a list, the index within it. +// +// For example, f(x, y) is a CallExpr whose three children are Idents. +// f has edge kind [edge.CallExpr_Fun] and index -1. +// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. +// +// If called on a child of the Root node, it returns ([edge.Invalid], -1). +// +// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) ParentEdge() (edge.Kind, int) { + if c.index < 0 { + panic("Cursor.ParentEdge called on Root node") + } + events := c.in.events + pop := events[c.index].index + return unpackEdgeKindAndIndex(events[pop].parent) +} + +// ChildAt returns the cursor for the child of the +// current node identified by its edge and index. +// The index must be -1 if the edge.Kind is not a slice. +// The indicated child node must exist. +// +// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). +// +// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. +func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { + target := packEdgeKindAndIndex(k, idx) + + // Unfortunately there's no shortcut to looping. + events := c.in.events + i := c.index + 1 + for { + pop := events[i].index + if pop < i { + break + } + if events[pop].parent == target { + return Cursor{c.in, i} + } + i = pop + 1 + } + panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) +} + +// Child returns the cursor for n, which must be a direct child of c's Node. +// +// Child must not be called on the Root node (whose [Cursor.Node] returns nil). +func (c Cursor) Child(n ast.Node) Cursor { + if c.index < 0 { + panic("Cursor.Child called on Root node") + } + + if false { + // reference implementation + for child := range c.Children() { + if child.Node() == n { + return child + } + } + + } else { + // optimized implementation + events := c.in.events + for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { + if events[i].node == n { + return Cursor{c.in, i} + } + } + } + panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) +} + +// NextSibling returns the cursor for the next sibling node in the same list +// (for example, of files, decls, specs, statements, fields, or expressions) as +// the current node. It returns (zero, false) if the node is the last node in +// the list, or is not part of a list. +// +// NextSibling must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) NextSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.NextSibling called on Root node") + } + + events := c.in.events + i := events[c.index].index + 1 // after corresponding pop + if i < int32(len(events)) { + if events[i].index > i { // push? + return Cursor{c.in, i}, true + } + } + return Cursor{}, false +} + +// PrevSibling returns the cursor for the previous sibling node in the +// same list (for example, of files, decls, specs, statements, fields, +// or expressions) as the current node. It returns zero if the node is +// the first node in the list, or is not part of a list. +// +// It must not be called on the Root node. +// +// See note at [Cursor.Children]. +func (c Cursor) PrevSibling() (Cursor, bool) { + if c.index < 0 { + panic("Cursor.PrevSibling called on Root node") + } + + events := c.in.events + i := c.index - 1 + if i >= 0 { + if j := events[i].index; j < i { // pop? + return Cursor{c.in, j}, true + } + } + return Cursor{}, false +} + +// FirstChild returns the first direct child of the current node, +// or zero if it has no children. +func (c Cursor) FirstChild() (Cursor, bool) { + events := c.in.events + i := c.index + 1 // i=0 if c is root + if i < int32(len(events)) && events[i].index > i { // push? + return Cursor{c.in, i}, true + } + return Cursor{}, false +} + +// LastChild returns the last direct child of the current node, +// or zero if it has no children. +func (c Cursor) LastChild() (Cursor, bool) { + events := c.in.events + if c.index < 0 { // root? + if len(events) > 0 { + // return push of final event (a pop) + return Cursor{c.in, events[len(events)-1].index}, true + } + } else { + j := events[c.index].index - 1 // before corresponding pop + // Inv: j == c.index if c has no children + // or j is last child's pop. + if j > c.index { // c has children + return Cursor{c.in, events[j].index}, true + } + } + return Cursor{}, false +} + +// Children returns an iterator over the direct children of the +// current node, if any. +// +// When using Children, NextChild, and PrevChild, bear in mind that a +// Node's children may come from different fields, some of which may +// be lists of nodes without a distinguished intervening container +// such as [ast.BlockStmt]. +// +// For example, [ast.CaseClause] has a field List of expressions and a +// field Body of statements, so the children of a CaseClause are a mix +// of expressions and statements. Other nodes that have "uncontained" +// list fields include: +// +// - [ast.ValueSpec] (Names, Values) +// - [ast.CompositeLit] (Type, Elts) +// - [ast.IndexListExpr] (X, Indices) +// - [ast.CallExpr] (Fun, Args) +// - [ast.AssignStmt] (Lhs, Rhs) +// +// So, do not assume that the previous sibling of an ast.Stmt is also +// an ast.Stmt, or if it is, that they are executed sequentially, +// unless you have established that, say, its parent is a BlockStmt +// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. +// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, +// even though they are not executed in sequence. +func (c Cursor) Children() iter.Seq[Cursor] { + return func(yield func(Cursor) bool) { + c, ok := c.FirstChild() + for ok && yield(c) { + c, ok = c.NextSibling() + } + } +} + +// Contains reports whether c contains or is equal to c2. +// +// Both Cursors must belong to the same [Inspector]; +// neither may be its Root node. +func (c Cursor) Contains(c2 Cursor) bool { + if c.in != c2.in { + panic("different inspectors") + } + events := c.in.events + return c.index <= c2.index && events[c2.index].index <= events[c.index].index +} + +// FindNode returns the cursor for node n if it belongs to the subtree +// rooted at c. It returns zero if n is not found. +func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { + + // FindNode is equivalent to this code, + // but more convenient and 15-20% faster: + if false { + for candidate := range c.Preorder(n) { + if candidate.Node() == n { + return candidate, true + } + } + return Cursor{}, false + } + + // TODO(adonovan): opt: should we assume Node.Pos is accurate + // and combine type-based filtering with position filtering + // like FindByPos? + + mask := maskOf([]ast.Node{n}) + events := c.in.events + + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + if ev.typ&mask != 0 && ev.node == n { + return Cursor{c.in, i}, true + } + pop := ev.index + if events[pop].typ&mask == 0 { + // Subtree does not contain type of n: skip. + i = pop + } + } + } + return Cursor{}, false +} + +// FindByPos returns the cursor for the innermost node n in the tree +// rooted at c such that n.Pos() <= start && end <= n.End(). +// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) +// +// It returns zero if none is found. +// Precondition: start <= end. +// +// See also [astutil.PathEnclosingInterval], which +// tolerates adjoining whitespace. +func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { + if end < start { + panic("end < start") + } + events := c.in.events + + // This algorithm could be implemented using c.Inspect, + // but it is about 2.5x slower. + + best := int32(-1) // push index of latest (=innermost) node containing range + for i, limit := c.indices(); i < limit; i++ { + ev := events[i] + if ev.index > i { // push? + n := ev.node + var nodeEnd token.Pos + if file, ok := n.(*ast.File); ok { + nodeEnd = file.FileEnd + // Note: files may be out of Pos order. + if file.FileStart > start { + i = ev.index // disjoint, after; skip to next file + continue + } + } else { + nodeEnd = n.End() + if n.Pos() > start { + break // disjoint, after; stop + } + } + // Inv: node.{Pos,FileStart} <= start + if end <= nodeEnd { + // node fully contains target range + best = i + } else if nodeEnd < start { + i = ev.index // disjoint, before; skip forward + } + } + } + if best >= 0 { + return Cursor{c.in, best}, true + } + return Cursor{}, false +} diff --git a/public-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/public-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go index 674490a6..a703cdfc 100644 --- a/public-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go +++ b/public-api/vendor/golang.org/x/tools/go/ast/inspector/inspector.go @@ -13,10 +13,19 @@ // This representation is sometimes called a "balanced parenthesis tree." // // Experiments suggest the inspector's traversals are about 2.5x faster -// than ast.Inspect, but it may take around 5 traversals for this +// than [ast.Inspect], but it may take around 5 traversals for this // benefit to amortize the inspector's construction cost. // If efficiency is the primary concern, do not use Inspector for // one-off traversals. +// +// The [Cursor] type provides a more flexible API for efficient +// navigation of syntax trees in all four "cardinal directions". For +// example, traversals may be nested, so you can find each node of +// type A and then search within it for nodes of type B. Or you can +// traverse from a node to its immediate neighbors: its parent, its +// previous and next sibling, or its first and last child. We +// recommend using methods of Cursor in preference to Inspector where +// possible. package inspector // There are four orthogonal features in a traversal: @@ -37,9 +46,8 @@ package inspector import ( "go/ast" - _ "unsafe" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) // An Inspector provides methods for inspecting @@ -48,18 +56,12 @@ type Inspector struct { events []event } -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *Inspector) []event { return in.events } - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex func packEdgeKindAndIndex(ek edge.Kind, index int) int32 { return int32(uint32(index+1)<<7 | uint32(ek)) } // unpackEdgeKindAndIndex unpacks the edge kind and edge index (within // an []ast.Node slice) from the parent field of a pop event. -// -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) { // The "parent" field of a pop node holds the // edge Kind in the lower 7 bits and the index+1 @@ -83,15 +85,21 @@ type event struct { // TODO: Experiment with storing only the second word of event.node (unsafe.Pointer). // Type can be recovered from the sole bit in typ. +// [Tried this, wasn't faster. --adonovan] // Preorder visits all the nodes of the files supplied to New in // depth-first order. It calls f(n) for each node n before it visits // n's children. // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Preorder] method provides a richer alternative interface. +// Example: +// +// for c := range in.Root().Preorder(types) { ... } func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // Because it avoids postorder calls to f, and the pruning // check, Preorder is almost twice as fast as Nodes. The two @@ -131,10 +139,18 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) { // of the non-nil children of the node, followed by a call of // f(n, false). // -// The complete traversal sequence is determined by ast.Inspect. +// The complete traversal sequence is determined by [ast.Inspect]. // The types argument, if non-empty, enables type-based filtering of // events. The function f if is called only for nodes whose type // matches an element of the types slice. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// ... +// return true +// } func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) { mask := maskOf(types) for i := int32(0); i < int32(len(in.events)); { @@ -168,6 +184,15 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proc // supplies each call to f an additional argument, the current // traversal stack. The stack's first element is the outermost node, // an *ast.File; its last is the innermost, n. +// +// The [Cursor.Inspect] method provides a richer alternative interface. +// Example: +// +// in.Root().Inspect(types, func(c Cursor) bool { +// stack := slices.Collect(c.Enclosing()) +// ... +// return true +// }) func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) { mask := maskOf(types) var stack []ast.Node @@ -233,7 +258,7 @@ type visitor struct { type item struct { index int32 // index of current node's push event parentIndex int32 // index of parent node's push event - typAccum uint64 // accumulated type bits of current node's descendents + typAccum uint64 // accumulated type bits of current node's descendants edgeKindAndIndex int32 // edge.Kind and index, bit packed } diff --git a/public-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/public-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index e936c67c..9852331a 100644 --- a/public-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/public-api/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - _ "unsafe" ) const ( @@ -217,7 +215,6 @@ func typeOf(n ast.Node) uint64 { return 0 } -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf func maskOf(nodes []ast.Node) uint64 { if len(nodes) == 0 { return math.MaxUint64 // match all node types diff --git a/public-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go b/public-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go index 5a42174a..5f1c93c8 100644 --- a/public-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go +++ b/public-api/vendor/golang.org/x/tools/go/ast/inspector/walk.go @@ -13,7 +13,7 @@ import ( "fmt" "go/ast" - "golang.org/x/tools/internal/astutil/edge" + "golang.org/x/tools/go/ast/edge" ) func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) { diff --git a/public-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go b/public-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go index 26225e7d..f66f4c73 100644 --- a/public-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go +++ b/public-api/vendor/golang.org/x/tools/go/callgraph/vta/graph.go @@ -658,7 +658,7 @@ func (b *builder) call(c ssa.CallInstruction) { } func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) { - // When f has no paremeters (including receiver), there is no type + // When f has no parameters (including receiver), there is no type // flow here. Also, f's body and parameters might be missing, such // as when vta is used within the golang.org/x/tools/go/analysis // framework (see github.com/golang/go/issues/50670). @@ -803,7 +803,7 @@ func (b *builder) nodeFromVal(val ssa.Value) node { return function{f: v} case *ssa.Parameter, *ssa.FreeVar, ssa.Instruction: // ssa.Param, ssa.FreeVar, and a specific set of "register" instructions, - // satisifying the ssa.Value interface, can serve as local variables. + // satisfying the ssa.Value interface, can serve as local variables. return local{val: v} default: panic(fmt.Errorf("unsupported value %v in node creation", val)) diff --git a/public-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go b/public-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go index bdd39397..adef1282 100644 --- a/public-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go +++ b/public-api/vendor/golang.org/x/tools/go/callgraph/vta/internal/trie/builder.go @@ -245,7 +245,7 @@ func (b *Builder) create(leaves []*leaf) node { } else if n == 1 { return leaves[0] } - // Note: we can do a more sophisicated algorithm by: + // Note: we can do a more sophisticated algorithm by: // - sorting the leaves ahead of time, // - taking the prefix and branching bit of the min and max key, // - binary searching for the branching bit, diff --git a/public-api/vendor/golang.org/x/tools/go/loader/doc.go b/public-api/vendor/golang.org/x/tools/go/loader/doc.go index e35b1fd7..769a1fcf 100644 --- a/public-api/vendor/golang.org/x/tools/go/loader/doc.go +++ b/public-api/vendor/golang.org/x/tools/go/loader/doc.go @@ -164,7 +164,7 @@ package loader // entry is created in this cache by startLoad the first time the // package is imported. The first goroutine to request an entry becomes // responsible for completing the task and broadcasting completion to -// subsequent requestors, which block until then. +// subsequent requesters, which block until then. // // Type checking occurs in (parallel) postorder: we cannot type-check a // set of files until we have loaded and type-checked all of their diff --git a/public-api/vendor/golang.org/x/tools/go/packages/doc.go b/public-api/vendor/golang.org/x/tools/go/packages/doc.go index f1931d10..366aab6b 100644 --- a/public-api/vendor/golang.org/x/tools/go/packages/doc.go +++ b/public-api/vendor/golang.org/x/tools/go/packages/doc.go @@ -76,6 +76,8 @@ uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. +See also [golang.org/x/tools/go/packages/internal/linecount] +for an example application. # The driver protocol diff --git a/public-api/vendor/golang.org/x/tools/go/packages/golist.go b/public-api/vendor/golang.org/x/tools/go/packages/golist.go index 96e43cd8..89f89dd2 100644 --- a/public-api/vendor/golang.org/x/tools/go/packages/golist.go +++ b/public-api/vendor/golang.org/x/tools/go/packages/golist.go @@ -224,13 +224,22 @@ extractQueries: return response.dr, nil } +// abs returns an absolute representation of path, based on cfg.Dir. +func (cfg *Config) abs(path string) (string, error) { + if filepath.IsAbs(path) { + return path, nil + } + // In case cfg.Dir is relative, pass it to filepath.Abs. + return filepath.Abs(filepath.Join(cfg.Dir, path)) +} + func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { for _, query := range queries { // TODO(matloob): Do only one query per directory. fdir := filepath.Dir(query) // Pass absolute path of directory to go list so that it knows to treat it as a directory, // not a package path. - pattern, err := filepath.Abs(fdir) + pattern, err := state.cfg.abs(fdir) if err != nil { return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err) } @@ -703,9 +712,8 @@ func (state *golistState) getGoVersion() (int, error) { // getPkgPath finds the package path of a directory if it's relative to a root // directory. func (state *golistState) getPkgPath(dir string) (string, bool, error) { - absDir, err := filepath.Abs(dir) - if err != nil { - return "", false, err + if !filepath.IsAbs(dir) { + panic("non-absolute dir passed to getPkgPath") } roots, err := state.determineRootDirs() if err != nil { @@ -715,7 +723,7 @@ func (state *golistState) getPkgPath(dir string) (string, bool, error) { for rdir, rpath := range roots { // Make sure that the directory is in the module, // to avoid creating a path relative to another module. - if !strings.HasPrefix(absDir, rdir) { + if !strings.HasPrefix(dir, rdir) { continue } // TODO(matloob): This doesn't properly handle symlinks. diff --git a/public-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/public-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go index d823c474..d9d5a45c 100644 --- a/public-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/public-api/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -55,7 +55,7 @@ func (state *golistState) determineRootDirsModules() (map[string]string, error) } if mod.Dir != "" && mod.Path != "" { // This is a valid module; add it to the map. - absDir, err := filepath.Abs(mod.Dir) + absDir, err := state.cfg.abs(mod.Dir) if err != nil { return nil, err } diff --git a/public-api/vendor/golang.org/x/tools/go/ssa/builder.go b/public-api/vendor/golang.org/x/tools/go/ssa/builder.go index 84ccbc09..a5ef8fb4 100644 --- a/public-api/vendor/golang.org/x/tools/go/ssa/builder.go +++ b/public-api/vendor/golang.org/x/tools/go/ssa/builder.go @@ -25,7 +25,7 @@ package ssa // populating fields such as Function.Body, .Params, and others. // // Building may create additional methods, including: -// - wrapper methods (e.g. for embeddding, or implicit &recv) +// - wrapper methods (e.g. for embedding, or implicit &recv) // - bound method closures (e.g. for use(recv.f)) // - thunks (e.g. for use(I.f) or use(T.f)) // - generic instances (e.g. to produce f[int] from f[any]). @@ -138,7 +138,7 @@ type builder struct { finished int // finished is the length of the prefix of fns containing built functions. // The task of building shared functions within the builder. - // Shared functions are ones the the builder may either create or lookup. + // Shared functions are ones the builder may either create or lookup. // These may be built by other builders in parallel. // The task is done when the builder has finished iterating, and it // waits for all shared functions to finish building. @@ -2920,6 +2920,9 @@ func (b *builder) buildParamsOnly(fn *Function) { for i, n := 0, params.Len(); i < n; i++ { fn.addParamVar(params.At(i)) } + + // clear out other function state (keep consistent with finishBody) + fn.subst = nil } // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. diff --git a/public-api/vendor/golang.org/x/tools/go/ssa/func.go b/public-api/vendor/golang.org/x/tools/go/ssa/func.go index 2d52309b..f48bd718 100644 --- a/public-api/vendor/golang.org/x/tools/go/ssa/func.go +++ b/public-api/vendor/golang.org/x/tools/go/ssa/func.go @@ -386,6 +386,8 @@ func (f *Function) finishBody() { f.results = nil // (used by lifting) f.deferstack = nil // (used by lifting) f.vars = nil // (used by lifting) + + // clear out other function state (keep consistent with buildParamsOnly) f.subst = nil numberRegisters(f) // uses f.namedRegisters diff --git a/public-api/vendor/golang.org/x/tools/go/ssa/sanity.go b/public-api/vendor/golang.org/x/tools/go/ssa/sanity.go index b11680a1..c47a137c 100644 --- a/public-api/vendor/golang.org/x/tools/go/ssa/sanity.go +++ b/public-api/vendor/golang.org/x/tools/go/ssa/sanity.go @@ -27,9 +27,10 @@ type sanity struct { } // sanityCheck performs integrity checking of the SSA representation -// of the function fn and returns true if it was valid. Diagnostics -// are written to reporter if non-nil, os.Stderr otherwise. Some -// diagnostics are only warnings and do not imply a negative result. +// of the function fn (which must have been "built") and returns true +// if it was valid. Diagnostics are written to reporter if non-nil, +// os.Stderr otherwise. Some diagnostics are only warnings and do not +// imply a negative result. // // Sanity-checking is intended to facilitate the debugging of code // transformation passes. diff --git a/public-api/vendor/golang.org/x/tools/go/ssa/subst.go b/public-api/vendor/golang.org/x/tools/go/ssa/subst.go index b4ea1685..362dce12 100644 --- a/public-api/vendor/golang.org/x/tools/go/ssa/subst.go +++ b/public-api/vendor/golang.org/x/tools/go/ssa/subst.go @@ -543,7 +543,7 @@ func (subst *subster) signature(t *types.Signature) types.Type { // We are choosing not to support tparams.Len() > 0 until a need has been observed in practice. // // There are some known usages for types.Types coming from types.{Eval,CheckExpr}. - // To support tparams.Len() > 0, we just need to do the following [psuedocode]: + // To support tparams.Len() > 0, we just need to do the following [pseudocode]: // targs := {subst.replacements[tparams[i]]]}; Instantiate(ctxt, t, targs, false) assert(tparams.Len() == 0, "Substituting types.Signatures with generic functions are currently unsupported.") diff --git a/public-api/vendor/golang.org/x/tools/go/ssa/util.go b/public-api/vendor/golang.org/x/tools/go/ssa/util.go index e53b31ff..932eb6cb 100644 --- a/public-api/vendor/golang.org/x/tools/go/ssa/util.go +++ b/public-api/vendor/golang.org/x/tools/go/ssa/util.go @@ -25,7 +25,7 @@ type unit struct{} //// Sanity checking utilities -// assert panics with the mesage msg if p is false. +// assert panics with the message msg if p is false. // Avoid combining with expensive string formatting. func assert(p bool, msg string) { if !p { diff --git a/public-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/public-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 16ed3c17..d3c2913b 100644 --- a/public-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/public-api/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -603,7 +603,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { type hasTypeParams interface { TypeParams() *types.TypeParamList } - // abstraction of *types.{Named,TypeParam} + // abstraction of *types.{Alias,Named,TypeParam} type hasObj interface { Obj() *types.TypeName } diff --git a/public-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/public-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index c4d10de3..e46aab02 100644 --- a/public-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/public-api/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -22,7 +22,6 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/cursor" "golang.org/x/tools/internal/typesinternal" ) @@ -526,7 +525,7 @@ func CanImport(from, to string) bool { func DeleteStmt(fset *token.FileSet, astFile *ast.File, stmt ast.Stmt, report func(string, ...any)) []analysis.TextEdit { // TODO: pass in the cursor to a ast.Stmt. callers should provide the Cursor insp := inspector.New([]*ast.File{astFile}) - root := cursor.Root(insp) + root := insp.Root() cstmt, ok := root.FindNode(stmt) if !ok { report("%s not found in file", stmt.Pos()) @@ -620,8 +619,8 @@ Outer: // otherwise remove the line edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()} if from.IsValid() || to.IsValid() { - // remove just the statment. - // we can't tell if there is a ; or whitespace right after the statment + // remove just the statement. + // we can't tell if there is a ; or whitespace right after the statement // ideally we'd like to remove the former and leave the latter // (if gofmt has run, there likely won't be a ;) // In type switches we know there's a semicolon somewhere after the statement, @@ -671,3 +670,14 @@ func IsStdPackage(path string) bool { } return !strings.Contains(path[:slash], ".") && path != "testdata" } + +// Range returns an [analysis.Range] for the specified start and end positions. +func Range(pos, end token.Pos) analysis.Range { + return tokenRange{pos, end} +} + +// tokenRange is an implementation of the [analysis.Range] interface. +type tokenRange struct{ StartPos, EndPos token.Pos } + +func (r tokenRange) Pos() token.Pos { return r.StartPos } +func (r tokenRange) End() token.Pos { return r.EndPos } diff --git a/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go b/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go deleted file mode 100644 index 78d874a8..00000000 --- a/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/cursor.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -// Package cursor augments [inspector.Inspector] with [Cursor] -// functionality allowing more flexibility and control during -// inspection. -// -// This package is a temporary private extension of inspector until -// proposal #70859 is accepted, and which point it will be moved into -// the inspector package, and [Root] will become a method of -// Inspector. -package cursor - -import ( - "fmt" - "go/ast" - "go/token" - "iter" - "reflect" - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// A Cursor represents an [ast.Node]. It is immutable. -// -// Two Cursors compare equal if they represent the same node. -// -// Call [Root] to obtain a valid cursor. -type Cursor struct { - in *inspector.Inspector - index int32 // index of push node; -1 for virtual root node -} - -// Root returns a cursor for the virtual root node, -// whose children are the files provided to [New]. -// -// Its [Cursor.Node] and [Cursor.Stack] methods return nil. -func Root(in *inspector.Inspector) Cursor { - return Cursor{in, -1} -} - -// At returns the cursor at the specified index in the traversal, -// which must have been obtained from [Cursor.Index] on a Cursor -// belonging to the same Inspector (see [Cursor.Inspector]). -func At(in *inspector.Inspector, index int32) Cursor { - if index < 0 { - panic("negative index") - } - events := events(in) - if int(index) >= len(events) { - panic("index out of range for this inspector") - } - if events[index].index < index { - panic("invalid index") // (a push, not a pop) - } - return Cursor{in, index} -} - -// Inspector returns the cursor's Inspector. -func (c Cursor) Inspector() *inspector.Inspector { return c.in } - -// Index returns the index of this cursor position within the package. -// -// Clients should not assume anything about the numeric Index value -// except that it increases monotonically throughout the traversal. -// It is provided for use with [At]. -// -// Index must not be called on the Root node. -func (c Cursor) Index() int32 { - if c.index < 0 { - panic("Index called on Root node") - } - return c.index -} - -// Node returns the node at the current cursor position, -// or nil for the cursor returned by [Inspector.Root]. -func (c Cursor) Node() ast.Node { - if c.index < 0 { - return nil - } - return c.events()[c.index].node -} - -// String returns information about the cursor's node, if any. -func (c Cursor) String() string { - if c.in == nil { - return "(invalid)" - } - if c.index < 0 { - return "(root)" - } - return reflect.TypeOf(c.Node()).String() -} - -// indices return the [start, end) half-open interval of event indices. -func (c Cursor) indices() (int32, int32) { - if c.index < 0 { - return 0, int32(len(c.events())) // root: all events - } else { - return c.index, c.events()[c.index].index + 1 // just one subtree - } -} - -// Preorder returns an iterator over the nodes of the subtree -// represented by c in depth-first order. Each node in the sequence is -// represented by a Cursor that allows access to the Node, but may -// also be used to start a new traversal, or to obtain the stack of -// nodes enclosing the cursor. -// -// The traversal sequence is determined by [ast.Inspect]. The types -// argument, if non-empty, enables type-based filtering of events. The -// function f if is called only for nodes whose type matches an -// element of the types slice. -// -// If you need control over descent into subtrees, -// or need both pre- and post-order notifications, use [Cursor.Inspect] -func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] { - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain types: skip. - i = pop + 1 - continue - } - } - i++ - } - } -} - -// Inspect visits the nodes of the subtree represented by c in -// depth-first order. It calls f(n) for each node n before it -// visits n's children. If f returns true, Inspect invokes f -// recursively for each of the non-nil children of the node. -// -// Each node is represented by a Cursor that allows access to the -// Node, but may also be used to start a new traversal, or to obtain -// the stack of nodes enclosing the cursor. -// -// The complete traversal sequence is determined by [ast.Inspect]. -// The types argument, if non-empty, enables type-based filtering of -// events. The function f if is called only for nodes whose type -// matches an element of the types slice. -func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) { - mask := maskOf(types) - events := c.events() - for i, limit := c.indices(); i < limit; { - ev := events[i] - if ev.index > i { - // push - pop := ev.index - if ev.typ&mask != 0 && !f(Cursor{c.in, i}) || - events[pop].typ&mask == 0 { - // The user opted not to descend, or the - // subtree does not contain types: - // skip past the pop. - i = pop + 1 - continue - } - } - i++ - } -} - -// Enclosing returns an iterator over the nodes enclosing the current -// current node, starting with the Cursor itself. -// -// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// The types argument, if non-empty, enables type-based filtering of -// events: the sequence includes only enclosing nodes whose type -// matches an element of the types slice. -func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] { - if c.index < 0 { - panic("Cursor.Enclosing called on Root node") - } - - mask := maskOf(types) - - return func(yield func(Cursor) bool) { - events := c.events() - for i := c.index; i >= 0; i = events[i].parent { - if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) { - break - } - } - } -} - -// Parent returns the parent of the current node. -// -// Parent must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Parent() Cursor { - if c.index < 0 { - panic("Cursor.Parent called on Root node") - } - - return Cursor{c.in, c.events()[c.index].parent} -} - -// ParentEdge returns the identity of the field in the parent node -// that holds this cursor's node, and if it is a list, the index within it. -// -// For example, f(x, y) is a CallExpr whose three children are Idents. -// f has edge kind [edge.CallExpr_Fun] and index -1. -// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively. -// -// If called on a child of the Root node, it returns ([edge.Invalid], -1). -// -// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) ParentEdge() (edge.Kind, int) { - if c.index < 0 { - panic("Cursor.ParentEdge called on Root node") - } - events := c.events() - pop := events[c.index].index - return unpackEdgeKindAndIndex(events[pop].parent) -} - -// ChildAt returns the cursor for the child of the -// current node identified by its edge and index. -// The index must be -1 if the edge.Kind is not a slice. -// The indicated child node must exist. -// -// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil). -// -// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c. -func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor { - target := packEdgeKindAndIndex(k, idx) - - // Unfortunately there's no shortcut to looping. - events := c.events() - i := c.index + 1 - for { - pop := events[i].index - if pop < i { - break - } - if events[pop].parent == target { - return Cursor{c.in, i} - } - i = pop + 1 - } - panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c)) -} - -// Child returns the cursor for n, which must be a direct child of c's Node. -// -// Child must not be called on the Root node (whose [Cursor.Node] returns nil). -func (c Cursor) Child(n ast.Node) Cursor { - if c.index < 0 { - panic("Cursor.Child called on Root node") - } - - if false { - // reference implementation - for child := range c.Children() { - if child.Node() == n { - return child - } - } - - } else { - // optimized implementation - events := c.events() - for i := c.index + 1; events[i].index > i; i = events[i].index + 1 { - if events[i].node == n { - return Cursor{c.in, i} - } - } - } - panic(fmt.Sprintf("Child(%T): not a child of %v", n, c)) -} - -// NextSibling returns the cursor for the next sibling node in the same list -// (for example, of files, decls, specs, statements, fields, or expressions) as -// the current node. It returns (zero, false) if the node is the last node in -// the list, or is not part of a list. -// -// NextSibling must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) NextSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.NextSibling called on Root node") - } - - events := c.events() - i := events[c.index].index + 1 // after corresponding pop - if i < int32(len(events)) { - if events[i].index > i { // push? - return Cursor{c.in, i}, true - } - } - return Cursor{}, false -} - -// PrevSibling returns the cursor for the previous sibling node in the -// same list (for example, of files, decls, specs, statements, fields, -// or expressions) as the current node. It returns zero if the node is -// the first node in the list, or is not part of a list. -// -// It must not be called on the Root node. -// -// See note at [Cursor.Children]. -func (c Cursor) PrevSibling() (Cursor, bool) { - if c.index < 0 { - panic("Cursor.PrevSibling called on Root node") - } - - events := c.events() - i := c.index - 1 - if i >= 0 { - if j := events[i].index; j < i { // pop? - return Cursor{c.in, j}, true - } - } - return Cursor{}, false -} - -// FirstChild returns the first direct child of the current node, -// or zero if it has no children. -func (c Cursor) FirstChild() (Cursor, bool) { - events := c.events() - i := c.index + 1 // i=0 if c is root - if i < int32(len(events)) && events[i].index > i { // push? - return Cursor{c.in, i}, true - } - return Cursor{}, false -} - -// LastChild returns the last direct child of the current node, -// or zero if it has no children. -func (c Cursor) LastChild() (Cursor, bool) { - events := c.events() - if c.index < 0 { // root? - if len(events) > 0 { - // return push of final event (a pop) - return Cursor{c.in, events[len(events)-1].index}, true - } - } else { - j := events[c.index].index - 1 // before corresponding pop - // Inv: j == c.index if c has no children - // or j is last child's pop. - if j > c.index { // c has children - return Cursor{c.in, events[j].index}, true - } - } - return Cursor{}, false -} - -// Children returns an iterator over the direct children of the -// current node, if any. -// -// When using Children, NextChild, and PrevChild, bear in mind that a -// Node's children may come from different fields, some of which may -// be lists of nodes without a distinguished intervening container -// such as [ast.BlockStmt]. -// -// For example, [ast.CaseClause] has a field List of expressions and a -// field Body of statements, so the children of a CaseClause are a mix -// of expressions and statements. Other nodes that have "uncontained" -// list fields include: -// -// - [ast.ValueSpec] (Names, Values) -// - [ast.CompositeLit] (Type, Elts) -// - [ast.IndexListExpr] (X, Indices) -// - [ast.CallExpr] (Fun, Args) -// - [ast.AssignStmt] (Lhs, Rhs) -// -// So, do not assume that the previous sibling of an ast.Stmt is also -// an ast.Stmt, or if it is, that they are executed sequentially, -// unless you have established that, say, its parent is a BlockStmt -// or its [Cursor.ParentEdge] is [edge.BlockStmt_List]. -// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1, -// even though they are not executed in sequence. -func (c Cursor) Children() iter.Seq[Cursor] { - return func(yield func(Cursor) bool) { - c, ok := c.FirstChild() - for ok && yield(c) { - c, ok = c.NextSibling() - } - } -} - -// Contains reports whether c contains or is equal to c2. -// -// Both Cursors must belong to the same [Inspector]; -// neither may be its Root node. -func (c Cursor) Contains(c2 Cursor) bool { - if c.in != c2.in { - panic("different inspectors") - } - events := c.events() - return c.index <= c2.index && events[c2.index].index <= events[c.index].index -} - -// FindNode returns the cursor for node n if it belongs to the subtree -// rooted at c. It returns zero if n is not found. -func (c Cursor) FindNode(n ast.Node) (Cursor, bool) { - - // FindNode is equivalent to this code, - // but more convenient and 15-20% faster: - if false { - for candidate := range c.Preorder(n) { - if candidate.Node() == n { - return candidate, true - } - } - return Cursor{}, false - } - - // TODO(adonovan): opt: should we assume Node.Pos is accurate - // and combine type-based filtering with position filtering - // like FindByPos? - - mask := maskOf([]ast.Node{n}) - events := c.events() - - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - if ev.typ&mask != 0 && ev.node == n { - return Cursor{c.in, i}, true - } - pop := ev.index - if events[pop].typ&mask == 0 { - // Subtree does not contain type of n: skip. - i = pop - } - } - } - return Cursor{}, false -} - -// FindByPos returns the cursor for the innermost node n in the tree -// rooted at c such that n.Pos() <= start && end <= n.End(). -// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.) -// -// It returns zero if none is found. -// Precondition: start <= end. -// -// See also [astutil.PathEnclosingInterval], which -// tolerates adjoining whitespace. -func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) { - if end < start { - panic("end < start") - } - events := c.events() - - // This algorithm could be implemented using c.Inspect, - // but it is about 2.5x slower. - - best := int32(-1) // push index of latest (=innermost) node containing range - for i, limit := c.indices(); i < limit; i++ { - ev := events[i] - if ev.index > i { // push? - n := ev.node - var nodeEnd token.Pos - if file, ok := n.(*ast.File); ok { - nodeEnd = file.FileEnd - // Note: files may be out of Pos order. - if file.FileStart > start { - i = ev.index // disjoint, after; skip to next file - continue - } - } else { - nodeEnd = n.End() - if n.Pos() > start { - break // disjoint, after; stop - } - } - // Inv: node.{Pos,FileStart} <= start - if end <= nodeEnd { - // node fully contains target range - best = i - } else if nodeEnd < start { - i = ev.index // disjoint, before; skip forward - } - } - } - if best >= 0 { - return Cursor{c.in, best}, true - } - return Cursor{}, false -} diff --git a/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go b/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go deleted file mode 100644 index 0257d61d..00000000 --- a/public-api/vendor/golang.org/x/tools/internal/astutil/cursor/hooks.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.23 - -package cursor - -import ( - "go/ast" - _ "unsafe" // for go:linkname - - "golang.org/x/tools/go/ast/inspector" - "golang.org/x/tools/internal/astutil/edge" -) - -// This file defines backdoor access to inspector. - -// Copied from inspector.event; must remain in sync. -// (Note that the linkname effects a type coercion too.) -type event struct { - node ast.Node - typ uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events - index int32 // index of corresponding push or pop event (relative to this event's index, +ve=push, -ve=pop) - parent int32 // index of parent's push node (push nodes only); or edge and index, bit packed (pop nodes only) -} - -//go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf -func maskOf(nodes []ast.Node) uint64 - -//go:linkname events golang.org/x/tools/go/ast/inspector.events -func events(in *inspector.Inspector) []event - -//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex -func packEdgeKindAndIndex(edge.Kind, int) int32 - -//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex -func unpackEdgeKindAndIndex(int32) (edge.Kind, int) - -func (c Cursor) events() []event { return events(c.in) } diff --git a/public-api/vendor/golang.org/x/tools/internal/astutil/util.go b/public-api/vendor/golang.org/x/tools/internal/astutil/util.go index 1862668a..f06dbda3 100644 --- a/public-api/vendor/golang.org/x/tools/internal/astutil/util.go +++ b/public-api/vendor/golang.org/x/tools/internal/astutil/util.go @@ -71,6 +71,8 @@ func PosInStringLiteral(lit *ast.BasicLit, offset int) (token.Pos, error) { // In practice, the second call is nearly always used only to pop the // stack, and it is surprisingly tricky to do this correctly; see // https://go.dev/issue/73319. +// +// TODO(adonovan): replace with [ast.PreorderStack] when go1.25 is assured. func PreorderStack(root ast.Node, stack []ast.Node, f func(n ast.Node, stack []ast.Node) bool) { before := len(stack) ast.Inspect(root, func(n ast.Node) bool { diff --git a/public-api/vendor/golang.org/x/tools/internal/imports/fix.go b/public-api/vendor/golang.org/x/tools/internal/imports/fix.go index 89b96381..50b6ca51 100644 --- a/public-api/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/public-api/vendor/golang.org/x/tools/internal/imports/fix.go @@ -27,12 +27,13 @@ import ( "unicode" "unicode/utf8" + "maps" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" "golang.org/x/tools/internal/stdlib" - "maps" ) // importToGroup is a list of functions which map from an import path to @@ -290,8 +291,8 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro return nil } -// if there is a trailing major version, remove it -func withoutVersion(nm string) string { +// WithoutVersion removes a trailing major version, if there is one. +func WithoutVersion(nm string) string { if v := path.Base(nm); len(v) > 0 && v[0] == 'v' { if _, err := strconv.Atoi(v[1:]); err == nil { // this is, for instance, called with rand/v2 and returns rand @@ -313,7 +314,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { } known := p.knownPackages[imp.ImportPath] if known != nil && known.Name != "" { - return withoutVersion(known.Name) + return WithoutVersion(known.Name) } return ImportPathToAssumedName(imp.ImportPath) } diff --git a/public-api/vendor/golang.org/x/tools/internal/imports/imports.go b/public-api/vendor/golang.org/x/tools/internal/imports/imports.go index 2215a128..b5f5218b 100644 --- a/public-api/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/public-api/vendor/golang.org/x/tools/internal/imports/imports.go @@ -93,7 +93,7 @@ func FixImports(ctx context.Context, filename string, src []byte, goroot string, // env is needed. func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) { // Don't use parse() -- we don't care about fragments or statement lists - // here, and we need to work with unparseable files. + // here, and we need to work with unparsable files. fileSet := token.NewFileSet() parserMode := parser.SkipObjectResolution if opt.Comments { diff --git a/public-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go b/public-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go index 05229f06..ca745d4a 100644 --- a/public-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go +++ b/public-api/vendor/golang.org/x/tools/internal/imports/source_modindex.go @@ -15,6 +15,10 @@ import ( // This code is here rather than in the modindex package // to avoid import loops +// TODO(adonovan): this code is only used by a test in this package. +// Can we delete it? Or is there a plan to call NewIndexSource from +// cmd/goimports? + // implements Source using modindex, so only for module cache. // // this is perhaps over-engineered. A new Index is read at first use. @@ -22,8 +26,8 @@ import ( // is read if the index changed. It is not clear the Mutex is needed. type IndexSource struct { modcachedir string - mutex sync.Mutex - ix *modindex.Index + mu sync.Mutex + index *modindex.Index // (access via getIndex) expires time.Time } @@ -39,13 +43,14 @@ func (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths } func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) { - if err := s.maybeReadIndex(); err != nil { + index, err := s.getIndex() + if err != nil { return nil, err } var cs []modindex.Candidate for pkg, nms := range missing { for nm := range nms { - x := s.ix.Lookup(pkg, nm, false) + x := index.Lookup(pkg, nm, false) cs = append(cs, x...) } } @@ -74,30 +79,22 @@ func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, mi return ans, nil } -func (s *IndexSource) maybeReadIndex() error { - s.mutex.Lock() - defer s.mutex.Unlock() - - var readIndex bool - if time.Now().After(s.expires) { - ok, err := modindex.Update(s.modcachedir) - if err != nil { - return err - } - if ok { - readIndex = true - } - } +func (s *IndexSource) getIndex() (*modindex.Index, error) { + s.mu.Lock() + defer s.mu.Unlock() - if readIndex || s.ix == nil { - ix, err := modindex.ReadIndex(s.modcachedir) + // (s.index = nil => s.expires is zero, + // so the first condition is strictly redundant. + // But it makes the postcondition very clear.) + if s.index == nil || time.Now().After(s.expires) { + index, err := modindex.Update(s.modcachedir) if err != nil { - return err + return nil, err } - s.ix = ix - // for now refresh every 15 minutes - s.expires = time.Now().Add(time.Minute * 15) + s.index = index + s.expires = index.ValidAt.Add(15 * time.Minute) // (refresh period) } + // Inv: s.index != nil - return nil + return s.index, nil } diff --git a/public-api/vendor/golang.org/x/tools/internal/modindex/directories.go b/public-api/vendor/golang.org/x/tools/internal/modindex/directories.go index 1e1a02f2..9a963744 100644 --- a/public-api/vendor/golang.org/x/tools/internal/modindex/directories.go +++ b/public-api/vendor/golang.org/x/tools/internal/modindex/directories.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "regexp" - "slices" "strings" "sync" "time" @@ -20,50 +19,48 @@ import ( ) type directory struct { - path Relpath + path string // relative to GOMODCACHE importPath string version string // semantic version - syms []symbol } -// filterDirs groups the directories by import path, -// sorting the ones with the same import path by semantic version, -// most recent first. -func byImportPath(dirs []Relpath) (map[string][]*directory, error) { - ans := make(map[string][]*directory) // key is import path - for _, d := range dirs { - ip, sv, err := DirToImportPathVersion(d) +// bestDirByImportPath returns the best directory for each import +// path, where "best" means most recent semantic version. These import +// paths are inferred from the GOMODCACHE-relative dir names in dirs. +func bestDirByImportPath(dirs []string) (map[string]directory, error) { + dirsByPath := make(map[string]directory) + for _, dir := range dirs { + importPath, version, err := dirToImportPathVersion(dir) if err != nil { return nil, err } - ans[ip] = append(ans[ip], &directory{ - path: d, - importPath: ip, - version: sv, - }) - } - for k, v := range ans { - semanticSort(v) - ans[k] = v + new := directory{ + path: dir, + importPath: importPath, + version: version, + } + if old, ok := dirsByPath[importPath]; !ok || compareDirectory(new, old) < 0 { + dirsByPath[importPath] = new + } } - return ans, nil + return dirsByPath, nil } -// sort the directories by semantic version, latest first -func semanticSort(v []*directory) { - slices.SortFunc(v, func(l, r *directory) int { - if n := semver.Compare(l.version, r.version); n != 0 { - return -n // latest first - } - return strings.Compare(string(l.path), string(r.path)) - }) +// compareDirectory defines an ordering of path@version directories, +// by descending version, then by ascending path. +func compareDirectory(x, y directory) int { + if sign := -semver.Compare(x.version, y.version); sign != 0 { + return sign // latest first + } + return strings.Compare(string(x.path), string(y.path)) } // modCacheRegexp splits a relpathpath into module, module version, and package. var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`) -// DirToImportPathVersion computes import path and semantic version -func DirToImportPathVersion(dir Relpath) (string, string, error) { +// dirToImportPathVersion computes import path and semantic version +// from a GOMODCACHE-relative directory name. +func dirToImportPathVersion(dir string) (string, string, error) { m := modCacheRegexp.FindStringSubmatch(string(dir)) // m[1] is the module path // m[2] is the version major.minor.patch(-

 that contains the name
+// Package modindex contains code for building and searching an
+// [Index] of the Go module cache.
+package modindex
+
+// The directory containing the index, returned by
+// [IndexDir], contains a file index-name- that contains the name
 // of the current index. We believe writing that short file is atomic.
-// ReadIndex reads that file to get the file name of the index.
+// [Read] reads that file to get the file name of the index.
 // WriteIndex writes an index with a unique name and then
 // writes that name into a new version of index-name-.
 // ( stands for the CurrentVersion of the index format.)
-package modindex
 
 import (
+	"maps"
+	"os"
 	"path/filepath"
 	"slices"
 	"strings"
@@ -21,144 +25,95 @@ import (
 	"golang.org/x/mod/semver"
 )
 
-// Create always creates a new index for the go module cache that is in cachedir.
-func Create(cachedir string) error {
-	_, err := indexModCache(cachedir, true)
-	return err
-}
-
-// Update the index for the go module cache that is in cachedir,
-// If there is no existing index it will build one.
-// If there are changed directories since the last index, it will
-// write a new one and return true. Otherwise it returns false.
-func Update(cachedir string) (bool, error) {
-	return indexModCache(cachedir, false)
+// Update updates the index for the specified Go
+// module cache directory, creating it as needed.
+// On success it returns the current index.
+func Update(gomodcache string) (*Index, error) {
+	prev, err := Read(gomodcache)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return nil, err
+		}
+		prev = nil
+	}
+	return update(gomodcache, prev)
 }
 
-// indexModCache writes an index current as of when it is called.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and the updates to the cache. It returns true if it wrote an index,
-// false otherwise.
-func indexModCache(cachedir string, clear bool) (bool, error) {
-	cachedir, err := filepath.Abs(cachedir)
+// update builds, writes, and returns the current index.
+//
+// If old is nil, the new index is built from all of GOMODCACHE;
+// otherwise it is built from the old index plus cache updates
+// since the previous index's time.
+func update(gomodcache string, old *Index) (*Index, error) {
+	gomodcache, err := filepath.Abs(gomodcache)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	cd := Abspath(cachedir)
-	future := time.Now().Add(24 * time.Hour) // safely in the future
-	ok, err := modindexTimed(future, cd, clear)
+	new, changed, err := build(gomodcache, old)
 	if err != nil {
-		return false, err
+		return nil, err
 	}
-	return ok, nil
-}
-
-// modindexTimed writes an index current as of onlyBefore.
-// If clear is true the index is constructed from all of GOMODCACHE
-// otherwise the index is constructed from the last previous index
-// and all the updates to the cache before onlyBefore.
-// It returns true if it wrote a new index, false if it wrote nothing.
-func modindexTimed(onlyBefore time.Time, cachedir Abspath, clear bool) (bool, error) {
-	var curIndex *Index
-	if !clear {
-		var err error
-		curIndex, err = ReadIndex(string(cachedir))
-		if clear && err != nil {
-			return false, err
+	if old == nil || changed {
+		if err := write(gomodcache, new); err != nil {
+			return nil, err
 		}
-		// TODO(pjw): check that most of those directories still exist
-	}
-	cfg := &work{
-		onlyBefore: onlyBefore,
-		oldIndex:   curIndex,
-		cacheDir:   cachedir,
-	}
-	if curIndex != nil {
-		cfg.onlyAfter = curIndex.Changed
-	}
-	if err := cfg.buildIndex(); err != nil {
-		return false, err
 	}
-	if len(cfg.newIndex.Entries) == 0 && curIndex != nil {
-		// no changes from existing curIndex, don't write a new index
-		return false, nil
-	}
-	if err := cfg.writeIndex(); err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-type work struct {
-	onlyBefore time.Time // do not use directories later than this
-	onlyAfter  time.Time // only interested in directories after this
-	// directories from before onlyAfter come from oldIndex
-	oldIndex *Index
-	newIndex *Index
-	cacheDir Abspath
+	return new, nil
 }
 
-func (w *work) buildIndex() error {
-	// The effective date of the new index should be at least
-	// slightly earlier than when the directories are scanned
-	// so set it now.
-	w.newIndex = &Index{Changed: time.Now(), Cachedir: w.cacheDir}
-	dirs := findDirs(string(w.cacheDir), w.onlyAfter, w.onlyBefore)
-	if len(dirs) == 0 {
-		return nil
+// build returns a new index for the specified Go module cache (an
+// absolute path).
+//
+// If an old index is provided, only directories more recent than it
+// that it are scanned; older directories are provided by the old
+// Index.
+//
+// The boolean result indicates whether new entries were found.
+func build(gomodcache string, old *Index) (*Index, bool, error) {
+	// Set the time window.
+	var start time.Time // = dawn of time
+	if old != nil {
+		start = old.ValidAt
 	}
-	newdirs, err := byImportPath(dirs)
+	now := time.Now()
+	end := now.Add(24 * time.Hour) // safely in the future
+
+	// Enumerate GOMODCACHE package directories.
+	// Choose the best (latest) package for each import path.
+	pkgDirs := findDirs(gomodcache, start, end)
+	dirByPath, err := bestDirByImportPath(pkgDirs)
 	if err != nil {
-		return err
+		return nil, false, err
 	}
-	// for each import path it might occur only in newdirs,
-	// only in w.oldIndex, or in both.
-	// If it occurs in both, use the semantically later one
-	if w.oldIndex != nil {
-		for _, e := range w.oldIndex.Entries {
-			found, ok := newdirs[e.ImportPath]
-			if !ok {
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				continue // use this one, there is no new one
-			}
-			if semver.Compare(found[0].version, e.Version) > 0 {
-				// use the new one
-			} else {
-				// use the old one, forget the new one
-				w.newIndex.Entries = append(w.newIndex.Entries, e)
-				delete(newdirs, e.ImportPath)
+
+	// For each import path it might occur only in
+	// dirByPath, only in old, or in both.
+	// If both, use the semantically later one.
+	var entries []Entry
+	if old != nil {
+		for _, entry := range old.Entries {
+			dir, ok := dirByPath[entry.ImportPath]
+			if !ok || semver.Compare(dir.version, entry.Version) <= 0 {
+				// New dir is missing or not more recent; use old entry.
+				entries = append(entries, entry)
+				delete(dirByPath, entry.ImportPath)
 			}
 		}
 	}
-	// get symbol information for all the new diredtories
-	getSymbols(w.cacheDir, newdirs)
-	// assemble the new index entries
-	for k, v := range newdirs {
-		d := v[0]
-		pkg, names := processSyms(d.syms)
-		if pkg == "" {
-			continue // PJW: does this ever happen?
-		}
-		entry := Entry{
-			PkgName:    pkg,
-			Dir:        d.path,
-			ImportPath: k,
-			Version:    d.version,
-			Names:      names,
-		}
-		w.newIndex.Entries = append(w.newIndex.Entries, entry)
-	}
-	// sort the entries in the new index
-	slices.SortFunc(w.newIndex.Entries, func(l, r Entry) int {
-		if n := strings.Compare(l.PkgName, r.PkgName); n != 0 {
+
+	// Extract symbol information for all the new directories.
+	newEntries := extractSymbols(gomodcache, maps.Values(dirByPath))
+	entries = append(entries, newEntries...)
+	slices.SortFunc(entries, func(x, y Entry) int {
+		if n := strings.Compare(x.PkgName, y.PkgName); n != 0 {
 			return n
 		}
-		return strings.Compare(l.ImportPath, r.ImportPath)
+		return strings.Compare(x.ImportPath, y.ImportPath)
 	})
-	return nil
-}
 
-func (w *work) writeIndex() error {
-	return writeIndex(w.cacheDir, w.newIndex)
+	return &Index{
+		GOMODCACHE: gomodcache,
+		ValidAt:    now, // time before the directories were scanned
+		Entries:    entries,
+	}, len(newEntries) > 0, nil
 }
diff --git a/public-api/vendor/golang.org/x/tools/internal/modindex/symbols.go b/public-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
index b918529d..fe24db9b 100644
--- a/public-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
+++ b/public-api/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -10,11 +10,13 @@ import (
 	"go/parser"
 	"go/token"
 	"go/types"
+	"iter"
 	"os"
 	"path/filepath"
 	"runtime"
 	"slices"
 	"strings"
+	"sync"
 
 	"golang.org/x/sync/errgroup"
 )
@@ -30,45 +32,69 @@ import (
 type symbol struct {
 	pkg  string // name of the symbols's package
 	name string // declared name
-	kind string // T, C, V, or F, follwed by D if deprecated
+	kind string // T, C, V, or F, followed by D if deprecated
 	sig  string // signature information, for F
 }
 
-// find the symbols for the best directories
-func getSymbols(cd Abspath, dirs map[string][]*directory) {
+// extractSymbols returns a (new, unordered) array of Entries, one for
+// each provided package directory, describing its exported symbols.
+func extractSymbols(cwd string, dirs iter.Seq[directory]) []Entry {
+	var (
+		mu      sync.Mutex
+		entries []Entry
+	)
+
 	var g errgroup.Group
 	g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
-	for _, vv := range dirs {
-		// throttling some day?
-		d := vv[0]
+	for dir := range dirs {
 		g.Go(func() error {
-			thedir := filepath.Join(string(cd), string(d.path))
+			thedir := filepath.Join(cwd, string(dir.path))
 			mode := parser.SkipObjectResolution | parser.ParseComments
 
-			fi, err := os.ReadDir(thedir)
+			// Parse all Go files in dir and extract symbols.
+			dirents, err := os.ReadDir(thedir)
 			if err != nil {
 				return nil // log this someday?
 			}
-			for _, fx := range fi {
-				if !strings.HasSuffix(fx.Name(), ".go") || strings.HasSuffix(fx.Name(), "_test.go") {
+			var syms []symbol
+			for _, dirent := range dirents {
+				if !strings.HasSuffix(dirent.Name(), ".go") ||
+					strings.HasSuffix(dirent.Name(), "_test.go") {
 					continue
 				}
-				fname := filepath.Join(thedir, fx.Name())
+				fname := filepath.Join(thedir, dirent.Name())
 				tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
 				if err != nil {
 					continue // ignore errors, someday log them?
 				}
-				d.syms = append(d.syms, getFileExports(tr)...)
+				syms = append(syms, getFileExports(tr)...)
+			}
+
+			// Create an entry for the package.
+			pkg, names := processSyms(syms)
+			if pkg != "" {
+				mu.Lock()
+				defer mu.Unlock()
+				entries = append(entries, Entry{
+					PkgName:    pkg,
+					Dir:        dir.path,
+					ImportPath: dir.importPath,
+					Version:    dir.version,
+					Names:      names,
+				})
 			}
+
 			return nil
 		})
 	}
-	g.Wait()
+	g.Wait() // ignore error
+
+	return entries
 }
 
 func getFileExports(f *ast.File) []symbol {
 	pkg := f.Name.Name
-	if pkg == "main" {
+	if pkg == "main" || pkg == "" {
 		return nil
 	}
 	var ans []symbol
@@ -110,7 +136,7 @@ func getFileExports(f *ast.File) []symbol {
 				// The only place a $ can occur seems to be in a struct tag, which
 				// can be an arbitrary string literal, and ExprString does not presently
 				// print struct tags. So for this to happen the type of a formal parameter
-				// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
+				// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
 				// would have to show the struct tag. Even testing for this case seems
 				// a waste of effort, but let's remember the possibility
 				if strings.Contains(tp, "$") {
@@ -202,17 +228,18 @@ func processSyms(syms []symbol) (string, []string) {
 	pkg := syms[0].pkg
 	var names []string
 	for _, s := range syms {
+		if s.pkg != pkg {
+			// Symbols came from two files in same dir
+			// with different package declarations.
+			continue
+		}
 		var nx string
-		if s.pkg == pkg {
-			if s.sig != "" {
-				nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
-			} else {
-				nx = fmt.Sprintf("%s %s", s.name, s.kind)
-			}
-			names = append(names, nx)
+		if s.sig != "" {
+			nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
 		} else {
-			continue // PJW: do we want to keep track of these?
+			nx = fmt.Sprintf("%s %s", s.name, s.kind)
 		}
+		names = append(names, nx)
 	}
 	return pkg, names
 }
diff --git a/public-api/vendor/golang.org/x/tools/internal/modindex/types.go b/public-api/vendor/golang.org/x/tools/internal/modindex/types.go
deleted file mode 100644
index ece44886..00000000
--- a/public-api/vendor/golang.org/x/tools/internal/modindex/types.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modindex
-
-import (
-	"strings"
-)
-
-// some special types to avoid confusions
-
-// distinguish various types of directory names. It's easy to get confused.
-type Abspath string // absolute paths
-type Relpath string // paths with GOMODCACHE prefix removed
-
-func toRelpath(cachedir Abspath, s string) Relpath {
-	if strings.HasPrefix(s, string(cachedir)) {
-		if s == string(cachedir) {
-			return Relpath("")
-		}
-		return Relpath(s[len(cachedir)+1:])
-	}
-	return Relpath(s)
-}
diff --git a/public-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/public-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 73eefa2a..929b470b 100644
--- a/public-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/public-api/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -5,6 +5,8 @@
 // Package packagesinternal exposes internal-only fields from go/packages.
 package packagesinternal
 
+import "fmt"
+
 var GetDepsErrors = func(p any) []*PackageError { return nil }
 
 type PackageError struct {
@@ -13,5 +15,9 @@ type PackageError struct {
 	Err         string   // the error itself
 }
 
+func (err PackageError) String() string {
+	return fmt.Sprintf("%s: %s (import stack: %s)", err.Pos, err.Err, err.ImportStack)
+}
+
 var TypecheckCgo int
 var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
diff --git a/public-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go b/public-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
index 649c82b6..3db2a135 100644
--- a/public-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
+++ b/public-api/vendor/golang.org/x/tools/internal/typesinternal/classify_call.go
@@ -65,14 +65,16 @@ func ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {
 	if info.Types == nil {
 		panic("ClassifyCall: info.Types is nil")
 	}
-	if info.Types[call.Fun].IsType() {
+	tv := info.Types[call.Fun]
+	if tv.IsType() {
 		return CallConversion
 	}
+	if tv.IsBuiltin() {
+		return CallBuiltin
+	}
 	obj := info.Uses[UsedIdent(info, call.Fun)]
 	// Classify the call by the type of the object, if any.
 	switch obj := obj.(type) {
-	case *types.Builtin:
-		return CallBuiltin
 	case *types.Func:
 		if interfaceMethod(obj) {
 			return CallInterface
diff --git a/public-api/vendor/golang.org/x/tools/internal/typesinternal/types.go b/public-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
index cc244689..a5cd7e8d 100644
--- a/public-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/public-api/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -69,6 +69,34 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 	}
 }
 
+// TypeNameFor returns the type name symbol for the specified type, if
+// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a
+// [*types.Basic] representing a type.
+//
+// For all other types, and for Basic types representing a builtin,
+// constant, or nil, it returns nil. Be careful not to convert the
+// resulting nil pointer to a [types.Object]!
+//
+// If t is the type of a constant, it may be an "untyped" type, which
+// has no TypeName. To access the name of such types (e.g. "untyped
+// int"), use [types.Basic.Name].
+func TypeNameFor(t types.Type) *types.TypeName {
+	switch t := t.(type) {
+	case *types.Alias:
+		return t.Obj()
+	case *types.Named:
+		return t.Obj()
+	case *types.TypeParam:
+		return t.Obj()
+	case *types.Basic:
+		// See issues #71886 and #66890 for some history.
+		if tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {
+			return tname
+		}
+	}
+	return nil
+}
+
 // A NamedOrAlias is a [types.Type] that is named (as
 // defined by the spec) and capable of bearing type parameters: it
 // abstracts aliases ([types.Alias]) and defined types
@@ -77,7 +105,7 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 // Every type declared by an explicit "type" declaration is a
 // NamedOrAlias. (Built-in type symbols may additionally
 // have type [types.Basic], which is not a NamedOrAlias,
-// though the spec regards them as "named".)
+// though the spec regards them as "named"; see [TypeNameFor].)
 //
 // NamedOrAlias cannot expose the Origin method, because
 // [types.Alias.Origin] and [types.Named.Origin] have different
@@ -85,32 +113,15 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 type NamedOrAlias interface {
 	types.Type
 	Obj() *types.TypeName
-	// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
-}
-
-// TypeParams is a light shim around t.TypeParams().
-// (go/types.Alias).TypeParams requires >= 1.23.
-func TypeParams(t NamedOrAlias) *types.TypeParamList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeParams(t)
-	case *types.Named:
-		return t.TypeParams()
-	}
-	return nil
+	TypeArgs() *types.TypeList
+	TypeParams() *types.TypeParamList
+	SetTypeParams(tparams []*types.TypeParam)
 }
 
-// TypeArgs is a light shim around t.TypeArgs().
-// (go/types.Alias).TypeArgs requires >= 1.23.
-func TypeArgs(t NamedOrAlias) *types.TypeList {
-	switch t := t.(type) {
-	case *types.Alias:
-		return aliases.TypeArgs(t)
-	case *types.Named:
-		return t.TypeArgs()
-	}
-	return nil
-}
+var (
+	_ NamedOrAlias = (*types.Alias)(nil)
+	_ NamedOrAlias = (*types.Named)(nil)
+)
 
 // Origin returns the generic type of the Named or Alias type t if it
 // is instantiated, otherwise it returns t.
diff --git a/public-api/vendor/golang.org/x/vuln/LICENSE b/public-api/vendor/golang.org/x/vuln/LICENSE
index 6a66aea5..2a7cf70d 100644
--- a/public-api/vendor/golang.org/x/vuln/LICENSE
+++ b/public-api/vendor/golang.org/x/vuln/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
+Copyright 2009 The Go Authors.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
-   * Neither the name of Google Inc. nor the names of its
+   * Neither the name of Google LLC nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.
 
diff --git a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
index b7b16d9f..8de6904a 100644
--- a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
+++ b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/doc.go
@@ -9,10 +9,10 @@ only those that could affect the application.
 
 By default, govulncheck makes requests to the Go vulnerability database at
 https://vuln.go.dev. Requests to the vulnerability database contain only module
-paths, not code or other properties of your program. See
-https://vuln.go.dev/privacy.html for more. Use the -db flag to specify a
-different database, which must implement the specification at
-https://go.dev/security/vuln/database.
+paths with vulnerabilities already known to the database, not code or other
+properties of your program. See https://vuln.go.dev/privacy.html for more.
+Use the -db flag to specify a different database, which must implement the
+specification at https://go.dev/security/vuln/database.
 
 Govulncheck looks for vulnerabilities in Go programs using a specific build
 configuration. For analyzing source code, that configuration is the Go version
@@ -20,8 +20,6 @@ specified by the “go” command found on the PATH. For binaries, the build
 configuration is the one used to build the binary. Note that different build
 configurations may have different known vulnerabilities.
 
-Govulncheck must be built with Go version 1.18 or later.
-
 # Usage
 
 To analyze source code, run govulncheck from the module directory, using the
@@ -41,44 +39,45 @@ To control which files are processed, use the -tags flag to provide a
 comma-separated list of build tags, and the -test flag to indicate that test
 files should be included.
 
-To run govulncheck on a compiled binary, pass it the path to the binary file
-with the -mode=binary flag:
-
-	$ govulncheck -mode=binary $HOME/go/bin/my-go-program
+To include more detailed stack traces, pass '-show traces', this will cause it to
+print the full call stack for each entry.
 
-Govulncheck uses the binary's symbol information to find mentions of vulnerable
-functions. Its output omits call stacks, which require source code analysis.
+To include progress messages and more details on findings, pass '-show verbose'.
 
-Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
-and exits unsuccessfully if there are. It also exits successfully if -json flag
-is provided, regardless of the number of detected vulnerabilities.
+To run govulncheck on a compiled binary, pass it the path to the binary file
+with the '-mode binary' flag:
 
-# Flags
+	$ govulncheck -mode binary $HOME/go/bin/my-go-program
 
-A few flags control govulncheck's behavior.
+Govulncheck uses the binary's symbol information to find mentions of vulnerable
+functions. These functions can belong to binary's transitive dependencies and
+also the main module of the binary. The latter functions are checked for only
+when the precise version of the binary module is known. Govulncheck output on
+binaries omits call stacks, which require source code analysis.
 
-The -C flag causes govulncheck to change its working directory to the provided
-directory before running. Any patterns or files named on the command line are
-interpreted after changing directories.
+Govulncheck also supports '-mode extract' on a Go binary for extraction of minimal
+information needed to analyze the binary. This will produce a blob, typically much
+smaller than the binary, that can also be passed to govulncheck as an argument with
+'-mode binary'. The users should not rely on the contents or representation of the blob.
 
-The -db flag causes govulncheck to read from the specified database, which must
-implement the specification at https://go.dev/security/vuln/database. By
-default, govulncheck fetches vulnerability data from https://vuln.go.dev.
+# Integrations
 
-The -json flag causes govulncheck to print its output as a JSON object
-corresponding to the type [golang.org/x/vuln/internal/govulncheck.Result]. The
-exit code of govulncheck is 0 when this flag is provided.
+Govulncheck supports streaming JSON. For more details, please see [golang.org/x/vuln/internal/govulncheck].
 
-The -mode flag causes govulncheck to run source or binary analysis. By default,
-govulnchecks runs source analysis.
+Govulncheck also supports Static Analysis Results Interchange Format (SARIF) output
+format, following the specification at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+For more details, please see [golang.org/x/vuln/internal/sarif].
 
-The -tags flag accepts a comma-separated list of build tags to control which
-files should be included in loaded packages for source analysis.
+Govulncheck supports the Vulnerability EXchange (VEX) output format, following
+the specification at https://github.com/openvex/spec.
+For more details, please see [golang.org/x/vuln/internal/openvex].
 
-The -test flag causes govulncheck to include test files in the source analysis.
+# Exit codes
 
-The -v flag causes govulncheck to output more information when run on source.
-It has no effect when run on a binary.
+Govulncheck exits successfully (exit code 0) if there are no vulnerabilities,
+and exits unsuccessfully if there are. It also exits successfully if the
+'format -json' ('-json'), '-format sarif', or '-format openvex' is provided,
+regardless of the number of detected vulnerabilities.
 
 # Limitations
 
@@ -88,22 +87,20 @@ Govulncheck has these limitations:
     which may result in false positives or inaccurate call stacks in some cases.
   - Calls to functions made using package reflect are not visible to static
     analysis. Vulnerable code reachable only through those calls will not be
-    reported.
+    reported in source scan mode. Similarly, use of the unsafe package may
+    result in false negatives.
   - Because Go binaries do not contain detailed call information, govulncheck
     cannot show the call graphs for detected vulnerabilities. It may also
     report false positives for code that is in the binary but unreachable.
-  - There is no support for silencing vulnerability findings.
-  - Govulncheck only reads binaries compiled with Go 1.18 and later.
-  - Govulncheck only reports vulnerabilities that apply to the current Go
-    version. For example, a standard library vulnerability that only applies for
-    Go 1.18 will not be reported if the current Go version is 1.19. See
-    https://go.dev/issue/54841 for updates to this limitation.
+  - There is no support for silencing vulnerability findings. See https://go.dev/issue/61211 for
+    updates.
+  - Govulncheck reports only standard library vulnerabilities for binaries
+    built with Go versions prior to Go 1.18.
   - For binaries where the symbol information cannot be extracted, govulncheck
     reports vulnerabilities for all modules on which the binary depends.
 
 # Feedback
 
-Govulncheck is an experimental tool under active development. To share
-feedback, see https://go.dev/security/vuln#feedback.
+To share feedback, see https://go.dev/security/vuln#feedback.
 */
 package main
diff --git a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
new file mode 100644
index 00000000..288c10c2
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/gotypesalias.go
@@ -0,0 +1,12 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.23
+
+//go:debug gotypesalias=1
+
+package main
+
+// Materialize aliases whenever the go toolchain version is after 1.23 (#69772).
+// Remove this file after go.mod >= 1.23 (which implies gotypesalias=1).
diff --git a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
index f6ca253f..73e3370a 100644
--- a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
+++ b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/main.go
@@ -9,10 +9,13 @@ import (
 	"fmt"
 	"os"
 
+	"golang.org/x/telemetry"
 	"golang.org/x/vuln/scan"
 )
 
 func main() {
+	telemetry.Start(telemetry.Config{ReportCrashes: true})
+
 	ctx := context.Background()
 
 	cmd := scan.Command(ctx, os.Args[1:]...)
diff --git a/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
new file mode 100644
index 00000000..826d6caf
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/cmd/govulncheck/test_utils.go
@@ -0,0 +1,128 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"testing"
+)
+
+// copyTestCase copies the test case at dir into a
+// temporary directory. The created files have 0644
+// permission and directories 0755. It does not create
+// symlinks.
+func copyTestCase(dir string, t *testing.T) string {
+	newDir, err := filepath.Abs(t.TempDir())
+	if err != nil {
+		t.Fatalf("failed to copy test case %s: cannot create root %v", dir, err)
+	}
+
+	if err := copyDir(dir, newDir); err != nil {
+		t.Fatalf("failed to copy test case %s: copy failure %v", dir, err)
+	}
+	return newDir
+}
+
+func copyDir(srcDir, destDir string) error {
+	entries, err := os.ReadDir(srcDir)
+	if err != nil {
+		return err
+	}
+	for _, entry := range entries {
+		src := filepath.Join(srcDir, entry.Name())
+		dest := filepath.Join(destDir, entry.Name())
+
+		fileInfo, err := os.Stat(src)
+		if err != nil {
+			return err
+		}
+
+		switch fileInfo.Mode() & os.ModeType {
+		case os.ModeDir:
+			if err := os.MkdirAll(dest, 0755); err != nil {
+				return err
+			}
+			if err := copyDir(src, dest); err != nil {
+				return err
+			}
+		default:
+			if err := copyFile(src, dest); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func copyFile(src, dest string) error {
+	b, err := os.ReadFile(src)
+	if err != nil {
+		return err
+	}
+	return os.WriteFile(dest, b, 0644)
+}
+
+type config struct {
+	// SkipGOOS is a list of GOOS to skip
+	SkipGOOS []string `json:"skipGOOS,omitempty"`
+	// Copy the folder to isolate it
+	Copy bool `json:"copy,omitempty"`
+	// SkipBuild the test case
+	SkipBuild bool `json:"skipBuild,omitempty"`
+	// Strip indicates if binaries should be stripped
+	Strip bool `json:"strip,omitempty"`
+	// EnableSBOM indicates if sbom should be
+	// printed in JSON.
+	EnableSBOM bool `json:"sbom,omitempty"`
+
+	Fixups []fixup `json:"fixups,omitempty"`
+}
+
+func (c *config) skip() bool {
+	for _, sg := range c.SkipGOOS {
+		if runtime.GOOS == sg {
+			return true
+		}
+	}
+	return false
+}
+
+type fixup struct {
+	Pattern     string `json:"pattern,omitempty"`
+	Replace     string `json:"replace,omitempty"`
+	compiled    *regexp.Regexp
+	replaceFunc func(b []byte) []byte
+}
+
+func (f *fixup) init() {
+	f.compiled = regexp.MustCompile(f.Pattern)
+}
+
+func (f *fixup) apply(data []byte) []byte {
+	if f.replaceFunc != nil {
+		return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
+	}
+	return f.compiled.ReplaceAll(data, []byte(f.Replace))
+}
+
+// loadConfig loads and initializes the config from path.
+func loadConfig(path string) (*config, error) {
+	b, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	var cfg config
+	if err := json.Unmarshal(b, &cfg); err != nil {
+		return nil, err
+	}
+	for i := range cfg.Fixups {
+		cfg.Fixups[i].init()
+	}
+	return &cfg, nil
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/README.md
similarity index 100%
rename from public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/README.md
rename to public-api/vendor/golang.org/x/vuln/internal/buildinfo/README.md
diff --git a/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
new file mode 100644
index 00000000..49869ce3
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_buildinfo.go
@@ -0,0 +1,257 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// This file adds to buildinfo the functionality for extracting the PCLN table.
+
+import (
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// ErrNoSymbols represents non-existence of symbol
+// table in binaries supported by buildinfo.
+var ErrNoSymbols = errors.New("no symbol section")
+
+// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
+func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil || sym == nil {
+		if errors.Is(err, elf.ErrNoSymbols) {
+			return 0, 0, nil, ErrNoSymbols
+		}
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	prog := x.progContaining(sym.Value)
+	if prog == nil {
+		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
+}
+
+func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		syms, err := x.f.Symbols()
+		if err != nil {
+			x.symbolsErr = err
+			return
+		}
+		x.symbols = make(map[string]*elf.Symbol, len(syms))
+		for _, s := range syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *elfExe) progContaining(addr uint64) *elf.Prog {
+	for _, p := range x.f.Progs {
+		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
+			return p
+		}
+	}
+	return nil
+}
+
+const go12magic = 0xfffffffb
+const go116magic = 0xfffffffa
+
+// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
+func (x *elfExe) PCLNTab() ([]byte, uint64) {
+	var offset uint64
+	text := x.f.Section(".text")
+	if text != nil {
+		offset = text.Offset
+	}
+	pclntab := x.f.Section(".gopclntab")
+	if pclntab == nil {
+		// Addition: this code is added to support some form of stripping.
+		pclntab = x.f.Section(".data.rel.ro.gopclntab")
+		if pclntab == nil {
+			pclntab = x.f.Section(".data.rel.ro")
+			if pclntab == nil {
+				return nil, 0
+			}
+			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
+			// its own section header. We can search for for the start by looking for the four
+			// byte magic and the go magic.
+			b, err := pclntab.Data()
+			if err != nil {
+				return nil, 0
+			}
+			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
+			// actually correct. During testing it worked, but that may be because I got lucky
+			// with the binary I was using, and we need to do four byte jumps to exhaustively
+			// search the section?
+			for i := 0; i < len(b); i += 16 {
+				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
+					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
+					(b[i+7] == 4 || b[i+7] == 8) {
+					// Also check for the go magic
+					leMagic := binary.LittleEndian.Uint32(b[i:])
+					beMagic := binary.BigEndian.Uint32(b[i:])
+					switch {
+					case leMagic == go12magic:
+						fallthrough
+					case beMagic == go12magic:
+						fallthrough
+					case leMagic == go116magic:
+						fallthrough
+					case beMagic == go116magic:
+						return b[i:], offset
+					}
+				}
+			}
+		}
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, offset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
+func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	sect := x.f.Sections[sym.SectionNumber-1]
+	// In PE, the symbol's value is the offset from the section start.
+	return uint64(sym.Value), 0, sect.ReaderAt, nil
+}
+
+func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
+		if len(x.f.Symbols) == 0 {
+			x.symbolsErr = ErrNoSymbols
+			return
+		}
+		for _, s := range x.f.Symbols {
+			x.symbols[s.Name] = s
+		}
+	})
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
+// Assumes that the underlying symbol table exists, otherwise
+// it might panic.
+func (x *peExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	for _, section := range x.f.Sections {
+		if section.Name == ".text" {
+			textOffset = uint64(section.Offset)
+			break
+		}
+	}
+
+	var start, end int64
+	var section int
+	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
+		start = int64(s.Value)
+		section = int(s.SectionNumber - 1)
+	}
+	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
+		end = int64(s.Value)
+	}
+	if start == 0 || end == 0 {
+		return nil, 0
+	}
+	offset := int64(x.f.Sections[section].Offset) + start
+	size := end - start
+
+	pclntab := make([]byte, size)
+	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
+		return nil, 0
+	}
+	return pclntab, textOffset
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
+func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
+	sym, err := x.lookupSymbol(name)
+	if err != nil {
+		return 0, 0, nil, err
+	}
+	if sym == nil {
+		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
+	}
+	seg := x.segmentContaining(sym.Value)
+	if seg == nil {
+		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
+	}
+	return sym.Value, seg.Addr, seg.ReaderAt, nil
+}
+
+func (x *machoExe) lookupSymbol(name string) (*macho.Symbol, error) {
+	const mustExistSymbol = "runtime.main"
+	x.symbolsOnce.Do(func() {
+		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
+		for _, s := range x.f.Symtab.Syms {
+			s := s // make a copy to prevent aliasing
+			x.symbols[s.Name] = &s
+		}
+		// In the presence of stripping, the symbol table for darwin
+		// binaries will not be empty, but the program symbols will
+		// be missing.
+		if _, ok := x.symbols[mustExistSymbol]; !ok {
+			x.symbolsErr = ErrNoSymbols
+		}
+	})
+
+	if x.symbolsErr != nil {
+		return nil, x.symbolsErr
+	}
+	return x.symbols[name], nil
+}
+
+func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
+			return seg
+		}
+	}
+	return nil
+}
+
+// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
+func (x *machoExe) PCLNTab() ([]byte, uint64) {
+	var textOffset uint64
+	text := x.f.Section("__text")
+	if text != nil {
+		textOffset = uint64(text.Offset)
+	}
+	pclntab := x.f.Section("__gopclntab")
+	if pclntab == nil {
+		return nil, 0
+	}
+	b, err := pclntab.Data()
+	if err != nil {
+		return nil, 0
+	}
+	return b, textOffset
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
new file mode 100644
index 00000000..ddbdea08
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/additions_scan.go
@@ -0,0 +1,160 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Code in this package is dervied from src/cmd/go/internal/version/version.go
+// and cmd/go/internal/version/exe.go.
+
+import (
+	"debug/buildinfo"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"runtime/debug"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/gosym"
+	"golang.org/x/vuln/internal/goversion"
+)
+
+func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
+	packagesModules := make([]*packages.Module, len(debugModules))
+	for i, mod := range debugModules {
+		packagesModules[i] = &packages.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+		if mod.Replace != nil {
+			packagesModules[i].Replace = &packages.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+	}
+	return packagesModules
+}
+
+type Symbol struct {
+	Pkg  string `json:"pkg,omitempty"`
+	Name string `json:"name,omitempty"`
+}
+
+// ExtractPackagesAndSymbols extracts symbols, packages, modules from
+// Go binary file as well as bin's metadata.
+//
+// If the symbol table is not available, such as in the case of stripped
+// binaries, returns module and binary info but without the symbol info.
+func ExtractPackagesAndSymbols(file string) ([]*packages.Module, []Symbol, *debug.BuildInfo, error) {
+	bin, err := os.Open(file)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+	defer bin.Close()
+
+	bi, err := buildinfo.Read(bin)
+	if err != nil {
+		// It could be that bin is an ancient Go binary.
+		v, err := goversion.ReadExe(file)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		bi := &debug.BuildInfo{
+			GoVersion: v.Release,
+			Main:      debug.Module{Path: v.ModuleInfo},
+		}
+		// We cannot analyze symbol tables of ancient binaries.
+		return nil, nil, bi, nil
+	}
+
+	funcSymName := gosym.FuncSymName(bi.GoVersion)
+	if funcSymName == "" {
+		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
+	}
+
+	x, err := openExe(bin)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	value, base, r, err := x.SymbolInfo(funcSymName)
+	if err != nil {
+		if errors.Is(err, ErrNoSymbols) {
+			// bin is stripped, so return just module info and metadata.
+			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+		}
+		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
+	}
+
+	pclntab, textOffset := x.PCLNTab()
+	if pclntab == nil {
+		// If we have build information, but not PCLN table, fall
+		// back to much higher granularity vulnerability checking.
+		return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
+	}
+	lineTab := gosym.NewLineTable(pclntab, textOffset)
+	if lineTab == nil {
+		return nil, nil, nil, errors.New("invalid line table")
+	}
+	tab, err := gosym.NewTable(nil, lineTab)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	pkgSyms := make(map[Symbol]bool)
+	for _, f := range tab.Funcs {
+		if f.Func == nil {
+			continue
+		}
+		pkgName, symName, err := parseName(f.Func.Sym)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		pkgSyms[Symbol{pkgName, symName}] = true
+
+		// Collect symbols that were inlined in f.
+		it, err := lineTab.InlineTree(&f, value, base, r)
+		if err != nil {
+			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
+		}
+		for _, ic := range it {
+			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
+			if err != nil {
+				return nil, nil, nil, err
+			}
+			pkgSyms[Symbol{pkgName, symName}] = true
+		}
+	}
+
+	var syms []Symbol
+	for ps := range pkgSyms {
+		syms = append(syms, ps)
+	}
+
+	return debugModulesToPackagesModules(bi.Deps), syms, bi, nil
+}
+
+func parseName(s *gosym.Sym) (pkg, sym string, err error) {
+	symName := s.BaseName()
+	if r := s.ReceiverName(); r != "" {
+		if strings.HasPrefix(r, "(*") {
+			r = strings.Trim(r, "(*)")
+		}
+		symName = fmt.Sprintf("%s.%s", r, symName)
+	}
+
+	pkgName := s.PackageName()
+	if pkgName != "" {
+		pkgName, err = url.PathUnescape(pkgName)
+		if err != nil {
+			return "", "", err
+		}
+	}
+	return pkgName, symName, nil
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
new file mode 100644
index 00000000..f29dffa2
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/buildinfo/buildinfo.go
@@ -0,0 +1,221 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.18
+// +build go1.18
+
+package buildinfo
+
+// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"fmt"
+	"sync"
+
+	// "internal/xcoff"
+	"io"
+)
+
+// Addition: modification of rawBuildInfo in the original file.
+// openExe returns reader r as an exe.
+func openExe(r io.ReaderAt) (exe, error) {
+	data := make([]byte, 16)
+	if _, err := r.ReadAt(data, 0); err != nil {
+		return nil, err
+	}
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &elfExe{f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &peExe{r: r, f: e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(r)
+		if err != nil {
+			return nil, err
+		}
+		return &machoExe{f: e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type exe interface {
+	// ReadData reads and returns up to size byte starting at virtual address addr.
+	ReadData(addr, size uint64) ([]byte, error)
+
+	// DataStart returns the virtual address of the segment or section that
+	// should contain build information. This is either a specially named section
+	// or the first writable non-zero data segment.
+	DataStart() uint64
+
+	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
+
+	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
+}
+
+// elfExe is the ELF implementation of the exe interface.
+type elfExe struct {
+	f *elf.File
+
+	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once              // Addition: for computing symbols
+	symbolsErr  error                  // Addition: error for computing symbols
+}
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *elfExe) DataStart() uint64 {
+	for _, s := range x.f.Sections {
+		if s.Name == ".go.buildinfo" {
+			return s.Addr
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
+			return p.Vaddr
+		}
+	}
+	return 0
+}
+
+// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
+type peExe struct {
+	r io.ReaderAt
+	f *pe.File
+
+	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once             // Addition: for computing symbols
+	symbolsErr  error                 // Addition: error for computing symbols
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
+			n := uint64(sect.VirtualAddress+sect.Size) - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *peExe) DataStart() uint64 {
+	// Assume data is first writable section.
+	const (
+		IMAGE_SCN_CNT_CODE               = 0x00000020
+		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
+		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
+		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
+		IMAGE_SCN_MEM_READ               = 0x40000000
+		IMAGE_SCN_MEM_WRITE              = 0x80000000
+		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
+		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
+		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
+	)
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 &&
+			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
+			return uint64(sect.VirtualAddress) + x.imageBase()
+		}
+	}
+	return 0
+}
+
+// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
+type machoExe struct {
+	f *macho.File
+
+	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
+	symbolsOnce sync.Once                // Addition: for computing symbols
+	symbolsErr  error                    // Addition: error for computing symbols
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			n := seg.Addr + seg.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped") // Addition: custom error
+}
+
+func (x *machoExe) DataStart() uint64 {
+	// Look for section named "__go_buildinfo".
+	for _, sec := range x.f.Sections {
+		if sec.Name == "__go_buildinfo" {
+			return sec.Addr
+		}
+	}
+	// Try the first non-empty writable segment.
+	const RW = 3
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
+			return seg.Addr
+		}
+	}
+	return 0
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/client/index.go b/public-api/vendor/golang.org/x/vuln/internal/client/index.go
index 5f2d0c00..435980c4 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/client/index.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/client/index.go
@@ -96,7 +96,7 @@ func (i *index) add(entry *osv.Entry) {
 		module.Vulns = append(module.Vulns, moduleVuln{
 			ID:       entry.ID,
 			Modified: entry.Modified,
-			Fixed:    isem.LatestFixedVersion(affected.Ranges),
+			Fixed:    isem.NonSupersededFix(affected.Ranges),
 		})
 	}
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/client/source.go b/public-api/vendor/golang.org/x/vuln/internal/client/source.go
index 3e47b09f..2e848c32 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/client/source.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/client/source.go
@@ -45,8 +45,9 @@ type httpSource struct {
 func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err error) {
 	derrors.Wrap(&err, "get(%s)", endpoint)
 
+	method := http.MethodGet
 	reqURL := fmt.Sprintf("%s/%s", hs.url, endpoint+".json.gz")
-	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
+	req, err := http.NewRequestWithContext(ctx, method, reqURL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -56,7 +57,7 @@ func (hs *httpSource) get(ctx context.Context, endpoint string) (_ []byte, err e
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
+		return nil, fmt.Errorf("HTTP %s %s returned unexpected status: %s", method, reqURL, resp.Status)
 	}
 
 	// Uncompress the result.
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md b/public-api/vendor/golang.org/x/vuln/internal/gosym/README.md
similarity index 100%
rename from public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/README.md
rename to public-api/vendor/golang.org/x/vuln/internal/gosym/README.md
diff --git a/public-api/vendor/golang.org/x/vuln/internal/gosym/additions.go b/public-api/vendor/golang.org/x/vuln/internal/gosym/additions.go
new file mode 100644
index 00000000..022cf92e
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/gosym/additions.go
@@ -0,0 +1,184 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gosym
+
+import (
+	"encoding/binary"
+	"io"
+	"strings"
+
+	sv "golang.org/x/mod/semver"
+	"golang.org/x/vuln/internal/semver"
+)
+
+const (
+	funcSymNameGo119Lower string = "go.func.*"
+	funcSymNameGo120      string = "go:func.*"
+)
+
+// FuncSymName returns symbol name for Go functions used in binaries
+// based on Go version. Supported Go versions are 1.18 and greater.
+// If the go version is unreadable it assumes that it is a newer version
+// and returns the symbol name for go version 1.20 or greater.
+func FuncSymName(goVersion string) string {
+	// Support devel goX.Y...
+	v := strings.TrimPrefix(goVersion, "devel ")
+	v = semver.GoTagToSemver(v)
+	mm := sv.MajorMinor(v)
+	if sv.Compare(mm, "v1.20") >= 0 || mm == "" {
+		return funcSymNameGo120
+	} else if sv.Compare(mm, "v1.18") >= 0 {
+		return funcSymNameGo119Lower
+	}
+	return ""
+}
+
+// Additions to the original package from cmd/internal/objabi/funcdata.go
+const (
+	pcdata_InlTreeIndex = 2
+	funcdata_InlTree    = 3
+)
+
+// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
+// goFuncValue is the value of the gosym.FuncSymName symbol.
+// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
+// progReader is a ReaderAt positioned at the start of that region.
+func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
+	if f.inlineTreeCount == 0 {
+		return nil, nil
+	}
+	if f.inlineTreeOffset == ^uint32(0) {
+		return nil, nil
+	}
+	var offset int64
+	if t.version >= ver118 {
+		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
+	} else {
+		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
+	}
+
+	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
+	ics := make([]InlinedCall, 0, f.inlineTreeCount)
+	for i := 0; i < f.inlineTreeCount; i++ {
+		if t.version >= ver120 {
+			var ric rawInlinedCall120
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.NameOff)),
+				ParentPC: ric.ParentPC,
+			})
+		} else {
+			var ric rawInlinedCall112
+			if err := binary.Read(r, t.binary, &ric); err != nil {
+				return nil, err
+			}
+			ics = append(ics, InlinedCall{
+				FuncID:   ric.FuncID,
+				Name:     t.funcName(uint32(ric.Func_)),
+				ParentPC: ric.ParentPC,
+			})
+		}
+	}
+	return ics, nil
+}
+
+// InlinedCall describes a call to an inlined function.
+type InlinedCall struct {
+	FuncID   uint8  // type of the called function
+	Name     string // name of called function
+	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall112 struct {
+	Parent   int16 // index of parent in the inltree, or < 0
+	FuncID   uint8 // type of the called function
+	_        byte
+	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
+	Line     int32 // line number of the call site
+	Func_    int32 // offset into pclntab for name of called function
+	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
+}
+
+// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
+// from Go 1.20. It is equivalent to runtime.inlinedCall.
+type rawInlinedCall120 struct {
+	FuncID    uint8 // type of the called function
+	_         [3]byte
+	NameOff   int32 // offset into pclntab for name of called function
+	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
+	StartLine int32 // line number of start of function (func keyword/TEXT directive)
+}
+
+func (f funcData) npcdata() uint32 { return f.field(7) }
+func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
+	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
+}
+
+func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.nfuncdata(numFuncFields) {
+		return ^uint32(0)
+	}
+	var off uint32
+	if f.t.version >= ver118 {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4 + // skip pcdata
+			uint32(i)*4 // index of i'th FUNCDATA
+	} else {
+		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
+			f.npcdata()*4
+		off += uint32(i) * f.t.ptrsize
+	}
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+func (f funcData) fieldOffset(n uint32) uint32 {
+	// In Go 1.18, the first field of _func changed
+	// from a uintptr entry PC to a uint32 entry offset.
+	sz0 := f.t.ptrsize
+	if f.t.version >= ver118 {
+		sz0 = 4
+	}
+	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
+}
+
+func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
+	if uint32(i) >= f.npcdata() {
+		return ^uint32(0)
+	}
+	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
+		uint32(i)*4 // index of i'th PCDATA
+	return f.t.binary.Uint32(f.data[off:])
+}
+
+// maxInlineTreeIndexValue returns the maximum value of the inline tree index
+// pc-value table in info. This is the only way to determine how many
+// IndexedCalls are in an inline tree, since the data of the tree itself is not
+// delimited in any way.
+func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
+	if info.npcdata() <= pcdata_InlTreeIndex {
+		return -1
+	}
+	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
+	p := t.pctab[off:]
+	val := int32(-1)
+	max := int32(-1)
+	var pc uint64
+	for t.step(&p, &pc, &val, pc == 0) {
+		if val > max {
+			max = val
+		}
+	}
+	return int(max)
+}
+
+type inlTree struct {
+	inlineTreeOffset uint32 // offset from go.func.* symbol
+	inlineTreeCount  int    // number of entries in inline tree
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go b/public-api/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
similarity index 100%
rename from public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/pclntab.go
rename to public-api/vendor/golang.org/x/vuln/internal/gosym/pclntab.go
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go b/public-api/vendor/golang.org/x/vuln/internal/gosym/symtab.go
similarity index 100%
rename from public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/symtab.go
rename to public-api/vendor/golang.org/x/vuln/internal/gosym/symtab.go
diff --git a/public-api/vendor/golang.org/x/vuln/internal/goversion/asm.go b/public-api/vendor/golang.org/x/vuln/internal/goversion/asm.go
new file mode 100644
index 00000000..1c165e60
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/goversion/asm.go
@@ -0,0 +1,349 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"encoding/binary"
+	"fmt"
+	"os"
+)
+
+type matcher [][]uint32
+
+const (
+	pWild    uint32 = 0xff00
+	pAddr    uint32 = 0x10000
+	pEnd     uint32 = 0x20000
+	pRelAddr uint32 = 0x30000
+
+	opMaybe = 1 + iota
+	opMust
+	opDone
+	opAnchor = 0x100
+	opSub8   = 0x200
+	opFlags  = opAnchor | opSub8
+)
+
+var amd64Matcher = matcher{
+	{opMaybe | opAnchor,
+		// __rt0_amd64_darwin:
+		//	JMP __rt0_amd64
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	lea ADDR(%rip), %rax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24, 0x48,
+		0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// _rt0_amd64_linux:
+		//	lea 0x8(%rsp), %rsi
+		//	mov (%rsp), %rdi
+		//	mov $ADDR, %eax # main
+		//	jmpq *%rax
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0x48, 0x8b, 0x3c, 0x24,
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe,
+		// __rt0_amd64:
+		//	mov (%rsp), %rdi
+		//	lea 8(%rsp), %rsi
+		//	jmp runtime.rt0_g0
+		0x48, 0x8b, 0x3c, 0x24,
+		0x48, 0x8d, 0x74, 0x24, 0x08,
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xcc, 0xcc,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	lea __libc_csu_fini(%rip), %r8
+		//	lea __libc_csu_init(%rip), %rcx
+		//	lea ADDR(%rip), %rdi # main
+		//	callq *xxx(%rip)
+		0x4c, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x3d, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0x15,
+	},
+	{opMaybe,
+		// _start (toward end)
+		//	push %rsp (1)
+		//	mov $__libc_csu_fini, %r8 (7)
+		//	mov $__libc_csu_init, %rcx (7)
+		//	mov $ADDR, %rdi # main (7)
+		//	callq *xxx(%rip)
+		0x54,
+		0x49, 0xc7, 0xc0, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc1, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0xc7, pAddr | pWild, pWild, pWild, pWild,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	lea ADDR(%rip), %rax # rt0_go
+		//	jmpq *%rax
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	mov $ADDR, %eax
+		//	jmpq *%rax
+		0xb8, pWild | pAddr, pWild, pWild, pWild,
+		0xff, 0xe0,
+	},
+	{opMaybe | opAnchor,
+		// main:
+		//	JMP runtime.rt0_go(SB)
+		0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
+	},
+	{opMust | opAnchor,
+		// rt0_go:
+		//	mov %rdi, %rax
+		//	mov %rsi, %rbx
+		//	sub %0x27, %rsp
+		//	and $0xfffffffffffffff0,%rsp
+		//	mov %rax,0x10(%rsp)
+		//	mov %rbx,0x18(%rsp)
+		0x48, 0x89, 0xf8,
+		0x48, 0x89, 0xf3,
+		0x48, 0x83, 0xec, 0x27,
+		0x48, 0x83, 0xe4, 0xf0,
+		0x48, 0x89, 0x44, 0x24, 0x10,
+		0x48, 0x89, 0x5c, 0x24, 0x18,
+	},
+	{opMust,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.schedinit (ADDR)
+		//	lea other(%rip), %rdi
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0x8d, 0x05,
+	},
+	{opMaybe,
+		// later in rt0_go:
+		//	mov %eax, (%rsp)
+		//	mov 0x18(%rsp), %rax
+		//	mov %rax, 0x8(%rsp)
+		//	callq runtime.args
+		//	callq runtime.osinit
+		//	callq runtime.hashinit
+		//	callq runtime.schedinit (ADDR)
+		//	pushq $main.main
+		0x89, 0x04, 0x24,
+		0x48, 0x8b, 0x44, 0x24, 0x18,
+		0x48, 0x89, 0x44, 0x24, 0x08,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild, pWild, pWild, pWild,
+		0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x68,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rax
+		//	test %rax, %rax
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc0,
+		0x75, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone | opSub8,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rbx
+		//	cmp $0x0, %rbx
+		//	jne 
+		//	lea "unknown"(%rip), %rbx
+		//	mov %rbx, ADDR(%rip)
+		//	movq $7, (ADDR+8)(%rip)
+		0x48, 0x8b, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x83, 0xfb, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x1d, pWild, pWild, pWild, pWild,
+		0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	lea "unknown"(%rip), %rax
+		//	mov %rax, ADDR(%rip)
+		//	lea ADDR(%rip), %rax
+		//	movq $7, 8(%rax)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x89, 0x05, pWild, pWild, pWild, pWild,
+		0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+		0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	cmpq $0x0, ADDR(%rip)
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+	{opDone,
+		//	test %eax, %eax
+		//	jne 
+		//	lea "unknown"(RIP), %rax
+		//	mov %rax, ADDR(%rip)
+		0x48, 0x85, 0xc0, 0x75, pWild, 0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild, 0x48, 0x89, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
+	},
+	{opDone,
+		// schedinit (toward end)
+		//	mov ADDR(%rip), %rcx
+		//	test %rcx, %rcx
+		//	jne 
+		//	movq $0x7, ADDR(%rip)
+		//
+		0x48, 0x8b, 0x0d, pWild, pWild, pWild, pWild,
+		0x48, 0x85, 0xc9,
+		0x75, pWild,
+		0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
+	},
+}
+
+var DebugMatch bool
+
+func (m matcher) match(f exe, addr uint64) (uint64, bool) {
+	data, err := f.ReadData(addr, 512)
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
+	}
+	if err != nil {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "match: %v\n", err)
+		}
+		return 0, false
+	}
+	if DebugMatch {
+		fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
+	}
+Matchers:
+	for pc, p := range m {
+		op := p[0]
+		p = p[1:]
+	Search:
+		for i := 0; i <= len(data)-len(p); i++ {
+			a := -1
+			e := -1
+			if i > 0 && op&opAnchor != 0 {
+				break
+			}
+			for j := 0; j < len(p); j++ {
+				b := byte(p[j])
+				m := byte(p[j] >> 8)
+				if data[i+j]&^m != b {
+					continue Search
+				}
+				if p[j]&pAddr != 0 {
+					a = j
+				}
+				if p[j]&pEnd != 0 {
+					e = j + 1
+				}
+			}
+			// matched
+			if DebugMatch {
+				fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
+			}
+			if a != -1 {
+				val := uint64(int32(binary.LittleEndian.Uint32(data[i+a:])))
+				if e == -1 {
+					addr = val
+				} else {
+					addr += uint64(i+e) + val
+				}
+				if op&opSub8 != 0 {
+					addr -= 8
+				}
+			}
+			if op&^opFlags == opDone {
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "done %x\n", addr)
+				}
+				return addr, true
+			}
+			if a != -1 {
+				// changed addr, so reload
+				data, err = f.ReadData(addr, 512)
+				if err != nil {
+					return 0, false
+				}
+				if DebugMatch {
+					fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
+				}
+			}
+			continue Matchers
+		}
+		// not matched
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
+		}
+		if op&^opFlags == opMust {
+			return 0, false
+		}
+	}
+	// ran off end of matcher
+	return 0, false
+}
+
+func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
+	entry := f.Entry()
+	if entry == 0 {
+		if DebugMatch {
+			fmt.Fprintf(os.Stderr, "missing entry!\n")
+		}
+		return
+	}
+	addr, ok := amd64Matcher.match(f, entry)
+	if !ok {
+		return
+	}
+	v, err := readBuildVersion(f, addr, 16)
+	if err != nil {
+		return
+	}
+	return true, v
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/goversion/exe.go b/public-api/vendor/golang.org/x/vuln/internal/goversion/exe.go
new file mode 100644
index 00000000..d833bfe6
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/goversion/exe.go
@@ -0,0 +1,324 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package goversion
+
+import (
+	"bytes"
+	"debug/elf"
+	"debug/macho"
+	"debug/pe"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+)
+
+type sym struct {
+	Name string
+	Addr uint64
+	Size uint64
+}
+
+type exe interface {
+	AddrSize() int // bytes
+	ReadData(addr, size uint64) ([]byte, error)
+	Symbols() ([]sym, error)
+	SectionNames() []string
+	Close() error
+	ByteOrder() binary.ByteOrder
+	Entry() uint64
+	TextRange() (uint64, uint64)
+	RODataRange() (uint64, uint64)
+}
+
+func openExe(file string) (exe, error) {
+	f, err := os.Open(file)
+	if err != nil {
+		return nil, err
+	}
+	data := make([]byte, 16)
+	if _, err := io.ReadFull(f, data); err != nil {
+		return nil, err
+	}
+	f.Seek(0, 0)
+	if bytes.HasPrefix(data, []byte("\x7FELF")) {
+		e, err := elf.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &elfExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("MZ")) {
+		e, err := pe.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &peExe{f, e}, nil
+	}
+	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
+		e, err := macho.NewFile(f)
+		if err != nil {
+			f.Close()
+			return nil, err
+		}
+		return &machoExe{f, e}, nil
+	}
+	return nil, fmt.Errorf("unrecognized executable format")
+}
+
+type elfExe struct {
+	os *os.File
+	f  *elf.File
+}
+
+func (x *elfExe) AddrSize() int { return 0 }
+
+func (x *elfExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *elfExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *elfExe) Entry() uint64 { return x.f.Entry }
+
+func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
+	for _, prog := range x.f.Progs {
+		// The following line was commented from the original code.
+		//fmt.Printf("%#x %#x %#x\n", addr, prog.Vaddr, prog.Vaddr+prog.Filesz)
+		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
+			n := prog.Vaddr + prog.Filesz - addr
+			if n > size {
+				n = size
+			}
+			data := make([]byte, n)
+			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *elfExe) Symbols() ([]sym, error) {
+	syms, err := x.f.Symbols()
+	if err != nil {
+		return nil, err
+	}
+	var out []sym
+	for _, s := range syms {
+		out = append(out, sym{s.Name, s.Value, s.Size})
+	}
+	return out, nil
+}
+
+func (x *elfExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *elfExe) TextRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *elfExe) RODataRange() (uint64, uint64) {
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == elf.PF_R {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	for _, p := range x.f.Progs {
+		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_R|elf.PF_W|elf.PF_X) == (elf.PF_R|elf.PF_X) {
+			return p.Vaddr, p.Vaddr + p.Filesz
+		}
+	}
+	return 0, 0
+}
+
+type peExe struct {
+	os *os.File
+	f  *pe.File
+}
+
+func (x *peExe) imageBase() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase
+	}
+	return 0
+}
+
+func (x *peExe) AddrSize() int {
+	if x.f.Machine == pe.IMAGE_FILE_MACHINE_AMD64 {
+		return 8
+	}
+	return 4
+}
+
+func (x *peExe) ByteOrder() binary.ByteOrder { return binary.LittleEndian }
+
+func (x *peExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *peExe) Entry() uint64 {
+	switch oh := x.f.OptionalHeader.(type) {
+	case *pe.OptionalHeader32:
+		return uint64(oh.ImageBase + oh.AddressOfEntryPoint)
+	case *pe.OptionalHeader64:
+		return oh.ImageBase + uint64(oh.AddressOfEntryPoint)
+	}
+	return 0
+}
+
+func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
+	addr -= x.imageBase()
+	data := make([]byte, size)
+	for _, sect := range x.f.Sections {
+		if uint64(sect.VirtualAddress) <= addr && addr+size-1 <= uint64(sect.VirtualAddress+sect.Size-1) {
+			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *peExe) Symbols() ([]sym, error) {
+	base := x.imageBase()
+	var out []sym
+	for _, s := range x.f.Symbols {
+		if s.SectionNumber <= 0 || int(s.SectionNumber) > len(x.f.Sections) {
+			continue
+		}
+		sect := x.f.Sections[s.SectionNumber-1]
+		out = append(out, sym{s.Name, uint64(s.Value) + base + uint64(sect.VirtualAddress), 0})
+	}
+	return out, nil
+}
+
+func (x *peExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *peExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty section.
+	for _, sect := range x.f.Sections {
+		if sect.VirtualAddress != 0 && sect.Size != 0 {
+			return uint64(sect.VirtualAddress) + x.imageBase(), uint64(sect.VirtualAddress+sect.Size) + x.imageBase()
+		}
+	}
+	return 0, 0
+}
+
+func (x *peExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
+
+type machoExe struct {
+	os *os.File
+	f  *macho.File
+}
+
+func (x *machoExe) AddrSize() int {
+	if x.f.Cpu&0x01000000 != 0 {
+		return 8
+	}
+	return 4
+}
+
+func (x *machoExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
+
+func (x *machoExe) Close() error {
+	return x.os.Close()
+}
+
+func (x *machoExe) Entry() uint64 {
+	for _, load := range x.f.Loads {
+		b, ok := load.(macho.LoadBytes)
+		if !ok {
+			continue
+		}
+		// TODO: Other thread states.
+		bo := x.f.ByteOrder
+		const x86_THREAD_STATE64 = 4
+		cmd, siz := macho.LoadCmd(bo.Uint32(b[0:4])), bo.Uint32(b[4:8])
+		if cmd == macho.LoadCmdUnixThread && siz == 184 && bo.Uint32(b[8:12]) == x86_THREAD_STATE64 {
+			return bo.Uint64(b[144:])
+		}
+	}
+	return 0
+}
+
+func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
+	data := make([]byte, size)
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if !ok {
+			continue
+		}
+		if seg.Addr <= addr && addr+size-1 <= seg.Addr+seg.Filesz-1 {
+			if seg.Name == "__PAGEZERO" {
+				continue
+			}
+			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
+			if err != nil {
+				return nil, err
+			}
+			return data, nil
+		}
+	}
+	return nil, fmt.Errorf("address not mapped")
+}
+
+func (x *machoExe) Symbols() ([]sym, error) {
+	var out []sym
+	for _, s := range x.f.Symtab.Syms {
+		out = append(out, sym{s.Name, s.Value, 0})
+	}
+	return out, nil
+}
+
+func (x *machoExe) SectionNames() []string {
+	var names []string
+	for _, sect := range x.f.Sections {
+		names = append(names, sect.Name)
+	}
+	return names
+}
+
+func (x *machoExe) TextRange() (uint64, uint64) {
+	// Assume text is first non-empty segment.
+	for _, load := range x.f.Loads {
+		seg, ok := load.(*macho.Segment)
+		if ok && seg.Name != "__PAGEZERO" && seg.Addr != 0 && seg.Filesz != 0 {
+			return seg.Addr, seg.Addr + seg.Filesz
+		}
+	}
+	return 0, 0
+}
+
+func (x *machoExe) RODataRange() (uint64, uint64) {
+	return x.TextRange()
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/goversion/read.go b/public-api/vendor/golang.org/x/vuln/internal/goversion/read.go
new file mode 100644
index 00000000..f298ef07
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/goversion/read.go
@@ -0,0 +1,246 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package goversion reports the Go version used to build program executables.
+//
+// This is a copy of rsc.io/goversion/version. We renamed the package to goversion
+// to differentiate between version package in standard library that we also use.
+package goversion
+
+import (
+	"bytes"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// Version is the information reported by ReadExe.
+type Version struct {
+	Release        string // Go version (runtime.Version in the program)
+	ModuleInfo     string // program's module information
+	BoringCrypto   bool   // program uses BoringCrypto
+	StandardCrypto bool   // program uses standard crypto (replaced by BoringCrypto)
+	FIPSOnly       bool   // program imports "crypto/tls/fipsonly"
+}
+
+// ReadExe reports information about the Go version used to build
+// the program executable named by file.
+func ReadExe(file string) (Version, error) {
+	var v Version
+	f, err := openExe(file)
+	if err != nil {
+		return v, err
+	}
+	defer f.Close()
+	isGo := false
+	for _, name := range f.SectionNames() {
+		if name == ".note.go.buildid" {
+			isGo = true
+		}
+	}
+	syms, symsErr := f.Symbols()
+	isGccgo := false
+	for _, sym := range syms {
+		name := sym.Name
+		if name == "runtime.main" || name == "main.main" {
+			isGo = true
+		}
+		if strings.HasPrefix(name, "runtime.") && strings.HasSuffix(name, "$descriptor") {
+			isGccgo = true
+		}
+		if name == "runtime.buildVersion" {
+			isGo = true
+			release, err := readBuildVersion(f, sym.Addr, sym.Size)
+			if err != nil {
+				return v, err
+			}
+			v.Release = release
+		}
+		// Note: Using strings.HasPrefix because Go 1.17+ adds ".abi0" to many of these symbols.
+		if strings.Contains(name, "_Cfunc__goboringcrypto_") || strings.HasPrefix(name, "crypto/internal/boring/sig.BoringCrypto") {
+			v.BoringCrypto = true
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.FIPSOnly") {
+			v.FIPSOnly = true
+		}
+		for _, re := range standardCryptoNames {
+			if re.MatchString(name) {
+				v.StandardCrypto = true
+			}
+		}
+		if strings.HasPrefix(name, "crypto/internal/boring/sig.StandardCrypto") {
+			v.StandardCrypto = true
+		}
+	}
+
+	if DebugMatch {
+		v.Release = ""
+	}
+	if err := findModuleInfo(&v, f); err != nil {
+		return v, err
+	}
+	if v.Release == "" {
+		g, release := readBuildVersionX86Asm(f)
+		if g {
+			isGo = true
+			v.Release = release
+			if err := findCryptoSigs(&v, f); err != nil {
+				return v, err
+			}
+		}
+	}
+	if isGccgo && v.Release == "" {
+		isGo = true
+		v.Release = "gccgo (version unknown)"
+	}
+	if !isGo && symsErr != nil {
+		return v, symsErr
+	}
+
+	if !isGo {
+		return v, errors.New("not a Go executable")
+	}
+	if v.Release == "" {
+		v.Release = "unknown Go version"
+	}
+	return v, nil
+}
+
+var re = regexp.MustCompile
+
+var standardCryptoNames = []*regexp.Regexp{
+	re(`^crypto/sha1\.\(\*digest\)`),
+	re(`^crypto/sha256\.\(\*digest\)`),
+	re(`^crypto/rand\.\(\*devReader\)`),
+	re(`^crypto/rsa\.encrypt(\.abi.)?$`),
+	re(`^crypto/rsa\.decrypt(\.abi.)?$`),
+}
+
+func readBuildVersion(f exe, addr, size uint64) (string, error) {
+	if size == 0 {
+		size = uint64(f.AddrSize() * 2)
+	}
+	if size != 8 && size != 16 {
+		return "", fmt.Errorf("invalid size for runtime.buildVersion")
+	}
+	data, err := f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion: %v", err)
+	}
+
+	if size == 8 {
+		addr = uint64(f.ByteOrder().Uint32(data))
+		size = uint64(f.ByteOrder().Uint32(data[4:]))
+	} else {
+		addr = f.ByteOrder().Uint64(data)
+		size = f.ByteOrder().Uint64(data[8:])
+	}
+	if size > 1000 {
+		return "", fmt.Errorf("implausible string size %d for runtime.buildVersion", size)
+	}
+
+	data, err = f.ReadData(addr, size)
+	if err != nil {
+		return "", fmt.Errorf("reading runtime.buildVersion string data: %v", err)
+	}
+	return string(data), nil
+}
+
+// Code signatures that indicate BoringCrypto or crypto/internal/fipsonly.
+// These are not byte literals in order to avoid the actual
+// byte signatures appearing in the goversion binary,
+// because on some systems you can't tell rodata from text.
+var (
+	sigBoringCrypto, _   = hex.DecodeString("EB1DF448F44BF4B332F52813A3B450D441CC2485F001454E92101B1D2F1950C3")
+	sigStandardCrypto, _ = hex.DecodeString("EB1DF448F44BF4BAEE4DFA9851CA56A91145E83E99C59CF911CB8E80DAF12FC3")
+	sigFIPSOnly, _       = hex.DecodeString("EB1DF448F44BF4363CB9CE9D68047D31F28D325D5CA5873F5D80CAF6D6151BC3")
+)
+
+func findCryptoSigs(v *Version, f exe) error {
+	const maxSigLen = 1 << 10
+	start, end := f.TextRange()
+	for addr := start; addr < end; {
+		size := uint64(1 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveSig(data, sigBoringCrypto) {
+			v.BoringCrypto = true
+		}
+		if haveSig(data, sigFIPSOnly) {
+			v.FIPSOnly = true
+		}
+		if haveSig(data, sigStandardCrypto) {
+			v.StandardCrypto = true
+		}
+		if addr+size < end {
+			size -= maxSigLen
+		}
+		addr += size
+	}
+	return nil
+}
+
+func haveSig(data, sig []byte) bool {
+	const align = 16
+	for {
+		i := bytes.Index(data, sig)
+		if i < 0 {
+			return false
+		}
+		if i&(align-1) == 0 {
+			return true
+		}
+		// Found unaligned match; unexpected but
+		// skip to next aligned boundary and keep searching.
+		data = data[(i+align-1)&^(align-1):]
+	}
+}
+
+func findModuleInfo(v *Version, f exe) error {
+	const maxModInfo = 128 << 10
+	start, end := f.RODataRange()
+	for addr := start; addr < end; {
+		size := uint64(4 << 20)
+		if end-addr < size {
+			size = end - addr
+		}
+		data, err := f.ReadData(addr, size)
+		if err != nil {
+			return fmt.Errorf("reading text: %v", err)
+		}
+		if haveModuleInfo(data, v) {
+			return nil
+		}
+		if addr+size < end {
+			size -= maxModInfo
+		}
+		addr += size
+	}
+	return nil
+}
+
+var (
+	infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+	infoEnd, _   = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func haveModuleInfo(data []byte, v *Version) bool {
+	i := bytes.Index(data, infoStart)
+	if i < 0 {
+		return false
+	}
+	j := bytes.Index(data[i:], infoEnd)
+	if j < 0 {
+		return false
+	}
+	v.ModuleInfo = string(data[i+len(infoStart) : i+j])
+	return true
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
new file mode 100644
index 00000000..377a3787
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/govulncheck.go
@@ -0,0 +1,241 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package govulncheck contains the JSON output structs for govulncheck.
+//
+// govulncheck supports streaming JSON by emitting a series of Message
+// objects as it analyzes user code and discovers vulnerabilities.
+// Streaming JSON is useful for displaying progress in real-time for
+// large projects where govulncheck execution might take some time.
+//
+// govulncheck JSON emits configuration used to perform the analysis,
+// a user-friendly message about what is being analyzed, and the
+// vulnerability findings. Findings for the same vulnerability can
+// can be emitted several times. For instance, govulncheck JSON will
+// emit a finding when it sees that a vulnerable module is required
+// before proceeding to check if the vulnerability is imported or called.
+// Please see documentation on Message and related types for precise
+// details on the stream encoding.
+//
+// There are no guarantees on the order of messages. The pattern of emitted
+// messages can change in the future. Clients can follow code in handler.go
+// for consuming the streaming JSON programmatically.
+package govulncheck
+
+import (
+	"time"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+const (
+	// ProtocolVersion is the current protocol version this file implements
+	ProtocolVersion = "v1.0.0"
+)
+
+// Message is an entry in the output stream. It will always have exactly one
+// field filled in.
+type Message struct {
+	Config   *Config   `json:"config,omitempty"`
+	Progress *Progress `json:"progress,omitempty"`
+	SBOM     *SBOM     `json:"SBOM,omitempty"`
+	// OSV is emitted for every vulnerability in the current database
+	// that applies to user modules regardless of their version. If a
+	// module is being used at a vulnerable version, the corresponding
+	// OSV will be referenced in Findings depending on the type of usage
+	// and the desired scan level.
+	OSV     *osv.Entry `json:"osv,omitempty"`
+	Finding *Finding   `json:"finding,omitempty"`
+}
+
+// Config must occur as the first message of a stream and informs the client
+// about the information used to generate the findings.
+// The only required field is the protocol version.
+type Config struct {
+	// ProtocolVersion specifies the version of the JSON protocol.
+	ProtocolVersion string `json:"protocol_version"`
+
+	// ScannerName is the name of the tool, for example, govulncheck.
+	//
+	// We expect this JSON format to be used by other tools that wrap
+	// govulncheck, which will have a different name.
+	ScannerName string `json:"scanner_name,omitempty"`
+
+	// ScannerVersion is the version of the tool.
+	ScannerVersion string `json:"scanner_version,omitempty"`
+
+	// DB is the database used by the tool, for example,
+	// vuln.go.dev.
+	DB string `json:"db,omitempty"`
+
+	// LastModified is the last modified time of the data source.
+	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
+
+	// GoVersion is the version of Go used for analyzing standard library
+	// vulnerabilities.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// ScanLevel instructs govulncheck to analyze at a specific level of detail.
+	// Valid values include module, package and symbol.
+	ScanLevel ScanLevel `json:"scan_level,omitempty"`
+
+	// ScanMode instructs govulncheck how to interpret the input and
+	// what to do with it. Valid values are source, binary, query,
+	// and extract.
+	ScanMode ScanMode `json:"scan_mode,omitempty"`
+}
+
+// SBOM contains minimal information about the artifacts govulncheck is scanning.
+type SBOM struct {
+	// The go version used by govulncheck when scanning, which also defines
+	// the version of the standard library used for detecting vulns.
+	GoVersion string `json:"go_version,omitempty"`
+
+	// The set of modules included in the scan.
+	Modules []*Module `json:"modules,omitempty"`
+
+	// The roots of the scan, as package paths.
+	// For binaries, this will be the main package.
+	// For source code, this will be the packages matching the provided package patterns.
+	Roots []string `json:"roots,omitempty"`
+}
+
+type Module struct {
+	// The full module path.
+	Path string `json:"path,omitempty"`
+
+	// The version of the module.
+	Version string `json:"version,omitempty"`
+}
+
+// Progress messages are informational only, intended to allow users to monitor
+// the progress of a long running scan.
+// A stream must remain fully valid and able to be interpreted with all progress
+// messages removed.
+type Progress struct {
+	// A time stamp for the message.
+	Timestamp *time.Time `json:"time,omitempty"`
+
+	// Message is the progress message.
+	Message string `json:"message,omitempty"`
+}
+
+// Finding contains information on a discovered vulnerability. Each vulnerability
+// will likely have multiple findings in JSON mode. This is because govulncheck
+// emits findings as it does work, and therefore could emit one module level,
+// one package level, and potentially multiple symbol level findings depending
+// on scan level.
+// Multiple symbol level findings can be emitted when multiple symbols of the
+// same vuln are called or govulncheck decides to show multiple traces for the
+// same symbol.
+type Finding struct {
+	// OSV is the id of the detected vulnerability.
+	OSV string `json:"osv,omitempty"`
+
+	// FixedVersion is the module version where the vulnerability was
+	// fixed. This is empty if a fix is not available.
+	//
+	// If there are multiple fixed versions in the OSV report, this will
+	// be the fixed version in the latest range event for the OSV report.
+	//
+	// For example, if the range events are
+	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
+	// will be empty.
+	//
+	// For the stdlib, we will show the fixed version closest to the
+	// Go version that is used. For example, if a fix is available in 1.17.5 and
+	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
+	// fixed version.
+	FixedVersion string `json:"fixed_version,omitempty"`
+
+	// Trace contains an entry for each frame in the trace.
+	//
+	// Frames are sorted starting from the imported vulnerable symbol
+	// until the entry point. The first frame in Frames should match
+	// Symbol.
+	//
+	// In binary mode, trace will contain a single-frame with no position
+	// information.
+	//
+	// For module level source findings, the trace will contain a single-frame
+	// with no symbol, position, or package information. For package level source
+	// findings, the trace will contain a single-frame with no symbol or position
+	// information.
+	Trace []*Frame `json:"trace,omitempty"`
+}
+
+// Frame represents an entry in a finding trace.
+type Frame struct {
+	// Module is the module path of the module containing this symbol.
+	//
+	// Importable packages in the standard library will have the path "stdlib".
+	Module string `json:"module"`
+
+	// Version is the module version from the build graph.
+	Version string `json:"version,omitempty"`
+
+	// Package is the import path.
+	Package string `json:"package,omitempty"`
+
+	// Function is the function name.
+	Function string `json:"function,omitempty"`
+
+	// Receiver is the receiver type if the called symbol is a method.
+	//
+	// The client can create the final symbol name by
+	// prepending Receiver to FuncName.
+	Receiver string `json:"receiver,omitempty"`
+
+	// Position describes an arbitrary source position
+	// including the file, line, and column location.
+	// A Position is valid if the line number is > 0.
+	//
+	// The filenames are relative to the directory of
+	// the enclosing module and always use "/" for
+	// portability.
+	Position *Position `json:"position,omitempty"`
+}
+
+// Position represents arbitrary source position.
+type Position struct {
+	Filename string `json:"filename,omitempty"` // filename, if any
+	Offset   int    `json:"offset"`             // byte offset, starting at 0
+	Line     int    `json:"line"`               // line number, starting at 1
+	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
+}
+
+// ScanLevel represents the detail level at which a scan occurred.
+// This can be necessary to correctly interpret the findings, for instance if
+// a scan is at symbol level and a finding does not have a symbol it means the
+// vulnerability was imported but not called. If the scan however was at
+// "package" level, that determination cannot be made.
+type ScanLevel string
+
+const (
+	ScanLevelModule  = "module"
+	ScanLevelPackage = "package"
+	ScanLevelSymbol  = "symbol"
+)
+
+// WantSymbols can be used to check whether the scan level is one that is able
+// to generate symbol-level findings.
+func (l ScanLevel) WantSymbols() bool { return l == ScanLevelSymbol }
+
+// WantPackages can be used to check whether the scan level is one that is able
+// to generate package-level findings.
+func (l ScanLevel) WantPackages() bool { return l == ScanLevelPackage || l == ScanLevelSymbol }
+
+// ScanMode represents the mode in which a scan occurred. This can
+// be necessary to correctly to interpret findings. For instance,
+// a binary can be checked for vulnerabilities or the user just wants
+// to extract minimal data necessary for the vulnerability check.
+type ScanMode string
+
+const (
+	ScanModeSource  = "source"
+	ScanModeBinary  = "binary"
+	ScanModeConvert = "convert"
+	ScanModeQuery   = "query"
+	ScanModeExtract = "extract" // currently, only binary extraction is supported
+)
diff --git a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
index 5676ea94..5ce7d532 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/handler.go
@@ -17,6 +17,9 @@ type Handler interface {
 	// Config communicates introductory message to the user.
 	Config(config *Config) error
 
+	// SBOM shows information about what govulncheck is scanning.
+	SBOM(sbom *SBOM) error
+
 	// Progress is called to display a progress message.
 	Progress(progress *Progress) error
 
@@ -45,6 +48,9 @@ func HandleJSON(from io.Reader, to Handler) error {
 		if msg.Progress != nil {
 			err = to.Progress(msg.Progress)
 		}
+		if msg.SBOM != nil {
+			err = to.SBOM(msg.SBOM)
+		}
 		if msg.OSV != nil {
 			err = to.OSV(msg.OSV)
 		}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go
deleted file mode 100644
index d1ea78af..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/json.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package govulncheck
-
-import (
-	"encoding/json"
-
-	"io"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-type jsonHandler struct {
-	enc *json.Encoder
-}
-
-// NewJSONHandler returns a handler that writes govulncheck output as json.
-func NewJSONHandler(w io.Writer) Handler {
-	enc := json.NewEncoder(w)
-	enc.SetIndent("", "  ")
-	return &jsonHandler{enc: enc}
-}
-
-// Config writes config block in JSON to the underlying writer.
-func (h *jsonHandler) Config(config *Config) error {
-	return h.enc.Encode(Message{Config: config})
-}
-
-// Progress writes a progress message in JSON to the underlying writer.
-func (h *jsonHandler) Progress(progress *Progress) error {
-	return h.enc.Encode(Message{Progress: progress})
-}
-
-// OSV writes an osv entry in JSON to the underlying writer.
-func (h *jsonHandler) OSV(entry *osv.Entry) error {
-	return h.enc.Encode(Message{OSV: entry})
-}
-
-// Finding writes a finding in JSON to the underlying writer.
-func (h *jsonHandler) Finding(finding *Finding) error {
-	return h.enc.Encode(Message{Finding: finding})
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
new file mode 100644
index 00000000..b1586e09
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/jsonhandler.go
@@ -0,0 +1,49 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package govulncheck
+
+import (
+	"encoding/json"
+
+	"io"
+
+	"golang.org/x/vuln/internal/osv"
+)
+
+type jsonHandler struct {
+	enc *json.Encoder
+}
+
+// NewJSONHandler returns a handler that writes govulncheck output as json.
+func NewJSONHandler(w io.Writer) Handler {
+	enc := json.NewEncoder(w)
+	enc.SetIndent("", "  ")
+	return &jsonHandler{enc: enc}
+}
+
+// Config writes config block in JSON to the underlying writer.
+func (h *jsonHandler) Config(config *Config) error {
+	return h.enc.Encode(Message{Config: config})
+}
+
+// Progress writes a progress message in JSON to the underlying writer.
+func (h *jsonHandler) Progress(progress *Progress) error {
+	return h.enc.Encode(Message{Progress: progress})
+}
+
+// SBOM writes the SBOM block in JSON to the underlying writer.
+func (h *jsonHandler) SBOM(sbom *SBOM) error {
+	return h.enc.Encode(Message{SBOM: sbom})
+}
+
+// OSV writes an osv entry in JSON to the underlying writer.
+func (h *jsonHandler) OSV(entry *osv.Entry) error {
+	return h.enc.Encode(Message{OSV: entry})
+}
+
+// Finding writes a finding in JSON to the underlying writer.
+func (h *jsonHandler) Finding(finding *Finding) error {
+	return h.enc.Encode(Message{Finding: finding})
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go b/public-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go
deleted file mode 100644
index 3c1f2bdd..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/govulncheck/result.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package result contains the JSON output structs for govulncheck.
-package govulncheck
-
-import (
-	"time"
-
-	"golang.org/x/vuln/internal/osv"
-)
-
-const (
-	// ProtocolVersion is the current protocol version this file implements
-	ProtocolVersion = "v0.1.0"
-)
-
-// Message is an entry in the output stream. It will always have exactly one
-// field filled in.
-type Message struct {
-	Config   *Config    `json:"config,omitempty"`
-	Progress *Progress  `json:"progress,omitempty"`
-	OSV      *osv.Entry `json:"osv,omitempty"`
-	Finding  *Finding   `json:"finding,omitempty"`
-}
-
-type Config struct {
-	// ProtocolVersion specifies the version of the JSON protocol.
-	ProtocolVersion string `json:"protocol_version,omitempty"`
-
-	// ScannerName is the name of the tool, for example, govulncheck.
-	//
-	// We expect this JSON format to be used by other tools that wrap
-	// govulncheck, which will have a different name.
-	ScannerName string `json:"scanner_name,omitempty"`
-
-	// ScannerVersion is the version of the tool.
-	ScannerVersion string `json:"scanner_version,omitempty"`
-
-	// DB is the database used by the tool, for example,
-	// vuln.go.dev.
-	DB string `json:"db,omitempty"`
-
-	// LastModified is the last modified time of the data source.
-	DBLastModified *time.Time `json:"db_last_modified,omitempty"`
-
-	// GoVersion is the version of Go used for analyzing standard library
-	// vulnerabilities.
-	GoVersion string `json:"go_version,omitempty"`
-
-	// ScanLevel instructs vulncheck to analyze at a specific level of detail.
-	// Valid values include module, package and symbol.
-	ScanLevel ScanLevel `json:"scan_level,omitempty"`
-}
-
-type Progress struct {
-	// A time stamp for the message.
-	Timestamp *time.Time `json:"time,omitempty"`
-
-	// Message is the progress message.
-	Message string `json:"message,omitempty"`
-}
-
-// Vuln represents a single OSV entry.
-type Finding struct {
-	// OSV is the id of the detected vulnerability.
-	OSV string `json:"osv,omitempty"`
-
-	// FixedVersion is the module version where the vulnerability was
-	// fixed. This is empty if a fix is not available.
-	//
-	// If there are multiple fixed versions in the OSV report, this will
-	// be the fixed version in the latest range event for the OSV report.
-	//
-	// For example, if the range events are
-	// {introduced: 0, fixed: 1.0.0} and {introduced: 1.1.0}, the fixed version
-	// will be empty.
-	//
-	// For the stdlib, we will show the fixed version closest to the
-	// Go version that is used. For example, if a fix is available in 1.17.5 and
-	// 1.18.5, and the GOVERSION is 1.17.3, 1.17.5 will be returned as the
-	// fixed version.
-	FixedVersion string `json:"fixed_version,omitempty"`
-
-	// Trace contains an entry for each frame in the trace.
-	//
-	// Frames are sorted starting from the imported vulnerable symbol
-	// until the entry point. The first frame in Frames should match
-	// Symbol.
-	//
-	// In binary mode, trace will contain a single-frame with no position
-	// information.
-	//
-	// When a package is imported but no vulnerable symbol is called, the trace
-	// will contain a single-frame with no symbol or position information.
-	Trace []*Frame `json:"trace,omitempty"`
-}
-
-// Frame represents an entry in a finding trace.
-type Frame struct {
-	// Module is the module path of the module containing this symbol.
-	//
-	// Importable packages in the standard library will have the path "stdlib".
-	Module string `json:"module"`
-
-	// Version is the module version from the build graph.
-	Version string `json:"version,omitempty"`
-
-	// Package is the import path.
-	Package string `json:"package,omitempty"`
-
-	// Function is the function name.
-	Function string `json:"function,omitempty"`
-
-	// Receiver is the receiver type if the called symbol is a method.
-	//
-	// The client can create the final symbol name by
-	// prepending Receiver to FuncName.
-	Receiver string `json:"receiver,omitempty"`
-
-	// Position describes an arbitrary source position
-	// including the file, line, and column location.
-	// A Position is valid if the line number is > 0.
-	Position *Position `json:"position,omitempty"`
-}
-
-// Position is a copy of token.Position used to marshal/unmarshal
-// JSON correctly.
-type Position struct {
-	Filename string `json:"filename,omitempty"` // filename, if any
-	Offset   int    `json:"offset"`             // offset, starting at 0
-	Line     int    `json:"line"`               // line number, starting at 1
-	Column   int    `json:"column"`             // column number, starting at 1 (byte count)
-}
-
-type ScanLevel string
-
-const (
-	scanLevelModule  = "module"
-	scanLevelPackage = "package"
-	scanLevelSymbol  = "symbol"
-)
-
-func (l ScanLevel) WantSymbols() bool { return l == scanLevelSymbol }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/internal.go b/public-api/vendor/golang.org/x/vuln/internal/internal.go
index 64c5e8d5..8e6b7f5c 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/internal.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/internal.go
@@ -24,5 +24,9 @@ const (
 
 	// UnknownModulePath is a special module path for when we cannot work out
 	// the module for a package.
-	UnknownModulePath = "unknown"
+	UnknownModulePath = "unknown-module"
+
+	// UnknownPackagePath is a special package path for when we cannot work out
+	// the packagUnknownModulePath = "unknown"
+	UnknownPackagePath = "unknown-package"
 )
diff --git a/public-api/vendor/golang.org/x/vuln/internal/openvex/handler.go b/public-api/vendor/golang.org/x/vuln/internal/openvex/handler.go
new file mode 100644
index 00000000..a2d32829
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/openvex/handler.go
@@ -0,0 +1,261 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"io"
+	"slices"
+	"time"
+
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+)
+
+type findingLevel int
+
+const (
+	invalid findingLevel = iota
+	required
+	imported
+	called
+)
+
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	sbom *govulncheck.SBOM
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(cfg *govulncheck.Config) error {
+	h.cfg = cfg
+	return nil
+}
+
+func (h *handler) Progress(progress *govulncheck.Progress) error {
+	return nil
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	h.sbom = s
+	return nil
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// foundAtLevel returns the level at which a specific finding is present in the
+// scanned product.
+func foundAtLevel(f *govulncheck.Finding) findingLevel {
+	frame := f.Trace[0]
+	if frame.Function != "" {
+		return called
+	}
+	if frame.Package != "" {
+		return imported
+	}
+	return required
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is at the same level of precision.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print the vex json to w.
+// This is needed as vex is not streamed.
+func (h *handler) Flush() error {
+	doc := toVex(h)
+	out, err := json.MarshalIndent(doc, "", "  ")
+	if err != nil {
+		return err
+	}
+	_, err = h.w.Write(out)
+	return err
+}
+
+func toVex(h *handler) Document {
+	doc := Document{
+		Context:    ContextURI,
+		Author:     DefaultAuthor,
+		Timestamp:  time.Now().UTC(),
+		Version:    1,
+		Tooling:    Tooling,
+		Statements: statements(h),
+	}
+
+	id := hashVex(doc)
+	doc.ID = "govulncheck/vex:" + id
+	return doc
+}
+
+// Given a slice of findings, returns those findings as a set of subcomponents
+// that are unique per the vulnerable artifact's PURL.
+func subcomponentSet(findings []*govulncheck.Finding) []Component {
+	var scs []Component
+	seen := make(map[string]bool)
+	for _, f := range findings {
+		purl := purlFromFinding(f)
+		if !seen[purl] {
+			scs = append(scs, Component{
+				ID: purlFromFinding(f),
+			})
+			seen[purl] = true
+		}
+	}
+	return scs
+}
+
+// statements combines all OSVs found by govulncheck and generates the list of
+// vex statements with the proper affected level and justification to match the
+// openVex specification.
+func statements(h *handler) []Statement {
+	var scanLevel findingLevel
+	switch h.cfg.ScanLevel {
+	case govulncheck.ScanLevelModule:
+		scanLevel = required
+	case govulncheck.ScanLevelPackage:
+		scanLevel = imported
+	case govulncheck.ScanLevelSymbol:
+		scanLevel = called
+	}
+
+	var statements []Statement
+	for id, osv := range h.osvs {
+		// if there are no findings emitted for a given OSV that means that
+		// the vulnerable module is not required at a vulnerable version.
+		if len(h.findings[id]) == 0 {
+			continue
+		}
+		description := osv.Summary
+		if description == "" {
+			description = osv.Details
+		}
+
+		s := Statement{
+			Vulnerability: Vulnerability{
+				ID:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", id),
+				Name:        id,
+				Description: description,
+				Aliases:     osv.Aliases,
+			},
+			Products: []Product{
+				{
+					Component:     Component{ID: DefaultPID},
+					Subcomponents: subcomponentSet(h.findings[id]),
+				},
+			},
+		}
+
+		// Findings are guaranteed to be at the same level, so we can just check the first element
+		fLevel := foundAtLevel(h.findings[id][0])
+		if fLevel >= scanLevel {
+			s.Status = StatusAffected
+		} else {
+			s.Status = StatusNotAffected
+			s.ImpactStatement = Impact
+			s.Justification = JustificationNotPresent
+			// We only reach this case if running in symbol mode
+			if fLevel == imported {
+				s.Justification = JustificationNotExecuted
+			}
+		}
+		statements = append(statements, s)
+	}
+
+	slices.SortFunc(statements, func(a, b Statement) int {
+		if a.Vulnerability.ID > b.Vulnerability.ID {
+			return 1
+		}
+		if a.Vulnerability.ID < b.Vulnerability.ID {
+			return -1
+		}
+		// this should never happen in practice, since statements are being
+		// populated from a map with the vulnerability IDs as keys
+		return 0
+	})
+	return statements
+}
+
+func hashVex(doc Document) string {
+	// json.Marshal should never error here (because of the structure of Document).
+	// If an error does occur, it won't be a jsonerror, but instead a panic
+	d := Document{
+		Context:    doc.Context,
+		ID:         doc.ID,
+		Author:     doc.Author,
+		Version:    doc.Version,
+		Tooling:    doc.Tooling,
+		Statements: doc.Statements,
+	}
+	out, err := json.Marshal(d)
+	if err != nil {
+		panic(err)
+	}
+	return fmt.Sprintf("%x", sha256.Sum256(out))
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/openvex/purl.go b/public-api/vendor/golang.org/x/vuln/internal/openvex/purl.go
new file mode 100644
index 00000000..fc1cea9c
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/openvex/purl.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openvex
+
+import (
+	"net/url"
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// The PURL is printed as: pkg:golang/MODULE_PATH@VERSION
+// Conceptually there is no namespace and the name is entirely defined by
+// the module path. See https://github.com/package-url/purl-spec/issues/63
+// for further disucssion.
+
+const suffix = "pkg:golang/"
+
+type purl struct {
+	name    string
+	version string
+}
+
+func (p *purl) String() string {
+	var b strings.Builder
+	b.WriteString(suffix)
+	b.WriteString(url.PathEscape(p.name))
+	if p.version != "" {
+		b.WriteString("@")
+		b.WriteString(p.version)
+	}
+	return b.String()
+}
+
+// purlFromFinding takes a govulncheck finding and generates a purl to the
+// vulnerable dependency.
+func purlFromFinding(f *govulncheck.Finding) string {
+	purl := purl{
+		name:    f.Trace[0].Module,
+		version: f.Trace[0].Version,
+	}
+
+	return purl.String()
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/openvex/vex.go b/public-api/vendor/golang.org/x/vuln/internal/openvex/vex.go
new file mode 100644
index 00000000..18779f70
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/openvex/vex.go
@@ -0,0 +1,113 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vex defines the Vulnerability EXchange Format (VEX) types
+// supported by govulncheck.
+//
+// These types match the OpenVEX standard. See https://github.com/openvex for
+// more information on VEX and OpenVEX.
+//
+// This is intended to be the minimimal amount of information required to output
+// a complete VEX document according to the specification.
+package openvex
+
+import "time"
+
+const (
+	ContextURI = "https://openvex.dev/ns/v0.2.0"
+	Tooling    = "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Impact     = "Govulncheck determined that the vulnerable code isn't called"
+
+	DefaultAuthor = "Unknown Author"
+	DefaultPID    = "Unknown Product"
+
+	// The following are defined by the VEX standard.
+	StatusAffected    = "affected"
+	StatusNotAffected = "not_affected"
+
+	// The following are defined by the VEX standard.
+	JustificationNotExecuted = "vulnerable_code_not_in_execute_path"
+	JustificationNotPresent  = "vulnerable_code_not_present"
+)
+
+// Document is the top-level struct for a VEX document.
+type Document struct {
+	// Context is an IRI pointing to the version of openVEX being used by the doc
+	// For govulncheck, it will always be https://openvex.dev/ns/v0.2.0
+	Context string `json:"@context,omitempty"`
+
+	// ID is the identifying string for the VEX document.
+	// govulncheck/vex-[content-based-hash]
+	ID string `json:"@id,omitempty"`
+
+	// Author is the identifier for the author of the VEX statement.
+	// Govulncheck will leave this field default (Unknown author) to be filled in by the user.
+	Author string `json:"author,omitempty"`
+
+	// Timestamp defines the time at which the document was issued.
+	Timestamp time.Time `json:"timestamp,omitempty"`
+
+	// Version is the document version. For govulncheck's output, this will always be 1.
+	Version int `json:"version,omitempty"`
+
+	// Tooling expresses how the VEX document and contained VEX statements were
+	// generated. In this case, it will always be:
+	// "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
+	Tooling string `json:"tooling,omitempty"`
+
+	// Statements are all statements for a given govulncheck output.
+	// Each OSV emitted by govulncheck will have a corresponding statement.
+	Statements []Statement `json:"statements,omitempty"`
+}
+
+// Statement conveys a single status for a single vulnerability for one or more products.
+type Statement struct {
+	// Vulnerability is the vuln being referenced by the statement.
+	Vulnerability Vulnerability `json:"vulnerability,omitempty"`
+
+	// Products are the products associated with the given vulnerability in the statement.
+	Products []Product `json:"products,omitempty"`
+
+	// The status of the vulnerability. Will be either not_affected or affected for govulncheck.
+	Status string `json:"status,omitempty"`
+
+	// If the status is not_affected, this must be filled. The official VEX justification that
+	// best matches govulncheck's vuln filtering is "vulnerable_code_not_in_execute_path"
+	Justification string `json:"justification,omitempty"`
+
+	// If the status is not_affected, this must be filled. For govulncheck, this will always be:
+	// "Govulncheck determined that the vulnerable code isn't called"
+	ImpactStatement string `json:"impact_statement,omitempty"`
+}
+
+// Vulnerability captures a vulnerability and its identifiers/aliases.
+type Vulnerability struct {
+	// ID is a URI that in govulncheck's case points to the govulndb link for the vulnerability.
+	// I.E. https://pkg.go.dev/vuln/GO-2024-2497
+	ID string `json:"@id,omitempty"`
+
+	// Name is the main identifier for the vulnerability (GO-YYYY-XXXX)
+	Name string `json:"name,omitempty"`
+
+	// Description is a short text description of the vulnerability.
+	// It will be populated from the 'summary' field of the vuln's OSV if it exists,
+	// and the 'description' field of the osv if a summary isn't present.
+	Description string `json:"description,omitempty"`
+
+	// Aliases a list of identifiers that other systems are using to track the vulnerability.
+	// I.E. GHSA or CVE ids.
+	Aliases []string `json:"aliases,omitempty"`
+}
+
+// Product identifies the products associated with the given vuln.
+type Product struct {
+	// The main product ID will remian default for now.
+	Component
+	// The subcomponent ID will be a PURL to the vulnerable dependency.
+	Subcomponents []Component `json:"subcomponents,omitempty"`
+}
+
+type Component struct {
+	ID string `json:"@id,omitempty"`
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/osv/osv.go b/public-api/vendor/golang.org/x/vuln/internal/osv/osv.go
index 3fa3a086..0bb44b27 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/osv/osv.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/osv/osv.go
@@ -97,7 +97,7 @@ type Range struct {
 	Events []RangeEvent `json:"events"`
 }
 
-// Reference type is a reference (link) type.
+// ReferenceType is a reference (link) type.
 type ReferenceType string
 
 const (
@@ -235,4 +235,6 @@ type DatabaseSpecific struct {
 	// The URL of the Go advisory for this vulnerability, of the form
 	// "https://pkg.go.dev/GO-YYYY-XXXX".
 	URL string `json:"url,omitempty"`
+	// The review status of this report (UNREVIEWED or REVIEWED).
+	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/osv/review_status.go b/public-api/vendor/golang.org/x/vuln/internal/osv/review_status.go
new file mode 100644
index 00000000..7185e184
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/osv/review_status.go
@@ -0,0 +1,67 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package osv
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type ReviewStatus int
+
+const (
+	ReviewStatusUnknown ReviewStatus = iota
+	ReviewStatusUnreviewed
+	ReviewStatusReviewed
+)
+
+var statusStrs = []string{
+	ReviewStatusUnknown:    "",
+	ReviewStatusUnreviewed: "UNREVIEWED",
+	ReviewStatusReviewed:   "REVIEWED",
+}
+
+func (r ReviewStatus) String() string {
+	if !r.IsValid() {
+		return fmt.Sprintf("INVALID(%d)", r)
+	}
+	return statusStrs[r]
+}
+
+func ReviewStatusValues() []string {
+	return statusStrs[1:]
+}
+
+func (r ReviewStatus) IsValid() bool {
+	return int(r) >= 0 && int(r) < len(statusStrs)
+}
+
+func ToReviewStatus(s string) (ReviewStatus, bool) {
+	for stat, str := range statusStrs {
+		if s == str {
+			return ReviewStatus(stat), true
+		}
+	}
+	return 0, false
+}
+
+func (r ReviewStatus) MarshalJSON() ([]byte, error) {
+	if !r.IsValid() {
+		return nil, fmt.Errorf("MarshalJSON: unrecognized review status: %d", r)
+	}
+	return json.Marshal(r.String())
+}
+
+func (r *ReviewStatus) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if rs, ok := ToReviewStatus(s); ok {
+		*r = rs
+		return nil
+	}
+	return fmt.Errorf("UnmarshalJSON: unrecognized review status: %s", s)
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/sarif/handler.go b/public-api/vendor/golang.org/x/vuln/internal/sarif/handler.go
new file mode 100644
index 00000000..d9e585b7
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/sarif/handler.go
@@ -0,0 +1,409 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"path/filepath"
+	"sort"
+
+	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
+)
+
+// handler for sarif output.
+type handler struct {
+	w    io.Writer
+	cfg  *govulncheck.Config
+	osvs map[string]*osv.Entry
+	// findings contains same-level findings for an
+	// OSV at the most precise level of granularity
+	// available. This means, for instance, that if
+	// an osv is indeed called, then all findings for
+	// the osv will have call stack info.
+	findings map[string][]*govulncheck.Finding
+}
+
+func NewHandler(w io.Writer) *handler {
+	return &handler{
+		w:        w,
+		osvs:     make(map[string]*osv.Entry),
+		findings: make(map[string][]*govulncheck.Finding),
+	}
+}
+
+func (h *handler) Config(c *govulncheck.Config) error {
+	h.cfg = c
+	return nil
+}
+
+func (h *handler) Progress(p *govulncheck.Progress) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) SBOM(s *govulncheck.SBOM) error {
+	return nil // not needed by sarif
+}
+
+func (h *handler) OSV(e *osv.Entry) error {
+	h.osvs[e.ID] = e
+	return nil
+}
+
+// moreSpecific favors a call finding over a non-call
+// finding and a package finding over a module finding.
+func moreSpecific(f1, f2 *govulncheck.Finding) int {
+	if len(f1.Trace) > 1 && len(f2.Trace) > 1 {
+		// Both are call stack findings.
+		return 0
+	}
+	if len(f1.Trace) > 1 {
+		return -1
+	}
+	if len(f2.Trace) > 1 {
+		return 1
+	}
+
+	fr1, fr2 := f1.Trace[0], f2.Trace[0]
+	if fr1.Function != "" && fr2.Function == "" {
+		return -1
+	}
+	if fr1.Function == "" && fr2.Function != "" {
+		return 1
+	}
+	if fr1.Package != "" && fr2.Package == "" {
+		return -1
+	}
+	if fr1.Package == "" && fr2.Package != "" {
+		return -1
+	}
+	return 0 // findings always have module info
+}
+
+func (h *handler) Finding(f *govulncheck.Finding) error {
+	fs := h.findings[f.OSV]
+	if len(fs) == 0 {
+		fs = []*govulncheck.Finding{f}
+	} else {
+		if ms := moreSpecific(f, fs[0]); ms == -1 {
+			// The new finding is more specific, so we need
+			// to erase existing findings and add the new one.
+			fs = []*govulncheck.Finding{f}
+		} else if ms == 0 {
+			// The new finding is equal to an existing one and
+			// because of the invariant on h.findings, it is
+			// also equal to all existing ones.
+			fs = append(fs, f)
+		}
+		// Otherwise, the new finding is at a less precise level.
+	}
+	h.findings[f.OSV] = fs
+	return nil
+}
+
+// Flush is used to print out to w the sarif json output.
+// This is needed as sarif is not streamed.
+func (h *handler) Flush() error {
+	sLog := toSarif(h)
+	s, err := json.MarshalIndent(sLog, "", "  ")
+	if err != nil {
+		return err
+	}
+	h.w.Write(s)
+	return nil
+}
+
+func toSarif(h *handler) Log {
+	cfg := h.cfg
+	r := Run{
+		Tool: Tool{
+			Driver: Driver{
+				Name:           cfg.ScannerName,
+				Version:        cfg.ScannerVersion,
+				InformationURI: "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
+				Properties:     *cfg,
+				Rules:          rules(h),
+			},
+		},
+		Results: results(h),
+	}
+
+	return Log{
+		Version: "2.1.0",
+		Schema:  "https://json.schemastore.org/sarif-2.1.0.json",
+		Runs:    []Run{r},
+	}
+}
+
+func rules(h *handler) []Rule {
+	rs := make([]Rule, 0, len(h.findings)) // must not be nil
+	for id := range h.findings {
+		osv := h.osvs[id]
+		// s is either summary if it exists, or details
+		// otherwise. Govulncheck text does the same.
+		s := osv.Summary
+		if s == "" {
+			s = osv.Details
+		}
+		rs = append(rs, Rule{
+			ID:               osv.ID,
+			ShortDescription: Description{Text: fmt.Sprintf("[%s] %s", osv.ID, s)},
+			FullDescription:  Description{Text: s},
+			HelpURI:          fmt.Sprintf("https://pkg.go.dev/vuln/%s", osv.ID),
+			Help:             Description{Text: osv.Details},
+			Properties:       RuleTags{Tags: tags(osv)},
+		})
+	}
+	sort.SliceStable(rs, func(i, j int) bool { return rs[i].ID < rs[j].ID })
+	return rs
+}
+
+// tags returns an slice of zero or
+// more aliases of o.
+func tags(o *osv.Entry) []string {
+	if len(o.Aliases) > 0 {
+		return o.Aliases
+	}
+	return []string{} // must not be nil
+}
+
+func results(h *handler) []Result {
+	results := make([]Result, 0, len(h.findings)) // must not be nil
+	for osv, fs := range h.findings {
+		var locs []Location
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			// Attach result to the go.mod file for source analysis.
+			// But there is no such place for binaries.
+			locs = []Location{{PhysicalLocation: PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       "go.mod",
+					URIBaseID: SrcRootID,
+				},
+				Region: Region{StartLine: 1}, // for now, point to the first line
+			},
+				Message: Description{Text: fmt.Sprintf("Findings for vulnerability %s", osv)}, // not having a message here results in an invalid sarif
+			}}
+		}
+
+		res := Result{
+			RuleID:    osv,
+			Level:     level(fs[0], h.cfg),
+			Message:   Description{Text: resultMessage(fs, h.cfg)},
+			Stacks:    stacks(h, fs),
+			CodeFlows: codeFlows(h, fs),
+			Locations: locs,
+		}
+		results = append(results, res)
+	}
+	sort.SliceStable(results, func(i, j int) bool { return results[i].RuleID < results[j].RuleID }) // for deterministic output
+	return results
+}
+
+func resultMessage(findings []*govulncheck.Finding, cfg *govulncheck.Config) string {
+	// We can infer the findings' level by just looking at the
+	// top trace frame of any finding.
+	frame := findings[0].Trace[0]
+	uniqueElems := make(map[string]bool)
+	if frame.Function == "" && frame.Package == "" { // module level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Module] = true
+		}
+	} else { // symbol and package level findings
+		for _, f := range findings {
+			uniqueElems[f.Trace[0].Package] = true
+		}
+	}
+	var elems []string
+	for e := range uniqueElems {
+		elems = append(elems, e)
+	}
+	sort.Strings(elems)
+
+	l := len(elems)
+	elemList := list(elems)
+	main, addition := "", ""
+	const runCallAnalysis = "Run the call-level analysis to understand whether your code actually calls the vulnerabilities."
+	switch {
+	case frame.Function != "":
+		main = fmt.Sprintf("calls vulnerable functions in %d package%s (%s).", l, choose("", "s", l == 1), elemList)
+	case frame.Package != "":
+		main = fmt.Sprintf("imports %d vulnerable package%s (%s)", l, choose("", "s", l == 1), elemList)
+		addition = choose(", but doesn’t appear to call any of the vulnerable symbols.", ". "+runCallAnalysis, cfg.ScanLevel.WantSymbols())
+	default:
+		main = fmt.Sprintf("depends on %d vulnerable module%s (%s)", l, choose("", "s", l == 1), elemList)
+		informational := ", but doesn't appear to " + choose("call", "import", cfg.ScanLevel.WantSymbols()) + " any of the vulnerable symbols."
+		addition = choose(informational, ". "+runCallAnalysis, cfg.ScanLevel.WantPackages())
+	}
+
+	return fmt.Sprintf("Your code %s%s", main, addition)
+}
+
+const (
+	errorLevel         = "error"
+	warningLevel       = "warning"
+	informationalLevel = "note"
+)
+
+func level(f *govulncheck.Finding, cfg *govulncheck.Config) string {
+	fr := f.Trace[0]
+	switch {
+	case cfg.ScanLevel.WantSymbols():
+		if fr.Function != "" {
+			return errorLevel
+		}
+		if fr.Package != "" {
+			return warningLevel
+		}
+		return informationalLevel
+	case cfg.ScanLevel.WantPackages():
+		if fr.Package != "" {
+			return errorLevel
+		}
+		return warningLevel
+	default:
+		return errorLevel
+	}
+}
+
+func stacks(h *handler, fs []*govulncheck.Finding) []Stack {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	var stacks []Stack
+	for _, f := range fs {
+		stacks = append(stacks, stack(h, f))
+	}
+	// Sort stacks for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(stacks, func(i, j int) bool { return stacks[i].Message.Text < stacks[j].Message.Text })
+	return stacks
+}
+
+// stack transforms call stack in f to a sarif stack.
+func stack(h *handler, f *govulncheck.Finding) Stack {
+	trace := f.Trace
+	top := trace[len(trace)-1] // belongs to top level module
+
+	frames := make([]Frame, 0, len(trace)) // must not be nil
+	for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+		frame := trace[i]
+		pos := govulncheck.Position{Line: 1, Column: 1}
+		if frame.Position != nil {
+			pos = *frame.Position
+		}
+
+		sf := Frame{
+			Module:   frame.Module + "@" + frame.Version,
+			Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+		}
+		file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+		if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+			sf.Location.PhysicalLocation = PhysicalLocation{
+				ArtifactLocation: ArtifactLocation{
+					URI:       file,
+					URIBaseID: base,
+				},
+				Region: Region{
+					StartLine:   pos.Line,
+					StartColumn: pos.Column,
+				},
+			}
+		}
+		frames = append(frames, sf)
+	}
+
+	return Stack{
+		Frames:  frames,
+		Message: Description{Text: fmt.Sprintf("A call stack for vulnerable function %s", symbol(trace[0]))},
+	}
+}
+
+func codeFlows(h *handler, fs []*govulncheck.Finding) []CodeFlow {
+	if fs[0].Trace[0].Function == "" { // not call level findings
+		return nil
+	}
+
+	// group call stacks per symbol. There should
+	// be one call stack currently per symbol, but
+	// this might change in the future.
+	m := make(map[govulncheck.Frame][]*govulncheck.Finding)
+	for _, f := range fs {
+		// fr.Position is currently the position
+		// of the definition of the vuln symbol
+		fr := *f.Trace[0]
+		m[fr] = append(m[fr], f)
+	}
+
+	var codeFlows []CodeFlow
+	for fr, fs := range m {
+		tfs := threadFlows(h, fs)
+		codeFlows = append(codeFlows, CodeFlow{
+			ThreadFlows: tfs,
+			// TODO: should we instead show the message from govulncheck text output?
+			Message: Description{Text: fmt.Sprintf("A summarized code flow for vulnerable function %s", symbol(&fr))},
+		})
+	}
+	// Sort flows for deterministic output. We sort by message
+	// which is effectively sorting by full symbol name. The
+	// performance should not be an issue here.
+	sort.SliceStable(codeFlows, func(i, j int) bool { return codeFlows[i].Message.Text < codeFlows[j].Message.Text })
+	return codeFlows
+}
+
+func threadFlows(h *handler, fs []*govulncheck.Finding) []ThreadFlow {
+	tfs := make([]ThreadFlow, 0, len(fs)) // must not be nil
+	for _, f := range fs {
+		trace := traces.Compact(f)
+		top := trace[len(trace)-1] // belongs to top level module
+
+		var tf []ThreadFlowLocation
+		for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
+			// TODO: should we, similar to govulncheck text output, only
+			// mention three elements of the compact trace?
+			frame := trace[i]
+			pos := govulncheck.Position{Line: 1, Column: 1}
+			if frame.Position != nil {
+				pos = *frame.Position
+			}
+
+			tfl := ThreadFlowLocation{
+				Module:   frame.Module + "@" + frame.Version,
+				Location: Location{Message: Description{Text: symbol(frame)}}, // show the (full) symbol name
+			}
+			file, base := fileURIInfo(pos.Filename, top.Module, frame.Module, frame.Version)
+			if h.cfg.ScanMode != govulncheck.ScanModeBinary {
+				tfl.Location.PhysicalLocation = PhysicalLocation{
+					ArtifactLocation: ArtifactLocation{
+						URI:       file,
+						URIBaseID: base,
+					},
+					Region: Region{
+						StartLine:   pos.Line,
+						StartColumn: pos.Column,
+					},
+				}
+			}
+			tf = append(tf, tfl)
+		}
+		tfs = append(tfs, ThreadFlow{Locations: tf})
+	}
+	return tfs
+}
+
+func fileURIInfo(filename, top, module, version string) (string, string) {
+	if top == module {
+		return filename, SrcRootID
+	}
+	if module == internal.GoStdModulePath {
+		return filename, GoRootID
+	}
+	return filepath.ToSlash(filepath.Join(module+"@"+version, filename)), GoModCacheID
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go b/public-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go
new file mode 100644
index 00000000..934ade8b
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/sarif/sarif.go
@@ -0,0 +1,213 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sarif defines Static Analysis Results Interchange Format
+// (SARIF) types supported by govulncheck.
+//
+// The implementation covers the subset of the specification available
+// at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif.
+//
+// The sarif encoding models govulncheck findings as Results. Each
+// Result encodes findings for a unique OSV entry at the most precise
+// detected level only. CodeFlows summarize call stacks, similar to govulncheck
+// textual output, while Stacks contain call stack information verbatim.
+//
+// The result Levels are defined by the govulncheck.ScanLevel and the most
+// precise level at which the finding was detected. Result error is produced
+// when the finding level matches the user desired level of scan precision;
+// all other finding levels are then classified as progressively weaker.
+// For instance, if the user specified symbol scan level and govulncheck
+// detected a use of a vulnerable symbol, then the Result will have error
+// Level. If the symbol was not used but its package was imported, then the
+// Result Level is warning, and so on.
+//
+// Each Result is attached to the first line of the go.mod file. Other
+// ArtifactLocations are paths relative to their enclosing modules.
+// Similar to JSON output format, this makes govulncheck sarif locations
+// portable.
+//
+// The relative paths in PhysicalLocations also come with a URIBaseID offset.
+// Paths for the source module analyzed, the Go standard library, and third-party
+// dependencies are relative to %SRCROOT%, %GOROOT%, and %GOMODCACHE% offsets,
+// resp. We note that the URIBaseID offsets are not explicitly defined in
+// the sarif output. It is the clients responsibility to set them to resolve
+// paths at their local machines.
+//
+// All paths use "/" delimiter for portability.
+//
+// Properties field of a Tool.Driver is a govulncheck.Config used for the
+// invocation of govulncheck producing the Results. Properties field of
+// a Rule contains information on CVE and GHSA aliases for the corresponding
+// rule OSV. Clients can use this information to, say, suppress and filter
+// vulnerabilities.
+//
+// Please see the definition of types below for more information.
+package sarif
+
+import "golang.org/x/vuln/internal/govulncheck"
+
+// Log is the top-level SARIF object encoded in UTF-8.
+type Log struct {
+	// Version should always be "2.1.0"
+	Version string `json:"version,omitempty"`
+
+	// Schema should always be "https://json.schemastore.org/sarif-2.1.0.json"
+	Schema string `json:"$schema,omitempty"`
+
+	// Runs describes executions of static analysis tools. For govulncheck,
+	// there will be only one run object.
+	Runs []Run `json:"runs,omitempty"`
+}
+
+// Run summarizes results of a single invocation of a static analysis tool,
+// in this case govulncheck.
+type Run struct {
+	Tool Tool `json:"tool,omitempty"`
+	// Results contain govulncheck findings. There should be exactly one
+	// Result per a detected use of an OSV.
+	Results []Result `json:"results"`
+}
+
+// Tool captures information about govulncheck analysis that was run.
+type Tool struct {
+	Driver Driver `json:"driver,omitempty"`
+}
+
+// Driver provides details about the govulncheck binary being executed.
+type Driver struct {
+	// Name is "govulncheck"
+	Name string `json:"name,omitempty"`
+	// Version is the govulncheck version
+	Version string `json:"semanticVersion,omitempty"`
+	// InformationURI points to the description of govulncheck tool
+	InformationURI string `json:"informationUri,omitempty"`
+	// Properties are govulncheck run metadata, such as vuln db, Go version, etc.
+	Properties govulncheck.Config `json:"properties,omitempty"`
+
+	Rules []Rule `json:"rules"`
+}
+
+// Rule corresponds to the static analysis rule/analyzer that
+// produces findings. For govulncheck, rules are OSVs.
+type Rule struct {
+	// ID is OSV.ID
+	ID               string      `json:"id,omitempty"`
+	ShortDescription Description `json:"shortDescription,omitempty"`
+	FullDescription  Description `json:"fullDescription,omitempty"`
+	Help             Description `json:"help,omitempty"`
+	HelpURI          string      `json:"helpUri,omitempty"`
+	// Properties contain OSV.Aliases (CVEs and GHSAs) as tags.
+	// Consumers of govulncheck SARIF can use these tags to filter
+	// results.
+	Properties RuleTags `json:"properties,omitempty"`
+}
+
+// RuleTags defines properties.tags.
+type RuleTags struct {
+	Tags []string `json:"tags"`
+}
+
+// Description is a text in its raw or markdown form.
+type Description struct {
+	Text     string `json:"text,omitempty"`
+	Markdown string `json:"markdown,omitempty"`
+}
+
+// Result is a set of govulncheck findings for an OSV. For call stack
+// mode, it will contain call stacks for the OSV. There is exactly
+// one Result per detected OSV. Only findings at the most precise
+// detected level appear in the Result. For instance, if there are
+// symbol findings for an OSV, those findings will be in the Result,
+// but not the package and module level findings for the same OSV.
+type Result struct {
+	// RuleID is the Rule.ID/OSV producing the finding.
+	RuleID string `json:"ruleId,omitempty"`
+	// Level is one of "error", "warning", and "note".
+	Level string `json:"level,omitempty"`
+	// Message explains the overall findings.
+	Message Description `json:"message,omitempty"`
+	// Locations to which the findings are associated. Always
+	// a single location pointing to the first line of the go.mod
+	// file. The path to the file is "go.mod".
+	Locations []Location `json:"locations,omitempty"`
+	// CodeFlows summarize call stacks produced by govulncheck.
+	CodeFlows []CodeFlow `json:"codeFlows,omitempty"`
+	// Stacks encode call stacks produced by govulncheck.
+	Stacks []Stack `json:"stacks,omitempty"`
+}
+
+// CodeFlow summarizes a detected offending flow of information in terms of
+// code locations. More precisely, it can contain several related information
+// flows, keeping them together. In govulncheck, those can be all call stacks
+// for, say, a particular symbol or package.
+type CodeFlow struct {
+	// ThreadFlows is effectively a set of related information flows.
+	ThreadFlows []ThreadFlow `json:"threadFlows"`
+	Message     Description  `json:"message,omitempty"`
+}
+
+// ThreadFlow encodes an information flow as a sequence of locations.
+// For govulncheck, it can encode a call stack.
+type ThreadFlow struct {
+	Locations []ThreadFlowLocation `json:"locations,omitempty"`
+}
+
+type ThreadFlowLocation struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module string `json:"module,omitempty"`
+	// Location also contains a Message field.
+	Location Location `json:"location,omitempty"`
+}
+
+// Stack is a sequence of frames and can encode a govulncheck call stack.
+type Stack struct {
+	Message Description `json:"message,omitempty"`
+	Frames  []Frame     `json:"frames"`
+}
+
+// Frame is effectively a module location. It can also contain thread and
+// parameter info, but those are not needed for govulncheck.
+type Frame struct {
+	// Module is module information in the form @.
+	//  can be empty when the module version is not known as
+	// with, say, the source module analyzed.
+	Module   string   `json:"module,omitempty"`
+	Location Location `json:"location,omitempty"`
+}
+
+// Location is currently a physical location annotated with a message.
+type Location struct {
+	PhysicalLocation PhysicalLocation `json:"physicalLocation,omitempty"`
+	Message          Description      `json:"message,omitempty"`
+}
+
+type PhysicalLocation struct {
+	ArtifactLocation ArtifactLocation `json:"artifactLocation,omitempty"`
+	Region           Region           `json:"region,omitempty"`
+}
+
+const (
+	SrcRootID    = "%SRCROOT%"
+	GoRootID     = "%GOROOT%"
+	GoModCacheID = "%GOMODCACHE%"
+)
+
+// ArtifactLocation is a path to an offending file.
+type ArtifactLocation struct {
+	// URI is a path relative to URIBaseID.
+	URI string `json:"uri,omitempty"`
+	// URIBaseID is offset for URI, one of %SRCROOT%, %GOROOT%,
+	// and %GOMODCACHE%.
+	URIBaseID string `json:"uriBaseId,omitempty"`
+}
+
+// Region is a target region within a file.
+type Region struct {
+	StartLine   int `json:"startLine,omitempty"`
+	StartColumn int `json:"startColumn,omitempty"`
+	EndLine     int `json:"endLine,omitempty"`
+	EndColumn   int `json:"endColumn,omitempty"`
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/sarif/utils.go b/public-api/vendor/golang.org/x/vuln/internal/sarif/utils.go
new file mode 100644
index 00000000..045cac76
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/sarif/utils.go
@@ -0,0 +1,46 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sarif
+
+import (
+	"strings"
+
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+func choose(s1, s2 string, cond bool) string {
+	if cond {
+		return s1
+	}
+	return s2
+}
+
+func list(elems []string) string {
+	l := len(elems)
+	if l == 0 {
+		return ""
+	}
+	if l == 1 {
+		return elems[0]
+	}
+
+	cList := strings.Join(elems[:l-1], ", ")
+	return cList + choose("", ",", l == 2) + " and " + elems[l-1]
+}
+
+// symbol is simplified adaptation of internal/scan/symbol.
+func symbol(fr *govulncheck.Frame) string {
+	if fr.Function == "" {
+		return ""
+	}
+	sym := strings.Split(fr.Function, "$")[0]
+	if fr.Receiver != "" {
+		sym = fr.Receiver + "." + sym
+	}
+	if fr.Package != "" {
+		sym = fr.Package + "." + sym
+	}
+	return sym
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/binary.go b/public-api/vendor/golang.org/x/vuln/internal/scan/binary.go
index 76b17f75..5cc8f6ba 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/binary.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/binary.go
@@ -2,93 +2,109 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package scan
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
+	"errors"
 	"os"
-	"strings"
-	"unicode"
+	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
-// runBinary detects presence of vulnerable symbols in an executable.
-func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) error {
-	var exe *os.File
-	exe, err := os.Open(cfg.patterns[0])
+// runBinary detects presence of vulnerable symbols in an executable or its minimal blob representation.
+func runBinary(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
 	if err != nil {
 		return err
 	}
-	defer exe.Close()
 
 	p := &govulncheck.Progress{Message: binaryProgressMessage}
 	if err := handler.Progress(p); err != nil {
 		return err
 	}
-	vr, err := binary(ctx, exe, &cfg.Config, client)
-	if err != nil {
-		return fmt.Errorf("govulncheck: %v", err)
-	}
-	callstacks := binaryCallstacks(vr)
-	return emitResult(handler, vr, callstacks)
+	return vulncheck.Binary(ctx, handler, bin, &cfg.Config, client)
 }
 
-func binaryCallstacks(vr *vulncheck.Result) map[*vulncheck.Vuln]vulncheck.CallStack {
-	callstacks := map[*vulncheck.Vuln]vulncheck.CallStack{}
-	for _, vv := range uniqueVulns(vr.Vulns) {
-		f := &vulncheck.FuncNode{Package: vv.ImportSink, Name: vv.Symbol}
-		parts := strings.Split(vv.Symbol, ".")
-		if len(parts) != 1 {
-			f.RecvType = parts[0]
-			f.Name = parts[1]
+func createBin(path string) (*vulncheck.Bin, error) {
+	// First check if the path points to a Go binary. Otherwise, blob
+	// parsing might json decode a Go binary which takes time.
+	//
+	// TODO(#64716): use fingerprinting to make this precise, clean, and fast.
+	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(path)
+	if err == nil {
+		var main *packages.Module
+		if bi.Main.Path != "" {
+			main = &packages.Module{
+				Path:    bi.Main.Path,
+				Version: bi.Main.Version,
+			}
 		}
-		callstacks[vv] = vulncheck.CallStack{vulncheck.StackEntry{Function: f}}
+
+		return &vulncheck.Bin{
+			Path:       bi.Path,
+			Main:       main,
+			Modules:    mods,
+			PkgSymbols: packageSymbols,
+			GoVersion:  bi.GoVersion,
+			GOOS:       findSetting("GOOS", bi),
+			GOARCH:     findSetting("GOARCH", bi),
+		}, nil
+	}
+
+	// Otherwise, see if the path points to a valid blob.
+	bin := parseBlob(path)
+	if bin != nil {
+		return bin, nil
 	}
-	return callstacks
+
+	return nil, errors.New("unrecognized binary format")
 }
 
-// uniqueVulns does for binary mode what uniqueCallStack does for source mode.
-// It tries not to report redundant symbols. Since there are no call stacks in
-// binary mode, the following approximate approach is used. Do not report unexported
-// symbols for a  triple if there are some exported symbols.
-// Otherwise, report all unexported symbols to avoid not reporting anything.
-func uniqueVulns(vulns []*vulncheck.Vuln) []*vulncheck.Vuln {
-	type key struct {
-		id  string
-		pkg string
-		mod string
+// parseBlob extracts vulncheck.Bin from a valid blob at path.
+// If it cannot recognize a valid blob, returns nil.
+func parseBlob(path string) *vulncheck.Bin {
+	from, err := os.Open(path)
+	if err != nil {
+		return nil
 	}
-	hasExported := make(map[key]bool)
-	for _, v := range vulns {
-		if isExported(v.Symbol) {
-			k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-			hasExported[k] = true
-		}
+	defer from.Close()
+
+	dec := json.NewDecoder(from)
+
+	var h header
+	if err := dec.Decode(&h); err != nil {
+		return nil // no header
+	} else if h.Name != extractModeID || h.Version != extractModeVersion {
+		return nil // invalid header
 	}
 
-	var uniques []*vulncheck.Vuln
-	for _, v := range vulns {
-		k := key{id: v.OSV.ID, pkg: v.ImportSink.PkgPath, mod: v.ImportSink.Module.Path}
-		if isExported(v.Symbol) || !hasExported[k] {
-			uniques = append(uniques, v)
-		}
+	var b vulncheck.Bin
+	if err := dec.Decode(&b); err != nil {
+		return nil // no body
+	}
+	if dec.More() {
+		return nil // we want just header and body, nothing else
 	}
-	return uniques
+	return &b
 }
 
-// isExported checks if the symbol is exported. Assumes that the
-// symbol is of the form "identifier" or "identifier1.identifier2".
-func isExported(symbol string) bool {
-	parts := strings.Split(symbol, ".")
-	if len(parts) == 1 {
-		return unicode.IsUpper(rune(symbol[0]))
+// findSetting returns value of setting from bi if present.
+// Otherwise, returns "".
+func findSetting(setting string, bi *debug.BuildInfo) string {
+	for _, s := range bi.Settings {
+		if s.Key == setting {
+			return s.Value
+		}
 	}
-	return unicode.IsUpper(rune(parts[1][0]))
+	return ""
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go b/public-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go
deleted file mode 100644
index d4345f3b..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/binary_118.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package scan
-
-import (
-	"context"
-	"io"
-
-	"golang.org/x/vuln/internal/client"
-	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *vulncheck.Result, err error) {
-	return vulncheck.Binary(ctx, exe, cfg, client)
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go b/public-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
deleted file mode 100644
index 0f66a02c..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/binary_not118.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.18
-// +build !go1.18
-
-package scan
-
-import (
-	"context"
-	"errors"
-	"io"
-
-	"golang.org/x/vuln/internal/vulncheck"
-)
-
-func binary(ctx context.Context, exe io.ReaderAt, cfg *vulncheck.Config) (_ *vulncheck.Result, err error) {
-	return nil, errors.New("compile with Go 1.18 or higher to analyze binary files")
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/errors.go b/public-api/vendor/golang.org/x/vuln/internal/scan/errors.go
index 920edd4c..c28e3c5a 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/errors.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/errors.go
@@ -22,7 +22,7 @@ var (
 	// errUsage indicates that there was a usage error on the command line.
 	//
 	// In this case, we assume that the user does not know how to run
-	// govulncheck, and print the usage message with exit status 2.
+	// govulncheck and exit with status 2.
 	errUsage = &exitCodeError{message: "invalid usage", code: 2}
 
 	// errGoVersionMismatch is used to indicate that there is a mismatch between
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/extract.go b/public-api/vendor/golang.org/x/vuln/internal/scan/extract.go
new file mode 100644
index 00000000..58a3f673
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/extract.go
@@ -0,0 +1,60 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scan
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"sort"
+
+	"golang.org/x/vuln/internal/derrors"
+	"golang.org/x/vuln/internal/vulncheck"
+)
+
+const (
+	// extractModeID is the unique name of the extract mode protocol
+	extractModeID      = "govulncheck-extract"
+	extractModeVersion = "0.1.0"
+)
+
+// header information for the blob output.
+type header struct {
+	Name    string `json:"name"`
+	Version string `json:"version"`
+}
+
+// runExtract dumps the extracted abstraction of binary at cfg.patterns to out.
+// It prints out exactly two blob messages, one with the header and one with
+// the vulncheck.Bin as the body.
+func runExtract(cfg *config, out io.Writer) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	bin, err := createBin(cfg.patterns[0])
+	if err != nil {
+		return err
+	}
+	sortBin(bin) // sort for easier testing and validation
+	header := header{
+		Name:    extractModeID,
+		Version: extractModeVersion,
+	}
+
+	enc := json.NewEncoder(out)
+
+	if err := enc.Encode(header); err != nil {
+		return fmt.Errorf("marshaling blob header: %v", err)
+	}
+	if err := enc.Encode(bin); err != nil {
+		return fmt.Errorf("marshaling blob body: %v", err)
+	}
+	return nil
+}
+
+func sortBin(bin *vulncheck.Bin) {
+	sort.SliceStable(bin.PkgSymbols, func(i, j int) bool {
+		return bin.PkgSymbols[i].Pkg+"."+bin.PkgSymbols[i].Name < bin.PkgSymbols[j].Pkg+"."+bin.PkgSymbols[j].Name
+	})
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/flags.go b/public-api/vendor/golang.org/x/vuln/internal/scan/flags.go
index 1e581102..5512540f 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/flags.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/flags.go
@@ -19,37 +19,37 @@ import (
 type config struct {
 	govulncheck.Config
 	patterns []string
-	mode     string
 	db       string
-	json     bool
 	dir      string
-	tags     []string
+	tags     buildutil.TagsFlag
 	test     bool
-	show     []string
+	show     ShowFlag
+	format   FormatFlag
 	env      []string
 }
 
-const (
-	modeBinary  = "binary"
-	modeSource  = "source"
-	modeConvert = "convert" // only intended for use by gopls
-	modeQuery   = "query"   // only intended for use by gopls
-)
-
 func parseFlags(cfg *config, stderr io.Writer, args []string) error {
-	var tagsFlag buildutil.TagsFlag
-	var showFlag showFlag
+	var version bool
+	var json bool
+	var scanFlag ScanFlag
+	var modeFlag ModeFlag
 	flags := flag.NewFlagSet("", flag.ContinueOnError)
 	flags.SetOutput(stderr)
-	flags.BoolVar(&cfg.json, "json", false, "output JSON")
-	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode)")
+	flags.BoolVar(&json, "json", false, "output JSON (Go compatible legacy flag, see format flag)")
+	flags.BoolVar(&cfg.test, "test", false, "analyze test files (only valid for source mode, default false)")
 	flags.StringVar(&cfg.dir, "C", "", "change to `dir` before running govulncheck")
 	flags.StringVar(&cfg.db, "db", "https://vuln.go.dev", "vulnerability database `url`")
-	flags.StringVar(&cfg.mode, "mode", modeSource, "supports source or binary")
-	flags.Var(&tagsFlag, "tags", "comma-separated `list` of build tags")
-	flags.Var(&showFlag, "show", "enable display of additional information specified by `list`")
-	scanLevel := flags.String("scan-level", "symbol", "set the scanning level desired, one of module, package or symbol")
-	flags.Usage = func() {
+	flags.Var(&modeFlag, "mode", "supports 'source', 'binary', and 'extract' (default 'source')")
+	flags.Var(&cfg.tags, "tags", "comma-separated `list` of build tags")
+	flags.Var(&cfg.show, "show", "enable display of additional information specified by the comma separated `list`\nThe supported values are 'traces','color', 'version', and 'verbose'")
+	flags.Var(&cfg.format, "format", "specify format output\nThe supported values are 'text', 'json', 'sarif', and 'openvex' (default 'text')")
+	flags.BoolVar(&version, "version", false, "print the version information")
+	flags.Var(&scanFlag, "scan", "set the scanning level desired, one of 'module', 'package', or 'symbol' (default 'symbol')")
+
+	// We don't want to print the whole usage message on each flags
+	// error, so we set to a no-op and do the printing ourselves.
+	flags.Usage = func() {}
+	usage := func() {
 		fmt.Fprint(flags.Output(), `Govulncheck reports known vulnerabilities in dependencies.
 
 Usage:
@@ -61,44 +61,60 @@ Usage:
 		flags.PrintDefaults()
 		fmt.Fprintf(flags.Output(), "\n%s\n", detailsMessage)
 	}
+
 	if err := flags.Parse(args); err != nil {
 		if err == flag.ErrHelp {
+			usage() // print usage only on help
 			return errHelp
 		}
-		return err
+		return errUsage
 	}
 	cfg.patterns = flags.Args()
-	if cfg.mode != modeConvert && len(cfg.patterns) == 0 {
-		flags.Usage()
-		return errUsage
+	if version {
+		cfg.show = append(cfg.show, "version")
 	}
-	cfg.tags = tagsFlag
-	cfg.show = showFlag
-	cfg.ScanLevel = govulncheck.ScanLevel(*scanLevel)
-	if err := validateConfig(cfg); err != nil {
+	cfg.ScanLevel = govulncheck.ScanLevel(scanFlag)
+	cfg.ScanMode = govulncheck.ScanMode(modeFlag)
+	if err := validateConfig(cfg, json); err != nil {
 		fmt.Fprintln(flags.Output(), err)
 		return errUsage
 	}
 	return nil
 }
 
-var supportedModes = map[string]bool{
-	modeSource:  true,
-	modeBinary:  true,
-	modeConvert: true,
-	modeQuery:   true,
-}
+func validateConfig(cfg *config, json bool) error {
+	// take care of default values
+	if cfg.ScanMode == "" {
+		cfg.ScanMode = govulncheck.ScanModeSource
+	}
+	if cfg.ScanLevel == "" {
+		cfg.ScanLevel = govulncheck.ScanLevelSymbol
+	}
+	if json {
+		if cfg.format != formatUnset {
+			return fmt.Errorf("the -json flag cannot be used with -format flag")
+		}
+		cfg.format = formatJSON
+	} else {
+		if cfg.format == formatUnset {
+			cfg.format = formatText
+		}
+	}
 
-func validateConfig(cfg *config) error {
-	if _, ok := supportedModes[cfg.mode]; !ok {
-		return fmt.Errorf("%q is not a valid mode", cfg.mode)
+	// show flag is only supported with text output
+	if cfg.format != formatText && len(cfg.show) > 0 {
+		return fmt.Errorf("the -show flag is not supported for %s output", cfg.format)
 	}
-	switch cfg.mode {
-	case modeSource:
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		if len(cfg.patterns) == 1 && isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is a file.\n\n%v", cfg.patterns[0], errNoBinaryFlag)
 		}
-	case modeBinary:
+		if cfg.ScanLevel == govulncheck.ScanLevelModule && len(cfg.patterns) != 0 {
+			return fmt.Errorf("patterns are not accepted for module only scanning")
+		}
+	case govulncheck.ScanModeBinary:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in binary mode")
 		}
@@ -111,7 +127,23 @@ func validateConfig(cfg *config) error {
 		if !isFile(cfg.patterns[0]) {
 			return fmt.Errorf("%q is not a file", cfg.patterns[0])
 		}
-	case modeConvert:
+	case govulncheck.ScanModeExtract:
+		if cfg.test {
+			return fmt.Errorf("the -test flag is not supported in extract mode")
+		}
+		if len(cfg.tags) > 0 {
+			return fmt.Errorf("the -tags flag is not supported in extract mode")
+		}
+		if len(cfg.patterns) != 1 {
+			return fmt.Errorf("only 1 binary can be extracted at a time")
+		}
+		if cfg.format == formatJSON {
+			return fmt.Errorf("the json format must be off in extract mode")
+		}
+		if !isFile(cfg.patterns[0]) {
+			return fmt.Errorf("%q is not a file (source extraction is not supported)", cfg.patterns[0])
+		}
+	case govulncheck.ScanModeConvert:
 		if len(cfg.patterns) != 0 {
 			return fmt.Errorf("patterns are not accepted in convert mode")
 		}
@@ -124,15 +156,15 @@ func validateConfig(cfg *config) error {
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in convert mode")
 		}
-	case modeQuery:
+	case govulncheck.ScanModeQuery:
 		if cfg.test {
 			return fmt.Errorf("the -test flag is not supported in query mode")
 		}
 		if len(cfg.tags) > 0 {
 			return fmt.Errorf("the -tags flag is not supported in query mode")
 		}
-		if !cfg.json {
-			return fmt.Errorf("the -json flag must be set in query mode")
+		if cfg.format != formatJSON {
+			return fmt.Errorf("the json format must be set in query mode")
 		}
 		for _, pattern := range cfg.patterns {
 			// Parse the input here so that we can catch errors before
@@ -142,9 +174,6 @@ func validateConfig(cfg *config) error {
 			}
 		}
 	}
-	if cfg.json && len(cfg.show) > 0 {
-		return fmt.Errorf("the -show flag is not supported for JSON output")
-	}
 	return nil
 }
 
@@ -156,26 +185,119 @@ func isFile(path string) bool {
 	return !s.IsDir()
 }
 
-// fileExists checks if file path exists. Returns true
-// if the file exists or it cannot prove that it does
-// not exist. Otherwise, returns false.
-func fileExists(path string) bool {
-	if _, err := os.Stat(path); err == nil {
-		return true
-	} else if errors.Is(err, os.ErrNotExist) {
-		return false
+var errFlagParse = errors.New("see -help for details")
+
+// ShowFlag is used for parsing and validation of
+// govulncheck -show flag.
+type ShowFlag []string
+
+var supportedShows = map[string]bool{
+	"traces":  true,
+	"color":   true,
+	"verbose": true,
+	"version": true,
+}
+
+func (v *ShowFlag) Set(s string) error {
+	if s == "" {
+		return nil
+	}
+	for _, show := range strings.Split(s, ",") {
+		sh := strings.TrimSpace(show)
+		if _, ok := supportedShows[sh]; !ok {
+			return errFlagParse
+		}
+		*v = append(*v, sh)
 	}
-	// Conservatively return true if os.Stat fails
-	// for some other reason.
-	return true
+	return nil
 }
 
-type showFlag []string
+func (v *ShowFlag) Get() interface{} { return *v }
+func (v *ShowFlag) String() string   { return "" }
+
+// Update the text handler h with values of the flag.
+func (v ShowFlag) Update(h *TextHandler) {
+	for _, show := range v {
+		switch show {
+		case "traces":
+			h.showTraces = true
+		case "color":
+			h.showColor = true
+		case "version":
+			h.showVersion = true
+		case "verbose":
+			h.showVerbose = true
+		}
+	}
+}
 
-func (v *showFlag) Set(s string) error {
-	*v = append(*v, strings.Split(s, ",")...)
+// FormatFlag is used for parsing and validation of
+// govulncheck -format flag.
+type FormatFlag string
+
+const (
+	formatUnset   = ""
+	formatJSON    = "json"
+	formatText    = "text"
+	formatSarif   = "sarif"
+	formatOpenVEX = "openvex"
+)
+
+var supportedFormats = map[string]bool{
+	formatJSON:    true,
+	formatText:    true,
+	formatSarif:   true,
+	formatOpenVEX: true,
+}
+
+func (f *FormatFlag) Get() interface{} { return *f }
+func (f *FormatFlag) Set(s string) error {
+	if _, ok := supportedFormats[s]; !ok {
+		return errFlagParse
+	}
+	*f = FormatFlag(s)
 	return nil
 }
+func (f *FormatFlag) String() string { return "" }
 
-func (f *showFlag) Get() interface{} { return *f }
-func (f *showFlag) String() string   { return "" }
+// ModeFlag is used for parsing and validation of
+// govulncheck -mode flag.
+type ModeFlag string
+
+var supportedModes = map[string]bool{
+	govulncheck.ScanModeSource:  true,
+	govulncheck.ScanModeBinary:  true,
+	govulncheck.ScanModeConvert: true,
+	govulncheck.ScanModeQuery:   true,
+	govulncheck.ScanModeExtract: true,
+}
+
+func (f *ModeFlag) Get() interface{} { return *f }
+func (f *ModeFlag) Set(s string) error {
+	if _, ok := supportedModes[s]; !ok {
+		return errFlagParse
+	}
+	*f = ModeFlag(s)
+	return nil
+}
+func (f *ModeFlag) String() string { return "" }
+
+// ScanFlag is used for parsing and validation of
+// govulncheck -scan flag.
+type ScanFlag string
+
+var supportedLevels = map[string]bool{
+	govulncheck.ScanLevelModule:  true,
+	govulncheck.ScanLevelPackage: true,
+	govulncheck.ScanLevelSymbol:  true,
+}
+
+func (f *ScanFlag) Get() interface{} { return *f }
+func (f *ScanFlag) Set(s string) error {
+	if _, ok := supportedLevels[s]; !ok {
+		return errFlagParse
+	}
+	*f = ScanFlag(s)
+	return nil
+}
+func (f *ScanFlag) String() string { return "" }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/run.go b/public-api/vendor/golang.org/x/vuln/internal/scan/run.go
index fe452cfa..f29b9d31 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/run.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/run.go
@@ -15,8 +15,11 @@ import (
 	"strings"
 	"time"
 
+	"golang.org/x/telemetry/counter"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
+	"golang.org/x/vuln/internal/openvex"
+	"golang.org/x/vuln/internal/sarif"
 )
 
 // RunGovulncheck performs main govulncheck functionality and exits the
@@ -27,9 +30,6 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 	if err := parseFlags(cfg, stderr, args); err != nil {
 		return err
 	}
-	if cfg.mode == modeConvert {
-		return convertJSONToText(r, stdout)
-	}
 
 	client, err := client.NewClient(cfg.db, nil)
 	if err != nil {
@@ -38,42 +38,48 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
 
 	prepareConfig(ctx, cfg, client)
 	var handler govulncheck.Handler
-	switch {
-	case cfg.json:
+	switch cfg.format {
+	case formatJSON:
 		handler = govulncheck.NewJSONHandler(stdout)
+	case formatSarif:
+		handler = sarif.NewHandler(stdout)
+	case formatOpenVEX:
+		handler = openvex.NewHandler(stdout)
 	default:
 		th := NewTextHandler(stdout)
-		th.Show(cfg.show)
+		cfg.show.Update(th)
 		handler = th
 	}
 
-	// Write the introductory message to the user.
 	if err := handler.Config(&cfg.Config); err != nil {
 		return err
 	}
 
-	switch cfg.mode {
-	case modeSource:
+	incTelemetryFlagCounters(cfg)
+
+	switch cfg.ScanMode {
+	case govulncheck.ScanModeSource:
 		dir := filepath.FromSlash(cfg.dir)
 		err = runSource(ctx, handler, cfg, client, dir)
-	case modeBinary:
+	case govulncheck.ScanModeBinary:
 		err = runBinary(ctx, handler, cfg, client)
-	case modeQuery:
+	case govulncheck.ScanModeExtract:
+		return runExtract(cfg, stdout)
+	case govulncheck.ScanModeQuery:
 		err = runQuery(ctx, handler, cfg, client)
+	case govulncheck.ScanModeConvert:
+		err = govulncheck.HandleJSON(r, handler)
 	}
 	if err != nil {
 		return err
 	}
-	if err := Flush(handler); err != nil {
-		return err
-	}
-	return nil
+	return Flush(handler)
 }
 
 func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 	cfg.ProtocolVersion = govulncheck.ProtocolVersion
 	cfg.DB = cfg.db
-	if cfg.mode == modeSource && cfg.GoVersion == "" {
+	if cfg.ScanMode == govulncheck.ScanModeSource && cfg.GoVersion == "" {
 		const goverPrefix = "GOVERSION="
 		for _, env := range cfg.env {
 			if val := strings.TrimPrefix(env, goverPrefix); val != env {
@@ -82,7 +88,7 @@ func prepareConfig(ctx context.Context, cfg *config, client *client.Client) {
 		}
 		if cfg.GoVersion == "" {
 			if out, err := exec.Command("go", "env", "GOVERSION").Output(); err == nil {
-				cfg.GoVersion = string(out)
+				cfg.GoVersion = strings.TrimSpace(string(out))
 			}
 		}
 	}
@@ -133,13 +139,22 @@ func scannerVersion(cfg *config, bi *debug.BuildInfo) {
 	cfg.ScannerVersion = buf.String()
 }
 
-// convertJSONToText converts r, which is expected to be the JSON output of govulncheck,
-// into the text output, and writes the output to w.
-func convertJSONToText(r io.Reader, w io.Writer) error {
-	h := NewTextHandler(w)
-	if err := govulncheck.HandleJSON(r, h); err != nil {
-		return err
+func incTelemetryFlagCounters(cfg *config) {
+	counter.Inc(fmt.Sprintf("govulncheck/mode:%s", cfg.ScanMode))
+	counter.Inc(fmt.Sprintf("govulncheck/scan:%s", cfg.ScanLevel))
+	counter.Inc(fmt.Sprintf("govulncheck/format:%s", cfg.format))
+
+	if len(cfg.show) == 0 {
+		counter.Inc("govulncheck/show:none")
+	}
+	for _, s := range cfg.show {
+		counter.Inc(fmt.Sprintf("govulncheck/show:%s", s))
+	}
+}
+
+func Flush(h govulncheck.Handler) error {
+	if th, ok := h.(interface{ Flush() error }); ok {
+		return th.Flush()
 	}
-	Flush(h)
 	return nil
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/source.go b/public-api/vendor/golang.org/x/vuln/internal/scan/source.go
index cfdc1227..e9232112 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/source.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/source.go
@@ -7,13 +7,11 @@ package scan
 import (
 	"context"
 	"fmt"
-	"path/filepath"
 
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/client"
+	"golang.org/x/vuln/internal/derrors"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
 	"golang.org/x/vuln/internal/vulncheck"
 )
 
@@ -22,189 +20,30 @@ import (
 // Vulnerabilities can be called (affecting the package, because a vulnerable
 // symbol is actually exercised) or just imported by the package
 // (likely having a non-affecting outcome).
-func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) error {
-	var pkgs []*packages.Package
+func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) (err error) {
+	defer derrors.Wrap(&err, "govulncheck")
+
+	if cfg.ScanLevel.WantPackages() && len(cfg.patterns) == 0 {
+		return nil // don't throw an error here
+	}
+	if !gomodExists(dir) {
+		return errNoGoMod
+	}
 	graph := vulncheck.NewPackageGraph(cfg.GoVersion)
 	pkgConfig := &packages.Config{
 		Dir:   dir,
 		Tests: cfg.test,
 		Env:   cfg.env,
 	}
-	pkgs, err := graph.LoadPackages(pkgConfig, cfg.tags, cfg.patterns)
-	if err != nil {
-		// Try to provide a meaningful and actionable error message.
-		if !fileExists(filepath.Join(dir, "go.mod")) {
-			return fmt.Errorf("govulncheck: %v", errNoGoMod)
-		}
+	if err := graph.LoadPackagesAndMods(pkgConfig, cfg.tags, cfg.patterns, cfg.ScanLevel == govulncheck.ScanLevelSymbol); err != nil {
 		if isGoVersionMismatchError(err) {
-			return fmt.Errorf("govulncheck: %v\n\n%v", errGoVersionMismatch, err)
-		}
-		return fmt.Errorf("govulncheck: loading packages: %w", err)
-	}
-	if err := handler.Progress(sourceProgressMessage(pkgs)); err != nil {
-		return err
-	}
-	vr, err := vulncheck.Source(ctx, pkgs, &cfg.Config, client, graph)
-	if err != nil {
-		return err
-	}
-	callStacks := vulncheck.CallStacks(vr)
-	return emitResult(handler, vr, callStacks)
-}
-
-func emitResult(handler govulncheck.Handler, vr *vulncheck.Result, callstacks map[*vulncheck.Vuln]vulncheck.CallStack) error {
-	osvs := map[string]*osv.Entry{}
-	// first deal with all the affected vulnerabilities
-	emitted := map[string]bool{}
-	seen := map[string]bool{}
-	for _, vv := range vr.Vulns {
-		osvs[vv.OSV.ID] = vv.OSV
-		fixed := fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected)
-		stack := callstacks[vv]
-		if stack == nil {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixed,
-			Trace:        tracefromEntries(stack),
-		})
-	}
-	for _, vv := range vr.Vulns {
-		if emitted[vv.OSV.ID] {
-			continue
+			return fmt.Errorf("%v\n\n%v", errGoVersionMismatch, err)
 		}
-		stacks := callstacks[vv]
-		if len(stacks) != 0 {
-			continue
-		}
-		emitted[vv.OSV.ID] = true
-		emitFinding(handler, osvs, seen, &govulncheck.Finding{
-			OSV:          vv.OSV.ID,
-			FixedVersion: fixedVersion(vv.ImportSink.Module.Path, vv.OSV.Affected),
-			Trace:        []*govulncheck.Frame{frameFromPackage(vv.ImportSink)},
-		})
-	}
-	return nil
-}
-
-func emitFinding(handler govulncheck.Handler, osvs map[string]*osv.Entry, seen map[string]bool, finding *govulncheck.Finding) error {
-	if !seen[finding.OSV] {
-		seen[finding.OSV] = true
-		if err := handler.OSV(osvs[finding.OSV]); err != nil {
-			return err
-		}
-	}
-	return handler.Finding(finding)
-}
-
-// tracefromEntries creates a sequence of
-// frames from vcs. Position of a Frame is the
-// call position of the corresponding stack entry.
-func tracefromEntries(vcs vulncheck.CallStack) []*govulncheck.Frame {
-	var frames []*govulncheck.Frame
-	for i := len(vcs) - 1; i >= 0; i-- {
-		e := vcs[i]
-		fr := frameFromPackage(e.Function.Package)
-		fr.Function = e.Function.Name
-		fr.Receiver = e.Function.Receiver()
-		if e.Call == nil || e.Call.Pos == nil {
-			fr.Position = nil
-		} else {
-			fr.Position = &govulncheck.Position{
-				Filename: e.Call.Pos.Filename,
-				Offset:   e.Call.Pos.Offset,
-				Line:     e.Call.Pos.Line,
-				Column:   e.Call.Pos.Column,
-			}
-		}
-		frames = append(frames, fr)
+		return fmt.Errorf("loading packages: %w", err)
 	}
-	return frames
-}
 
-func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
-	fr := &govulncheck.Frame{}
-	if pkg != nil {
-		fr.Module = pkg.Module.Path
-		fr.Version = pkg.Module.Version
-		fr.Package = pkg.PkgPath
-	}
-	if pkg.Module.Replace != nil {
-		fr.Module = pkg.Module.Replace.Path
-		fr.Version = pkg.Module.Replace.Version
+	if cfg.ScanLevel.WantPackages() && len(graph.TopPkgs()) == 0 {
+		return nil // early exit
 	}
-	return fr
-}
-
-// sourceProgressMessage returns a string of the form
-//
-//	"Scanning your code and P packages across M dependent modules for known vulnerabilities..."
-//
-// P is the number of strictly dependent packages of
-// topPkgs and Y is the number of their modules.
-func sourceProgressMessage(topPkgs []*packages.Package) *govulncheck.Progress {
-	pkgs, mods := depPkgsAndMods(topPkgs)
-
-	pkgsPhrase := fmt.Sprintf("%d package", pkgs)
-	if pkgs != 1 {
-		pkgsPhrase += "s"
-	}
-
-	modsPhrase := fmt.Sprintf("%d dependent module", mods)
-	if mods != 1 {
-		modsPhrase += "s"
-	}
-
-	msg := fmt.Sprintf("Scanning your code and %s across %s for known vulnerabilities...", pkgsPhrase, modsPhrase)
-	return &govulncheck.Progress{Message: msg}
-}
-
-// depPkgsAndMods returns the number of packages that
-// topPkgs depend on and the number of their modules.
-func depPkgsAndMods(topPkgs []*packages.Package) (int, int) {
-	tops := make(map[string]bool)
-	depPkgs := make(map[string]bool)
-	depMods := make(map[string]bool)
-
-	for _, t := range topPkgs {
-		tops[t.PkgPath] = true
-	}
-
-	var visit func(*packages.Package, bool)
-	visit = func(p *packages.Package, top bool) {
-		path := p.PkgPath
-		if depPkgs[path] {
-			return
-		}
-		if tops[path] && !top {
-			// A top package that is a dependency
-			// will not be in depPkgs, so we skip
-			// reiterating on it here.
-			return
-		}
-
-		// We don't count a top-level package as
-		// a dependency even when they are used
-		// as a dependent package.
-		if !tops[path] {
-			depPkgs[path] = true
-			if p.Module != nil &&
-				p.Module.Path != internal.GoStdModulePath && // no module for stdlib
-				p.Module.Path != internal.UnknownModulePath { // no module for unknown
-				depMods[p.Module.Path] = true
-			}
-		}
-
-		for _, d := range p.Imports {
-			visit(d, false)
-		}
-	}
-
-	for _, t := range topPkgs {
-		visit(t, true)
-	}
-
-	return len(depPkgs), len(depMods)
+	return vulncheck.Source(ctx, handler, &cfg.Config, client, graph)
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/template.go b/public-api/vendor/golang.org/x/vuln/internal/scan/template.go
index 953fbaeb..5c1a4a75 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/template.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/template.go
@@ -14,9 +14,9 @@ import (
 	"unicode"
 	"unicode/utf8"
 
-	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/traces"
 )
 
 type findingSummary struct {
@@ -26,9 +26,11 @@ type findingSummary struct {
 }
 
 type summaryCounters struct {
-	VulnerabilitiesCalled int
-	ModulesCalled         int
-	StdlibCalled          bool
+	VulnerabilitiesCalled   int
+	ModulesCalled           int
+	VulnerabilitiesImported int
+	VulnerabilitiesRequired int
+	StdlibCalled            bool
 }
 
 func fixupFindings(osvs []*osv.Entry, findings []*findingSummary) {
@@ -74,27 +76,22 @@ func groupBy(findings []*findingSummary, compare func(left, right *findingSummar
 	return result
 }
 
-func counters(findings []*findingSummary) summaryCounters {
-	vulns := map[string]struct{}{}
-	modules := map[string]struct{}{}
+func isRequired(findings []*findingSummary) bool {
 	for _, f := range findings {
-		if f.Trace[0].Function == "" {
-			continue
+		if f.Trace[0].Module != "" {
+			return true
 		}
-		id := f.OSV.ID
-		vulns[id] = struct{}{}
-		mod := f.Trace[0].Module
-		modules[mod] = struct{}{}
-	}
-	result := summaryCounters{
-		VulnerabilitiesCalled: len(vulns),
-		ModulesCalled:         len(modules),
 	}
-	if _, found := modules[internal.GoStdModulePath]; found {
-		result.StdlibCalled = true
-		result.ModulesCalled--
+	return false
+}
+
+func isImported(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if f.Trace[0].Package != "" {
+			return true
+		}
 	}
-	return result
+	return false
 }
 
 func isCalled(findings []*findingSummary) bool {
@@ -105,6 +102,7 @@ func isCalled(findings []*findingSummary) bool {
 	}
 	return false
 }
+
 func getOSV(osvs []*osv.Entry, id string) *osv.Entry {
 	for _, entry := range osvs {
 		if entry.ID == id {
@@ -184,7 +182,13 @@ func posToString(p *govulncheck.Position) string {
 
 func symbol(frame *govulncheck.Frame, short bool) string {
 	buf := &strings.Builder{}
-	addSymbolName(buf, frame, short)
+	addSymbol(buf, frame, short)
+	return buf.String()
+}
+
+func symbolName(frame *govulncheck.Frame) string {
+	buf := &strings.Builder{}
+	addSymbolName(buf, frame)
 	return buf.String()
 }
 
@@ -196,44 +200,36 @@ func symbol(frame *govulncheck.Frame, short bool) string {
 // If the vulnerable symbol is in the users code, it will show the entry point
 // and the vulnerable symbol.
 func compactTrace(finding *govulncheck.Finding) string {
-	if len(finding.Trace) < 1 {
+	compact := traces.Compact(finding)
+	if len(compact) == 0 {
 		return ""
 	}
-	iTop := len(finding.Trace) - 1
-	topModule := finding.Trace[iTop].Module
-	// search for the exit point of the top module
-	for i, frame := range finding.Trace {
-		if frame.Module == topModule {
-			iTop = i
-			break
-		}
-	}
-
-	if iTop == 0 {
-		// all in one module, reset to the end
-		iTop = len(finding.Trace) - 1
-	}
 
+	l := len(compact)
+	iTop := l - 1
 	buf := &strings.Builder{}
-	topPos := posToString(finding.Trace[iTop].Position)
+	topPos := posToString(compact[iTop].Position)
 	if topPos != "" {
 		buf.WriteString(topPos)
 		buf.WriteString(": ")
 	}
 
-	if iTop > 0 {
-		addSymbolName(buf, finding.Trace[iTop], true)
+	if l > 1 {
+		// print the root of the compact trace
+		addSymbol(buf, compact[iTop], true)
 		buf.WriteString(" calls ")
 	}
-	if iTop > 1 {
-		addSymbolName(buf, finding.Trace[iTop-1], true)
+	if l > 2 {
+		// print next element of the trace, if any
+		addSymbol(buf, compact[iTop-1], true)
 		buf.WriteString(", which")
-		if iTop > 2 {
+		if l > 3 {
+			// don't print the third element, just acknowledge it
 			buf.WriteString(" eventually")
 		}
 		buf.WriteString(" calls ")
 	}
-	addSymbolName(buf, finding.Trace[0], true)
+	addSymbol(buf, compact[0], true) // print the vulnerable symbol
 	return buf.String()
 }
 
@@ -265,7 +261,7 @@ func importPathToAssumedName(importPath string) string {
 	return base
 }
 
-func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
+func addSymbol(w io.Writer, frame *govulncheck.Frame, short bool) {
 	if frame.Function == "" {
 		return
 	}
@@ -277,6 +273,10 @@ func addSymbolName(w io.Writer, frame *govulncheck.Frame, short bool) {
 		io.WriteString(w, pkg)
 		io.WriteString(w, ".")
 	}
+	addSymbolName(w, frame)
+}
+
+func addSymbolName(w io.Writer, frame *govulncheck.Frame) {
 	if frame.Receiver != "" {
 		if frame.Receiver[0] == '*' {
 			io.WriteString(w, frame.Receiver[1:])
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/text.go b/public-api/vendor/golang.org/x/vuln/internal/scan/text.go
index 845054b9..ab49bdd1 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/text.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/text.go
@@ -7,19 +7,19 @@ package scan
 import (
 	"fmt"
 	"io"
+	"sort"
 	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/vulncheck"
 )
 
 type style int
 
 const (
 	defaultStyle = style(iota)
-	goStyle
-	scannerStyle
 	osvCalledStyle
 	osvImportedStyle
 	detailsStyle
@@ -34,81 +34,143 @@ func NewTextHandler(w io.Writer) *TextHandler {
 }
 
 type TextHandler struct {
-	w        io.Writer
-	osvs     []*osv.Entry
-	findings []*findingSummary
+	w         io.Writer
+	sbom      *govulncheck.SBOM
+	osvs      []*osv.Entry
+	findings  []*findingSummary
+	scanLevel govulncheck.ScanLevel
+	scanMode  govulncheck.ScanMode
 
 	err error
 
-	showColor  bool
-	showTraces bool
+	showColor   bool
+	showTraces  bool
+	showVersion bool
+	showVerbose bool
 }
 
 const (
 	detailsMessage = `For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.`
 
 	binaryProgressMessage = `Scanning your binary for known vulnerabilities...`
-)
 
-func (h *TextHandler) Show(show []string) {
-	for _, show := range show {
-		switch show {
-		case "traces":
-			h.showTraces = true
-		case "color":
-			h.showColor = true
-		}
-	}
-}
+	noVulnsMessage = `No vulnerabilities found.`
 
-func Flush(h govulncheck.Handler) error {
-	if th, ok := h.(interface{ Flush() error }); ok {
-		return th.Flush()
-	}
-	return nil
-}
+	noOtherVulnsMessage = `No other vulnerabilities found.`
+
+	verboseMessage = `'-show verbose' for more details`
+
+	symbolMessage = `'-scan symbol' for more fine grained vulnerability detection`
+)
 
 func (h *TextHandler) Flush() error {
+	if h.showVerbose {
+		h.printSBOM()
+	}
 	if len(h.findings) == 0 {
-		return nil
+		h.print(noVulnsMessage + "\n")
+	} else {
+		fixupFindings(h.osvs, h.findings)
+		counters := h.allVulns(h.findings)
+		h.summary(counters)
 	}
-	fixupFindings(h.osvs, h.findings)
-	h.byVulnerability(h.findings)
-	h.summary(h.findings)
 	if h.err != nil {
 		return h.err
 	}
-	if isCalled(h.findings) {
+	// We found vulnerabilities when the findings' level matches the scan level.
+	if (isCalled(h.findings) && h.scanLevel == govulncheck.ScanLevelSymbol) ||
+		(isImported(h.findings) && h.scanLevel == govulncheck.ScanLevelPackage) ||
+		(isRequired(h.findings) && h.scanLevel == govulncheck.ScanLevelModule) {
 		return errVulnerabilitiesFound
 	}
+
 	return nil
 }
 
-// Config writes text output formatted according to govulncheck-intro.tmpl.
+// Config writes version information only if --version was set.
 func (h *TextHandler) Config(config *govulncheck.Config) error {
-	h.print("govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.\n\nUsing ")
+	h.scanLevel = config.ScanLevel
+	h.scanMode = config.ScanMode
+
+	if !h.showVersion {
+		return nil
+	}
 	if config.GoVersion != "" {
-		h.style(goStyle, config.GoVersion)
-		h.print(` and `)
+		h.style(keyStyle, "Go: ")
+		h.print(config.GoVersion, "\n")
 	}
 	if config.ScannerName != "" {
-		h.style(scannerStyle, config.ScannerName)
+		h.style(keyStyle, "Scanner: ")
+		h.print(config.ScannerName)
 		if config.ScannerVersion != "" {
 			h.print(`@`, config.ScannerVersion)
 		}
-		h.print(` with `)
+		h.print("\n")
 	}
-	h.print(`vulnerability data from `, config.DB)
-	if config.DBLastModified != nil {
-		h.print(` (last modified `, *config.DBLastModified, `)`)
+	if config.DB != "" {
+		h.style(keyStyle, "DB: ")
+		h.print(config.DB, "\n")
+		if config.DBLastModified != nil {
+			h.style(keyStyle, "DB updated: ")
+			h.print(*config.DBLastModified, "\n")
+		}
 	}
-	h.print(".\n\n")
+	h.print("\n")
 	return h.err
 }
 
-// Progress writes progress updates during govulncheck execution..
+func (h *TextHandler) SBOM(sbom *govulncheck.SBOM) error {
+	h.sbom = sbom
+	return nil
+}
+
+func (h *TextHandler) printSBOM() error {
+	if h.sbom == nil {
+		h.print("No packages matched the provided pattern.\n")
+		return nil
+	}
+
+	printed := false
+
+	for i, root := range h.sbom.Roots {
+		if i == 0 {
+			if len(h.sbom.Roots) > 1 {
+				h.print("The package pattern matched the following ", len(h.sbom.Roots), " root packages:\n")
+			} else {
+				h.print("The package pattern matched the following root package:\n")
+			}
+		}
+
+		h.print("  ", root, "\n")
+		printed = true
+	}
+	for i, mod := range h.sbom.Modules {
+		if i == 0 && mod.Path != "stdlib" {
+			h.print("Govulncheck scanned the following ", len(h.sbom.Modules)-1, " modules and the ", h.sbom.GoVersion, " standard library:\n")
+		}
+
+		if mod.Path == "stdlib" {
+			continue
+		}
+
+		h.print("  ", mod.Path)
+		if mod.Version != "" {
+			h.print("@", mod.Version)
+		}
+		h.print("\n")
+		printed = true
+	}
+	if printed {
+		h.print("\n")
+	}
+	return nil
+}
+
+// Progress writes progress updates during govulncheck execution.
 func (h *TextHandler) Progress(progress *govulncheck.Progress) error {
-	h.print(progress.Message, "\n\n")
+	if h.showVerbose {
+		h.print(progress.Message, "\n\n")
+	}
 	return h.err
 }
 
@@ -127,39 +189,64 @@ func (h *TextHandler) Finding(finding *govulncheck.Finding) error {
 	return nil
 }
 
-func (h *TextHandler) byVulnerability(findings []*findingSummary) {
+func (h *TextHandler) allVulns(findings []*findingSummary) summaryCounters {
 	byVuln := groupByVuln(findings)
-	called := 0
+	var called, imported, required [][]*findingSummary
+	mods := map[string]struct{}{}
+	stdlibCalled := false
 	for _, findings := range byVuln {
-		if isCalled(findings) {
-			if called > 0 {
-				h.print("\n")
+		switch {
+		case isCalled(findings):
+			called = append(called, findings)
+			if isStdFindings(findings) {
+				stdlibCalled = true
+			} else {
+				mods[findings[0].Trace[0].Module] = struct{}{}
 			}
-			h.vulnerability(called, findings)
-			called++
+		case isImported(findings):
+			imported = append(imported, findings)
+		default:
+			required = append(required, findings)
 		}
 	}
-	unCalled := len(byVuln) - called
-	if unCalled == 0 {
-		return
+
+	if h.scanLevel.WantSymbols() {
+		h.style(sectionStyle, "=== Symbol Results ===\n\n")
+		if len(called) == 0 {
+			h.print(noVulnsMessage, "\n\n")
+		}
+		for index, findings := range called {
+			h.vulnerability(index, findings)
+		}
 	}
-	h.print("\n")
-	h.style(sectionStyle, "=== Informational ===\n")
-	h.print("\nFound ", unCalled)
-	h.print(choose(unCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(" in packages that you import, but there are no call\nstacks leading to the use of ")
-	h.print(choose(unCalled == 1, `this vulnerability`, `these vulnerabilities`))
-	h.print(". You may not need to\ntake any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck\nfor details.\n\n")
-	index := 0
-	for _, findings := range byVuln {
-		if !isCalled(findings) {
-			if index > 0 {
-				h.print("\n")
-			}
+
+	if h.scanLevel == govulncheck.ScanLevelPackage || (h.scanLevel.WantPackages() && h.showVerbose) {
+		h.style(sectionStyle, "=== Package Results ===\n\n")
+		if len(imported) == 0 {
+			h.print(choose(!h.scanLevel.WantSymbols(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range imported {
 			h.vulnerability(index, findings)
-			index++
 		}
 	}
+
+	if h.showVerbose || h.scanLevel == govulncheck.ScanLevelModule {
+		h.style(sectionStyle, "=== Module Results ===\n\n")
+		if len(required) == 0 {
+			h.print(choose(!h.scanLevel.WantPackages(), noVulnsMessage, noOtherVulnsMessage), "\n\n")
+		}
+		for index, findings := range required {
+			h.vulnerability(index, findings)
+		}
+	}
+
+	return summaryCounters{
+		VulnerabilitiesCalled:   len(called),
+		VulnerabilitiesImported: len(imported),
+		VulnerabilitiesRequired: len(required),
+		ModulesCalled:           len(mods),
+		StdlibCalled:            stdlibCalled,
+	}
 }
 
 func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
@@ -185,13 +272,20 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 	byModule := groupByModule(findings)
 	first := true
 	for _, module := range byModule {
-		//TODO: this assumes all traces on a module are found and fixed at the same versions
+		// Note: there can be several findingSummaries for the same vulnerability
+		// emitted during streaming for different scan levels.
+
+		// The module is same for all finding summaries.
 		lastFrame := module[0].Trace[0]
 		mod := lastFrame.Module
+		// For stdlib, try to show package path as module name where
+		// the scan level allows it.
+		// TODO: should this be done in byModule as well?
 		path := lastFrame.Module
-		if path == internal.GoStdModulePath {
-			path = lastFrame.Package
+		if stdPkg := h.pkg(module); path == internal.GoStdModulePath && stdPkg != "" {
+			path = stdPkg
 		}
+		// All findings on a module are found and fixed at the same version
 		foundVersion := moduleVersionString(lastFrame.Module, lastFrame.Version)
 		fixedVersion := moduleVersionString(lastFrame.Module, module[0].FixedVersion)
 		if !first {
@@ -228,59 +322,180 @@ func (h *TextHandler) vulnerability(index int, findings []*findingSummary) {
 		}
 		h.traces(module)
 	}
+	h.print("\n")
+}
+
+// pkg gives the package information for findings summaries
+// if one exists. This is only used to print package path
+// instead of a module for stdlib vulnerabilities at symbol
+// and package scan level.
+func (h *TextHandler) pkg(summaries []*findingSummary) string {
+	for _, f := range summaries {
+		if pkg := f.Trace[0].Package; pkg != "" {
+			return pkg
+		}
+	}
+	return ""
 }
 
+// traces prints out the most precise trace information
+// found in the given summaries.
 func (h *TextHandler) traces(traces []*findingSummary) {
-	first := true
-	for i, entry := range traces {
-		if entry.Compact == "" {
-			continue
+	// Sort the traces by the vulnerable symbol. This
+	// guarantees determinism since we are currently
+	// showing only one trace per symbol.
+	sort.SliceStable(traces, func(i, j int) bool {
+		return symbol(traces[i].Trace[0], true) < symbol(traces[j].Trace[0], true)
+	})
+
+	// compacts are finding summaries with compact traces
+	// suitable for non-verbose textual output. Currently,
+	// only traces produced by symbol analysis.
+	var compacts []*findingSummary
+	for _, t := range traces {
+		if t.Compact != "" {
+			compacts = append(compacts, t)
 		}
-		if first {
-			h.style(keyStyle, "    Example traces found:\n")
+	}
+
+	// binLimit is a limit on the number of binary traces
+	// to show. Traces for binaries are less interesting
+	// as users cannot act on them and they can hence
+	// spam users.
+	const binLimit = 5
+	binary := h.scanMode == govulncheck.ScanModeBinary
+	for i, entry := range compacts {
+		if i == 0 {
+			if binary {
+				h.style(keyStyle, "    Vulnerable symbols found:\n")
+			} else {
+				h.style(keyStyle, "    Example traces found:\n")
+			}
+		}
+
+		// skip showing all symbols in binary mode unless '-show traces' is on.
+		if binary && (i+1) > binLimit && !h.showTraces {
+			h.print("      Use '-show traces' to see the other ", len(compacts)-binLimit, " found symbols\n")
+			break
 		}
-		first = false
 
 		h.print("      #", i+1, ": ")
-		if !h.showTraces {
+
+		if !h.showTraces { // show summarized traces
 			h.print(entry.Compact, "\n")
+			continue
+		}
+
+		if binary {
+			// There are no call stacks in binary mode
+			// so just show the full symbol name.
+			h.print(symbol(entry.Trace[0], false), "\n")
 		} else {
 			h.print("for function ", symbol(entry.Trace[0], false), "\n")
 			for i := len(entry.Trace) - 1; i >= 0; i-- {
 				t := entry.Trace[i]
 				h.print("        ")
+				h.print(symbolName(t))
 				if t.Position != nil {
-					h.print(posToString(t.Position), ": ")
+					h.print(" @ ", symbolPath(t))
 				}
-				h.print(symbol(t, false), "\n")
+				h.print("\n")
 			}
 		}
 	}
 }
 
-func (h *TextHandler) summary(findings []*findingSummary) {
-	counters := counters(findings)
-	h.print("\n")
-	if counters.VulnerabilitiesCalled == 0 {
-		h.print("No vulnerabilities found.\n")
-		return
-	}
-	h.print(`Your code is affected by `)
-	h.style(valueStyle, counters.VulnerabilitiesCalled)
-	h.print(choose(counters.VulnerabilitiesCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(` from`)
-	if counters.ModulesCalled > 0 {
-		h.print(` `)
-		h.style(valueStyle, counters.ModulesCalled)
-		h.print(choose(counters.ModulesCalled == 1, ` module`, ` modules`))
+// symbolPath returns a user-friendly path to a symbol.
+func symbolPath(t *govulncheck.Frame) string {
+	// Add module path prefix to symbol paths to be more
+	// explicit to which module the symbols belong to.
+	return t.Module + "/" + posToString(t.Position)
+}
+
+func (h *TextHandler) summary(c summaryCounters) {
+	// print short summary of findings identified at the desired level of scan precision
+	var vulnCount int
+	h.print("Your code ", choose(h.scanLevel.WantSymbols(), "is", "may be"), " affected by ")
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		vulnCount = c.VulnerabilitiesCalled
+	case govulncheck.ScanLevelPackage:
+		vulnCount = c.VulnerabilitiesImported
+	case govulncheck.ScanLevelModule:
+		vulnCount = c.VulnerabilitiesRequired
 	}
-	if counters.StdlibCalled {
-		if counters.ModulesCalled != 0 {
-			h.print(` and`)
+	h.style(valueStyle, vulnCount)
+	h.print(choose(vulnCount == 1, ` vulnerability`, ` vulnerabilities`))
+	if h.scanLevel.WantSymbols() {
+		h.print(choose(c.ModulesCalled > 0 || c.StdlibCalled, ` from `, ``))
+		if c.ModulesCalled > 0 {
+			h.style(valueStyle, c.ModulesCalled)
+			h.print(choose(c.ModulesCalled == 1, ` module`, ` modules`))
+		}
+		if c.StdlibCalled {
+			if c.ModulesCalled != 0 {
+				h.print(` and `)
+			}
+			h.print(`the Go standard library`)
 		}
-		h.print(` the Go standard library`)
 	}
 	h.print(".\n")
+
+	// print summary for vulnerabilities found at other levels of scan precision
+	if other := h.summaryOtherVulns(c); other != "" {
+		h.wrap("", other, 80)
+		h.print("\n")
+	}
+
+	// print suggested flags for more/better info depending on scan level and if in verbose mode
+	if sugg := h.summarySuggestion(); sugg != "" {
+		h.wrap("", sugg, 80)
+		h.print("\n")
+	}
+}
+
+func (h *TextHandler) summaryOtherVulns(c summaryCounters) string {
+	var summary strings.Builder
+	if c.VulnerabilitiesRequired+c.VulnerabilitiesImported == 0 {
+		summary.WriteString("This scan found no other vulnerabilities in ")
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString("packages you import or ")
+		}
+		summary.WriteString("modules you require.")
+	} else {
+		summary.WriteString(choose(h.scanLevel.WantPackages(), "This scan also found ", ""))
+		if h.scanLevel.WantSymbols() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesImported))
+			summary.WriteString(choose(c.VulnerabilitiesImported == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in packages you import and ")
+		}
+		if h.scanLevel.WantPackages() {
+			summary.WriteString(fmt.Sprint(c.VulnerabilitiesRequired))
+			summary.WriteString(choose(c.VulnerabilitiesRequired == 1, ` vulnerability `, ` vulnerabilities `))
+			summary.WriteString("in modules you require")
+			summary.WriteString(choose(h.scanLevel.WantSymbols(), ", but your code doesn't appear to call these vulnerabilities.", "."))
+		}
+	}
+	return summary.String()
+}
+
+func (h *TextHandler) summarySuggestion() string {
+	var sugg strings.Builder
+	switch h.scanLevel {
+	case govulncheck.ScanLevelSymbol:
+		if !h.showVerbose {
+			sugg.WriteString("Use " + verboseMessage + ".")
+		}
+	case govulncheck.ScanLevelPackage:
+		sugg.WriteString("Use " + symbolMessage)
+		if !h.showVerbose {
+			sugg.WriteString(" and " + verboseMessage)
+		}
+		sugg.WriteString(".")
+	case govulncheck.ScanLevelModule:
+		sugg.WriteString("Use " + symbolMessage + ".")
+	}
+	return sugg.String()
 }
 
 func (h *TextHandler) style(style style, values ...any) {
@@ -288,10 +503,6 @@ func (h *TextHandler) style(style style, values ...any) {
 		switch style {
 		default:
 			h.print(colorReset)
-		case goStyle:
-			h.print(colorBold)
-		case scannerStyle:
-			h.print(colorBold)
 		case osvCalledStyle:
 			h.print(colorBold, fgRed)
 		case osvImportedStyle:
@@ -347,9 +558,18 @@ func (h *TextHandler) wrap(indent string, s string, maxWidth int) {
 	}
 }
 
-func choose(b bool, yes, no any) any {
+func choose[t any](b bool, yes, no t) t {
 	if b {
 		return yes
 	}
 	return no
 }
+
+func isStdFindings(findings []*findingSummary) bool {
+	for _, f := range findings {
+		if vulncheck.IsStdPackage(f.Trace[0].Package) || f.Trace[0].Module == internal.GoStdModulePath {
+			return true
+		}
+	}
+	return false
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/scan/util.go b/public-api/vendor/golang.org/x/vuln/internal/scan/util.go
index ce5500bb..0d82ca82 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/scan/util.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/scan/util.go
@@ -6,11 +6,12 @@ package scan
 
 import (
 	"fmt"
+	"os"
+	"os/exec"
+	"strings"
 
 	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	isem "golang.org/x/vuln/internal/semver"
 )
 
 // validateFindings checks that the supplied findings all obey the protocol
@@ -25,48 +26,19 @@ func validateFindings(findings ...*govulncheck.Finding) error {
 		}
 		for _, frame := range f.Trace {
 			if frame.Version != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Version is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Version (%s) is set, Frame.Module must also be", frame.Version)
 			}
 			if frame.Package != "" && frame.Module == "" {
-				return fmt.Errorf("invalid finding: if Frame.Package is set, Frame.Module must also be")
+				return fmt.Errorf("invalid finding: if Frame.Package (%s) is set, Frame.Module must also be", frame.Package)
 			}
 			if frame.Function != "" && frame.Package == "" {
-				return fmt.Errorf("invalid finding: if Frame.Function is set, Frame.Package must also be")
+				return fmt.Errorf("invalid finding: if Frame.Function (%s) is set, Frame.Package must also be", frame.Function)
 			}
 		}
 	}
 	return nil
 }
 
-// latestFixed returns the latest fixed version in the list of affected ranges,
-// or the empty string if there are no fixed versions.
-func latestFixed(modulePath string, as []osv.Affected) string {
-	v := ""
-	for _, a := range as {
-		if modulePath != a.Module.Path {
-			continue
-		}
-		fixed := isem.LatestFixedVersion(a.Ranges)
-		// Special case: if there is any affected block for this module
-		// with no fix, the module is considered unfixed.
-		if fixed == "" {
-			return ""
-		}
-		if isem.Less(v, fixed) {
-			v = fixed
-		}
-	}
-	return v
-}
-
-func fixedVersion(modulePath string, affected []osv.Affected) string {
-	fixed := latestFixed(modulePath, affected)
-	if fixed != "" {
-		fixed = "v" + fixed
-	}
-	return fixed
-}
-
 func moduleVersionString(modulePath, version string) string {
 	if version == "" {
 		return ""
@@ -76,3 +48,13 @@ func moduleVersionString(modulePath, version string) string {
 	}
 	return version
 }
+
+func gomodExists(dir string) bool {
+	cmd := exec.Command("go", "env", "GOMOD")
+	cmd.Dir = dir
+	out, err := cmd.Output()
+	output := strings.TrimSpace(string(out))
+	// If module-aware mode is enabled, but there is no go.mod, GOMOD will be os.DevNull
+	// If module-aware mode is disabled, GOMOD will be the empty string.
+	return err == nil && !(output == os.DevNull || output == "")
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/semver/affects.go b/public-api/vendor/golang.org/x/vuln/internal/semver/affects.go
index 603d8277..03ea6fd7 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/semver/affects.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/semver/affects.go
@@ -21,7 +21,7 @@ func Affects(a []osv.Range, v string) bool {
 			continue
 		}
 		semverRangePresent = true
-		if containsSemver(r, v) {
+		if ContainsSemver(r, v) {
 			return true
 		}
 	}
@@ -32,9 +32,10 @@ func Affects(a []osv.Range, v string) bool {
 	return !semverRangePresent
 }
 
-// containsSemver checks if semver version v is in the
+// ContainsSemver checks if semver version v is in the
 // range encoded by ar. If ar is not a semver range,
-// returns false.
+// returns false. A range is interpreted as a left-closed
+// and right-open interval.
 //
 // Assumes that
 //   - exactly one of Introduced or Fixed fields is set
@@ -42,7 +43,7 @@ func Affects(a []osv.Range, v string) bool {
 //   - beginning of time is encoded with .Introduced="0"
 //   - no-fix is not an event, as opposed to being an
 //     event where Introduced="" and Fixed=""
-func containsSemver(ar osv.Range, v string) bool {
+func ContainsSemver(ar osv.Range, v string) bool {
 	if ar.Type != osv.RangeTypeSemver {
 		return false
 	}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/semver/fixed.go b/public-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
index 152fc1de..bd29c407 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/semver/fixed.go
@@ -6,7 +6,11 @@ package semver
 
 import "golang.org/x/vuln/internal/osv"
 
-func LatestFixedVersion(ranges []osv.Range) string {
+// NonSupersededFix returns a fixed version from ranges
+// that is not superseded by any other fix or any other
+// introduction of a vulnerability. Returns "" in case
+// there is no such fixed version.
+func NonSupersededFix(ranges []osv.Range) string {
 	var latestFixed string
 	for _, r := range ranges {
 		if r.Type == "SEMVER" {
@@ -16,6 +20,7 @@ func LatestFixedVersion(ranges []osv.Range) string {
 					latestFixed = fixed
 				}
 			}
+
 			// If the vulnerability was re-introduced after the latest fix
 			// we found, there is no latest fix for this range.
 			for _, e := range r.Events {
diff --git a/public-api/vendor/golang.org/x/vuln/internal/semver/semver.go b/public-api/vendor/golang.org/x/vuln/internal/semver/semver.go
index fe0f701b..efe1e006 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/semver/semver.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/semver/semver.go
@@ -7,6 +7,7 @@
 package semver
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -93,3 +94,47 @@ func GoTagToSemver(tag string) string {
 	}
 	return version
 }
+
+// This is a modified copy of pkgsite/internal/stlib:TagForVersion
+func SemverToGoTag(v string) string {
+	// Special case: v1.0.0 => go1.
+	if v == "v1.0.0" {
+		return "go1"
+	}
+
+	goVersion := semver.Canonical(v)
+	prerelease := semver.Prerelease(goVersion)
+	versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease)
+	patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".")
+	if patch == "0" && (semver.Compare(v, "v1.21.0") < 0 || prerelease != "") {
+		// Starting with go1.21.0, the first patch version includes .0.
+		// Prereleases do not include .0 (we don't do prereleases for other patch releases).
+		versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0")
+	}
+	goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v"))
+	if prerelease != "" {
+		i := finalDigitsIndex(prerelease)
+		if i >= 1 {
+			// Remove the dot.
+			prerelease = prerelease[:i-1] + prerelease[i:]
+		}
+		goVersion += prerelease
+	}
+	return goVersion
+}
+
+// finalDigitsIndex returns the index of the first digit in the sequence of digits ending s.
+// If s doesn't end in digits, it returns -1.
+func finalDigitsIndex(s string) int {
+	// Assume ASCII (since the semver package does anyway).
+	var i int
+	for i = len(s) - 1; i >= 0; i-- {
+		if s[i] < '0' || s[i] > '9' {
+			break
+		}
+	}
+	if i == len(s)-1 {
+		return -1
+	}
+	return i + 1
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/traces/traces.go b/public-api/vendor/golang.org/x/vuln/internal/traces/traces.go
new file mode 100644
index 00000000..e413ae7d
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/traces/traces.go
@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package traces
+
+import (
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// Compact returns a summarization of finding.Trace. The first
+// returned element is the vulnerable symbol and the last element
+// is the exit point of the user module. There can also be two
+// elements in between, if applicable, which are the two elements
+// preceding the user module exit point.
+func Compact(finding *govulncheck.Finding) []*govulncheck.Frame {
+	if len(finding.Trace) < 1 {
+		return nil
+	}
+	iTop := len(finding.Trace) - 1
+	topModule := finding.Trace[iTop].Module
+	// search for the exit point of the top module
+	for i, frame := range finding.Trace {
+		if frame.Module == topModule {
+			iTop = i
+			break
+		}
+	}
+
+	if iTop == 0 {
+		// all in one module, reset to the end
+		iTop = len(finding.Trace) - 1
+	}
+
+	compact := []*govulncheck.Frame{finding.Trace[0]}
+	if iTop > 1 {
+		if iTop > 2 {
+			compact = append(compact, finding.Trace[iTop-2])
+		}
+		compact = append(compact, finding.Trace[iTop-1])
+	}
+	if iTop > 0 {
+		compact = append(compact, finding.Trace[iTop])
+	}
+	return compact
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
index a35a3a0a..d78af3ff 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/binary.go
@@ -2,120 +2,184 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build go1.18
-// +build go1.18
-
 package vulncheck
 
 import (
 	"context"
 	"fmt"
-	"io"
-	"runtime/debug"
 
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/buildinfo"
 	"golang.org/x/vuln/internal/client"
 	"golang.org/x/vuln/internal/govulncheck"
-	"golang.org/x/vuln/internal/osv"
-	"golang.org/x/vuln/internal/vulncheck/internal/buildinfo"
+	"golang.org/x/vuln/internal/semver"
 )
 
-// Binary detects presence of vulnerable symbols in exe.
-// The Calls, Imports, and Requires fields on Result will be empty.
-func Binary(ctx context.Context, exe io.ReaderAt, cfg *govulncheck.Config, client *client.Client) (_ *Result, err error) {
-	mods, packageSymbols, bi, err := buildinfo.ExtractPackagesAndSymbols(exe)
+// Bin is an abstraction of Go binary containing
+// minimal information needed by govulncheck.
+type Bin struct {
+	// Path of the main package.
+	Path string `json:"path,omitempty"`
+	// Main module. When present, it never has empty information.
+	Main       *packages.Module   `json:"main,omitempty"`
+	Modules    []*packages.Module `json:"modules,omitempty"`
+	PkgSymbols []buildinfo.Symbol `json:"pkgSymbols,omitempty"`
+	GoVersion  string             `json:"goVersion,omitempty"`
+	GOOS       string             `json:"goos,omitempty"`
+	GOARCH     string             `json:"goarch,omitempty"`
+}
+
+// Binary detects presence of vulnerable symbols in bin and
+// emits findings to handler.
+func Binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) error {
+	vr, err := binary(ctx, handler, bin, cfg, client)
 	if err != nil {
-		return nil, fmt.Errorf("could not parse provided binary: %v", err)
+		return err
+	}
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, binaryCallstacks(vr))
+	}
+	return nil
+}
+
+// binary detects presence of vulnerable symbols in bin.
+// It does not compute call graphs so the corresponding
+// info in Result will be empty.
+func binary(ctx context.Context, handler govulncheck.Handler, bin *Bin, cfg *govulncheck.Config, client *client.Client) (*Result, error) {
+	graph := NewPackageGraph(bin.GoVersion)
+	mods := append(bin.Modules, graph.GetModule(internal.GoStdModulePath))
+
+	if bin.Main != nil {
+		mods = append(mods, bin.Main)
 	}
 
-	graph := NewPackageGraph(bi.GoVersion)
 	graph.AddModules(mods...)
-	mods = append(mods, graph.GetModule(internal.GoStdModulePath))
+
+	if err := handler.SBOM(bin.SBOM()); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
+	}
 
 	mv, err := FetchVulnerabilities(ctx, client, mods)
 	if err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
 
-	goos := findSetting("GOOS", bi)
-	goarch := findSetting("GOARCH", bi)
-	if goos == "" || goarch == "" {
-		fmt.Printf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", goos, goarch)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
+
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingBinVulnsMessage}); err != nil {
+		return nil, err
+	}
+
+	// Emit warning message for ancient Go binaries, defined as binaries
+	// built with Go version without support for debug.BuildInfo (< go1.18).
+	if semver.Valid(bin.GoVersion) && semver.Less(bin.GoVersion, "go1.18") {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: binary built with Go version %s, only standard library vulnerabilities will be checked", bin.GoVersion)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+
+	if bin.GOOS == "" || bin.GOARCH == "" {
+		p := &govulncheck.Progress{Message: fmt.Sprintf("warning: failed to extract build system specification GOOS: %s GOARCH: %s\n", bin.GOOS, bin.GOARCH)}
+		if err := handler.Progress(p); err != nil {
+			return nil, err
+		}
+	}
+	affVulns := affectingVulnerabilities(mv, bin.GOOS, bin.GOARCH)
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
 
-	modVulns = modVulns.filter(goos, goarch)
-	result := &Result{}
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
+	}
 
-	if packageSymbols == nil {
+	// Group symbols per package to avoid querying affVulns all over again.
+	var pkgSymbols map[string][]string
+	if len(bin.PkgSymbols) == 0 {
 		// The binary exe is stripped. We currently cannot detect inlined
 		// symbols for stripped binaries (see #57764), so we report
 		// vulnerabilities at the go.mod-level precision.
-		addRequiresOnlyVulns(result, graph, modVulns)
+		pkgSymbols = allKnownVulnerableSymbols(affVulns)
 	} else {
-		for pkg, symbols := range packageSymbols {
-			if !cfg.ScanLevel.WantSymbols() {
-				addImportsOnlyVulns(result, graph, pkg, symbols, modVulns)
-			} else {
-				addSymbolVulns(result, graph, pkg, symbols, modVulns)
-			}
-		}
+		pkgSymbols = packagesAndSymbols(bin)
 	}
-	return result, nil
-}
 
-// addImportsOnlyVulns adds Vuln entries to result in imports only mode, i.e., for each vulnerable symbol
-// of pkg.
-func addImportsOnlyVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, osv := range modVulns.vulnsForPackage(pkg) {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg {
-					continue
-				}
-				syms := p.Symbols
-				if len(syms) == 0 {
-					// If every symbol of pkg is vulnerable, we would ideally
-					// compute every symbol mentioned in the pkg and then add
-					// Vuln entry for it, just as we do in Source. However,
-					// we don't have code of pkg here so we have to do best
-					// we can, which is the symbols of pkg actually appearing
-					// in the binary.
-					syms = symbols
-				}
+	impVulns := binImportedVulnPackages(graph, pkgSymbols, affVulns)
+	// Emit information on imported vulnerable packages now to
+	// mimic behavior of source.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
+	}
 
-				for _, symbol := range syms {
-					addVuln(result, graph, osv, symbol, pkg)
-				}
-			}
+	// Return result immediately if not in symbol mode to mimic the
+	// behavior of source.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
+
+	symVulns := binVulnSymbols(graph, pkgSymbols, affVulns)
+	return &Result{Vulns: symVulns}, nil
+}
+
+func packagesAndSymbols(bin *Bin) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, sym := range bin.PkgSymbols {
+		// If the name of the package is main, we need to expand
+		// it to its full path as that is what vuln db uses.
+		if sym.Pkg == "main" && bin.Path != "" {
+			pkgSymbols[bin.Path] = append(pkgSymbols[bin.Path], sym.Name)
+		} else {
+			pkgSymbols[sym.Pkg] = append(pkgSymbols[sym.Pkg], sym.Name)
 		}
 	}
+	return pkgSymbols
 }
 
-// addSymbolVulns adds Vuln entries to result for every symbol of pkg in the binary that is vulnerable.
-func addSymbolVulns(result *Result, graph *PackageGraph, pkg string, symbols []string, modVulns moduleVulnerabilities) {
-	for _, symbol := range symbols {
-		for _, osv := range modVulns.vulnsForSymbol(pkg, symbol) {
-			addVuln(result, graph, osv, symbol, pkg)
+func binImportedVulnPackages(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg := range pkgSymbols {
+		for _, osv := range affVulns.ForPackage(internal.UnknownModulePath, pkg) {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg),
+			}
+			vulns = append(vulns, vuln)
 		}
 	}
+	return vulns
 }
 
-// findSetting returns value of setting from bi if present.
-// Otherwise, returns "".
-func findSetting(setting string, bi *debug.BuildInfo) string {
-	for _, s := range bi.Settings {
-		if s.Key == setting {
-			return s.Value
+func binVulnSymbols(graph *PackageGraph, pkgSymbols map[string][]string, affVulns affectingVulns) []*Vuln {
+	var vulns []*Vuln
+	for pkg, symbols := range pkgSymbols {
+		for _, symbol := range symbols {
+			for _, osv := range affVulns.ForSymbol(internal.UnknownModulePath, pkg, symbol) {
+				vuln := &Vuln{
+					OSV:     osv,
+					Symbol:  symbol,
+					Package: graph.GetPackage(pkg),
+				}
+				vulns = append(vulns, vuln)
+			}
 		}
 	}
-	return ""
+	return vulns
 }
 
-// addRequiresOnlyVulns adds to result all vulnerabilities in modVulns.
-// Used when the binary under analysis is stripped.
-func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVulnerabilities) {
-	for _, mv := range modVulns {
+// allKnownVulnerableSymbols returns all known vulnerable symbols for packages in graph.
+// If all symbols of a package are vulnerable, that is modeled as a wild car symbol "/*".
+func allKnownVulnerableSymbols(affVulns affectingVulns) map[string][]string {
+	pkgSymbols := make(map[string][]string)
+	for _, mv := range affVulns {
 		for _, osv := range mv.Vulns {
 			for _, affected := range osv.Affected {
 				for _, p := range affected.EcosystemSpecific.Packages {
@@ -134,19 +198,40 @@ func addRequiresOnlyVulns(result *Result, graph *PackageGraph, modVulns moduleVu
 						syms = []string{fmt.Sprintf("%s/*", p.Path)}
 					}
 
-					for _, symbol := range syms {
-						addVuln(result, graph, osv, symbol, p.Path)
-					}
+					pkgSymbols[p.Path] = append(pkgSymbols[p.Path], syms...)
 				}
 			}
 		}
 	}
+	return pkgSymbols
 }
 
-func addVuln(result *Result, graph *PackageGraph, osv *osv.Entry, symbol string, pkgPath string) {
-	result.Vulns = append(result.Vulns, &Vuln{
-		OSV:        osv,
-		Symbol:     symbol,
-		ImportSink: graph.GetPackage(pkgPath),
+func (bin *Bin) SBOM() (sbom *govulncheck.SBOM) {
+	sbom = &govulncheck.SBOM{}
+	if bin.Main != nil {
+		sbom.Roots = []string{bin.Main.Path}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    bin.Main.Path,
+			Version: bin.Main.Version,
+		})
+	}
+
+	sbom.GoVersion = bin.GoVersion
+	for _, mod := range bin.Modules {
+		if mod.Replace != nil {
+			mod = mod.Replace
+		}
+		sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		})
+	}
+
+	// add stdlib to mirror source mode output
+	sbom.Modules = append(sbom.Modules, &govulncheck.Module{
+		Path:    internal.GoStdModulePath,
+		Version: bin.GoVersion,
 	})
+
+	return sbom
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
index 3f19e299..e56cdfbc 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/doc.go
@@ -24,8 +24,7 @@ detection in Go source code and binaries, respectively.
 
 [Source] accepts a list of [Package] objects, which
 are a trimmed version of [golang.org/x/tools/go/packages.Package] objects to
-reduce memory consumption. [Binary] accepts a path to a Go binary file that
-must have been compiled with Go 1.18 or greater.
+reduce memory consumption. [Binary] accepts a path to a Go binary file.
 
 Both [Source] and [Binary] require information about known
 vulnerabilities in the form of a vulnerability database,
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
new file mode 100644
index 00000000..fc9b2d7a
--- /dev/null
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/emit.go
@@ -0,0 +1,198 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vulncheck
+
+import (
+	"go/token"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/vuln/internal/govulncheck"
+)
+
+// emitOSVs emits all OSV vuln entries in modVulns to handler.
+func emitOSVs(handler govulncheck.Handler, modVulns []*ModVulns) error {
+	for _, mv := range modVulns {
+		for _, v := range mv.Vulns {
+			if err := handler.OSV(v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitModuleFindings emits module-level findings for vulnerabilities in modVulns.
+func emitModuleFindings(handler govulncheck.Handler, affVulns affectingVulns) error {
+	for _, vuln := range affVulns {
+		for _, osv := range vuln.Vulns {
+			if err := handler.Finding(&govulncheck.Finding{
+				OSV:          osv.ID,
+				FixedVersion: FixedVersion(modPath(vuln.Module), modVersion(vuln.Module), osv.Affected),
+				Trace:        []*govulncheck.Frame{frameFromModule(vuln.Module)},
+			}); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// emitPackageFinding emits package-level findings fod vulnerabilities in vulns.
+func emitPackageFindings(handler govulncheck.Handler, vulns []*Vuln) error {
+	for _, v := range vulns {
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          v.OSV.ID,
+			FixedVersion: FixedVersion(modPath(v.Package.Module), modVersion(v.Package.Module), v.OSV.Affected),
+			Trace:        []*govulncheck.Frame{frameFromPackage(v.Package)},
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// emitCallFindings emits call-level findings for vulnerabilities
+// that have a call stack in callstacks.
+func emitCallFindings(handler govulncheck.Handler, callstacks map[*Vuln]CallStack) error {
+	var vulns []*Vuln
+	for v := range callstacks {
+		vulns = append(vulns, v)
+	}
+
+	for _, vuln := range vulns {
+		stack := callstacks[vuln]
+		if stack == nil {
+			continue
+		}
+		fixed := FixedVersion(modPath(vuln.Package.Module), modVersion(vuln.Package.Module), vuln.OSV.Affected)
+		if err := handler.Finding(&govulncheck.Finding{
+			OSV:          vuln.OSV.ID,
+			FixedVersion: fixed,
+			Trace:        traceFromEntries(stack),
+		}); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// traceFromEntries creates a sequence of
+// frames from vcs. Position of a Frame is the
+// call position of the corresponding stack entry.
+func traceFromEntries(vcs CallStack) []*govulncheck.Frame {
+	var frames []*govulncheck.Frame
+	for i := len(vcs) - 1; i >= 0; i-- {
+		e := vcs[i]
+		fr := frameFromPackage(e.Function.Package)
+		fr.Function = e.Function.Name
+		fr.Receiver = e.Function.Receiver()
+		isSink := i == (len(vcs) - 1)
+		fr.Position = posFromStackEntry(e, isSink)
+		frames = append(frames, fr)
+	}
+	return frames
+}
+
+func posFromStackEntry(e StackEntry, sink bool) *govulncheck.Position {
+	var p *token.Position
+	var f *FuncNode
+	if sink && e.Function != nil && e.Function.Pos != nil {
+		// For sinks, i.e., vulns we take the position
+		// of the symbol.
+		p = e.Function.Pos
+		f = e.Function
+	} else if e.Call != nil && e.Call.Pos != nil {
+		// Otherwise, we take the position of
+		// the call statement.
+		p = e.Call.Pos
+		f = e.Call.Parent
+	}
+
+	if p == nil {
+		return nil
+	}
+	return &govulncheck.Position{
+		Filename: pathRelativeToMod(p.Filename, f),
+		Offset:   p.Offset,
+		Line:     p.Line,
+		Column:   p.Column,
+	}
+}
+
+// pathRelativeToMod computes a version of path
+// relative to the module of f. If it does not
+// have all the necessary information, returns
+// an empty string.
+//
+// The returned paths always use slash as separator
+// so they can work across different platforms.
+func pathRelativeToMod(path string, f *FuncNode) string {
+	if path == "" || f == nil || f.Package == nil { // sanity
+		return ""
+	}
+
+	mod := f.Package.Module
+	if mod.Replace != nil {
+		mod = mod.Replace // for replace directive
+	}
+
+	modDir := modDirWithVendor(mod.Dir, path, mod.Path)
+	p, err := filepath.Rel(modDir, path)
+	if err != nil {
+		return ""
+	}
+	// make sure paths are portable.
+	return filepath.ToSlash(p)
+}
+
+// modDirWithVendor returns modDir if modDir is not empty.
+// Otherwise, the module might be located in the vendor
+// directory. This function attempts to reconstruct the
+// vendored module directory from path and module. It
+// returns an empty string if reconstruction fails.
+func modDirWithVendor(modDir, path, module string) string {
+	if modDir != "" {
+		return modDir
+	}
+
+	sep := string(os.PathSeparator)
+	vendor := sep + "vendor" + sep
+	vendorIndex := strings.Index(path, vendor)
+	if vendorIndex == -1 {
+		return ""
+	}
+	return filepath.Join(path[:vendorIndex], "vendor", filepath.FromSlash(module))
+}
+
+func frameFromPackage(pkg *packages.Package) *govulncheck.Frame {
+	fr := &govulncheck.Frame{}
+	if pkg != nil {
+		fr.Module = pkg.Module.Path
+		fr.Version = pkg.Module.Version
+		fr.Package = pkg.PkgPath
+	}
+	if pkg.Module.Replace != nil {
+		fr.Module = pkg.Module.Replace.Path
+		fr.Version = pkg.Module.Replace.Version
+	}
+	return fr
+}
+
+func frameFromModule(mod *packages.Module) *govulncheck.Frame {
+	fr := &govulncheck.Frame{
+		Module:  mod.Path,
+		Version: mod.Version,
+	}
+
+	if mod.Replace != nil {
+		fr.Module = mod.Replace.Path
+		fr.Version = mod.Replace.Version
+	}
+
+	return fr
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
index 834d5901..3d46f6ca 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/entries.go
@@ -10,6 +10,12 @@ import (
 	"golang.org/x/tools/go/ssa"
 )
 
+// entryPoints returns functions of topPackages considered entry
+// points of govulncheck analysis: main, inits, and exported methods
+// and functions.
+//
+// TODO(https://go.dev/issue/57221): currently, entry functions
+// that are generics are not considered an entry point.
 func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
 	var entries []*ssa.Function
 	for _, pkg := range topPackages {
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
index ef0c7ca9..700a7f99 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/fetch.go
@@ -6,6 +6,7 @@ package vulncheck
 
 import (
 	"context"
+	"fmt"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal/client"
@@ -25,7 +26,7 @@ func FetchVulnerabilities(ctx context.Context, c *client.Client, modules []*pack
 	}
 	resps, err := c.ByModules(ctx, mreqs)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("fetching vulnerabilities: %v", err)
 	}
 	var mv []*ModVulns
 	for i, resp := range resps {
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
deleted file mode 100644
index 1bdd38c7..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_buildinfo.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// This file adds to buildinfo the functionality for extracting the PCLN table.
-
-import (
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-)
-
-// ErrNoSymbols represents non-existence of symbol
-// table in binaries supported by buildinfo.
-var ErrNoSymbols = errors.New("no symbol section")
-
-// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
-func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		if errors.Is(err, elf.ErrNoSymbols) {
-			return 0, 0, nil, ErrNoSymbols
-		}
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	prog := x.progContaining(sym.Value)
-	if prog == nil {
-		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
-}
-
-func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		syms, err := x.f.Symbols()
-		if err != nil {
-			x.symbolsErr = err
-			return
-		}
-		x.symbols = make(map[string]*elf.Symbol, len(syms))
-		for _, s := range syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-func (x *elfExe) progContaining(addr uint64) *elf.Prog {
-	for _, p := range x.f.Progs {
-		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
-			return p
-		}
-	}
-	return nil
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
-	var offset uint64
-	text := x.f.Section(".text")
-	if text != nil {
-		offset = text.Offset
-	}
-	pclntab := x.f.Section(".gopclntab")
-	if pclntab == nil {
-		// Addition: this code is added to support some form of stripping.
-		pclntab = x.f.Section(".data.rel.ro.gopclntab")
-		if pclntab == nil {
-			pclntab = x.f.Section(".data.rel.ro")
-			if pclntab == nil {
-				return nil, 0
-			}
-			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
-			// its own section header. We can search for for the start by looking for the four
-			// byte magic and the go magic.
-			b, err := pclntab.Data()
-			if err != nil {
-				return nil, 0
-			}
-			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
-			// actually correct. During testing it worked, but that may be because I got lucky
-			// with the binary I was using, and we need to do four byte jumps to exhaustively
-			// search the section?
-			for i := 0; i < len(b); i += 16 {
-				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
-					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
-					(b[i+7] == 4 || b[i+7] == 8) {
-					// Also check for the go magic
-					leMagic := binary.LittleEndian.Uint32(b[i:])
-					beMagic := binary.BigEndian.Uint32(b[i:])
-					switch {
-					case leMagic == go12magic:
-						fallthrough
-					case beMagic == go12magic:
-						fallthrough
-					case leMagic == go116magic:
-						fallthrough
-					case beMagic == go116magic:
-						return b[i:], offset
-					}
-				}
-			}
-		}
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, offset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
-func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym, err := x.lookupSymbol(name)
-	if err != nil {
-		return 0, 0, nil, err
-	}
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	sect := x.f.Sections[sym.SectionNumber-1]
-	// In PE, the symbol's value is the offset from the section start.
-	return uint64(sym.Value), 0, sect.ReaderAt, nil
-}
-
-func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
-		if len(x.f.Symbols) == 0 {
-			x.symbolsErr = ErrNoSymbols
-			return
-		}
-		for _, s := range x.f.Symbols {
-			x.symbols[s.Name] = s
-		}
-	})
-	if x.symbolsErr != nil {
-		return nil, x.symbolsErr
-	}
-	return x.symbols[name], nil
-}
-
-// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
-// Assumes that the underlying symbol table exists, otherwise
-// it might panic.
-func (x *peExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	for _, section := range x.f.Sections {
-		if section.Name == ".text" {
-			textOffset = uint64(section.Offset)
-			break
-		}
-	}
-
-	var start, end int64
-	var section int
-	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
-		start = int64(s.Value)
-		section = int(s.SectionNumber - 1)
-	}
-	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
-		end = int64(s.Value)
-	}
-	if start == 0 || end == 0 {
-		return nil, 0
-	}
-	offset := int64(x.f.Sections[section].Offset) + start
-	size := end - start
-
-	pclntab := make([]byte, size)
-	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
-		return nil, 0
-	}
-	return pclntab, textOffset
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
-func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
-	sym := x.lookupSymbol(name)
-	if sym == nil {
-		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
-	}
-	seg := x.segmentContaining(sym.Value)
-	if seg == nil {
-		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
-	}
-	return sym.Value, seg.Addr, seg.ReaderAt, nil
-}
-
-func (x *machoExe) lookupSymbol(name string) *macho.Symbol {
-	x.symbolsOnce.Do(func() {
-		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
-		for _, s := range x.f.Symtab.Syms {
-			s := s // make a copy to prevent aliasing
-			x.symbols[s.Name] = &s
-		}
-	})
-	return x.symbols[name]
-}
-
-func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
-			return seg
-		}
-	}
-	return nil
-}
-
-// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	text := x.f.Section("__text")
-	if text != nil {
-		textOffset = uint64(text.Offset)
-	}
-	pclntab := x.f.Section("__gopclntab")
-	if pclntab == nil {
-		return nil, 0
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, textOffset
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
deleted file mode 100644
index 9790cfa9..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/additions_scan.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
-	"debug/buildinfo"
-	"errors"
-	"fmt"
-	"io"
-	"net/url"
-	"runtime/debug"
-	"sort"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/internal/vulncheck/internal/gosym"
-)
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
-	packagesModules := make([]*packages.Module, len(debugModules))
-	for i, mod := range debugModules {
-		packagesModules[i] = &packages.Module{
-			Path:    mod.Path,
-			Version: mod.Version,
-		}
-		if mod.Replace != nil {
-			packagesModules[i].Replace = &packages.Module{
-				Path:    mod.Replace.Path,
-				Version: mod.Replace.Version,
-			}
-		}
-	}
-	return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts symbols, packages, modules from
-// bin as well as bin's metadata.
-//
-// If the symbol table is not available, such as in the case of stripped
-// binaries, returns module and binary info but without the symbol info.
-func ExtractPackagesAndSymbols(bin io.ReaderAt) ([]*packages.Module, map[string][]string, *debug.BuildInfo, error) {
-	bi, err := buildinfo.Read(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	funcSymName := gosym.FuncSymName(bi.GoVersion)
-	if funcSymName == "" {
-		return nil, nil, nil, fmt.Errorf("binary built using unsupported Go version: %q", bi.GoVersion)
-	}
-
-	x, err := openExe(bin)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	value, base, r, err := x.SymbolInfo(funcSymName)
-	if err != nil {
-		if errors.Is(err, ErrNoSymbols) {
-			// bin is stripped, so return just module info and metadata.
-			return debugModulesToPackagesModules(bi.Deps), nil, bi, nil
-		}
-		return nil, nil, nil, fmt.Errorf("reading %v: %v", funcSymName, err)
-	}
-
-	pclntab, textOffset := x.PCLNTab()
-	if pclntab == nil {
-		// TODO(https://go.dev/issue/59731): if we have build information, but
-		// not PCLN table, we should be able to fall back to much higher
-		// granularity vulnerability checking.
-		return nil, nil, nil, errors.New("unable to load the PCLN table")
-	}
-	lineTab := gosym.NewLineTable(pclntab, textOffset)
-	if lineTab == nil {
-		return nil, nil, nil, errors.New("invalid line table")
-	}
-	tab, err := gosym.NewTable(nil, lineTab)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	type pkgSymbol struct {
-		pkg string
-		sym string
-	}
-	pkgSyms := make(map[pkgSymbol]bool)
-	for _, f := range tab.Funcs {
-		if f.Func == nil {
-			continue
-		}
-		pkgName, symName, err := parseName(f.Func.Sym)
-		if err != nil {
-			return nil, nil, nil, err
-		}
-		pkgSyms[pkgSymbol{pkgName, symName}] = true
-
-		// Collect symbols that were inlined in f.
-		it, err := lineTab.InlineTree(&f, value, base, r)
-		if err != nil {
-			return nil, nil, nil, fmt.Errorf("InlineTree: %v", err)
-		}
-		for _, ic := range it {
-			pkgName, symName, err := parseName(&gosym.Sym{Name: ic.Name})
-			if err != nil {
-				return nil, nil, nil, err
-			}
-			pkgSyms[pkgSymbol{pkgName, symName}] = true
-		}
-	}
-
-	packageSymbols := make(map[string][]string)
-	for p := range pkgSyms {
-		packageSymbols[p.pkg] = append(packageSymbols[p.pkg], p.sym)
-	}
-	// Sort symbols per pkg for deterministic results.
-	for _, syms := range packageSymbols {
-		sort.Strings(syms)
-	}
-
-	return debugModulesToPackagesModules(bi.Deps), packageSymbols, bi, nil
-}
-
-func parseName(s *gosym.Sym) (pkg, sym string, err error) {
-	symName := s.BaseName()
-	if r := s.ReceiverName(); r != "" {
-		if strings.HasPrefix(r, "(*") {
-			r = strings.Trim(r, "(*)")
-		}
-		symName = fmt.Sprintf("%s.%s", r, symName)
-	}
-
-	pkgName := s.PackageName()
-	if pkgName != "" {
-		pkgName, err = url.PathUnescape(pkgName)
-		if err != nil {
-			return "", "", err
-		}
-	}
-	return pkgName, symName, nil
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
deleted file mode 100644
index 1be795ee..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/buildinfo/buildinfo.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.18
-// +build go1.18
-
-package buildinfo
-
-// Addition: this file is a trimmed and slightly modified version of debug/buildinfo/buildinfo.go
-
-import (
-	"bytes"
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"fmt"
-	"sync"
-
-	// "internal/xcoff"
-	"io"
-)
-
-// Addition: modification of rawBuildInfo in the original file.
-// openExe returns reader r as an exe.
-func openExe(r io.ReaderAt) (exe, error) {
-	data := make([]byte, 16)
-	if _, err := r.ReadAt(data, 0); err != nil {
-		return nil, err
-	}
-	if bytes.HasPrefix(data, []byte("\x7FELF")) {
-		e, err := elf.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &elfExe{f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("MZ")) {
-		e, err := pe.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &peExe{r: r, f: e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
-		e, err := macho.NewFile(r)
-		if err != nil {
-			return nil, err
-		}
-		return &machoExe{f: e}, nil
-	}
-	return nil, fmt.Errorf("unrecognized executable format")
-}
-
-type exe interface {
-	// ReadData reads and returns up to size byte starting at virtual address addr.
-	ReadData(addr, size uint64) ([]byte, error)
-
-	// DataStart returns the virtual address of the segment or section that
-	// should contain build information. This is either a specially named section
-	// or the first writable non-zero data segment.
-	DataStart() uint64
-
-	PCLNTab() ([]byte, uint64) // Addition: for constructing symbol table
-
-	SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) // Addition: for inlining purposes
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
-	f *elf.File
-
-	symbols     map[string]*elf.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once              // Addition: for computing symbols
-	symbolsErr  error                  // Addition: error for computing symbols
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, prog := range x.f.Progs {
-		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
-			n := prog.Vaddr + prog.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *elfExe) DataStart() uint64 {
-	for _, s := range x.f.Sections {
-		if s.Name == ".go.buildinfo" {
-			return s.Addr
-		}
-	}
-	for _, p := range x.f.Progs {
-		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
-			return p.Vaddr
-		}
-	}
-	return 0
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
-	r io.ReaderAt
-	f *pe.File
-
-	symbols     map[string]*pe.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once             // Addition: for computing symbols
-	symbolsErr  error                 // Addition: error for computing symbols
-}
-
-func (x *peExe) imageBase() uint64 {
-	switch oh := x.f.OptionalHeader.(type) {
-	case *pe.OptionalHeader32:
-		return uint64(oh.ImageBase)
-	case *pe.OptionalHeader64:
-		return oh.ImageBase
-	}
-	return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
-	addr -= x.imageBase()
-	for _, sect := range x.f.Sections {
-		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-			n := uint64(sect.VirtualAddress+sect.Size) - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *peExe) DataStart() uint64 {
-	// Assume data is first writable section.
-	const (
-		IMAGE_SCN_CNT_CODE               = 0x00000020
-		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-		IMAGE_SCN_MEM_READ               = 0x40000000
-		IMAGE_SCN_MEM_WRITE              = 0x80000000
-		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-	)
-	for _, sect := range x.f.Sections {
-		if sect.VirtualAddress != 0 && sect.Size != 0 &&
-			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
-			return uint64(sect.VirtualAddress) + x.imageBase()
-		}
-	}
-	return 0
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
-	f *macho.File
-
-	symbols     map[string]*macho.Symbol // Addition: symbols in the binary
-	symbolsOnce sync.Once                // Addition: for computing symbols
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if !ok {
-			continue
-		}
-		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
-			if seg.Name == "__PAGEZERO" {
-				continue
-			}
-			n := seg.Addr + seg.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped") // Addition: custom error
-}
-
-func (x *machoExe) DataStart() uint64 {
-	// Look for section named "__go_buildinfo".
-	for _, sec := range x.f.Sections {
-		if sec.Name == "__go_buildinfo" {
-			return sec.Addr
-		}
-	}
-	// Try the first non-empty writable segment.
-	const RW = 3
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
-			return seg.Addr
-		}
-	}
-	return 0
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
deleted file mode 100644
index f608c151..00000000
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/internal/gosym/additions.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gosym
-
-import (
-	"encoding/binary"
-	"io"
-	"strings"
-
-	sv "golang.org/x/mod/semver"
-	"golang.org/x/vuln/internal/semver"
-)
-
-const (
-	funcSymNameGo119Lower string = "go.func.*"
-	funcSymNameGo120      string = "go:func.*"
-)
-
-// FuncSymName returns symbol name for Go functions
-// used in binaries based on Go version. Supported
-// Go versions are 1.18, 1.19, and 1.20. Otherwise,
-// returns an empty string.
-func FuncSymName(goVersion string) string {
-	// Support devel goX.Y...
-	v := strings.TrimPrefix(goVersion, "devel ")
-	v = semver.GoTagToSemver(v)
-	mm := sv.MajorMinor(v)
-	if mm == "v1.18" || mm == "v1.19" {
-		return funcSymNameGo119Lower
-	} else if mm == "v1.20" {
-		return funcSymNameGo120
-	} else if v == "" && strings.HasPrefix(goVersion, "devel") {
-		// We currently don't have a direct way of mapping
-		// Go versions of the form devel  to semver,
-		// so we map it to the most recent supported major
-		// Go version, which is currently go1.20.
-		return funcSymNameGo120
-	}
-	return ""
-}
-
-// Additions to the original package from cmd/internal/objabi/funcdata.go
-const (
-	pcdata_InlTreeIndex = 2
-	funcdata_InlTree    = 3
-)
-
-// InlineTree returns the inline tree for Func f as a sequence of InlinedCalls.
-// goFuncValue is the value of the gosym.FuncSymName symbol.
-// baseAddr is the address of the memory region (ELF Prog) containing goFuncValue.
-// progReader is a ReaderAt positioned at the start of that region.
-func (t *LineTable) InlineTree(f *Func, goFuncValue, baseAddr uint64, progReader io.ReaderAt) ([]InlinedCall, error) {
-	if f.inlineTreeCount == 0 {
-		return nil, nil
-	}
-	if f.inlineTreeOffset == ^uint32(0) {
-		return nil, nil
-	}
-	var offset int64
-	if t.version >= ver118 {
-		offset = int64(goFuncValue - baseAddr + uint64(f.inlineTreeOffset))
-	} else {
-		offset = int64(uint64(f.inlineTreeOffset) - baseAddr)
-	}
-
-	r := io.NewSectionReader(progReader, offset, 1<<32) // pick a size larger than we need
-	var ics []InlinedCall
-	for i := 0; i < f.inlineTreeCount; i++ {
-		if t.version >= ver120 {
-			var ric rawInlinedCall120
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.NameOff)),
-				ParentPC: ric.ParentPC,
-			})
-		} else {
-			var ric rawInlinedCall112
-			if err := binary.Read(r, t.binary, &ric); err != nil {
-				return nil, err
-			}
-			ics = append(ics, InlinedCall{
-				FuncID:   ric.FuncID,
-				Name:     t.funcName(uint32(ric.Func_)),
-				ParentPC: ric.ParentPC,
-			})
-		}
-	}
-	return ics, nil
-}
-
-// InlinedCall describes a call to an inlined function.
-type InlinedCall struct {
-	FuncID   uint8  // type of the called function
-	Name     string // name of called function
-	ParentPC int32  // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall112 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.12 through 1.19. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall112 struct {
-	Parent   int16 // index of parent in the inltree, or < 0
-	FuncID   uint8 // type of the called function
-	_        byte
-	File     int32 // perCU file index for inlined call. See cmd/link:pcln.go
-	Line     int32 // line number of the call site
-	Func_    int32 // offset into pclntab for name of called function
-	ParentPC int32 // position of an instruction whose source position is the call site (offset from entry)
-}
-
-// rawInlinedCall120 is the encoding of entries in the FUNCDATA_InlTree table
-// from Go 1.20. It is equivalent to runtime.inlinedCall.
-type rawInlinedCall120 struct {
-	FuncID    uint8 // type of the called function
-	_         [3]byte
-	NameOff   int32 // offset into pclntab for name of called function
-	ParentPC  int32 // position of an instruction whose source position is the call site (offset from entry)
-	StartLine int32 // line number of start of function (func keyword/TEXT directive)
-}
-
-func (f funcData) npcdata() uint32 { return f.field(7) }
-func (f funcData) nfuncdata(numFuncFields uint32) uint32 {
-	return uint32(f.data[f.fieldOffset(numFuncFields-1)+3])
-}
-
-func (f funcData) funcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.nfuncdata(numFuncFields) {
-		return ^uint32(0)
-	}
-	var off uint32
-	if f.t.version >= ver118 {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4 + // skip pcdata
-			uint32(i)*4 // index of i'th FUNCDATA
-	} else {
-		off = f.fieldOffset(numFuncFields) + // skip fixed part of _func
-			f.npcdata()*4
-		off += uint32(i) * f.t.ptrsize
-	}
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-func (f funcData) fieldOffset(n uint32) uint32 {
-	// In Go 1.18, the first field of _func changed
-	// from a uintptr entry PC to a uint32 entry offset.
-	sz0 := f.t.ptrsize
-	if f.t.version >= ver118 {
-		sz0 = 4
-	}
-	return sz0 + (n-1)*4 // subsequent fields are 4 bytes each
-}
-
-func (f funcData) pcdataOffset(i uint8, numFuncFields uint32) uint32 {
-	if uint32(i) >= f.npcdata() {
-		return ^uint32(0)
-	}
-	off := f.fieldOffset(numFuncFields) + // skip fixed part of _func
-		uint32(i)*4 // index of i'th PCDATA
-	return f.t.binary.Uint32(f.data[off:])
-}
-
-// maxInlineTreeIndexValue returns the maximum value of the inline tree index
-// pc-value table in info. This is the only way to determine how many
-// IndexedCalls are in an inline tree, since the data of the tree itself is not
-// delimited in any way.
-func (t *LineTable) maxInlineTreeIndexValue(info funcData, numFuncFields uint32) int {
-	if info.npcdata() <= pcdata_InlTreeIndex {
-		return -1
-	}
-	off := info.pcdataOffset(pcdata_InlTreeIndex, numFuncFields)
-	p := t.pctab[off:]
-	val := int32(-1)
-	max := int32(-1)
-	var pc uint64
-	for t.step(&p, &pc, &val, pc == 0) {
-		if val > max {
-			max = val
-		}
-	}
-	return int(max)
-}
-
-type inlTree struct {
-	inlineTreeOffset uint32 // offset from go.func.* symbol
-	inlineTreeCount  int    // number of entries in inline tree
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
index 124a9a50..484e5494 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/packages.go
@@ -6,18 +6,25 @@ package vulncheck
 
 import (
 	"fmt"
+	"os/exec"
+	"slices"
 	"strings"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/vuln/internal"
+	"golang.org/x/vuln/internal/govulncheck"
 	"golang.org/x/vuln/internal/semver"
 )
 
 // PackageGraph holds a complete module and package graph.
-// Its primary purpose is to allow fast access to the nodes by path.
+// Its primary purpose is to allow fast access to the nodes
+// by path and make sure all(stdlib)  packages have a module.
 type PackageGraph struct {
-	modules  map[string]*packages.Module
-	packages map[string]*packages.Package
+	// topPkgs are top-level packages specified by the user.
+	// Empty in binary mode.
+	topPkgs  []*packages.Package
+	modules  map[string]*packages.Module  // all modules (even replacing ones)
+	packages map[string]*packages.Package // all packages (even dependencies)
 }
 
 func NewPackageGraph(goVersion string) *PackageGraph {
@@ -25,15 +32,83 @@ func NewPackageGraph(goVersion string) *PackageGraph {
 		modules:  map[string]*packages.Module{},
 		packages: map[string]*packages.Package{},
 	}
-	graph.AddModules(&packages.Module{
+
+	goRoot := ""
+	if out, err := exec.Command("go", "env", "GOROOT").Output(); err == nil {
+		goRoot = strings.TrimSpace(string(out))
+	}
+	stdlibModule := &packages.Module{
 		Path:    internal.GoStdModulePath,
 		Version: semver.GoTagToSemver(goVersion),
-	})
+		Dir:     goRoot,
+	}
+	graph.AddModules(stdlibModule)
 	return graph
 }
 
+func (g *PackageGraph) TopPkgs() []*packages.Package {
+	return g.topPkgs
+}
+
+// DepPkgs returns the number of packages that graph.TopPkgs()
+// strictly depend on. This does not include topPkgs even if
+// they are dependency of each other.
+func (g *PackageGraph) DepPkgs() []*packages.Package {
+	topPkgs := g.TopPkgs()
+	tops := make(map[string]bool)
+	depPkgs := make(map[string]*packages.Package)
+
+	for _, t := range topPkgs {
+		tops[t.PkgPath] = true
+	}
+
+	var visit func(*packages.Package, bool)
+	visit = func(p *packages.Package, top bool) {
+		path := p.PkgPath
+		if _, ok := depPkgs[path]; ok {
+			return
+		}
+		if tops[path] && !top {
+			// A top package that is a dependency
+			// will not be in depPkgs, so we skip
+			// reiterating on it here.
+			return
+		}
+
+		// We don't count a top-level package as
+		// a dependency even when they are used
+		// as a dependent package.
+		if !tops[path] {
+			depPkgs[path] = p
+		}
+
+		for _, d := range p.Imports {
+			visit(d, false)
+		}
+	}
+
+	for _, t := range topPkgs {
+		visit(t, true)
+	}
+
+	var deps []*packages.Package
+	for _, d := range depPkgs {
+		deps = append(deps, g.GetPackage(d.PkgPath))
+	}
+	return deps
+}
+
+func (g *PackageGraph) Modules() []*packages.Module {
+	var mods []*packages.Module
+	for _, m := range g.modules {
+		mods = append(mods, m)
+	}
+	return mods
+}
+
 // AddModules adds the modules and any replace modules provided.
-// It will ignore modules that have duplicate paths to ones the graph already holds.
+// It will ignore modules that have duplicate paths to ones the
+// graph already holds.
 func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	for _, mod := range mods {
 		if _, found := g.modules[mod.Path]; found {
@@ -47,7 +122,8 @@ func (g *PackageGraph) AddModules(mods ...*packages.Module) {
 	}
 }
 
-// .
+// GetModule gets module at path if one exists. Otherwise,
+// it creates a module and returns it.
 func (g *PackageGraph) GetModule(path string) *packages.Module {
 	if mod, ok := g.modules[path]; ok {
 		return mod
@@ -60,8 +136,9 @@ func (g *PackageGraph) GetModule(path string) *packages.Module {
 	return mod
 }
 
-// AddPackages adds the packages and the full graph of imported packages.
-// It will ignore packages that have duplicate paths to ones the graph already holds.
+// AddPackages adds the packages and their full graph of imported packages.
+// It also adds the modules of the added packages. It will ignore packages
+// that have duplicate paths to ones the graph already holds.
 func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	for _, pkg := range pkgs {
 		if _, found := g.packages[pkg.PkgPath]; found {
@@ -76,6 +153,9 @@ func (g *PackageGraph) AddPackages(pkgs ...*packages.Package) {
 	}
 }
 
+// fixupPackage adds the module of pkg, if any, to the set
+// of all modules in g. If packages is not assigned a module
+// (likely stdlib package), a module set for pkg.
 func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 	if pkg.Module != nil {
 		g.AddModules(pkg.Module)
@@ -89,7 +169,7 @@ func (g *PackageGraph) fixupPackage(pkg *packages.Package) {
 // not find anything, it returns the "unknown" module.
 func (g *PackageGraph) findModule(pkgPath string) *packages.Module {
 	//TODO: better stdlib test
-	if !strings.Contains(pkgPath, ".") {
+	if IsStdPackage(pkgPath) {
 		return g.GetModule(internal.GoStdModulePath)
 	}
 	for _, m := range g.modules {
@@ -116,22 +196,16 @@ func (g *PackageGraph) GetPackage(path string) *packages.Package {
 
 // LoadPackages loads the packages specified by the patterns into the graph.
 // See golang.org/x/tools/go/packages.Load for details of how it works.
-func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, patterns []string) ([]*packages.Package, error) {
+func (g *PackageGraph) LoadPackagesAndMods(cfg *packages.Config, tags []string, patterns []string, wantSymbols bool) error {
 	if len(tags) > 0 {
 		cfg.BuildFlags = []string{fmt.Sprintf("-tags=%s", strings.Join(tags, ","))}
 	}
-	cfg.Mode |=
-		packages.NeedDeps |
-			packages.NeedImports |
-			packages.NeedModule |
-			packages.NeedSyntax |
-			packages.NeedTypes |
-			packages.NeedTypesInfo |
-			packages.NeedName
+
+	addLoadMode(cfg, wantSymbols)
 
 	pkgs, err := packages.Load(cfg, patterns...)
 	if err != nil {
-		return nil, err
+		return err
 	}
 	var perrs []packages.Error
 	packages.Visit(pkgs, nil, func(p *packages.Package) {
@@ -140,8 +214,27 @@ func (g *PackageGraph) LoadPackages(cfg *packages.Config, tags []string, pattern
 	if len(perrs) > 0 {
 		err = &packageError{perrs}
 	}
+
+	// Add all packages, top-level ones and their imports.
+	// This will also add their respective modules.
 	g.AddPackages(pkgs...)
-	return pkgs, err
+
+	// save top-level packages
+	for _, p := range pkgs {
+		g.topPkgs = append(g.topPkgs, g.GetPackage(p.PkgPath))
+	}
+	return err
+}
+
+func addLoadMode(cfg *packages.Config, wantSymbols bool) {
+	cfg.Mode |=
+		packages.NeedModule |
+			packages.NeedName |
+			packages.NeedDeps |
+			packages.NeedImports
+	if wantSymbols {
+		cfg.Mode |= packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo
+	}
 }
 
 // packageError contains errors from loading a set of packages.
@@ -159,3 +252,67 @@ func (e *packageError) Error() string {
 	fmt.Fprintln(&b, "\nFor details on package patterns, see https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.")
 	return b.String()
 }
+
+func (g *PackageGraph) SBOM() *govulncheck.SBOM {
+	getMod := func(mod *packages.Module) *govulncheck.Module {
+		if mod.Replace != nil {
+			return &govulncheck.Module{
+				Path:    mod.Replace.Path,
+				Version: mod.Replace.Version,
+			}
+		}
+
+		return &govulncheck.Module{
+			Path:    mod.Path,
+			Version: mod.Version,
+		}
+	}
+
+	var roots []string
+	rootMods := make(map[string]*govulncheck.Module)
+	for _, pkg := range g.TopPkgs() {
+		roots = append(roots, pkg.PkgPath)
+		mod := getMod(pkg.Module)
+		rootMods[mod.Path] = mod
+	}
+
+	// Govulncheck attempts to put the modules that correspond to the matched package patterns (i.e. the root modules)
+	// at the beginning of the SBOM.Modules message.
+	// Note: This does not guarantee that the first element is the root module.
+	var topMods, depMods []*govulncheck.Module
+	var goVersion string
+	for _, mod := range g.Modules() {
+		mod := getMod(mod)
+
+		if mod.Path == internal.GoStdModulePath {
+			goVersion = semver.SemverToGoTag(mod.Version)
+		}
+
+		// if the mod is not associated with a root package, add it to depMods
+		if rootMods[mod.Path] == nil {
+			depMods = append(depMods, mod)
+		}
+	}
+
+	for _, mod := range rootMods {
+		topMods = append(topMods, mod)
+	}
+	// Sort for deterministic output
+	sortMods(topMods)
+	sortMods(depMods)
+
+	mods := append(topMods, depMods...)
+
+	return &govulncheck.SBOM{
+		GoVersion: goVersion,
+		Modules:   mods,
+		Roots:     roots,
+	}
+}
+
+// Sorts modules alphabetically by path.
+func sortMods(mods []*govulncheck.Module) {
+	slices.SortFunc(mods, func(a, b *govulncheck.Module) int {
+		return strings.Compare(a.Path, b.Path)
+	})
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
index 71fffc41..0bfa1603 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/slicing.go
@@ -44,12 +44,3 @@ func forwardSlice(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.
 	}
 	return seen
 }
-
-// pruneSet removes functions in `set` that are in `toPrune`.
-func pruneSet(set, toPrune map[*ssa.Function]bool) {
-	for f := range set {
-		if !toPrune[f] {
-			delete(set, f)
-		}
-	}
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
index 2119c70d..348c3b96 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/source.go
@@ -6,8 +6,6 @@ package vulncheck
 
 import (
 	"context"
-	"fmt"
-	"go/token"
 	"sync"
 
 	"golang.org/x/tools/go/callgraph"
@@ -18,32 +16,24 @@ import (
 	"golang.org/x/vuln/internal/osv"
 )
 
-// Source detects vulnerabilities in packages. The result will contain:
-//
-// 1) An ImportGraph related to an import of a package with some known
-// vulnerabilities.
-//
-// 2) A RequireGraph related to a require of a module with a package that has
-// some known vulnerabilities.
-//
-// 3) A CallGraph leading to the use of a known vulnerable function or method.
-func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (_ *Result, err error) {
-	// buildSSA builds a whole program that assumes all packages use the same FileSet.
-	// Check all packages in pkgs are using the same FileSet.
-	// TODO(https://go.dev/issue/59729): take FileSet out of Package and
-	// let Source take a single FileSet. That will make the enforcement
-	// clearer from the API level.
-	var fset *token.FileSet
-	for _, p := range pkgs {
-		if fset == nil {
-			fset = p.Fset
-		} else {
-			if fset != p.Fset {
-				return nil, fmt.Errorf("[]*Package must have created with the same FileSet")
-			}
-		}
+// Source detects vulnerabilities in pkgs and emits the findings to handler.
+func Source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) error {
+	vr, err := source(ctx, handler, cfg, client, graph)
+	if err != nil {
+		return err
+	}
+
+	if cfg.ScanLevel.WantSymbols() {
+		return emitCallFindings(handler, sourceCallstacks(vr))
 	}
+	return nil
+}
 
+// source detects vulnerabilities in packages. It emits findings to handler
+// and produces a Result that contains info on detected vulnerabilities.
+//
+// Assumes that pkgs are non-empty and belong to the same program.
+func source(ctx context.Context, handler govulncheck.Handler, cfg *govulncheck.Config, client *client.Client, graph *PackageGraph) (*Result, error) {
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
@@ -57,118 +47,109 @@ func Source(ctx context.Context, pkgs []*packages.Package, cfg *govulncheck.Conf
 		buildErr error
 	)
 	if cfg.ScanLevel.WantSymbols() {
+		fset := graph.TopPkgs()[0].Fset
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			prog, ssaPkgs := buildSSA(pkgs, fset)
+			prog, ssaPkgs := buildSSA(graph.TopPkgs(), fset)
 			entries = entryPoints(ssaPkgs)
 			cg, buildErr = callGraph(ctx, prog, entries)
 		}()
 	}
 
-	mods := extractModules(pkgs)
-	mv, err := FetchVulnerabilities(ctx, client, mods)
-	if err != nil {
+	if err := handler.SBOM(graph.SBOM()); err != nil {
 		return nil, err
 	}
-	modVulns := moduleVulnerabilities(mv)
-	modVulns = modVulns.filter("", "")
-	result := &Result{}
 
-	vulnPkgModSlice(pkgs, modVulns, result)
-	// Return result immediately if not in symbol mode or
-	// if there are no vulnerable packages.
-	if !cfg.ScanLevel.WantSymbols() || len(result.EntryPackages) == 0 {
-		return result, nil
+	if err := handler.Progress(&govulncheck.Progress{Message: fetchingVulnsMessage}); err != nil {
+		return nil, err
 	}
 
-	wg.Wait() // wait for build to finish
-	if buildErr != nil {
+	mv, err := FetchVulnerabilities(ctx, client, graph.Modules())
+	if err != nil {
 		return nil, err
 	}
 
-	vulnCallGraphSlice(entries, modVulns, cg, result, graph)
+	// Emit OSV entries immediately in their raw unfiltered form.
+	if err := emitOSVs(handler, mv); err != nil {
+		return nil, err
+	}
 
-	return result, nil
-}
+	if err := handler.Progress(&govulncheck.Progress{Message: checkingSrcVulnsMessage}); err != nil {
+		return nil, err
+	}
 
-// vulnPkgModSlice computes the slice of pkgs imports and requires graph
-// leading to imports/requires of vulnerable packages/modules in modVulns
-// and stores the computed slices to result.
-func vulnPkgModSlice(pkgs []*packages.Package, modVulns moduleVulnerabilities, result *Result) {
-	// analyzedPkgs contains information on packages analyzed thus far.
-	// If a package is mapped to false, this means it has been visited
-	// but it does not lead to a vulnerable imports. Otherwise, a
-	// visited package is mapped to true.
-	analyzedPkgs := make(map[*packages.Package]bool)
-	for _, pkg := range pkgs {
-		// Top level packages that lead to vulnerable imports are
-		// stored as result.EntryPackages graph entry points.
-		if vulnerable := vulnImportSlice(pkg, modVulns, result, analyzedPkgs); vulnerable {
-			result.EntryPackages = append(result.EntryPackages, pkg)
-		}
+	affVulns := affectingVulnerabilities(mv, "", "")
+	if err := emitModuleFindings(handler, affVulns); err != nil {
+		return nil, err
 	}
-}
 
-// vulnImportSlice checks if pkg has some vulnerabilities or transitively imports
-// a package with known vulnerabilities. If that is the case, populates result.Imports
-// graph with this reachability information and returns the result.Imports package
-// node for pkg. Otherwise, returns nil.
-func vulnImportSlice(pkg *packages.Package, modVulns moduleVulnerabilities, result *Result, analyzed map[*packages.Package]bool) bool {
-	if vulnerable, ok := analyzed[pkg]; ok {
-		return vulnerable
+	if !cfg.ScanLevel.WantPackages() || len(affVulns) == 0 {
+		return &Result{}, nil
 	}
-	analyzed[pkg] = false
-	// Recursively compute which direct dependencies lead to an import of
-	// a vulnerable package and remember the nodes of such dependencies.
-	transitiveVulnerable := false
-	for _, imp := range pkg.Imports {
-		if impVulnerable := vulnImportSlice(imp, modVulns, result, analyzed); impVulnerable {
-			transitiveVulnerable = true
-		}
+
+	impVulns := importedVulnPackages(affVulns, graph)
+	// Emit information on imported vulnerable packages now as
+	// call graph computation might take a while.
+	if err := emitPackageFindings(handler, impVulns); err != nil {
+		return nil, err
 	}
 
-	// Check if pkg has known vulnerabilities.
-	vulns := modVulns.vulnsForPackage(pkg.PkgPath)
+	// Return result immediately if not in symbol mode or
+	// if there are no vulnerabilities imported.
+	if !cfg.ScanLevel.WantSymbols() || len(impVulns) == 0 {
+		return &Result{Vulns: impVulns}, nil
+	}
 
-	// If pkg is not vulnerable nor it transitively leads
-	// to vulnerabilities, jump out.
-	if !transitiveVulnerable && len(vulns) == 0 {
-		return false
+	wg.Wait() // wait for build to finish
+	if buildErr != nil {
+		return nil, err
 	}
 
-	// Create Vuln entry for each symbol of known OSV entries for pkg.
-	for _, osv := range vulns {
-		for _, affected := range osv.Affected {
-			for _, p := range affected.EcosystemSpecific.Packages {
-				if p.Path != pkg.PkgPath {
-					continue
-				}
-
-				symbols := p.Symbols
-				if len(symbols) == 0 {
-					symbols = allSymbols(pkg.Types)
-				}
-
-				for _, symbol := range symbols {
-					vuln := &Vuln{
-						OSV:        osv,
-						Symbol:     symbol,
-						ImportSink: pkg,
-					}
-					result.Vulns = append(result.Vulns, vuln)
-				}
+	entryFuncs, callVulns := calledVulnSymbols(entries, affVulns, cg, graph)
+	return &Result{EntryFunctions: entryFuncs, Vulns: callVulns}, nil
+}
+
+// importedVulnPackages detects imported vulnerable packages.
+func importedVulnPackages(affVulns affectingVulns, graph *PackageGraph) []*Vuln {
+	var vulns []*Vuln
+	analyzed := make(map[*packages.Package]bool) // skip analyzing the same package multiple times
+	var vulnImports func(pkg *packages.Package)
+	vulnImports = func(pkg *packages.Package) {
+		if analyzed[pkg] {
+			return
+		}
+
+		osvs := affVulns.ForPackage(pkgModPath(pkg), pkg.PkgPath)
+		// Create Vuln entry for each OSV entry for pkg.
+		for _, osv := range osvs {
+			vuln := &Vuln{
+				OSV:     osv,
+				Package: graph.GetPackage(pkg.PkgPath),
 			}
+			vulns = append(vulns, vuln)
+		}
+
+		analyzed[pkg] = true
+		for _, imp := range pkg.Imports {
+			vulnImports(imp)
 		}
 	}
-	analyzed[pkg] = true
-	return true
+
+	for _, pkg := range graph.TopPkgs() {
+		vulnImports(pkg)
+	}
+	return vulns
 }
 
-// vulnCallGraphSlice checks if known vulnerabilities are transitively reachable from sources
-// via call graph cg. If so, populates result.Calls graph with this reachability information.
-func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result, graph *PackageGraph) {
-	sinksWithVulns := vulnFuncs(cg, modVulns)
+// calledVulnSymbols detects vuln symbols transitively reachable from sources
+// via call graph cg.
+//
+// A slice of call graph is computed related to the reachable vulnerabilities. Each
+// reachable Vuln has attached FuncNode that can be upward traversed to the entry points.
+// Entry points that reach the vulnerable symbols are also returned.
+func calledVulnSymbols(sources []*ssa.Function, affVulns affectingVulns, cg *callgraph.Graph, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	sinksWithVulns := vulnFuncs(cg, affVulns, graph)
 
 	// Compute call graph backwards reachable
 	// from vulnerable functions and methods.
@@ -197,8 +178,8 @@ func vulnCallGraphSlice(sources []*ssa.Function, modVulns moduleVulnerabilities,
 	}
 
 	// Transform the resulting call graph slice into
-	// vulncheck representation and store it to result.
-	vulnCallGraph(filteredSources, filteredSinks, result, graph)
+	// vulncheck representation.
+	return vulnCallGraph(filteredSources, filteredSinks, graph)
 }
 
 // callGraphSlice computes a slice of callgraph beginning at starts
@@ -240,25 +221,25 @@ func callGraphSlice(starts []*callgraph.Node, forward bool) *callgraph.Graph {
 	return g
 }
 
-// vulnCallGraph creates vulnerability call graph from sources -> sinks reachability info.
-func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, result *Result, graph *PackageGraph) {
+// vulnCallGraph creates vulnerability call graph in terms of sources and sinks.
+func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.Entry, graph *PackageGraph) ([]*FuncNode, []*Vuln) {
+	var entries []*FuncNode
+	var vulns []*Vuln
 	nodes := make(map[*ssa.Function]*FuncNode)
 
 	// First create entries and sinks and store relevant information.
 	for _, s := range sources {
 		fn := createNode(nodes, s.Func, graph)
-		result.EntryFunctions = append(result.EntryFunctions, fn)
+		entries = append(entries, fn)
 	}
 
-	for s, vulns := range sinks {
+	for s, osvs := range sinks {
 		f := s.Func
 		funNode := createNode(nodes, s.Func, graph)
 
 		// Populate CallSink field for each detected vuln symbol.
-		for _, osv := range vulns {
-			if vulnMatchesPackage(osv, funNode.Package.PkgPath) {
-				addCallSinkForVuln(funNode, osv, dbFuncName(f), funNode.Package.PkgPath, result)
-			}
+		for _, osv := range osvs {
+			vulns = append(vulns, calledVuln(funNode, osv, dbFuncName(f), funNode.Package))
 		}
 	}
 
@@ -291,13 +272,15 @@ func vulnCallGraph(sources []*callgraph.Node, sinks map[*callgraph.Node][]*osv.E
 	for s := range sinks {
 		visit(s)
 	}
+	return entries, vulns
 }
 
 // vulnFuncs returns vulnerability information for vulnerable functions in cg.
-func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgraph.Node][]*osv.Entry {
+func vulnFuncs(cg *callgraph.Graph, affVulns affectingVulns, graph *PackageGraph) map[*callgraph.Node][]*osv.Entry {
 	m := make(map[*callgraph.Node][]*osv.Entry)
 	for f, n := range cg.Nodes {
-		vulns := modVulns.vulnsForSymbol(pkgPath(f), dbFuncName(f))
+		p := pkgPath(f)
+		vulns := affVulns.ForSymbol(pkgModPath(graph.GetPackage(p)), p, dbFuncName(f))
 		if len(vulns) > 0 {
 			m[n] = vulns
 		}
@@ -305,15 +288,6 @@ func vulnFuncs(cg *callgraph.Graph, modVulns moduleVulnerabilities) map[*callgra
 	return m
 }
 
-// pkgPath returns the path of the f's enclosing package, if any.
-// Otherwise, returns "".
-func pkgPath(f *ssa.Function) string {
-	if f.Package() != nil && f.Package().Pkg != nil {
-		return f.Package().Pkg.Path()
-	}
-	return ""
-}
-
 func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *PackageGraph) *FuncNode {
 	if fn, ok := nodes[f]; ok {
 		return fn
@@ -328,46 +302,11 @@ func createNode(nodes map[*ssa.Function]*FuncNode, f *ssa.Function, graph *Packa
 	return fn
 }
 
-// addCallSinkForVuln adds callID as call sink to vuln of result.Vulns
-// identified with .
-func addCallSinkForVuln(call *FuncNode, osv *osv.Entry, symbol, pkg string, result *Result) {
-	for _, vuln := range result.Vulns {
-		if vuln.OSV == osv && vuln.Symbol == symbol && vuln.ImportSink.PkgPath == pkg {
-			vuln.CallSink = call
-			return
-		}
-	}
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*packages.Package) []*packages.Module {
-	modMap := map[string]*packages.Module{}
-	seen := map[*packages.Package]bool{}
-	var extract func(*packages.Package, map[string]*packages.Module)
-	extract = func(pkg *packages.Package, modMap map[string]*packages.Module) {
-		if pkg == nil || seen[pkg] {
-			return
-		}
-		if pkg.Module != nil {
-			if pkg.Module.Replace != nil {
-				modMap[pkg.Module.Replace.Path] = pkg.Module
-			} else {
-				modMap[pkg.Module.Path] = pkg.Module
-			}
-		}
-		seen[pkg] = true
-		for _, imp := range pkg.Imports {
-			extract(imp, modMap)
-		}
-	}
-	for _, pkg := range pkgs {
-		extract(pkg, modMap)
-	}
-
-	modules := []*packages.Module{}
-	for _, mod := range modMap {
-		modules = append(modules, mod)
+func calledVuln(call *FuncNode, osv *osv.Entry, symbol string, pkg *packages.Package) *Vuln {
+	return &Vuln{
+		Symbol:   symbol,
+		Package:  pkg,
+		OSV:      osv,
+		CallSink: call,
 	}
-	return modules
 }
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
index 4fa9c69a..e752f4a0 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/utils.go
@@ -9,15 +9,17 @@ import (
 	"context"
 	"go/token"
 	"go/types"
+	"sort"
 	"strings"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/callgraph/cha"
 	"golang.org/x/tools/go/callgraph/vta"
 	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa/ssautil"
 	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/vuln/internal"
 	"golang.org/x/vuln/internal/osv"
+	"golang.org/x/vuln/internal/semver"
 
 	"golang.org/x/tools/go/ssa"
 )
@@ -26,7 +28,6 @@ import (
 // the ssa program encapsulating the packages and top level
 // ssa packages corresponding to pkgs.
 func buildSSA(pkgs []*packages.Package, fset *token.FileSet) (*ssa.Program, []*ssa.Package) {
-	// TODO(https://go.dev/issue/57221): what about entry functions that are generics?
 	prog := ssa.NewProgram(fset, ssa.InstantiateGenerics)
 
 	imports := make(map[*packages.Package]*ssa.Package)
@@ -69,12 +70,8 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 		return nil, err
 	}
 	initial := cha.CallGraph(prog)
-	allFuncs := ssautil.AllFunctions(prog)
 
 	fslice := forwardSlice(entrySlice, initial)
-	// Keep only actually linked functions.
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -83,8 +80,6 @@ func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function)
 	// Repeat the process once more, this time using
 	// the produced VTA call graph as the base graph.
 	fslice = forwardSlice(entrySlice, vtaCg)
-	pruneSet(fslice, allFuncs)
-
 	if err := ctx.Err(); err != nil { // cancelled?
 		return nil, err
 	}
@@ -110,15 +105,17 @@ func dbTypeFormat(t types.Type) string {
 
 // dbFuncName computes a function name consistent with the namings used in vulnerability
 // databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
+// If a receiver is a pointer, this information is not encoded in the resulting name. If
+// a function has type argument/parameter, this information is omitted. The name of
+// anonymous functions is simply "". The function names are unique subject to the enclosing
+// package, but not globally.
 //
 // Examples:
 //
 //	func (a A) foo (...) {...}  -> A.foo
 //	func foo(...) {...}         -> foo
 //	func (b *B) bar (...) {...} -> B.bar
+//	func (c C[T]) do(...) {...} -> C.do
 func dbFuncName(f *ssa.Function) string {
 	selectBound := func(f *ssa.Function) types.Type {
 		// If f is a "bound" function introduced by ssa for a given type, return the type.
@@ -151,18 +148,17 @@ func dbFuncName(f *ssa.Function) string {
 	}
 
 	if qprefix == "" {
-		return f.Name()
+		return funcName(f)
 	}
-	return qprefix + "." + f.Name()
+	return qprefix + "." + funcName(f)
 }
 
-// dbTypesFuncName is dbFuncName defined over *types.Func.
-func dbTypesFuncName(f *types.Func) string {
-	sig := f.Type().(*types.Signature)
-	if sig.Recv() == nil {
-		return f.Name()
-	}
-	return dbTypeFormat(sig.Recv().Type()) + "." + f.Name()
+// funcName returns the name of the ssa function f.
+// It is f.Name() without additional type argument
+// information in case of generics.
+func funcName(f *ssa.Function) string {
+	n, _, _ := strings.Cut(f.Name(), "[")
+	return n
 }
 
 // memberFuncs returns functions associated with the `member`:
@@ -227,35 +223,124 @@ func funcRecvType(f *ssa.Function) string {
 	return buf.String()
 }
 
-// allSymbols returns all top-level functions and methods defined in pkg.
-func allSymbols(pkg *types.Package) []string {
-	var names []string
-	scope := pkg.Scope()
-	for _, name := range scope.Names() {
-		o := scope.Lookup(name)
-		switch o := o.(type) {
-		case *types.Func:
-			names = append(names, dbTypesFuncName(o))
-		case *types.TypeName:
-			ms := types.NewMethodSet(types.NewPointer(o.Type()))
-			for i := 0; i < ms.Len(); i++ {
-				if f, ok := ms.At(i).Obj().(*types.Func); ok {
-					names = append(names, dbTypesFuncName(f))
+func FixedVersion(modulePath, version string, affected []osv.Affected) string {
+	fixed := earliestValidFix(modulePath, version, affected)
+	// Add "v" prefix if one does not exist. moduleVersionString
+	// will later on replace it with "go" if needed.
+	if fixed != "" && !strings.HasPrefix(fixed, "v") {
+		fixed = "v" + fixed
+	}
+	return fixed
+}
+
+// earliestValidFix returns the earliest fix for version of modulePath that
+// itself is not vulnerable in affected.
+//
+// Suppose we have a version "v1.0.0" and we use {...} to denote different
+// affected regions. Assume for simplicity that all affected apply to the
+// same input modulePath.
+//
+//	{[v0.1.0, v0.1.9), [v1.0.0, v2.0.0)} -> v2.0.0
+//	{[v1.0.0, v1.5.0), [v2.0.0, v2.1.0}, {[v1.4.0, v1.6.0)} -> v2.1.0
+func earliestValidFix(modulePath, version string, affected []osv.Affected) string {
+	var moduleAffected []osv.Affected
+	for _, a := range affected {
+		if a.Module.Path == modulePath {
+			moduleAffected = append(moduleAffected, a)
+		}
+	}
+
+	vFixes := validFixes(version, moduleAffected)
+	for _, fix := range vFixes {
+		if !fixNegated(fix, moduleAffected) {
+			return fix
+		}
+	}
+	return ""
+
+}
+
+// validFixes computes all fixes for version in affected and
+// returns them sorted increasingly. Assumes that all affected
+// apply to the same module.
+func validFixes(version string, affected []osv.Affected) []string {
+	var fixes []string
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if r.Type != osv.RangeTypeSemver {
+				continue
+			}
+			for _, e := range r.Events {
+				fix := e.Fixed
+				if fix != "" && semver.Less(version, fix) {
+					fixes = append(fixes, fix)
 				}
 			}
 		}
 	}
-	return names
+	sort.SliceStable(fixes, func(i, j int) bool { return semver.Less(fixes[i], fixes[j]) })
+	return fixes
 }
 
-// vulnMatchesPackage reports whether an entry applies to pkg (an import path).
-func vulnMatchesPackage(v *osv.Entry, pkg string) bool {
-	for _, a := range v.Affected {
-		for _, p := range a.EcosystemSpecific.Packages {
-			if p.Path == pkg {
+// fixNegated checks if fix is negated to by a re-introduction
+// of a vulnerability in affected. Assumes that all affected apply
+// to the same module.
+func fixNegated(fix string, affected []osv.Affected) bool {
+	for _, a := range affected {
+		for _, r := range a.Ranges {
+			if semver.ContainsSemver(r, fix) {
 				return true
 			}
 		}
 	}
 	return false
 }
+
+func modPath(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Path
+	}
+	return mod.Path
+}
+
+func modVersion(mod *packages.Module) string {
+	if mod.Replace != nil {
+		return mod.Replace.Version
+	}
+	return mod.Version
+}
+
+// pkgPath returns the path of the f's enclosing package, if any.
+// Otherwise, returns internal.UnknownPackagePath.
+func pkgPath(f *ssa.Function) string {
+	g := f
+	if f.Origin() != nil {
+		// Instantiations of generics do not have
+		// an associated package. We hence look up
+		// the original function for the package.
+		g = f.Origin()
+	}
+	if g.Package() != nil && g.Package().Pkg != nil {
+		return g.Package().Pkg.Path()
+	}
+	return internal.UnknownPackagePath
+}
+
+func pkgModPath(pkg *packages.Package) string {
+	if pkg != nil && pkg.Module != nil {
+		return pkg.Module.Path
+	}
+	return internal.UnknownModulePath
+}
+
+func IsStdPackage(pkg string) bool {
+	if pkg == "" || pkg == internal.UnknownPackagePath {
+		return false
+	}
+	// std packages do not have a "." in their path. For instance, see
+	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
+	if i := strings.IndexByte(pkg, '/'); i != -1 {
+		pkg = pkg[:i]
+	}
+	return !strings.Contains(pkg, ".")
+}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
index 7786695c..198fffe0 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/vulncheck.go
@@ -16,31 +16,31 @@ import (
 	"golang.org/x/vuln/internal/semver"
 )
 
-// Result contains information on how known vulnerabilities are reachable
-// in the call graph, package imports graph, and module requires graph of
-// the user code.
+const (
+	fetchingVulnsMessage    = "Fetching vulnerabilities from the database..."
+	checkingSrcVulnsMessage = "Checking the code against the vulnerabilities..."
+	checkingBinVulnsMessage = "Checking the binary against the vulnerabilities..."
+)
+
+// Result contains information on detected vulnerabilities.
+// For call graph analysis, it provides information on reachability
+// of vulnerable symbols through entry points of the program.
 type Result struct {
 	// EntryFunctions are a subset of Functions representing vulncheck entry points.
 	EntryFunctions []*FuncNode
 
-	// EntryPackages are a subset of Packages representing packages of vulncheck entry points.
-	EntryPackages []*packages.Package
-
-	// Vulns contains information on detected vulnerabilities and their place in
-	// the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
-	// or whose packages are imported in Imports, or whose modules are required in
-	// Requires, have an entry in Vulns.
+	// Vulns contains information on detected vulnerabilities.
 	Vulns []*Vuln
 }
 
-// Vuln provides information on how a vulnerability is affecting user code by
-// connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities
-// detected in Go binaries do not appear in the Result graphs.
+// Vuln provides information on a detected vulnerability. For call
+// graph mode, Vuln will also contain the information on how the
+// vulnerability is reachable in the user call graph.
 type Vuln struct {
 	// OSV contains information on the detected vulnerability in the shared
 	// vulnerability format.
 	//
-	// OSV, Symbol, PkgPath, and ModPath identify a vulnerability.
+	// OSV, Symbol, and Package identify a vulnerability.
 	//
 	// Note that *osv.Entry may describe multiple symbols from multiple
 	// packages.
@@ -49,17 +49,17 @@ type Vuln struct {
 	// Symbol is the name of the detected vulnerable function or method.
 	Symbol string
 
-	// CallSink is the FuncNode in Result.Calls corresponding to Symbol.
+	// CallSink is the FuncNode corresponding to Symbol.
 	//
 	// When analyzing binaries, Symbol is not reachable, or cfg.ScanLevel
-	// is symbol, CallSink will be unavailable and set to 0.
+	// is symbol, CallSink will be unavailable and set to nil.
 	CallSink *FuncNode
 
-	// ImportSink is the PkgNode in Result.Imports corresponding to PkgPath.
+	// Package of Symbol.
 	//
-	// When analyzing binaries or PkgPath is not imported, ImportSink will be
-	// unavailable and set to 0.
-	ImportSink *packages.Package
+	// When the package of symbol is not imported, Package will be
+	// unavailable and set to nil.
+	Package *packages.Package
 }
 
 // A FuncNode describes a function in the call graph.
@@ -111,10 +111,10 @@ type CallSite struct {
 	Resolved bool
 }
 
-// moduleVulnerabilities is an internal structure for
-// holding and querying vulnerabilities provided by a
-// vulnerability database client.
-type moduleVulnerabilities []*ModVulns
+// affectingVulns is an internal structure for querying
+// vulnerabilities that apply to the current program
+// and platform under consideration.
+type affectingVulns []*ModVulns
 
 // ModVulns groups vulnerabilities per module.
 type ModVulns struct {
@@ -122,10 +122,10 @@ type ModVulns struct {
 	Vulns  []*osv.Entry
 }
 
-func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
+func affectingVulnerabilities(vulns []*ModVulns, os, arch string) affectingVulns {
 	now := time.Now()
-	var filteredMod moduleVulnerabilities
-	for _, mod := range mv {
+	var filtered affectingVulns
+	for _, mod := range vulns {
 		module := mod.Module
 		modVersion := module.Version
 		if module.Replace != nil {
@@ -150,24 +150,20 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 				if a.Module.Path != module.Path {
 					continue
 				}
-
-				// A module version is affected if
-				//  - it is included in one of the affected version ranges
-				//  - and module version is not ""
-				if modVersion == "" {
-					// Module version of "" means the module version is not available,
-					// and so we don't want to spam users with potential false alarms.
-					continue
-				}
-				if !semver.Affects(a.Ranges, modVersion) {
+				if !affected(modVersion, a) {
 					continue
 				}
+
 				var filteredImports []osv.Package
 				for _, p := range a.EcosystemSpecific.Packages {
 					if matchesPlatform(os, arch, p) {
 						filteredImports = append(filteredImports, p)
 					}
 				}
+				// If we pruned all existing Packages, then the affected is
+				// empty and we can filter it out. Note that Packages can
+				// be empty for vulnerabilities that have no package or
+				// symbol information available.
 				if len(a.EcosystemSpecific.Packages) != 0 && len(filteredImports) == 0 {
 					continue
 				}
@@ -183,12 +179,28 @@ func (mv moduleVulnerabilities) filter(os, arch string) moduleVulnerabilities {
 			newV.Affected = filteredAffected
 			filteredVulns = append(filteredVulns, &newV)
 		}
-		filteredMod = append(filteredMod, &ModVulns{
+
+		filtered = append(filtered, &ModVulns{
 			Module: module,
 			Vulns:  filteredVulns,
 		})
 	}
-	return filteredMod
+	return filtered
+}
+
+// affected checks if modVersion is affected by a:
+//   - it is included in one of the affected version ranges
+//   - and module version is not "" and "(devel)"
+func affected(modVersion string, a osv.Affected) bool {
+	const devel = "(devel)"
+	if modVersion == "" || modVersion == devel {
+		// Module version of "" means the module version is not available
+		// and devel means it is in development stage. Either way, we don't
+		// know the exact version so we don't want to spam users with
+		// potential false alarms.
+		return false
+	}
+	return semver.Affects(a.Ranges, modVersion)
 }
 
 func matchesPlatform(os, arch string, e osv.Package) bool {
@@ -211,37 +223,66 @@ func matchesPlatformComponent(s string, ps []string) bool {
 	return false
 }
 
-// vulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv moduleVulnerabilities) vulnsForPackage(importPath string) []*osv.Entry {
-	isStd := isStdPackage(importPath)
-	var mostSpecificMod *ModVulns
-	for _, mod := range mv {
+// moduleVulns return vulnerabilities for module. If module is unknown,
+// it figures the module from package importPath. It returns the module
+// whose path is the longest prefix of importPath.
+func (aff affectingVulns) moduleVulns(module, importPath string) *ModVulns {
+	moduleKnown := module != "" && module != internal.UnknownModulePath
+
+	isStd := IsStdPackage(importPath)
+	var mostSpecificMod *ModVulns // for the case where !moduleKnown
+	for _, mod := range aff {
 		md := mod
 		if isStd && mod.Module.Path == internal.GoStdModulePath {
-			// standard library packages do not have an associated module,
+			// Standard library packages do not have an associated module,
 			// so we relate them to the artificial stdlib module.
-			mostSpecificMod = md
+			return md
+		}
+
+		if moduleKnown {
+			if mod.Module.Path == module {
+				// If we know exactly which module we need,
+				// return its vulnerabilities.
+				return md
+			}
 		} else if strings.HasPrefix(importPath, md.Module.Path) {
+			// If module is unknown, we try to figure it out from importPath.
+			// We take the module whose path has the longest match to importPath.
+			// TODO: do matching based on path components.
 			if mostSpecificMod == nil || len(mostSpecificMod.Module.Path) < len(md.Module.Path) {
 				mostSpecificMod = md
 			}
 		}
 	}
-	if mostSpecificMod == nil {
+	return mostSpecificMod
+}
+
+// ForPackage returns the vulnerabilities for the importPath belonging to
+// module.
+//
+// If module is unknown, ForPackage will resolve it as the most specific
+// prefix of importPath.
+func (aff affectingVulns) ForPackage(module, importPath string) []*osv.Entry {
+	mod := aff.moduleVulns(module, importPath)
+	if mod == nil {
 		return nil
 	}
 
-	if mostSpecificMod.Module.Replace != nil {
+	if mod.Module.Replace != nil {
 		// standard libraries do not have a module nor replace module
-		importPath = fmt.Sprintf("%s%s", mostSpecificMod.Module.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.Module.Path))
+		importPath = fmt.Sprintf("%s%s", mod.Module.Replace.Path, strings.TrimPrefix(importPath, mod.Module.Path))
 	}
-	vulns := mostSpecificMod.Vulns
+	vulns := mod.Vulns
 	packageVulns := []*osv.Entry{}
 Vuln:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all packages are vulnerable
+				packageVulns = append(packageVulns, v)
+				continue Vuln
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path == importPath {
 					packageVulns = append(packageVulns, v)
@@ -253,9 +294,9 @@ Vuln:
 	return packageVulns
 }
 
-// vulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv.Entry {
-	vulns := mv.vulnsForPackage(importPath)
+// ForSymbol returns vulnerabilities for symbol in aff.ForPackage(module, importPath).
+func (aff affectingVulns) ForSymbol(module, importPath, symbol string) []*osv.Entry {
+	vulns := aff.ForPackage(module, importPath)
 	if vulns == nil {
 		return nil
 	}
@@ -264,6 +305,12 @@ func (mv moduleVulnerabilities) vulnsForSymbol(importPath, symbol string) []*osv
 vulnLoop:
 	for _, v := range vulns {
 		for _, a := range v.Affected {
+			if len(a.EcosystemSpecific.Packages) == 0 {
+				// no packages means all symbols of all packages are vulnerable
+				symbolVulns = append(symbolVulns, v)
+				continue vulnLoop
+			}
+
 			for _, p := range a.EcosystemSpecific.Packages {
 				if p.Path != importPath {
 					continue
@@ -287,15 +334,3 @@ func contains(symbols []string, target string) bool {
 	}
 	return false
 }
-
-func isStdPackage(pkg string) bool {
-	if pkg == "" {
-		return false
-	}
-	// std packages do not have a "." in their path. For instance, see
-	// Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
-	if i := strings.IndexByte(pkg, '/'); i != -1 {
-		pkg = pkg[:i]
-	}
-	return !strings.Contains(pkg, ".")
-}
diff --git a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
index 7de37587..7bc18581 100644
--- a/public-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
+++ b/public-api/vendor/golang.org/x/vuln/internal/vulncheck/witness.go
@@ -13,6 +13,7 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"unicode"
 
 	"golang.org/x/tools/go/packages"
 )
@@ -32,18 +33,18 @@ type StackEntry struct {
 	Call *CallSite
 }
 
-// CallStacks returns representative call stacks for each
+// sourceCallstacks returns representative call stacks for each
 // vulnerability in res. The returned call stacks are heuristically
 // ordered by how seemingly easy is to understand them: shorter
 // call stacks with less dynamic call sites appear earlier in the
 // returned slices.
 //
-// CallStacks performs a breadth-first search of res.CallGraph starting
-// at the vulnerable symbol and going up until reaching an entry
+// sourceCallstacks performs a breadth-first search of res.CallGraph
+// starting at the vulnerable symbol and going up until reaching an entry
 // function or method in res.CallGraph.Entries. During this search,
 // each function is visited at most once to avoid potential
 // exponential explosion. Hence, not all call stacks are analyzed.
-func CallStacks(res *Result) map[*Vuln]CallStack {
+func sourceCallstacks(res *Result) map[*Vuln]CallStack {
 	var (
 		wg sync.WaitGroup
 		mu sync.Mutex
@@ -53,7 +54,7 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 		vuln := vuln
 		wg.Add(1)
 		go func() {
-			cs := callStack(vuln, res)
+			cs := sourceCallstack(vuln, res)
 			mu.Lock()
 			stackPerVuln[vuln] = cs
 			mu.Unlock()
@@ -66,10 +67,10 @@ func CallStacks(res *Result) map[*Vuln]CallStack {
 	return stackPerVuln
 }
 
-// callStack finds a representative call stack for vuln.
+// sourceCallstack finds a representative call stack for vuln.
 // This is a shortest unique call stack with the least
 // number of dynamic call sites.
-func callStack(vuln *Vuln, res *Result) CallStack {
+func sourceCallstack(vuln *Vuln, res *Result) CallStack {
 	vulnSink := vuln.CallSink
 	if vulnSink == nil {
 		return nil
@@ -100,7 +101,7 @@ func callStack(vuln *Vuln, res *Result) CallStack {
 	skipSymbols := make(map[*FuncNode]bool)
 	for _, v := range res.Vulns {
 		if v.CallSink != nil && v != vuln &&
-			v.OSV == vuln.OSV && v.ImportSink == vuln.ImportSink {
+			v.OSV == vuln.OSV && v.Package == vuln.Package {
 			skipSymbols[v.CallSink] = true
 		}
 	}
@@ -390,3 +391,59 @@ func isInit(f *FuncNode) bool {
 	// positive integer. Implicit inits are named simply "init".
 	return f.Name == "init" || strings.HasPrefix(f.Name, "init#")
 }
+
+// binaryCallstacks computes representative call stacks for binary results.
+func binaryCallstacks(vr *Result) map[*Vuln]CallStack {
+	callstacks := map[*Vuln]CallStack{}
+	for _, vv := range uniqueVulns(vr.Vulns) {
+		f := &FuncNode{Package: vv.Package, Name: vv.Symbol}
+		parts := strings.Split(vv.Symbol, ".")
+		if len(parts) != 1 {
+			f.RecvType = parts[0]
+			f.Name = parts[1]
+		}
+		callstacks[vv] = CallStack{StackEntry{Function: f}}
+	}
+	return callstacks
+}
+
+// uniqueVulns does for binary mode what sourceCallstacks does for source mode.
+// It tries not to report redundant symbols. Since there are no call stacks in
+// binary mode, the following approximate approach is used. Do not report unexported
+// symbols for a  triple if there are some exported symbols.
+// Otherwise, report all unexported symbols to avoid not reporting anything.
+func uniqueVulns(vulns []*Vuln) []*Vuln {
+	type key struct {
+		id  string
+		pkg string
+		mod string
+	}
+	hasExported := make(map[key]bool)
+	for _, v := range vulns {
+		if isExported(v.Symbol) {
+			k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+			hasExported[k] = true
+		}
+	}
+
+	var uniques []*Vuln
+	for _, v := range vulns {
+		k := key{id: v.OSV.ID, pkg: v.Package.PkgPath, mod: v.Package.Module.Path}
+		if isExported(v.Symbol) || !hasExported[k] {
+			uniques = append(uniques, v)
+		}
+	}
+	return uniques
+}
+
+// isExported checks if the symbol is exported. Assumes that the
+// symbol is of the form "identifier", "identifier1.identifier2",
+// or "identifier.".
+func isExported(symbol string) bool {
+	parts := strings.Split(symbol, ".")
+	last := parts[len(parts)-1]
+	if last == "" { // case for "identifier."
+		return false
+	}
+	return unicode.IsUpper(rune(last[0]))
+}
diff --git a/public-api/vendor/golang.org/x/vuln/scan/scan.go b/public-api/vendor/golang.org/x/vuln/scan/scan.go
index 83ed75a9..0aa9975e 100644
--- a/public-api/vendor/golang.org/x/vuln/scan/scan.go
+++ b/public-api/vendor/golang.org/x/vuln/scan/scan.go
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+/*
+Package scan provides functionality for running govulncheck.
+
+See [cmd/govulncheck/main.go] as a usage example.
+
+[cmd/govulncheck/main.go]: https://go.googlesource.com/vuln/+/master/cmd/govulncheck/main.go
+*/
 package scan
 
 import (
diff --git a/public-api/vendor/google.golang.org/grpc/MAINTAINERS.md b/public-api/vendor/google.golang.org/grpc/MAINTAINERS.md
index 5d4096d4..df35bb9a 100644
--- a/public-api/vendor/google.golang.org/grpc/MAINTAINERS.md
+++ b/public-api/vendor/google.golang.org/grpc/MAINTAINERS.md
@@ -9,21 +9,19 @@ for general contribution guidelines.
 
 ## Maintainers (in alphabetical order)
 
-- [aranjans](https://github.com/aranjans), Google LLC
 - [arjan-bal](https://github.com/arjan-bal), Google LLC
 - [arvindbr8](https://github.com/arvindbr8), Google LLC
 - [atollena](https://github.com/atollena), Datadog, Inc.
 - [dfawley](https://github.com/dfawley), Google LLC
 - [easwars](https://github.com/easwars), Google LLC
-- [erm-g](https://github.com/erm-g), Google LLC
 - [gtcooke94](https://github.com/gtcooke94), Google LLC
-- [purnesh42h](https://github.com/purnesh42h), Google LLC
-- [zasweq](https://github.com/zasweq), Google LLC
 
 ## Emeritus Maintainers (in alphabetical order)
 - [adelez](https://github.com/adelez)
+- [aranjans](https://github.com/aranjans)
 - [canguler](https://github.com/canguler)
 - [cesarghali](https://github.com/cesarghali)
+- [erm-g](https://github.com/erm-g)
 - [iamqizhao](https://github.com/iamqizhao)
 - [jeanbza](https://github.com/jeanbza)
 - [jtattermusch](https://github.com/jtattermusch)
@@ -32,5 +30,7 @@ for general contribution guidelines.
 - [matt-kwong](https://github.com/matt-kwong)
 - [menghanl](https://github.com/menghanl)
 - [nicolasnoble](https://github.com/nicolasnoble)
+- [purnesh42h](https://github.com/purnesh42h)
 - [srini100](https://github.com/srini100)
 - [yongni](https://github.com/yongni)
+- [zasweq](https://github.com/zasweq)
diff --git a/public-api/vendor/google.golang.org/grpc/balancer/balancer.go b/public-api/vendor/google.golang.org/grpc/balancer/balancer.go
index c9b343c7..b1264017 100644
--- a/public-api/vendor/google.golang.org/grpc/balancer/balancer.go
+++ b/public-api/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -360,6 +360,10 @@ type Balancer interface {
 	// call SubConn.Shutdown for its existing SubConns; however, this will be
 	// required in a future release, so it is recommended.
 	Close()
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // ExitIdler is an optional interface for balancers to implement.  If
@@ -367,8 +371,8 @@ type Balancer interface {
 // the ClientConn is idle.  If unimplemented, ClientConn.Connect will cause
 // all SubConns to connect.
 //
-// Notice: it will be required for all balancers to implement this in a future
-// release.
+// Deprecated: All balancers must implement this interface. This interface will
+// be removed in a future release.
 type ExitIdler interface {
 	// ExitIdle instructs the LB policy to reconnect to backends / exit the
 	// IDLE state, if appropriate and possible.  Note that SubConns that enter
diff --git a/public-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/public-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
index cc606f4d..360db08e 100644
--- a/public-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
+++ b/public-api/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go
@@ -37,6 +37,8 @@ import (
 	"google.golang.org/grpc/resolver"
 )
 
+var randIntN = rand.IntN
+
 // ChildState is the balancer state of a child along with the endpoint which
 // identifies the child balancer.
 type ChildState struct {
@@ -45,7 +47,15 @@ type ChildState struct {
 
 	// Balancer exposes only the ExitIdler interface of the child LB policy.
 	// Other methods of the child policy are called only by endpointsharding.
-	Balancer balancer.ExitIdler
+	Balancer ExitIdler
+}
+
+// ExitIdler provides access to only the ExitIdle method of the child balancer.
+type ExitIdler interface {
+	// ExitIdle instructs the LB policy to reconnect to backends / exit the
+	// IDLE state, if appropriate and possible.  Note that SubConns that enter
+	// the IDLE state will not reconnect until SubConn.Connect is called.
+	ExitIdle()
 }
 
 // Options are the options to configure the behaviour of the
@@ -104,6 +114,21 @@ type endpointSharding struct {
 	mu sync.Mutex
 }
 
+// rotateEndpoints returns a slice of all the input endpoints rotated a random
+// amount.
+func rotateEndpoints(es []resolver.Endpoint) []resolver.Endpoint {
+	les := len(es)
+	if les == 0 {
+		return es
+	}
+	r := randIntN(les)
+	// Make a copy to avoid mutating data beyond the end of es.
+	ret := make([]resolver.Endpoint, les)
+	copy(ret, es[r:])
+	copy(ret[les-r:], es[:r])
+	return ret
+}
+
 // UpdateClientConnState creates a child for new endpoints and deletes children
 // for endpoints that are no longer present. It also updates all the children,
 // and sends a single synchronous update of the childrens' aggregated state at
@@ -125,7 +150,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
 	newChildren := resolver.NewEndpointMap[*balancerWrapper]()
 
 	// Update/Create new children.
-	for _, endpoint := range state.ResolverState.Endpoints {
+	for _, endpoint := range rotateEndpoints(state.ResolverState.Endpoints) {
 		if _, ok := newChildren.Get(endpoint); ok {
 			// Endpoint child was already created, continue to avoid duplicate
 			// update.
@@ -205,6 +230,16 @@ func (es *endpointSharding) Close() {
 	}
 }
 
+func (es *endpointSharding) ExitIdle() {
+	es.childMu.Lock()
+	defer es.childMu.Unlock()
+	for _, bw := range es.children.Load().Values() {
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+	}
+}
+
 // updateState updates this component's state. It sends the aggregated state,
 // and a picker with round robin behavior with all the child states present if
 // needed.
@@ -261,7 +296,7 @@ func (es *endpointSharding) updateState() {
 	p := &pickerWithChildStates{
 		pickers:     pickers,
 		childStates: childStates,
-		next:        uint32(rand.IntN(len(pickers))),
+		next:        uint32(randIntN(len(pickers))),
 	}
 	es.cc.UpdateState(balancer.State{
 		ConnectivityState: aggState,
@@ -326,15 +361,13 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) {
 // ExitIdle pings an IDLE child balancer to exit idle in a new goroutine to
 // avoid deadlocks due to synchronous balancer state updates.
 func (bw *balancerWrapper) ExitIdle() {
-	if ei, ok := bw.child.(balancer.ExitIdler); ok {
-		go func() {
-			bw.es.childMu.Lock()
-			if !bw.isClosed {
-				ei.ExitIdle()
-			}
-			bw.es.childMu.Unlock()
-		}()
-	}
+	go func() {
+		bw.es.childMu.Lock()
+		if !bw.isClosed {
+			bw.child.ExitIdle()
+		}
+		bw.es.childMu.Unlock()
+	}()
 }
 
 // updateClientConnStateLocked delivers the ClientConnState to the child
diff --git a/public-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/public-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
index 494314f2..67f315a0 100644
--- a/public-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
+++ b/public-api/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go
@@ -54,18 +54,9 @@ func init() {
 	balancer.Register(pickfirstBuilder{})
 }
 
-type (
-	// enableHealthListenerKeyType is a unique key type used in resolver
-	// attributes to indicate whether the health listener usage is enabled.
-	enableHealthListenerKeyType struct{}
-	// managedByPickfirstKeyType is an attribute key type to inform Outlier
-	// Detection that the generic health listener is being used.
-	// TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when
-	// implementing the dualstack design. This is a hack. Once Dualstack is
-	// completed, outlier detection will stop sending ejection updates through
-	// the connectivity listener.
-	managedByPickfirstKeyType struct{}
-)
+// enableHealthListenerKeyType is a unique key type used in resolver
+// attributes to indicate whether the health listener usage is enabled.
+type enableHealthListenerKeyType struct{}
 
 var (
 	logger = grpclog.Component("pick-first-leaf-lb")
@@ -76,21 +67,21 @@ var (
 	disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.disconnections",
 		Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
-		Unit:        "disconnection",
+		Unit:        "{disconnection}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_succeeded",
 		Description: "EXPERIMENTAL. Number of successful connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
 	connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
 		Name:        "grpc.lb.pick_first.connection_attempts_failed",
 		Description: "EXPERIMENTAL. Number of failed connection attempts.",
-		Unit:        "attempt",
+		Unit:        "{attempt}",
 		Labels:      []string{"grpc.target"},
 		Default:     false,
 	})
@@ -149,17 +140,6 @@ func EnableHealthListener(state resolver.State) resolver.State {
 	return state
 }
 
-// IsManagedByPickfirst returns whether an address belongs to a SubConn
-// managed by the pickfirst LB policy.
-// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable
-// outlier_detection via the with connectivity listener when using pick_first.
-// Once Dualstack changes are complete, all SubConns will be created by
-// pick_first and outlier detection will only use the health listener for
-// ejection. This hack can then be removed.
-func IsManagedByPickfirst(addr resolver.Address) bool {
-	return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil
-}
-
 type pfConfig struct {
 	serviceconfig.LoadBalancingConfig `json:"-"`
 
@@ -186,7 +166,6 @@ type scData struct {
 }
 
 func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) {
-	addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true)
 	sd := &scData{
 		rawConnectivityState: connectivity.Idle,
 		effectiveState:       connectivity.Idle,
diff --git a/public-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/public-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
index 35da5d1e..22045bf3 100644
--- a/public-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
+++ b/public-api/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -70,10 +70,3 @@ func (b *rrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
 		ResolverState: pickfirstleaf.EnableHealthListener(ccs.ResolverState),
 	})
 }
-
-func (b *rrBalancer) ExitIdle() {
-	// Should always be ok, as child is endpoint sharding.
-	if ei, ok := b.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-	}
-}
diff --git a/public-api/vendor/google.golang.org/grpc/clientconn.go b/public-api/vendor/google.golang.org/grpc/clientconn.go
index cd3eaf8d..3f762285 100644
--- a/public-api/vendor/google.golang.org/grpc/clientconn.go
+++ b/public-api/vendor/google.golang.org/grpc/clientconn.go
@@ -208,7 +208,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error)
 	channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority)
 
 	cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz)
-	cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers)
+	cc.pickerWrapper = newPickerWrapper()
 
 	cc.metricsRecorderList = stats.NewMetricsRecorderList(cc.dopts.copts.StatsHandlers)
 
@@ -1076,13 +1076,6 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
 	return cc.sc.healthCheckConfig
 }
 
-func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
-	return cc.pickerWrapper.pick(ctx, failfast, balancer.PickInfo{
-		Ctx:            ctx,
-		FullMethodName: method,
-	})
-}
-
 func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSelector iresolver.ConfigSelector) {
 	if sc == nil {
 		// should never reach here.
@@ -1831,7 +1824,7 @@ func (cc *ClientConn) initAuthority() error {
 	} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
 		cc.authority = auth.OverrideAuthority(cc.parsedTarget)
 	} else if strings.HasPrefix(endpoint, ":") {
-		cc.authority = "localhost" + endpoint
+		cc.authority = "localhost" + encodeAuthority(endpoint)
 	} else {
 		cc.authority = encodeAuthority(endpoint)
 	}
diff --git a/public-api/vendor/google.golang.org/grpc/credentials/credentials.go b/public-api/vendor/google.golang.org/grpc/credentials/credentials.go
index a63ab606..c8e337cd 100644
--- a/public-api/vendor/google.golang.org/grpc/credentials/credentials.go
+++ b/public-api/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -96,10 +96,11 @@ func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
 	return c
 }
 
-// ProtocolInfo provides information regarding the gRPC wire protocol version,
-// security protocol, security protocol version in use, server name, etc.
+// ProtocolInfo provides static information regarding transport credentials.
 type ProtocolInfo struct {
 	// ProtocolVersion is the gRPC wire protocol version.
+	//
+	// Deprecated: this is unused by gRPC.
 	ProtocolVersion string
 	// SecurityProtocol is the security protocol in use.
 	SecurityProtocol string
@@ -109,7 +110,16 @@ type ProtocolInfo struct {
 	//
 	// Deprecated: please use Peer.AuthInfo.
 	SecurityVersion string
-	// ServerName is the user-configured server name.
+	// ServerName is the user-configured server name.  If set, this overrides
+	// the default :authority header used for all RPCs on the channel using the
+	// containing credentials, unless grpc.WithAuthority is set on the channel,
+	// in which case that setting will take precedence.
+	//
+	// This must be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: Users should use grpc.WithAuthority to override the authority
+	// on a channel instead of configuring the credentials.
 	ServerName string
 }
 
@@ -173,12 +183,17 @@ type TransportCredentials interface {
 	// Clone makes a copy of this TransportCredentials.
 	Clone() TransportCredentials
 	// OverrideServerName specifies the value used for the following:
+	//
 	// - verifying the hostname on the returned certificates
 	// - as SNI in the client's handshake to support virtual hosting
 	// - as the value for `:authority` header at stream creation time
 	//
-	// Deprecated: use grpc.WithAuthority instead. Will be supported
-	// throughout 1.x.
+	// The provided string should be a valid `:authority` header according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
+	//
+	// Deprecated: this method is unused by gRPC.  Users should use
+	// grpc.WithAuthority to override the authority on a channel instead of
+	// configuring the credentials.
 	OverrideServerName(string) error
 }
 
diff --git a/public-api/vendor/google.golang.org/grpc/credentials/tls.go b/public-api/vendor/google.golang.org/grpc/credentials/tls.go
index 20f65f7b..8277be7d 100644
--- a/public-api/vendor/google.golang.org/grpc/credentials/tls.go
+++ b/public-api/vendor/google.golang.org/grpc/credentials/tls.go
@@ -110,14 +110,14 @@ func (c tlsCreds) Info() ProtocolInfo {
 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
 	// use local cfg to avoid clobbering ServerName if using multiple endpoints
 	cfg := credinternal.CloneTLSConfig(c.config)
-	if cfg.ServerName == "" {
-		serverName, _, err := net.SplitHostPort(authority)
-		if err != nil {
-			// If the authority had no host port or if the authority cannot be parsed, use it as-is.
-			serverName = authority
-		}
-		cfg.ServerName = serverName
+
+	serverName, _, err := net.SplitHostPort(authority)
+	if err != nil {
+		// If the authority had no host port or if the authority cannot be parsed, use it as-is.
+		serverName = authority
 	}
+	cfg.ServerName = serverName
+
 	conn := tls.Client(rawConn, cfg)
 	errChannel := make(chan error, 1)
 	go func() {
@@ -259,9 +259,11 @@ func applyDefaults(c *tls.Config) *tls.Config {
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
 }
@@ -271,9 +273,11 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
 // certificates to establish the identity of the client need to be included in
 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
 // tls.Config can be specified.
-// serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header
-// field) in requests.
+//
+// serverNameOverride is for testing only. If set to a non empty string, it will
+// override the virtual host name of authority (e.g. :authority header field) in
+// requests.  Users should use grpc.WithAuthority passed to grpc.NewClient to
+// override the authority of the client instead.
 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
 	b, err := os.ReadFile(certFile)
 	if err != nil {
diff --git a/public-api/vendor/google.golang.org/grpc/dialoptions.go b/public-api/vendor/google.golang.org/grpc/dialoptions.go
index 050ba0f1..7a5ac2e7 100644
--- a/public-api/vendor/google.golang.org/grpc/dialoptions.go
+++ b/public-api/vendor/google.golang.org/grpc/dialoptions.go
@@ -213,6 +213,7 @@ func WithReadBufferSize(s int) DialOption {
 func WithInitialWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -222,6 +223,26 @@ func WithInitialWindowSize(s int32) DialOption {
 func WithInitialConnWindowSize(s int32) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticStreamWindowSize returns a DialOption which sets the initial
+// stream window size to the value provided and disables dynamic flow control.
+func WithStaticStreamWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialWindowSize = s
+		o.copts.StaticWindowSize = true
+	})
+}
+
+// WithStaticConnWindowSize returns a DialOption which sets the initial
+// connection window size to the value provided and disables dynamic flow
+// control.
+func WithStaticConnWindowSize(s int32) DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.copts.InitialConnWindowSize = s
+		o.copts.StaticWindowSize = true
 	})
 }
 
@@ -587,6 +608,8 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
 
 // WithAuthority returns a DialOption that specifies the value to be used as the
 // :authority pseudo-header and as the server name in authentication handshake.
+// This overrides all other ways of setting authority on the channel, but can be
+// overridden per-call by using grpc.CallAuthority.
 func WithAuthority(a string) DialOption {
 	return newFuncDialOption(func(o *dialOptions) {
 		o.authority = a
diff --git a/public-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go b/public-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
index 93136610..f2c01f29 100644
--- a/public-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
+++ b/public-api/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go
@@ -188,13 +188,13 @@ type HealthServer interface {
 type UnimplementedHealthServer struct{}
 
 func (UnimplementedHealthServer) Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
+	return nil, status.Error(codes.Unimplemented, "method Check not implemented")
 }
 func (UnimplementedHealthServer) List(context.Context, *HealthListRequest) (*HealthListResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
+	return nil, status.Error(codes.Unimplemented, "method List not implemented")
 }
 func (UnimplementedHealthServer) Watch(*HealthCheckRequest, grpc.ServerStreamingServer[HealthCheckResponse]) error {
-	return status.Errorf(codes.Unimplemented, "method Watch not implemented")
+	return status.Error(codes.Unimplemented, "method Watch not implemented")
 }
 func (UnimplementedHealthServer) testEmbeddedByValue() {}
 
diff --git a/public-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/public-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
index fbc1ca35..ba25b898 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go
@@ -223,15 +223,7 @@ func (gsb *Balancer) ExitIdle() {
 	// There is no need to protect this read with a mutex, as the write to the
 	// Balancer field happens in SwitchTo, which completes before this can be
 	// called.
-	if ei, ok := balToUpdate.Balancer.(balancer.ExitIdler); ok {
-		ei.ExitIdle()
-		return
-	}
-	gsb.mu.Lock()
-	defer gsb.mu.Unlock()
-	for sc := range balToUpdate.subconns {
-		sc.Connect()
-	}
+	balToUpdate.ExitIdle()
 }
 
 // updateSubConnState forwards the update to the appropriate child.
diff --git a/public-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/public-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
index f5f2bdeb..7e060f5e 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -26,30 +26,32 @@ import (
 )
 
 var (
-	// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
+	// EnableTXTServiceConfig is set if the DNS resolver should perform TXT
+	// lookups for service config ("GRPC_ENABLE_TXT_SERVICE_CONFIG" is not
+	// "false").
+	EnableTXTServiceConfig = boolFromEnv("GRPC_ENABLE_TXT_SERVICE_CONFIG", true)
+
+	// TXTErrIgnore is set if TXT errors should be ignored
+	// ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
 	TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true)
+
 	// RingHashCap indicates the maximum ring size which defaults to 4096
 	// entries but may be overridden by setting the environment variable
 	// "GRPC_RING_HASH_CAP".  This does not override the default bounds
 	// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
 	RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
-	// LeastRequestLB is set if we should support the least_request_experimental
-	// LB policy, which can be enabled by setting the environment variable
-	// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
-	LeastRequestLB = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST", true)
+
 	// ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS
 	// handshakes that can be performed.
 	ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100)
+
 	// EnforceALPNEnabled is set if TLS connections to servers with ALPN disabled
 	// should be rejected. The HTTP/2 protocol requires ALPN to be enabled, this
 	// option is present for backward compatibility. This option may be overridden
 	// by setting the environment variable "GRPC_ENFORCE_ALPN_ENABLED" to "true"
 	// or "false".
 	EnforceALPNEnabled = boolFromEnv("GRPC_ENFORCE_ALPN_ENABLED", true)
-	// XDSFallbackSupport is the env variable that controls whether support for
-	// xDS fallback is turned on. If this is unset or is false, only the first
-	// xDS server in the list of server configs will be used.
-	XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true)
+
 	// NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used
 	// instead of the exiting pickfirst implementation. This can be disabled by
 	// setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST"
diff --git a/public-api/vendor/google.golang.org/grpc/internal/internal.go b/public-api/vendor/google.golang.org/grpc/internal/internal.go
index 3ac798e8..2699223a 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/internal.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/internal.go
@@ -182,35 +182,6 @@ var (
 	// other features, including the CSDS service.
 	NewXDSResolverWithClientForTesting any // func(xdsclient.XDSClient) (resolver.Builder, error)
 
-	// RegisterRLSClusterSpecifierPluginForTesting registers the RLS Cluster
-	// Specifier Plugin for testing purposes, regardless of the XDSRLS environment
-	// variable.
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	RegisterRLSClusterSpecifierPluginForTesting func()
-
-	// UnregisterRLSClusterSpecifierPluginForTesting unregisters the RLS Cluster
-	// Specifier Plugin for testing purposes. This is needed because there is no way
-	// to unregister the RLS Cluster Specifier Plugin after registering it solely
-	// for testing purposes using RegisterRLSClusterSpecifierPluginForTesting().
-	//
-	// TODO: Remove this function once the RLS env var is removed.
-	UnregisterRLSClusterSpecifierPluginForTesting func()
-
-	// RegisterRBACHTTPFilterForTesting registers the RBAC HTTP Filter for testing
-	// purposes, regardless of the RBAC environment variable.
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	RegisterRBACHTTPFilterForTesting func()
-
-	// UnregisterRBACHTTPFilterForTesting unregisters the RBAC HTTP Filter for
-	// testing purposes. This is needed because there is no way to unregister the
-	// HTTP Filter after registering it solely for testing purposes using
-	// RegisterRBACHTTPFilterForTesting().
-	//
-	// TODO: Remove this function once the RBAC env var is removed.
-	UnregisterRBACHTTPFilterForTesting func()
-
 	// ORCAAllowAnyMinReportingInterval is for examples/orca use ONLY.
 	ORCAAllowAnyMinReportingInterval any // func(so *orca.ServiceOptions)
 
diff --git a/public-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/public-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
index ba5c5a95..ada5251c 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
@@ -132,13 +132,13 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
 	// DNS address (non-IP).
 	ctx, cancel := context.WithCancel(context.Background())
 	d := &dnsResolver{
-		host:                 host,
-		port:                 port,
-		ctx:                  ctx,
-		cancel:               cancel,
-		cc:                   cc,
-		rn:                   make(chan struct{}, 1),
-		disableServiceConfig: opts.DisableServiceConfig,
+		host:                host,
+		port:                port,
+		ctx:                 ctx,
+		cancel:              cancel,
+		cc:                  cc,
+		rn:                  make(chan struct{}, 1),
+		enableServiceConfig: envconfig.EnableTXTServiceConfig && !opts.DisableServiceConfig,
 	}
 
 	d.resolver, err = internal.NewNetResolver(target.URL.Host)
@@ -181,8 +181,8 @@ type dnsResolver struct {
 	// finishes, race detector sometimes will warn lookup (READ the lookup
 	// function pointers) inside watcher() goroutine has data race with
 	// replaceNetFunc (WRITE the lookup function pointers).
-	wg                   sync.WaitGroup
-	disableServiceConfig bool
+	wg                  sync.WaitGroup
+	enableServiceConfig bool
 }
 
 // ResolveNow invoke an immediate resolution of the target that this
@@ -346,7 +346,7 @@ func (d *dnsResolver) lookup() (*resolver.State, error) {
 	if len(srv) > 0 {
 		state = grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: srv})
 	}
-	if !d.disableServiceConfig {
+	if d.enableServiceConfig {
 		state.ServiceConfig = d.lookupTXT(ctx)
 	}
 	return &state, nil
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/public-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
index ef72fbb3..a2831e5d 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -40,6 +40,13 @@ var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
 	e.SetMaxDynamicTableSizeLimit(v)
 }
 
+// itemNodePool is used to reduce heap allocations.
+var itemNodePool = sync.Pool{
+	New: func() any {
+		return &itemNode{}
+	},
+}
+
 type itemNode struct {
 	it   any
 	next *itemNode
@@ -51,7 +58,9 @@ type itemList struct {
 }
 
 func (il *itemList) enqueue(i any) {
-	n := &itemNode{it: i}
+	n := itemNodePool.Get().(*itemNode)
+	n.next = nil
+	n.it = i
 	if il.tail == nil {
 		il.head, il.tail = n, n
 		return
@@ -71,7 +80,9 @@ func (il *itemList) dequeue() any {
 		return nil
 	}
 	i := il.head.it
+	temp := il.head
 	il.head = il.head.next
+	itemNodePool.Put(temp)
 	if il.head == nil {
 		il.tail = nil
 	}
@@ -146,10 +157,11 @@ type earlyAbortStream struct {
 func (*earlyAbortStream) isTransportResponseFrame() bool { return false }
 
 type dataFrame struct {
-	streamID  uint32
-	endStream bool
-	h         []byte
-	reader    mem.Reader
+	streamID   uint32
+	endStream  bool
+	h          []byte
+	data       mem.BufferSlice
+	processing bool
 	// onEachWrite is called every time
 	// a part of data is written out.
 	onEachWrite func()
@@ -234,6 +246,7 @@ type outStream struct {
 	itl              *itemList
 	bytesOutStanding int
 	wq               *writeQuota
+	reader           mem.Reader
 
 	next *outStream
 	prev *outStream
@@ -461,7 +474,9 @@ func (c *controlBuffer) finish() {
 				v.onOrphaned(ErrConnClosing)
 			}
 		case *dataFrame:
-			_ = v.reader.Close()
+			if !v.processing {
+				v.data.Free()
+			}
 		}
 	}
 
@@ -650,10 +665,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
 
 func (l *loopyWriter) registerStreamHandler(h *registerStream) {
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	l.estdStreams[h.streamID] = str
 }
@@ -685,10 +701,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
 	}
 	// Case 2: Client wants to originate stream.
 	str := &outStream{
-		id:    h.streamID,
-		state: empty,
-		itl:   &itemList{},
-		wq:    h.wq,
+		id:     h.streamID,
+		state:  empty,
+		itl:    &itemList{},
+		wq:     h.wq,
+		reader: mem.BufferSlice{}.Reader(),
 	}
 	return l.originateStream(str, h)
 }
@@ -790,10 +807,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
 		// a RST_STREAM before stream initialization thus the stream might
 		// not be established yet.
 		delete(l.estdStreams, c.streamID)
+		str.reader.Close()
 		str.deleteSelf()
 		for head := str.itl.dequeueAll(); head != nil; head = head.next {
 			if df, ok := head.it.(*dataFrame); ok {
-				_ = df.reader.Close()
+				if !df.processing {
+					df.data.Free()
+				}
 			}
 		}
 	}
@@ -928,7 +948,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	if str == nil {
 		return true, nil
 	}
+	reader := str.reader
 	dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
+	if !dataItem.processing {
+		dataItem.processing = true
+		str.reader.Reset(dataItem.data)
+		dataItem.data.Free()
+	}
 	// A data item is represented by a dataFrame, since it later translates into
 	// multiple HTTP2 data frames.
 	// Every dataFrame has two buffers; h that keeps grpc-message header and data
@@ -936,13 +962,13 @@ func (l *loopyWriter) processData() (bool, error) {
 	// from data is copied to h to make as big as the maximum possible HTTP2 frame
 	// size.
 
-	if len(dataItem.h) == 0 && dataItem.reader.Remaining() == 0 { // Empty data frame
+	if len(dataItem.h) == 0 && reader.Remaining() == 0 { // Empty data frame
 		// Client sends out empty data frame with endStream = true
 		if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
 			return false, err
 		}
 		str.itl.dequeue() // remove the empty data item from stream
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		if str.itl.isEmpty() {
 			str.state = empty
 		} else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
@@ -971,8 +997,8 @@ func (l *loopyWriter) processData() (bool, error) {
 	}
 	// Compute how much of the header and data we can send within quota and max frame length
 	hSize := min(maxSize, len(dataItem.h))
-	dSize := min(maxSize-hSize, dataItem.reader.Remaining())
-	remainingBytes := len(dataItem.h) + dataItem.reader.Remaining() - hSize - dSize
+	dSize := min(maxSize-hSize, reader.Remaining())
+	remainingBytes := len(dataItem.h) + reader.Remaining() - hSize - dSize
 	size := hSize + dSize
 
 	var buf *[]byte
@@ -993,7 +1019,7 @@ func (l *loopyWriter) processData() (bool, error) {
 		defer pool.Put(buf)
 
 		copy((*buf)[:hSize], dataItem.h)
-		_, _ = dataItem.reader.Read((*buf)[hSize:])
+		_, _ = reader.Read((*buf)[hSize:])
 	}
 
 	// Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1014,7 +1040,7 @@ func (l *loopyWriter) processData() (bool, error) {
 	dataItem.h = dataItem.h[hSize:]
 
 	if remainingBytes == 0 { // All the data from that message was written out.
-		_ = dataItem.reader.Close()
+		_ = reader.Close()
 		str.itl.dequeue()
 	}
 	if str.itl.isEmpty() {
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/public-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 3dea2357..d954a64c 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -277,11 +277,13 @@ func (ht *serverHandlerTransport) writeStatus(s *ServerStream, st *status.Status
 	if err == nil { // transport has not been closed
 		// Note: The trailer fields are compressed with hpack after this call returns.
 		// No WireLength field is set here.
+		s.hdrMu.Lock()
 		for _, sh := range ht.stats {
 			sh.HandleRPC(s.Context(), &stats.OutTrailer{
 				Trailer: s.trailer.Copy(),
 			})
 		}
+		s.hdrMu.Unlock()
 	}
 	ht.Close(errors.New("finished writing status"))
 	return err
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/public-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index ef56592b..5467fe97 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -309,11 +309,9 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 			scheme = "https"
 		}
 	}
-	dynamicWindow := true
 	icwz := int32(initialWindowSize)
 	if opts.InitialConnWindowSize >= defaultWindowSize {
 		icwz = opts.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	writeBufSize := opts.WriteBufferSize
 	readBufSize := opts.ReadBufferSize
@@ -381,9 +379,8 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
 	t.controlBuf = newControlBuffer(t.ctxDone)
 	if opts.InitialWindowSize >= defaultWindowSize {
 		t.initialWindowSize = opts.InitialWindowSize
-		dynamicWindow = false
 	}
-	if dynamicWindow {
+	if !opts.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -1091,32 +1088,29 @@ func (t *http2Client) GracefulClose() {
 // Write formats the data into HTTP2 data frame(s) and sends it out. The caller
 // should proceed only if Write returns nil.
 func (t *http2Client) write(s *ClientStream, hdr []byte, data mem.BufferSlice, opts *WriteOptions) error {
-	reader := data.Reader()
-
 	if opts.Last {
 		// If it's the last message, update stream state.
 		if !s.compareAndSwapState(streamActive, streamWriteDone) {
-			_ = reader.Close()
 			return errStreamDone
 		}
 	} else if s.getState() != streamActive {
-		_ = reader.Close()
 		return errStreamDone
 	}
 	df := &dataFrame{
 		streamID:  s.id,
 		endStream: opts.Last,
 		h:         hdr,
-		reader:    reader,
+		data:      data,
 	}
-	if hdr != nil || df.reader.Remaining() != 0 { // If it's not an empty data frame, check quota.
-		if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-			_ = reader.Close()
+	dataLen := data.Len()
+	if hdr != nil || dataLen != 0 { // If it's not an empty data frame, check quota.
+		if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 			return err
 		}
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/public-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index e4c3731b..83cee314 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -132,6 +132,10 @@ type http2Server struct {
 	maxStreamID uint32 // max stream ID ever seen
 
 	logger *grpclog.PrefixLogger
+	// setResetPingStrikes is stored as a closure instead of making this a
+	// method on http2Server to avoid a heap allocation when converting a method
+	// to a closure for passing to frames objects.
+	setResetPingStrikes func()
 }
 
 // NewServerTransport creates a http2 transport with conn and configuration
@@ -176,16 +180,13 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 			Val: config.MaxStreams,
 		})
 	}
-	dynamicWindow := true
 	iwz := int32(initialWindowSize)
 	if config.InitialWindowSize >= defaultWindowSize {
 		iwz = config.InitialWindowSize
-		dynamicWindow = false
 	}
 	icwz := int32(initialWindowSize)
 	if config.InitialConnWindowSize >= defaultWindowSize {
 		icwz = config.InitialConnWindowSize
-		dynamicWindow = false
 	}
 	if iwz != defaultWindowSize {
 		isettings = append(isettings, http2.Setting{
@@ -266,6 +267,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 		initialWindowSize: iwz,
 		bufferPool:        config.BufferPool,
 	}
+	t.setResetPingStrikes = func() {
+		atomic.StoreUint32(&t.resetPingStrikes, 1)
+	}
 	var czSecurity credentials.ChannelzSecurityValue
 	if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok {
 		czSecurity = au.GetSecurityValue()
@@ -285,7 +289,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
 	t.logger = prefixLoggerForServerTransport(t)
 
 	t.controlBuf = newControlBuffer(t.done)
-	if dynamicWindow {
+	if !config.StaticWindowSize {
 		t.bdpEst = &bdpEstimator{
 			bdp:               initialWindowSize,
 			updateFlowControl: t.updateFlowControl,
@@ -596,10 +600,25 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
 			return nil
 		}
 	}
+
+	if s.ctx.Err() != nil {
+		t.mu.Unlock()
+		// Early abort in case the timeout was zero or so low it already fired.
+		t.controlBuf.put(&earlyAbortStream{
+			httpStatus:     http.StatusOK,
+			streamID:       s.id,
+			contentSubtype: s.contentSubtype,
+			status:         status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()),
+			rst:            !frame.StreamEnded(),
+		})
+		return nil
+	}
+
 	t.activeStreams[streamID] = s
 	if len(t.activeStreams) == 1 {
 		t.idle = time.Time{}
 	}
+
 	// Start a timer to close the stream on reaching the deadline.
 	if timeoutSet {
 		// We need to wait for s.cancel to be updated before calling
@@ -1016,10 +1035,6 @@ func (t *http2Server) writeHeader(s *ServerStream, md metadata.MD) error {
 	return nil
 }
 
-func (t *http2Server) setResetPingStrikes() {
-	atomic.StoreUint32(&t.resetPingStrikes, 1)
-}
-
 func (t *http2Server) writeHeaderLocked(s *ServerStream) error {
 	// TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
 	// first and create a slice of that exact size.
@@ -1132,17 +1147,13 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error {
 // Write converts the data into HTTP2 data frame and sends it out. Non-nil error
 // is returns if it fails (e.g., framing error, transport error).
 func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _ *WriteOptions) error {
-	reader := data.Reader()
-
 	if !s.isHeaderSent() { // Headers haven't been written yet.
 		if err := t.writeHeader(s, nil); err != nil {
-			_ = reader.Close()
 			return err
 		}
 	} else {
 		// Writing headers checks for this condition.
 		if s.getState() == streamDone {
-			_ = reader.Close()
 			return t.streamContextErr(s)
 		}
 	}
@@ -1150,15 +1161,16 @@ func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _
 	df := &dataFrame{
 		streamID:    s.id,
 		h:           hdr,
-		reader:      reader,
+		data:        data,
 		onEachWrite: t.setResetPingStrikes,
 	}
-	if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil {
-		_ = reader.Close()
+	dataLen := data.Len()
+	if err := s.wq.get(int32(len(hdr) + dataLen)); err != nil {
 		return t.streamContextErr(s)
 	}
+	data.Ref()
 	if err := t.controlBuf.put(df); err != nil {
-		_ = reader.Close()
+		data.Free()
 		return err
 	}
 	t.incrMsgSent()
@@ -1341,10 +1353,10 @@ func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCo
 	// called to interrupt the potential blocking on other goroutines.
 	s.cancel()
 
-	oldState := s.swapState(streamDone)
-	if oldState == streamDone {
-		return
-	}
+	// We can't return early even if the stream's state is "done" as the state
+	// might have been set by the `finishStream` method. Deleting the stream via
+	// `finishStream` can get blocked on flow control.
+	s.swapState(streamDone)
 	t.deleteStream(s, eosReceived)
 
 	t.controlBuf.put(&cleanupStream{
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/http_util.go b/public-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
index 607d2c4c..e3663f87 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -200,9 +200,6 @@ func decodeTimeout(s string) (time.Duration, error) {
 	if err != nil {
 		return 0, err
 	}
-	if t == 0 {
-		return 0, fmt.Errorf("transport: timeout must be positive: %q", s)
-	}
 	const maxHours = math.MaxInt64 / uint64(time.Hour)
 	if d == time.Hour && t > maxHours {
 		// This timeout would overflow math.MaxInt64; clamp it.
diff --git a/public-api/vendor/google.golang.org/grpc/internal/transport/transport.go b/public-api/vendor/google.golang.org/grpc/internal/transport/transport.go
index 1730a639..7dd53e80 100644
--- a/public-api/vendor/google.golang.org/grpc/internal/transport/transport.go
+++ b/public-api/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -466,6 +466,7 @@ type ServerConfig struct {
 	MaxHeaderListSize     *uint32
 	HeaderTableSize       *uint32
 	BufferPool            mem.BufferPool
+	StaticWindowSize      bool
 }
 
 // ConnectOptions covers all relevant options for communicating with the server.
@@ -504,6 +505,8 @@ type ConnectOptions struct {
 	MaxHeaderListSize *uint32
 	// The mem.BufferPool to use when reading/writing to the wire.
 	BufferPool mem.BufferPool
+	// StaticWindowSize controls whether dynamic window sizing is enabled.
+	StaticWindowSize bool
 }
 
 // WriteOptions provides additional hints and information for message
diff --git a/public-api/vendor/google.golang.org/grpc/mem/buffer_slice.go b/public-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
index 65002e2c..af510d20 100644
--- a/public-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
+++ b/public-api/vendor/google.golang.org/grpc/mem/buffer_slice.go
@@ -137,6 +137,9 @@ type Reader interface {
 	Close() error
 	// Remaining returns the number of unread bytes remaining in the slice.
 	Remaining() int
+	// Reset frees the currently held buffer slice and starts reading from the
+	// provided slice. This allows reusing the reader object.
+	Reset(s BufferSlice)
 }
 
 type sliceReader struct {
@@ -150,6 +153,14 @@ func (r *sliceReader) Remaining() int {
 	return r.len
 }
 
+func (r *sliceReader) Reset(s BufferSlice) {
+	r.data.Free()
+	s.Ref()
+	r.data = s
+	r.len = s.Len()
+	r.bufferIdx = 0
+}
+
 func (r *sliceReader) Close() error {
 	r.data.Free()
 	r.data = nil
diff --git a/public-api/vendor/google.golang.org/grpc/picker_wrapper.go b/public-api/vendor/google.golang.org/grpc/picker_wrapper.go
index a2d2a798..aa52bfe9 100644
--- a/public-api/vendor/google.golang.org/grpc/picker_wrapper.go
+++ b/public-api/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -29,7 +29,6 @@ import (
 	"google.golang.org/grpc/internal/channelz"
 	istatus "google.golang.org/grpc/internal/status"
 	"google.golang.org/grpc/internal/transport"
-	"google.golang.org/grpc/stats"
 	"google.golang.org/grpc/status"
 )
 
@@ -48,14 +47,11 @@ type pickerGeneration struct {
 // actions and unblock when there's a picker update.
 type pickerWrapper struct {
 	// If pickerGen holds a nil pointer, the pickerWrapper is closed.
-	pickerGen     atomic.Pointer[pickerGeneration]
-	statsHandlers []stats.Handler // to record blocking picker calls
+	pickerGen atomic.Pointer[pickerGeneration]
 }
 
-func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
-	pw := &pickerWrapper{
-		statsHandlers: statsHandlers,
-	}
+func newPickerWrapper() *pickerWrapper {
+	pw := &pickerWrapper{}
 	pw.pickerGen.Store(&pickerGeneration{
 		blockingCh: make(chan struct{}),
 	})
@@ -93,6 +89,12 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 	}
 }
 
+type pick struct {
+	transport transport.ClientTransport // the selected transport
+	result    balancer.PickResult       // the contents of the pick from the LB policy
+	blocked   bool                      // set if a picker call queued for a new picker
+}
+
 // pick returns the transport that will be used for the RPC.
 // It may block in the following cases:
 // - there's no picker
@@ -100,15 +102,16 @@ func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) {
 // - the current picker returns other errors and failfast is false.
 // - the subConn returned by the current picker is not READY
 // When one of these situations happens, pick blocks until the picker gets updated.
-func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (transport.ClientTransport, balancer.PickResult, error) {
+func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.PickInfo) (pick, error) {
 	var ch chan struct{}
 
 	var lastPickErr error
+	pickBlocked := false
 
 	for {
 		pg := pw.pickerGen.Load()
 		if pg == nil {
-			return nil, balancer.PickResult{}, ErrClientConnClosing
+			return pick{}, ErrClientConnClosing
 		}
 		if pg.picker == nil {
 			ch = pg.blockingCh
@@ -127,9 +130,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				}
 				switch ctx.Err() {
 				case context.DeadlineExceeded:
-					return nil, balancer.PickResult{}, status.Error(codes.DeadlineExceeded, errStr)
+					return pick{}, status.Error(codes.DeadlineExceeded, errStr)
 				case context.Canceled:
-					return nil, balancer.PickResult{}, status.Error(codes.Canceled, errStr)
+					return pick{}, status.Error(codes.Canceled, errStr)
 				}
 			case <-ch:
 			}
@@ -145,9 +148,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		// In the second case, the only way it will get to this conditional is
 		// if there is a new picker.
 		if ch != nil {
-			for _, sh := range pw.statsHandlers {
-				sh.HandleRPC(ctx, &stats.PickerUpdated{})
-			}
+			pickBlocked = true
 		}
 
 		ch = pg.blockingCh
@@ -164,7 +165,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				if istatus.IsRestrictedControlPlaneCode(st) {
 					err = status.Errorf(codes.Internal, "received picker error with illegal status: %v", err)
 				}
-				return nil, balancer.PickResult{}, dropError{error: err}
+				return pick{}, dropError{error: err}
 			}
 			// For all other errors, wait for ready RPCs should block and other
 			// RPCs should fail with unavailable.
@@ -172,7 +173,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 				lastPickErr = err
 				continue
 			}
-			return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error())
+			return pick{}, status.Error(codes.Unavailable, err.Error())
 		}
 
 		acbw, ok := pickResult.SubConn.(*acBalancerWrapper)
@@ -183,9 +184,8 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer.
 		if t := acbw.ac.getReadyTransport(); t != nil {
 			if channelz.IsOn() {
 				doneChannelzWrapper(acbw, &pickResult)
-				return t, pickResult, nil
 			}
-			return t, pickResult, nil
+			return pick{transport: t, result: pickResult, blocked: pickBlocked}, nil
 		}
 		if pickResult.Done != nil {
 			// Calling done with nil error, no bytes sent and no bytes received.
diff --git a/public-api/vendor/google.golang.org/grpc/resolver/resolver.go b/public-api/vendor/google.golang.org/grpc/resolver/resolver.go
index b84ef26d..8e6af951 100644
--- a/public-api/vendor/google.golang.org/grpc/resolver/resolver.go
+++ b/public-api/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -332,6 +332,11 @@ type AuthorityOverrider interface {
 	// OverrideAuthority returns the authority to use for a ClientConn with the
 	// given target. The implementation must generate it without blocking,
 	// typically in line, and must keep it unchanged.
+	//
+	// The returned string must be a valid ":authority" header value, i.e. be
+	// encoded according to
+	// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
+	// necessary.
 	OverrideAuthority(Target) string
 }
 
diff --git a/public-api/vendor/google.golang.org/grpc/server.go b/public-api/vendor/google.golang.org/grpc/server.go
index 976e70ae..1da2a542 100644
--- a/public-api/vendor/google.golang.org/grpc/server.go
+++ b/public-api/vendor/google.golang.org/grpc/server.go
@@ -179,6 +179,7 @@ type serverOptions struct {
 	numServerWorkers      uint32
 	bufferPool            mem.BufferPool
 	waitForHandlers       bool
+	staticWindowSize      bool
 }
 
 var defaultServerOptions = serverOptions{
@@ -279,6 +280,7 @@ func ReadBufferSize(s int) ServerOption {
 func InitialWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -287,6 +289,29 @@ func InitialWindowSize(s int32) ServerOption {
 func InitialConnWindowSize(s int32) ServerOption {
 	return newFuncServerOption(func(o *serverOptions) {
 		o.initialConnWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticStreamWindowSize returns a ServerOption to set the initial stream
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticStreamWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialWindowSize = s
+		o.staticWindowSize = true
+	})
+}
+
+// StaticConnWindowSize returns a ServerOption to set the initial connection
+// window size to the value provided and disables dynamic flow control.
+// The lower bound for window size is 64K and any value smaller than that
+// will be ignored.
+func StaticConnWindowSize(s int32) ServerOption {
+	return newFuncServerOption(func(o *serverOptions) {
+		o.initialConnWindowSize = s
+		o.staticWindowSize = true
 	})
 }
 
@@ -986,6 +1011,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
 		MaxHeaderListSize:     s.opts.maxHeaderListSize,
 		HeaderTableSize:       s.opts.headerTableSize,
 		BufferPool:            s.opts.bufferPool,
+		StaticWindowSize:      s.opts.staticWindowSize,
 	}
 	st, err := transport.NewServerTransport(c, config)
 	if err != nil {
@@ -1572,6 +1598,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv
 		s:                     stream,
 		p:                     &parser{r: stream, bufferPool: s.opts.bufferPool},
 		codec:                 s.getCodec(stream.ContentSubtype()),
+		desc:                  sd,
 		maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
 		maxSendMessageSize:    s.opts.maxSendMessageSize,
 		trInfo:                trInfo,
diff --git a/public-api/vendor/google.golang.org/grpc/stats/stats.go b/public-api/vendor/google.golang.org/grpc/stats/stats.go
index baf7740e..10bf998a 100644
--- a/public-api/vendor/google.golang.org/grpc/stats/stats.go
+++ b/public-api/vendor/google.golang.org/grpc/stats/stats.go
@@ -64,15 +64,21 @@ func (s *Begin) IsClient() bool { return s.Client }
 
 func (s *Begin) isRPCStats() {}
 
-// PickerUpdated indicates that the LB policy provided a new picker while the
-// RPC was waiting for one.
-type PickerUpdated struct{}
+// DelayedPickComplete indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+type DelayedPickComplete struct{}
 
-// IsClient indicates if the stats information is from client side. Only Client
-// Side interfaces with a Picker, thus always returns true.
-func (*PickerUpdated) IsClient() bool { return true }
+// IsClient indicates DelayedPickComplete is available on the client.
+func (*DelayedPickComplete) IsClient() bool { return true }
 
-func (*PickerUpdated) isRPCStats() {}
+func (*DelayedPickComplete) isRPCStats() {}
+
+// PickerUpdated indicates that the RPC is unblocked following a delay in
+// selecting a connection for the call.
+//
+// Deprecated: will be removed in a future release; use DelayedPickComplete
+// instead.
+type PickerUpdated = DelayedPickComplete
 
 // InPayload contains stats about an incoming payload.
 type InPayload struct {
diff --git a/public-api/vendor/google.golang.org/grpc/stream.go b/public-api/vendor/google.golang.org/grpc/stream.go
index d58bb647..d9bbd4c5 100644
--- a/public-api/vendor/google.golang.org/grpc/stream.go
+++ b/public-api/vendor/google.golang.org/grpc/stream.go
@@ -469,8 +469,9 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error)
 func (a *csAttempt) getTransport() error {
 	cs := a.cs
 
-	var err error
-	a.transport, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method)
+	pickInfo := balancer.PickInfo{Ctx: a.ctx, FullMethodName: cs.callHdr.Method}
+	pick, err := cs.cc.pickerWrapper.pick(a.ctx, cs.callInfo.failFast, pickInfo)
+	a.transport, a.pickResult = pick.transport, pick.result
 	if err != nil {
 		if de, ok := err.(dropError); ok {
 			err = de.error
@@ -481,6 +482,11 @@ func (a *csAttempt) getTransport() error {
 	if a.trInfo != nil {
 		a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr())
 	}
+	if pick.blocked {
+		for _, sh := range a.statsHandlers {
+			sh.HandleRPC(a.ctx, &stats.DelayedPickComplete{})
+		}
+	}
 	return nil
 }
 
@@ -1171,7 +1177,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (a *csAttempt) finish(err error) {
@@ -1495,7 +1501,7 @@ func (as *addrConnStream) RecvMsg(m any) (err error) {
 	} else if err != nil {
 		return toRPCErr(err)
 	}
-	return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want "))
+	return status.Errorf(codes.Internal, "cardinality violation: expected  for non server-streaming RPCs, but received another message")
 }
 
 func (as *addrConnStream) finish(err error) {
@@ -1580,6 +1586,7 @@ type serverStream struct {
 	s     *transport.ServerStream
 	p     *parser
 	codec baseCodec
+	desc  *StreamDesc
 
 	compressorV0   Compressor
 	compressorV1   encoding.Compressor
@@ -1588,6 +1595,8 @@ type serverStream struct {
 
 	sendCompressorName string
 
+	recvFirstMsg bool // set after the first message is received
+
 	maxReceiveMessageSize int
 	maxSendMessageSize    int
 	trInfo                *traceInfo
@@ -1774,6 +1783,10 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 					binlog.Log(ss.ctx, chc)
 				}
 			}
+			// Received no request msg for non-client streaming rpcs.
+			if !ss.desc.ClientStreams && !ss.recvFirstMsg {
+				return status.Error(codes.Internal, "cardinality violation: received no request message from non-client-streaming RPC")
+			}
 			return err
 		}
 		if err == io.ErrUnexpectedEOF {
@@ -1781,6 +1794,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 		}
 		return toRPCErr(err)
 	}
+	ss.recvFirstMsg = true
 	if len(ss.statsHandler) != 0 {
 		for _, sh := range ss.statsHandler {
 			sh.HandleRPC(ss.s.Context(), &stats.InPayload{
@@ -1800,7 +1814,19 @@ func (ss *serverStream) RecvMsg(m any) (err error) {
 			binlog.Log(ss.ctx, cm)
 		}
 	}
-	return nil
+
+	if ss.desc.ClientStreams {
+		// Subsequent messages should be received by subsequent RecvMsg calls.
+		return nil
+	}
+	// Special handling for non-client-stream rpcs.
+	// This recv expects EOF or errors, so we don't collect inPayload.
+	if err := recv(ss.p, ss.codec, ss.s, ss.decompressorV0, m, ss.maxReceiveMessageSize, nil, ss.decompressorV1, true); err == io.EOF {
+		return nil
+	} else if err != nil {
+		return err
+	}
+	return status.Error(codes.Internal, "cardinality violation: received multiple request messages for non-client-streaming RPC")
 }
 
 // MethodFromServerStream returns the method string for the input stream.
diff --git a/public-api/vendor/google.golang.org/grpc/version.go b/public-api/vendor/google.golang.org/grpc/version.go
index bd82673d..468f1106 100644
--- a/public-api/vendor/google.golang.org/grpc/version.go
+++ b/public-api/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.73.0"
+const Version = "1.75.1"
diff --git a/public-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/public-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
index e942bc98..743bfb81 100644
--- a/public-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
+++ b/public-api/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
@@ -371,7 +371,31 @@ func ConsumeVarint(b []byte) (v uint64, n int) {
 func SizeVarint(v uint64) int {
 	// This computes 1 + (bits.Len64(v)-1)/7.
 	// 9/64 is a good enough approximation of 1/7
-	return int(9*uint32(bits.Len64(v))+64) / 64
+	//
+	// The Go compiler can translate the bits.LeadingZeros64 call into the LZCNT
+	// instruction, which is very fast on CPUs from the last few years. The
+	// specific way of expressing the calculation matches C++ Protobuf, see
+	// https://godbolt.org/z/4P3h53oM4 for the C++ code and how gcc/clang
+	// optimize that function for GOAMD64=v1 and GOAMD64=v3 (-march=haswell).
+
+	// By OR'ing v with 1, we guarantee that v is never 0, without changing the
+	// result of SizeVarint. LZCNT is not defined for 0, meaning the compiler
+	// needs to add extra instructions to handle that case.
+	//
+	// The Go compiler currently (go1.24.4) does not make use of this knowledge.
+	// This opportunity (removing the XOR instruction, which handles the 0 case)
+	// results in a small (1%) performance win across CPU architectures.
+	//
+	// Independently of avoiding the 0 case, we need the v |= 1 line because
+	// it allows the Go compiler to eliminate an extra XCHGL barrier.
+	v |= 1
+
+	// It would be clearer to write log2value := 63 - uint32(...), but
+	// writing uint32(...) ^ 63 is much more efficient (-14% ARM, -20% Intel).
+	// Proof of identity for our value range [0..63]:
+	// https://go.dev/play/p/Pdn9hEWYakX
+	log2value := uint32(bits.LeadingZeros64(v)) ^ 63
+	return int((log2value*9 + (64 + 9)) / 64)
 }
 
 // AppendFixed32 appends v to b as a little-endian uint32.
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/public-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb
index 323829da..04696351 100644
Binary files a/public-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb and b/public-api/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb differ
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 688aabe4..dbcf90b8 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -72,9 +72,10 @@ type (
 		EditionFeatures EditionFeatures
 	}
 	FileL2 struct {
-		Options   func() protoreflect.ProtoMessage
-		Imports   FileImports
-		Locations SourceLocations
+		Options       func() protoreflect.ProtoMessage
+		Imports       FileImports
+		OptionImports func() protoreflect.FileImports
+		Locations     SourceLocations
 	}
 
 	// EditionFeatures is a frequently-instantiated struct, so please take care
@@ -126,12 +127,9 @@ func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
 func (fd *File) Parent() protoreflect.Descriptor         { return nil }
 func (fd *File) Index() int                              { return 0 }
 func (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }
-
-// Not exported and just used to reconstruct the original FileDescriptor proto
-func (fd *File) Edition() int32                  { return int32(fd.L1.Edition) }
-func (fd *File) Name() protoreflect.Name         { return fd.L1.Package.Name() }
-func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
-func (fd *File) IsPlaceholder() bool             { return false }
+func (fd *File) Name() protoreflect.Name                 { return fd.L1.Package.Name() }
+func (fd *File) FullName() protoreflect.FullName         { return fd.L1.Package }
+func (fd *File) IsPlaceholder() bool                     { return false }
 func (fd *File) Options() protoreflect.ProtoMessage {
 	if f := fd.lazyInit().Options; f != nil {
 		return f()
@@ -150,6 +148,16 @@ func (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatD
 func (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
 func (fd *File) ProtoInternal(pragma.DoNotImplement)           {}
 
+// The next two are not part of the FileDescriptor interface. They are just used to reconstruct
+// the original FileDescriptor proto.
+func (fd *File) Edition() int32 { return int32(fd.L1.Edition) }
+func (fd *File) OptionImports() protoreflect.FileImports {
+	if f := fd.lazyInit().OptionImports; f != nil {
+		return f()
+	}
+	return emptyFiles
+}
+
 func (fd *File) lazyInit() *FileL2 {
 	if atomic.LoadUint32(&fd.once) == 0 {
 		fd.lazyInitOnce()
@@ -182,9 +190,9 @@ type (
 		L2 *EnumL2 // protected by fileDesc.once
 	}
 	EnumL1 struct {
-		eagerValues bool // controls whether EnumL2.Values is already populated
-
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		eagerValues     bool // controls whether EnumL2.Values is already populated
 	}
 	EnumL2 struct {
 		Options        func() protoreflect.ProtoMessage
@@ -219,6 +227,11 @@ func (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit()
 func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
 func (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
 func (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
+
+// This is not part of the EnumDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (ed *Enum) Visibility() int32 { return ed.L1.Visibility }
+
 func (ed *Enum) lazyInit() *EnumL2 {
 	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return ed.L2
@@ -244,13 +257,13 @@ type (
 		L2 *MessageL2 // protected by fileDesc.once
 	}
 	MessageL1 struct {
-		Enums        Enums
-		Messages     Messages
-		Extensions   Extensions
-		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
-		IsMessageSet bool // promoted from google.protobuf.MessageOptions
-
+		Enums           Enums
+		Messages        Messages
+		Extensions      Extensions
 		EditionFeatures EditionFeatures
+		Visibility      int32
+		IsMapEntry      bool // promoted from google.protobuf.MessageOptions
+		IsMessageSet    bool // promoted from google.protobuf.MessageOptions
 	}
 	MessageL2 struct {
 		Options               func() protoreflect.ProtoMessage
@@ -319,6 +332,11 @@ func (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L
 func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
 func (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
 func (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
+
+// This is not part of the MessageDescriptor interface. It is just used to reconstruct
+// the original FileDescriptor proto.
+func (md *Message) Visibility() int32 { return md.L1.Visibility }
+
 func (md *Message) lazyInit() *MessageL2 {
 	md.L0.ParentFile.lazyInit() // implicitly initializes L2
 	return md.L2
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
index d2f54949..e91860f5 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
@@ -284,6 +284,13 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protorefl
 			case genid.EnumDescriptorProto_Value_field_number:
 				numValues++
 			}
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.EnumDescriptorProto_Visibility_field_number:
+				ed.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
@@ -365,6 +372,13 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
 				md.unmarshalSeedOptions(v)
 			}
 			prevField = num
+		case protowire.VarintType:
+			v, m := protowire.ConsumeVarint(b)
+			b = b[m:]
+			switch num {
+			case genid.DescriptorProto_Visibility_field_number:
+				md.L1.Visibility = int32(v)
+			}
 		default:
 			m := protowire.ConsumeFieldValue(num, typ, b)
 			b = b[m:]
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index d4c94458..dd31faae 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -134,6 +134,7 @@ func (fd *File) unmarshalFull(b []byte) {
 
 	var enumIdx, messageIdx, extensionIdx, serviceIdx int
 	var rawOptions []byte
+	var optionImports []string
 	fd.L2 = new(FileL2)
 	for len(b) > 0 {
 		num, typ, n := protowire.ConsumeTag(b)
@@ -157,6 +158,8 @@ func (fd *File) unmarshalFull(b []byte) {
 					imp = PlaceholderFile(path)
 				}
 				fd.L2.Imports = append(fd.L2.Imports, protoreflect.FileImport{FileDescriptor: imp})
+			case genid.FileDescriptorProto_OptionDependency_field_number:
+				optionImports = append(optionImports, sb.MakeString(v))
 			case genid.FileDescriptorProto_EnumType_field_number:
 				fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
 				enumIdx++
@@ -178,6 +181,23 @@ func (fd *File) unmarshalFull(b []byte) {
 		}
 	}
 	fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
+	if len(optionImports) > 0 {
+		var imps FileImports
+		var once sync.Once
+		fd.L2.OptionImports = func() protoreflect.FileImports {
+			once.Do(func() {
+				imps = make(FileImports, len(optionImports))
+				for i, path := range optionImports {
+					imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
+					if imp == nil {
+						imp = PlaceholderFile(path)
+					}
+					imps[i] = protoreflect.FileImport{FileDescriptor: imp}
+				}
+			})
+			return &imps
+		}
+	}
 }
 
 func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
index b08b7183..66ba9068 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
@@ -13,8 +13,10 @@ import (
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
-var defaultsCache = make(map[Edition]EditionFeatures)
-var defaultsKeys = []Edition{}
+var (
+	defaultsCache = make(map[Edition]EditionFeatures)
+	defaultsKeys  = []Edition{}
+)
 
 func init() {
 	unmarshalEditionDefaults(editiondefaults.Defaults)
@@ -41,7 +43,7 @@ func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
 			b = b[m:]
 			parent.StripEnumPrefix = int(v)
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling GoFeatures", num))
 		}
 	}
 	return parent
@@ -72,8 +74,11 @@ func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
 			case genid.FeatureSet_EnforceNamingStyle_field_number:
 				// EnforceNamingStyle is enforced in protoc, languages other than C++
 				// are not supposed to do anything with this feature.
+			case genid.FeatureSet_DefaultSymbolVisibility_field_number:
+				// DefaultSymbolVisibility is enforced in protoc, runtimes should not
+				// inspect this value.
 			default:
-				panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
+				panic(fmt.Sprintf("unknown field number %d while unmarshalling FeatureSet", num))
 			}
 		case protowire.BytesType:
 			v, m := protowire.ConsumeBytes(b)
@@ -147,7 +152,7 @@ func unmarshalEditionDefaults(b []byte) {
 			_, m := protowire.ConsumeVarint(b)
 			b = b[m:]
 		default:
-			panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
+			panic(fmt.Sprintf("unknown field number %d while unmarshalling EditionDefault", num))
 		}
 	}
 }
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
new file mode 100644
index 00000000..a12ec979
--- /dev/null
+++ b/public-api/vendor/google.golang.org/protobuf/internal/filedesc/presence.go
@@ -0,0 +1,33 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package filedesc
+
+import "google.golang.org/protobuf/reflect/protoreflect"
+
+// UsePresenceForField reports whether the presence bitmap should be used for
+// the specified field.
+func UsePresenceForField(fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
+	switch {
+	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
+		// Oneof fields never use the presence bitmap.
+		//
+		// Synthetic oneofs are an exception: Those are used to implement proto3
+		// optional fields and hence should follow non-oneof field semantics.
+		return false, false
+
+	case fd.IsMap():
+		// Map-typed fields never use the presence bitmap.
+		return false, false
+
+	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
+		// Lazy fields always use the presence bitmap (only messages can be lazy).
+		isLazy := fd.(interface{ IsLazy() bool }).IsLazy()
+		return isLazy, isLazy
+
+	default:
+		// If the field has presence, use the presence bitmap.
+		return fd.HasPresence(), false
+	}
+}
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go b/public-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
index df8f9185..3ceb6fa7 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/genid/api_gen.go
@@ -27,6 +27,7 @@ const (
 	Api_SourceContext_field_name protoreflect.Name = "source_context"
 	Api_Mixins_field_name        protoreflect.Name = "mixins"
 	Api_Syntax_field_name        protoreflect.Name = "syntax"
+	Api_Edition_field_name       protoreflect.Name = "edition"
 
 	Api_Name_field_fullname          protoreflect.FullName = "google.protobuf.Api.name"
 	Api_Methods_field_fullname       protoreflect.FullName = "google.protobuf.Api.methods"
@@ -35,6 +36,7 @@ const (
 	Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context"
 	Api_Mixins_field_fullname        protoreflect.FullName = "google.protobuf.Api.mixins"
 	Api_Syntax_field_fullname        protoreflect.FullName = "google.protobuf.Api.syntax"
+	Api_Edition_field_fullname       protoreflect.FullName = "google.protobuf.Api.edition"
 )
 
 // Field numbers for google.protobuf.Api.
@@ -46,6 +48,7 @@ const (
 	Api_SourceContext_field_number protoreflect.FieldNumber = 5
 	Api_Mixins_field_number        protoreflect.FieldNumber = 6
 	Api_Syntax_field_number        protoreflect.FieldNumber = 7
+	Api_Edition_field_number       protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Method.
@@ -63,6 +66,7 @@ const (
 	Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming"
 	Method_Options_field_name           protoreflect.Name = "options"
 	Method_Syntax_field_name            protoreflect.Name = "syntax"
+	Method_Edition_field_name           protoreflect.Name = "edition"
 
 	Method_Name_field_fullname              protoreflect.FullName = "google.protobuf.Method.name"
 	Method_RequestTypeUrl_field_fullname    protoreflect.FullName = "google.protobuf.Method.request_type_url"
@@ -71,6 +75,7 @@ const (
 	Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming"
 	Method_Options_field_fullname           protoreflect.FullName = "google.protobuf.Method.options"
 	Method_Syntax_field_fullname            protoreflect.FullName = "google.protobuf.Method.syntax"
+	Method_Edition_field_fullname           protoreflect.FullName = "google.protobuf.Method.edition"
 )
 
 // Field numbers for google.protobuf.Method.
@@ -82,6 +87,7 @@ const (
 	Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5
 	Method_Options_field_number           protoreflect.FieldNumber = 6
 	Method_Syntax_field_number            protoreflect.FieldNumber = 7
+	Method_Edition_field_number           protoreflect.FieldNumber = 8
 )
 
 // Names for google.protobuf.Mixin.
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/public-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
index 39524782..950a6a32 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
@@ -34,6 +34,19 @@ const (
 	Edition_EDITION_MAX_enum_value             = 2147483647
 )
 
+// Full and short names for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_enum_fullname = "google.protobuf.SymbolVisibility"
+	SymbolVisibility_enum_name     = "SymbolVisibility"
+)
+
+// Enum values for google.protobuf.SymbolVisibility.
+const (
+	SymbolVisibility_VISIBILITY_UNSET_enum_value  = 0
+	SymbolVisibility_VISIBILITY_LOCAL_enum_value  = 1
+	SymbolVisibility_VISIBILITY_EXPORT_enum_value = 2
+)
+
 // Names for google.protobuf.FileDescriptorSet.
 const (
 	FileDescriptorSet_message_name     protoreflect.Name     = "FileDescriptorSet"
@@ -65,6 +78,7 @@ const (
 	FileDescriptorProto_Dependency_field_name       protoreflect.Name = "dependency"
 	FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency"
 	FileDescriptorProto_WeakDependency_field_name   protoreflect.Name = "weak_dependency"
+	FileDescriptorProto_OptionDependency_field_name protoreflect.Name = "option_dependency"
 	FileDescriptorProto_MessageType_field_name      protoreflect.Name = "message_type"
 	FileDescriptorProto_EnumType_field_name         protoreflect.Name = "enum_type"
 	FileDescriptorProto_Service_field_name          protoreflect.Name = "service"
@@ -79,6 +93,7 @@ const (
 	FileDescriptorProto_Dependency_field_fullname       protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency"
 	FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency"
 	FileDescriptorProto_WeakDependency_field_fullname   protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency"
+	FileDescriptorProto_OptionDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.option_dependency"
 	FileDescriptorProto_MessageType_field_fullname      protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type"
 	FileDescriptorProto_EnumType_field_fullname         protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type"
 	FileDescriptorProto_Service_field_fullname          protoreflect.FullName = "google.protobuf.FileDescriptorProto.service"
@@ -96,6 +111,7 @@ const (
 	FileDescriptorProto_Dependency_field_number       protoreflect.FieldNumber = 3
 	FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10
 	FileDescriptorProto_WeakDependency_field_number   protoreflect.FieldNumber = 11
+	FileDescriptorProto_OptionDependency_field_number protoreflect.FieldNumber = 15
 	FileDescriptorProto_MessageType_field_number      protoreflect.FieldNumber = 4
 	FileDescriptorProto_EnumType_field_number         protoreflect.FieldNumber = 5
 	FileDescriptorProto_Service_field_number          protoreflect.FieldNumber = 6
@@ -124,6 +140,7 @@ const (
 	DescriptorProto_Options_field_name        protoreflect.Name = "options"
 	DescriptorProto_ReservedRange_field_name  protoreflect.Name = "reserved_range"
 	DescriptorProto_ReservedName_field_name   protoreflect.Name = "reserved_name"
+	DescriptorProto_Visibility_field_name     protoreflect.Name = "visibility"
 
 	DescriptorProto_Name_field_fullname           protoreflect.FullName = "google.protobuf.DescriptorProto.name"
 	DescriptorProto_Field_field_fullname          protoreflect.FullName = "google.protobuf.DescriptorProto.field"
@@ -135,6 +152,7 @@ const (
 	DescriptorProto_Options_field_fullname        protoreflect.FullName = "google.protobuf.DescriptorProto.options"
 	DescriptorProto_ReservedRange_field_fullname  protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range"
 	DescriptorProto_ReservedName_field_fullname   protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name"
+	DescriptorProto_Visibility_field_fullname     protoreflect.FullName = "google.protobuf.DescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.DescriptorProto.
@@ -149,6 +167,7 @@ const (
 	DescriptorProto_Options_field_number        protoreflect.FieldNumber = 7
 	DescriptorProto_ReservedRange_field_number  protoreflect.FieldNumber = 9
 	DescriptorProto_ReservedName_field_number   protoreflect.FieldNumber = 10
+	DescriptorProto_Visibility_field_number     protoreflect.FieldNumber = 11
 )
 
 // Names for google.protobuf.DescriptorProto.ExtensionRange.
@@ -388,12 +407,14 @@ const (
 	EnumDescriptorProto_Options_field_name       protoreflect.Name = "options"
 	EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range"
 	EnumDescriptorProto_ReservedName_field_name  protoreflect.Name = "reserved_name"
+	EnumDescriptorProto_Visibility_field_name    protoreflect.Name = "visibility"
 
 	EnumDescriptorProto_Name_field_fullname          protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name"
 	EnumDescriptorProto_Value_field_fullname         protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value"
 	EnumDescriptorProto_Options_field_fullname       protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options"
 	EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range"
 	EnumDescriptorProto_ReservedName_field_fullname  protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name"
+	EnumDescriptorProto_Visibility_field_fullname    protoreflect.FullName = "google.protobuf.EnumDescriptorProto.visibility"
 )
 
 // Field numbers for google.protobuf.EnumDescriptorProto.
@@ -403,6 +424,7 @@ const (
 	EnumDescriptorProto_Options_field_number       protoreflect.FieldNumber = 3
 	EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4
 	EnumDescriptorProto_ReservedName_field_number  protoreflect.FieldNumber = 5
+	EnumDescriptorProto_Visibility_field_number    protoreflect.FieldNumber = 6
 )
 
 // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange.
@@ -1008,32 +1030,35 @@ const (
 
 // Field names for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_name         protoreflect.Name = "field_presence"
-	FeatureSet_EnumType_field_name              protoreflect.Name = "enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_name        protoreflect.Name = "utf8_validation"
-	FeatureSet_MessageEncoding_field_name       protoreflect.Name = "message_encoding"
-	FeatureSet_JsonFormat_field_name            protoreflect.Name = "json_format"
-	FeatureSet_EnforceNamingStyle_field_name    protoreflect.Name = "enforce_naming_style"
-
-	FeatureSet_FieldPresence_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
-	FeatureSet_EnumType_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
-	FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
-	FeatureSet_Utf8Validation_field_fullname        protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
-	FeatureSet_MessageEncoding_field_fullname       protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
-	FeatureSet_JsonFormat_field_fullname            protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
-	FeatureSet_EnforceNamingStyle_field_fullname    protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_FieldPresence_field_name           protoreflect.Name = "field_presence"
+	FeatureSet_EnumType_field_name                protoreflect.Name = "enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_name   protoreflect.Name = "repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_name          protoreflect.Name = "utf8_validation"
+	FeatureSet_MessageEncoding_field_name         protoreflect.Name = "message_encoding"
+	FeatureSet_JsonFormat_field_name              protoreflect.Name = "json_format"
+	FeatureSet_EnforceNamingStyle_field_name      protoreflect.Name = "enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_name protoreflect.Name = "default_symbol_visibility"
+
+	FeatureSet_FieldPresence_field_fullname           protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
+	FeatureSet_EnumType_field_fullname                protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
+	FeatureSet_RepeatedFieldEncoding_field_fullname   protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
+	FeatureSet_Utf8Validation_field_fullname          protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
+	FeatureSet_MessageEncoding_field_fullname         protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
+	FeatureSet_JsonFormat_field_fullname              protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
+	FeatureSet_EnforceNamingStyle_field_fullname      protoreflect.FullName = "google.protobuf.FeatureSet.enforce_naming_style"
+	FeatureSet_DefaultSymbolVisibility_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.default_symbol_visibility"
 )
 
 // Field numbers for google.protobuf.FeatureSet.
 const (
-	FeatureSet_FieldPresence_field_number         protoreflect.FieldNumber = 1
-	FeatureSet_EnumType_field_number              protoreflect.FieldNumber = 2
-	FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
-	FeatureSet_Utf8Validation_field_number        protoreflect.FieldNumber = 4
-	FeatureSet_MessageEncoding_field_number       protoreflect.FieldNumber = 5
-	FeatureSet_JsonFormat_field_number            protoreflect.FieldNumber = 6
-	FeatureSet_EnforceNamingStyle_field_number    protoreflect.FieldNumber = 7
+	FeatureSet_FieldPresence_field_number           protoreflect.FieldNumber = 1
+	FeatureSet_EnumType_field_number                protoreflect.FieldNumber = 2
+	FeatureSet_RepeatedFieldEncoding_field_number   protoreflect.FieldNumber = 3
+	FeatureSet_Utf8Validation_field_number          protoreflect.FieldNumber = 4
+	FeatureSet_MessageEncoding_field_number         protoreflect.FieldNumber = 5
+	FeatureSet_JsonFormat_field_number              protoreflect.FieldNumber = 6
+	FeatureSet_EnforceNamingStyle_field_number      protoreflect.FieldNumber = 7
+	FeatureSet_DefaultSymbolVisibility_field_number protoreflect.FieldNumber = 8
 )
 
 // Full and short names for google.protobuf.FeatureSet.FieldPresence.
@@ -1128,6 +1153,27 @@ const (
 	FeatureSet_STYLE_LEGACY_enum_value                 = 2
 )
 
+// Names for google.protobuf.FeatureSet.VisibilityFeature.
+const (
+	FeatureSet_VisibilityFeature_message_name     protoreflect.Name     = "VisibilityFeature"
+	FeatureSet_VisibilityFeature_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet.VisibilityFeature"
+)
+
+// Full and short names for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_fullname = "google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility"
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_enum_name     = "DefaultSymbolVisibility"
+)
+
+// Enum values for google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility.
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN_enum_value = 0
+	FeatureSet_VisibilityFeature_EXPORT_ALL_enum_value                        = 1
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL_enum_value                  = 2
+	FeatureSet_VisibilityFeature_LOCAL_ALL_enum_value                         = 3
+	FeatureSet_VisibilityFeature_STRICT_enum_value                            = 4
+)
+
 // Names for google.protobuf.FeatureSetDefaults.
 const (
 	FeatureSetDefaults_message_name     protoreflect.Name     = "FeatureSetDefaults"
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/public-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
index 41c1f74e..bdad12a9 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
@@ -11,6 +11,7 @@ import (
 
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/encoding/messageset"
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/order"
 	"google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -80,7 +81,7 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
 		// permit us to skip over definitely-unset fields at marshal time.
 
 		var hasPresence bool
-		hasPresence, cf.isLazy = usePresenceForField(si, fd)
+		hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
 
 		if hasPresence {
 			cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/public-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
index dd55e8e0..5a439daa 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"sync/atomic"
 
+	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/reflect/protoreflect"
 )
 
@@ -53,7 +54,7 @@ func opaqueInitHook(mi *MessageInfo) bool {
 		fd := fds.Get(i)
 		fs := si.fieldsByNumber[fd.Number()]
 		var fi fieldInfo
-		usePresence, _ := usePresenceForField(si, fd)
+		usePresence, _ := filedesc.UsePresenceForField(fd)
 
 		switch {
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
@@ -343,17 +344,15 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return false
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return false
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			return rv.Elem().Len() > 0
 		},
 		clear: func(p pointer) {
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if !sp.IsNil() {
-				rv := sp.AsValueOf(fs.Type.Elem())
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if !rv.IsNil() {
 				rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
 			}
 		},
@@ -361,11 +360,10 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn
 			if p.IsNil() {
 				return conv.Zero()
 			}
-			sp := p.Apply(fieldOffset).AtomicGetPointer()
-			if sp.IsNil() {
+			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
+			if rv.IsNil() {
 				return conv.Zero()
 			}
-			rv := sp.AsValueOf(fs.Type.Elem())
 			if rv.Elem().Len() == 0 {
 				return conv.Zero()
 			}
@@ -598,30 +596,3 @@ func (mi *MessageInfo) clearPresent(p pointer, index uint32) {
 func (mi *MessageInfo) present(p pointer, index uint32) bool {
 	return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
 }
-
-// usePresenceForField implements the somewhat intricate logic of when
-// the presence bitmap is used for a field.  The main logic is that a
-// field that is optional or that can be lazy will use the presence
-// bit, but for proto2, also maps have a presence bit. It also records
-// if the field can ever be lazy, which is true if we have a
-// lazyOffset and the field is a message or a slice of messages. A
-// field that is lazy will always need a presence bit.  Oneofs are not
-// lazy and do not use presence, unless they are a synthetic oneof,
-// which is a proto3 optional field. For proto3 optionals, we use the
-// presence and they can also be lazy when applicable (a message).
-func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (usePresence, canBeLazy bool) {
-	hasLazyField := fd.(interface{ IsLazy() bool }).IsLazy()
-
-	// Non-oneof scalar fields with explicit field presence use the presence array.
-	usesPresenceArray := fd.HasPresence() && fd.Message() == nil && (fd.ContainingOneof() == nil || fd.ContainingOneof().IsSynthetic())
-	switch {
-	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
-		return false, false
-	case fd.IsMap():
-		return false, false
-	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
-		return hasLazyField, hasLazyField
-	default:
-		return usesPresenceArray || (hasLazyField && fd.HasPresence()), false
-	}
-}
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/impl/presence.go b/public-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
index 914cb1de..443afe81 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/impl/presence.go
@@ -32,9 +32,6 @@ func (p presence) toElem(num uint32) (ret *uint32) {
 
 // Present checks for the presence of a specific field number in a presence set.
 func (p presence) Present(num uint32) bool {
-	if p.P == nil {
-		return false
-	}
 	return Export{}.Present(p.toElem(num), num)
 }
 
diff --git a/public-api/vendor/google.golang.org/protobuf/internal/version/version.go b/public-api/vendor/google.golang.org/protobuf/internal/version/version.go
index aac1cb18..77de0f23 100644
--- a/public-api/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/public-api/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -52,7 +52,7 @@ import (
 const (
 	Major      = 1
 	Minor      = 36
-	Patch      = 6
+	Patch      = 10
 	PreRelease = ""
 )
 
diff --git a/public-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/public-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
index a4a0a297..730331e6 100644
--- a/public-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
+++ b/public-api/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
@@ -21,6 +21,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "public_dependency", nil)
 	case 11:
 		b = p.appendRepeatedField(b, "weak_dependency", nil)
+	case 15:
+		b = p.appendRepeatedField(b, "option_dependency", nil)
 	case 4:
 		b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto)
 	case 5:
@@ -66,6 +68,8 @@ func (p *SourcePath) appendDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange)
 	case 10:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 11:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -85,6 +89,8 @@ func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte {
 		b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange)
 	case 5:
 		b = p.appendRepeatedField(b, "reserved_name", nil)
+	case 6:
+		b = p.appendSingularField(b, "visibility", nil)
 	}
 	return b
 }
@@ -400,6 +406,8 @@ func (p *SourcePath) appendFeatureSet(b []byte) []byte {
 		b = p.appendSingularField(b, "json_format", nil)
 	case 7:
 		b = p.appendSingularField(b, "enforce_naming_style", nil)
+	case 8:
+		b = p.appendSingularField(b, "default_symbol_visibility", nil)
 	}
 	return b
 }
diff --git a/public-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/public-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
index 7fe280f1..4eacb523 100644
--- a/public-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
+++ b/public-api/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
@@ -151,6 +151,70 @@ func (Edition) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0}
 }
 
+// Describes the 'visibility' of a symbol with respect to the proto import
+// system. Symbols can only be imported when the visibility rules do not prevent
+// it (ex: local symbols cannot be imported).  Visibility modifiers can only set
+// on `message` and `enum` as they are the only types available to be referenced
+// from other files.
+type SymbolVisibility int32
+
+const (
+	SymbolVisibility_VISIBILITY_UNSET  SymbolVisibility = 0
+	SymbolVisibility_VISIBILITY_LOCAL  SymbolVisibility = 1
+	SymbolVisibility_VISIBILITY_EXPORT SymbolVisibility = 2
+)
+
+// Enum value maps for SymbolVisibility.
+var (
+	SymbolVisibility_name = map[int32]string{
+		0: "VISIBILITY_UNSET",
+		1: "VISIBILITY_LOCAL",
+		2: "VISIBILITY_EXPORT",
+	}
+	SymbolVisibility_value = map[string]int32{
+		"VISIBILITY_UNSET":  0,
+		"VISIBILITY_LOCAL":  1,
+		"VISIBILITY_EXPORT": 2,
+	}
+)
+
+func (x SymbolVisibility) Enum() *SymbolVisibility {
+	p := new(SymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x SymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+}
+
+func (SymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+}
+
+func (x SymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *SymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = SymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use SymbolVisibility.Descriptor instead.
+func (SymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1}
+}
+
 // The verification state of the extension range.
 type ExtensionRangeOptions_VerificationState int32
 
@@ -183,11 +247,11 @@ func (x ExtensionRangeOptions_VerificationState) String() string {
 }
 
 func (ExtensionRangeOptions_VerificationState) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
 }
 
 func (ExtensionRangeOptions_VerificationState) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[1]
+	return &file_google_protobuf_descriptor_proto_enumTypes[2]
 }
 
 func (x ExtensionRangeOptions_VerificationState) Number() protoreflect.EnumNumber {
@@ -299,11 +363,11 @@ func (x FieldDescriptorProto_Type) String() string {
 }
 
 func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
 }
 
 func (FieldDescriptorProto_Type) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[2]
+	return &file_google_protobuf_descriptor_proto_enumTypes[3]
 }
 
 func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber {
@@ -362,11 +426,11 @@ func (x FieldDescriptorProto_Label) String() string {
 }
 
 func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
 }
 
 func (FieldDescriptorProto_Label) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[3]
+	return &file_google_protobuf_descriptor_proto_enumTypes[4]
 }
 
 func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber {
@@ -423,11 +487,11 @@ func (x FileOptions_OptimizeMode) String() string {
 }
 
 func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
 }
 
 func (FileOptions_OptimizeMode) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[4]
+	return &file_google_protobuf_descriptor_proto_enumTypes[5]
 }
 
 func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber {
@@ -489,11 +553,11 @@ func (x FieldOptions_CType) String() string {
 }
 
 func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
 }
 
 func (FieldOptions_CType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[5]
+	return &file_google_protobuf_descriptor_proto_enumTypes[6]
 }
 
 func (x FieldOptions_CType) Number() protoreflect.EnumNumber {
@@ -551,11 +615,11 @@ func (x FieldOptions_JSType) String() string {
 }
 
 func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
 }
 
 func (FieldOptions_JSType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[6]
+	return &file_google_protobuf_descriptor_proto_enumTypes[7]
 }
 
 func (x FieldOptions_JSType) Number() protoreflect.EnumNumber {
@@ -611,11 +675,11 @@ func (x FieldOptions_OptionRetention) String() string {
 }
 
 func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
 }
 
 func (FieldOptions_OptionRetention) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[7]
+	return &file_google_protobuf_descriptor_proto_enumTypes[8]
 }
 
 func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber {
@@ -694,11 +758,11 @@ func (x FieldOptions_OptionTargetType) String() string {
 }
 
 func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
 }
 
 func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[8]
+	return &file_google_protobuf_descriptor_proto_enumTypes[9]
 }
 
 func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber {
@@ -756,11 +820,11 @@ func (x MethodOptions_IdempotencyLevel) String() string {
 }
 
 func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
 }
 
 func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[9]
+	return &file_google_protobuf_descriptor_proto_enumTypes[10]
 }
 
 func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber {
@@ -818,11 +882,11 @@ func (x FeatureSet_FieldPresence) String() string {
 }
 
 func (FeatureSet_FieldPresence) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
 }
 
 func (FeatureSet_FieldPresence) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[10]
+	return &file_google_protobuf_descriptor_proto_enumTypes[11]
 }
 
 func (x FeatureSet_FieldPresence) Number() protoreflect.EnumNumber {
@@ -877,11 +941,11 @@ func (x FeatureSet_EnumType) String() string {
 }
 
 func (FeatureSet_EnumType) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
 }
 
 func (FeatureSet_EnumType) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[11]
+	return &file_google_protobuf_descriptor_proto_enumTypes[12]
 }
 
 func (x FeatureSet_EnumType) Number() protoreflect.EnumNumber {
@@ -936,11 +1000,11 @@ func (x FeatureSet_RepeatedFieldEncoding) String() string {
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
 }
 
 func (FeatureSet_RepeatedFieldEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[12]
+	return &file_google_protobuf_descriptor_proto_enumTypes[13]
 }
 
 func (x FeatureSet_RepeatedFieldEncoding) Number() protoreflect.EnumNumber {
@@ -995,11 +1059,11 @@ func (x FeatureSet_Utf8Validation) String() string {
 }
 
 func (FeatureSet_Utf8Validation) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
 }
 
 func (FeatureSet_Utf8Validation) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[13]
+	return &file_google_protobuf_descriptor_proto_enumTypes[14]
 }
 
 func (x FeatureSet_Utf8Validation) Number() protoreflect.EnumNumber {
@@ -1054,11 +1118,11 @@ func (x FeatureSet_MessageEncoding) String() string {
 }
 
 func (FeatureSet_MessageEncoding) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
 }
 
 func (FeatureSet_MessageEncoding) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[14]
+	return &file_google_protobuf_descriptor_proto_enumTypes[15]
 }
 
 func (x FeatureSet_MessageEncoding) Number() protoreflect.EnumNumber {
@@ -1113,11 +1177,11 @@ func (x FeatureSet_JsonFormat) String() string {
 }
 
 func (FeatureSet_JsonFormat) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
 }
 
 func (FeatureSet_JsonFormat) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[15]
+	return &file_google_protobuf_descriptor_proto_enumTypes[16]
 }
 
 func (x FeatureSet_JsonFormat) Number() protoreflect.EnumNumber {
@@ -1172,11 +1236,11 @@ func (x FeatureSet_EnforceNamingStyle) String() string {
 }
 
 func (FeatureSet_EnforceNamingStyle) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
 }
 
 func (FeatureSet_EnforceNamingStyle) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[16]
+	return &file_google_protobuf_descriptor_proto_enumTypes[17]
 }
 
 func (x FeatureSet_EnforceNamingStyle) Number() protoreflect.EnumNumber {
@@ -1198,6 +1262,77 @@ func (FeatureSet_EnforceNamingStyle) EnumDescriptor() ([]byte, []int) {
 	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 6}
 }
 
+type FeatureSet_VisibilityFeature_DefaultSymbolVisibility int32
+
+const (
+	FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 0
+	// Default pre-EDITION_2024, all UNSET visibility are export.
+	FeatureSet_VisibilityFeature_EXPORT_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 1
+	// All top-level symbols default to export, nested default to local.
+	FeatureSet_VisibilityFeature_EXPORT_TOP_LEVEL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 2
+	// All symbols default to local.
+	FeatureSet_VisibilityFeature_LOCAL_ALL FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 3
+	// All symbols local by default. Nested types cannot be exported.
+	// With special case caveat for message { enum {} reserved 1 to max; }
+	// This is the recommended setting for new protos.
+	FeatureSet_VisibilityFeature_STRICT FeatureSet_VisibilityFeature_DefaultSymbolVisibility = 4
+)
+
+// Enum value maps for FeatureSet_VisibilityFeature_DefaultSymbolVisibility.
+var (
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_name = map[int32]string{
+		0: "DEFAULT_SYMBOL_VISIBILITY_UNKNOWN",
+		1: "EXPORT_ALL",
+		2: "EXPORT_TOP_LEVEL",
+		3: "LOCAL_ALL",
+		4: "STRICT",
+	}
+	FeatureSet_VisibilityFeature_DefaultSymbolVisibility_value = map[string]int32{
+		"DEFAULT_SYMBOL_VISIBILITY_UNKNOWN": 0,
+		"EXPORT_ALL":                        1,
+		"EXPORT_TOP_LEVEL":                  2,
+		"LOCAL_ALL":                         3,
+		"STRICT":                            4,
+	}
+)
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Enum() *FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	p := new(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)
+	*p = x
+	return p
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Descriptor() protoreflect.EnumDescriptor {
+	return file_google_protobuf_descriptor_proto_enumTypes[18].Descriptor()
+}
+
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Type() protoreflect.EnumType {
+	return &file_google_protobuf_descriptor_proto_enumTypes[18]
+}
+
+func (x FeatureSet_VisibilityFeature_DefaultSymbolVisibility) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_VisibilityFeature_DefaultSymbolVisibility) UnmarshalJSON(b []byte) error {
+	num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+	if err != nil {
+		return err
+	}
+	*x = FeatureSet_VisibilityFeature_DefaultSymbolVisibility(num)
+	return nil
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature_DefaultSymbolVisibility.Descriptor instead.
+func (FeatureSet_VisibilityFeature_DefaultSymbolVisibility) EnumDescriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0, 0}
+}
+
 // Represents the identified object's effect on the element in the original
 // .proto file.
 type GeneratedCodeInfo_Annotation_Semantic int32
@@ -1236,11 +1371,11 @@ func (x GeneratedCodeInfo_Annotation_Semantic) String() string {
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor {
-	return file_google_protobuf_descriptor_proto_enumTypes[17].Descriptor()
+	return file_google_protobuf_descriptor_proto_enumTypes[19].Descriptor()
 }
 
 func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType {
-	return &file_google_protobuf_descriptor_proto_enumTypes[17]
+	return &file_google_protobuf_descriptor_proto_enumTypes[19]
 }
 
 func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber {
@@ -1321,6 +1456,9 @@ type FileDescriptorProto struct {
 	// Indexes of the weak imported files in the dependency list.
 	// For Google-internal migration only. Do not use.
 	WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+	// Names of files imported by this file purely for the purpose of providing
+	// option extensions. These are excluded from the dependency list above.
+	OptionDependency []string `protobuf:"bytes,15,rep,name=option_dependency,json=optionDependency" json:"option_dependency,omitempty"`
 	// All top-level definitions in this file.
 	MessageType []*DescriptorProto        `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
 	EnumType    []*EnumDescriptorProto    `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
@@ -1414,6 +1552,13 @@ func (x *FileDescriptorProto) GetWeakDependency() []int32 {
 	return nil
 }
 
+func (x *FileDescriptorProto) GetOptionDependency() []string {
+	if x != nil {
+		return x.OptionDependency
+	}
+	return nil
+}
+
 func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto {
 	if x != nil {
 		return x.MessageType
@@ -1484,7 +1629,9 @@ type DescriptorProto struct {
 	ReservedRange  []*DescriptorProto_ReservedRange  `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved field names, which may not be used by fields in the same message.
 	// A given name may only be reserved once.
-	ReservedName  []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,11,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1589,6 +1736,13 @@ func (x *DescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *DescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 type ExtensionRangeOptions struct {
 	state protoimpl.MessageState `protogen:"open.v1"`
 	// The parser stores options it doesn't recognize here. See above.
@@ -1901,7 +2055,9 @@ type EnumDescriptorProto struct {
 	ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
 	// Reserved enum value names, which may not be reused. A given name may only
 	// be reserved once.
-	ReservedName  []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+	// Support for `export` and `local` keywords on enums.
+	Visibility    *SymbolVisibility `protobuf:"varint,6,opt,name=visibility,enum=google.protobuf.SymbolVisibility" json:"visibility,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }
@@ -1971,6 +2127,13 @@ func (x *EnumDescriptorProto) GetReservedName() []string {
 	return nil
 }
 
+func (x *EnumDescriptorProto) GetVisibility() SymbolVisibility {
+	if x != nil && x.Visibility != nil {
+		return *x.Visibility
+	}
+	return SymbolVisibility_VISIBILITY_UNSET
+}
+
 // Describes a value within an enum.
 type EnumValueDescriptorProto struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
@@ -2710,7 +2873,10 @@ type FieldOptions struct {
 	// for accessors, or it will be completely ignored; in the very least, this
 	// is a formalization for deprecating fields.
 	Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+	// DEPRECATED. DO NOT USE!
 	// For Google-internal migration only. Do not use.
+	//
+	// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 	Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
 	// Indicate that the field value should not be printed out when using debug
 	// formats, e.g. when the field contains sensitive credentials.
@@ -2814,6 +2980,7 @@ func (x *FieldOptions) GetDeprecated() bool {
 	return Default_FieldOptions_Deprecated
 }
 
+// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 func (x *FieldOptions) GetWeak() bool {
 	if x != nil && x.Weak != nil {
 		return *x.Weak
@@ -3392,17 +3559,18 @@ func (x *UninterpretedOption) GetAggregateValue() string {
 // be designed and implemented to handle this, hopefully before we ever hit a
 // conflict here.
 type FeatureSet struct {
-	state                 protoimpl.MessageState            `protogen:"open.v1"`
-	FieldPresence         *FeatureSet_FieldPresence         `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
-	EnumType              *FeatureSet_EnumType              `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
-	RepeatedFieldEncoding *FeatureSet_RepeatedFieldEncoding `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
-	Utf8Validation        *FeatureSet_Utf8Validation        `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
-	MessageEncoding       *FeatureSet_MessageEncoding       `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
-	JsonFormat            *FeatureSet_JsonFormat            `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
-	EnforceNamingStyle    *FeatureSet_EnforceNamingStyle    `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
-	extensionFields       protoimpl.ExtensionFields
-	unknownFields         protoimpl.UnknownFields
-	sizeCache             protoimpl.SizeCache
+	state                   protoimpl.MessageState                                `protogen:"open.v1"`
+	FieldPresence           *FeatureSet_FieldPresence                             `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
+	EnumType                *FeatureSet_EnumType                                  `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
+	RepeatedFieldEncoding   *FeatureSet_RepeatedFieldEncoding                     `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
+	Utf8Validation          *FeatureSet_Utf8Validation                            `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
+	MessageEncoding         *FeatureSet_MessageEncoding                           `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
+	JsonFormat              *FeatureSet_JsonFormat                                `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
+	EnforceNamingStyle      *FeatureSet_EnforceNamingStyle                        `protobuf:"varint,7,opt,name=enforce_naming_style,json=enforceNamingStyle,enum=google.protobuf.FeatureSet_EnforceNamingStyle" json:"enforce_naming_style,omitempty"`
+	DefaultSymbolVisibility *FeatureSet_VisibilityFeature_DefaultSymbolVisibility `protobuf:"varint,8,opt,name=default_symbol_visibility,json=defaultSymbolVisibility,enum=google.protobuf.FeatureSet_VisibilityFeature_DefaultSymbolVisibility" json:"default_symbol_visibility,omitempty"`
+	extensionFields         protoimpl.ExtensionFields
+	unknownFields           protoimpl.UnknownFields
+	sizeCache               protoimpl.SizeCache
 }
 
 func (x *FeatureSet) Reset() {
@@ -3484,6 +3652,13 @@ func (x *FeatureSet) GetEnforceNamingStyle() FeatureSet_EnforceNamingStyle {
 	return FeatureSet_ENFORCE_NAMING_STYLE_UNKNOWN
 }
 
+func (x *FeatureSet) GetDefaultSymbolVisibility() FeatureSet_VisibilityFeature_DefaultSymbolVisibility {
+	if x != nil && x.DefaultSymbolVisibility != nil {
+		return *x.DefaultSymbolVisibility
+	}
+	return FeatureSet_VisibilityFeature_DEFAULT_SYMBOL_VISIBILITY_UNKNOWN
+}
+
 // A compiled specification for the defaults of a set of features.  These
 // messages are generated from FeatureSet extensions and can be used to seed
 // feature resolution. The resolution with this object becomes a simple search
@@ -4144,6 +4319,42 @@ func (x *UninterpretedOption_NamePart) GetIsExtension() bool {
 	return false
 }
 
+type FeatureSet_VisibilityFeature struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *FeatureSet_VisibilityFeature) Reset() {
+	*x = FeatureSet_VisibilityFeature{}
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *FeatureSet_VisibilityFeature) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSet_VisibilityFeature) ProtoMessage() {}
+
+func (x *FeatureSet_VisibilityFeature) ProtoReflect() protoreflect.Message {
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSet_VisibilityFeature.ProtoReflect.Descriptor instead.
+func (*FeatureSet_VisibilityFeature) Descriptor() ([]byte, []int) {
+	return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+}
+
 // A map from every known edition with a unique set of defaults to its
 // defaults. Not all editions may be contained here.  For a given edition,
 // the defaults at the closest matching edition ordered at or before it should
@@ -4161,7 +4372,7 @@ type FeatureSetDefaults_FeatureSetEditionDefault struct {
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() {
 	*x = FeatureSetDefaults_FeatureSetEditionDefault{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4173,7 +4384,7 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string {
 func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {}
 
 func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4309,7 +4520,7 @@ type SourceCodeInfo_Location struct {
 
 func (x *SourceCodeInfo_Location) Reset() {
 	*x = SourceCodeInfo_Location{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4321,7 +4532,7 @@ func (x *SourceCodeInfo_Location) String() string {
 func (*SourceCodeInfo_Location) ProtoMessage() {}
 
 func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4393,7 +4604,7 @@ type GeneratedCodeInfo_Annotation struct {
 
 func (x *GeneratedCodeInfo_Annotation) Reset() {
 	*x = GeneratedCodeInfo_Annotation{}
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -4405,7 +4616,7 @@ func (x *GeneratedCodeInfo_Annotation) String() string {
 func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
 
 func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
-	mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
+	mi := &file_google_protobuf_descriptor_proto_msgTypes[33]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -4462,7 +4673,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\n" +
 	" google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"[\n" +
 	"\x11FileDescriptorSet\x128\n" +
-	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\x98\x05\n" +
+	"\x04file\x18\x01 \x03(\v2$.google.protobuf.FileDescriptorProtoR\x04file*\f\b\x80\xec\xca\xff\x01\x10\x81\xec\xca\xff\x01\"\xc5\x05\n" +
 	"\x13FileDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
 	"\apackage\x18\x02 \x01(\tR\apackage\x12\x1e\n" +
@@ -4471,7 +4682,8 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"dependency\x12+\n" +
 	"\x11public_dependency\x18\n" +
 	" \x03(\x05R\x10publicDependency\x12'\n" +
-	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12C\n" +
+	"\x0fweak_dependency\x18\v \x03(\x05R\x0eweakDependency\x12+\n" +
+	"\x11option_dependency\x18\x0f \x03(\tR\x10optionDependency\x12C\n" +
 	"\fmessage_type\x18\x04 \x03(\v2 .google.protobuf.DescriptorProtoR\vmessageType\x12A\n" +
 	"\tenum_type\x18\x05 \x03(\v2$.google.protobuf.EnumDescriptorProtoR\benumType\x12A\n" +
 	"\aservice\x18\x06 \x03(\v2'.google.protobuf.ServiceDescriptorProtoR\aservice\x12C\n" +
@@ -4479,7 +4691,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\b \x01(\v2\x1c.google.protobuf.FileOptionsR\aoptions\x12I\n" +
 	"\x10source_code_info\x18\t \x01(\v2\x1f.google.protobuf.SourceCodeInfoR\x0esourceCodeInfo\x12\x16\n" +
 	"\x06syntax\x18\f \x01(\tR\x06syntax\x122\n" +
-	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xb9\x06\n" +
+	"\aedition\x18\x0e \x01(\x0e2\x18.google.protobuf.EditionR\aedition\"\xfc\x06\n" +
 	"\x0fDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12;\n" +
 	"\x05field\x18\x02 \x03(\v2%.google.protobuf.FieldDescriptorProtoR\x05field\x12C\n" +
@@ -4493,7 +4705,10 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\aoptions\x18\a \x01(\v2\x1f.google.protobuf.MessageOptionsR\aoptions\x12U\n" +
 	"\x0ereserved_range\x18\t \x03(\v2..google.protobuf.DescriptorProto.ReservedRangeR\rreservedRange\x12#\n" +
 	"\rreserved_name\x18\n" +
-	" \x03(\tR\freservedName\x1az\n" +
+	" \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\v \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1az\n" +
 	"\x0eExtensionRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\x12@\n" +
@@ -4562,13 +4777,16 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0eLABEL_REQUIRED\x10\x02\"c\n" +
 	"\x14OneofDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x127\n" +
-	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xe3\x02\n" +
+	"\aoptions\x18\x02 \x01(\v2\x1d.google.protobuf.OneofOptionsR\aoptions\"\xa6\x03\n" +
 	"\x13EnumDescriptorProto\x12\x12\n" +
 	"\x04name\x18\x01 \x01(\tR\x04name\x12?\n" +
 	"\x05value\x18\x02 \x03(\v2).google.protobuf.EnumValueDescriptorProtoR\x05value\x126\n" +
 	"\aoptions\x18\x03 \x01(\v2\x1c.google.protobuf.EnumOptionsR\aoptions\x12]\n" +
 	"\x0ereserved_range\x18\x04 \x03(\v26.google.protobuf.EnumDescriptorProto.EnumReservedRangeR\rreservedRange\x12#\n" +
-	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x1a;\n" +
+	"\rreserved_name\x18\x05 \x03(\tR\freservedName\x12A\n" +
+	"\n" +
+	"visibility\x18\x06 \x01(\x0e2!.google.protobuf.SymbolVisibilityR\n" +
+	"visibility\x1a;\n" +
 	"\x11EnumReservedRange\x12\x14\n" +
 	"\x05start\x18\x01 \x01(\x05R\x05start\x12\x10\n" +
 	"\x03end\x18\x02 \x01(\x05R\x03end\"\x83\x01\n" +
@@ -4629,7 +4847,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"&deprecated_legacy_json_field_conflicts\x18\v \x01(\bB\x02\x18\x01R\"deprecatedLegacyJsonFieldConflicts\x127\n" +
 	"\bfeatures\x18\f \x01(\v2\x1b.google.protobuf.FeatureSetR\bfeatures\x12X\n" +
 	"\x14uninterpreted_option\x18\xe7\a \x03(\v2$.google.protobuf.UninterpretedOptionR\x13uninterpretedOption*\t\b\xe8\a\x10\x80\x80\x80\x80\x02J\x04\b\x04\x10\x05J\x04\b\x05\x10\x06J\x04\b\x06\x10\aJ\x04\b\b\x10\tJ\x04\b\t\x10\n" +
-	"\"\x9d\r\n" +
+	"\"\xa1\r\n" +
 	"\fFieldOptions\x12A\n" +
 	"\x05ctype\x18\x01 \x01(\x0e2#.google.protobuf.FieldOptions.CType:\x06STRINGR\x05ctype\x12\x16\n" +
 	"\x06packed\x18\x02 \x01(\bR\x06packed\x12G\n" +
@@ -4638,9 +4856,9 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0funverified_lazy\x18\x0f \x01(\b:\x05falseR\x0eunverifiedLazy\x12%\n" +
 	"\n" +
 	"deprecated\x18\x03 \x01(\b:\x05falseR\n" +
-	"deprecated\x12\x19\n" +
+	"deprecated\x12\x1d\n" +
 	"\x04weak\x18\n" +
-	" \x01(\b:\x05falseR\x04weak\x12(\n" +
+	" \x01(\b:\x05falseB\x02\x18\x01R\x04weak\x12(\n" +
 	"\fdebug_redact\x18\x10 \x01(\b:\x05falseR\vdebugRedact\x12K\n" +
 	"\tretention\x18\x11 \x01(\x0e2-.google.protobuf.FieldOptions.OptionRetentionR\tretention\x12H\n" +
 	"\atargets\x18\x13 \x03(\x0e2..google.protobuf.FieldOptions.OptionTargetTypeR\atargets\x12W\n" +
@@ -4728,7 +4946,7 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x0faggregate_value\x18\b \x01(\tR\x0eaggregateValue\x1aJ\n" +
 	"\bNamePart\x12\x1b\n" +
 	"\tname_part\x18\x01 \x02(\tR\bnamePart\x12!\n" +
-	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\xae\f\n" +
+	"\fis_extension\x18\x02 \x02(\bR\visExtension\"\x8e\x0f\n" +
 	"\n" +
 	"FeatureSet\x12\x91\x01\n" +
 	"\x0efield_presence\x18\x01 \x01(\x0e2).google.protobuf.FeatureSet.FieldPresenceB?\x88\x01\x01\x98\x01\x04\x98\x01\x01\xa2\x01\r\x12\bEXPLICIT\x18\x84\a\xa2\x01\r\x12\bIMPLICIT\x18\xe7\a\xa2\x01\r\x12\bEXPLICIT\x18\xe8\a\xb2\x01\x03\b\xe8\aR\rfieldPresence\x12l\n" +
@@ -4739,7 +4957,18 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\vjson_format\x18\x06 \x01(\x0e2&.google.protobuf.FeatureSet.JsonFormatB9\x88\x01\x01\x98\x01\x03\x98\x01\x06\x98\x01\x01\xa2\x01\x17\x12\x12LEGACY_BEST_EFFORT\x18\x84\a\xa2\x01\n" +
 	"\x12\x05ALLOW\x18\xe7\a\xb2\x01\x03\b\xe8\aR\n" +
 	"jsonFormat\x12\xab\x01\n" +
-	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\"\\\n" +
+	"\x14enforce_naming_style\x18\a \x01(\x0e2..google.protobuf.FeatureSet.EnforceNamingStyleBI\x88\x01\x02\x98\x01\x01\x98\x01\x02\x98\x01\x03\x98\x01\x04\x98\x01\x05\x98\x01\x06\x98\x01\a\x98\x01\b\x98\x01\t\xa2\x01\x11\x12\fSTYLE_LEGACY\x18\x84\a\xa2\x01\x0e\x12\tSTYLE2024\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x12enforceNamingStyle\x12\xb9\x01\n" +
+	"\x19default_symbol_visibility\x18\b \x01(\x0e2E.google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibilityB6\x88\x01\x02\x98\x01\x01\xa2\x01\x0f\x12\n" +
+	"EXPORT_ALL\x18\x84\a\xa2\x01\x15\x12\x10EXPORT_TOP_LEVEL\x18\xe9\a\xb2\x01\x03\b\xe9\aR\x17defaultSymbolVisibility\x1a\xa1\x01\n" +
+	"\x11VisibilityFeature\"\x81\x01\n" +
+	"\x17DefaultSymbolVisibility\x12%\n" +
+	"!DEFAULT_SYMBOL_VISIBILITY_UNKNOWN\x10\x00\x12\x0e\n" +
+	"\n" +
+	"EXPORT_ALL\x10\x01\x12\x14\n" +
+	"\x10EXPORT_TOP_LEVEL\x10\x02\x12\r\n" +
+	"\tLOCAL_ALL\x10\x03\x12\n" +
+	"\n" +
+	"\x06STRICT\x10\x04J\b\b\x01\x10\x80\x80\x80\x80\x02\"\\\n" +
 	"\rFieldPresence\x12\x1a\n" +
 	"\x16FIELD_PRESENCE_UNKNOWN\x10\x00\x12\f\n" +
 	"\bEXPLICIT\x10\x01\x12\f\n" +
@@ -4817,7 +5046,11 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" +
 	"\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99998_TEST_ONLY\x10\x9e\x8d\x06\x12\x1d\n" +
 	"\x17EDITION_99999_TEST_ONLY\x10\x9f\x8d\x06\x12\x13\n" +
-	"\vEDITION_MAX\x10\xff\xff\xff\xff\aB~\n" +
+	"\vEDITION_MAX\x10\xff\xff\xff\xff\a*U\n" +
+	"\x10SymbolVisibility\x12\x14\n" +
+	"\x10VISIBILITY_UNSET\x10\x00\x12\x14\n" +
+	"\x10VISIBILITY_LOCAL\x10\x01\x12\x15\n" +
+	"\x11VISIBILITY_EXPORT\x10\x02B~\n" +
 	"\x13com.google.protobufB\x10DescriptorProtosH\x01Z-google.golang.org/protobuf/types/descriptorpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection"
 
 var (
@@ -4832,145 +5065,151 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte {
 	return file_google_protobuf_descriptor_proto_rawDescData
 }
 
-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 18)
-var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 20)
+var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
 var file_google_protobuf_descriptor_proto_goTypes = []any{
-	(Edition)(0), // 0: google.protobuf.Edition
-	(ExtensionRangeOptions_VerificationState)(0),        // 1: google.protobuf.ExtensionRangeOptions.VerificationState
-	(FieldDescriptorProto_Type)(0),                      // 2: google.protobuf.FieldDescriptorProto.Type
-	(FieldDescriptorProto_Label)(0),                     // 3: google.protobuf.FieldDescriptorProto.Label
-	(FileOptions_OptimizeMode)(0),                       // 4: google.protobuf.FileOptions.OptimizeMode
-	(FieldOptions_CType)(0),                             // 5: google.protobuf.FieldOptions.CType
-	(FieldOptions_JSType)(0),                            // 6: google.protobuf.FieldOptions.JSType
-	(FieldOptions_OptionRetention)(0),                   // 7: google.protobuf.FieldOptions.OptionRetention
-	(FieldOptions_OptionTargetType)(0),                  // 8: google.protobuf.FieldOptions.OptionTargetType
-	(MethodOptions_IdempotencyLevel)(0),                 // 9: google.protobuf.MethodOptions.IdempotencyLevel
-	(FeatureSet_FieldPresence)(0),                       // 10: google.protobuf.FeatureSet.FieldPresence
-	(FeatureSet_EnumType)(0),                            // 11: google.protobuf.FeatureSet.EnumType
-	(FeatureSet_RepeatedFieldEncoding)(0),               // 12: google.protobuf.FeatureSet.RepeatedFieldEncoding
-	(FeatureSet_Utf8Validation)(0),                      // 13: google.protobuf.FeatureSet.Utf8Validation
-	(FeatureSet_MessageEncoding)(0),                     // 14: google.protobuf.FeatureSet.MessageEncoding
-	(FeatureSet_JsonFormat)(0),                          // 15: google.protobuf.FeatureSet.JsonFormat
-	(FeatureSet_EnforceNamingStyle)(0),                  // 16: google.protobuf.FeatureSet.EnforceNamingStyle
-	(GeneratedCodeInfo_Annotation_Semantic)(0),          // 17: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	(*FileDescriptorSet)(nil),                           // 18: google.protobuf.FileDescriptorSet
-	(*FileDescriptorProto)(nil),                         // 19: google.protobuf.FileDescriptorProto
-	(*DescriptorProto)(nil),                             // 20: google.protobuf.DescriptorProto
-	(*ExtensionRangeOptions)(nil),                       // 21: google.protobuf.ExtensionRangeOptions
-	(*FieldDescriptorProto)(nil),                        // 22: google.protobuf.FieldDescriptorProto
-	(*OneofDescriptorProto)(nil),                        // 23: google.protobuf.OneofDescriptorProto
-	(*EnumDescriptorProto)(nil),                         // 24: google.protobuf.EnumDescriptorProto
-	(*EnumValueDescriptorProto)(nil),                    // 25: google.protobuf.EnumValueDescriptorProto
-	(*ServiceDescriptorProto)(nil),                      // 26: google.protobuf.ServiceDescriptorProto
-	(*MethodDescriptorProto)(nil),                       // 27: google.protobuf.MethodDescriptorProto
-	(*FileOptions)(nil),                                 // 28: google.protobuf.FileOptions
-	(*MessageOptions)(nil),                              // 29: google.protobuf.MessageOptions
-	(*FieldOptions)(nil),                                // 30: google.protobuf.FieldOptions
-	(*OneofOptions)(nil),                                // 31: google.protobuf.OneofOptions
-	(*EnumOptions)(nil),                                 // 32: google.protobuf.EnumOptions
-	(*EnumValueOptions)(nil),                            // 33: google.protobuf.EnumValueOptions
-	(*ServiceOptions)(nil),                              // 34: google.protobuf.ServiceOptions
-	(*MethodOptions)(nil),                               // 35: google.protobuf.MethodOptions
-	(*UninterpretedOption)(nil),                         // 36: google.protobuf.UninterpretedOption
-	(*FeatureSet)(nil),                                  // 37: google.protobuf.FeatureSet
-	(*FeatureSetDefaults)(nil),                          // 38: google.protobuf.FeatureSetDefaults
-	(*SourceCodeInfo)(nil),                              // 39: google.protobuf.SourceCodeInfo
-	(*GeneratedCodeInfo)(nil),                           // 40: google.protobuf.GeneratedCodeInfo
-	(*DescriptorProto_ExtensionRange)(nil),              // 41: google.protobuf.DescriptorProto.ExtensionRange
-	(*DescriptorProto_ReservedRange)(nil),               // 42: google.protobuf.DescriptorProto.ReservedRange
-	(*ExtensionRangeOptions_Declaration)(nil),           // 43: google.protobuf.ExtensionRangeOptions.Declaration
-	(*EnumDescriptorProto_EnumReservedRange)(nil),       // 44: google.protobuf.EnumDescriptorProto.EnumReservedRange
-	(*FieldOptions_EditionDefault)(nil),                 // 45: google.protobuf.FieldOptions.EditionDefault
-	(*FieldOptions_FeatureSupport)(nil),                 // 46: google.protobuf.FieldOptions.FeatureSupport
-	(*UninterpretedOption_NamePart)(nil),                // 47: google.protobuf.UninterpretedOption.NamePart
-	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 48: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	(*SourceCodeInfo_Location)(nil),                     // 49: google.protobuf.SourceCodeInfo.Location
-	(*GeneratedCodeInfo_Annotation)(nil),                // 50: google.protobuf.GeneratedCodeInfo.Annotation
+	(Edition)(0),          // 0: google.protobuf.Edition
+	(SymbolVisibility)(0), // 1: google.protobuf.SymbolVisibility
+	(ExtensionRangeOptions_VerificationState)(0),              // 2: google.protobuf.ExtensionRangeOptions.VerificationState
+	(FieldDescriptorProto_Type)(0),                            // 3: google.protobuf.FieldDescriptorProto.Type
+	(FieldDescriptorProto_Label)(0),                           // 4: google.protobuf.FieldDescriptorProto.Label
+	(FileOptions_OptimizeMode)(0),                             // 5: google.protobuf.FileOptions.OptimizeMode
+	(FieldOptions_CType)(0),                                   // 6: google.protobuf.FieldOptions.CType
+	(FieldOptions_JSType)(0),                                  // 7: google.protobuf.FieldOptions.JSType
+	(FieldOptions_OptionRetention)(0),                         // 8: google.protobuf.FieldOptions.OptionRetention
+	(FieldOptions_OptionTargetType)(0),                        // 9: google.protobuf.FieldOptions.OptionTargetType
+	(MethodOptions_IdempotencyLevel)(0),                       // 10: google.protobuf.MethodOptions.IdempotencyLevel
+	(FeatureSet_FieldPresence)(0),                             // 11: google.protobuf.FeatureSet.FieldPresence
+	(FeatureSet_EnumType)(0),                                  // 12: google.protobuf.FeatureSet.EnumType
+	(FeatureSet_RepeatedFieldEncoding)(0),                     // 13: google.protobuf.FeatureSet.RepeatedFieldEncoding
+	(FeatureSet_Utf8Validation)(0),                            // 14: google.protobuf.FeatureSet.Utf8Validation
+	(FeatureSet_MessageEncoding)(0),                           // 15: google.protobuf.FeatureSet.MessageEncoding
+	(FeatureSet_JsonFormat)(0),                                // 16: google.protobuf.FeatureSet.JsonFormat
+	(FeatureSet_EnforceNamingStyle)(0),                        // 17: google.protobuf.FeatureSet.EnforceNamingStyle
+	(FeatureSet_VisibilityFeature_DefaultSymbolVisibility)(0), // 18: google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	(GeneratedCodeInfo_Annotation_Semantic)(0),                // 19: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	(*FileDescriptorSet)(nil),                                 // 20: google.protobuf.FileDescriptorSet
+	(*FileDescriptorProto)(nil),                               // 21: google.protobuf.FileDescriptorProto
+	(*DescriptorProto)(nil),                                   // 22: google.protobuf.DescriptorProto
+	(*ExtensionRangeOptions)(nil),                             // 23: google.protobuf.ExtensionRangeOptions
+	(*FieldDescriptorProto)(nil),                              // 24: google.protobuf.FieldDescriptorProto
+	(*OneofDescriptorProto)(nil),                              // 25: google.protobuf.OneofDescriptorProto
+	(*EnumDescriptorProto)(nil),                               // 26: google.protobuf.EnumDescriptorProto
+	(*EnumValueDescriptorProto)(nil),                          // 27: google.protobuf.EnumValueDescriptorProto
+	(*ServiceDescriptorProto)(nil),                            // 28: google.protobuf.ServiceDescriptorProto
+	(*MethodDescriptorProto)(nil),                             // 29: google.protobuf.MethodDescriptorProto
+	(*FileOptions)(nil),                                       // 30: google.protobuf.FileOptions
+	(*MessageOptions)(nil),                                    // 31: google.protobuf.MessageOptions
+	(*FieldOptions)(nil),                                      // 32: google.protobuf.FieldOptions
+	(*OneofOptions)(nil),                                      // 33: google.protobuf.OneofOptions
+	(*EnumOptions)(nil),                                       // 34: google.protobuf.EnumOptions
+	(*EnumValueOptions)(nil),                                  // 35: google.protobuf.EnumValueOptions
+	(*ServiceOptions)(nil),                                    // 36: google.protobuf.ServiceOptions
+	(*MethodOptions)(nil),                                     // 37: google.protobuf.MethodOptions
+	(*UninterpretedOption)(nil),                               // 38: google.protobuf.UninterpretedOption
+	(*FeatureSet)(nil),                                        // 39: google.protobuf.FeatureSet
+	(*FeatureSetDefaults)(nil),                                // 40: google.protobuf.FeatureSetDefaults
+	(*SourceCodeInfo)(nil),                                    // 41: google.protobuf.SourceCodeInfo
+	(*GeneratedCodeInfo)(nil),                                 // 42: google.protobuf.GeneratedCodeInfo
+	(*DescriptorProto_ExtensionRange)(nil),                    // 43: google.protobuf.DescriptorProto.ExtensionRange
+	(*DescriptorProto_ReservedRange)(nil),                     // 44: google.protobuf.DescriptorProto.ReservedRange
+	(*ExtensionRangeOptions_Declaration)(nil),                 // 45: google.protobuf.ExtensionRangeOptions.Declaration
+	(*EnumDescriptorProto_EnumReservedRange)(nil),             // 46: google.protobuf.EnumDescriptorProto.EnumReservedRange
+	(*FieldOptions_EditionDefault)(nil),                       // 47: google.protobuf.FieldOptions.EditionDefault
+	(*FieldOptions_FeatureSupport)(nil),                       // 48: google.protobuf.FieldOptions.FeatureSupport
+	(*UninterpretedOption_NamePart)(nil),                      // 49: google.protobuf.UninterpretedOption.NamePart
+	(*FeatureSet_VisibilityFeature)(nil),                      // 50: google.protobuf.FeatureSet.VisibilityFeature
+	(*FeatureSetDefaults_FeatureSetEditionDefault)(nil),       // 51: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	(*SourceCodeInfo_Location)(nil),                           // 52: google.protobuf.SourceCodeInfo.Location
+	(*GeneratedCodeInfo_Annotation)(nil),                      // 53: google.protobuf.GeneratedCodeInfo.Annotation
 }
 var file_google_protobuf_descriptor_proto_depIdxs = []int32{
-	19, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
-	20, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
-	24, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	26, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
-	22, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	28, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
-	39, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
+	21, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
+	22, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
+	26, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	28, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
+	24, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	30, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
+	41, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
 	0,  // 7: google.protobuf.FileDescriptorProto.edition:type_name -> google.protobuf.Edition
-	22, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
-	22, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
-	20, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
-	24, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
-	41, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
-	23, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
-	29, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
-	42, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
-	36, // 16: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	43, // 17: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
-	37, // 18: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
-	1,  // 19: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
-	3,  // 20: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
-	2,  // 21: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
-	30, // 22: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
-	31, // 23: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
-	25, // 24: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
-	32, // 25: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
-	44, // 26: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
-	33, // 27: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
-	27, // 28: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
-	34, // 29: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
-	35, // 30: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
-	4,  // 31: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
-	37, // 32: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 33: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 34: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 35: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	5,  // 36: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
-	6,  // 37: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
-	7,  // 38: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
-	8,  // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
-	45, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
-	37, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
-	46, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
-	36, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	37, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	9,  // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
-	37, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
-	36, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
-	47, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
-	10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
-	11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
-	12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
-	13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
-	14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
-	15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
-	16, // 63: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
-	48, // 64: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
-	0,  // 65: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
-	0,  // 66: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
-	49, // 67: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
-	50, // 68: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
-	21, // 69: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
-	0,  // 70: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
-	0,  // 71: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
-	0,  // 72: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
-	0,  // 73: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
-	0,  // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
-	37, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
-	37, // 76: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
-	17, // 77: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
-	78, // [78:78] is the sub-list for method output_type
-	78, // [78:78] is the sub-list for method input_type
-	78, // [78:78] is the sub-list for extension type_name
-	78, // [78:78] is the sub-list for extension extendee
-	0,  // [0:78] is the sub-list for field type_name
+	24, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
+	24, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+	22, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
+	26, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+	43, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
+	25, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
+	31, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
+	44, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
+	1,  // 16: google.protobuf.DescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	38, // 17: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	45, // 18: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
+	39, // 19: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
+	2,  // 20: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
+	4,  // 21: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
+	3,  // 22: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
+	32, // 23: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
+	33, // 24: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
+	27, // 25: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
+	34, // 26: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
+	46, // 27: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
+	1,  // 28: google.protobuf.EnumDescriptorProto.visibility:type_name -> google.protobuf.SymbolVisibility
+	35, // 29: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
+	29, // 30: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
+	36, // 31: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
+	37, // 32: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
+	5,  // 33: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
+	39, // 34: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 35: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 36: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 37: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	6,  // 38: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
+	7,  // 39: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
+	8,  // 40: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
+	9,  // 41: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
+	47, // 42: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
+	39, // 43: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 44: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 45: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 46: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 47: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 48: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 49: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 50: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
+	48, // 51: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+	38, // 52: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	39, // 53: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 54: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	10, // 55: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
+	39, // 56: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
+	38, // 57: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+	49, // 58: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
+	11, // 59: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
+	12, // 60: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
+	13, // 61: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
+	14, // 62: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
+	15, // 63: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
+	16, // 64: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
+	17, // 65: google.protobuf.FeatureSet.enforce_naming_style:type_name -> google.protobuf.FeatureSet.EnforceNamingStyle
+	18, // 66: google.protobuf.FeatureSet.default_symbol_visibility:type_name -> google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility
+	51, // 67: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+	0,  // 68: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
+	0,  // 69: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
+	52, // 70: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
+	53, // 71: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
+	23, // 72: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
+	0,  // 73: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
+	0,  // 74: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
+	0,  // 75: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
+	0,  // 76: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
+	0,  // 77: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
+	39, // 78: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
+	39, // 79: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
+	19, // 80: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+	81, // [81:81] is the sub-list for method output_type
+	81, // [81:81] is the sub-list for method input_type
+	81, // [81:81] is the sub-list for extension type_name
+	81, // [81:81] is the sub-list for extension extendee
+	0,  // [0:81] is the sub-list for field type_name
 }
 
 func init() { file_google_protobuf_descriptor_proto_init() }
@@ -4983,8 +5222,8 @@ func file_google_protobuf_descriptor_proto_init() {
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_protobuf_descriptor_proto_rawDesc), len(file_google_protobuf_descriptor_proto_rawDesc)),
-			NumEnums:      18,
-			NumMessages:   33,
+			NumEnums:      20,
+			NumMessages:   34,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/public-api/vendor/gopkg.in/ini.v1/.editorconfig b/public-api/vendor/gopkg.in/ini.v1/.editorconfig
deleted file mode 100644
index 4a2d9180..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# http://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*_test.go]
-trim_trailing_whitespace = false
diff --git a/public-api/vendor/gopkg.in/ini.v1/.gitignore b/public-api/vendor/gopkg.in/ini.v1/.gitignore
deleted file mode 100644
index 588388bd..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-testdata/conf_out.ini
-ini.sublime-project
-ini.sublime-workspace
-testdata/conf_reflect.ini
-.idea
-/.vscode
-.DS_Store
diff --git a/public-api/vendor/gopkg.in/ini.v1/.golangci.yml b/public-api/vendor/gopkg.in/ini.v1/.golangci.yml
deleted file mode 100644
index 631e3692..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/.golangci.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-linters-settings:
-  staticcheck:
-    checks: [
-      "all",
-      "-SA1019" # There are valid use cases of strings.Title
-    ]
-  nakedret:
-    max-func-lines: 0 # Disallow any unnamed return statement
-
-linters:
-  enable:
-    - deadcode
-    - errcheck
-    - gosimple
-    - govet
-    - ineffassign
-    - staticcheck
-    - structcheck
-    - typecheck
-    - unused
-    - varcheck
-    - nakedret
-    - gofmt
-    - rowserrcheck
-    - unconvert
-    - goimports
-    - unparam
diff --git a/public-api/vendor/gopkg.in/ini.v1/LICENSE b/public-api/vendor/gopkg.in/ini.v1/LICENSE
deleted file mode 100644
index d361bbcd..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the Work and such
-Derivative Works in Source or Object form.
-
-3. Grant of Patent License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable (except as stated in this section) patent license to make, have
-made, use, offer to sell, sell, import, and otherwise transfer the Work, where
-such license applies only to those patent claims licensable by such Contributor
-that are necessarily infringed by their Contribution(s) alone or by combination
-of their Contribution(s) with the Work to which such Contribution(s) was
-submitted. If You institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work or a
-Contribution incorporated within the Work constitutes direct or contributory
-patent infringement, then any patent licenses granted to You under this License
-for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.
-
-You may reproduce and distribute copies of the Work or Derivative Works thereof
-in any medium, with or without modifications, and in Source or Object form,
-provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of
-this License; and
-You must cause any modified files to carry prominent notices stating that You
-changed the files; and
-You must retain, in the Source form of any Derivative Works that You distribute,
-all copyright, patent, trademark, and attribution notices from the Source form
-of the Work, excluding those notices that do not pertain to any part of the
-Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any
-Derivative Works that You distribute must include a readable copy of the
-attribution notices contained within such NOTICE file, excluding those notices
-that do not pertain to any part of the Derivative Works, in at least one of the
-following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions.
-
-Unless You explicitly state otherwise, any Contribution intentionally submitted
-for inclusion in the Work by You to the Licensor shall be under the terms and
-conditions of this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify the terms of
-any separate license agreement you may have executed with Licensor regarding
-such Contributions.
-
-6. Trademarks.
-
-This License does not grant permission to use the trade names, trademarks,
-service marks, or product names of the Licensor, except as required for
-reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty.
-
-Unless required by applicable law or agreed to in writing, Licensor provides the
-Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
-including, without limitation, any warranties or conditions of TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
-solely responsible for determining the appropriateness of using or
-redistributing the Work and assume any risks associated with Your exercise of
-permissions under this License.
-
-8. Limitation of Liability.
-
-In no event and under no legal theory, whether in tort (including negligence),
-contract, or otherwise, unless required by applicable law (such as deliberate
-and grossly negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special, incidental,
-or consequential damages of any character arising as a result of this License or
-out of the use or inability to use the Work (including but not limited to
-damages for loss of goodwill, work stoppage, computer failure or malfunction, or
-any and all other commercial damages or losses), even if such Contributor has
-been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability.
-
-While redistributing the Work or Derivative Works thereof, You may choose to
-offer, and charge a fee for, acceptance of support, warranty, indemnity, or
-other liability obligations and/or rights consistent with this License. However,
-in accepting such obligations, You may act only on Your own behalf and on Your
-sole responsibility, not on behalf of any other Contributor, and only if You
-agree to indemnify, defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason of your
-accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work
-
-To apply the Apache License to your work, attach the following boilerplate
-notice, with the fields enclosed by brackets "[]" replaced with your own
-identifying information. (Don't include the brackets!) The text should be
-enclosed in the appropriate comment syntax for the file format. We also
-recommend that a file or class name and description of purpose be included on
-the same "printed page" as the copyright notice for easier identification within
-third-party archives.
-
-   Copyright 2014 Unknwon
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/public-api/vendor/gopkg.in/ini.v1/Makefile b/public-api/vendor/gopkg.in/ini.v1/Makefile
deleted file mode 100644
index f3b0dae2..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-.PHONY: build test bench vet coverage
-
-build: vet bench
-
-test:
-	go test -v -cover -race
-
-bench:
-	go test -v -cover -test.bench=. -test.benchmem
-
-vet:
-	go vet
-
-coverage:
-	go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
diff --git a/public-api/vendor/gopkg.in/ini.v1/README.md b/public-api/vendor/gopkg.in/ini.v1/README.md
deleted file mode 100644
index 30606d97..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# INI
-
-[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain)
-[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini)
-[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc)
-[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini)
-
-![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
-
-Package ini provides INI file read and write functionality in Go.
-
-## Features
-
-- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites.
-- Read with recursion values.
-- Read with parent-child sections.
-- Read with auto-increment key names.
-- Read with multiple-line values.
-- Read with tons of helper methods.
-- Read and convert values to Go types.
-- Read and **WRITE** comments of sections and keys.
-- Manipulate sections, keys and comments with ease.
-- Keep sections and keys in order as you parse and save.
-
-## Installation
-
-The minimum requirement of Go is **1.13**.
-
-```sh
-$ go get gopkg.in/ini.v1
-```
-
-Please add `-u` flag to update in the future.
-
-## Getting Help
-
-- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started)
-- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
-- 中国大陆镜像:https://ini.unknwon.cn
-
-## License
-
-This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
diff --git a/public-api/vendor/gopkg.in/ini.v1/codecov.yml b/public-api/vendor/gopkg.in/ini.v1/codecov.yml
deleted file mode 100644
index e02ec84b..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/codecov.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-coverage:
-  range: "60...95"
-  status:
-    project:
-      default:
-        threshold: 1%
-        informational: true
-    patch:
-      defualt:
-        only_pulls: true
-        informational: true
-
-comment:
-  layout: 'diff'
-
-github_checks: false
diff --git a/public-api/vendor/gopkg.in/ini.v1/data_source.go b/public-api/vendor/gopkg.in/ini.v1/data_source.go
deleted file mode 100644
index c3a541f1..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/data_source.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-)
-
-var (
-	_ dataSource = (*sourceFile)(nil)
-	_ dataSource = (*sourceData)(nil)
-	_ dataSource = (*sourceReadCloser)(nil)
-)
-
-// dataSource is an interface that returns object which can be read and closed.
-type dataSource interface {
-	ReadCloser() (io.ReadCloser, error)
-}
-
-// sourceFile represents an object that contains content on the local file system.
-type sourceFile struct {
-	name string
-}
-
-func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
-	return os.Open(s.name)
-}
-
-// sourceData represents an object that contains content in memory.
-type sourceData struct {
-	data []byte
-}
-
-func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewReader(s.data)), nil
-}
-
-// sourceReadCloser represents an input stream with Close method.
-type sourceReadCloser struct {
-	reader io.ReadCloser
-}
-
-func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
-	return s.reader, nil
-}
-
-func parseDataSource(source interface{}) (dataSource, error) {
-	switch s := source.(type) {
-	case string:
-		return sourceFile{s}, nil
-	case []byte:
-		return &sourceData{s}, nil
-	case io.ReadCloser:
-		return &sourceReadCloser{s}, nil
-	case io.Reader:
-		return &sourceReadCloser{ioutil.NopCloser(s)}, nil
-	default:
-		return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
-	}
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/deprecated.go b/public-api/vendor/gopkg.in/ini.v1/deprecated.go
deleted file mode 100644
index 48b8e66d..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/deprecated.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-var (
-	// Deprecated: Use "DefaultSection" instead.
-	DEFAULT_SECTION = DefaultSection
-	// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
-	AllCapsUnderscore = SnackCase
-)
diff --git a/public-api/vendor/gopkg.in/ini.v1/error.go b/public-api/vendor/gopkg.in/ini.v1/error.go
deleted file mode 100644
index f66bc94b..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/error.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"fmt"
-)
-
-// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one.
-type ErrDelimiterNotFound struct {
-	Line string
-}
-
-// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound.
-func IsErrDelimiterNotFound(err error) bool {
-	_, ok := err.(ErrDelimiterNotFound)
-	return ok
-}
-
-func (err ErrDelimiterNotFound) Error() string {
-	return fmt.Sprintf("key-value delimiter not found: %s", err.Line)
-}
-
-// ErrEmptyKeyName indicates the error type of no key name is found which there should be one.
-type ErrEmptyKeyName struct {
-	Line string
-}
-
-// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName.
-func IsErrEmptyKeyName(err error) bool {
-	_, ok := err.(ErrEmptyKeyName)
-	return ok
-}
-
-func (err ErrEmptyKeyName) Error() string {
-	return fmt.Sprintf("empty key name: %s", err.Line)
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/file.go b/public-api/vendor/gopkg.in/ini.v1/file.go
deleted file mode 100644
index f8b22408..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/file.go
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2017 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"sync"
-)
-
-// File represents a combination of one or more INI files in memory.
-type File struct {
-	options     LoadOptions
-	dataSources []dataSource
-
-	// Should make things safe, but sometimes doesn't matter.
-	BlockMode bool
-	lock      sync.RWMutex
-
-	// To keep data in order.
-	sectionList []string
-	// To keep track of the index of a section with same name.
-	// This meta list is only used with non-unique section names are allowed.
-	sectionIndexes []int
-
-	// Actual data is stored here.
-	sections map[string][]*Section
-
-	NameMapper
-	ValueMapper
-}
-
-// newFile initializes File object with given data sources.
-func newFile(dataSources []dataSource, opts LoadOptions) *File {
-	if len(opts.KeyValueDelimiters) == 0 {
-		opts.KeyValueDelimiters = "=:"
-	}
-	if len(opts.KeyValueDelimiterOnWrite) == 0 {
-		opts.KeyValueDelimiterOnWrite = "="
-	}
-	if len(opts.ChildSectionDelimiter) == 0 {
-		opts.ChildSectionDelimiter = "."
-	}
-
-	return &File{
-		BlockMode:   true,
-		dataSources: dataSources,
-		sections:    make(map[string][]*Section),
-		options:     opts,
-	}
-}
-
-// Empty returns an empty file object.
-func Empty(opts ...LoadOptions) *File {
-	var opt LoadOptions
-	if len(opts) > 0 {
-		opt = opts[0]
-	}
-
-	// Ignore error here, we are sure our data is good.
-	f, _ := LoadSources(opt, []byte(""))
-	return f
-}
-
-// NewSection creates a new section.
-func (f *File) NewSection(name string) (*Section, error) {
-	if len(name) == 0 {
-		return nil, errors.New("empty section name")
-	}
-
-	if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) {
-		return f.sections[name][0], nil
-	}
-
-	f.sectionList = append(f.sectionList, name)
-
-	// NOTE: Append to indexes must happen before appending to sections,
-	// otherwise index will have off-by-one problem.
-	f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name]))
-
-	sec := newSection(f, name)
-	f.sections[name] = append(f.sections[name], sec)
-
-	return sec, nil
-}
-
-// NewRawSection creates a new section with an unparseable body.
-func (f *File) NewRawSection(name, body string) (*Section, error) {
-	section, err := f.NewSection(name)
-	if err != nil {
-		return nil, err
-	}
-
-	section.isRawSection = true
-	section.rawBody = body
-	return section, nil
-}
-
-// NewSections creates a list of sections.
-func (f *File) NewSections(names ...string) (err error) {
-	for _, name := range names {
-		if _, err = f.NewSection(name); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// GetSection returns section by given name.
-func (f *File) GetSection(name string) (*Section, error) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return nil, err
-	}
-
-	return secs[0], err
-}
-
-// HasSection returns true if the file contains a section with given name.
-func (f *File) HasSection(name string) bool {
-	section, _ := f.GetSection(name)
-	return section != nil
-}
-
-// SectionsByName returns all sections with given name.
-func (f *File) SectionsByName(name string) ([]*Section, error) {
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	secs := f.sections[name]
-	if len(secs) == 0 {
-		return nil, fmt.Errorf("section %q does not exist", name)
-	}
-
-	return secs, nil
-}
-
-// Section assumes named section exists and returns a zero-value when not.
-func (f *File) Section(name string) *Section {
-	sec, err := f.GetSection(name)
-	if err != nil {
-		if name == "" {
-			name = DefaultSection
-		}
-		sec, _ = f.NewSection(name)
-		return sec
-	}
-	return sec
-}
-
-// SectionWithIndex assumes named section exists and returns a new section when not.
-func (f *File) SectionWithIndex(name string, index int) *Section {
-	secs, err := f.SectionsByName(name)
-	if err != nil || len(secs) <= index {
-		// NOTE: It's OK here because the only possible error is empty section name,
-		// but if it's empty, this piece of code won't be executed.
-		newSec, _ := f.NewSection(name)
-		return newSec
-	}
-
-	return secs[index]
-}
-
-// Sections returns a list of Section stored in the current instance.
-func (f *File) Sections() []*Section {
-	if f.BlockMode {
-		f.lock.RLock()
-		defer f.lock.RUnlock()
-	}
-
-	sections := make([]*Section, len(f.sectionList))
-	for i, name := range f.sectionList {
-		sections[i] = f.sections[name][f.sectionIndexes[i]]
-	}
-	return sections
-}
-
-// ChildSections returns a list of child sections of given section name.
-func (f *File) ChildSections(name string) []*Section {
-	return f.Section(name).ChildSections()
-}
-
-// SectionStrings returns list of section names.
-func (f *File) SectionStrings() []string {
-	list := make([]string, len(f.sectionList))
-	copy(list, f.sectionList)
-	return list
-}
-
-// DeleteSection deletes a section or all sections with given name.
-func (f *File) DeleteSection(name string) {
-	secs, err := f.SectionsByName(name)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(secs); i++ {
-		// For non-unique sections, it is always needed to remove the first one so
-		// in the next iteration, the subsequent section continue having index 0.
-		// Ignoring the error as index 0 never returns an error.
-		_ = f.DeleteSectionWithIndex(name, 0)
-	}
-}
-
-// DeleteSectionWithIndex deletes a section with given name and index.
-func (f *File) DeleteSectionWithIndex(name string, index int) error {
-	if !f.options.AllowNonUniqueSections && index != 0 {
-		return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled")
-	}
-
-	if len(name) == 0 {
-		name = DefaultSection
-	}
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(name)
-	}
-
-	if f.BlockMode {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-	}
-
-	// Count occurrences of the sections
-	occurrences := 0
-
-	sectionListCopy := make([]string, len(f.sectionList))
-	copy(sectionListCopy, f.sectionList)
-
-	for i, s := range sectionListCopy {
-		if s != name {
-			continue
-		}
-
-		if occurrences == index {
-			if len(f.sections[name]) <= 1 {
-				delete(f.sections, name) // The last one in the map
-			} else {
-				f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...)
-			}
-
-			// Fix section lists
-			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
-			f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...)
-
-		} else if occurrences > index {
-			// Fix the indices of all following sections with this name.
-			f.sectionIndexes[i-1]--
-		}
-
-		occurrences++
-	}
-
-	return nil
-}
-
-func (f *File) reload(s dataSource) error {
-	r, err := s.ReadCloser()
-	if err != nil {
-		return err
-	}
-	defer r.Close()
-
-	return f.parse(r)
-}
-
-// Reload reloads and parses all data sources.
-func (f *File) Reload() (err error) {
-	for _, s := range f.dataSources {
-		if err = f.reload(s); err != nil {
-			// In loose mode, we create an empty default section for nonexistent files.
-			if os.IsNotExist(err) && f.options.Loose {
-				_ = f.parse(bytes.NewBuffer(nil))
-				continue
-			}
-			return err
-		}
-		if f.options.ShortCircuit {
-			return nil
-		}
-	}
-	return nil
-}
-
-// Append appends one or more data sources and reloads automatically.
-func (f *File) Append(source interface{}, others ...interface{}) error {
-	ds, err := parseDataSource(source)
-	if err != nil {
-		return err
-	}
-	f.dataSources = append(f.dataSources, ds)
-	for _, s := range others {
-		ds, err = parseDataSource(s)
-		if err != nil {
-			return err
-		}
-		f.dataSources = append(f.dataSources, ds)
-	}
-	return f.Reload()
-}
-
-func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
-	equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight
-
-	if PrettyFormat || PrettyEqual {
-		equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite)
-	}
-
-	// Use buffer to make sure target is safe until finish encoding.
-	buf := bytes.NewBuffer(nil)
-	lastSectionIdx := len(f.sectionList) - 1
-	for i, sname := range f.sectionList {
-		sec := f.SectionWithIndex(sname, f.sectionIndexes[i])
-		if len(sec.Comment) > 0 {
-			// Support multiline comments
-			lines := strings.Split(sec.Comment, LineBreak)
-			for i := range lines {
-				if lines[i][0] != '#' && lines[i][0] != ';' {
-					lines[i] = "; " + lines[i]
-				} else {
-					lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-				}
-
-				if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) {
-			if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
-				return nil, err
-			}
-		} else {
-			// Write nothing if default section is empty
-			if len(sec.keyList) == 0 {
-				continue
-			}
-		}
-
-		isLastSection := i == lastSectionIdx
-		if sec.isRawSection {
-			if _, err := buf.WriteString(sec.rawBody); err != nil {
-				return nil, err
-			}
-
-			if PrettySection && !isLastSection {
-				// Put a line between sections
-				if _, err := buf.WriteString(LineBreak); err != nil {
-					return nil, err
-				}
-			}
-			continue
-		}
-
-		// Count and generate alignment length and buffer spaces using the
-		// longest key. Keys may be modified if they contain certain characters so
-		// we need to take that into account in our calculation.
-		alignLength := 0
-		if PrettyFormat {
-			for _, kname := range sec.keyList {
-				keyLength := len(kname)
-				// First case will surround key by ` and second by """
-				if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) {
-					keyLength += 2
-				} else if strings.Contains(kname, "`") {
-					keyLength += 6
-				}
-
-				if keyLength > alignLength {
-					alignLength = keyLength
-				}
-			}
-		}
-		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
-
-	KeyList:
-		for _, kname := range sec.keyList {
-			key := sec.Key(kname)
-			if len(key.Comment) > 0 {
-				if len(indent) > 0 && sname != DefaultSection {
-					buf.WriteString(indent)
-				}
-
-				// Support multiline comments
-				lines := strings.Split(key.Comment, LineBreak)
-				for i := range lines {
-					if lines[i][0] != '#' && lines[i][0] != ';' {
-						lines[i] = "; " + strings.TrimSpace(lines[i])
-					} else {
-						lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:])
-					}
-
-					if _, err := buf.WriteString(lines[i] + LineBreak); err != nil {
-						return nil, err
-					}
-				}
-			}
-
-			if len(indent) > 0 && sname != DefaultSection {
-				buf.WriteString(indent)
-			}
-
-			switch {
-			case key.isAutoIncrement:
-				kname = "-"
-			case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters):
-				kname = "`" + kname + "`"
-			case strings.Contains(kname, "`"):
-				kname = `"""` + kname + `"""`
-			}
-
-			writeKeyValue := func(val string) (bool, error) {
-				if _, err := buf.WriteString(kname); err != nil {
-					return false, err
-				}
-
-				if key.isBooleanType {
-					buf.WriteString(LineBreak)
-					return true, nil
-				}
-
-				// Write out alignment spaces before "=" sign
-				if PrettyFormat {
-					buf.Write(alignSpaces[:alignLength-len(kname)])
-				}
-
-				// In case key value contains "\n", "`", "\"", "#" or ";"
-				if strings.ContainsAny(val, "\n`") {
-					val = `"""` + val + `"""`
-				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
-					val = "`" + val + "`"
-				} else if len(strings.TrimSpace(val)) != len(val) {
-					val = `"` + val + `"`
-				}
-				if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
-					return false, err
-				}
-				return false, nil
-			}
-
-			shadows := key.ValueWithShadows()
-			if len(shadows) == 0 {
-				if _, err := writeKeyValue(""); err != nil {
-					return nil, err
-				}
-			}
-
-			for _, val := range shadows {
-				exitLoop, err := writeKeyValue(val)
-				if err != nil {
-					return nil, err
-				} else if exitLoop {
-					continue KeyList
-				}
-			}
-
-			for _, val := range key.nestedValues {
-				if _, err := buf.WriteString(indent + "  " + val + LineBreak); err != nil {
-					return nil, err
-				}
-			}
-		}
-
-		if PrettySection && !isLastSection {
-			// Put a line between sections
-			if _, err := buf.WriteString(LineBreak); err != nil {
-				return nil, err
-			}
-		}
-	}
-
-	return buf, nil
-}
-
-// WriteToIndent writes content into io.Writer with given indention.
-// If PrettyFormat has been set to be true,
-// it will align "=" sign with spaces under each section.
-func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return 0, err
-	}
-	return buf.WriteTo(w)
-}
-
-// WriteTo writes file content into io.Writer.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
-	return f.WriteToIndent(w, "")
-}
-
-// SaveToIndent writes content to file system with given value indention.
-func (f *File) SaveToIndent(filename, indent string) error {
-	// Note: Because we are truncating with os.Create,
-	// 	so it's safer to save to a temporary file location and rename after done.
-	buf, err := f.writeToBuffer(indent)
-	if err != nil {
-		return err
-	}
-
-	return ioutil.WriteFile(filename, buf.Bytes(), 0666)
-}
-
-// SaveTo writes content to file system.
-func (f *File) SaveTo(filename string) error {
-	return f.SaveToIndent(filename, "")
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/helper.go b/public-api/vendor/gopkg.in/ini.v1/helper.go
deleted file mode 100644
index f9d80a68..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/helper.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-func inSlice(str string, s []string) bool {
-	for _, v := range s {
-		if str == v {
-			return true
-		}
-	}
-	return false
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/ini.go b/public-api/vendor/gopkg.in/ini.v1/ini.go
deleted file mode 100644
index 99e7f865..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/ini.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-// Package ini provides INI file read and write functionality in Go.
-package ini
-
-import (
-	"os"
-	"regexp"
-	"runtime"
-	"strings"
-)
-
-const (
-	// Maximum allowed depth when recursively substituing variable names.
-	depthValues = 99
-)
-
-var (
-	// DefaultSection is the name of default section. You can use this var or the string literal.
-	// In most of cases, an empty string is all you need to access the section.
-	DefaultSection = "DEFAULT"
-
-	// LineBreak is the delimiter to determine or compose a new line.
-	// This variable will be changed to "\r\n" automatically on Windows at package init time.
-	LineBreak = "\n"
-
-	// Variable regexp pattern: %(variable)s
-	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)
-
-	// DefaultHeader explicitly writes default section header.
-	DefaultHeader = false
-
-	// PrettySection indicates whether to put a line between sections.
-	PrettySection = true
-	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
-	// or reduce all possible spaces for compact format.
-	PrettyFormat = true
-	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
-	PrettyEqual = false
-	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatLeft = ""
-	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
-	DefaultFormatRight = ""
-)
-
-var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
-
-func init() {
-	if runtime.GOOS == "windows" && !inTest {
-		LineBreak = "\r\n"
-	}
-}
-
-// LoadOptions contains all customized options used for load data source(s).
-type LoadOptions struct {
-	// Loose indicates whether the parser should ignore nonexistent files or return error.
-	Loose bool
-	// Insensitive indicates whether the parser forces all section and key names to lowercase.
-	Insensitive bool
-	// InsensitiveSections indicates whether the parser forces all section to lowercase.
-	InsensitiveSections bool
-	// InsensitiveKeys indicates whether the parser forces all key names to lowercase.
-	InsensitiveKeys bool
-	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
-	IgnoreContinuation bool
-	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
-	IgnoreInlineComment bool
-	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs.
-	SkipUnrecognizableLines bool
-	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source.
-	ShortCircuit bool
-	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
-	// This type of keys are mostly used in my.cnf.
-	AllowBooleanKeys bool
-	// AllowShadows indicates whether to keep track of keys with same name under same section.
-	AllowShadows bool
-	// AllowNestedValues indicates whether to allow AWS-like nested values.
-	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
-	AllowNestedValues bool
-	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values.
-	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
-	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper
-	// than the first line of the value.
-	AllowPythonMultilineValues bool
-	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
-	// Docs: https://docs.python.org/2/library/configparser.html
-	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
-	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
-	SpaceBeforeInlineComment bool
-	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
-	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
-	UnescapeValueDoubleQuotes bool
-	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
-	// when value is NOT surrounded by any quotes.
-	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
-	UnescapeValueCommentSymbols bool
-	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
-	// conform to key/value pairs. Specify the names of those blocks here.
-	UnparseableSections []string
-	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
-	KeyValueDelimiters string
-	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=".
-	KeyValueDelimiterOnWrite string
-	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
-	ChildSectionDelimiter string
-	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
-	PreserveSurroundedQuote bool
-	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
-	DebugFunc DebugFunc
-	// ReaderBufferSize is the buffer size of the reader in bytes.
-	ReaderBufferSize int
-	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
-	AllowNonUniqueSections bool
-	// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated.
-	AllowDuplicateShadowValues bool
-}
-
-// DebugFunc is the type of function called to log parse events.
-type DebugFunc func(message string)
-
-// LoadSources allows caller to apply customized options for loading from data source(s).
-func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
-	sources := make([]dataSource, len(others)+1)
-	sources[0], err = parseDataSource(source)
-	if err != nil {
-		return nil, err
-	}
-	for i := range others {
-		sources[i+1], err = parseDataSource(others[i])
-		if err != nil {
-			return nil, err
-		}
-	}
-	f := newFile(sources, opts)
-	if err = f.Reload(); err != nil {
-		return nil, err
-	}
-	return f, nil
-}
-
-// Load loads and parses from INI data sources.
-// Arguments can be mixed of file name with string type, or raw data in []byte.
-// It will return error if list contains nonexistent files.
-func Load(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{}, source, others...)
-}
-
-// LooseLoad has exactly same functionality as Load function
-// except it ignores nonexistent files instead of returning error.
-func LooseLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Loose: true}, source, others...)
-}
-
-// InsensitiveLoad has exactly same functionality as Load function
-// except it forces all section and key names to be lowercased.
-func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
-}
-
-// ShadowLoad has exactly same functionality as Load function
-// except it allows have shadow keys.
-func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
-	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/key.go b/public-api/vendor/gopkg.in/ini.v1/key.go
deleted file mode 100644
index a19d9f38..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/key.go
+++ /dev/null
@@ -1,837 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Key represents a key under a section.
-type Key struct {
-	s               *Section
-	Comment         string
-	name            string
-	value           string
-	isAutoIncrement bool
-	isBooleanType   bool
-
-	isShadow bool
-	shadows  []*Key
-
-	nestedValues []string
-}
-
-// newKey simply return a key object with given values.
-func newKey(s *Section, name, val string) *Key {
-	return &Key{
-		s:     s,
-		name:  name,
-		value: val,
-	}
-}
-
-func (k *Key) addShadow(val string) error {
-	if k.isShadow {
-		return errors.New("cannot add shadow to another shadow key")
-	} else if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add shadow to auto-increment or boolean key")
-	}
-
-	if !k.s.f.options.AllowDuplicateShadowValues {
-		// Deduplicate shadows based on their values.
-		if k.value == val {
-			return nil
-		}
-		for i := range k.shadows {
-			if k.shadows[i].value == val {
-				return nil
-			}
-		}
-	}
-
-	shadow := newKey(k.s, k.name, val)
-	shadow.isShadow = true
-	k.shadows = append(k.shadows, shadow)
-	return nil
-}
-
-// AddShadow adds a new shadow key to itself.
-func (k *Key) AddShadow(val string) error {
-	if !k.s.f.options.AllowShadows {
-		return errors.New("shadow key is not allowed")
-	}
-	return k.addShadow(val)
-}
-
-func (k *Key) addNestedValue(val string) error {
-	if k.isAutoIncrement || k.isBooleanType {
-		return errors.New("cannot add nested value to auto-increment or boolean key")
-	}
-
-	k.nestedValues = append(k.nestedValues, val)
-	return nil
-}
-
-// AddNestedValue adds a nested value to the key.
-func (k *Key) AddNestedValue(val string) error {
-	if !k.s.f.options.AllowNestedValues {
-		return errors.New("nested value is not allowed")
-	}
-	return k.addNestedValue(val)
-}
-
-// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
-type ValueMapper func(string) string
-
-// Name returns name of key.
-func (k *Key) Name() string {
-	return k.name
-}
-
-// Value returns raw value of key for performance purpose.
-func (k *Key) Value() string {
-	return k.value
-}
-
-// ValueWithShadows returns raw values of key and its shadows if any. Shadow
-// keys with empty values are ignored from the returned list.
-func (k *Key) ValueWithShadows() []string {
-	if len(k.shadows) == 0 {
-		if k.value == "" {
-			return []string{}
-		}
-		return []string{k.value}
-	}
-
-	vals := make([]string, 0, len(k.shadows)+1)
-	if k.value != "" {
-		vals = append(vals, k.value)
-	}
-	for _, s := range k.shadows {
-		if s.value != "" {
-			vals = append(vals, s.value)
-		}
-	}
-	return vals
-}
-
-// NestedValues returns nested values stored in the key.
-// It is possible returned value is nil if no nested values stored in the key.
-func (k *Key) NestedValues() []string {
-	return k.nestedValues
-}
-
-// transformValue takes a raw value and transforms to its final string.
-func (k *Key) transformValue(val string) string {
-	if k.s.f.ValueMapper != nil {
-		val = k.s.f.ValueMapper(val)
-	}
-
-	// Fail-fast if no indicate char found for recursive value
-	if !strings.Contains(val, "%") {
-		return val
-	}
-	for i := 0; i < depthValues; i++ {
-		vr := varPattern.FindString(val)
-		if len(vr) == 0 {
-			break
-		}
-
-		// Take off leading '%(' and trailing ')s'.
-		noption := vr[2 : len(vr)-2]
-
-		// Search in the same section.
-		// If not found or found the key itself, then search again in default section.
-		nk, err := k.s.GetKey(noption)
-		if err != nil || k == nk {
-			nk, _ = k.s.f.Section("").GetKey(noption)
-			if nk == nil {
-				// Stop when no results found in the default section,
-				// and returns the value as-is.
-				break
-			}
-		}
-
-		// Substitute by new value and take off leading '%(' and trailing ')s'.
-		val = strings.Replace(val, vr, nk.value, -1)
-	}
-	return val
-}
-
-// String returns string representation of value.
-func (k *Key) String() string {
-	return k.transformValue(k.value)
-}
-
-// Validate accepts a validate function which can
-// return modifed result as key value.
-func (k *Key) Validate(fn func(string) string) string {
-	return fn(k.String())
-}
-
-// parseBool returns the boolean value represented by the string.
-//
-// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On,
-// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off.
-// Any other value returns an error.
-func parseBool(str string) (value bool, err error) {
-	switch str {
-	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On":
-		return true, nil
-	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off":
-		return false, nil
-	}
-	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
-}
-
-// Bool returns bool type value.
-func (k *Key) Bool() (bool, error) {
-	return parseBool(k.String())
-}
-
-// Float64 returns float64 type value.
-func (k *Key) Float64() (float64, error) {
-	return strconv.ParseFloat(k.String(), 64)
-}
-
-// Int returns int type value.
-func (k *Key) Int() (int, error) {
-	v, err := strconv.ParseInt(k.String(), 0, 64)
-	return int(v), err
-}
-
-// Int64 returns int64 type value.
-func (k *Key) Int64() (int64, error) {
-	return strconv.ParseInt(k.String(), 0, 64)
-}
-
-// Uint returns uint type valued.
-func (k *Key) Uint() (uint, error) {
-	u, e := strconv.ParseUint(k.String(), 0, 64)
-	return uint(u), e
-}
-
-// Uint64 returns uint64 type value.
-func (k *Key) Uint64() (uint64, error) {
-	return strconv.ParseUint(k.String(), 0, 64)
-}
-
-// Duration returns time.Duration type value.
-func (k *Key) Duration() (time.Duration, error) {
-	return time.ParseDuration(k.String())
-}
-
-// TimeFormat parses with given format and returns time.Time type value.
-func (k *Key) TimeFormat(format string) (time.Time, error) {
-	return time.Parse(format, k.String())
-}
-
-// Time parses with RFC3339 format and returns time.Time type value.
-func (k *Key) Time() (time.Time, error) {
-	return k.TimeFormat(time.RFC3339)
-}
-
-// MustString returns default value if key value is empty.
-func (k *Key) MustString(defaultVal string) string {
-	val := k.String()
-	if len(val) == 0 {
-		k.value = defaultVal
-		return defaultVal
-	}
-	return val
-}
-
-// MustBool always returns value without error,
-// it returns false if error occurs.
-func (k *Key) MustBool(defaultVal ...bool) bool {
-	val, err := k.Bool()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatBool(defaultVal[0])
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustFloat64 always returns value without error,
-// it returns 0.0 if error occurs.
-func (k *Key) MustFloat64(defaultVal ...float64) float64 {
-	val, err := k.Float64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt(defaultVal ...int) int {
-	val, err := k.Int()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(int64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustInt64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustInt64(defaultVal ...int64) int64 {
-	val, err := k.Int64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatInt(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint(defaultVal ...uint) uint {
-	val, err := k.Uint()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(uint64(defaultVal[0]), 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustUint64 always returns value without error,
-// it returns 0 if error occurs.
-func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
-	val, err := k.Uint64()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = strconv.FormatUint(defaultVal[0], 10)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustDuration always returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
-	val, err := k.Duration()
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].String()
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTimeFormat always parses with given format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
-	val, err := k.TimeFormat(format)
-	if len(defaultVal) > 0 && err != nil {
-		k.value = defaultVal[0].Format(format)
-		return defaultVal[0]
-	}
-	return val
-}
-
-// MustTime always parses with RFC3339 format and returns value without error,
-// it returns zero value if error occurs.
-func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
-	return k.MustTimeFormat(time.RFC3339, defaultVal...)
-}
-
-// In always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) In(defaultVal string, candidates []string) string {
-	val := k.String()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InFloat64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
-	val := k.MustFloat64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt(defaultVal int, candidates []int) int {
-	val := k.MustInt()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InInt64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
-	val := k.MustInt64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
-	val := k.MustUint()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InUint64 always returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
-	val := k.MustUint64()
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTimeFormat always parses with given format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	for _, cand := range candidates {
-		if val == cand {
-			return val
-		}
-	}
-	return defaultVal
-}
-
-// InTime always parses with RFC3339 format and returns value without error,
-// it returns default value if error occurs or doesn't fit into candidates.
-func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
-	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
-}
-
-// RangeFloat64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
-	val := k.MustFloat64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt(defaultVal, min, max int) int {
-	val := k.MustInt()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeInt64 checks if value is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
-	val := k.MustInt64()
-	if val < min || val > max {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTimeFormat checks if value with given format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
-	val := k.MustTimeFormat(format)
-	if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
-		return defaultVal
-	}
-	return val
-}
-
-// RangeTime checks if value with RFC3339 format is in given range inclusively,
-// and returns default value if it's not.
-func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
-	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
-}
-
-// Strings returns list of string divided by given delimiter.
-func (k *Key) Strings(delim string) []string {
-	str := k.String()
-	if len(str) == 0 {
-		return []string{}
-	}
-
-	runes := []rune(str)
-	vals := make([]string, 0, 2)
-	var buf bytes.Buffer
-	escape := false
-	idx := 0
-	for {
-		if escape {
-			escape = false
-			if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
-				buf.WriteRune('\\')
-			}
-			buf.WriteRune(runes[idx])
-		} else {
-			if runes[idx] == '\\' {
-				escape = true
-			} else if strings.HasPrefix(string(runes[idx:]), delim) {
-				idx += len(delim) - 1
-				vals = append(vals, strings.TrimSpace(buf.String()))
-				buf.Reset()
-			} else {
-				buf.WriteRune(runes[idx])
-			}
-		}
-		idx++
-		if idx == len(runes) {
-			break
-		}
-	}
-
-	if buf.Len() > 0 {
-		vals = append(vals, strings.TrimSpace(buf.String()))
-	}
-
-	return vals
-}
-
-// StringsWithShadows returns list of string divided by given delimiter.
-// Shadows will also be appended if any.
-func (k *Key) StringsWithShadows(delim string) []string {
-	vals := k.ValueWithShadows()
-	results := make([]string, 0, len(vals)*2)
-	for i := range vals {
-		if len(vals) == 0 {
-			continue
-		}
-
-		results = append(results, strings.Split(vals[i], delim)...)
-	}
-
-	for i := range results {
-		results[i] = k.transformValue(strings.TrimSpace(results[i]))
-	}
-	return results
-}
-
-// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Float64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Ints(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), true, false)
-	return vals
-}
-
-// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Int64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), true, false)
-	return vals
-}
-
-// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Uint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), true, false)
-	return vals
-}
-
-// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value.
-func (k *Key) Bools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), true, false)
-	return vals
-}
-
-// TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) TimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
-	return vals
-}
-
-// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
-func (k *Key) Times(delim string) []time.Time {
-	return k.TimesFormat(time.RFC3339, delim)
-}
-
-// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
-// it will not be included to result list.
-func (k *Key) ValidFloat64s(delim string) []float64 {
-	vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
-// not be included to result list.
-func (k *Key) ValidInts(delim string) []int {
-	vals, _ := k.parseInts(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
-// then it will not be included to result list.
-func (k *Key) ValidInt64s(delim string) []int64 {
-	vals, _ := k.parseInt64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
-// then it will not be included to result list.
-func (k *Key) ValidUints(delim string) []uint {
-	vals, _ := k.parseUints(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidUint64s(delim string) []uint64 {
-	vals, _ := k.parseUint64s(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned
-// integer, then it will not be included to result list.
-func (k *Key) ValidBools(delim string) []bool {
-	vals, _ := k.parseBools(k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
-	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
-	return vals
-}
-
-// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.
-func (k *Key) ValidTimes(delim string) []time.Time {
-	return k.ValidTimesFormat(time.RFC3339, delim)
-}
-
-// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
-	return k.parseFloat64s(k.Strings(delim), false, true)
-}
-
-// StrictInts returns list of int divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInts(delim string) ([]int, error) {
-	return k.parseInts(k.Strings(delim), false, true)
-}
-
-// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictInt64s(delim string) ([]int64, error) {
-	return k.parseInt64s(k.Strings(delim), false, true)
-}
-
-// StrictUints returns list of uint divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUints(delim string) ([]uint, error) {
-	return k.parseUints(k.Strings(delim), false, true)
-}
-
-// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
-func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
-	return k.parseUint64s(k.Strings(delim), false, true)
-}
-
-// StrictBools returns list of bool divided by given delimiter or error on first invalid input.
-func (k *Key) StrictBools(delim string) ([]bool, error) {
-	return k.parseBools(k.Strings(delim), false, true)
-}
-
-// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
-	return k.parseTimesFormat(format, k.Strings(delim), false, true)
-}
-
-// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
-// or error on first invalid input.
-func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
-	return k.StrictTimesFormat(time.RFC3339, delim)
-}
-
-// parseBools transforms strings to bools.
-func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) {
-	vals := make([]bool, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := parseBool(str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(bool))
-		}
-	}
-	return vals, err
-}
-
-// parseFloat64s transforms strings to float64s.
-func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
-	vals := make([]float64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseFloat(str, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(float64))
-		}
-	}
-	return vals, err
-}
-
-// parseInts transforms strings to ints.
-func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
-	vals := make([]int, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, int(val.(int64)))
-		}
-	}
-	return vals, err
-}
-
-// parseInt64s transforms strings to int64s.
-func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
-	vals := make([]int64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseInt(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(int64))
-		}
-	}
-	return vals, err
-}
-
-// parseUints transforms strings to uints.
-func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
-	vals := make([]uint, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, uint(val.(uint64)))
-		}
-	}
-	return vals, err
-}
-
-// parseUint64s transforms strings to uint64s.
-func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
-	vals := make([]uint64, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := strconv.ParseUint(str, 0, 64)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(uint64))
-		}
-	}
-	return vals, err
-}
-
-type Parser func(str string) (interface{}, error)
-
-// parseTimesFormat transforms strings to times in given format.
-func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
-	vals := make([]time.Time, 0, len(strs))
-	parser := func(str string) (interface{}, error) {
-		val, err := time.Parse(format, str)
-		return val, err
-	}
-	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser)
-	if err == nil {
-		for _, val := range rawVals {
-			vals = append(vals, val.(time.Time))
-		}
-	}
-	return vals, err
-}
-
-// doParse transforms strings to different types
-func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) {
-	vals := make([]interface{}, 0, len(strs))
-	for _, str := range strs {
-		val, err := parser(str)
-		if err != nil && returnOnInvalid {
-			return nil, err
-		}
-		if err == nil || addInvalid {
-			vals = append(vals, val)
-		}
-	}
-	return vals, nil
-}
-
-// SetValue changes key value.
-func (k *Key) SetValue(v string) {
-	if k.s.f.BlockMode {
-		k.s.f.lock.Lock()
-		defer k.s.f.lock.Unlock()
-	}
-
-	k.value = v
-	k.s.keysHash[k.name] = v
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/parser.go b/public-api/vendor/gopkg.in/ini.v1/parser.go
deleted file mode 100644
index 44fc526c..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/parser.go
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2015 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"regexp"
-	"strconv"
-	"strings"
-	"unicode"
-)
-
-const minReaderBufferSize = 4096
-
-var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`)
-
-type parserOptions struct {
-	IgnoreContinuation          bool
-	IgnoreInlineComment         bool
-	AllowPythonMultilineValues  bool
-	SpaceBeforeInlineComment    bool
-	UnescapeValueDoubleQuotes   bool
-	UnescapeValueCommentSymbols bool
-	PreserveSurroundedQuote     bool
-	DebugFunc                   DebugFunc
-	ReaderBufferSize            int
-}
-
-type parser struct {
-	buf     *bufio.Reader
-	options parserOptions
-
-	isEOF   bool
-	count   int
-	comment *bytes.Buffer
-}
-
-func (p *parser) debug(format string, args ...interface{}) {
-	if p.options.DebugFunc != nil {
-		p.options.DebugFunc(fmt.Sprintf(format, args...))
-	}
-}
-
-func newParser(r io.Reader, opts parserOptions) *parser {
-	size := opts.ReaderBufferSize
-	if size < minReaderBufferSize {
-		size = minReaderBufferSize
-	}
-
-	return &parser{
-		buf:     bufio.NewReaderSize(r, size),
-		options: opts,
-		count:   1,
-		comment: &bytes.Buffer{},
-	}
-}
-
-// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
-// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
-func (p *parser) BOM() error {
-	mask, err := p.buf.Peek(2)
-	if err != nil && err != io.EOF {
-		return err
-	} else if len(mask) < 2 {
-		return nil
-	}
-
-	switch {
-	case mask[0] == 254 && mask[1] == 255:
-		fallthrough
-	case mask[0] == 255 && mask[1] == 254:
-		_, err = p.buf.Read(mask)
-		if err != nil {
-			return err
-		}
-	case mask[0] == 239 && mask[1] == 187:
-		mask, err := p.buf.Peek(3)
-		if err != nil && err != io.EOF {
-			return err
-		} else if len(mask) < 3 {
-			return nil
-		}
-		if mask[2] == 191 {
-			_, err = p.buf.Read(mask)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func (p *parser) readUntil(delim byte) ([]byte, error) {
-	data, err := p.buf.ReadBytes(delim)
-	if err != nil {
-		if err == io.EOF {
-			p.isEOF = true
-		} else {
-			return nil, err
-		}
-	}
-	return data, nil
-}
-
-func cleanComment(in []byte) ([]byte, bool) {
-	i := bytes.IndexAny(in, "#;")
-	if i == -1 {
-		return nil, false
-	}
-	return in[i:], true
-}
-
-func readKeyName(delimiters string, in []byte) (string, int, error) {
-	line := string(in)
-
-	// Check if key name surrounded by quotes.
-	var keyQuote string
-	if line[0] == '"' {
-		if len(line) > 6 && line[0:3] == `"""` {
-			keyQuote = `"""`
-		} else {
-			keyQuote = `"`
-		}
-	} else if line[0] == '`' {
-		keyQuote = "`"
-	}
-
-	// Get out key name
-	var endIdx int
-	if len(keyQuote) > 0 {
-		startIdx := len(keyQuote)
-		// FIXME: fail case -> """"""name"""=value
-		pos := strings.Index(line[startIdx:], keyQuote)
-		if pos == -1 {
-			return "", -1, fmt.Errorf("missing closing key quote: %s", line)
-		}
-		pos += startIdx
-
-		// Find key-value delimiter
-		i := strings.IndexAny(line[pos+startIdx:], delimiters)
-		if i < 0 {
-			return "", -1, ErrDelimiterNotFound{line}
-		}
-		endIdx = pos + i
-		return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
-	}
-
-	endIdx = strings.IndexAny(line, delimiters)
-	if endIdx < 0 {
-		return "", -1, ErrDelimiterNotFound{line}
-	}
-	if endIdx == 0 {
-		return "", -1, ErrEmptyKeyName{line}
-	}
-
-	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
-}
-
-func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := string(data)
-
-		pos := strings.LastIndex(next, valQuote)
-		if pos > -1 {
-			val += next[:pos]
-
-			comment, has := cleanComment([]byte(next[pos:]))
-			if has {
-				p.comment.Write(bytes.TrimSpace(comment))
-			}
-			break
-		}
-		val += next
-		if p.isEOF {
-			return "", fmt.Errorf("missing closing key quote from %q to %q", line, next)
-		}
-	}
-	return val, nil
-}
-
-func (p *parser) readContinuationLines(val string) (string, error) {
-	for {
-		data, err := p.readUntil('\n')
-		if err != nil {
-			return "", err
-		}
-		next := strings.TrimSpace(string(data))
-
-		if len(next) == 0 {
-			break
-		}
-		val += next
-		if val[len(val)-1] != '\\' {
-			break
-		}
-		val = val[:len(val)-1]
-	}
-	return val, nil
-}
-
-// hasSurroundedQuote check if and only if the first and last characters
-// are quotes \" or \'.
-// It returns false if any other parts also contain same kind of quotes.
-func hasSurroundedQuote(in string, quote byte) bool {
-	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
-		strings.IndexByte(in[1:], quote) == len(in)-2
-}
-
-func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
-
-	line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
-	if len(line) == 0 {
-		if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' {
-			return p.readPythonMultilines(line, bufferSize)
-		}
-		return "", nil
-	}
-
-	var valQuote string
-	if len(line) > 3 && line[0:3] == `"""` {
-		valQuote = `"""`
-	} else if line[0] == '`' {
-		valQuote = "`"
-	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
-		valQuote = `"`
-	}
-
-	if len(valQuote) > 0 {
-		startIdx := len(valQuote)
-		pos := strings.LastIndex(line[startIdx:], valQuote)
-		// Check for multi-line value
-		if pos == -1 {
-			return p.readMultilines(line, line[startIdx:], valQuote)
-		}
-
-		if p.options.UnescapeValueDoubleQuotes && valQuote == `"` {
-			return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
-		}
-		return line[startIdx : pos+startIdx], nil
-	}
-
-	lastChar := line[len(line)-1]
-	// Won't be able to reach here if value only contains whitespace
-	line = strings.TrimSpace(line)
-	trimmedLastChar := line[len(line)-1]
-
-	// Check continuation lines when desired
-	if !p.options.IgnoreContinuation && trimmedLastChar == '\\' {
-		return p.readContinuationLines(line[:len(line)-1])
-	}
-
-	// Check if ignore inline comment
-	if !p.options.IgnoreInlineComment {
-		var i int
-		if p.options.SpaceBeforeInlineComment {
-			i = strings.Index(line, " #")
-			if i == -1 {
-				i = strings.Index(line, " ;")
-			}
-
-		} else {
-			i = strings.IndexAny(line, "#;")
-		}
-
-		if i > -1 {
-			p.comment.WriteString(line[i:])
-			line = strings.TrimSpace(line[:i])
-		}
-
-	}
-
-	// Trim single and double quotes
-	if (hasSurroundedQuote(line, '\'') ||
-		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
-		line = line[1 : len(line)-1]
-	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
-		line = strings.ReplaceAll(line, `\;`, ";")
-		line = strings.ReplaceAll(line, `\#`, "#")
-	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
-		return p.readPythonMultilines(line, bufferSize)
-	}
-
-	return line, nil
-}
-
-func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
-	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
-	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
-
-	for {
-		peekData, peekErr := peekBuffer.ReadBytes('\n')
-		if peekErr != nil && peekErr != io.EOF {
-			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
-			return "", peekErr
-		}
-
-		p.debug("readPythonMultilines: parsing %q", string(peekData))
-
-		peekMatches := pythonMultiline.FindStringSubmatch(string(peekData))
-		p.debug("readPythonMultilines: matched %d parts", len(peekMatches))
-		for n, v := range peekMatches {
-			p.debug("   %d: %q", n, v)
-		}
-
-		// Return if not a Python multiline value.
-		if len(peekMatches) != 3 {
-			p.debug("readPythonMultilines: end of value, got: %q", line)
-			return line, nil
-		}
-
-		// Advance the parser reader (buffer) in-sync with the peek buffer.
-		_, err := p.buf.Discard(len(peekData))
-		if err != nil {
-			p.debug("readPythonMultilines: failed to skip to the end, returning error")
-			return "", err
-		}
-
-		line += "\n" + peekMatches[0]
-	}
-}
-
-// parse parses data through an io.Reader.
-func (f *File) parse(reader io.Reader) (err error) {
-	p := newParser(reader, parserOptions{
-		IgnoreContinuation:          f.options.IgnoreContinuation,
-		IgnoreInlineComment:         f.options.IgnoreInlineComment,
-		AllowPythonMultilineValues:  f.options.AllowPythonMultilineValues,
-		SpaceBeforeInlineComment:    f.options.SpaceBeforeInlineComment,
-		UnescapeValueDoubleQuotes:   f.options.UnescapeValueDoubleQuotes,
-		UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols,
-		PreserveSurroundedQuote:     f.options.PreserveSurroundedQuote,
-		DebugFunc:                   f.options.DebugFunc,
-		ReaderBufferSize:            f.options.ReaderBufferSize,
-	})
-	if err = p.BOM(); err != nil {
-		return fmt.Errorf("BOM: %v", err)
-	}
-
-	// Ignore error because default section name is never empty string.
-	name := DefaultSection
-	if f.options.Insensitive || f.options.InsensitiveSections {
-		name = strings.ToLower(DefaultSection)
-	}
-	section, _ := f.NewSection(name)
-
-	// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
-	var isLastValueEmpty bool
-	var lastRegularKey *Key
-
-	var line []byte
-	var inUnparseableSection bool
-
-	// NOTE: Iterate and increase `currentPeekSize` until
-	// the size of the parser buffer is found.
-	// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`.
-	parserBufferSize := 0
-	// NOTE: Peek 4kb at a time.
-	currentPeekSize := minReaderBufferSize
-
-	if f.options.AllowPythonMultilineValues {
-		for {
-			peekBytes, _ := p.buf.Peek(currentPeekSize)
-			peekBytesLength := len(peekBytes)
-
-			if parserBufferSize >= peekBytesLength {
-				break
-			}
-
-			currentPeekSize *= 2
-			parserBufferSize = peekBytesLength
-		}
-	}
-
-	for !p.isEOF {
-		line, err = p.readUntil('\n')
-		if err != nil {
-			return err
-		}
-
-		if f.options.AllowNestedValues &&
-			isLastValueEmpty && len(line) > 0 {
-			if line[0] == ' ' || line[0] == '\t' {
-				err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line)))
-				if err != nil {
-					return err
-				}
-				continue
-			}
-		}
-
-		line = bytes.TrimLeftFunc(line, unicode.IsSpace)
-		if len(line) == 0 {
-			continue
-		}
-
-		// Comments
-		if line[0] == '#' || line[0] == ';' {
-			// Note: we do not care ending line break,
-			// it is needed for adding second line,
-			// so just clean it once at the end when set to value.
-			p.comment.Write(line)
-			continue
-		}
-
-		// Section
-		if line[0] == '[' {
-			// Read to the next ']' (TODO: support quoted strings)
-			closeIdx := bytes.LastIndexByte(line, ']')
-			if closeIdx == -1 {
-				return fmt.Errorf("unclosed section: %s", line)
-			}
-
-			name := string(line[1:closeIdx])
-			section, err = f.NewSection(name)
-			if err != nil {
-				return err
-			}
-
-			comment, has := cleanComment(line[closeIdx+1:])
-			if has {
-				p.comment.Write(comment)
-			}
-
-			section.Comment = strings.TrimSpace(p.comment.String())
-
-			// Reset auto-counter and comments
-			p.comment.Reset()
-			p.count = 1
-			// Nested values can't span sections
-			isLastValueEmpty = false
-
-			inUnparseableSection = false
-			for i := range f.options.UnparseableSections {
-				if f.options.UnparseableSections[i] == name ||
-					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
-					inUnparseableSection = true
-					continue
-				}
-			}
-			continue
-		}
-
-		if inUnparseableSection {
-			section.isRawSection = true
-			section.rawBody += string(line)
-			continue
-		}
-
-		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
-		if err != nil {
-			switch {
-			// Treat as boolean key when desired, and whole line is key name.
-			case IsErrDelimiterNotFound(err):
-				switch {
-				case f.options.AllowBooleanKeys:
-					kname, err := p.readValue(line, parserBufferSize)
-					if err != nil {
-						return err
-					}
-					key, err := section.NewBooleanKey(kname)
-					if err != nil {
-						return err
-					}
-					key.Comment = strings.TrimSpace(p.comment.String())
-					p.comment.Reset()
-					continue
-
-				case f.options.SkipUnrecognizableLines:
-					continue
-				}
-			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines:
-				continue
-			}
-			return err
-		}
-
-		// Auto increment.
-		isAutoIncr := false
-		if kname == "-" {
-			isAutoIncr = true
-			kname = "#" + strconv.Itoa(p.count)
-			p.count++
-		}
-
-		value, err := p.readValue(line[offset:], parserBufferSize)
-		if err != nil {
-			return err
-		}
-		isLastValueEmpty = len(value) == 0
-
-		key, err := section.NewKey(kname, value)
-		if err != nil {
-			return err
-		}
-		key.isAutoIncrement = isAutoIncr
-		key.Comment = strings.TrimSpace(p.comment.String())
-		p.comment.Reset()
-		lastRegularKey = key
-	}
-	return nil
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/section.go b/public-api/vendor/gopkg.in/ini.v1/section.go
deleted file mode 100644
index a3615d82..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/section.go
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"errors"
-	"fmt"
-	"strings"
-)
-
-// Section represents a config section.
-type Section struct {
-	f        *File
-	Comment  string
-	name     string
-	keys     map[string]*Key
-	keyList  []string
-	keysHash map[string]string
-
-	isRawSection bool
-	rawBody      string
-}
-
-func newSection(f *File, name string) *Section {
-	return &Section{
-		f:        f,
-		name:     name,
-		keys:     make(map[string]*Key),
-		keyList:  make([]string, 0, 10),
-		keysHash: make(map[string]string),
-	}
-}
-
-// Name returns name of Section.
-func (s *Section) Name() string {
-	return s.name
-}
-
-// Body returns rawBody of Section if the section was marked as unparseable.
-// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
-func (s *Section) Body() string {
-	return strings.TrimSpace(s.rawBody)
-}
-
-// SetBody updates body content only if section is raw.
-func (s *Section) SetBody(body string) {
-	if !s.isRawSection {
-		return
-	}
-	s.rawBody = body
-}
-
-// NewKey creates a new key to given section.
-func (s *Section) NewKey(name, val string) (*Key, error) {
-	if len(name) == 0 {
-		return nil, errors.New("error creating new key: empty key name")
-	} else if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	if inSlice(name, s.keyList) {
-		if s.f.options.AllowShadows {
-			if err := s.keys[name].addShadow(val); err != nil {
-				return nil, err
-			}
-		} else {
-			s.keys[name].value = val
-			s.keysHash[name] = val
-		}
-		return s.keys[name], nil
-	}
-
-	s.keyList = append(s.keyList, name)
-	s.keys[name] = newKey(s, name, val)
-	s.keysHash[name] = val
-	return s.keys[name], nil
-}
-
-// NewBooleanKey creates a new boolean type key to given section.
-func (s *Section) NewBooleanKey(name string) (*Key, error) {
-	key, err := s.NewKey(name, "true")
-	if err != nil {
-		return nil, err
-	}
-
-	key.isBooleanType = true
-	return key, nil
-}
-
-// GetKey returns key in section by given name.
-func (s *Section) GetKey(name string) (*Key, error) {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-	}
-	if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
-		name = strings.ToLower(name)
-	}
-	key := s.keys[name]
-	if s.f.BlockMode {
-		s.f.lock.RUnlock()
-	}
-
-	if key == nil {
-		// Check if it is a child-section.
-		sname := s.name
-		for {
-			if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-				sname = sname[:i]
-				sec, err := s.f.GetSection(sname)
-				if err != nil {
-					continue
-				}
-				return sec.GetKey(name)
-			}
-			break
-		}
-		return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name)
-	}
-	return key, nil
-}
-
-// HasKey returns true if section contains a key with given name.
-func (s *Section) HasKey(name string) bool {
-	key, _ := s.GetKey(name)
-	return key != nil
-}
-
-// Deprecated: Use "HasKey" instead.
-func (s *Section) Haskey(name string) bool {
-	return s.HasKey(name)
-}
-
-// HasValue returns true if section contains given raw value.
-func (s *Section) HasValue(value string) bool {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	for _, k := range s.keys {
-		if value == k.value {
-			return true
-		}
-	}
-	return false
-}
-
-// Key assumes named Key exists in section and returns a zero-value when not.
-func (s *Section) Key(name string) *Key {
-	key, err := s.GetKey(name)
-	if err != nil {
-		// It's OK here because the only possible error is empty key name,
-		// but if it's empty, this piece of code won't be executed.
-		key, _ = s.NewKey(name, "")
-		return key
-	}
-	return key
-}
-
-// Keys returns list of keys of section.
-func (s *Section) Keys() []*Key {
-	keys := make([]*Key, len(s.keyList))
-	for i := range s.keyList {
-		keys[i] = s.Key(s.keyList[i])
-	}
-	return keys
-}
-
-// ParentKeys returns list of keys of parent section.
-func (s *Section) ParentKeys() []*Key {
-	var parentKeys []*Key
-	sname := s.name
-	for {
-		if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
-			sname = sname[:i]
-			sec, err := s.f.GetSection(sname)
-			if err != nil {
-				continue
-			}
-			parentKeys = append(parentKeys, sec.Keys()...)
-		} else {
-			break
-		}
-
-	}
-	return parentKeys
-}
-
-// KeyStrings returns list of key names of section.
-func (s *Section) KeyStrings() []string {
-	list := make([]string, len(s.keyList))
-	copy(list, s.keyList)
-	return list
-}
-
-// KeysHash returns keys hash consisting of names and values.
-func (s *Section) KeysHash() map[string]string {
-	if s.f.BlockMode {
-		s.f.lock.RLock()
-		defer s.f.lock.RUnlock()
-	}
-
-	hash := make(map[string]string, len(s.keysHash))
-	for key, value := range s.keysHash {
-		hash[key] = value
-	}
-	return hash
-}
-
-// DeleteKey deletes a key from section.
-func (s *Section) DeleteKey(name string) {
-	if s.f.BlockMode {
-		s.f.lock.Lock()
-		defer s.f.lock.Unlock()
-	}
-
-	for i, k := range s.keyList {
-		if k == name {
-			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
-			delete(s.keys, name)
-			delete(s.keysHash, name)
-			return
-		}
-	}
-}
-
-// ChildSections returns a list of child sections of current section.
-// For example, "[parent.child1]" and "[parent.child12]" are child sections
-// of section "[parent]".
-func (s *Section) ChildSections() []*Section {
-	prefix := s.name + s.f.options.ChildSectionDelimiter
-	children := make([]*Section, 0, 3)
-	for _, name := range s.f.sectionList {
-		if strings.HasPrefix(name, prefix) {
-			children = append(children, s.f.sections[name]...)
-		}
-	}
-	return children
-}
diff --git a/public-api/vendor/gopkg.in/ini.v1/struct.go b/public-api/vendor/gopkg.in/ini.v1/struct.go
deleted file mode 100644
index a486b2fe..00000000
--- a/public-api/vendor/gopkg.in/ini.v1/struct.go
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright 2014 Unknwon
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package ini
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"reflect"
-	"strings"
-	"time"
-	"unicode"
-)
-
-// NameMapper represents a ini tag name mapper.
-type NameMapper func(string) string
-
-// Built-in name getters.
-var (
-	// SnackCase converts to format SNACK_CASE.
-	SnackCase NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-			}
-			newstr = append(newstr, unicode.ToUpper(chr))
-		}
-		return string(newstr)
-	}
-	// TitleUnderscore converts to format title_underscore.
-	TitleUnderscore NameMapper = func(raw string) string {
-		newstr := make([]rune, 0, len(raw))
-		for i, chr := range raw {
-			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
-				if i > 0 {
-					newstr = append(newstr, '_')
-				}
-				chr -= 'A' - 'a'
-			}
-			newstr = append(newstr, chr)
-		}
-		return string(newstr)
-	}
-)
-
-func (s *Section) parseFieldName(raw, actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	if s.f.NameMapper != nil {
-		return s.f.NameMapper(raw)
-	}
-	return raw
-}
-
-func parseDelim(actual string) string {
-	if len(actual) > 0 {
-		return actual
-	}
-	return ","
-}
-
-var reflectTime = reflect.TypeOf(time.Now()).Kind()
-
-// setSliceWithProperType sets proper values to slice based on its type.
-func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	var strs []string
-	if allowShadow {
-		strs = key.StringsWithShadows(delim)
-	} else {
-		strs = key.Strings(delim)
-	}
-
-	numVals := len(strs)
-	if numVals == 0 {
-		return nil
-	}
-
-	var vals interface{}
-	var err error
-
-	sliceOf := field.Type().Elem().Kind()
-	switch sliceOf {
-	case reflect.String:
-		vals = strs
-	case reflect.Int:
-		vals, err = key.parseInts(strs, true, false)
-	case reflect.Int64:
-		vals, err = key.parseInt64s(strs, true, false)
-	case reflect.Uint:
-		vals, err = key.parseUints(strs, true, false)
-	case reflect.Uint64:
-		vals, err = key.parseUint64s(strs, true, false)
-	case reflect.Float64:
-		vals, err = key.parseFloat64s(strs, true, false)
-	case reflect.Bool:
-		vals, err = key.parseBools(strs, true, false)
-	case reflectTime:
-		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
-	default:
-		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-	}
-	if err != nil && isStrict {
-		return err
-	}
-
-	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
-	for i := 0; i < numVals; i++ {
-		switch sliceOf {
-		case reflect.String:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
-		case reflect.Int:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
-		case reflect.Int64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
-		case reflect.Uint:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
-		case reflect.Uint64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
-		case reflect.Float64:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
-		case reflect.Bool:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i]))
-		case reflectTime:
-			slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
-		}
-	}
-	field.Set(slice)
-	return nil
-}
-
-func wrapStrictError(err error, isStrict bool) error {
-	if isStrict {
-		return err
-	}
-	return nil
-}
-
-// setWithProperType sets proper value to field based on its type,
-// but it does not return error for failing parsing,
-// because we want to use default value that is already assigned to struct.
-func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
-	vt := t
-	isPtr := t.Kind() == reflect.Ptr
-	if isPtr {
-		vt = t.Elem()
-	}
-	switch vt.Kind() {
-	case reflect.String:
-		stringVal := key.String()
-		if isPtr {
-			field.Set(reflect.ValueOf(&stringVal))
-		} else if len(stringVal) > 0 {
-			field.SetString(key.String())
-		}
-	case reflect.Bool:
-		boolVal, err := key.Bool()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&boolVal))
-		} else {
-			field.SetBool(boolVal)
-		}
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		// ParseDuration will not return err for `0`, so check the type name
-		if vt.Name() == "Duration" {
-			durationVal, err := key.Duration()
-			if err != nil {
-				if intVal, err := key.Int64(); err == nil {
-					field.SetInt(intVal)
-					return nil
-				}
-				return wrapStrictError(err, isStrict)
-			}
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else if int64(durationVal) > 0 {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		intVal, err := key.Int64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetInt(intVal)
-			field.Set(pv)
-		} else {
-			field.SetInt(intVal)
-		}
-	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
-	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		durationVal, err := key.Duration()
-		// Skip zero value
-		if err == nil && uint64(durationVal) > 0 {
-			if isPtr {
-				field.Set(reflect.ValueOf(&durationVal))
-			} else {
-				field.Set(reflect.ValueOf(durationVal))
-			}
-			return nil
-		}
-
-		uintVal, err := key.Uint64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetUint(uintVal)
-			field.Set(pv)
-		} else {
-			field.SetUint(uintVal)
-		}
-
-	case reflect.Float32, reflect.Float64:
-		floatVal, err := key.Float64()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			pv := reflect.New(t.Elem())
-			pv.Elem().SetFloat(floatVal)
-			field.Set(pv)
-		} else {
-			field.SetFloat(floatVal)
-		}
-	case reflectTime:
-		timeVal, err := key.Time()
-		if err != nil {
-			return wrapStrictError(err, isStrict)
-		}
-		if isPtr {
-			field.Set(reflect.ValueOf(&timeVal))
-		} else {
-			field.Set(reflect.ValueOf(timeVal))
-		}
-	case reflect.Slice:
-		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) {
-	opts := strings.SplitN(tag, ",", 5)
-	rawName = opts[0]
-	for _, opt := range opts[1:] {
-		omitEmpty = omitEmpty || (opt == "omitempty")
-		allowShadow = allowShadow || (opt == "allowshadow")
-		allowNonUnique = allowNonUnique || (opt == "nonunique")
-		extends = extends || (opt == "extends")
-	}
-	return rawName, omitEmpty, allowShadow, allowNonUnique, extends
-}
-
-// mapToField maps the given value to the matching field of the given section.
-// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
-func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		isStruct := tpField.Type.Kind() == reflect.Struct
-		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
-		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
-		if isAnonymousPtr {
-			field.Set(reflect.New(tpField.Type.Elem()))
-		}
-
-		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) {
-			if isStructPtr && field.IsNil() {
-				field.Set(reflect.New(tpField.Type.Elem()))
-			}
-			fieldSection := s
-			if rawName != "" {
-				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName
-				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) {
-					fieldSection = secs[sectionIndex]
-				}
-			}
-			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil {
-				return fmt.Errorf("map to field %q: %v", fieldName, err)
-			}
-		} else if isAnonymousPtr || isStruct || isStructPtr {
-			if secs, err := s.f.SectionsByName(fieldName); err == nil {
-				if len(secs) <= sectionIndex {
-					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
-				}
-				// Only set the field to non-nil struct value if we have a section for it.
-				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
-				if isStructPtr && field.IsNil() {
-					field.Set(reflect.New(tpField.Type.Elem()))
-				}
-				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil {
-					return fmt.Errorf("map to field %q: %v", fieldName, err)
-				}
-				continue
-			}
-		}
-
-		// Map non-unique sections
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			newField, err := s.mapToSlice(fieldName, field, isStrict)
-			if err != nil {
-				return fmt.Errorf("map to slice %q: %v", fieldName, err)
-			}
-
-			field.Set(newField)
-			continue
-		}
-
-		if key, err := s.GetKey(fieldName); err == nil {
-			delim := parseDelim(tpField.Tag.Get("delim"))
-			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
-				return fmt.Errorf("set field %q: %v", fieldName, err)
-			}
-		}
-	}
-	return nil
-}
-
-// mapToSlice maps all sections with the same name and returns the new value.
-// The type of the Value must be a slice.
-func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
-	secs, err := s.f.SectionsByName(secName)
-	if err != nil {
-		return reflect.Value{}, err
-	}
-
-	typ := val.Type().Elem()
-	for i, sec := range secs {
-		elem := reflect.New(typ)
-		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
-			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
-		}
-
-		val = reflect.Append(val, elem.Elem())
-	}
-	return val, nil
-}
-
-// mapTo maps a section to object v.
-func (s *Section) mapTo(v interface{}, isStrict bool) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-	if typ.Kind() == reflect.Ptr {
-		typ = typ.Elem()
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	if typ.Kind() == reflect.Slice {
-		newField, err := s.mapToSlice(s.name, val, isStrict)
-		if err != nil {
-			return err
-		}
-
-		val.Set(newField)
-		return nil
-	}
-
-	return s.mapToField(val, isStrict, 0, s.name)
-}
-
-// MapTo maps section to given struct.
-func (s *Section) MapTo(v interface{}) error {
-	return s.mapTo(v, false)
-}
-
-// StrictMapTo maps section to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (s *Section) StrictMapTo(v interface{}) error {
-	return s.mapTo(v, true)
-}
-
-// MapTo maps file to given struct.
-func (f *File) MapTo(v interface{}) error {
-	return f.Section("").MapTo(v)
-}
-
-// StrictMapTo maps file to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func (f *File) StrictMapTo(v interface{}) error {
-	return f.Section("").StrictMapTo(v)
-}
-
-// MapToWithMapper maps data sources to given struct with name mapper.
-func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.MapTo(v)
-}
-
-// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
-	cfg, err := Load(source, others...)
-	if err != nil {
-		return err
-	}
-	cfg.NameMapper = mapper
-	return cfg.StrictMapTo(v)
-}
-
-// MapTo maps data sources to given struct.
-func MapTo(v, source interface{}, others ...interface{}) error {
-	return MapToWithMapper(v, nil, source, others...)
-}
-
-// StrictMapTo maps data sources to given struct in strict mode,
-// which returns all possible error including value parsing error.
-func StrictMapTo(v, source interface{}, others ...interface{}) error {
-	return StrictMapToWithMapper(v, nil, source, others...)
-}
-
-// reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
-func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	slice := field.Slice(0, field.Len())
-	if field.Len() == 0 {
-		return nil
-	}
-	sliceOf := field.Type().Elem().Kind()
-
-	if allowShadow {
-		var keyWithShadows *Key
-		for i := 0; i < field.Len(); i++ {
-			var val string
-			switch sliceOf {
-			case reflect.String:
-				val = slice.Index(i).String()
-			case reflect.Int, reflect.Int64:
-				val = fmt.Sprint(slice.Index(i).Int())
-			case reflect.Uint, reflect.Uint64:
-				val = fmt.Sprint(slice.Index(i).Uint())
-			case reflect.Float64:
-				val = fmt.Sprint(slice.Index(i).Float())
-			case reflect.Bool:
-				val = fmt.Sprint(slice.Index(i).Bool())
-			case reflectTime:
-				val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
-			default:
-				return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-			}
-
-			if i == 0 {
-				keyWithShadows = newKey(key.s, key.name, val)
-			} else {
-				_ = keyWithShadows.AddShadow(val)
-			}
-		}
-		*key = *keyWithShadows
-		return nil
-	}
-
-	var buf bytes.Buffer
-	for i := 0; i < field.Len(); i++ {
-		switch sliceOf {
-		case reflect.String:
-			buf.WriteString(slice.Index(i).String())
-		case reflect.Int, reflect.Int64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
-		case reflect.Uint, reflect.Uint64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
-		case reflect.Float64:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
-		case reflect.Bool:
-			buf.WriteString(fmt.Sprint(slice.Index(i).Bool()))
-		case reflectTime:
-			buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
-		default:
-			return fmt.Errorf("unsupported type '[]%s'", sliceOf)
-		}
-		buf.WriteString(delim)
-	}
-	key.SetValue(buf.String()[:buf.Len()-len(delim)])
-	return nil
-}
-
-// reflectWithProperType does the opposite thing as setWithProperType.
-func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
-	switch t.Kind() {
-	case reflect.String:
-		key.SetValue(field.String())
-	case reflect.Bool:
-		key.SetValue(fmt.Sprint(field.Bool()))
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		key.SetValue(fmt.Sprint(field.Int()))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		key.SetValue(fmt.Sprint(field.Uint()))
-	case reflect.Float32, reflect.Float64:
-		key.SetValue(fmt.Sprint(field.Float()))
-	case reflectTime:
-		key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
-	case reflect.Slice:
-		return reflectSliceWithProperType(key, field, delim, allowShadow)
-	case reflect.Ptr:
-		if !field.IsNil() {
-			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
-		}
-	default:
-		return fmt.Errorf("unsupported type %q", t)
-	}
-	return nil
-}
-
-// CR: copied from encoding/json/encode.go with modifications of time.Time support.
-// TODO: add more test coverage.
-func isEmptyValue(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	case reflectTime:
-		t, ok := v.Interface().(time.Time)
-		return ok && t.IsZero()
-	}
-	return false
-}
-
-// StructReflector is the interface implemented by struct types that can extract themselves into INI objects.
-type StructReflector interface {
-	ReflectINIStruct(*File) error
-}
-
-func (s *Section) reflectFrom(val reflect.Value) error {
-	if val.Kind() == reflect.Ptr {
-		val = val.Elem()
-	}
-	typ := val.Type()
-
-	for i := 0; i < typ.NumField(); i++ {
-		if !val.Field(i).CanInterface() {
-			continue
-		}
-
-		field := val.Field(i)
-		tpField := typ.Field(i)
-
-		tag := tpField.Tag.Get("ini")
-		if tag == "-" {
-			continue
-		}
-
-		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
-		if omitEmpty && isEmptyValue(field) {
-			continue
-		}
-
-		if r, ok := field.Interface().(StructReflector); ok {
-			return r.ReflectINIStruct(s.f)
-		}
-
-		fieldName := s.parseFieldName(tpField.Name, rawName)
-		if len(fieldName) == 0 || !field.CanSet() {
-			continue
-		}
-
-		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
-			if err := s.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
-			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
-			// Note: The only error here is section doesn't exist.
-			sec, err := s.f.GetSection(fieldName)
-			if err != nil {
-				// Note: fieldName can never be empty here, ignore error.
-				sec, _ = s.f.NewSection(fieldName)
-			}
-
-			// Add comment from comment tag
-			if len(sec.Comment) == 0 {
-				sec.Comment = tpField.Tag.Get("comment")
-			}
-
-			if err = sec.reflectFrom(field); err != nil {
-				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-			}
-			continue
-		}
-
-		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
-			slice := field.Slice(0, field.Len())
-			if field.Len() == 0 {
-				return nil
-			}
-			sliceOf := field.Type().Elem().Kind()
-
-			for i := 0; i < field.Len(); i++ {
-				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
-					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
-				}
-
-				sec, err := s.f.NewSection(fieldName)
-				if err != nil {
-					return err
-				}
-
-				// Add comment from comment tag
-				if len(sec.Comment) == 0 {
-					sec.Comment = tpField.Tag.Get("comment")
-				}
-
-				if err := sec.reflectFrom(slice.Index(i)); err != nil {
-					return fmt.Errorf("reflect from field %q: %v", fieldName, err)
-				}
-			}
-			continue
-		}
-
-		// Note: Same reason as section.
-		key, err := s.GetKey(fieldName)
-		if err != nil {
-			key, _ = s.NewKey(fieldName, "")
-		}
-
-		// Add comment from comment tag
-		if len(key.Comment) == 0 {
-			key.Comment = tpField.Tag.Get("comment")
-		}
-
-		delim := parseDelim(tpField.Tag.Get("delim"))
-		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
-			return fmt.Errorf("reflect field %q: %v", fieldName, err)
-		}
-
-	}
-	return nil
-}
-
-// ReflectFrom reflects section from given struct. It overwrites existing ones.
-func (s *Section) ReflectFrom(v interface{}) error {
-	typ := reflect.TypeOf(v)
-	val := reflect.ValueOf(v)
-
-	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
-		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
-		// Clear sections to make sure none exists before adding the new ones
-		s.f.DeleteSection(s.name)
-
-		if typ.Kind() == reflect.Ptr {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-			return sec.reflectFrom(val.Elem())
-		}
-
-		slice := val.Slice(0, val.Len())
-		sliceOf := val.Type().Elem().Kind()
-		if sliceOf != reflect.Ptr {
-			return fmt.Errorf("not a slice of pointers")
-		}
-
-		for i := 0; i < slice.Len(); i++ {
-			sec, err := s.f.NewSection(s.name)
-			if err != nil {
-				return err
-			}
-
-			err = sec.reflectFrom(slice.Index(i))
-			if err != nil {
-				return fmt.Errorf("reflect from %dth field: %v", i, err)
-			}
-		}
-
-		return nil
-	}
-
-	if typ.Kind() == reflect.Ptr {
-		val = val.Elem()
-	} else {
-		return errors.New("not a pointer to a struct")
-	}
-
-	return s.reflectFrom(val)
-}
-
-// ReflectFrom reflects file from given struct.
-func (f *File) ReflectFrom(v interface{}) error {
-	return f.Section("").ReflectFrom(v)
-}
-
-// ReflectFromWithMapper reflects data sources from given struct with name mapper.
-func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
-	cfg.NameMapper = mapper
-	return cfg.ReflectFrom(v)
-}
-
-// ReflectFrom reflects data sources from given struct.
-func ReflectFrom(cfg *File, v interface{}) error {
-	return ReflectFromWithMapper(cfg, v, nil)
-}
diff --git a/public-api/vendor/gorm.io/gorm/association.go b/public-api/vendor/gorm.io/gorm/association.go
index e3f51d17..f210ca0a 100644
--- a/public-api/vendor/gorm.io/gorm/association.go
+++ b/public-api/vendor/gorm.io/gorm/association.go
@@ -19,10 +19,10 @@ type Association struct {
 }
 
 func (db *DB) Association(column string) *Association {
-	association := &Association{DB: db}
+	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
 	table := db.Statement.Table
 
-	if err := db.Statement.Parse(db.Statement.Model); err == nil {
+	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
 		db.Statement.Table = table
 		association.Relationship = db.Statement.Schema.Relationships.Relations[column]
 
@@ -34,8 +34,6 @@ func (db *DB) Association(column string) *Association {
 		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
 			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
 		}
-	} else {
-		association.Error = err
 	}
 
 	return association
@@ -58,6 +56,8 @@ func (association *Association) Find(out interface{}, conds ...interface{}) erro
 }
 
 func (association *Association) Append(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		switch association.Relationship.Type {
 		case schema.HasOne, schema.BelongsTo:
@@ -73,6 +73,8 @@ func (association *Association) Append(values ...interface{}) error {
 }
 
 func (association *Association) Replace(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		reflectValue := association.DB.Statement.ReflectValue
 		rel := association.Relationship
@@ -195,6 +197,8 @@ func (association *Association) Replace(values ...interface{}) error {
 }
 
 func (association *Association) Delete(values ...interface{}) error {
+	values = expandValues(values)
+
 	if association.Error == nil {
 		var (
 			reflectValue  = association.DB.Statement.ReflectValue
@@ -431,10 +435,49 @@ func (association *Association) saveAssociation(clear bool, values ...interface{
 				}
 			}
 
+			processMap := func(mapv reflect.Value) {
+				child := reflect.New(association.Relationship.FieldSchema.ModelType)
+
+				switch association.Relationship.Type {
+				case schema.HasMany:
+					for _, ref := range association.Relationship.References {
+						key := reflect.ValueOf(ref.ForeignKey.DBName)
+						if ref.OwnPrimaryKey {
+							v := ref.PrimaryKey.ReflectValueOf(association.DB.Statement.Context, source)
+							mapv.SetMapIndex(key, v)
+						} else if ref.PrimaryValue != "" {
+							mapv.SetMapIndex(key, reflect.ValueOf(ref.PrimaryValue))
+						}
+					}
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+				case schema.Many2Many:
+					association.Error = association.DB.Session(&Session{
+						NewDB: true,
+					}).Model(child.Interface()).Create(mapv.Interface()).Error
+
+					for _, key := range mapv.MapKeys() {
+						k := strings.ToLower(key.String())
+						if f, ok := association.Relationship.FieldSchema.FieldsByDBName[k]; ok {
+							_ = f.Set(association.DB.Statement.Context, child, mapv.MapIndex(key).Interface())
+						}
+					}
+					appendToFieldValues(child)
+				}
+			}
+
 			switch rv.Kind() {
+			case reflect.Map:
+				processMap(rv)
 			case reflect.Slice, reflect.Array:
 				for i := 0; i < rv.Len(); i++ {
-					appendToFieldValues(reflect.Indirect(rv.Index(i)).Addr())
+					elem := reflect.Indirect(rv.Index(i))
+					if elem.Kind() == reflect.Map {
+						processMap(elem)
+						continue
+					}
+					appendToFieldValues(elem.Addr())
 				}
 			case reflect.Struct:
 				if !rv.CanAddr() {
@@ -591,3 +634,32 @@ func (association *Association) buildCondition() *DB {
 
 	return tx
 }
+
+func expandValues(values ...any) (results []any) {
+	appendToResult := func(rv reflect.Value) {
+		// unwrap interface
+		if rv.IsValid() && rv.Kind() == reflect.Interface {
+			rv = rv.Elem()
+		}
+		if rv.IsValid() && rv.Kind() == reflect.Struct {
+			p := reflect.New(rv.Type())
+			p.Elem().Set(rv)
+			results = append(results, p.Interface())
+		} else if rv.IsValid() {
+			results = append(results, rv.Interface())
+		}
+	}
+
+	// Process each argument; if an argument is a slice/array, expand its elements
+	for _, value := range values {
+		rv := reflect.ValueOf(value)
+		if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array {
+			for i := 0; i < rv.Len(); i++ {
+				appendToResult(rv.Index(i))
+			}
+		} else {
+			appendToResult(rv)
+		}
+	}
+	return
+}
diff --git a/public-api/vendor/gorm.io/gorm/callbacks.go b/public-api/vendor/gorm.io/gorm/callbacks.go
index 50b5b0e9..bd97f040 100644
--- a/public-api/vendor/gorm.io/gorm/callbacks.go
+++ b/public-api/vendor/gorm.io/gorm/callbacks.go
@@ -89,10 +89,16 @@ func (p *processor) Execute(db *DB) *DB {
 		resetBuildClauses = true
 	}
 
-	if optimizer, ok := db.Statement.Dest.(StatementModifier); ok {
+	if optimizer, ok := stmt.Dest.(StatementModifier); ok {
 		optimizer.ModifyStatement(stmt)
 	}
 
+	if db.DefaultContextTimeout > 0 {
+		if _, ok := stmt.Context.Deadline(); !ok {
+			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
+		}
+	}
+
 	// assign model values
 	if stmt.Model == nil {
 		stmt.Model = stmt.Dest
diff --git a/public-api/vendor/gorm.io/gorm/callbacks/create.go b/public-api/vendor/gorm.io/gorm/callbacks/create.go
index d8701f51..e5929adb 100644
--- a/public-api/vendor/gorm.io/gorm/callbacks/create.go
+++ b/public-api/vendor/gorm.io/gorm/callbacks/create.go
@@ -53,9 +53,13 @@ func Create(config *Config) func(db *gorm.DB) {
 				if _, ok := db.Statement.Clauses["RETURNING"]; !ok {
 					fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue))
 					for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue {
-						fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						if field.Readable {
+							fromColumns = append(fromColumns, clause.Column{Name: field.DBName})
+						}
+					}
+					if len(fromColumns) > 0 {
+						db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 					}
-					db.Statement.AddClause(clause.Returning{Columns: fromColumns})
 				}
 			}
 		}
@@ -76,8 +80,11 @@ func Create(config *Config) func(db *gorm.DB) {
 		ok, mode := hasReturning(db, supportReturning)
 		if ok {
 			if c, ok := db.Statement.Clauses["ON CONFLICT"]; ok {
-				if onConflict, _ := c.Expression.(clause.OnConflict); onConflict.DoNothing {
+				onConflict, _ := c.Expression.(clause.OnConflict)
+				if onConflict.DoNothing {
 					mode |= gorm.ScanOnConflictDoNothing
+				} else if len(onConflict.DoUpdates) > 0 || onConflict.UpdateAll {
+					mode |= gorm.ScanUpdate
 				}
 			}
 
@@ -122,6 +129,16 @@ func Create(config *Config) func(db *gorm.DB) {
 			pkFieldName = "@id"
 		)
 
+		if db.Statement.Schema != nil {
+			if db.Statement.Schema.PrioritizedPrimaryField == nil ||
+				!db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue ||
+				!db.Statement.Schema.PrioritizedPrimaryField.Readable {
+				return
+			}
+			pkField = db.Statement.Schema.PrioritizedPrimaryField
+			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
+		}
+
 		insertID, err := result.LastInsertId()
 		insertOk := err == nil && insertID > 0
 
@@ -132,14 +149,6 @@ func Create(config *Config) func(db *gorm.DB) {
 			return
 		}
 
-		if db.Statement.Schema != nil {
-			if db.Statement.Schema.PrioritizedPrimaryField == nil || !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue {
-				return
-			}
-			pkField = db.Statement.Schema.PrioritizedPrimaryField
-			pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName
-		}
-
 		// append @id column with value for auto-increment primary key
 		// the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1
 		switch values := db.Statement.Dest.(type) {
diff --git a/public-api/vendor/gorm.io/gorm/clause/association.go b/public-api/vendor/gorm.io/gorm/clause/association.go
new file mode 100644
index 00000000..a9bf7eb0
--- /dev/null
+++ b/public-api/vendor/gorm.io/gorm/clause/association.go
@@ -0,0 +1,35 @@
+package clause
+
+// AssociationOpType represents association operation types
+type AssociationOpType int
+
+const (
+	OpUnlink AssociationOpType = iota // Unlink association
+	OpDelete                          // Delete association records
+	OpUpdate                          // Update association records
+	OpCreate                          // Create association records with assignments
+)
+
+// Association represents an association operation
+type Association struct {
+	Association string            // Association name
+	Type        AssociationOpType // Operation type
+	Conditions  []Expression      // Filter conditions
+	Set         []Assignment      // Assignment operations (for Update and Create)
+	Values      []interface{}     // Values for Create operation
+}
+
+// AssociationAssigner is an interface for association operation providers
+type AssociationAssigner interface {
+	AssociationAssignments() []Association
+}
+
+// Assignments implements the Assigner interface so that AssociationOperation can be used as a Set method parameter
+func (ao Association) Assignments() []Assignment {
+	return []Assignment{}
+}
+
+// AssociationAssignments implements the AssociationAssigner interface
+func (ao Association) AssociationAssignments() []Association {
+	return []Association{ao}
+}
diff --git a/public-api/vendor/gorm.io/gorm/clause/set.go b/public-api/vendor/gorm.io/gorm/clause/set.go
index 75eb6bdd..cb5f36a0 100644
--- a/public-api/vendor/gorm.io/gorm/clause/set.go
+++ b/public-api/vendor/gorm.io/gorm/clause/set.go
@@ -9,6 +9,11 @@ type Assignment struct {
 	Value  interface{}
 }
 
+// Assigner assignments provider interface
+type Assigner interface {
+	Assignments() []Assignment
+}
+
 func (set Set) Name() string {
 	return "SET"
 }
@@ -37,6 +42,9 @@ func (set Set) MergeClause(clause *Clause) {
 	clause.Expression = Set(copiedAssignments)
 }
 
+// Assignments implements Assigner for Set.
+func (set Set) Assignments() []Assignment { return []Assignment(set) }
+
 func Assignments(values map[string]interface{}) Set {
 	keys := make([]string, 0, len(values))
 	for key := range values {
@@ -58,3 +66,6 @@ func AssignmentColumns(values []string) Set {
 	}
 	return assignments
 }
+
+// Assignments implements Assigner for a single Assignment.
+func (a Assignment) Assignments() []Assignment { return []Assignment{a} }
diff --git a/public-api/vendor/gorm.io/gorm/finisher_api.go b/public-api/vendor/gorm.io/gorm/finisher_api.go
index 57809d17..e601fe66 100644
--- a/public-api/vendor/gorm.io/gorm/finisher_api.go
+++ b/public-api/vendor/gorm.io/gorm/finisher_api.go
@@ -675,9 +675,9 @@ func (db *DB) Begin(opts ...*sql.TxOptions) *DB {
 	}
 
 	ctx := tx.Statement.Context
-	if _, ok := ctx.Deadline(); !ok {
-		if db.Config.DefaultTransactionTimeout > 0 {
-			ctx, _ = context.WithTimeout(ctx, db.Config.DefaultTransactionTimeout)
+	if db.DefaultTransactionTimeout > 0 {
+		if _, ok := ctx.Deadline(); !ok {
+			ctx, _ = context.WithTimeout(ctx, db.DefaultTransactionTimeout)
 		}
 	}
 
diff --git a/public-api/vendor/gorm.io/gorm/generics.go b/public-api/vendor/gorm.io/gorm/generics.go
index ad2d063f..79238d5f 100644
--- a/public-api/vendor/gorm.io/gorm/generics.go
+++ b/public-api/vendor/gorm.io/gorm/generics.go
@@ -3,12 +3,15 @@ package gorm
 import (
 	"context"
 	"database/sql"
+	"errors"
 	"fmt"
+	"reflect"
 	"sort"
 	"strings"
 
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/logger"
+	"gorm.io/gorm/schema"
 )
 
 type result struct {
@@ -35,10 +38,34 @@ type Interface[T any] interface {
 }
 
 type CreateInterface[T any] interface {
-	ChainInterface[T]
+	ExecInterface[T]
+	// chain methods available at start; return ChainInterface
+	Scopes(scopes ...func(db *Statement)) ChainInterface[T]
+	Where(query interface{}, args ...interface{}) ChainInterface[T]
+	Not(query interface{}, args ...interface{}) ChainInterface[T]
+	Or(query interface{}, args ...interface{}) ChainInterface[T]
+	Limit(offset int) ChainInterface[T]
+	Offset(offset int) ChainInterface[T]
+	Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[T]
+	Preload(association string, query func(db PreloadBuilder) error) ChainInterface[T]
+	Select(query string, args ...interface{}) ChainInterface[T]
+	Omit(columns ...string) ChainInterface[T]
+	MapColumns(m map[string]string) ChainInterface[T]
+	Distinct(args ...interface{}) ChainInterface[T]
+	Group(name string) ChainInterface[T]
+	Having(query interface{}, args ...interface{}) ChainInterface[T]
+	Order(value interface{}) ChainInterface[T]
+	Build(builder clause.Builder)
+
+	Delete(ctx context.Context) (rowsAffected int, err error)
+	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
+	Updates(ctx context.Context, t T) (rowsAffected int, err error)
+	Count(ctx context.Context, column string) (result int64, err error)
+
 	Table(name string, args ...interface{}) CreateInterface[T]
 	Create(ctx context.Context, r *T) error
 	CreateInBatches(ctx context.Context, r *[]T, batchSize int) error
+	Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T]
 }
 
 type ChainInterface[T any] interface {
@@ -58,15 +85,28 @@ type ChainInterface[T any] interface {
 	Group(name string) ChainInterface[T]
 	Having(query interface{}, args ...interface{}) ChainInterface[T]
 	Order(value interface{}) ChainInterface[T]
+	Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T]
 
 	Build(builder clause.Builder)
 
+	Table(name string, args ...interface{}) ChainInterface[T]
 	Delete(ctx context.Context) (rowsAffected int, err error)
 	Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
 	Updates(ctx context.Context, t T) (rowsAffected int, err error)
 	Count(ctx context.Context, column string) (result int64, err error)
 }
 
+// SetUpdateOnlyInterface is returned by Set after chaining; only Update is allowed
+type SetUpdateOnlyInterface[T any] interface {
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
+// SetCreateOrUpdateInterface is returned by Set at start; Create or Update are allowed
+type SetCreateOrUpdateInterface[T any] interface {
+	Create(ctx context.Context) error
+	Update(ctx context.Context) (rowsAffected int, err error)
+}
+
 type ExecInterface[T any] interface {
 	Scan(ctx context.Context, r interface{}) error
 	First(context.Context) (T, error)
@@ -142,13 +182,15 @@ func (c *g[T]) Raw(sql string, values ...interface{}) ExecInterface[T] {
 	return execG[T]{g: &g[T]{
 		db: c.db,
 		ops: append(c.ops, func(db *DB) *DB {
-			return db.Raw(sql, values...)
+			var r T
+			return db.Model(r).Raw(sql, values...)
 		}),
 	}}
 }
 
 func (c *g[T]) Exec(ctx context.Context, sql string, values ...interface{}) error {
-	return c.apply(ctx).Exec(sql, values...).Error
+	var r T
+	return c.apply(ctx).Model(r).Exec(sql, values...).Error
 }
 
 type createG[T any] struct {
@@ -161,6 +203,10 @@ func (c createG[T]) Table(name string, args ...interface{}) CreateInterface[T] {
 	})}
 }
 
+func (c createG[T]) Set(assignments ...clause.Assigner) SetCreateOrUpdateInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c createG[T]) Create(ctx context.Context, r *T) error {
 	return c.g.apply(ctx).Create(r).Error
 }
@@ -187,6 +233,12 @@ func (c chainG[T]) with(v op) chainG[T] {
 	}
 }
 
+func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
+	return c.with(func(db *DB) *DB {
+		return db.Table(name, args...)
+	})
+}
+
 func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		for _, fc := range scopes {
@@ -196,12 +248,6 @@ func (c chainG[T]) Scopes(scopes ...func(db *Statement)) ChainInterface[T] {
 	})
 }
 
-func (c chainG[T]) Table(name string, args ...interface{}) ChainInterface[T] {
-	return c.with(func(db *DB) *DB {
-		return db.Table(name, args...)
-	})
-}
-
 func (c chainG[T]) Where(query interface{}, args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Where(query, args...)
@@ -388,6 +434,10 @@ func (c chainG[T]) MapColumns(m map[string]string) ChainInterface[T] {
 	})
 }
 
+func (c chainG[T]) Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T] {
+	return c.processSet(assignments...)
+}
+
 func (c chainG[T]) Distinct(args ...interface{}) ChainInterface[T] {
 	return c.with(func(db *DB) *DB {
 		return db.Distinct(args...)
@@ -425,12 +475,12 @@ func (c chainG[T]) Preload(association string, query func(db PreloadBuilder) err
 			relation, ok := db.Statement.Schema.Relationships.Relations[association]
 			if !ok {
 				if preloadFields := strings.Split(association, "."); len(preloadFields) > 1 {
-					relationships := db.Statement.Schema.Relationships
+					relationships := &db.Statement.Schema.Relationships
 					for _, field := range preloadFields {
 						var ok bool
 						relation, ok = relationships.Relations[field]
 						if ok {
-							relationships = relation.FieldSchema.Relationships
+							relationships = &relation.FieldSchema.Relationships
 						} else {
 							db.AddError(fmt.Errorf("relation %s not found", association))
 							return nil
@@ -567,7 +617,7 @@ func (g execG[T]) First(ctx context.Context) (T, error) {
 
 func (g execG[T]) Scan(ctx context.Context, result interface{}) error {
 	var r T
-	err := g.g.apply(ctx).Model(r).Find(&result).Error
+	err := g.g.apply(ctx).Model(r).Find(result).Error
 	return err
 }
 
@@ -603,3 +653,242 @@ func (g execG[T]) Row(ctx context.Context) *sql.Row {
 func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) {
 	return g.g.apply(ctx).Rows()
 }
+
+func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdateG[T] {
+	var (
+		assigns  []clause.Assignment
+		assocOps []clause.Association
+	)
+
+	for _, item := range items {
+		// Check if it's an AssociationAssigner
+		if assocAssigner, ok := item.(clause.AssociationAssigner); ok {
+			assocOps = append(assocOps, assocAssigner.AssociationAssignments()...)
+		} else {
+			assigns = append(assigns, item.Assignments()...)
+		}
+	}
+
+	return setCreateOrUpdateG[T]{
+		c:        c,
+		assigns:  assigns,
+		assocOps: assocOps,
+	}
+}
+
+// setCreateOrUpdateG[T] is a struct that holds operations to be executed in a batch.
+// It supports regular assignments and association operations.
+type setCreateOrUpdateG[T any] struct {
+	c        chainG[T]
+	assigns  []clause.Assignment
+	assocOps []clause.Association
+}
+
+func (s setCreateOrUpdateG[T]) Update(ctx context.Context) (rowsAffected int, err error) {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return 0, err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		var r T
+		res := s.c.g.apply(ctx).Model(r).Clauses(clause.Set(s.assigns)).Updates(map[string]interface{}{})
+		return int(res.RowsAffected), res.Error
+	}
+
+	return 0, nil
+}
+
+func (s setCreateOrUpdateG[T]) Create(ctx context.Context) error {
+	// Execute association operations
+	for _, assocOp := range s.assocOps {
+		if err := s.executeAssociationOperation(ctx, assocOp); err != nil {
+			return err
+		}
+	}
+
+	// Execute assignment operations
+	if len(s.assigns) > 0 {
+		data := make(map[string]interface{}, len(s.assigns))
+		for _, a := range s.assigns {
+			data[a.Column.Name] = a.Value
+		}
+		var r T
+		return s.c.g.apply(ctx).Model(r).Create(data).Error
+	}
+
+	return nil
+}
+
+// executeAssociationOperation executes an association operation
+func (s setCreateOrUpdateG[T]) executeAssociationOperation(ctx context.Context, op clause.Association) error {
+	var r T
+	base := s.c.g.apply(ctx).Model(r)
+
+	switch op.Type {
+	case clause.OpCreate:
+		return s.handleAssociationCreate(ctx, base, op)
+	case clause.OpUnlink, clause.OpDelete, clause.OpUpdate:
+		return s.handleAssociation(ctx, base, op)
+	default:
+		return fmt.Errorf("unknown association operation type: %v", op.Type)
+	}
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociationCreate(ctx context.Context, base *DB, op clause.Association) error {
+	if len(op.Set) > 0 {
+		return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+			data := make(map[string]interface{}, len(op.Set))
+			for _, a := range op.Set {
+				data[a.Column.Name] = a.Value
+			}
+			return assoc.Append(data)
+		}, op.Association)
+	}
+
+	return s.handleAssociationForOwners(base, ctx, func(owner T, assoc *Association) error {
+		return assoc.Append(op.Values...)
+	}, op.Association)
+}
+
+// handleAssociationForOwners is a helper function that handles associations for all owners
+func (s setCreateOrUpdateG[T]) handleAssociationForOwners(base *DB, ctx context.Context, handler func(owner T, association *Association) error, associationName string) error {
+	var owners []T
+	if err := base.Find(&owners).Error; err != nil {
+		return err
+	}
+
+	for _, owner := range owners {
+		assoc := base.Session(&Session{NewDB: true, Context: ctx}).Model(&owner).Association(associationName)
+		if assoc.Error != nil {
+			return assoc.Error
+		}
+
+		if err := handler(owner, assoc); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, base *DB, op clause.Association) error {
+	assoc := base.Association(op.Association)
+	if assoc.Error != nil {
+		return assoc.Error
+	}
+
+	var (
+		rel            = assoc.Relationship
+		assocModel     = reflect.New(rel.FieldSchema.ModelType).Interface()
+		fkNil          = map[string]any{}
+		setMap         = make(map[string]any, len(op.Set))
+		ownerPKNames   []string
+		ownerFKNames   []string
+		primaryColumns []any
+		foreignColumns []any
+	)
+
+	for _, a := range op.Set {
+		setMap[a.Column.Name] = a.Value
+	}
+
+	for _, ref := range rel.References {
+		fkNil[ref.ForeignKey.DBName] = nil
+
+		if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerPKNames = append(ownerPKNames, ref.PrimaryKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+			foreignColumns = append(foreignColumns, clause.Column{Name: ref.ForeignKey.DBName})
+		} else if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+			ownerFKNames = append(ownerFKNames, ref.ForeignKey.DBName)
+			primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName})
+		}
+	}
+
+	assocDB := s.c.g.db.Session(&Session{NewDB: true, Context: ctx}).Model(assocModel).Where(op.Conditions)
+
+	switch rel.Type {
+	case schema.HasOne, schema.HasMany:
+		assocDB = assocDB.Where("? IN (?)", foreignColumns, base.Select(ownerPKNames))
+		switch op.Type {
+		case clause.OpUnlink:
+			return assocDB.Updates(fkNil).Error
+		case clause.OpDelete:
+			return assocDB.Delete(assocModel).Error
+		case clause.OpUpdate:
+			return assocDB.Updates(setMap).Error
+		}
+	case schema.BelongsTo:
+		switch op.Type {
+		case clause.OpDelete:
+			return base.Transaction(func(tx *DB) error {
+				assocDB.Statement.ConnPool = tx.Statement.ConnPool
+				base.Statement.ConnPool = tx.Statement.ConnPool
+
+				if err := assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Delete(assocModel).Error; err != nil {
+					return err
+				}
+				return base.Updates(fkNil).Error
+			})
+		case clause.OpUnlink:
+			return base.Updates(fkNil).Error
+		case clause.OpUpdate:
+			return assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Updates(setMap).Error
+		}
+	case schema.Many2Many:
+		joinModel := reflect.New(rel.JoinTable.ModelType).Interface()
+		joinDB := base.Session(&Session{NewDB: true, Context: ctx}).Model(joinModel)
+
+		// EXISTS owners: owners.pk = join.owner_fk for all owner refs
+		ownersExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.Schema.Table).Select("1")
+		for _, ref := range rel.References {
+			if ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				ownersExists = ownersExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.Schema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+
+		// EXISTS related: related.pk = join.rel_fk for all related refs, plus optional conditions
+		relatedExists := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Select("1")
+		for _, ref := range rel.References {
+			if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+				relatedExists = relatedExists.Where(clause.Eq{
+					Column: clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					Value:  clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+				})
+			}
+		}
+		relatedExists = relatedExists.Where(op.Conditions)
+
+		switch op.Type {
+		case clause.OpUnlink, clause.OpDelete:
+			joinDB = joinDB.Where("EXISTS (?)", ownersExists)
+			if len(op.Conditions) > 0 {
+				joinDB = joinDB.Where("EXISTS (?)", relatedExists)
+			}
+			return joinDB.Delete(nil).Error
+		case clause.OpUpdate:
+			// Update related table rows that have join rows matching owners
+			relatedDB := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.FieldSchema.Table).Where(op.Conditions)
+
+			// correlated join subquery: join.rel_fk = related.pk AND EXISTS owners
+			joinSub := base.Session(&Session{NewDB: true, Context: ctx}).Table(rel.JoinTable.Table).Select("1")
+			for _, ref := range rel.References {
+				if !ref.OwnPrimaryKey && ref.PrimaryKey != nil {
+					joinSub = joinSub.Where(clause.Eq{
+						Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
+						Value:  clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
+					})
+				}
+			}
+			joinSub = joinSub.Where("EXISTS (?)", ownersExists)
+			return relatedDB.Where("EXISTS (?)", joinSub).Updates(setMap).Error
+		}
+	}
+	return errors.New("unsupported relationship")
+}
diff --git a/public-api/vendor/gorm.io/gorm/gorm.go b/public-api/vendor/gorm.io/gorm/gorm.go
index 67889262..a209bb09 100644
--- a/public-api/vendor/gorm.io/gorm/gorm.go
+++ b/public-api/vendor/gorm.io/gorm/gorm.go
@@ -23,6 +23,7 @@ type Config struct {
 	// You can disable it by setting `SkipDefaultTransaction` to true
 	SkipDefaultTransaction    bool
 	DefaultTransactionTimeout time.Duration
+	DefaultContextTimeout     time.Duration
 
 	// NamingStrategy tables, columns naming strategy
 	NamingStrategy schema.Namer
@@ -137,6 +138,14 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
 		return isConfig && !isConfig2
 	})
 
+	if len(opts) > 0 {
+		if c, ok := opts[0].(*Config); ok {
+			config = c
+		} else {
+			opts = append([]Option{config}, opts...)
+		}
+	}
+
 	var skipAfterInitialize bool
 	for _, opt := range opts {
 		if opt != nil {
diff --git a/public-api/vendor/gorm.io/gorm/logger/slog.go b/public-api/vendor/gorm.io/gorm/logger/slog.go
new file mode 100644
index 00000000..613234ca
--- /dev/null
+++ b/public-api/vendor/gorm.io/gorm/logger/slog.go
@@ -0,0 +1,100 @@
+//go:build go1.21
+
+package logger
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"log/slog"
+	"time"
+)
+
+type slogLogger struct {
+	Logger                    *slog.Logger
+	LogLevel                  LogLevel
+	SlowThreshold             time.Duration
+	Parameterized             bool
+	Colorful                  bool // Ignored in slog
+	IgnoreRecordNotFoundError bool
+}
+
+func NewSlogLogger(logger *slog.Logger, config Config) Interface {
+	return &slogLogger{
+		Logger:                    logger,
+		LogLevel:                  config.LogLevel,
+		SlowThreshold:             config.SlowThreshold,
+		Parameterized:             config.ParameterizedQueries,
+		IgnoreRecordNotFoundError: config.IgnoreRecordNotFoundError,
+	}
+}
+
+func (l *slogLogger) LogMode(level LogLevel) Interface {
+	newLogger := *l
+	newLogger.LogLevel = level
+	return &newLogger
+}
+
+func (l *slogLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Info {
+		l.Logger.InfoContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Warn {
+		l.Logger.WarnContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+	if l.LogLevel >= Error {
+		l.Logger.ErrorContext(ctx, msg, slog.Any("data", data))
+	}
+}
+
+func (l *slogLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
+	if l.LogLevel <= Silent {
+		return
+	}
+
+	elapsed := time.Since(begin)
+	sql, rows := fc()
+	fields := []slog.Attr{
+		slog.String("duration", fmt.Sprintf("%.3fms", float64(elapsed.Nanoseconds())/1e6)),
+		slog.String("sql", sql),
+	}
+
+	if rows != -1 {
+		fields = append(fields, slog.Int64("rows", rows))
+	}
+
+	switch {
+	case err != nil && (!l.IgnoreRecordNotFoundError || !errors.Is(err, ErrRecordNotFound)):
+		fields = append(fields, slog.String("error", err.Error()))
+		l.Logger.ErrorContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.SlowThreshold != 0 && elapsed > l.SlowThreshold:
+		l.Logger.WarnContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+
+	case l.LogLevel >= Info:
+		l.Logger.InfoContext(ctx, "SQL executed", slog.Attr{
+			Key:   "trace",
+			Value: slog.GroupValue(fields...),
+		})
+	}
+}
+
+// ParamsFilter filter params
+func (l *slogLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) {
+	if l.Parameterized {
+		return sql, nil
+	}
+	return sql, params
+}
diff --git a/public-api/vendor/gorm.io/gorm/migrator/migrator.go b/public-api/vendor/gorm.io/gorm/migrator/migrator.go
index cec4e30f..50a36d10 100644
--- a/public-api/vendor/gorm.io/gorm/migrator/migrator.go
+++ b/public-api/vendor/gorm.io/gorm/migrator/migrator.go
@@ -474,7 +474,6 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 	// found, smart migrate
 	fullDataType := strings.TrimSpace(strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL))
 	realDataType := strings.ToLower(columnType.DatabaseTypeName())
-
 	var (
 		alterColumn bool
 		isSameType  = fullDataType == realDataType
@@ -513,8 +512,19 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
 				}
 			}
 		}
+	}
 
-		// check precision
+	// check precision
+	if realDataType == "decimal" || realDataType == "numeric" &&
+		regexp.MustCompile(realDataType+`\(.*\)`).FindString(fullDataType) != "" { // if realDataType has no precision,ignore
+		precision, scale, ok := columnType.DecimalSize()
+		if ok {
+			if !strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d,%d)", realDataType, precision, scale)) &&
+				!strings.HasPrefix(fullDataType, fmt.Sprintf("%s(%d)", realDataType, precision)) {
+				alterColumn = true
+			}
+		}
+	} else {
 		if precision, _, ok := columnType.DecimalSize(); ok && int64(field.Precision) != precision {
 			if regexp.MustCompile(fmt.Sprintf("[^0-9]%d[^0-9]", field.Precision)).MatchString(m.DataTypeOf(field)) {
 				alterColumn = true
diff --git a/public-api/vendor/gorm.io/gorm/schema/field.go b/public-api/vendor/gorm.io/gorm/schema/field.go
index a6ff1a72..de797402 100644
--- a/public-api/vendor/gorm.io/gorm/schema/field.go
+++ b/public-api/vendor/gorm.io/gorm/schema/field.go
@@ -448,16 +448,17 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 }
 
 // create valuer, setter when parse struct
-func (field *Field) setupValuerAndSetter() {
+func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
 	// Setup NewValuePool
 	field.setupNewValuePool()
 
 	// ValueOf returns field's value and if it is zero
 	fieldIndex := field.StructField.Index[0]
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
-			fieldValue := reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
+			v = reflect.Indirect(v)
+			fieldValue := v.Field(fieldIndex)
 			return fieldValue.Interface(), fieldValue.IsZero()
 		}
 	default:
@@ -504,9 +505,10 @@ func (field *Field) setupValuerAndSetter() {
 
 	// ReflectValueOf returns field's reflect value
 	switch {
-	case len(field.StructField.Index) == 1 && fieldIndex > 0:
-		field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
-			return reflect.Indirect(value).Field(fieldIndex)
+	case len(field.StructField.Index) == 1 && fieldIndex >= 0:
+		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
+			v = reflect.Indirect(v)
+			return v.Field(fieldIndex)
 		}
 	default:
 		field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
diff --git a/public-api/vendor/gorm.io/gorm/schema/relationship.go b/public-api/vendor/gorm.io/gorm/schema/relationship.go
index f1ace924..0535bba4 100644
--- a/public-api/vendor/gorm.io/gorm/schema/relationship.go
+++ b/public-api/vendor/gorm.io/gorm/schema/relationship.go
@@ -75,9 +75,7 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
 		}
 	)
 
-	cacheStore := schema.cacheStore
-
-	if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
+	if relation.FieldSchema, err = getOrParse(fieldValue, schema.cacheStore, schema.namer); err != nil {
 		schema.err = fmt.Errorf("failed to parse field: %s, error: %w", field.Name, err)
 		return nil
 	}
@@ -147,6 +145,9 @@ func hasPolymorphicRelation(tagSettings map[string]string) bool {
 }
 
 func (schema *Schema) setRelation(relation *Relationship) {
+	schema.Relationships.Mux.Lock()
+	defer schema.Relationships.Mux.Unlock()
+
 	// set non-embedded relation
 	if rel := schema.Relationships.Relations[relation.Name]; rel != nil {
 		if len(rel.Field.BindNames) > 1 {
@@ -590,6 +591,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 	// build references
 	for idx, foreignField := range foreignFields {
 		// use same data type for foreign keys
+		schema.Relationships.Mux.Lock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Lock()
+		}
 		if copyableDataType(primaryFields[idx].DataType) {
 			foreignField.DataType = primaryFields[idx].DataType
 		}
@@ -597,6 +602,10 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
 		if foreignField.Size == 0 {
 			foreignField.Size = primaryFields[idx].Size
 		}
+		schema.Relationships.Mux.Unlock()
+		if schema != foreignField.Schema {
+			foreignField.Schema.Relationships.Mux.Unlock()
+		}
 
 		relation.References = append(relation.References, &Reference{
 			PrimaryKey:    primaryFields[idx],
diff --git a/public-api/vendor/gorm.io/gorm/schema/schema.go b/public-api/vendor/gorm.io/gorm/schema/schema.go
index db236797..9419846b 100644
--- a/public-api/vendor/gorm.io/gorm/schema/schema.go
+++ b/public-api/vendor/gorm.io/gorm/schema/schema.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"go/ast"
+	"path"
 	"reflect"
 	"strings"
 	"sync"
@@ -59,14 +60,14 @@ type Schema struct {
 	cacheStore                *sync.Map
 }
 
-func (schema Schema) String() string {
+func (schema *Schema) String() string {
 	if schema.ModelType.Name() == "" {
 		return fmt.Sprintf("%s(%s)", schema.Name, schema.Table)
 	}
 	return fmt.Sprintf("%s.%s", schema.ModelType.PkgPath(), schema.ModelType.Name())
 }
 
-func (schema Schema) MakeSlice() reflect.Value {
+func (schema *Schema) MakeSlice() reflect.Value {
 	slice := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(schema.ModelType)), 0, 20)
 	results := reflect.New(slice.Type())
 	results.Elem().Set(slice)
@@ -74,7 +75,7 @@ func (schema Schema) MakeSlice() reflect.Value {
 	return results
 }
 
-func (schema Schema) LookUpField(name string) *Field {
+func (schema *Schema) LookUpField(name string) *Field {
 	if field, ok := schema.FieldsByDBName[name]; ok {
 		return field
 	}
@@ -92,10 +93,7 @@ func (schema Schema) LookUpField(name string) *Field {
 //		}
 //		ID string // is selected by LookUpFieldByBindName([]string{"ID"}, "ID")
 //	}
-func (schema Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
-	if len(bindNames) == 0 {
-		return nil
-	}
+func (schema *Schema) LookUpFieldByBindName(bindNames []string, name string) *Field {
 	for i := len(bindNames) - 1; i >= 0; i-- {
 		find := strings.Join(bindNames[:i], ".") + "." + name
 		if field, ok := schema.FieldsByBindName[find]; ok {
@@ -113,6 +111,14 @@ type TablerWithNamer interface {
 	TableName(Namer) string
 }
 
+var callbackTypes = []callbackType{
+	callbackTypeBeforeCreate, callbackTypeAfterCreate,
+	callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
+	callbackTypeBeforeSave, callbackTypeAfterSave,
+	callbackTypeBeforeDelete, callbackTypeAfterDelete,
+	callbackTypeAfterFind,
+}
+
 // Parse get data type from dialector
 func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	return ParseWithSpecialTableName(dest, cacheStore, namer, "")
@@ -124,34 +130,33 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
 	}
 
-	value := reflect.ValueOf(dest)
-	if value.Kind() == reflect.Ptr && value.IsNil() {
-		value = reflect.New(value.Type().Elem())
-	}
-	modelType := reflect.Indirect(value).Type()
-
-	if modelType.Kind() == reflect.Interface {
-		modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
-	}
-
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+	modelType := reflect.ValueOf(dest).Type()
+	if modelType.Kind() == reflect.Ptr {
 		modelType = modelType.Elem()
 	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		if modelType.Kind() == reflect.Interface {
+			modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
+		}
+
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	// Cache the Schema for performance,
 	// Use the modelType or modelType + schemaTable (if it present) as cache key.
-	var schemaCacheKey interface{}
+	var schemaCacheKey interface{} = modelType
 	if specialTableName != "" {
 		schemaCacheKey = fmt.Sprintf("%p-%s", modelType, specialTableName)
-	} else {
-		schemaCacheKey = modelType
 	}
 
 	// Load exist schema cache, return if exists
@@ -162,28 +167,29 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		return s, s.err
 	}
 
+	var tableName string
 	modelValue := reflect.New(modelType)
-	tableName := namer.TableName(modelType.Name())
-	if tabler, ok := modelValue.Interface().(Tabler); ok {
+	if specialTableName != "" {
+		tableName = specialTableName
+	} else if en, ok := namer.(embeddedNamer); ok {
+		tableName = en.Table
+	} else if tabler, ok := modelValue.Interface().(Tabler); ok {
 		tableName = tabler.TableName()
-	}
-	if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
+	} else if tabler, ok := modelValue.Interface().(TablerWithNamer); ok {
 		tableName = tabler.TableName(namer)
-	}
-	if en, ok := namer.(embeddedNamer); ok {
-		tableName = en.Table
-	}
-	if specialTableName != "" && specialTableName != tableName {
-		tableName = specialTableName
+	} else {
+		tableName = namer.TableName(modelType.Name())
 	}
 
 	schema := &Schema{
 		Name:             modelType.Name(),
 		ModelType:        modelType,
 		Table:            tableName,
-		FieldsByName:     map[string]*Field{},
-		FieldsByBindName: map[string]*Field{},
-		FieldsByDBName:   map[string]*Field{},
+		DBNames:          make([]string, 0, 10),
+		Fields:           make([]*Field, 0, 10),
+		FieldsByName:     make(map[string]*Field, 10),
+		FieldsByBindName: make(map[string]*Field, 10),
+		FieldsByDBName:   make(map[string]*Field, 10),
 		Relationships:    Relationships{Relations: map[string]*Relationship{}},
 		cacheStore:       cacheStore,
 		namer:            namer,
@@ -227,8 +233,9 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 				schema.FieldsByBindName[bindName] = field
 
 				if v != nil && v.PrimaryKey {
+					// remove the existing primary key field
 					for idx, f := range schema.PrimaryFields {
-						if f == v {
+						if f.DBName == v.DBName {
 							schema.PrimaryFields = append(schema.PrimaryFields[0:idx], schema.PrimaryFields[idx+1:]...)
 						}
 					}
@@ -247,7 +254,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 			schema.FieldsByBindName[bindName] = field
 		}
 
-		field.setupValuerAndSetter()
+		field.setupValuerAndSetter(modelType)
 	}
 
 	prioritizedPrimaryField := schema.LookUpField("id")
@@ -283,10 +290,37 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		schema.PrimaryFieldDBNames = append(schema.PrimaryFieldDBNames, field.DBName)
 	}
 
+	_, embedded := schema.cacheStore.Load(embeddedCacheKey)
+	relationshipFields := []*Field{}
 	for _, field := range schema.Fields {
 		if field.DataType != "" && field.HasDefaultValue && field.DefaultValueInterface == nil {
 			schema.FieldsWithDefaultDBValue = append(schema.FieldsWithDefaultDBValue, field)
 		}
+
+		if !embedded {
+			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
+				relationshipFields = append(relationshipFields, field)
+				schema.FieldsByName[field.Name] = field
+				schema.FieldsByBindName[field.BindName()] = field
+			}
+
+			fieldValue := reflect.New(field.IndirectFieldType).Interface()
+			if fc, ok := fieldValue.(CreateClausesInterface); ok {
+				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(QueryClausesInterface); ok {
+				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(UpdateClausesInterface); ok {
+				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
+			}
+
+			if fc, ok := fieldValue.(DeleteClausesInterface); ok {
+				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
+			}
+		}
 	}
 
 	if field := schema.PrioritizedPrimaryField; field != nil {
@@ -303,24 +337,6 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}
 
-	callbackTypes := []callbackType{
-		callbackTypeBeforeCreate, callbackTypeAfterCreate,
-		callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
-		callbackTypeBeforeSave, callbackTypeAfterSave,
-		callbackTypeBeforeDelete, callbackTypeAfterDelete,
-		callbackTypeAfterFind,
-	}
-	for _, cbName := range callbackTypes {
-		if methodValue := callBackToMethodValue(modelValue, cbName); methodValue.IsValid() {
-			switch methodValue.Type().String() {
-			case "func(*gorm.DB) error": // TODO hack
-				reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
-			default:
-				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
-			}
-		}
-	}
-
 	// Cache the schema
 	if v, loaded := cacheStore.LoadOrStore(schemaCacheKey, schema); loaded {
 		s := v.(*Schema)
@@ -336,84 +352,47 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
 		}
 	}()
 
-	if _, embedded := schema.cacheStore.Load(embeddedCacheKey); !embedded {
-		for _, field := range schema.Fields {
-			if field.DataType == "" && field.GORMDataType == "" && (field.Creatable || field.Updatable || field.Readable) {
-				if schema.parseRelation(field); schema.err != nil {
-					return schema, schema.err
+	for _, cbName := range callbackTypes {
+		if methodValue := modelValue.MethodByName(string(cbName)); methodValue.IsValid() {
+			switch methodValue.Type().String() {
+			case "func(*gorm.DB) error":
+				expectedPkgPath := path.Dir(reflect.TypeOf(schema).Elem().PkgPath())
+				if inVarPkg := methodValue.Type().In(0).Elem().PkgPath(); inVarPkg == expectedPkgPath {
+					reflect.Indirect(reflect.ValueOf(schema)).FieldByName(string(cbName)).SetBool(true)
 				} else {
-					schema.FieldsByName[field.Name] = field
-					schema.FieldsByBindName[field.BindName()] = field
+					logger.Default.Warn(context.Background(), "In model %v, the hook function `%v(*gorm.DB) error` has an incorrect parameter type. The expected parameter type is `%v`, but the provided type is `%v`.", schema, cbName, expectedPkgPath, inVarPkg)
+					// PASS
 				}
+			default:
+				logger.Default.Warn(context.Background(), "Model %v don't match %vInterface, should be `%v(*gorm.DB) error`. Please see https://gorm.io/docs/hooks.html", schema, cbName, cbName)
 			}
+		}
+	}
 
-			fieldValue := reflect.New(field.IndirectFieldType)
-			fieldInterface := fieldValue.Interface()
-			if fc, ok := fieldInterface.(CreateClausesInterface); ok {
-				field.Schema.CreateClauses = append(field.Schema.CreateClauses, fc.CreateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(QueryClausesInterface); ok {
-				field.Schema.QueryClauses = append(field.Schema.QueryClauses, fc.QueryClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(UpdateClausesInterface); ok {
-				field.Schema.UpdateClauses = append(field.Schema.UpdateClauses, fc.UpdateClauses(field)...)
-			}
-
-			if fc, ok := fieldInterface.(DeleteClausesInterface); ok {
-				field.Schema.DeleteClauses = append(field.Schema.DeleteClauses, fc.DeleteClauses(field)...)
-			}
+	// parse relationships
+	for _, field := range relationshipFields {
+		if schema.parseRelation(field); schema.err != nil {
+			return schema, schema.err
 		}
 	}
 
 	return schema, schema.err
 }
 
-// This unrolling is needed to show to the compiler the exact set of methods
-// that can be used on the modelType.
-// Prior to go1.22 any use of MethodByName would cause the linker to
-// abandon dead code elimination for the entire binary.
-// As of go1.22 the compiler supports one special case of a string constant
-// being passed to MethodByName. For enterprise customers or those building
-// large binaries, this gives a significant reduction in binary size.
-// https://github.com/golang/go/issues/62257
-func callBackToMethodValue(modelType reflect.Value, cbType callbackType) reflect.Value {
-	switch cbType {
-	case callbackTypeBeforeCreate:
-		return modelType.MethodByName(string(callbackTypeBeforeCreate))
-	case callbackTypeAfterCreate:
-		return modelType.MethodByName(string(callbackTypeAfterCreate))
-	case callbackTypeBeforeUpdate:
-		return modelType.MethodByName(string(callbackTypeBeforeUpdate))
-	case callbackTypeAfterUpdate:
-		return modelType.MethodByName(string(callbackTypeAfterUpdate))
-	case callbackTypeBeforeSave:
-		return modelType.MethodByName(string(callbackTypeBeforeSave))
-	case callbackTypeAfterSave:
-		return modelType.MethodByName(string(callbackTypeAfterSave))
-	case callbackTypeBeforeDelete:
-		return modelType.MethodByName(string(callbackTypeBeforeDelete))
-	case callbackTypeAfterDelete:
-		return modelType.MethodByName(string(callbackTypeAfterDelete))
-	case callbackTypeAfterFind:
-		return modelType.MethodByName(string(callbackTypeAfterFind))
-	default:
-		return reflect.ValueOf(nil)
-	}
-}
-
 func getOrParse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
 	modelType := reflect.ValueOf(dest).Type()
-	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
-		modelType = modelType.Elem()
-	}
 
 	if modelType.Kind() != reflect.Struct {
-		if modelType.PkgPath() == "" {
-			return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+			modelType = modelType.Elem()
+		}
+
+		if modelType.Kind() != reflect.Struct {
+			if modelType.PkgPath() == "" {
+				return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
+			}
+			return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 		}
-		return nil, fmt.Errorf("%w: %s.%s", ErrUnsupportedDataType, modelType.PkgPath(), modelType.Name())
 	}
 
 	if v, ok := cacheStore.Load(modelType); ok {
diff --git a/public-api/vendor/gorm.io/gorm/schema/utils.go b/public-api/vendor/gorm.io/gorm/schema/utils.go
index fa1c65d4..d4fe252e 100644
--- a/public-api/vendor/gorm.io/gorm/schema/utils.go
+++ b/public-api/vendor/gorm.io/gorm/schema/utils.go
@@ -121,6 +121,17 @@ func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value,
 	}
 
 	switch reflectValue.Kind() {
+	case reflect.Map:
+		results = [][]interface{}{make([]interface{}, len(fields))}
+		for idx, field := range fields {
+			mapValue := reflectValue.MapIndex(reflect.ValueOf(field.DBName))
+			if mapValue.IsZero() {
+				mapValue = reflectValue.MapIndex(reflect.ValueOf(field.Name))
+			}
+			results[0][idx] = mapValue.Interface()
+		}
+
+		dataResults[utils.ToStringKey(results[0]...)] = []reflect.Value{reflectValue}
 	case reflect.Struct:
 		results = [][]interface{}{make([]interface{}, len(fields))}
 
diff --git a/public-api/vendor/gorm.io/gorm/statement.go b/public-api/vendor/gorm.io/gorm/statement.go
index c6183724..736087d7 100644
--- a/public-api/vendor/gorm.io/gorm/statement.go
+++ b/public-api/vendor/gorm.io/gorm/statement.go
@@ -96,7 +96,9 @@ func (stmt *Statement) QuoteTo(writer clause.Writer, field interface{}) {
 		if v.Name == clause.CurrentTable {
 			if stmt.TableExpr != nil {
 				stmt.TableExpr.Build(stmt)
-			} else {
+			} else if stmt.Table != "" {
+				write(v.Raw, stmt.Table)
+			} else if stmt.AddError(stmt.Parse(stmt.Model)) == nil {
 				write(v.Raw, stmt.Table)
 			}
 		} else {
@@ -334,6 +336,8 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 		switch v := arg.(type) {
 		case clause.Expression:
 			conds = append(conds, v)
+		case []clause.Expression:
+			conds = append(conds, v...)
 		case *DB:
 			v.executeScopes()
 
@@ -341,7 +345,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 				if where, ok := cs.Expression.(clause.Where); ok {
 					if len(where.Exprs) == 1 {
 						if orConds, ok := where.Exprs[0].(clause.OrConditions); ok {
-							where.Exprs[0] = clause.AndConditions(orConds)
+							if len(orConds.Exprs) == 1 {
+								where.Exprs[0] = clause.AndConditions(orConds)
+							}
 						}
 					}
 					conds = append(conds, clause.And(where.Exprs...))
@@ -362,6 +368,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 
 			for _, key := range keys {
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				conds = append(conds, clause.Eq{Column: column, Value: v[key]})
 			}
 		case map[string]interface{}:
@@ -374,6 +383,9 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) []
 			for _, key := range keys {
 				reflectValue := reflect.Indirect(reflect.ValueOf(v[key]))
 				column := clause.Column{Name: key, Table: curTable}
+				if strings.Contains(key, ".") {
+					column = clause.Column{Name: key}
+				}
 				switch reflectValue.Kind() {
 				case reflect.Slice, reflect.Array:
 					if _, ok := v[key].(driver.Valuer); ok {
@@ -650,12 +662,15 @@ func (stmt *Statement) Changed(fields ...string) bool {
 				for destValue.Kind() == reflect.Ptr {
 					destValue = destValue.Elem()
 				}
-
-				changedValue, zero := field.ValueOf(stmt.Context, destValue)
-				if v {
-					return !utils.AssertEqual(changedValue, fieldValue)
+				if descSchema, err := schema.Parse(stmt.Dest, stmt.DB.cacheStore, stmt.DB.NamingStrategy); err == nil {
+					if destField := descSchema.LookUpField(field.DBName); destField != nil {
+						changedValue, zero := destField.ValueOf(stmt.Context, destValue)
+						if v {
+							return !utils.AssertEqual(changedValue, fieldValue)
+						}
+						return !zero && !utils.AssertEqual(changedValue, fieldValue)
+					}
 				}
-				return !zero && !utils.AssertEqual(changedValue, fieldValue)
 			}
 		}
 		return false
diff --git a/public-api/vendor/modules.txt b/public-api/vendor/modules.txt
index 2634d3e1..28e86eb3 100644
--- a/public-api/vendor/modules.txt
+++ b/public-api/vendor/modules.txt
@@ -161,9 +161,10 @@ github.com/felixge/httpsnoop
 # github.com/firefart/nonamedreturns v1.0.5
 ## explicit; go 1.18
 github.com/firefart/nonamedreturns/analyzer
-# github.com/fsnotify/fsnotify v1.6.0
-## explicit; go 1.16
+# github.com/fsnotify/fsnotify v1.8.0
+## explicit; go 1.17
 github.com/fsnotify/fsnotify
+github.com/fsnotify/fsnotify/internal
 # github.com/fzipp/gocyclo v0.6.0
 ## explicit; go 1.18
 github.com/fzipp/gocyclo
@@ -202,7 +203,7 @@ github.com/go-toolsmith/strparse
 # github.com/go-toolsmith/typep v1.1.0
 ## explicit; go 1.16
 github.com/go-toolsmith/typep
-# github.com/go-viper/mapstructure/v2 v2.2.1
+# github.com/go-viper/mapstructure/v2 v2.4.0
 ## explicit; go 1.18
 github.com/go-viper/mapstructure/v2
 github.com/go-viper/mapstructure/v2/internal/errors
@@ -440,8 +441,8 @@ github.com/gostaticanalysis/forcetypeassert
 # github.com/gostaticanalysis/nilerr v0.1.1
 ## explicit; go 1.15
 github.com/gostaticanalysis/nilerr
-# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1
-## explicit; go 1.23.0
+# github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
+## explicit; go 1.24.0
 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
 github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options
 github.com/grpc-ecosystem/grpc-gateway/v2/runtime
@@ -456,18 +457,6 @@ github.com/hashicorp/go-version
 ## explicit; go 1.18
 github.com/hashicorp/golang-lru/v2/internal
 github.com/hashicorp/golang-lru/v2/simplelru
-# github.com/hashicorp/hcl v1.0.0
-## explicit
-github.com/hashicorp/hcl
-github.com/hashicorp/hcl/hcl/ast
-github.com/hashicorp/hcl/hcl/parser
-github.com/hashicorp/hcl/hcl/printer
-github.com/hashicorp/hcl/hcl/scanner
-github.com/hashicorp/hcl/hcl/strconv
-github.com/hashicorp/hcl/hcl/token
-github.com/hashicorp/hcl/json/parser
-github.com/hashicorp/hcl/json/scanner
-github.com/hashicorp/hcl/json/token
 # github.com/hexops/gotextdiff v1.0.3
 ## explicit; go 1.16
 github.com/hexops/gotextdiff
@@ -482,8 +471,8 @@ github.com/jackc/pgpassfile
 # github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
 ## explicit; go 1.14
 github.com/jackc/pgservicefile
-# github.com/jackc/pgx/v5 v5.7.1
-## explicit; go 1.21
+# github.com/jackc/pgx/v5 v5.7.6
+## explicit; go 1.23.0
 github.com/jackc/pgx/v5
 github.com/jackc/pgx/v5/internal/iobufpool
 github.com/jackc/pgx/v5/internal/pgio
@@ -569,9 +558,6 @@ github.com/lufia/plan9stats
 # github.com/macabu/inamedparam v0.1.3
 ## explicit; go 1.20
 github.com/macabu/inamedparam
-# github.com/magiconair/properties v1.8.7
-## explicit; go 1.19
-github.com/magiconair/properties
 # github.com/maratori/testableexamples v1.0.0
 ## explicit; go 1.19
 github.com/maratori/testableexamples/pkg/testableexamples
@@ -602,9 +588,6 @@ github.com/mgechev/revive/rule
 # github.com/mitchellh/go-homedir v1.1.0
 ## explicit
 github.com/mitchellh/go-homedir
-# github.com/mitchellh/mapstructure v1.5.0
-## explicit; go 1.14
-github.com/mitchellh/mapstructure
 # github.com/moricho/tparallel v0.3.2
 ## explicit; go 1.20
 github.com/moricho/tparallel
@@ -674,8 +657,8 @@ github.com/prometheus/client_model/go
 ## explicit; go 1.21
 github.com/prometheus/common/expfmt
 github.com/prometheus/common/model
-# github.com/prometheus/procfs v0.15.1
-## explicit; go 1.20
+# github.com/prometheus/procfs v0.17.0
+## explicit; go 1.23.0
 github.com/prometheus/procfs
 github.com/prometheus/procfs/internal/fs
 github.com/prometheus/procfs/internal/util
@@ -724,24 +707,24 @@ github.com/rogpeppe/go-internal/internal/syscall/windows
 github.com/rogpeppe/go-internal/internal/syscall/windows/sysdll
 github.com/rogpeppe/go-internal/lockedfile
 github.com/rogpeppe/go-internal/lockedfile/internal/filelock
-# github.com/rs/cors v1.11.0
+# github.com/rs/cors v1.11.1
 ## explicit; go 1.13
 github.com/rs/cors
 github.com/rs/cors/internal
-# github.com/rs/zerolog v1.33.0
+# github.com/rs/zerolog v1.34.0
 ## explicit; go 1.15
 github.com/rs/zerolog
 github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/event-processor v0.4.14 => ../event-processor
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/event-processor/api
 # github.com/runtime-radar/runtime-radar/history-api v0.0.0-00010101000000-000000000000 => ../history-api
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/history-api/api
 # github.com/runtime-radar/runtime-radar/lib v0.0.24 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/errcommon
 github.com/runtime-radar/runtime-radar/lib/security
@@ -751,7 +734,7 @@ github.com/runtime-radar/runtime-radar/lib/server/healthcheck
 github.com/runtime-radar/runtime-radar/lib/server/interceptor
 github.com/runtime-radar/runtime-radar/lib/server/middleware
 # github.com/runtime-radar/runtime-radar/policy-enforcer v0.4.8 => ../policy-enforcer
-## explicit; go 1.23.0
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/policy-enforcer/api
 # github.com/ryancurrah/gomodguard v1.3.5
 ## explicit; go 1.22.0
@@ -759,12 +742,9 @@ github.com/ryancurrah/gomodguard
 # github.com/ryanrolds/sqlclosecheck v0.5.1
 ## explicit; go 1.20
 github.com/ryanrolds/sqlclosecheck/pkg/analyzer
-# github.com/sagikazarmark/locafero v0.3.0
-## explicit; go 1.20
+# github.com/sagikazarmark/locafero v0.7.0
+## explicit; go 1.21
 github.com/sagikazarmark/locafero
-# github.com/sagikazarmark/slog-shim v0.1.0
-## explicit; go 1.20
-github.com/sagikazarmark/slog-shim
 # github.com/sanposhiho/wastedassign/v2 v2.1.0
 ## explicit; go 1.18
 github.com/sanposhiho/wastedassign/v2
@@ -825,26 +805,23 @@ github.com/sourcegraph/go-diff/diff
 github.com/spf13/afero
 github.com/spf13/afero/internal/common
 github.com/spf13/afero/mem
-# github.com/spf13/cast v1.5.1
-## explicit; go 1.18
+# github.com/spf13/cast v1.7.1
+## explicit; go 1.19
 github.com/spf13/cast
 # github.com/spf13/cobra v1.9.1
 ## explicit; go 1.15
 github.com/spf13/cobra
-# github.com/spf13/pflag v1.0.6
+# github.com/spf13/pflag v1.0.7
 ## explicit; go 1.12
 github.com/spf13/pflag
-# github.com/spf13/viper v1.17.0
-## explicit; go 1.18
+# github.com/spf13/viper v1.20.1
+## explicit; go 1.21.0
 github.com/spf13/viper
-github.com/spf13/viper/internal/encoding
 github.com/spf13/viper/internal/encoding/dotenv
-github.com/spf13/viper/internal/encoding/hcl
-github.com/spf13/viper/internal/encoding/ini
-github.com/spf13/viper/internal/encoding/javaproperties
 github.com/spf13/viper/internal/encoding/json
 github.com/spf13/viper/internal/encoding/toml
 github.com/spf13/viper/internal/encoding/yaml
+github.com/spf13/viper/internal/features
 # github.com/ssgreg/nlreturn/v2 v2.2.1
 ## explicit; go 1.13
 github.com/ssgreg/nlreturn/v2/pkg/nlreturn
@@ -956,26 +933,19 @@ go.uber.org/zap/internal/exit
 go.uber.org/zap/internal/pool
 go.uber.org/zap/internal/stacktrace
 go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.38.0
+# golang.org/x/crypto v0.41.0
 ## explicit; go 1.23.0
 golang.org/x/crypto/pbkdf2
-# golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
-## explicit; go 1.22.0
-golang.org/x/exp/constraints
-golang.org/x/exp/slices
-golang.org/x/exp/slog
-golang.org/x/exp/slog/internal
-golang.org/x/exp/slog/internal/buffer
 # golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac
 ## explicit; go 1.18
 golang.org/x/exp/typeparams
-# golang.org/x/mod v0.25.0
+# golang.org/x/mod v0.27.0
 ## explicit; go 1.23.0
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.40.0
+# golang.org/x/net v0.43.0
 ## explicit; go 1.23.0
 golang.org/x/net/http/httpguts
 golang.org/x/net/http2
@@ -984,16 +954,27 @@ golang.org/x/net/idna
 golang.org/x/net/internal/httpcommon
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
-# golang.org/x/sync v0.15.0
-## explicit; go 1.23.0
+# golang.org/x/sync v0.17.0
+## explicit; go 1.24.0
 golang.org/x/sync/errgroup
 golang.org/x/sync/semaphore
-# golang.org/x/sys v0.33.0
+# golang.org/x/sys v0.35.0
 ## explicit; go 1.23.0
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/text v0.26.0
+# golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
 ## explicit; go 1.23.0
+golang.org/x/telemetry
+golang.org/x/telemetry/counter
+golang.org/x/telemetry/internal/config
+golang.org/x/telemetry/internal/configstore
+golang.org/x/telemetry/internal/counter
+golang.org/x/telemetry/internal/crashmonitor
+golang.org/x/telemetry/internal/mmap
+golang.org/x/telemetry/internal/telemetry
+golang.org/x/telemetry/internal/upload
+# golang.org/x/text v0.29.0
+## explicit; go 1.24.0
 golang.org/x/text/cases
 golang.org/x/text/encoding
 golang.org/x/text/encoding/internal
@@ -1019,7 +1000,7 @@ golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
-# golang.org/x/tools v0.33.0
+# golang.org/x/tools v0.36.0
 ## explicit; go 1.23.0
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/passes/appends
@@ -1071,6 +1052,7 @@ golang.org/x/tools/go/analysis/passes/unusedresult
 golang.org/x/tools/go/analysis/passes/unusedwrite
 golang.org/x/tools/go/analysis/passes/waitgroup
 golang.org/x/tools/go/ast/astutil
+golang.org/x/tools/go/ast/edge
 golang.org/x/tools/go/ast/inspector
 golang.org/x/tools/go/buildutil
 golang.org/x/tools/go/callgraph
@@ -1091,8 +1073,6 @@ golang.org/x/tools/imports
 golang.org/x/tools/internal/aliases
 golang.org/x/tools/internal/analysisinternal
 golang.org/x/tools/internal/astutil
-golang.org/x/tools/internal/astutil/cursor
-golang.org/x/tools/internal/astutil/edge
 golang.org/x/tools/internal/event
 golang.org/x/tools/internal/event/core
 golang.org/x/tools/internal/event/keys
@@ -1109,31 +1089,35 @@ golang.org/x/tools/internal/stdlib
 golang.org/x/tools/internal/typeparams
 golang.org/x/tools/internal/typesinternal
 golang.org/x/tools/internal/versions
-# golang.org/x/vuln v0.2.0
-## explicit; go 1.18
+# golang.org/x/vuln v1.1.4
+## explicit; go 1.22.0
 golang.org/x/vuln/cmd/govulncheck
 golang.org/x/vuln/internal
+golang.org/x/vuln/internal/buildinfo
 golang.org/x/vuln/internal/client
 golang.org/x/vuln/internal/derrors
+golang.org/x/vuln/internal/gosym
+golang.org/x/vuln/internal/goversion
 golang.org/x/vuln/internal/govulncheck
+golang.org/x/vuln/internal/openvex
 golang.org/x/vuln/internal/osv
+golang.org/x/vuln/internal/sarif
 golang.org/x/vuln/internal/scan
 golang.org/x/vuln/internal/semver
+golang.org/x/vuln/internal/traces
 golang.org/x/vuln/internal/vulncheck
-golang.org/x/vuln/internal/vulncheck/internal/buildinfo
-golang.org/x/vuln/internal/vulncheck/internal/gosym
 golang.org/x/vuln/internal/web
 golang.org/x/vuln/scan
-# google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/api
 google.golang.org/genproto/googleapis/api/annotations
 google.golang.org/genproto/googleapis/api/httpbody
-# google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822
-## explicit; go 1.23.0
+# google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff
+## explicit; go 1.24.0
 google.golang.org/genproto/googleapis/rpc/errdetails
 google.golang.org/genproto/googleapis/rpc/status
-# google.golang.org/grpc v1.73.0
+# google.golang.org/grpc v1.75.1
 ## explicit; go 1.23.0
 google.golang.org/grpc
 google.golang.org/grpc/attributes
@@ -1196,8 +1180,8 @@ google.golang.org/grpc/serviceconfig
 google.golang.org/grpc/stats
 google.golang.org/grpc/status
 google.golang.org/grpc/tap
-# google.golang.org/protobuf v1.36.6
-## explicit; go 1.22
+# google.golang.org/protobuf v1.36.10
+## explicit; go 1.23
 google.golang.org/protobuf/encoding/protodelim
 google.golang.org/protobuf/encoding/protojson
 google.golang.org/protobuf/encoding/prototext
@@ -1237,9 +1221,6 @@ google.golang.org/protobuf/types/known/fieldmaskpb
 google.golang.org/protobuf/types/known/structpb
 google.golang.org/protobuf/types/known/timestamppb
 google.golang.org/protobuf/types/known/wrapperspb
-# gopkg.in/ini.v1 v1.67.0
-## explicit
-gopkg.in/ini.v1
 # gopkg.in/yaml.v2 v2.4.0
 ## explicit; go 1.15
 gopkg.in/yaml.v2
@@ -1249,7 +1230,7 @@ gopkg.in/yaml.v3
 # gorm.io/driver/postgres v1.6.0
 ## explicit; go 1.20
 gorm.io/driver/postgres
-# gorm.io/gorm v1.30.0
+# gorm.io/gorm v1.31.0
 ## explicit; go 1.18
 gorm.io/gorm
 gorm.io/gorm/callbacks
diff --git a/reverse-proxy/Dockerfile b/reverse-proxy/Dockerfile
index 05d1fc3a..c4d7d822 100644
--- a/reverse-proxy/Dockerfile
+++ b/reverse-proxy/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 COPY --from=tools /usr/bin/task /usr/bin
 COPY . /app
diff --git a/runtime-monitor/Dockerfile b/runtime-monitor/Dockerfile
index adfc9b6f..d31a8d9e 100644
--- a/runtime-monitor/Dockerfile
+++ b/runtime-monitor/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.24.1 AS tools
+FROM golang:1.25.0 AS tools
 
 RUN CGO_ENABLED=0 GOBIN=/usr/bin go install github.com/go-task/task/v3/cmd/task@v3.38.0
 
-FROM golang:1.24.1 AS builder
+FROM golang:1.25.0 AS builder
 
 ARG BUILD_RELEASE
 ARG BUILD_BRANCH
diff --git a/runtime-monitor/docker-compose.test.yml b/runtime-monitor/docker-compose.test.yml
index 3126a730..c59784f0 100644
--- a/runtime-monitor/docker-compose.test.yml
+++ b/runtime-monitor/docker-compose.test.yml
@@ -1,6 +1,6 @@
 services:
   test:
-      image: golang:1.24
+      image: golang:1.25
       working_dir: /go/src/repo
       volumes:
         - .:/go/src/repo
diff --git a/runtime-monitor/go.mod b/runtime-monitor/go.mod
index 43a714d7..45c7b5cd 100644
--- a/runtime-monitor/go.mod
+++ b/runtime-monitor/go.mod
@@ -1,6 +1,6 @@
 module github.com/runtime-radar/runtime-radar/runtime-monitor
 
-go 1.23.0
+go 1.25
 
 require (
 	github.com/cilium/tetragon v1.3.0
diff --git a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
index fb4087d9..3604294e 100644
--- a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
+++ b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/security/jwt/jwt.go
@@ -43,6 +43,10 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
 	return nil
 }
 
+func (jt JSONTime) String() string {
+	return time.Time(jt).String()
+}
+
 type Token struct {
 	Username              string    `json:"username"`
 	UserID                string    `json:"user_id"`
@@ -189,7 +193,7 @@ func TokenFromContext(ctx context.Context, key []byte) (*Token, error) {
 		return nil, errors.New("unknown authorization format")
 	}
 
-	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(t *jwt.Token) (any, error) {
+	token, err := jwt.ParseWithClaims(tokenStr, &Token{}, func(*jwt.Token) (any, error) {
 		return key, nil
 	})
 	if err != nil {
diff --git a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
index 79432fec..24b0d6e3 100644
--- a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
+++ b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/healthcheck/healthcheck.go
@@ -27,7 +27,7 @@ func SetReady() {
 }
 
 // ReadyHandler handles ready probes.
-func ReadyHandler(w http.ResponseWriter, r *http.Request) {
+func ReadyHandler(w http.ResponseWriter, _ *http.Request) {
 	if IsReady() {
 		// Make it simple: do nothing and have 200 OK
 		return
@@ -37,6 +37,6 @@ func ReadyHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // LiveHandler handles live probes.
-func LiveHandler(w http.ResponseWriter, r *http.Request) {
+func LiveHandler(http.ResponseWriter, *http.Request) {
 	// Make it simple: do nothing and have 200 OK
 }
diff --git a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
index cb9487d6..822eb440 100644
--- a/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
+++ b/runtime-monitor/vendor/github.com/runtime-radar/runtime-radar/lib/server/interceptor/interceptor.go
@@ -31,7 +31,7 @@ func Recovery(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
 
 const CorrelationHeader = "correlation-id"
 
-func Correlation(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+func Correlation(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	var corrID string
 
 	md, ok := metadata.FromIncomingContext(ctx)
diff --git a/runtime-monitor/vendor/modules.txt b/runtime-monitor/vendor/modules.txt
index 462f3b1b..0efaadd1 100644
--- a/runtime-monitor/vendor/modules.txt
+++ b/runtime-monitor/vendor/modules.txt
@@ -909,7 +909,7 @@ github.com/rs/zerolog/internal/cbor
 github.com/rs/zerolog/internal/json
 github.com/rs/zerolog/log
 # github.com/runtime-radar/runtime-radar/lib v0.0.0-00010101000000-000000000000 => ../lib
-## explicit; go 1.23
+## explicit; go 1.25
 github.com/runtime-radar/runtime-radar/lib/config
 github.com/runtime-radar/runtime-radar/lib/errcommon
 github.com/runtime-radar/runtime-radar/lib/logger
diff --git a/values.yaml b/values.yaml
new file mode 100644
index 00000000..7d8157b9
--- /dev/null
+++ b/values.yaml
@@ -0,0 +1,69 @@
+global:
+  imageTag: v0.0.0-izy1
+  keys:
+    encryption: 29e41dc147c14e8be3da5ac88abe58c4e2e13d4b086652dc0c9fd5859fb26621
+    publicAccessTokenSalt: 6c1aa47a391ae667eccc458dd9ff3bda2cfb66e3e0816e9a52f32eabe511ad6f6c1aa47a391ae667eccc458dd9ff3bda2cfb66e3e0816e9a52f32eabe511ad6f
+  csVersion: v0.0.1
+  imageRegistry: docker-ptcs-dev.devops.ptsecurity.ru
+  ownCsUrl: https://izy-k8s.appsec-stand.ptsecurity.cloud:32690
+  # ownCsUrl: https://nla-k8s.appsec-stand.ptsecurity.cloud:30582
+  centralCsUrl: ""
+  postgresql:
+    tls:
+      verify: true
+      enabled: true
+  redis:
+    tls:
+      verify: true
+      enabled: true
+  clickhouse:
+    tls:
+      verify: true
+      enabled: true
+  devMode: true
+tls:
+  verify: true
+auth-center:
+  administrator:
+    username: ptcs
+    password: |-
+      ptcs
+history-api:
+  retentionInterval: 8760h
+postgresql:
+  auth:
+    username: ptcs
+    password: |-
+      ptcs
+  persistence:
+    enabled: false
+    storageClass: nfs-client
+redis:
+  auth:
+    username: ptcs
+    password: |-
+      ptcs
+  persistence:
+    enabled: false
+rabbitmq:
+  auth:
+    username: ptcs
+    password: |-
+      ptcs
+  persistence:
+    enabled: false
+    storageClass: nfs-client
+clickhouse:
+  auth:
+    username: ptcs
+    password: |-
+      ptcs
+  persistence:
+    enabled: false
+    storageClass: nfs-client
+admission-controller:
+  webhookBlockOnFailure: false
+reverse-proxy:
+  ingress:
+    enabled: true
+    class: "nginx"